Beispiel #1
0
        internal AutoDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // account and role info
            var automationAccountId      = "123456789";
            var automationWorkerRoleName = $"AWS-SystemsManager-AutomationExecutionRole-{Aws.REGION}";
            var automationAdminRoleName  = $"AWS-SystemsManager-AutomationAdministrationRole-{Aws.REGION}";

            //Goes into Automation account
            Role automationAdminRole = new Role(this, "autoAdminRole", new RoleProps
            {
                AssumedBy = new CompositePrincipal(
                    new ServicePrincipal("ssm.amazonaws.com")
                    ),
                RoleName       = automationAdminRoleName,
                InlinePolicies = new Dictionary <string, PolicyDocument>
                {
                    ["ExecutionPolicy"] = new PolicyDocument(new PolicyDocumentProps
                    {
                        Statements = new PolicyStatement[]
                        {
                            new PolicyStatement(new PolicyStatementProps
                            {
                                Effect    = Effect.ALLOW,
                                Resources = new [] { $"arn:aws:iam::*:role/{automationWorkerRoleName}" },//construct this
                                Actions   = new []
                                {
                                    "sts:AssumeRole"
                                }
                            }),
                            new PolicyStatement(new PolicyStatementProps
                            {
                                Effect    = Effect.ALLOW,
                                Resources = new [] { "*" },
                                Actions   = new [] { "organizations:ListAccountsForParent" }
                            })
                        }
                    })
                }
            });

            var listResourceGroups = new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Resources = new[] { "*" },
                Actions   = new[]
                {
                    "resource-groups:ListGroupResources",
                    "tag:GetResources"
                }
            });

            var passRole = new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Resources = new[] {
                    Arn.Format(new ArnComponents
                    {
                        Account      = automationAccountId,
                        Region       = "",
                        Resource     = "role",
                        ResourceName = automationWorkerRoleName,
                        Service      = "iam"
                    }, this)
                },
                Actions = new[] { "iam:PassRole" }
            });


            var managedPolicyTest = new ManagedPolicy(this, "test-managed-policy", new ManagedPolicyProps
            {
                Statements = new PolicyStatement[]
                {
                    listResourceGroups,
                    passRole
                }
            });


            //Goes into all accounts
            Role automationWorkerRole = new Role(this, "automasterrole", new RoleProps
            {
                AssumedBy = new CompositePrincipal(
                    new AccountPrincipal(automationAccountId),
                    new ServicePrincipal("ssm.amazonaws.com")
                    ),
                RoleName        = automationWorkerRoleName,
                ManagedPolicies = new IManagedPolicy[] {
                    ManagedPolicy.FromAwsManagedPolicyName("service-role/AmazonSSMAutomationRole"),
                    managedPolicyTest
                },
                Path = "/",

                InlinePolicies = new Dictionary <string, PolicyDocument>
                {
                    ["ExecutionPolicy"] = new PolicyDocument(new PolicyDocumentProps
                    {
                        Statements = new PolicyStatement[]
                        {
                            new PolicyStatement(new PolicyStatementProps
                            {
                                Effect    = Effect.ALLOW,
                                Resources = new [] { "*" },
                                Actions   = new []
                                {
                                    "resource-groups:ListGroupResources",
                                    "tag:GetResources"
                                }
                            }),
                            new PolicyStatement(new PolicyStatementProps
                            {
                                Effect    = Effect.ALLOW,
                                Resources = new[] {
                                    Arn.Format(new ArnComponents
                                    {
                                        Account      = automationAccountId,
                                        Region       = "",
                                        Resource     = "role",
                                        ResourceName = automationWorkerRoleName,
                                        Service      = "iam"
                                    }, this)
                                },
                                Actions = new [] { "iam:PassRole" }
                            })
                        }
                    })
                }
            });


            User automationUser = new User(this, "automation-user", new UserProps
            {
                UserName = "******"
            });


            Role myLimitedAssumeRole = new Role(this, "roleToAssume", new RoleProps
            {
                AssumedBy = new ArnPrincipal(Arn.Format(new ArnComponents
                {
                    Account      = automationAccountId,
                    Region       = "",
                    Resource     = "user",
                    ResourceName = automationUser.UserName,
                    Service      = "iam"
                }, this)),
                RoleName = $"Automation-Restricted-{Aws.REGION}",

                InlinePolicies = new Dictionary <string, PolicyDocument>
                {
                    ["limited-actions"] = new PolicyDocument(new PolicyDocumentProps
                    {
                        Statements = new PolicyStatement[] {
                            new PolicyStatement(new PolicyStatementProps {
                                Resources = new string[]
                                {
                                    "*"
                                },
                                Actions = new string[]
                                {
                                    "ssm:DescribeAutomationExecutions",
                                    "ssm:DescribeAutomationStepExecutions",
                                    "ssm:DescribeDocument",
                                    "ssm:GetAutomationExecution",
                                    "ssm:GetDocument",
                                    "ssm:ListDocuments",
                                    "ssm:ListDocumentVersions",
                                    "ssm:StartAutomationExecution"
                                }
                            }),
                            new PolicyStatement(new PolicyStatementProps {
                                Resources = new string[]
                                {
                                    Arn.Format(new ArnComponents
                                    {
                                        Account      = automationAccountId,
                                        Region       = "",
                                        Resource     = "role",
                                        ResourceName = automationAdminRoleName,
                                        Service      = "iam"
                                    }, this)
                                },
                                Actions = new string[]
                                {
                                    "iam:PassRole"
                                },
                                Effect = Effect.ALLOW
                            })
                        }
                    })
                }
            });


            //Automation document for updating AMI's
            var amiUpdateDoc = new CfnDocument(this, "ami-update-document", new CfnDocumentProps
            {
                // Name = "ami-update",
                DocumentType = "Automation",

                Content = new Dictionary <string, object>
                {
                    ["schemaVersion"] = "0.3",
                    ["description"]   = "Updates Parameter store with the latest AMI for specific images",
                    ["assumeRole"]    = "{{ AutomationAssumeRole }}",
                    ["parameters"]    = new Dictionary <string, object>
                    {
                        ["AutomationAssumeRole"] = new Dictionary <string, string>
                        {
                            ["type"]        = "String",
                            ["description"] = "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf"
                        },
                        ["AmiID"] = new Dictionary <string, string>
                        {
                            ["type"]        = "String",
                            ["description"] = "(Required) The image ID for the new AMI"
                        },
                        ["ImageName"] = new Dictionary <string, string>
                        {
                            ["type"]        = "String",
                            ["description"] = "(Required) The name of the image which shoud have the AMI ID updated."
                        }
                    },
                    ["mainSteps"] = new Dictionary <string, object>[] {
                        new Dictionary <string, object> {
                            ["action"] = "aws:executeAwsApi",
                            ["name"]   = "getCurrentValue",
                            ["inputs"] = new Dictionary <string, object> {
                                ["Api"]     = "GetParameter",
                                ["Name"]    = "/amis/{{ ImageName }}/id",
                                ["Service"] = "ssm"
                            },
                            ["outputs"] = new Dictionary <string, object>[] {
                                new Dictionary <string, object> {
                                    ["Name"]     = "value",
                                    ["Selector"] = "$.Parameter.Value",
                                    ["Type"]     = "String"
                                }
                            }
                        },

                        /*new Dictionary<string,object> {
                         *  ["action"] = "aws:branch",
                         *  ["name"] = "confirmChange",
                         *  ["isEnd"] = true,
                         *  ["inputs"] = new Dictionary<string,object> {
                         *      ["Choices"] = new Dictionary<string,object>[] {
                         *          new Dictionary<string,object> {
                         *              ["NextStep"] = "getDeployRole",
                         *              ["Not"] = new Dictionary<string,object> {
                         *                  ["StringEquals"] = "{{ Version }}",
                         *                  ["Variable"] = "{{ getCurrentValue.value }}"
                         *              }
                         *          }
                         *      }
                         *  }
                         * },*/
                        new Dictionary <string, object> {
                            ["action"] = "aws:executeAwsApi",
                            ["name"]   = "putNewVersion",
                            ["inputs"] = new Dictionary <string, object> {
                                ["Api"]       = "PutParameter",
                                ["Name"]      = "/amis/{{ ImageName }}/id-new",
                                ["Overwrite"] = true,
                                ["Service"]   = "ssm",
                                ["Value"]     = "{{ AmiID }}",
                                ["Type"]      = "String "
                            }
                        }
                    }
                }
            });



            //create the SSM parameters
            var param       = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-ECS_Optimized/image_id";
            var lookupParam = StringParameter.ValueForTypedStringParameter(this, param);

            var lookupParamTest = StringParameter.ValueForTypedStringParameter(this, param);

            // ami-082a23ee4379053a2 - default

            Console.WriteLine(lookupParam);

            new StringParameter(this, $"ami-windows-parameter", new StringParameterProps
            {
                Description   = $"The AMI ID for the Windows image",
                ParameterName = $"/amis/windows/id",
                //Type = ParameterType.AWS_EC2_IMAGE_ID,
                StringValue = lookupParam,
                Tier        = ParameterTier.STANDARD
            });


            new Amazon.CDK.AWS.SSM.CfnParameter(this, "ami-testing", new Amazon.CDK.AWS.SSM.CfnParameterProps
            {
                DataType    = "aws:ec2:image",
                Description = "Testing ami data type",
                Name        = "/amis/windows-test/id",
                Type        = "String",
                Value       = lookupParamTest
            });


            new StringParameter(this, "ami-deploy-document-parameter", new StringParameterProps
            {
                Description   = "The name of the SSM document for rolling out new AMI's",
                ParameterName = $"/ci-deploy/ci-deploy-document",
                StringValue   = amiUpdateDoc.Ref,
                Tier          = ParameterTier.STANDARD
            });
        }
 internal SecretStack(Construct scope, string id, object passwordObject, string secretName, IStackProps props = null) : base(scope, id, props)
 {
     PasswordObject = passwordObject;
     Secret         = new Secret(this, id, new SecretProps {
         GenerateSecretString = new SecretStringGenerator {
             SecretStringTemplate = JsonSerializer.Serialize(passwordObject),
             GenerateStringKey    = "Password",
             ExcludePunctuation   = true
         },
         SecretName = secretName
     });
 }
        internal MadStack(Construct scope, string id, Vpc vpc, string domainName, string edition, SecretStack secret, IStackProps props = null) : base(scope, id, props)
        {
            AD = new CfnMicrosoftAD(this, "MAD", new CfnMicrosoftADProps
            {
                VpcSettings = new CfnMicrosoftAD.VpcSettingsProperty
                {
                    SubnetIds = vpc.SelectSubnets(new SubnetSelection {
                        SubnetType = SubnetType.PRIVATE
                    }).SubnetIds,
                    VpcId = vpc.VpcId
                },
                Name     = domainName,
                Password = secret.ClearTextSecret,
                Edition  = edition
            });

            var mad_dns_ip1 = Fn.Select(0, AD.AttrDnsIpAddresses);
            var mad_dns_ip2 = Fn.Select(1, AD.AttrDnsIpAddresses);

            new CfnOutput(this, "mad-dns1", new CfnOutputProps {
                Value      = mad_dns_ip1,
                ExportName = "mad-dns1"
            });

            new CfnOutput(this, "mad-dns2", new CfnOutputProps {
                Value      = mad_dns_ip2,
                ExportName = "mad-dns2"
            });
        }
