Beispiel #1
0
        internal TheLambdaPowerTunerStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            //  An example lambda that can be used to test the powertuner
            _functionExample = new Lambda.Function(this, "exampleLambda", new Lambda.FunctionProps
            {
                Runtime = Lambda.Runtime.NODEJS_12_X,
                Handler = "index.handler",
                Code    = Lambda.Code.FromInline("exports.handler = function(event, ctx, cb) { return cb(null, 'hi'); }"),
            });

            // uncomment to only allow this power tuner to manipulate this defined function
            //var _lambdaResource = _functionExample.FunctionArn;

            // Output the Lambda function ARN in the deploy logs to ease testing
            new CfnOutput(this, "LambdaARN", new CfnOutputProps
            {
                Value = _functionExample.FunctionArn
            });

            // Deploy the aws-lambda-powertuning application from the Serverless Application Repository
            // https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:451282441545:applications~aws-lambda-power-tuning
            new SAM.CfnApplication(this, "powerTuner", new SAM.CfnApplicationProps
            {
                Location = new SAM.CfnApplication.ApplicationLocationProperty
                {
                    ApplicationId   = "arn:aws:serverlessrepo:us-east-1:451282441545:applications/aws-lambda-power-tuning",
                    SemanticVersion = "3.4.0"
                },
                Parameters = new Dictionary <string, object>
                {
                    { "lambdaResource", _lambdaResource },
                    { "PowerValues", _powerValues }
                }
            });
        }
Beispiel #2
0
        internal TheEfsLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // EFS needs to be setup in a VPC with 2Azs
            _vpc = new EC2.Vpc(this, "Vpc", new EC2.VpcProps
            {
                MaxAzs = 2
            });

            // Create a file system in EFS to store information
            _fileSystem = new EFS.FileSystem(this, "Filesystem", new EFS.FileSystemProps
            {
                Vpc           = _vpc,
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            // Create a access point to EFS
            EFS.AccessPoint accessPoint;
            accessPoint = _fileSystem.AddAccessPoint("AccessPoint", new EFS.AccessPointOptions
            {
                CreateAcl = new EFS.Acl {
                    OwnerGid = "1001", OwnerUid = "1001", Permissions = "750"
                },
                Path      = "/export/lambda",
                PosixUser = new EFS.PosixUser {
                    Gid = "1001", Uid = "1001",
                }
            });

            // Create the lambda function
            _functionProxyHandler = new Lambda.Function(this, "efsLambdaFunction", new Lambda.FunctionProps
            {
                Runtime    = Lambda.Runtime.PYTHON_3_8,
                Code       = Lambda.Code.FromAsset("lambda_fns"),
                Handler    = "message_wall.lambda_handler",
                Vpc        = _vpc,
                Filesystem = Lambda.FileSystem.FromEfsAccessPoint(accessPoint, "/mnt/msg")
            });

            // Api Gateway HTTP integration
            _apiGateway = new APIGv2.HttpApi(this, "EFS Lambda", new APIGv2.HttpApiProps
            {
                DefaultIntegration = new APIGv2Integration.LambdaProxyIntegration(new APIGv2Integration.LambdaProxyIntegrationProps
                {
                    Handler = _functionProxyHandler
                })
            });


            // Output to CFN
            new CfnOutput(this, "HTTP API Url", new CfnOutputProps
            {
                Value = _apiGateway.Url
            });
        }
Beispiel #3
0
        internal PollyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Lambda Function that takes in text and returns a polly voice synthesis
            _pollyFunction = new Lambda.Function(this, "pollyHandler", new Lambda.FunctionProps
            {
                Runtime = Lambda.Runtime.PYTHON_3_8,
                Code    = Lambda.Code.FromAsset("lambda_fns"),
                Handler = "polly.handler"
            });

            // https://docs.aws.amazon.com/polly/latest/dg/api-permissions-reference.html
            // https://docs.aws.amazon.com/translate/latest/dg/translate-api-permissions-ref.html
            _pollyPolicy = new IAM.PolicyStatement(new IAM.PolicyStatementProps
            {
                Effect    = IAM.Effect.ALLOW,
                Resources = new[] { "*" },
                Actions   = new[]
                {
                    "translate:TranslateText", "polly:SynthesizeSpeech"
                }
            });

            _pollyFunction.AddToRolePolicy(_pollyPolicy);

            // defines an API Gateway Http API resource backed by our "pollyHandler" function.
            _httpApi = new APIGatewayV2.HttpApi(this, "Polly", new APIGatewayV2.HttpApiProps
            {
                DefaultIntegration = new APIGatewayV2Integrations.LambdaProxyIntegration(
                    new APIGatewayV2Integrations.LambdaProxyIntegrationProps
                {
                    Handler = _pollyFunction
                })
            });

            new CfnOutput(this, "HTTP API Url", new CfnOutputProps
            {
                Value = _httpApi.Url
            });
        }
