Пример #1
0
        internal CICD(
            CdkStack stack,
            CfnParameter targetPlatform,
            LoadBalancedInstancesResult frontEndInstanceInfo,
            LoadBalancedInstancesResult restAPIInstanceInfo)
        {
            var artifactBucket = new Bucket(stack, "ArtifactBucket");
            var repo           = new Repository(stack, "ApplicationRepository", new RepositoryProps
            {
                RepositoryName = stack.StackName,
                Description    = $"Contains the code for the {stack.StackName} application."
            });
            var cfnRepo = repo.Node.DefaultChild as Amazon.CDK.AWS.CodeCommit.CfnRepository;

            cfnRepo.Code = new CfnRepository.CodeProperty
            {
                S3 = new CfnRepository.S3Property
                {
                    Bucket = SourceBucketName,
                    Key    = SourceBucketKey
                }
            };

            var build = new PipelineProject(stack, "ApplicationBuild", new PipelineProjectProps
            {
                Environment = new BuildEnvironment
                {
                    BuildImage           = LinuxBuildImage.AMAZON_LINUX_2_3,
                    EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> {
                        {
                            "TARGET_OS",
                            new BuildEnvironmentVariable {
                                Type  = BuildEnvironmentVariableType.PLAINTEXT,
                                Value = targetPlatform.Value
                            }
                        }
                    }
                }
            });
            var frontEndApplication = new ServerApplication(stack, "FrontEnd", new ServerApplicationProps
            {
                ApplicationName = $"{stack.StackName}-FrontEnd"
            });
            var frontEndDeploymentGroup = new ServerDeploymentGroup(stack, "FrontEndDeploymentGroup", new ServerDeploymentGroupProps
            {
                Application         = frontEndApplication,
                DeploymentGroupName = $"{stack.StackName.ToLower()}-frontend-deployment-group",
                //Role = new Role(stack, "DeploymentServiceRole", new RoleProps
                //{
                //    AssumedBy = new ServicePrincipal("codedeploy.amazonaws.com"),
                //    Description = "Allows Application Deployment.",
                //    ManagedPolicies = new[] { ManagedPolicy.FromAwsManagedPolicyName("service-role/AWSCodeDeployRole") }
                //}),
                //AutoRollback = new AutoRollbackConfig { FailedDeployment = true },
                //DeploymentConfig = ServerDeploymentConfig.HALF_AT_A_TIME,
                LoadBalancer      = LoadBalancer.Application(frontEndInstanceInfo.TargetGroup),
                AutoScalingGroups = new[] { frontEndInstanceInfo.AutoScalingGroup }
            });
            var restApiApplication = new ServerApplication(stack, "RestAPI", new ServerApplicationProps
            {
                ApplicationName = $"{stack.StackName}-RESTAPI"
            });
            var restApiDeploymentGroup = new ServerDeploymentGroup(stack, "RestAPIDeploymentGroup", new ServerDeploymentGroupProps
            {
                Application         = restApiApplication,
                DeploymentGroupName = $"{stack.StackName.ToLower()}-restapi-deployment-group",
                //AutoRollback = new AutoRollbackConfig { FailedDeployment = true },
                //DeploymentConfig = ServerDeploymentConfig.HALF_AT_A_TIME,
                LoadBalancer      = LoadBalancer.Application(restAPIInstanceInfo.TargetGroup),
                AutoScalingGroups = new[] { restAPIInstanceInfo.AutoScalingGroup }
            });
            var sourceOutput      = new Artifact_();
            var frontEndArtifacts = new Artifact_("FrontEndOutput");
            var restAPIArtifacts  = new Artifact_("RESTAPIOutput");
            var pipeline          = new Pipeline(stack, "ApplicationPipeline", new PipelineProps
            {
                ArtifactBucket = artifactBucket,
                PipelineName   = $"{stack.StackName}-Pipeline",
                Stages         = new[]
                {
                    new Amazon.CDK.AWS.CodePipeline.StageProps
                    {
                        StageName = "Source",
                        Actions   = new []
                        {
                            new CodeCommitSourceAction(new CodeCommitSourceActionProps
                            {
                                ActionName = "Source",
                                Repository = repo,
                                Output     = sourceOutput
                            })
                        }
                    },
                    new Amazon.CDK.AWS.CodePipeline.StageProps
                    {
                        StageName = "Build",
                        Actions   = new []
                        {
                            new CodeBuildAction(new CodeBuildActionProps
                            {
                                ActionName = "CodeBuild",
                                Project    = build,
                                Input      = sourceOutput,
                                Outputs    = new [] { frontEndArtifacts, restAPIArtifacts }
                            })
                        }
                    },
                    new Amazon.CDK.AWS.CodePipeline.StageProps
                    {
                        StageName = "Deploy",
                        Actions   = new []
                        {
                            new CodeDeployServerDeployAction(new CodeDeployServerDeployActionProps {
                                ActionName      = "DeployFrontEnd",
                                DeploymentGroup = frontEndDeploymentGroup,
                                Input           = frontEndArtifacts
                            }),
                            new CodeDeployServerDeployAction(new CodeDeployServerDeployActionProps {
                                ActionName      = "DeployRESTAPI",
                                DeploymentGroup = restApiDeploymentGroup,
                                Input           = restAPIArtifacts
                            })
                        }
                    }
                }
            });
        }
        internal AppdeploymentStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            #region Application hosting resources

            var vpc = new Vpc(this, "appVpc", new VpcProps
            {
                MaxAzs = 3
            });

            var image = new LookupMachineImage(new LookupMachineImageProps
            {
                // maps to "Amazon Linux 2 with .NET Core 3.0 and Mono 5.18"
                Name   = "amzn2-ami-hvm-2.0.*-x86_64-gp2-mono-*",
                Owners = new [] { "amazon" }
            });

            var userData = UserData.ForLinux();
            userData.AddCommands(new string[]
            {
                "sudo yum install -y httpd",
                "sudo systemctl start httpd",
                "sudo systemctl enable httpd"
            });

            var scalingGroup = new AutoScalingGroup(this, "appASG", new AutoScalingGroupProps
            {
                Vpc              = vpc,
                InstanceType     = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MEDIUM),
                MachineImage     = image,
                MinCapacity      = 1,
                MaxCapacity      = 4,
                AllowAllOutbound = true,
                UserData         = userData
            });

            var alb = new ApplicationLoadBalancer(this, "appLB", new ApplicationLoadBalancerProps
            {
                Vpc            = vpc,
                InternetFacing = true
            });

            var albListener = alb.AddListener("Port80Listener", new BaseApplicationListenerProps
            {
                Port = 80
            });

            albListener.AddTargets("Port80ListenerTargets", new AddApplicationTargetsProps
            {
                Port    = 80,
                Targets = new [] { scalingGroup }
            });

            albListener.Connections.AllowDefaultPortFromAnyIpv4("Open access to port 80");

            scalingGroup.ScaleOnRequestCount("ScaleOnModestLoad", new RequestCountScalingProps
            {
                TargetRequestsPerSecond = 1
            });

            #endregion

            #region CI/CD resources

            var _sourceOutput = new Artifact_("Source");
            var _buildOutput  = new Artifact_("Build");

            var build = new PipelineProject(this, "CodeBuild", new PipelineProjectProps
            {
                // relative path to sample app's file (single html page for now)
                BuildSpec   = BuildSpec.FromSourceFilename("talk-demos/appdeployment/SimplePage/buildspec.yml"),
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_2
                },
            });

            var appDeployment = new ServerApplication(this, "appDeployment");
            // we will use CodeDeploy's default one-at-a-time deployment mode as we are
            // not specifying a deployment config
            var deploymentGroup = new ServerDeploymentGroup(this, "appDeploymentGroup", new ServerDeploymentGroupProps
            {
                Application  = appDeployment,
                InstallAgent = true,
                AutoRollback = new AutoRollbackConfig
                {
                    FailedDeployment = true
                },
                AutoScalingGroups = new [] { scalingGroup }
            });

            // SecretValue.SsmSecure is not currently supported for setting OauthToken,
            // and haven't gotten the SecretsManager approach to work either so
            // resorting to keeping my token in an environment var for now!
            var oauthToken = SecretValue.PlainText(System.Environment.GetEnvironmentVariable("GitHubPersonalToken"));

            var pipeline = new Pipeline(this, "sampleappPipeline", new PipelineProps
            {
                Stages = new StageProps[]
                {
                    new StageProps
                    {
                        StageName = "Source",
                        Actions   = new IAction[]
                        {
                            new GitHubSourceAction(new GitHubSourceActionProps
                            {
                                ActionName = "GitHubSource",
                                Branch     = "master",
                                Repo       = this.Node.TryGetContext("repo-name").ToString(),
                                Owner      = this.Node.TryGetContext("repo-owner").ToString(),
                                OauthToken = oauthToken,
                                Output     = _sourceOutput
                            })
                        }
                    },

                    new StageProps
                    {
                        StageName = "Build",
                        Actions   = new IAction[]
                        {
                            new CodeBuildAction(new CodeBuildActionProps
                            {
                                ActionName = "Build-app",
                                Project    = build,
                                Input      = _sourceOutput,
                                Outputs    = new Artifact_[] { _buildOutput },
                                RunOrder   = 1
                            })
                        }
                    },

                    new StageProps
                    {
                        StageName = "Deploy",
                        Actions   = new IAction[]
                        {
                            new CodeDeployServerDeployAction(new CodeDeployServerDeployActionProps
                            {
                                ActionName      = "Deploy-app",
                                Input           = _buildOutput,
                                RunOrder        = 2,
                                DeploymentGroup = deploymentGroup
                            })
                        }
                    }
                }
            });

            #endregion
        }