Beispiel #4
0
 internal CdkVpcStack(Construct scope, string id, IStackProps props = null)
     : base(scope, id, props)
 {
     // The code that defines your stack goes here
     var vpc = new CustomVpc(this, $"{id}", Cidr);
 }
Beispiel #5
0
        public WorkshopPipelineStack(Construct parent, string id, IStackProps props = null) : base(parent, id, props)
        {
            // Creates a CodeCommit repository called 'WorkshopRepo'
            var repo = new Repository(this, "WorkshopRepo", new RepositoryProps
            {
                RepositoryName = "WorkshopRepo"
            });

            // Defines the artifact representing the sourcecode
            var sourceArtifact = new Artifact_();
            // Defines the artifact representing the cloud assembly
            // (cloudformation template + all other assets)
            var cloudAssemblyArtifact = new Artifact_();

            // The basic pipeline declaration. This sets the initial structure
            // of our pipeline
            var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps
            {
                PipelineName          = "WorkshopPipeline",
                CloudAssemblyArtifact = cloudAssemblyArtifact,

                // Generates the source artifact from the repo we created in the last step
                SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps
                {
                    ActionName = "CodeCommit",   // Any Git-based source control
                    Output     = sourceArtifact, // Indicates where the artifact is stored
                    Repository = repo            // Designates the repo to draw code from
                }),

                // Builds our source code outlined above into a could assembly artifact
                SynthAction = SimpleSynthAction.StandardNpmSynth(new StandardNpmSynthOptions
                {
                    SourceArtifact        = sourceArtifact,        // Where to get source code to build
                    CloudAssemblyArtifact = cloudAssemblyArtifact, // Where to place built source

                    InstallCommands = new []
                    {
                        "npm install -g aws-cdk",
                        "sudo apt-get install -y dotnet-sdk-3.1"
                    },
                    BuildCommands = new [] { "dotnet build" } // Language-specific build cmd
                })
            });

            var deploy      = new WorkshopPipelineStage(this, "Deploy");
            var deployStage = pipeline.AddApplicationStage(deploy);

            deployStage.AddActions(new ShellScriptAction(new ShellScriptActionProps
            {
                ActionName = "TestViewerEndpoint",
                UseOutputs = new Dictionary <string, StackOutput> {
                    { "ENDPOINT_URL", pipeline.StackOutput(deploy.HCViewerUrl) }
                },
                Commands = new string[] { "curl -Ssf $ENDPOINT_URL" }
            }));
            deployStage.AddActions(new ShellScriptAction(new ShellScriptActionProps
            {
                ActionName = "TestAPIGatewayEndpoint",
                UseOutputs = new Dictionary <string, StackOutput> {
                    { "ENDPOINT_URL", pipeline.StackOutput(deploy.HCEndpoint) }
                },
                Commands = new string[] {
                    "curl -Ssf $ENDPOINT_URL/",
                    "curl -Ssf $ENDPOINT_URL/hello",
                    "curl -Ssf $ENDPOINT_URL/test"
                }
            }));
        }