Beispiel #4
0
        // Hackiness to set stagevariable: https://github.com/aws/aws-cdk/issues/6143#issuecomment-720432475
        private AwsIntegration StageSpecificLambda(Lambda.Function lambda)
        {
            var credentialsRole = new IAM.Role(this, "apigateway-api-role", new IAM.RoleProps
            {
                AssumedBy = new IAM.ServicePrincipal("apigateway.amazonaws.com"),
            });

            // Add the regular lambda Arns to the credentialsRole
            credentialsRole.AddToPolicy(
                new IAM.PolicyStatement(new IAM.PolicyStatementProps
            {
                Actions   = new[] { "lambda:InvokeFunction" },
                Resources = new[]
                {
                    lambda.FunctionArn,
                    $"{lambda.FunctionArn}:*"
                },
                Effect = IAM.Effect.ALLOW
            })
                );

            var stageLambda = Lambda.Function.FromFunctionArn(this, "MyLambda-preprod", lambda.FunctionArn + ":${stageVariables.lambdaAlias}");

            // Add the stageLambda Arn to the integration.
            var integration = new AwsIntegration(new AwsIntegrationProps
            {
                Proxy   = true,
                Service = "lambda",
                Path    = $"2015-03-31/functions/{stageLambda.FunctionArn}/invocations",
                Options = new IntegrationOptions
                {
                    CredentialsRole = credentialsRole,
                }
            });

            return(integration);
        }
        internal TheScheduledLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // DynamoDB Table
            _dynamoDbTable = new DynamoDB.Table(this, "RequestTable", new DynamoDB.TableProps
            {
                PartitionKey = new DynamoDB.Attribute
                {
                    Name = "requestid", Type = DynamoDB.AttributeType.STRING
                },
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            // Create the Lambda function we want to run on a schedule
            _functionScheduled = new Lambda.Function(this, "ScheduledLambda", new Lambda.FunctionProps
            {
                Runtime     = Lambda.Runtime.NODEJS_12_X,          // execution environment
                Handler     = "index.handler",                     // file is "index", function is "handler"
                Code        = Lambda.Code.FromAsset("lambda_fns"), // code loaded from the "lambda_fns" directory,
                Environment = new Dictionary <string, string>
                {
                    { "TABLE_NAME", _dynamoDbTable.TableName }
                }
            });

            // Allow our lambda fn to write to the table
            _dynamoDbTable.GrantReadWriteData(_functionScheduled);

            // Create EventBridge rule that will execute our Lambda every 2 minutes
            _ruleScheduled = new Events.Rule(this, "scheduledLambda-schedule", new Events.RuleProps
            {
                Schedule = Events.Schedule.Expression("rate(2 minutes)")
            });

            // Set the target of our EventBridge rule to our Lambda function
            _ruleScheduled.AddTarget(new EventsTarget.LambdaFunction(_functionScheduled));
        }
Beispiel #6
0
        internal TheScalableWebhookStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            /*
             * DynamoDB Table
             * This is standing in for what is RDS on the diagram due to simpler/cheaper setup
             */
            _dynamoDbTable = new DynamoDB.Table(this, "Messages", new DynamoDB.TableProps
            {
                PartitionKey = new DynamoDB.Attribute {
                    Name = "id", Type = DynamoDB.AttributeType.STRING
                }
            });

            /*
             * Queue Setup
             */
            _queueRds = new SQS.Queue(this, "RDSPublishQueue", new SQS.QueueProps
            {
                VisibilityTimeout = Duration.Seconds(300)
            });

            /*
             * Lambdas
             * Both publisher and subscriber from pattern
             */

            /*
             * defines an AWS  Lambda resource to publish to our sqs_queue
             */
            _functionPublish = new Lambda.Function(this, "SQSPublishLambdaHandler", new Lambda.FunctionProps
            {
                Runtime     = Lambda.Runtime.NODEJS_12_X,                  // execution environment
                Handler     = "lambda.handler",                            // file is "lambda", function is "handler"
                Code        = Lambda.Code.FromAsset("lambda_fns/publish"), // code loaded from the "lambda_fns/publish" directory
                Environment = new Dictionary <string, string>
                {
                    { "queueURL", _queueRds.QueueUrl }
                }
            });

            _queueRds.GrantSendMessages(_functionPublish);

            /*
             * defines an AWS  Lambda resource to pull from our sqs_queue
             */
            _functionSubscribe = new Lambda.Function(this, "SQSSubscribeLambdaHandler", new Lambda.FunctionProps
            {
                Runtime     = Lambda.Runtime.NODEJS_12_X,                    // execution environment
                Handler     = "lambda.handler",                              // file is "lambda", function is "handler"
                Code        = Lambda.Code.FromAsset("lambda_fns/subscribe"), // code loaded from the "lambda_fns/subscribe" directory
                Environment = new Dictionary <string, string>
                {
                    { "queueURL", _queueRds.QueueUrl },
                    { "tableName", _dynamoDbTable.TableName }
                },
                ReservedConcurrentExecutions = 2 // throttle lambda to 2 concurrent invocations
            });

            _queueRds.GrantConsumeMessages(_functionSubscribe);
            _functionSubscribe.AddEventSource(new LambdaEvents.SqsEventSource(_queueRds));
            _dynamoDbTable.GrantReadWriteData(_functionSubscribe);

            /**
             * API Gateway Proxy
             * Used to expose the webhook through a URL
             *
             * defines an API Gateway REST API resource backed by our "sqs_publish_lambda" function.
             */
            new APIG.LambdaRestApi(this, "Endpoint", new APIG.LambdaRestApiProps
            {
                Handler = _functionPublish
            });
        }
