internal CdkPipelineStack(Construct scope, string id, CdkPipelineStackProps props = null) : base(scope, id, props)
        {
            var sourceArtifact = new Artifact_("SourceArtifact");
            var outputArtifact = new Artifact_("OutputArtifact");

            var sourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps
            {
                ActionName = "CodeCommit",
                Output     = sourceArtifact,
                Repository = props.MyRepository,
                Branch     = "main",
            });

            // Self mutation
            var pipeline = new CdkPipeline(this, "CdkPipeline", new CdkPipelineProps
            {
                PipelineName          = "CrossAccountSourcePipeline",
                CloudAssemblyArtifact = outputArtifact,

                SourceAction = sourceAction,

                // 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,
                    InstallCommands       = new[]
                    {
                        "npm install -g aws-cdk",
                    },
                    BuildCommands = new[] { "dotnet build" },
                    SynthCommand  = "cdk synth",
                }),
            });
        }
Ejemplo n.º 2
0
        public WorkshopPipelineStack(Constructs.Construct scope = null, string id = null, IStackProps props = null) : base(scope, id, props)
        {
            var repo = new Repository(this, "WorkshopRepo", new RepositoryProps {
                RepositoryName = "WorkshopRepo"
            });

            var sourceArtifact        = new Artifact_();
            var cloudAssemblyArtifact = new Artifact_();

            var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps {
                PipelineName          = "WorkshopPipeline",
                CloudAssemblyArtifact = cloudAssemblyArtifact,
                SourceAction          = new CodeCommitSourceAction(new CodeCommitSourceActionProps {
                    ActionName = "CodeCommit",
                    Output     = sourceArtifact,
                    Repository = repo
                }),
                SynthAction = SimpleSynthAction.StandardNpmSynth(new StandardNpmSynthOptions {
                    SourceArtifact        = sourceArtifact,
                    CloudAssemblyArtifact = cloudAssemblyArtifact,

                    InstallCommand = "npm install -g aws-cdk"
                                     + " && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb"
                                     + " && dpkg -i packages-microsoft-prod.deb"
                                     + " && apt-get update"
                                     + " && apt-get install -y dotnet-sdk-3.1",
                    BuildCommand = "dotnet build src"
                })
            });

            var deploy      = new WorkshopPipelineStage(this, "Deploy");
            var deployStage = pipeline.AddApplicationStage(deploy);
        }
Ejemplo n.º 3
0
        public PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var sourceArtifact        = new Artifact_();
            var cloudAssemblyArtifact = new Artifact_();

            var pipeline = new CdkPipeline(this, "CdkPipeline", new CdkPipelineProps
            {
                PipelineName  = "sandbank-api-pipeline",
                CdkCliVersion = "1.63.0",
                SourceAction  = new GitHubSourceAction(new GitHubSourceActionProps
                {
                    ActionName = "synth-cdk",
                    Owner      = "nicostouch",
                    Repo       = "sandbank",
                    Output     = sourceArtifact,
                    OauthToken = SecretValue.SecretsManager("github/oauth/token")
                }),
                SynthAction = new SimpleSynthAction(new SimpleSynthActionProps
                {
                    SynthCommand          = "cdk synth",
                    Subdirectory          = "DevOps/Infrastructure/CDK",
                    SourceArtifact        = sourceArtifact,
                    CloudAssemblyArtifact = cloudAssemblyArtifact
                }),
                CloudAssemblyArtifact = cloudAssemblyArtifact
            });
        }
Ejemplo n.º 4
0
        internal PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            Artifact_   sourceArtifact        = new Artifact_();
            Artifact_   cloudAssemblyArtifact = new Artifact_();
            CdkPipeline pipeline = new CdkPipeline(this, "LambdaApiSolutionPipeline", new CdkPipelineProps()
            {
                CloudAssemblyArtifact = cloudAssemblyArtifact,
                PipelineName          = "LambdaApiSolutionPipeline",
                SourceAction          = new GitHubSourceAction(new GitHubSourceActionProps()
                {
                    ActionName = "GitHubSource",
                    Output     = sourceArtifact,
                    OauthToken = SecretValue.SecretsManager(Constants.GitHubTokenSecretsManagerId),
                    Owner      = Constants.Owner,
                    Repo       = Constants.RepositoryName,
                    Branch     = Constants.Branch,
                    Trigger    = GitHubTrigger.POLL
                }),
                SynthAction = new SimpleSynthAction(new SimpleSynthActionProps()
                {
                    Environment = new BuildEnvironment
                    {
                        // required for .NET 5
                        // https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
                        BuildImage = LinuxBuildImage.STANDARD_5_0
                    },
                    SourceArtifact        = sourceArtifact,
                    CloudAssemblyArtifact = cloudAssemblyArtifact,
                    Subdirectory          = "LambdaApiSolution",
                    InstallCommands       = new[] { "npm install -g aws-cdk" },
                    BuildCommands         = new[] { "dotnet build src/LambdaApiSolution.sln" },
                    SynthCommand          = "cdk synth"
                })
            });
            CdkStage developmentStage = pipeline.AddApplicationStage(new SolutionStage(this, "Development"));
            CdkStage testStage        = pipeline.AddApplicationStage(new SolutionStage(this, "Test"));

            testStage.AddManualApprovalAction(new AddManualApprovalOptions()
            {
                ActionName = "PromoteToProduction"
            });
            CdkStage productionStage = pipeline.AddApplicationStage(new SolutionStage(this, "Production"));
        }
Ejemplo n.º 5
0
        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
                });
            }


            // 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 = new[]
                    {
                        "SOURCE_REPOSITORY_ARN",
                        "SOURCE_BRANCH_NAME",
                        "SOURCE_CROSS_ACCOUNT_ROLE_ARN",
                        "BASE_ECRS",
                        "STAGE_ECR",
                        "BETA_ECRS",
                        "PROD_ECRS",
                        "ECR_REPOSITORY_NAME",
                    }
                })
            });


            // Stage
            var dockerBuild = new Project(this, "DockerBuild", new ProjectProps()
            {
                BuildSpec   = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"),
                Description = $"Builds and pushes image to {configuration.Ecrs.Stage}",
                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>
                {
                    { "BASE_ECRS", new BuildEnvironmentVariable()
                      {
                          Value = configuration.Ecrs.Base
                      } },
                    { "STAGE_ECR", new BuildEnvironmentVariable {
                          Value = configuration.Ecrs.Stage
                      } },
                    { "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"
            }));


            // 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>
                {
                    { "SOURCE_ECR", new BuildEnvironmentVariable {
                          Value = configuration.Ecrs.Stage
                      } },
                    { "ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = configuration.EcrRepositoryName
                      } },
                    { "DESTINATION_ECRS", new BuildEnvironmentVariable {
                          Value = configuration.Ecrs.Beta
                      } },
                    { "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"
            }));


            // Manual Approval
            var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval");

            manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps()
            {
                ActionName = "ManualApproval"
            }));


            // Prod
            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>
                {
                    { "SOURCE_ECR", new BuildEnvironmentVariable {
                          Value = configuration.Ecrs.Stage
                      } },
                    { "ECR_REPOSITORY_NAME", new BuildEnvironmentVariable {
                          Value = configuration.EcrRepositoryName
                      } },
                    { "DESTINATION_ECRS", new BuildEnvironmentVariable {
                          Value = configuration.Ecrs.Prod
                      } },
                    { "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"
            }));
        }
Ejemplo n.º 6
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"
                }
            }));
        }
Ejemplo n.º 7
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"
                }));
            }
        }
Ejemplo n.º 8
0
        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"
                }));
            }
        }