Beispiel #6
0
        internal CdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var stackProps                = ReportStackProps.ParseOrDefault(props);
            var dframeWorkerLogGroup      = "MagicOnionBenchWorkerLogGroup";
            var dframeMasterLogGroup      = "MagicOnionBenchMasterLogGroup";
            var benchNetwork              = stackProps.GetBenchNetwork();
            var recreateMagicOnionTrigger = stackProps.GetBenchmarkServerBinariesHash();

            // s3
            var s3 = new Bucket(this, "Bucket", new BucketProps
            {
                AutoDeleteObjects = true,
                RemovalPolicy     = RemovalPolicy.DESTROY,
                AccessControl     = BucketAccessControl.PRIVATE,
            });
            var lifecycleRule = new LifecycleRule
            {
                Enabled    = true,
                Prefix     = "reports/",
                Expiration = Duration.Days(stackProps.DaysKeepReports),
                AbortIncompleteMultipartUploadAfter = Duration.Days(1),
            };

            s3.AddLifecycleRule(lifecycleRule);
            s3.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Sid        = "AllowPublicRead",
                Effect     = Effect.ALLOW,
                Principals = new[] { new AnyPrincipal() },
                Actions    = new[] { "s3:GetObject*" },
                Resources  = new[] { $"{s3.BucketArn}/html/*" },
            }));
            s3.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Sid        = "AllowAwsAccountAccess",
                Effect     = Effect.ALLOW,
                Principals = new[] { new AccountRootPrincipal() },
                Actions    = new[] { "s3:*" },
                Resources  = new[] { $"{s3.BucketArn}/*" },
            }));

            // s3 deploy
            var masterDllDeployment = new BucketDeployment(this, "DeployMasterDll", new BucketDeploymentProps
            {
                DestinationBucket    = s3,
                Sources              = new[] { Source.Asset(Path.Combine(Directory.GetCurrentDirectory(), $"out/linux/server")) },
                DestinationKeyPrefix = $"assembly/linux/server"
            });
            var userdataDeployment = new BucketDeployment(this, "UserData", new BucketDeploymentProps
            {
                DestinationBucket    = s3,
                Sources              = new[] { Source.Asset(Path.Combine(Directory.GetCurrentDirectory(), "userdata/")) },
                DestinationKeyPrefix = "userdata/"
            });

            // docker deploy
            var dockerImage = new DockerImageAsset(this, "dframeWorkerImage", new DockerImageAssetProps
            {
                Directory = Path.Combine(Directory.GetCurrentDirectory(), "app"),
                File      = "ConsoleAppEcs/Dockerfile.Ecs",
            });
            var dframeImage = ContainerImage.FromDockerImageAsset(dockerImage);

            // network
            var vpc = new Vpc(this, "Vpc", new VpcProps
            {
                MaxAzs              = 2,
                NatGateways         = 0,
                SubnetConfiguration = new[] { new SubnetConfiguration {
                                                  Name = "public", SubnetType = SubnetType.PUBLIC
                                              } },
            });
            var allsubnets = new SubnetSelection {
                Subnets = vpc.PublicSubnets
            };
            var singleSubnets = new SubnetSelection {
                Subnets = new[] { vpc.PublicSubnets.First() }
            };
            var sg = new SecurityGroup(this, "MasterSg", new SecurityGroupProps
            {
                AllowAllOutbound = true,
                Vpc = vpc,
            });

            foreach (var subnet in vpc.PublicSubnets)
            {
                sg.AddIngressRule(Peer.Ipv4(vpc.VpcCidrBlock), Port.AllTcp(), "VPC", true);
            }

            // service discovery
            var serviceDiscoveryDomain = "local";
            var serverMapName          = "server";
            var dframeMapName          = "dframe-master";
            var ns = new PrivateDnsNamespace(this, "Namespace", new PrivateDnsNamespaceProps
            {
                Vpc  = vpc,
                Name = serviceDiscoveryDomain,
            });
            var serviceDiscoveryServer = ns.CreateService("server", new DnsServiceProps
            {
                Name          = serverMapName,
                DnsRecordType = DnsRecordType.A,
                RoutingPolicy = RoutingPolicy.MULTIVALUE,
            });

            // alb
            var albDnsName = "benchmark-alb";
            var benchToMagicOnionDnsName = benchNetwork.RequireAlb
                ? $"{benchNetwork.EndpointScheme}://{albDnsName}.{stackProps.AlbDomain.domain}"
                : $"{benchNetwork.EndpointScheme}://{serverMapName}.{serviceDiscoveryDomain}";
            IApplicationTargetGroup grpcTargetGroup  = null;
            IApplicationTargetGroup httpsTargetGroup = null;

            if (benchNetwork.RequireAlb)
            {
                // route53
                var hostedZone = HostedZone.FromHostedZoneAttributes(this, "HostedZone", new HostedZoneAttributes
                {
                    HostedZoneId = stackProps.AlbDomain.zoneId,
                    ZoneName     = stackProps.AlbDomain.domain,
                });

                // acm
                var certificate = new DnsValidatedCertificate(this, "certificate", new DnsValidatedCertificateProps
                {
                    DomainName = $"{albDnsName}.{hostedZone.ZoneName}",
                    HostedZone = hostedZone,
                });
                // alb
                var lb = new ApplicationLoadBalancer(this, "LB", new ApplicationLoadBalancerProps
                {
                    Vpc           = vpc,
                    VpcSubnets    = allsubnets,
                    SecurityGroup = new SecurityGroup(this, "AlbSg", new SecurityGroupProps
                    {
                        AllowAllOutbound = true,
                        Vpc = vpc,
                    }),
                    InternetFacing = false,
                    Http2Enabled   = true,
                });
                grpcTargetGroup  = AddGrpcTargetGroup(benchNetwork, vpc, certificate, lb);
                httpsTargetGroup = AddHttpsTargetGroup(benchNetwork, vpc, certificate, lb);

                // Dns Record
                _ = new CnameRecord(this, "alb-alias-record", new CnameRecordProps
                {
                    RecordName = $"{albDnsName}.{stackProps.AlbDomain.domain}",
                    Ttl        = Duration.Seconds(60),
                    Zone       = hostedZone,
                    DomainName = lb.LoadBalancerDnsName,
                });
            }

            // iam
            var iamEc2MagicOnionRole  = GetIamEc2MagicOnionRole(s3, serviceDiscoveryServer);
            var iamEcsTaskExecuteRole = GetIamEcsTaskExecuteRole(new[] { dframeWorkerLogGroup, dframeMasterLogGroup });
            var iamDFrameTaskDefRole  = GetIamEcsDframeTaskDefRole(s3);
            var iamWorkerTaskDefRole  = GetIamEcsWorkerTaskDefRole(s3);

            // secrets
            var ddToken = stackProps.UseEc2DatadogAgentProfiler || stackProps.UseFargateDatadogAgentProfiler
                ? Amazon.CDK.AWS.SecretsManager.Secret.FromSecretNameV2(this, "dd-token", "magiconion-benchmark-datadog-token")
                : null;

            // MagicOnion
            var asg = new AutoScalingGroup(this, "MagicOnionAsg", new AutoScalingGroupProps
            {
                // Monitoring is default DETAILED.
                SpotPrice                = "1.0", // 0.0096 for spot price average for m3.medium
                Vpc                      = vpc,
                SecurityGroup            = sg,
                VpcSubnets               = singleSubnets,
                InstanceType             = stackProps.MagicOnionInstanceType,
                DesiredCapacity          = 1,
                MaxCapacity              = 1,
                MinCapacity              = 0,
                AssociatePublicIpAddress = true,
                MachineImage             = new AmazonLinuxImage(new AmazonLinuxImageProps
                {
                    CpuType        = AmazonLinuxCpuType.X86_64,
                    Generation     = AmazonLinuxGeneration.AMAZON_LINUX_2,
                    Storage        = AmazonLinuxStorage.GENERAL_PURPOSE,
                    Virtualization = AmazonLinuxVirt.HVM,
                }),
                AllowAllOutbound = true,
                GroupMetrics     = new[] { GroupMetrics.All() },
                Role             = iamEc2MagicOnionRole,
                UpdatePolicy     = UpdatePolicy.ReplacingUpdate(),
                Signals          = Signals.WaitForCount(1, new SignalsOptions
                {
                    Timeout = Duration.Minutes(10),
                }),
            });

            asg.AddSecretsReadGrant(ddToken, () => stackProps.UseEc2DatadogAgentProfiler);
            var userdata = GetUserData(recreateMagicOnionTrigger, s3.BucketName, stackProps.BenchmarkBinaryNames, serviceDiscoveryServer.ServiceId, stackProps.UseEc2CloudWatchAgentProfiler, stackProps.UseEc2DatadogAgentProfiler);

            asg.AddUserData(userdata);
            asg.UserData.AddSignalOnExitCommand(asg);
            asg.Node.AddDependency(masterDllDeployment);
            asg.Node.AddDependency(userdataDeployment);
            if (stackProps.EnableMagicOnionScaleInCron)
            {
                asg.ScaleOnSchedule("ScheduleOut", new BasicScheduledActionProps
                {
                    DesiredCapacity = 1,
                    MaxCapacity     = 1,
                    // AM9:00 (JST+9) on Monday to Wednesday
                    Schedule = Schedule.Expression("0 0 * 1-3 *"),
                });
                asg.ScaleOnSchedule("ScheduleIn", new BasicScheduledActionProps
                {
                    DesiredCapacity = 0,
                    MaxCapacity     = 0,
                    // PM9:00 (JST+9) on Everyday
                    Schedule = Schedule.Expression("0 12 * 1-7 *"),
                });
            }
            if (benchNetwork.RequireAlb)
            {
                asg.AttachToApplicationTargetGroup(grpcTargetGroup);
                asg.AttachToApplicationTargetGroup(httpsTargetGroup);
            }

            // ECS
            var cluster = new Cluster(this, "WorkerCluster", new ClusterProps
            {
                Vpc = vpc,
            });

            cluster.Node.AddDependency(asg); // wait until asg is up

            // dframe-worker
            var dframeWorkerContainerName = "worker";
            var dframeWorkerTaskDef       = new FargateTaskDefinition(this, "DFrameWorkerTaskDef", new FargateTaskDefinitionProps
            {
                ExecutionRole  = iamEcsTaskExecuteRole,
                TaskRole       = iamWorkerTaskDefRole,
                Cpu            = stackProps.WorkerFargate.CpuSize,
                MemoryLimitMiB = stackProps.WorkerFargate.MemorySize,
            });

            dframeWorkerTaskDef.AddContainer(dframeWorkerContainerName, new ContainerDefinitionOptions
            {
                Image       = dframeImage,
                Command     = new[] { "--worker-flag" },
                Environment = new Dictionary <string, string>
                {
                    { "DFRAME_MASTER_CONNECT_TO_HOST", $"{dframeMapName}.{serviceDiscoveryDomain}" },
                    { "DFRAME_MASTER_CONNECT_TO_PORT", "12345" },
                    { "BENCH_SERVER_HOST", benchToMagicOnionDnsName },
                    { "BENCH_REPORTID", stackProps.ReportId },
                    { "BENCH_S3BUCKET", s3.BucketName },
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "WorkerLogGroup", new LogGroupProps
                    {
                        LogGroupName  = dframeWorkerLogGroup,
                        RemovalPolicy = RemovalPolicy.DESTROY,
                        Retention     = RetentionDays.TWO_WEEKS,
                    }),
                    StreamPrefix = dframeWorkerLogGroup,
                }),
            });
            dframeWorkerTaskDef.AddDatadogContainer($"{dframeWorkerContainerName}-datadog", ddToken, () => stackProps.UseFargateDatadogAgentProfiler);
            var dframeWorkerService = new FargateService(this, "DFrameWorkerService", new FargateServiceProps
            {
                ServiceName       = "DFrameWorkerService",
                DesiredCount      = 0,
                Cluster           = cluster,
                TaskDefinition    = dframeWorkerTaskDef,
                VpcSubnets        = singleSubnets,
                SecurityGroups    = new[] { sg },
                PlatformVersion   = FargatePlatformVersion.VERSION1_4,
                MinHealthyPercent = 0,
                AssignPublicIp    = true,
            });

            // dframe-master
            var dframeMasterTaskDef = new FargateTaskDefinition(this, "DFrameMasterTaskDef", new FargateTaskDefinitionProps
            {
                ExecutionRole  = iamEcsTaskExecuteRole,
                TaskRole       = iamDFrameTaskDefRole,
                Cpu            = stackProps.MasterFargate.CpuSize,
                MemoryLimitMiB = stackProps.MasterFargate.MemorySize,
            });

            dframeMasterTaskDef.AddContainer("dframe", new ContainerDefinitionOptions
            {
                Image       = dframeImage,
                Environment = new Dictionary <string, string>
                {
                    { "DFRAME_CLUSTER_NAME", cluster.ClusterName },
                    { "DFRAME_MASTER_SERVICE_NAME", "DFrameMasterService" },
                    { "DFRAME_WORKER_CONTAINER_NAME", dframeWorkerContainerName },
                    { "DFRAME_WORKER_SERVICE_NAME", dframeWorkerService.ServiceName },
                    { "DFRAME_WORKER_TASK_NAME", Fn.Select(1, Fn.Split("/", dframeWorkerTaskDef.TaskDefinitionArn)) },
                    { "DFRAME_WORKER_IMAGE", dockerImage.ImageUri },
                    { "BENCH_REPORTID", stackProps.ReportId },
                    { "BENCH_S3BUCKET", s3.BucketName },
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "MasterLogGroup", new LogGroupProps
                    {
                        LogGroupName  = dframeMasterLogGroup,
                        RemovalPolicy = RemovalPolicy.DESTROY,
                        Retention     = RetentionDays.TWO_WEEKS,
                    }),
                    StreamPrefix = dframeMasterLogGroup,
                }),
            });
            dframeMasterTaskDef.AddDatadogContainer($"dframe-datadog", ddToken, () => stackProps.UseFargateDatadogAgentProfiler);
            var dframeMasterService = new FargateService(this, "DFrameMasterService", new FargateServiceProps
            {
                ServiceName       = "DFrameMasterService",
                DesiredCount      = 1,
                Cluster           = cluster,
                TaskDefinition    = dframeMasterTaskDef,
                VpcSubnets        = singleSubnets,
                SecurityGroups    = new[] { sg },
                PlatformVersion   = FargatePlatformVersion.VERSION1_4,
                MinHealthyPercent = 0,
                AssignPublicIp    = true,
            });

            dframeMasterService.EnableCloudMap(new CloudMapOptions
            {
                CloudMapNamespace = ns,
                Name          = dframeMapName,
                DnsRecordType = DnsRecordType.A,
                DnsTtl        = Duration.Seconds(300),
            });

            // output
            new CfnOutput(this, "ReportUrl", new CfnOutputProps {
                Value = $"https://{s3.BucketRegionalDomainName}/html/{stackProps.ReportId}/index.html"
            });
            new CfnOutput(this, "EndPointStyle", new CfnOutputProps {
                Value = stackProps.BenchmarkEndpoint.ToString()
            });
            new CfnOutput(this, "AsgName", new CfnOutputProps {
                Value = asg.AutoScalingGroupName
            });
            new CfnOutput(this, "EcsClusterName", new CfnOutputProps {
                Value = cluster.ClusterName
            });
            new CfnOutput(this, "DFrameWorkerEcsTaskdefImage", new CfnOutputProps {
                Value = dockerImage.ImageUri
            });
        }