Beispiel #7
0
        internal ApiGatewayCDKStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var api = new RestApi(this, "MyApi2", new RestApiProps
            {
                RestApiName   = "my-api2",
                Deploy        = true,
                DeployOptions = new StageOptions
                {
                    StageName = "preprod",
                    Variables = new Dictionary <string, string>
                    {
                        { "lambdaAlias", "preprod" }
                    },
                    TracingEnabled = true
                }
            });

            //var deployment = new Deployment(this, "preprd", new DeploymentProps
            //{
            //    Api = api,
            //    Description = "Initial Deployment",
            //    RetainDeployments
            //});

            //deployment.AddStage("prod");
            //deployment.AddStage("preprod");

            var ddbTable = new DynamoDB.Table(this, "SampleTable", new DynamoDB.TableProps
            {
                TableName    = "SampleTable",
                PartitionKey = new DynamoDB.Attribute
                {
                    Name = "PartitionKey",
                    Type = DynamoDB.AttributeType.STRING
                },
                SortKey = new DynamoDB.Attribute
                {
                    Name = "SortKey",
                    Type = DynamoDB.AttributeType.STRING
                }
            });

            var lambda = new Lambda.Function(this, "MyLambda", new Lambda.FunctionProps
            {
                FunctionName          = "DemoProxyLambda",
                Code                  = Lambda.Code.FromAsset("./LambdaSource"),
                Handler               = "WebAppLambda::WebAppLambda.LambdaEntryPoint::FunctionHandlerAsync",
                Runtime               = Lambda.Runtime.DOTNET_CORE_3_1,
                MemorySize            = 1536,
                Timeout               = Duration.Seconds(30),
                CurrentVersionOptions = new Lambda.VersionOptions
                {
                    RemovalPolicy = RemovalPolicy.RETAIN,
                    RetryAttempts = 1,
                },
                Tracing     = Lambda.Tracing.ACTIVE,
                Environment = new Dictionary <string, string>
                {
                    { "CodeVersionString", "0.0.13" }
                }
            });

            lambda.Role.AttachInlinePolicy(new IAM.Policy(this, "lambdaiam", new IAM.PolicyProps
            {
                PolicyName = "DynamoDbAccess",
                Document   = new IAM.PolicyDocument(new IAM.PolicyDocumentProps
                {
                    Statements = new[]
                    {
                        new IAM.PolicyStatement(new IAM.PolicyStatementProps
                        {
                            Effect  = IAM.Effect.ALLOW,
                            Actions = new []
                            {
                                "dynamodb:BatchGetItem",
                                "dynamodb:BatchWriteItem",
                                "dynamodb:PutItem",
                                "dynamodb:DeleteItem",
                                "dynamodb:PartiQLUpdate",
                                "dynamodb:Scan",
                                "dynamodb:ListTagsOfResource",
                                "dynamodb:Query",
                                "dynamodb:UpdateItem",
                                "dynamodb:PartiQLSelect",
                                "dynamodb:DescribeTable",
                                "dynamodb:PartiQLInsert",
                                "dynamodb:GetItem",
                                "dynamodb:GetRecords",
                                "dynamodb:PartiQLDelete"
                            },
                            Resources = new []
                            {
                                ddbTable.TableArn
                            }
                        })
                    }
                })
            }));

            lambda.CurrentVersion.AddAlias("preprod");

            var awsIntegration = StageSpecificLambda(lambda);

            api.Root.AddProxy(new ProxyResourceOptions
            {
                DefaultIntegration = awsIntegration
            });

            api.Root.AddMethod("GET", awsIntegration);

            new RouteToS3(this, "s3route", new RouteToS3Props
            {
                Api = api,
                PathInApiGateway = "content",
                S3Bucket         = "test-rfsship-content",
                S3Prefix         = "content",
            });
        }
        internal TheStateMachineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Step Function Starts Here

            // The first thing we need to do is see if they are asking for pineapple on a pizza
            _pineappleCheckHandler = new Lambda.Function(this, "pineappleCheckHandler", new Lambda.FunctionProps
            {
                Runtime = Lambda.Runtime.NODEJS_12_X,
                Code    = Lambda.Code.FromAsset("lambda_fns"),
                Handler = "orderPizza.handler"
            });

            /*
             * Step functions are built up of steps, we need to define our first step
             * This step was refactored due to Deprecated function
             */
            _orderPizzaTask = new StepFunctionTasks.LambdaInvoke(this, "Order Pizza Job", new StepFunctionTasks.LambdaInvokeProps
            {
                LambdaFunction      = _pineappleCheckHandler,
                InputPath           = "$.flavour",
                ResultPath          = "$.pineappleAnalysis",
                PayloadResponseOnly = true
            });

            // Pizza Order failure step defined
            _jobFailed = new StepFunction.Fail(this, "Sorry, We Dont add Pineapple", new StepFunction.FailProps
            {
                Cause = "They asked for Pineapple",
                Error = "Failed To Make Pizza"
            });

            // If they didnt ask for pineapple let's cook the pizza
            _cookPizza = new StepFunction.Pass(this, "Lets make your pizza");

            // If they ask for a pizza with pineapple, fail. Otherwise cook the pizza
            _chainDefinition = StepFunction.Chain
                               .Start(_orderPizzaTask)
                               .Next(new StepFunction.Choice(this, "With Pineapple?") // Logical choice added to flow
                                     .When(StepFunction.Condition.BooleanEquals("$.pineappleAnalysis.containsPineapple", true), _jobFailed)
                                     .Otherwise(_cookPizza));

            // Building the state machine
            _stateMachine = new StepFunction.StateMachine(this, "StateMachine", new StepFunction.StateMachineProps
            {
                Definition       = _chainDefinition,
                Timeout          = Duration.Minutes(5),
                TracingEnabled   = true,
                StateMachineType = StepFunction.StateMachineType.EXPRESS
            });

            /**
             * HTTP API Definition
             **/

            // We need to give our HTTP API permission to invoke our step function
            _httpApiRole = new IAM.Role(this, "HttpAPIRole", new IAM.RoleProps
            {
                AssumedBy      = new IAM.ServicePrincipal("apigateway.amazonaws.com"),
                InlinePolicies = new Dictionary <string, IAM.PolicyDocument>
                {
                    { "AllowSFNExec", new IAM.PolicyDocument(new IAM.PolicyDocumentProps
                        {
                            Statements = new IAM.PolicyStatement[]
                            {
                                new IAM.PolicyStatement(new IAM.PolicyStatementProps
                                {
                                    Actions   = new string[] { "states:StartSyncExecution" },
                                    Effect    = IAM.Effect.ALLOW,
                                    Resources = new string[] { _stateMachine.StateMachineArn }
                                })
                            }
                        }) }
                }
            });

            _api = new APIGateway.HttpApi(this, "TheStateMachineAPI", new APIGateway.HttpApiProps
            {
                CreateDefaultStage = true
            });

            _integration = new APIGateway.CfnIntegration(this, "Integration", new APIGateway.CfnIntegrationProps
            {
                ApiId              = _api.HttpApiId,
                IntegrationType    = "AWS_PROXY",
                ConnectionType     = "INTERNET",
                IntegrationSubtype = "StepFunctions-StartSyncExecution",
                CredentialsArn     = _httpApiRole.RoleArn,
                RequestParameters  = new Dictionary <string, string>
                {
                    { "Input", "$request.body" }, { "StateMachineArn", _stateMachine.StateMachineArn }
                },
                PayloadFormatVersion = "1.0",
                TimeoutInMillis      = 10000
            });

            new APIGateway.CfnRoute(this, "DefaultRoute", new APIGateway.CfnRouteProps
            {
                ApiId    = _api.HttpApiId,
                RouteKey = APIGateway.HttpRouteKey.DEFAULT.Key,
                Target   = "integrations/" + _integration.Ref
            });

            new Amazon.CDK.CfnOutput(this, "HTTP API Url", new Amazon.CDK.CfnOutputProps
            {
                Value = _api.Url
            });
        }