Beispiel #7
0
 internal TimestreamDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
 {
     new TimestreamService(this, "Steps");
     // The code that defines your stack goes here
 }
Beispiel #8
0
 internal CdkBlogStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
 {
     // The code that defines your stack goes here
 }
        internal MyDotNetCoreServerlessWebAppEcsFargateCdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var         imageTagParameter = this.Node.TryGetContext("ImageTag");
            string      imageTag          = imageTagParameter.ToString() ?? "latest";
            IRepository ecrRepository     = Repository.FromRepositoryArn(this, "MyDotNetCorServerlessWebAppServiceContainerRepository", "arn:aws:ecr:eu-west-1:098208531922:repository/mydotnetcorewebapp");

            var loadBalancedFargateService = new ApplicationLoadBalancedFargateService(this, "MyDotNetCorServerlessWebAppService", new ApplicationLoadBalancedFargateServiceProps()
            {
                AssignPublicIp   = true,
                TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions()
                {
                    Image = ContainerImage.FromEcrRepository(ecrRepository, imageTag),
                }
            });;
        }
Beispiel #10
0
        internal StepFunctionDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            Bucket stepFunctionDemoBucket = new Bucket(this, "StepFunctionDemoBucket", new BucketProps
            {
                Encryption    = BucketEncryption.S3_MANAGED,
                RemovalPolicy = RemovalPolicy.RETAIN
            });

            Table stepFunctionDemoTable = new Table(this, "StepFunctionDemoTable", new TableProps {
                BillingMode  = BillingMode.PROVISIONED,
                PartitionKey = new Amazon.CDK.AWS.DynamoDB.Attribute
                {
                    Name = "Id",
                    Type = AttributeType.STRING
                },
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            //Step Function invoking Lambda function
            Function invokeOddEvenStepFunction = new Function(this, "InvokeOddEvenStepFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::InvokeOddEvenStepFunction",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Lambda Function that invokes the Demo Step Function",
            });


            //Function to calculate Odd or Even
            Function oddOrEvenFunction = new Function(this, "OddOrEvenFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::OddOrEvenFunction",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Lambda Function that calculates odd or even",
            });

            //Demo Lambda to perform Process 1
            Function process1Function = new Function(this, "Process1Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process1Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process1",
            });

            Function processAFunction = new Function(this, "ProcessAFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process1Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process1",
            });

            //Demo Lambda to perform Process 2
            Function process2Function = new Function(this, "Process2Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process2Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process2",
            });

            //Demo Lambda to perform Process 1
            Function process11Function = new Function(this, "Process11Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process11Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs job process1",
            });

            //Demo Lambda to perform Process 2
            Function process12Function = new Function(this, "Process12Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process12Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs job process2",
            });

            Function taskTokenExecutorFunction = new Function(this, "TaskTokenExecutorFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::TaskTokenExecutor",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that executes Task Token Step",
                Environment = new Dictionary <string, string>()
                {
                    ["STEP_FUNCTION_DEMO_BUCKET"] = stepFunctionDemoBucket.BucketName
                }
            });

            stepFunctionDemoBucket.GrantReadWrite(taskTokenExecutorFunction);


            var oddEvenFunction = new Task(this, "OddEvenFunction", new TaskProps
            {
                Task = new InvokeFunction(oddOrEvenFunction.LatestVersion)
            });


            var process1 = new Task(this, "Process1", new TaskProps
            {
                Task = new InvokeFunction(process1Function.LatestVersion)
            });

            var processA = new Task(this, "ProcessA", new TaskProps
            {
                Task = new InvokeFunction(processAFunction.LatestVersion)
            });


            var process2 = new Task(this, "Process2", new TaskProps
            {
                Task = new InvokeFunction(process2Function.LatestVersion)
            });

            var process11 = new Task(this, "Process11", new TaskProps
            {
                Task       = new InvokeFunction(process11Function.LatestVersion),
                ResultPath = "$.Resolved"
            });

            var process12 = new Task(this, "Process12", new TaskProps
            {
                Task = new InvokeFunction(process12Function.LatestVersion)
            });

            var taskTokenExecutor = new Task(this, "TaskTokenExecutor", new TaskProps
            {
                Task = new RunLambdaTask(taskTokenExecutorFunction.LatestVersion, new RunLambdaTaskProps()
                {
                    IntegrationPattern = ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN,
                    Payload            = TaskInput.FromContextAt("$$.Task.Token")
                }),
                Parameters = new Dictionary <string, object>
                {
                    ["Payload"] = new Dictionary <string, object>
                    {
                        ["TaskToken.$"] = "$$.Task.Token",
                        ["State.$"]     = "$"
                    }
                }
            });


            //Choice to go to Process 1 or Process 2 based on input number is odd or even.
            var isEven = new Choice(this, "Is the number Even?");
            var isResolvedOrOverriden = new Choice(this, "Is Resolved Or Overriden?");

            //var chain1 = Chain.Start(oddEvenFunction)
            //    .Next(isEven
            //            .When(
            //                Condition.StringEquals("$.Result", "Even"),
            //                Chain.Start(process1)
            //                    .Next(process11)
            //                    .Next(isResolvedOrOverriden
            //                        .When(
            //                            Condition.Or(
            //                                new[]
            //                                {
            //                                    Condition.BooleanEquals("$.Resolved", true),
            //                                    Condition.BooleanEquals("$.Override", true)
            //                                }), process12)
            //                        .Otherwise(process2)))
            //            .When(Condition.StringEquals("$.Result", "Odd"), process2));

            var chain1 = Chain.Start(oddEvenFunction)
                         .Next(isEven
                               .When(
                                   Condition.StringEquals("$.Result", "Even"),
                                   Chain.Start(process1)
                                   .Next(taskTokenExecutor)
                                   .Next(isResolvedOrOverriden
                                         .When(
                                             Condition.Or(
                                                 new[]
            {
                Condition.BooleanEquals("$.Resolved", true),
                Condition.BooleanEquals("$.Override", true)
            }), process12)
                                         .Otherwise(process2)))
                               .When(Condition.StringEquals("$.Result", "Odd"), process2));


            //State Machine

            var stateMachine = new StateMachine(this, "JobDemoStateMachine", new StateMachineProps
            {
                StateMachineName = "JobDemoStateMachine",
                Timeout          = Duration.Minutes(5),
                Definition       = chain1
            });

            stateMachine.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "DynamoDBFullAccessForStepFunction", "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"));

            stateMachine.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "LambdaFullAccessForStepFunction", "arn:aws:iam::aws:policy/AWSLambdaFullAccess"));

            var demofargateTask1 = new FargateTaskDefinition(this,
                                                             "demoECSTask1Definition", new FargateTaskDefinitionProps
            {
                MemoryLimitMiB = 4096,
                Cpu            = 2048
            });
            var demofargateTask2 = new FargateTaskDefinition(this,
                                                             "demoECSTask2Definition", new FargateTaskDefinitionProps
            {
                MemoryLimitMiB = 4096,
                Cpu            = 2048
            });

            stepFunctionDemoBucket.GrantReadWrite(demofargateTask2.TaskRole);

            IVpc publicVpc = Vpc.FromLookup(this, "PublicVPC", new VpcLookupOptions
            {
                Tags = new Dictionary <string, string>
                {
                    ["Paces:VpcType"] = "Public"
                }
            });
            var cluster = Cluster.FromClusterAttributes(this, "PublicCluster", new ClusterAttributes
            {
                ClusterName    = "OHC-PACES",
                Vpc            = publicVpc,
                SecurityGroups = new[]
                { SecurityGroup.FromSecurityGroupId(this, "SecurityGroup", "sg-0a1bab8166d8fb715") }
            });

            var container1 = demofargateTask1.AddContainer("app", new ContainerDefinitionOptions
            {
                Image = ContainerImage.FromAsset(".", new AssetImageProps
                {
                    File = "Dockerfile"
                }),
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "demoECSTask1LogGroup", new LogGroupProps
                    {
                        LogGroupName = "/ecs/demoECSTask1-" + RandomString.Generate(10, StackId),
                    }),
                    StreamPrefix = "logs"
                }),
            });


            var container2 = demofargateTask2.AddContainer("app", new ContainerDefinitionOptions
            {
                Image = ContainerImage.FromAsset(".", new AssetImageProps
                {
                    File = "Dockerfile.1"
                }),
                Environment = new Dictionary <string, string>
                {
                    ["STEP_FUNCTION_DEMO_BUCKET"] = stepFunctionDemoBucket.BucketName
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "demoECSTask2LogGroup", new LogGroupProps
                    {
                        LogGroupName = $"/ecs/demoECSTask2-{RandomString.Generate(10, StackId)}",
                    }),
                    StreamPrefix = "logs"
                })
            });


            Rule rule = new Rule(this, "DemoJobRule", new RuleProps
            {
                Schedule = Schedule.Cron(new CronOptions
                {
                    Day    = "*",
                    Hour   = "*",
                    Minute = "1",
                    Month  = "*",
                    Year   = "*"
                }),
                Description = "Runs demo job fargate task",
                Targets     = new IRuleTarget[]
                {
                    new EcsTask(
                        new EcsTaskProps
                    {
                        Cluster         = cluster,
                        TaskDefinition  = demofargateTask2,
                        SubnetSelection = new SubnetSelection
                        {
                            OnePerAz = true
                        }
                    })
                }
            });



            //var ecsTask1 = new Task(this, "ecsTask1", new TaskProps
            //{
            //    InputPath = "$",
            //    Task = new CustomTask(new RunEcsFargateTaskProps
            //    {

            //        Cluster = Cluster.FromClusterAttributes(this, "PublicCluster", new ClusterAttributes
            //        {
            //            ClusterName = "OHC-PACES",
            //            Vpc = publicVpc,
            //            SecurityGroups = new[] { SecurityGroup.FromSecurityGroupId(this, "SecurityGroup", "sg-0a1bab8166d8fb715") }
            //        }),
            //        TaskDefinition = fargateTask1,

            //        ContainerOverrides = new[]
            //        {
            //            new ContainerOverride
            //            {
            //               ContainerDefinition = container,
            //               Command = new []{"$.Data"}
            //            },

            //        }
            //    })
            //});

            var ecsTask1 = new Task(this, "EcsTask1", new TaskProps
            {
                InputPath = "$",
                Task      = new RunEcsFargateTask(new RunEcsFargateTaskProps
                {
                    Cluster        = cluster,
                    TaskDefinition = demofargateTask1,

                    //ContainerOverrides = new[]
                    //{
                    //    new ContainerOverride
                    //    {
                    //        ContainerDefinition = container,
                    //
                    //    },

                    //}
                }),
                Parameters = new Dictionary <string, object>
                {
                    ["Overrides"] = new Dictionary <string, object>
                    {
                        ["ContainerOverrides"] = new Dictionary <string, string>[]
                        {
                            new Dictionary <string, string> {
                                ["Name"]      = "app",
                                ["Command.$"] = "$.ECSPayload"
                            }
                        }
                    }
                }
            });

            var chain2 = Chain.Start(processA).Next(ecsTask1);


            var stateMachineWithTask = new StateMachine(this, "JobDemoStateMachine-1", new StateMachineProps
            {
                StateMachineName = "JobDemoStateMachine-1",
                Timeout          = Duration.Minutes(15),
                Definition       = chain2,
                Role             = Role.FromRoleArn(this, "StateMachineWithTaskRole",
                                                    "arn:aws:iam::342600918501:role/service-role/PacesEdi274DefaultStateMachineRole")
            });

            //All Policies
            // 1. Invoke function policies

            invokeOddEvenStepFunction.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "InvokeLambdaPolicy", "arn:aws:iam::aws:policy/AWSLambdaFullAccess"));

            var policyStatement = new PolicyStatement
            {
                Sid    = "CanInvokeStepFunctions",
                Effect = Effect.ALLOW
            };

            policyStatement.AddActions(new[] { "states:StartExecution" });

            invokeOddEvenStepFunction.AddToRolePolicy(policyStatement);
            policyStatement.AddResources(stateMachine.StateMachineArn);
            invokeOddEvenStepFunction.AddEnvironment(Functions.StateMachineArnKey, stateMachine.StateMachineArn);

            process12Function.AddEnvironment(Functions.StepFunctionDemoBucketKey, stepFunctionDemoBucket.BucketName);

            stepFunctionDemoBucket.GrantReadWrite(process12Function);


            var policyStatementDemofargateTask2 = new PolicyStatement
            {
                Sid    = "CanNotifyStepFunction",
                Effect = Effect.ALLOW
            };

            policyStatementDemofargateTask2.AddActions(new[] { "states:SendTask*" });
            demofargateTask2.AddToExecutionRolePolicy(policyStatementDemofargateTask2);
            demofargateTask2.AddToTaskRolePolicy(policyStatementDemofargateTask2);

            policyStatementDemofargateTask2.AddAllResources();
        }
Beispiel #11
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
            });
        }
Beispiel #12
0
        internal AppStack(Construct scope, RecipeConfiguration <Configuration> recipeConfiguration, IStackProps props = null)
            : base(scope, recipeConfiguration.StackName, props)
        {
            var settings = recipeConfiguration.Settings;

            IVpc vpc;

            if (settings.Vpc.IsDefault)
            {
                vpc = Vpc.FromLookup(this, "Vpc", new VpcLookupOptions
                {
                    IsDefault = true
                });
            }
            else if (settings.Vpc.CreateNew)
            {
                vpc = new Vpc(this, "Vpc", new VpcProps
                {
                    MaxAzs = 2
                });
            }
            else
            {
                vpc = Vpc.FromLookup(this, "Vpc", new VpcLookupOptions
                {
                    VpcId = settings.Vpc.VpcId
                });
            }

            ICluster cluster;

            if (settings.ECSCluster.CreateNew)
            {
                cluster = new Cluster(this, "Cluster", new ClusterProps
                {
                    Vpc         = vpc,
                    ClusterName = settings.ECSCluster.NewClusterName
                });
            }
            else
            {
                cluster = Cluster.FromClusterAttributes(this, "Cluster", new ClusterAttributes
                {
                    ClusterArn     = settings.ECSCluster.ClusterArn,
                    ClusterName    = ECSFargateUtilities.GetClusterNameFromArn(settings.ECSCluster.ClusterArn),
                    SecurityGroups = new ISecurityGroup[0],
                    Vpc            = vpc
                });
            }

            IRole taskRole;

            if (settings.ApplicationIAMRole.CreateNew)
            {
                taskRole = new Role(this, "TaskRole", new RoleProps
                {
                    AssumedBy = new ServicePrincipal("ecs-tasks.amazonaws.com")
                });
            }
            else
            {
                taskRole = Role.FromRoleArn(this, "TaskRole", settings.ApplicationIAMRole.RoleArn, new FromRoleArnOptions {
                    Mutable = false
                });
            }

            var taskDefinition = new FargateTaskDefinition(this, "TaskDefinition", new FargateTaskDefinitionProps
            {
                TaskRole       = taskRole,
                Cpu            = settings.TaskCpu,
                MemoryLimitMiB = settings.TaskMemory
            });

            var logging = new AwsLogDriver(new AwsLogDriverProps
            {
                StreamPrefix = recipeConfiguration.StackName
            });

            var ecrRepository = Repository.FromRepositoryName(this, "ECRRepository", recipeConfiguration.ECRRepositoryName);

            taskDefinition.AddContainer("Container", new ContainerDefinitionOptions
            {
                Image   = ContainerImage.FromEcrRepository(ecrRepository, recipeConfiguration.ECRImageTag),
                Logging = logging
            });

            var fargateServiceProps = new FargateServiceProps
            {
                Cluster        = cluster,
                TaskDefinition = taskDefinition,
                AssignPublicIp = settings.Vpc.IsDefault,
                DesiredCount   = settings.DesiredCount
            };


            if (!string.IsNullOrEmpty(settings.ECSServiceSecurityGroups))
            {
                var ecsServiceSecurityGroups = new List <ISecurityGroup>();
                var count = 1;
                foreach (var securityGroupId in settings.ECSServiceSecurityGroups.Split(','))
                {
                    ecsServiceSecurityGroups.Add(SecurityGroup.FromSecurityGroupId(this, $"AdditionalGroup-{count++}", securityGroupId.Trim(), new SecurityGroupImportOptions
                    {
                        Mutable = false
                    }));
                }

                fargateServiceProps.SecurityGroups = ecsServiceSecurityGroups.ToArray();
            }

            new FargateService(this, "FargateService", fargateServiceProps);
        }