Beispiel #9
0
        internal TheStateMachineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Step Function Starts Here

            // The first thing we need to do is see if they are asking for pineapple on a pizza
            _pineppaleCheckHandler = new Lambda.Function(this, "pineappleCheckLambdaHandler", new Lambda.FunctionProps
            {
                Runtime = Lambda.Runtime.NODEJS_12_X,
                Code    = Lambda.Code.FromAsset("lambda_fns"),
                Handler = "orderPizza.handler"
            });

            /*
             * Step functions are built up of steps, we need to define our first step
             * This step was refactored due to Deprecated function
             */
            _orderPizzaTask = new StepFuncionTasks.LambdaInvoke(this, "Order Pizza Job", new StepFuncionTasks.LambdaInvokeProps
            {
                LambdaFunction      = _pineppaleCheckHandler,
                InputPath           = "$.flavour",
                ResultPath          = "$.pineappleAnalysis",
                PayloadResponseOnly = true
            });

            // Pizza Order failure step defined
            _jobFailed = new StepFunction.Fail(this, "Sorry, We Dont add Pineapple", new StepFunction.FailProps
            {
                Cause = "Failed To Make Pizza",
                Error = "They asked for Pineapple"
            });

            // If they didnt ask for pineapple let's cook the pizza
            _cookPizza = new StepFunction.Pass(this, "Lets make your pizza");

            // If they ask for a pizza with pineapple, fail. Otherwise cook the pizza
            _chainDefinition = StepFunction.Chain
                               .Start(_orderPizzaTask)
                               .Next(new StepFunction.Choice(this, "With Pineapple?") // Logical choice added to flow
                                     .When(StepFunction.Condition.BooleanEquals("$.pineappleAnalysis.containsPineapple", true), _jobFailed)
                                     .Otherwise(_cookPizza));

            // Building the state machine
            _stateMachine = new StepFunction.StateMachine(this, "StateMachine", new StepFunction.StateMachineProps
            {
                Definition = _chainDefinition,
                Timeout    = Duration.Minutes(5)
            });

            /**
             * Dead Letter Queue Setup
             * SQS creation
             * https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html
             */
            _deadeLetterQueue = new SQS.Queue(this, "stateMachineLambdaDLQ", new SQS.QueueProps
            {
                VisibilityTimeout = Duration.Seconds(300)
            });

            // defines an AWS Lambda resource to connect to our API Gateway
            _stateMachineHandler = new Lambda.Function(this, "stateMachineLambdaHandler", new Lambda.FunctionProps
            {
                Runtime         = Lambda.Runtime.NODEJS_12_X,
                Code            = Lambda.Code.FromAsset("lambda_fns"),
                Handler         = "stateMachineLambda.handler",
                DeadLetterQueue = _deadeLetterQueue,
                Environment     = new Dictionary <string, string>
                {
                    { "statemachine_arn", _stateMachine.StateMachineArn }
                }
            });

            // Grants to state machine execution
            _stateMachine.GrantStartExecution(_stateMachineHandler);

            /*
             * Simple API Gateway proxy integration
             */
            // defines an API Gateway REST API resource backed by our "sqs_publish_lambda" function.
            new APIGateway.LambdaRestApi(this, "Endpoint", new APIGateway.LambdaRestApiProps
            {
                Handler = _stateMachineHandler
            });
        }
        public SrcStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
        {
            #region VPC, Subnets and Security Groups
            IVpc batchVpc = new Vpc(this, Constants.VPC_ID, new VpcProps {
                Cidr   = Constants.CIDR_RANGE,
                MaxAzs = 4
            });

            var privateSubnetIds = new List <string>();
            foreach (Subnet subnet in batchVpc.PrivateSubnets)
            {
                privateSubnetIds.Add(subnet.SubnetId);
            }

            var batchSecurityGroup = new SecurityGroup(this, Constants.BATCH_SECURITY_GROUP_ID,
                                                       new SecurityGroupProps {
                Vpc = batchVpc,
                SecurityGroupName = Constants.BATCH_SECURITY_GROUP_NAME,
                Description       = Constants.BATCH_SECURITY_GROUP_DESCRIPTION,
            }
                                                       );

            var batchSecurityGroupIds = new List <string>()
            {
                batchSecurityGroup.SecurityGroupId
            };

            #endregion

            #region S3, DynamoDB, Lambda (to trigger the batch on file drop)
            s3.Bucket bucket = new s3.Bucket(this, Constants.S3_BUCKET_ID, new s3.BucketProps {
                BucketName = Constants.S3_BUCKET_NAME + this.Account
            });
            var bucketName = bucket.BucketName;

            var gsi = new dynamo.GlobalSecondaryIndexProps()
            {
                IndexName    = "GSI",
                PartitionKey = new dynamo.Attribute {
                    Name = "CreatedTime", Type = dynamo.AttributeType.STRING
                },
                ProjectionType = dynamo.ProjectionType.KEYS_ONLY
            };

            dynamo.Table table = new dynamo.Table(this, Constants.DynamoDB_TABLE_ID, new dynamo.TableProps {
                TableName    = Constants.DynamoDB_TABLE_ID,
                PartitionKey = new dynamo.Attribute {
                    Name = "ProductId", Type = dynamo.AttributeType.STRING
                },
                BillingMode = dynamo.BillingMode.PAY_PER_REQUEST
            });
            table.AddGlobalSecondaryIndex(gsi);


            var lambdaBatchExecutionRoleProvider = new LambdaBatchExecutionRole(this, Constants.LAMBDA_BATCH_EXECUTION_ROLE_ID);
            #endregion

            DockerImageAsset imageAsset = new DockerImageAsset(this, "BatchProcessorImage", new DockerImageAssetProps {
                Directory      = Constants.BATCH_PROCESSOR_PYTHON_CODE_PATH,
                RepositoryName = Constants.ECR_REPOSITORY_NAME
            });

            #region Batch - ComputeEnvironment - Job Queue - Job Definition
            var batchServiceRole     = new BatchServiceRole(this, Constants.BATCH_SERVICE_ROLE_ID);
            var ecsInstanceRole      = new EcsInstanceRole(this, Constants.ECS_INSTANCE_ROLE_ID);
            var batchInstanceProfile = new InstanceProfile(this, Constants.BATCH_INSTANCE_PROFILE_ID, ecsInstanceRole);

            var computeEnvironment = new batch.CfnComputeEnvironment(this, Constants.BATCH_COMPUTE_ENVIRONMENT_ID,
                                                                     new batch.CfnComputeEnvironmentProps {
                ComputeEnvironmentName = Constants.BATCH_COMPUTE_ENVIRONMENT_NAME,
                Type             = Constants.BATCH_COMPUTE_TYPE,
                ServiceRole      = batchServiceRole.Role.RoleName,
                ComputeResources = new batch.CfnComputeEnvironment.ComputeResourcesProperty {
                    Type          = Constants.BATCH_COMPUTE_RESOURCE_TYPE,
                    MinvCpus      = 0,
                    MaxvCpus      = 32,
                    DesiredvCpus  = 0,
                    InstanceRole  = ecsInstanceRole.Role.RoleName,
                    InstanceTypes = new string[] {
                        Constants.BATCH_INSTANCE_TYPE
                    },
                    SecurityGroupIds = batchSecurityGroupIds.ToArray(),
                    Subnets          = privateSubnetIds.ToArray()
                }
            });

            var computeEnvironmentOrders = new List <batch.CfnJobQueue.ComputeEnvironmentOrderProperty>();
            var computeEnvironmentOrder  = new batch.CfnJobQueue.ComputeEnvironmentOrderProperty()
            {
                Order = 1,
                ComputeEnvironment = computeEnvironment.Ref
            };
            computeEnvironmentOrders.Add(computeEnvironmentOrder);

            var batchProcessingJobQueue = new batch.CfnJobQueue(this, Constants.BATCH_JOB_QUEUE_ID, new batch.CfnJobQueueProps {
                JobQueueName            = Constants.BATCH_PROCESSING_JOB_QUEUE,
                Priority                = 1,
                ComputeEnvironmentOrder = computeEnvironmentOrders.ToArray()
            });

            var batchProcessingJobDefinition = new batch.CfnJobDefinition(this, Constants.BATCH_JOB_DEFINITION_ID, new batch.CfnJobDefinitionProps {
                Type = Constants.CONTAINER,
                JobDefinitionName   = Constants.BATCH_JOB_DEFINITION_NAME,
                ContainerProperties = new batch.CfnJobDefinition.ContainerPropertiesProperty()
                {
                    Image   = imageAsset.ImageUri,
                    Vcpus   = Constants.BATCH_JOB_DEFINITION_VCPU,
                    Memory  = Constants.BATCH_JOB_DEFINITION_MemoryLimitMiB,
                    Command = new string[] {
                        "python",
                        "batch_processor.py"
                    }
                }
            });
            #endregion


            #region lambda s3 event trigger

            BatchTriggerLambdaInput batchTriggerLambdaInput = new BatchTriggerLambdaInput {
                BucketName         = bucketName,
                FileName           = "sample.csv",
                Region             = "us-east-1",
                BatchJobDefinition = batchProcessingJobDefinition.JobDefinitionName,
                BatchJobName       = Constants.BATCH_JOB_NAME,
                BatchJobQueue      = batchProcessingJobQueue.JobQueueName,
                DBTable            = table.TableName
            };

            lambda.Function lambda = BatchTriggerLambda.BatchTriggerLambdaFunction(this, Constants.LAMBDA_NAME,
                                                                                   batchTriggerLambdaInput, lambdaBatchExecutionRoleProvider);

            var batchLambdaFunction = new LambdaFunction(
                lambda
                );

            var eventPutSource = new eventsources.S3EventSource(bucket, new eventsources.S3EventSourceProps {
                Events = new s3.EventType[] {
                    s3.EventType.OBJECT_CREATED_PUT
                }
            });

            lambda.AddEventSource(eventPutSource);

            #endregion

            #region OUTPUTS
            var cfnComputeOutput = new CfnOutput(this, Constants.BATCH_COMPUTE_ENVIRONMENT_NAME_OUTPUT_ID,
                                                 new CfnOutputProps {
                Value = computeEnvironment.Ref
            }
                                                 );

            var cfnS3Output = new CfnOutput(this, Constants.S3_BUCKET_OUTPUT_ID,
                                            new CfnOutputProps {
                Value = bucket.BucketName
            }
                                            );

            var cfnEcrRepositoryOutput = new CfnOutput(this, Constants.ECR_REPOSITORY_OUTPUT_ID,
                                                       new CfnOutputProps {
                Value = imageAsset.Repository.RepositoryArn
            }
                                                       );

            var cfnDynamoTableOutput = new CfnOutput(this, Constants.DYNAMO_TABLE_OUTPUT_ID,
                                                     new CfnOutputProps {
                Value = table.TableName
            }
                                                     );

            var cfnLambdaRepositoryOutput = new CfnOutput(this, Constants.LAMBDA_OUTPUT_ID,
                                                          new CfnOutputProps {
                Value = lambda.FunctionArn
            }
                                                          );

            #endregion

            Tag.Add(this, "Name", Constants.APP_NAME);
        }