Beispiel #13
0
        internal PipelineStack(
            Construct scope,
            string id,
            string ecrRepositoryName,
            string framework,
            string channel,
            string dockerBuildImage,
            Configuration configuration,
            IStackProps props = null) : base(scope, $"{id}-{framework}", props)
        {
            var repository = Repository.FromRepositoryArn(this, "Repository", configuration.Source.RepositoryArn);

            var sourceArtifact = new Artifact_();
            var outputArtifact = new Artifact_();
            var ecrPolicy      = new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new[] { "ecr:*" },
                Resources = new[] { "*" }
            });


            // Setup CodeCommit cross account role access policies if required
            IRole codeCommitRole = null;

            if (!string.IsNullOrWhiteSpace(configuration.Source.CrossAccountRoleArn))
            {
                codeCommitRole = Role.FromRoleArn(this, "CodeCommitRole", configuration.Source.CrossAccountRoleArn, new FromRoleArnOptions
                {
                    Mutable = false // Flag to indicate CDK to not modify the role
                });
            }

            // Strict ordering is required to make sure CloudFormation template doesn't result in false difference
            var environmentVariablesToCopy = System.Environment.GetEnvironmentVariables()
                                             .Keys.Cast <string>()
                                             .Where(variable => variable.StartsWith("AWS_LAMBDA_"))
                                             .OrderBy(variable => variable);

            // Self mutation
            // TODO: DOTNET-6085 - Migration from CDKPipeline to CodePipeline
            const string cdkCliVersion = "1.159.0";
            var          pipeline      = new CdkPipeline(this, "Pipeline", new CdkPipelineProps
            {
                PipelineName          = $"{id}-{framework}",
                CloudAssemblyArtifact = outputArtifact,
                CdkCliVersion         = cdkCliVersion,

                SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps
                {
                    ActionName = "CodeCommit",
                    Output     = sourceArtifact,
                    Repository = repository,
                    Branch     = configuration.Source.BranchName,
                    Role       = codeCommitRole,
                    Trigger    = CodeCommitTrigger.POLL
                }),

                // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline
                SynthAction = new SimpleSynthAction(new SimpleSynthActionProps
                {
                    SourceArtifact        = sourceArtifact,
                    CloudAssemblyArtifact = outputArtifact,
                    Subdirectory          = "LambdaRuntimeDockerfiles/Infrastructure",
                    InstallCommands       = new[]
                    {
                        $"npm install -g aws-cdk@{cdkCliVersion}",
                    },
                    BuildCommands            = new[] { "dotnet build" },
                    SynthCommand             = "cdk synth",
                    CopyEnvironmentVariables = environmentVariablesToCopy.ToArray()
                })
            });

            var stageEcr = GetStageEcr(this, ecrRepositoryName, configuration);

            var dockerBuildStage = pipeline.AddStage("Stage-DockerBuild");

            // Stage
            // Build AMD64 image
            var dockerBuildAmd64 = new Project(this, "DockerBuild-amd64", new ProjectProps
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"),
                Description = $"Builds and pushes image to {stageEcr}",
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                    Privileged = true
                },
                Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                {
                    Repository  = repository,
                    BranchOrRef = configuration.Source.BranchName
                }),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable {
                          Value = stageEcr
                      } },
                    { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = ecrRepositoryName
                      } },
                    { "AWS_LAMBDA_ARCHITECTURE", new BuildEnvironmentVariable {
                          Value = "amd64"
                      } },
                    { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable {
                          Value = PowershellAmd64
                      } },
                    { "AWS_LAMBDA_IMAGE_TAG", new BuildEnvironmentVariable {
                          Value = configuration.BaseImageAMD64Tags[framework]
                      } },
                    { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable {
                          Value = framework
                      } },
                    { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable {
                          Value = channel
                      } }
                }
            });

            dockerBuildAmd64.AddToRolePolicy(ecrPolicy);
            dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
            {
                Input      = sourceArtifact,
                Project    = dockerBuildAmd64,
                ActionName = "amd64"
            }));

            if (configuration.DockerARM64Images.Contains(framework))
            {
                // Build ARM64 image
                var dockerBuildArm64 = new Project(this, "DockerBuild-arm64", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"),
                    Description = $"Builds and pushes image to {stageEcr}",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_ARM,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = configuration.Source.BranchName
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = ecrRepositoryName
                          } },
                        { "AWS_LAMBDA_ARCHITECTURE", new BuildEnvironmentVariable {
                              Value = "arm64"
                          } },
                        { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable {
                              Value = PowershellArm64
                          } },
                        { "AWS_LAMBDA_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = configuration.BaseImageARM64Tags[framework]
                          } },
                        { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable {
                              Value = framework
                          } },
                        { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable {
                              Value = channel
                          } }
                    }
                });

                dockerBuildArm64.AddToRolePolicy(ecrPolicy);
                dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = dockerBuildArm64,
                    ActionName = "arm64"
                }));
            }

            // Create multi arch image manifest
            var dockerImageManifest = new Project(this, "DockerImageManifest", new ProjectProps
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerImageManifest/buildspec.yml"),
                Description = $"Creates image manifest and pushes to {stageEcr}",
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                    Privileged = true
                },
                Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                {
                    Repository  = repository,
                    BranchOrRef = configuration.Source.BranchName
                }),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable {
                          Value = stageEcr
                      } },
                    { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = ecrRepositoryName
                      } },
                    { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable {
                          Value = BaseImageMultiArch
                      } },
                    { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable {
                          Value = configuration.BaseImageAMD64Tags[framework]
                      } },
                    { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable {
                          Value = configuration.BaseImageARM64Tags[framework]
                      } },
                    { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable {
                          Value = configuration.DockerARM64Images.Contains(framework).ToString()
                      } },
                }
            });

            dockerImageManifest.AddToRolePolicy(ecrPolicy);

            var dockerImageManifestStage = pipeline.AddStage("DockerImageManifest");

            dockerImageManifestStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
            {
                Input      = sourceArtifact,
                Project    = dockerImageManifest,
                ActionName = "DockerImageManifest"
            }));

            // Smoke test AMD64 image
            var amd64SmokeTests = new Project(this, "SmokeTests-amd64", new ProjectProps
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"),
                Description = "Runs smoke tests on the built image.",
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                    Privileged = true
                },
                Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                {
                    Repository  = repository,
                    BranchOrRef = configuration.Source.BranchName
                }),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                          Value = stageEcr
                      } },
                    { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = ecrRepositoryName
                      } },
                    { "AWS_LAMBDA_SOURCE_IMAGE_TAG", new BuildEnvironmentVariable {
                          Value = BaseImageMultiArch
                      } },
                    { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable {
                          Value = PowershellAmd64
                      } },
                    { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable {
                          Value = framework
                      } },
                    { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable {
                          Value = channel
                      } },
                    { "AWS_LAMBDA_DOTNET_BUILD_IMAGE", new BuildEnvironmentVariable {
                          Value = dockerBuildImage
                      } },
                }
            });

            var smokeTestsPolicy = new PolicyStatement(new PolicyStatementProps
            {
                Effect  = Effect.ALLOW,
                Actions = new[]
                {
                    "sts:*",
                    "iam:*",
                    "ecr:*",
                    "lambda:*"
                },
                Resources = new[] { "*" }
            });

            amd64SmokeTests.AddToRolePolicy(smokeTestsPolicy);

            var smokeTestsStage = pipeline.AddStage("SmokeTests");

            smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
            {
                Input      = sourceArtifact,
                Project    = amd64SmokeTests,
                ActionName = "amd64"
            }));

            if (configuration.DockerARM64Images.Contains(framework))
            {
                // Smoke test ARM64 image
                var arm64SmokeTests = new Project(this, "SmokeTests-arm64", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"),
                    Description = "Runs smoke tests on the built image.",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_ARM,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = configuration.Source.BranchName
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = ecrRepositoryName
                          } },
                        { "AWS_LAMBDA_SOURCE_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = BaseImageMultiArch
                          } },
                        { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable {
                              Value = PowershellArm64
                          } },
                        { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable {
                              Value = framework
                          } },
                        { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable {
                              Value = channel
                          } },
                        { "AWS_LAMBDA_DOTNET_BUILD_IMAGE", new BuildEnvironmentVariable {
                              Value = dockerBuildImage
                          } },
                    }
                });

                arm64SmokeTests.AddToRolePolicy(smokeTestsPolicy);

                smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = arm64SmokeTests,
                    ActionName = "arm64"
                }));
            }

            // Beta
            if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Beta))
            {
                var betaDockerPush = new Project(this, "Beta-DockerPush", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"),
                    Description = $"Pushes staged image to {configuration.Ecrs.Beta}",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = configuration.Source.BranchName
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = ecrRepositoryName
                          } },
                        { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable {
                              Value = configuration.Ecrs.Beta
                          } },
                        { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = BaseImageMultiArch
                          } },
                        { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = configuration.BaseImageAMD64Tags[framework]
                          } },
                        { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = configuration.BaseImageARM64Tags[framework]
                          } },
                        { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable {
                              Value = configuration.DockerARM64Images.Contains(framework).ToString()
                          } },
                    }
                });

                betaDockerPush.AddToRolePolicy(ecrPolicy);

                var betaDockerPushStage = pipeline.AddStage("Beta-DockerPush");
                betaDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = betaDockerPush,
                    ActionName = "DockerPush"
                }));
            }


            // Prod
            if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Prod))
            {
                // Manual Approval
                var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval");
                manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps
                {
                    ActionName = "ManualApproval"
                }));


                var prodDockerPush = new Project(this, "Prod-DockerPush", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"),
                    Description = $"Pushes staged image to {configuration.Ecrs.Prod}",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = configuration.Source.BranchName
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = ecrRepositoryName
                          } },
                        { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable {
                              Value = configuration.Ecrs.Prod
                          } },
                        { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = BaseImageMultiArch
                          } },
                        { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = configuration.BaseImageAMD64Tags[framework]
                          } },
                        { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = configuration.BaseImageARM64Tags[framework]
                          } },
                        { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable {
                              Value = configuration.DockerARM64Images.Contains(framework).ToString()
                          } },
                    }
                });

                prodDockerPush.AddToRolePolicy(ecrPolicy);

                var prodDockerPushStage = pipeline.AddStage("Prod-DockerPush");
                prodDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = prodDockerPush,
                    ActionName = "DockerPush"
                }));
            }
        }
        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);
        }
Beispiel #15
0
        internal CdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            //Stage setting for Deployment (Need to have Deploy = false in RestApiProps to configure the Stage
            string environment = "PRD";


            //STORAGE INFRASTRUCTURE
            // default RemovalPolicy is RETAIN (on a "cdk destroy")
            //Create an S3 Bucket (s3 Buckets must be unique for each region)
            //S3 Buckets must be unique by region
            //NOTE: If you put objects in this S3 bucket you will be required to delete it manually
            var rand       = new Random();
            int randNumber = rand.Next(100000);
            var s3Bucket   = new Bucket(this, "MyS3Bucket", new BucketProps
            {
                BucketName    = (environment + "-MyS3Bucket" + randNumber).ToLower(),
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            //Create a DynamoDB Table
            var dynamoDbTable = new Table(this, "User", new TableProps
            {
                TableName    = environment + "-" + "User",
                PartitionKey = new Amazon.CDK.AWS.DynamoDB.Attribute
                {
                    Name = "email",
                    Type = AttributeType.STRING
                },
                ReadCapacity  = 1,
                WriteCapacity = 1,
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            //COMPUTE INFRASTRUCTURE
            //Basic Lambda
            var simpleLambdaHandler = new Function(this, "simpleLambdaHandler", new FunctionProps
            {
                Runtime      = Runtime.DOTNET_CORE_3_1,
                FunctionName = "simpleLambda",
                //Where to get the code
                Code        = Code.FromAsset("Lambdas\\src\\Lambdas\\bin\\Debug\\netcoreapp3.1"),
                Handler     = "Lambdas::Lambdas.Function::SimpleLambdaHandler",
                Environment = new Dictionary <string, string>
                {
                    ["ENVIRONMENT"] = environment,
                    ["BUCKET"]      = s3Bucket.BucketName
                }
            });

            s3Bucket.GrantReadWrite(simpleLambdaHandler);

            //S3 Lambda
            var s3LambdaHandler = new Function(this, "s3LambdaHandler", new FunctionProps
            {
                Runtime      = Runtime.DOTNET_CORE_3_1,
                Timeout      = Duration.Seconds(20),
                FunctionName = "s3Lambda",
                //Where to get the code
                Code        = Code.FromAsset("Lambdas\\src\\Lambdas\\bin\\Debug\\netcoreapp3.1"),
                Handler     = "Lambdas::Lambdas.Function::S3LambdaHandler",
                Environment = new Dictionary <string, string>
                {
                    ["ENVIRONMENT"] = environment,
                    ["BUCKET"]      = s3Bucket.BucketName,
                    ["REGION"]      = this.Region
                }
            });

            s3Bucket.GrantReadWrite(s3LambdaHandler);

            //Write DynamoDb Lambda
            var writeDynamoDBHandler = new Function(this, "writeDynamoDBHandler", new FunctionProps
            {
                Runtime      = Runtime.DOTNET_CORE_3_1,
                FunctionName = "writeDynamoDB",
                Timeout      = Duration.Seconds(20),
                //Where to get the code
                Code        = Code.FromAsset("Lambdas\\src\\Lambdas\\bin\\Debug\\netcoreapp3.1"),
                Handler     = "Lambdas::Lambdas.Function::WriteDynamoDBLambdaHandler",
                Environment = new Dictionary <string, string>
                {
                    ["ENVIRONMENT"] = environment,
                    //["BUCKET"] = s3Bucket.BucketName,
                    ["TABLE"] = dynamoDbTable.TableName
                }
            });

            dynamoDbTable.GrantFullAccess(writeDynamoDBHandler);

            //Read DynamoDb Lambda
            var readDynamoDBHandler = new Function(this, "readDynamoDBHandler", new FunctionProps
            {
                Runtime      = Runtime.DOTNET_CORE_3_1,
                FunctionName = "readDynamoDBLambda",
                Timeout      = Duration.Seconds(20),
                //Where to get the code
                Code        = Code.FromAsset("Lambdas\\src\\Lambdas\\bin\\Debug\\netcoreapp3.1"),
                Handler     = "Lambdas::Lambdas.Function::ReadDynamoDBLambdaHandler",
                Environment = new Dictionary <string, string>
                {
                    ["ENVIRONMENT"] = environment,
                    ["BUCKET"]      = s3Bucket.BucketName,
                    ["TABLE"]       = dynamoDbTable.TableName
                }
            });

            dynamoDbTable.GrantFullAccess(readDynamoDBHandler);
            s3Bucket.GrantReadWrite(readDynamoDBHandler);

            //This is the name of the API in the APIGateway
            var api = new RestApi(this, "CDKAPI", new RestApiProps
            {
                RestApiName = "cdkAPI",
                Description = "This our CDKAPI",
                Deploy      = false
            });

            var deployment = new Deployment(this, "My Deployment", new DeploymentProps {
                Api = api
            });
            var stage = new Amazon.CDK.AWS.APIGateway.Stage(this, "stage name", new Amazon.CDK.AWS.APIGateway.StageProps
            {
                Deployment = deployment,
                StageName  = environment
            });

            api.DeploymentStage = stage;

            //Lambda integrations
            var simpleLambdaIntegration = new LambdaIntegration(simpleLambdaHandler, new LambdaIntegrationOptions
            {
                RequestTemplates = new Dictionary <string, string>
                {
                    ["application/json"] = "{ \"statusCode\": \"200\" }"
                }
            });

            var s3LambdaIntegration = new LambdaIntegration(s3LambdaHandler, new LambdaIntegrationOptions
            {
                RequestTemplates = new Dictionary <string, string>
                {
                    ["application/json"] = "{ \"statusCode\": \"200\" }"
                }
            });

            var writeDynamoDbLambdaIntegration = new LambdaIntegration(writeDynamoDBHandler, new LambdaIntegrationOptions
            {
                RequestTemplates = new Dictionary <string, string>
                {
                    ["application/json"] = "{ \"statusCode\": \"200\" }"
                }
            });

            var readDynamoDbLambdaIntegration = new LambdaIntegration(readDynamoDBHandler, new LambdaIntegrationOptions
            {
                RequestTemplates = new Dictionary <string, string>
                {
                    ["application/json"] = "{ \"statusCode\": \"200\" }"
                }
            });


            //It is up to you if you want to structure your lambdas in separate APIGateway APIs (RestApi)

            //Option 1: Adding at the top level of the APIGateway API
            // api.Root.AddMethod("POST", simpleLambdaIntegration);

            //Option 2: Or break out resources under one APIGateway API as follows
            var simpleResource        = api.Root.AddResource("simple");
            var simpleMethod          = simpleResource.AddMethod("POST", simpleLambdaIntegration);
            var s3Resource            = api.Root.AddResource("s3");
            var s3Method              = s3Resource.AddMethod("POST", s3LambdaIntegration);
            var writeDynamoDBResource = api.Root.AddResource("writedynamodb");
            var writeDynamoDBMethod   = writeDynamoDBResource.AddMethod("POST", writeDynamoDbLambdaIntegration);
            var readDynamoDBResource  = api.Root.AddResource("readdynamodb");
            var readDynamoDBMethod    = readDynamoDBResource.AddMethod("POST", readDynamoDbLambdaIntegration);

            //Output results of the CDK Deployment
            new CfnOutput(this, "A Region:", new CfnOutputProps()
            {
                Value = this.Region
            });
            new CfnOutput(this, "B S3 Bucket:", new CfnOutputProps()
            {
                Value = s3Bucket.BucketName
            });
            new CfnOutput(this, "C DynamoDBTable:", new CfnOutputProps()
            {
                Value = dynamoDbTable.TableName
            });
            new CfnOutput(this, "D API Gateway API:", new CfnOutputProps()
            {
                Value = api.Url
            });
            string urlPrefix = api.Url.Remove(api.Url.Length - 1);

            new CfnOutput(this, "E Simple Lambda:", new CfnOutputProps()
            {
                Value = urlPrefix + simpleMethod.Resource.Path
            });
            new CfnOutput(this, "F S3 Lambda:", new CfnOutputProps()
            {
                Value = urlPrefix + s3Method.Resource.Path
            });
            new CfnOutput(this, "G Write DynamoDB Lambda:", new CfnOutputProps()
            {
                Value = urlPrefix + writeDynamoDBMethod.Resource.Path
            });
            new CfnOutput(this, "H Read DynamoDB Lambda:", new CfnOutputProps()
            {
                Value = urlPrefix + readDynamoDBMethod.Resource.Path
            });
        }
Beispiel #16
0
        internal Apigatewayv2JwtAuthzSampleStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            const string LambdaKey = "secure-lambda";
            // Create a lambda function that will execute the logic when the api is called.
            var function = new Function(this, LambdaKey, new FunctionProps
            {
                Runtime = Runtime.NODEJS_12_X,
                Code    = Code.FromAsset("lambdas"),
                Handler = "my-secure-lambda.handler"
            });

            // Add cors options. (if you intend to call this from a web app)
            var cors = new CorsPreflightOptions
            {
                AllowCredentials = true,
                AllowHeaders     = new string[] { "Authorization" },
                AllowMethods     = new HttpMethod[] { HttpMethod.GET, HttpMethod.OPTIONS },
                AllowOrigins     = new string[] { "http://*****:*****@"/secureresource";

            // add a route to the api, attaching the JWT authorizer and targeting the integration.
            var cr = new CfnRoute(this, $"{LambdaKey}-route", new CfnRouteProps
            {
                ApiId             = api.HttpApiId,
                RouteKey          = $"GET {apiPath}",
                AuthorizationType = "JWT",
                AuthorizerId      = jwtAuthZ.Ref,
                Target            = $"integrations/{integration.Ref}"
            });

            // finally, add permissions so the http api can invoke the lambda for the api path.
            var resource = (CfnResource)api.Node.FindChild("Resource");

            function.AddPermission($"{LambdaKey}-permission", new Permission
            {
                Principal = new Amazon.CDK.AWS.IAM.ServicePrincipal("apigateway.amazonaws.com"),
                Action    = "lambda:InvokeFunction",
                SourceArn = $"arn:aws:execute-api:{this.Region}:{this.Account}:{resource.Ref}/*/*{apiPath}"
            });
        }
        public ElasticbeanstalkBgPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id)
        {
            var blueEnv  = this.Node.TryGetContext("blue_env");
            var greenEnv = this.Node.TryGetContext("green_env");
            var appName  = this.Node.TryGetContext("app_name");

            var bucket = new Bucket(this, "BlueGreenBucket", new BucketProps
            {
                // The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
                // the new bucket, and it will remain in your account until manually deleted. By setting the policy to
                // DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty.
                RemovalPolicy = RemovalPolicy.DESTROY // NOT recommended for production code
            });

            var handler = new Function(this, "BlueGreenLambda", new FunctionProps
            {
                Runtime     = Runtime.PYTHON_3_7,
                Code        = Code.FromAsset("resources"),
                Handler     = "blue_green.lambda_handler",
                Environment = new Dictionary <string, string>
                {
                    ["BUCKET"] = bucket.BucketName
                }
            });

            bucket.GrantReadWrite(handler);

            var repo = new Repository(this, "Repository", new RepositoryProps
            {
                RepositoryName = "MyRepositoryName"
            });

            var pipeline = new Pipeline(this, "MyFirstPipeline");

            var sourceStage = pipeline.AddStage(new StageOptions
            {
                StageName = "Source"
            });

            var sourceArtifact = new Artifact_("Source");

            var sourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps
            {
                ActionName = "CodeCommit",
                Repository = repo,
                Output     = sourceArtifact
            });

            sourceStage.AddAction(sourceAction);

            var deployStage = pipeline.AddStage(new StageOptions
            {
                StageName = "Deploy"
            });

            var lambdaAction = new LambdaInvokeAction(new LambdaInvokeActionProps
            {
                ActionName     = "InvokeAction",
                Lambda         = handler,
                UserParameters = new Dictionary <string, object>
                {
                    ["blueEnvironment"]  = blueEnv,
                    ["greenEnvironment"] = greenEnv,
                    ["application"]      = appName
                },
                Inputs = new Artifact_[] { sourceArtifact }
            });

            deployStage.AddAction(lambdaAction);
        }
Beispiel #18
0
        internal LambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // The code that defines your stack goes here
            DotNetCore31HelloLambda = new Function(this, "DotNetCore31HelloLambda", new FunctionProps
            {
                FunctionName = "hello-dotnetcore31",
                Runtime      = Runtime.DOTNET_CORE_3_1,
                Code         = Code.FromAsset("../lambdas/hello-dotnetcore31/bin/Release/netcoreapp3.1/publish"),
                Handler      = "Hello::Hello.Functions::Get",
                Timeout      = Duration.Seconds(10),
                MemorySize   = 128,
                Tracing      = Tracing.ACTIVE
            });

            DotNetCore31SCHelloLambda = new Function(this, "DotNetCore31SCHelloLambda", new FunctionProps
            {
                FunctionName = "hello-dotnetcore31-sc",
                Runtime      = Runtime.DOTNET_CORE_3_1,
                Code         = Code.FromAsset("../lambdas/hello-dotnetcore31-sc/bin/Release/netcoreapp3.1/linux-x64/publish"),
                Handler      = "Hello::Hello.Functions::Get",
                Timeout      = Duration.Seconds(30),
                MemorySize   = 128,
                Tracing      = Tracing.ACTIVE
            });

            DotNetCore31RTRHelloLambda = new Function(this, "DotNetCore31RTRHelloLambda", new FunctionProps
            {
                FunctionName = "hello-dotnetcore31-rtr",
                Runtime      = Runtime.DOTNET_CORE_3_1,
                Code         = Code.FromAsset("../lambdas/hello-dotnetcore31-rtr/bin/Release/netcoreapp3.1/linux-x64/publish"),
                Handler      = "Hello::Hello.Functions::Get",
                Timeout      = Duration.Seconds(30),
                MemorySize   = 128,
                Tracing      = Tracing.ACTIVE
            });

            DotNetCore21HelloLambda = new Function(this, "DotNetCore21HelloLambda", new FunctionProps
            {
                FunctionName = "hello-dotnetcore21",
                Runtime      = Runtime.DOTNET_CORE_2_1,
                Code         = Code.FromAsset("../lambdas/hello-dotnetcore21/bin/Release/netcoreapp2.1/publish"),
                Handler      = "Hello::Hello.Functions::Get",
                Timeout      = Duration.Seconds(30),
                MemorySize   = 128,
                Tracing      = Tracing.ACTIVE
            });

            var api = new RestApi(this, "DotNetCoreHelloApi", new LambdaRestApiProps
            {
                RestApiName = "Hello"
            });

            var dotnetcore31 = api.Root.AddResource("31");

            dotnetcore31.AddMethod("GET", new LambdaIntegration(DotNetCore31HelloLambda));

            var dotnetcore31SC = api.Root.AddResource("31-sc");

            dotnetcore31SC.AddMethod("GET", new LambdaIntegration(DotNetCore31SCHelloLambda));

            var dotnetcore31RTR = api.Root.AddResource("31-rtr");

            dotnetcore31RTR.AddMethod("GET", new LambdaIntegration(DotNetCore31RTRHelloLambda));

            var dotnetcore21 = api.Root.AddResource("21");

            dotnetcore21.AddMethod("GET", new LambdaIntegration(DotNetCore21HelloLambda));
        }
        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
            });
        }
        internal PipelineStack(Construct scope, string id, Configuration configuration, IStackProps props = null) : base(scope, id, props)
        {
            var repository = Repository.FromRepositoryArn(this, "Repository", configuration.Source.RepositoryArn);

            var sourceArtifact = new Artifact_();
            var outputArtifact = new Artifact_();
            var ecrPolicy      = new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new[] { "ecr:*" },
                Resources = new[] { "*" }
            });


            // Setup CodeCommit cross account role access policies if required
            IRole codeCommitRole = null;

            if (!string.IsNullOrWhiteSpace(configuration.Source.CrossAccountRoleArn))
            {
                codeCommitRole = Role.FromRoleArn(this, "CodeCommitRole", configuration.Source.CrossAccountRoleArn, new FromRoleArnOptions
                {
                    Mutable = false // Flag to indicate CDK to not modify the role
                });
            }

            // Strict ordering is required to make sure CloudFormation template doesn't result in false difference
            var environmentVariablesToCopy = System.Environment.GetEnvironmentVariables()
                                             .Keys.Cast <string>()
                                             .Where(variable => variable.StartsWith("AWS_LAMBDA_"))
                                             .OrderBy(variable => variable);

            // Self mutation
            var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps
            {
                PipelineName          = Configuration.ProjectName,
                CloudAssemblyArtifact = outputArtifact,

                SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps
                {
                    ActionName = "CodeCommit",
                    Output     = sourceArtifact,
                    Repository = repository,
                    Branch     = configuration.Source.BranchName,
                    Role       = codeCommitRole,
                    Trigger    = CodeCommitTrigger.POLL
                }),

                // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline
                SynthAction = new SimpleSynthAction(new SimpleSynthActionProps
                {
                    SourceArtifact        = sourceArtifact,
                    CloudAssemblyArtifact = outputArtifact,
                    Subdirectory          = "LambdaRuntimeDockerfiles/dotnet5/Infrastructure",
                    InstallCommands       = new[]
                    {
                        "npm install -g aws-cdk",
                    },
                    BuildCommands            = new[] { "dotnet build" },
                    SynthCommand             = "cdk synth",
                    CopyEnvironmentVariables = environmentVariablesToCopy.ToArray()
                })
            });

            var stageEcr = GetStageEcr(this, configuration);

            // Stage
            var dockerBuild = new Project(this, "DockerBuild", new ProjectProps
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"),
                Description = $"Builds and pushes image to {stageEcr}",
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                    Privileged = true
                },
                Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                {
                    Repository  = repository,
                    BranchOrRef = configuration.Source.BranchName
                }),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable {
                          Value = stageEcr
                      } },
                    { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = configuration.EcrRepositoryName
                      } }
                }
            });

            dockerBuild.AddToRolePolicy(ecrPolicy);

            var dockerBuildStage = pipeline.AddStage("Stage-DockerBuild");

            dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
            {
                Input      = sourceArtifact,
                Project    = dockerBuild,
                ActionName = "DockerBuild"
            }));


            var smokeTests = new Project(this, "SmokeTests", new ProjectProps
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"),
                Description = "Runs smoke tests on the built image.",
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                    Privileged = true
                },
                Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                {
                    Repository  = repository,
                    BranchOrRef = configuration.Source.BranchName
                }),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                          Value = stageEcr
                      } },
                    { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = configuration.EcrRepositoryName
                      } },
                }
            });

            var smokeTestsPolicy = new PolicyStatement(new PolicyStatementProps
            {
                Effect  = Effect.ALLOW,
                Actions = new[]
                {
                    "sts:*",
                    "iam:*",
                    "ecr:*",
                    "lambda:*"
                },
                Resources = new[] { "*" }
            });

            smokeTests.AddToRolePolicy(smokeTestsPolicy);

            var smokeTestsStage = pipeline.AddStage("SmokeTests");

            smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
            {
                Input      = sourceArtifact,
                Project    = smokeTests,
                ActionName = "SmokeTests"
            }));


            // Beta
            if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Beta))
            {
                var betaDockerPush = new Project(this, "Beta-DockerPush", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"),
                    Description = $"Pushes staged image to {configuration.Ecrs.Beta}",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = configuration.Source.BranchName
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = configuration.EcrRepositoryName
                          } },
                        { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable {
                              Value = configuration.Ecrs.Beta
                          } },
                        { "AWS_LAMBDA_DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = "beta"
                          } },
                    }
                });

                betaDockerPush.AddToRolePolicy(ecrPolicy);

                var betaDockerPushStage = pipeline.AddStage("Beta-DockerPush");
                betaDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = betaDockerPush,
                    ActionName = "DockerPush"
                }));
            }


            // Prod
            if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Prod))
            {
                // Manual Approval
                var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval");
                manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps
                {
                    ActionName = "ManualApproval"
                }));


                var prodDockerPush = new Project(this, "Prod-DockerPush", new ProjectProps
                {
                    BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"),
                    Description = $"Pushes staged image to {configuration.Ecrs.Prod}",
                    Environment = new BuildEnvironment
                    {
                        BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3,
                        Privileged = true
                    },
                    Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps
                    {
                        Repository  = repository,
                        BranchOrRef = "dotnet5/cdk"
                    }),
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                    {
                        { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable {
                              Value = stageEcr
                          } },
                        { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                              Value = configuration.EcrRepositoryName
                          } },
                        { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable {
                              Value = configuration.Ecrs.Prod
                          } },
                        { "AWS_LAMBDA_DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable {
                              Value = "beta"
                          } },                                                                               // Prod images are also tagged as beta
                    }
                });

                prodDockerPush.AddToRolePolicy(ecrPolicy);

                var prodDockerPushStage = pipeline.AddStage("Prod-DockerPush");
                prodDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps
                {
                    Input      = sourceArtifact,
                    Project    = prodDockerPush,
                    ActionName = "DockerPush"
                }));
            }
        }