├── .DS_Store ├── .github └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Detail_Instructions.md ├── LICENSE ├── Prerequisites.md ├── README.md ├── WebApp-bkup.zip ├── WebApp.zip ├── WebApp ├── README.md ├── app.js ├── appspec.yml ├── buildspec.yml ├── package.json ├── public │ ├── css │ │ ├── gradients.css │ │ └── styles.css │ ├── img │ │ └── tweet.svg │ ├── index.html │ └── js │ │ └── set-background.js ├── scripts │ ├── beforeInstall.sh │ ├── start_server.sh │ └── stop_server.sh ├── template.yml └── tests │ └── test.js ├── config └── images ├── bg-1.png ├── bg-10.png ├── bg-11.png ├── bg-2.png ├── bg-3.png ├── bg-4.png ├── bg-5.png ├── bg-6.png ├── bg-7.png ├── bg-9.png ├── codecommit-iam-gc1.png ├── codestar1.png ├── codestar2.png ├── codestar3.png ├── codestar4.png └── codestar5.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/.DS_Store -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-samples/aws-cicd-bluegreen/issues), or [recently closed](https://github.com/aws-samples/aws-cicd-bluegreen/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-cicd-bluegreen/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws-samples/aws-cicd-bluegreen/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /Detail_Instructions.md: -------------------------------------------------------------------------------- 1 | # Step by Step Instructions 2 | 3 | ## Create Cloud9 environment 4 | 5 | > AWS Cloud9 is a cloud-based integrated development environment (IDE) that lets you write, run, and debug your code with just a browser. It includes a code editor, debugger, and terminal. Cloud9 comes prepackaged with essential tools for popular programming languages, including JavaScript, Python, PHP, and more, so you don’t need to install files or configure your development machine to start new projects. Since your Cloud9 IDE is cloud-based, you can work on your projects from your office, home, or anywhere using an internet-connected machine. Cloud9 also provides a seamless experience for developing serverless applications enabling you to easily define resources, debug, and switch between local and remote execution of serverless applications. With Cloud9, you can quickly share your development environment with your team, enabling you to pair program and track each other's inputs in real time. 6 | 7 | Note: 8 | 1. For this lab you will need to use an IAM user and not a federated user account or root account. See the [Prerequisites](./Prerequisites.md) 9 | 2. Only us-east-1(N.VA), us-east-2(Ohio), us-west-2(Oregon) and eu-west-1(Irland) are supported. 10 | 11 | 1. Go to the AWS Management Console, click **Services** then select **Cloud9** under Developer Tools. 12 | 2. Click **Create environment**. 13 | 3. Enter **_BlueGreenEnvironment_** into **Name** and optionally provide a **Description**. 14 | 4. Click **Next step**. 15 | 5. You may leave **Environment settings** at their defaults of launching a new **t2.micro** EC2 instance which will be paused after **30 minutes** of inactivity. 16 | 6. Click **Next step**. 17 | 7. Review the environment settings and click **Create environment**. It will take several minutes for your environment to be provisioned and prepared. 18 | 8. Once ready, your IDE will open to a welcome screen. Below that, you should see a terminal prompt. You can run AWS CLI commands in here just like you would on your local computer. Verify that your user is logged in by running this command. 19 | 20 | ```console 21 | user:~/environment $ aws sts get-caller-identity 22 | ``` 23 | 24 | ![Cloud9](./images/bg-1.png) 25 | 26 | We will be using Cloud9 IDE for our development. 27 | 28 | ## Create Code Commit Credentials 29 | 30 | 1. Go to IAM Console and click **User** on the left menu. Click the Username of the IAM user which you are currently logging on with. 31 | 2. On the user details page in IAM console, choose the **Security Credentials** tab, and in **HTTPS Git credentials for AWS CodeCommit**, choose **Generate**. 32 | 33 | ![HTTPS Git Credential](./images/codecommit-iam-gc1.png) 34 | 35 | Note: Make Note of the Git HTTP credentials handy. It will be used for cloning and pushing changes to Repo. Also, You can find detail instruction on how to configure HTTPS Git Credential [here](https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-gc.html) 36 | 37 | ## Create an AWS CodeCommit Repository 38 | 39 | 1. Open the AWS CodeCommit console at . 40 | 2. In the region selector, choose the region where you will create the repository. For more information, see [Regions and Git Connection Endpoints](http://docs.aws.amazon.com/codecommit/latest/userguide/regions.html). 41 | 3. On the Welcome page, choose Get Started Now. (If a **_Dashboard_** page appears instead, choose **_Create repository_**.) 42 | 4. On the **Create repository** page, in the **Repository name** box, type **_BlueGreenWebApp_**. 43 | 5. In the **Description** box, type **_BlueGreenWebApp repository_**. 44 | 6. Click **Create repository** to create an empty AWS CodeCommit repository. 45 | 7. On the **Connection Steps** screen, review Connection steps. We completed step 2 from the previous section. Select the **Clone URL** drop-down list to copy the Clone HTTPS command. 46 | 8. Go to your Cloud9 IDE. In the terminal prompt paste clone command you previouly copied. Enter Username and Password of your Git Credential. (You will not see the password when you pasted it. Do not worry! Hit Enter.) 47 | 48 | ![Cloned Repo](./images/bg-2.png) 49 | 50 | 9. Configure Git user in Cloud9 environment. 51 | 52 | ```console 53 | user:~/environment $ git config --global user.email you@example.com 54 | user:~/environment $ git config --global user.name "Your Name" 55 | user:~/environment $ cd BlueGreenWebApp 56 | user:~/environment $ git config credential.helper store 57 | ``` 58 | 59 | 10. Inside BlueGreenWebApp folder, download the Sample Web App Archive by running the following command from IDE terminal and unzip the archvie. 60 | 61 | ```console 62 | user:~/environment $ wget https://github.com/aws-samples/aws-cicd-bluegreen/raw/master/WebApp.zip 63 | user:~/environment $ unzip WebApp.zip 64 | user:~/environment $ mv WebApp/* . 65 | user:~/environment $ rm -rf WebApp 66 | user:~/environment $ rm WebApp.zip 67 | ``` 68 | 69 | Your IDE environment should look like this. 70 | 71 | ![Project](./images/bg-3.png) 72 | 73 | 11. Stage your change by running **_git add_**. You can use **_git status_** to review the changes. 74 | 75 | ```console 76 | user:~/environment/BlueGreenEnvironment/ $ git add . 77 | user:~/environment/BlueGreenEnvironment/ $ git status 78 | ``` 79 | 80 | 12. Commit your change by running **_git commit_** to commit the change to the local repository then run **_git push_** to push your commit the default remote name Git uses for your AWS CodeCommit repository (origin). Enter your git credential. 81 | 82 | ```console 83 | user:~/environment/BlueGreenEnvironment/ $ git commit -m "Initial Commit" 84 | user:~/environment/BlueGreenEnvironment/ $ git push 85 | ``` 86 | 87 | ![Project](./images/bg-4.png) 88 | 89 | **_💡 Tip_** After you have pushed files to your AWS CodeCommit repository, you can use the AWS CodeCommit console to view the contents. For more information, see [Browse the Contents of a Repository](http://docs.aws.amazon.com/codecommit/latest/userguide/how-to-browse.html). 90 | 91 | ## Create Infrastructure 92 | 93 | In this step, we will be using CloudFormation template to create infrstructure used for this lab. Review template.yml. 94 | 95 | 1. In Cloud9, create CloudFormation stack by running this command. If the command execute with no issues, you should see the StackId return back. 96 | 97 | ```console 98 | user:~/environment/BlueGreenEnvironment/BlueGreenWebApp $ aws cloudformation create-stack --stack-name BlueGreenEnvironment --template-body file://template.yml --capabilities CAPABILITY_IAM 99 | ``` 100 | 101 | 2. Go to AWS CloudFormation console to view its progress. Once complete, go to Outputs Tab and observe the Cloudformation output value. Browse the URL of your ALB, in your favorite browser. 102 | 103 | ![ALB](./images/bg-11.png) 104 | 105 | ## Configure CodeBuild 106 | 107 | > AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces software packages that are ready to deploy. With CodeBuild, you don’t need to provision, manage, and scale your own build servers. CodeBuild scales continuously and processes multiple builds concurrently, so your builds are not left waiting in a queue. You can get started quickly by using prepackaged build environments, or you can create custom build environments that use your own build tools. With CodeBuild, you are charged by the minute for the compute resources you use. 108 | 109 | 1. Go to CodeBuild Console and click Create build project. Enter your build project information. 110 | 111 | **_Project configuration_** 112 | 113 | * **Project Name:** BlueGreenWebAppBuild 114 | * **Description:** NodeJS WebApp build 115 | 116 | **_Source_** 117 | 118 | * **Source provider:** AWS CodeCommit 119 | * **Repository:** BlueGreenWebApp _Note:_ this is your source reporsitory that you have created earlier. 120 | 121 | **_Environment_** 122 | 123 | In this step, we configure the build environment. 124 | 125 | * **Environment image:** Managed image 126 | * **Operating system:** Ubuntu 127 | * **Runtime(s):** Standard 128 | * **Image:** aws/codebuild/standard:2.0 129 | * **Image version:** Always use the latest image for this runtime version 130 | * **Environment type:** Linux 131 | * **Service role:** New service role 132 | * **Role name:** codebuild-BlueGreenWebAppBuild-service-role (Automatically filled) 133 | 134 | **_Buildspec_** 135 | 136 | * **Build specifications:** Use a buildspec file 137 | * **Buildspec name:** empty _Note:_ We will be using buildspec.yml which is in the project. Because we are using default name, we can leave this field empty. 138 | 139 | **_Artifacts_** 140 | 141 | * **Type:** Amazon S3 Note: We will store build output in S3 bucket. 142 | * **Bucket Name:** build-artifact-bluegreenbucket-us-east-1-xxxxxxxxxxx Note: This bucket was created with CloudFormation template and can be copied fro the Outputs section of the stack. 143 | * **Name:** BlueGreenWebAppBuild.zip 144 | * **Artifacts packaging:** Zip 145 | 146 | Click **Create build project** 147 | 148 | 2. In your Build Project, click **Start build**. Leave everything with defualt value, click **Start build** 149 | 3. Observe the build process and logs. When completed, click **View artifacts** link in the Build status section which should take you to the build output zip file in your build artifact S3 bucket. 150 | 4. Congratulations! You succesfully made your first build. 151 | 152 | ## Configure CodeDeploy 153 | 154 | > AWS CodeDeploy is a fully managed deployment service that automates software deployments to a variety of compute services such as Amazon EC2, AWS Lambda, and your on-premises servers. AWS CodeDeploy makes it easier for you to rapidly release new features, helps you avoid downtime during application deployment, and handles the complexity of updating your applications. You can use AWS CodeDeploy to automate software deployments, eliminating the need for error-prone manual operations. The service scales to match your deployment needs, from a single Lambda function to thousands of EC2 instances. 155 | 156 | 1. Go to CodeDeploy Console, click **Create application**. Enter Application configuration and click **Create application** 157 | 158 | * **Application name:** BlueGreenWebApp 159 | * **Compute platform:** EC2/On-premises 160 | 161 | 2. In your CodeDeploy Application, BlueGreenWebApp, on Deployment groups tab, click **Create Deployment group**. Configure the deployment as follow: 162 | 163 | **_Deployment group name_** 164 | 165 | * **Enter a deployment group name:** BlueGreenWebApp_DeploymentGroup 166 | * **Service role:** BlueGreenEnvironment-DeployTrustRole-xxxxxxxx Note: This role was created as a part of CloudFormation. 167 | 168 | **_Deployment type_** 169 | 170 | * **Choose how to deploy your application:** Blue/green 171 | 172 | **_Environment configuration_** 173 | 174 | * **Specify the Amazon EC2 Auto Scaling groups or Amazon EC2 instances where the current application revision is deployed:** Automatically copy Amazon EC2 Auto Scaling group 175 | * **Choose the Amazon EC2 Auto Scaling group where the current application revision is deployed:** BlueGreenASGroup _Note:_ This AS was created as a part of CloudFormation. 176 | 177 | **_Deployment settings_** 178 | 179 | * **Choose whether traffic reroutes to the replacement environment immediately or waits for you to start the rerouting process manually:** Reroute traffic immediately 180 | * **Choose whether instances in the original environment are terminated after the deployment is succeeds, and how long to wait before termination:** Terminate the original instances in the deployment group: 5 Minutes 181 | * **Deployment configuration:** CodeDeployDefault.AllAtOnce 182 | 183 | **_Load balancer_** 184 | 185 | * **Application Load Balancer or Network Load Balancer** 186 | * **Choose a load balancer:** BlueGreenTG _Note:_ This role was created as a part of CloudFormation. 187 | 188 | Click **Create deployment group** 189 | 190 | 3. Under the deployment group, click **Create deployment**. Configure the deployment as followed: 191 | 192 | **_Deployment settings_** 193 | 194 | * **Deployment group:** BlueGreenWebApp_DeploymentGroup 195 | * **Revision type:** My application is stored in Amazon S3 196 | * **Revision location:** s3://build-artifact-bluegreenbucket-us-east-1-XXXXXXXXXXXX/BlueGreenWebAppBuild.zip Note: This is the location of the build artifact from your CodeBuild project. 197 | * **Revision file type:** .zip 198 | 199 | Leave everything as the default value. 200 | 201 | Click **Create deployment** 202 | 203 | 4. Under the deployment, observe Deployment status. 204 | 205 | ![ALB](./images/bg-7.png) 206 | 207 | ## Create CICD with CodePipeline 208 | 209 | > AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates. CodePipeline automates the build, test, and deploy phases of your release process every time there is a code change, based on the release model you define. This enables you to rapidly and reliably deliver features and updates. You can easily integrate AWS CodePipeline with third-party services such as GitHub or with your own custom plugin. With AWS CodePipeline, you only pay for what you use. There are no upfront fees or long-term commitments. 210 | 211 | You are going to configure a CodePipleline to use CodeBuild and CodeDeploy previously created. 212 | 213 | 1. Go to CodePipeline Console and click **Create Pipeline**. Configure your Pipeline as followed: 214 | 215 | * **Pipeline name:** BlueGreenWebApp_Pipeline 216 | * **Service role:** New service role 217 | * **Role name:** AWSCodePipelineServiceRole-us-east-1-BlueGreenWebApp_Pipeline (Automatically filled) 218 | Enable **Allow AWS CodePipeline to create a service role so it can be used with this new pipeline** 219 | * **Artifact Store:** Default location 220 | 221 | **_Source_** 222 | 223 | * **Source provider:** AWS CodeCommit 224 | 225 | **_AWS CodeCommit_** 226 | 227 | * **Choose a repository:** BlueGreenWebApp 228 | * **Branch name:** master 229 | * **Change detection options:** Amazon CloudWatch Events(recommended) 230 | 231 | **_Build_** 232 | 233 | * **Build provider:** AWS CodeBuild 234 | 235 | **_AWS CodeBuild_** 236 | 237 | * **Project name:** BlueGreenWebAppBuild 238 | 239 | **_Deploy_** 240 | 241 | * **Deploy provider:** AWS CodeDeploy 242 | 243 | **_AWS CodeDeploy_** 244 | 245 | * **Application name:** BlueGreenWebApp 246 | * **Deployment group:** BlueGreenWebApp_DeploymentGroup 247 | 248 | Click **Next** and **Create pipeline**. 249 | 250 | 2. Observe your existing commit going through CodePipeline. 251 | 252 | ## Deploy your new code 253 | 254 | 1. Go back to your Cloud9 IDE. 255 | 2. Navigate to BlueGreenWebApp and public folder. Open index.html. 256 | 3. Make a change to the file and save. 257 | 258 | ```html 259 |
260 | 261 |
262 |

Congratulations!

263 |

You just created a Node.js web application V2 from re:invent!

264 |
265 |
266 | ``` 267 | 268 | 4. Commit the change and push to the remote repository. 269 | 270 | ```console 271 | user:~/environment/BlueGreenEnvironment/ $ git add . 272 | user:~/environment/BlueGreenEnvironment/ $ git commit -m "Changes from re:invent" 273 | user:~/environment/BlueGreenEnvironment/ $ git push 274 | ``` 275 | 276 | 5. Go back to CodePipeline Console and observe the progress. 277 | 6. Once completed, browse to your ALB endpoint. 278 | 279 | **Congratulations! You have completed the lab.** 280 | 281 | ## Clean up Instruction 282 | 283 | 1. Go to EC2 Console and navigate to Auto Scaling Groups. Select CodeDeploy_BlueGreenWebApp_DeploymentGroup-XXXXXXXXXXXX, click Actions and select Delete. (There may be more than one Auto Scaling Group with the naming convention CodeDeploy_BlueGreenWebApp_DeploymentGroup-XXXXXXXXXXXX, Delete all that exist with this naming convention) 284 | 2. Go to S3 Console and empty bucket build-artifact-bluegreenbucket-us-east-1-XXXXXXXXXXXX and empty and delete bucket codepipeline-region-XXXXXXXXXXX. 285 | 3. Go to CloudFormation console, select the stack name BlueGreenEnvironment or the stackname that you created. Click Actions and select Delete Stack. 286 | 4. Go to CodeCommit, CodeBuild, CodeDeploy and CodePipeline console. Delete the resource that you have created. 287 | 5. Go to IAM Console and delete CodeDeploy role, CodePipeline roles and CodePipeline Policies. Search for BlueGreenWebApp. 288 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /Prerequisites.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | 3 | 1. AWS account with an IAM user. For simplicity, this user need to have full access to your account. 4 | 2. The following regions are supported in this lab, us-east-1(N.VA), us-east-2(Ohio), us-west-2(Oregon) and eu-west-1(Irland). 5 | 3. You must be able to create a new VPC in your account in the region you selected. 6 | 4. You must be able to create 5 new instances in your account. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CICD with CodePipeline and Blue Green Deployment 2 | 3 | Blue-Green is a deployment technique that keep 2 production environments running but only one of the environment is live and one is idle. As you prepare a new version of your software, the current production (Blue) is serving all production traffic. You also have another environment running the new software. Once it has been fully tested (Green), you switch the traffic to route to the Green environment instead of Blue. Now Green is live and Blue is idle. 4 | 5 | This technique can reduce the downtime and risks. If there is unexpected issues with Green then you can switch the traffic back to Blue. 6 | 7 | ## License Summary 8 | 9 | This sample code is made available under a modified MIT license. See the LICENSE file. 10 | 11 | ## What we will be doing in this lab 12 | 13 | We will be create a Cloud9 environment to do development. We will use CloudFormation to build our infrastructructure consisting of VPC, public and private subnets, Application Load Balancer and AutoScaling Group. We will use CodePipeline for CICD which utilize CodeCommit, CodeBuild and CodeDeploy. In CodeDeploy we will configure Blue/Green Deployment. 14 | 15 | ![ALB](./images/bg-10.png) 16 | 17 | ## Overall steps 18 | 19 | 1. Create Cloud9 environment. 20 | 2. Create a repository for your code and commit you first code. 21 | 3. Create infrastructure (ALB, ASG, EC2 and S3). 22 | 4. Create Build project with CodeBuild and store build artifact in S3. 23 | 5. Create Application and Deployment group to deploy the artifact to AutoScaling Group with Blue Green deployment. 24 | 6. Create CICD with CodePipeline. 25 | 26 | Follow the Detail Instruction [here](Detail_Instructions.md). -------------------------------------------------------------------------------- /WebApp-bkup.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/WebApp-bkup.zip -------------------------------------------------------------------------------- /WebApp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/WebApp.zip -------------------------------------------------------------------------------- /WebApp/README.md: -------------------------------------------------------------------------------- 1 | Welcome to the AWS CodeStar sample web application 2 | ================================================== 3 | 4 | This sample code helps get you started with a simple Node.js web application 5 | deployed by AWS CodeDeploy and AWS CloudFormation to an Amazon EC2 instance. 6 | 7 | What's Here 8 | ----------- 9 | 10 | This sample includes: 11 | 12 | * README.md - this file 13 | * app.js - this file contains the code for your application 14 | * appspec.yml - this file is used by AWS CodeDeploy when deploying the web 15 | application to EC2 16 | * buildspec.yml - this file is a collection of build commands and related settings that 17 | AWS CodeBuild uses to run a build 18 | * package.json - this file contains various metadata relevant to your Node.js 19 | application such as dependencies 20 | * public/ - this directory contains static web assets used by your application 21 | * scripts/ - this directory contains scripts used by AWS CodeDeploy when 22 | installing and deploying your application on the Amazon EC2 instance 23 | * tests/ - this directory contains unit tests for your application 24 | * template.yml - this file contains the description of AWS resources used by AWS 25 | CloudFormation to deploy your infrastructure 26 | 27 | 28 | Getting Started 29 | --------------- 30 | 31 | These directions assume you want to develop on your local computer, and not 32 | from the Amazon EC2 instance itself. If you're on the Amazon EC2 instance, the 33 | virtual environment is already set up for you, and you can start working on the 34 | code. 35 | 36 | To work on the sample code, you'll need to clone your project's repository to your 37 | local computer. If you haven't, do that first. You can find instructions in the 38 | AWS CodeStar user guide. 39 | 40 | 1. Install Node.js on your computer. For details on available installers visit 41 | https://nodejs.org/en/download/. 42 | 43 | 2. Install NPM dependencies: 44 | 45 | $ npm install 46 | 47 | 2. Start the development server: 48 | 49 | $ node app.js 50 | 51 | 3. Open http://127.0.0.1:3000/ in a web browser to view your application. 52 | 53 | What Do I Do Next? 54 | ------------------ 55 | 56 | Once you have a virtual environment running, you can start making changes to 57 | the sample Node.js web application. We suggest making a small change to 58 | /public/index.html first, so you can see how changes pushed to your project's 59 | repository are automatically picked up by your project pipeline and deployed to 60 | the Amazon EC2 instance. (You can watch the progress on your project dashboard.) 61 | Once you've seen how that works, start developing your own code, and have fun! 62 | 63 | To run your tests locally, go to the root directory of the 64 | sample code and run the `npm test` command, which 65 | AWS CodeBuild also runs through your `buildspec.yml` file. 66 | 67 | To test your new code during the release process, modify the existing tests or 68 | add tests to the tests directory. AWS CodeBuild will run the tests during the 69 | build stage of your project pipeline. You can find the test results 70 | in the AWS CodeBuild console. 71 | 72 | Learn more about AWS CodeBuild and how it builds and tests your application here: 73 | https://docs.aws.amazon.com/codebuild/latest/userguide/concepts.html 74 | 75 | Learn more about AWS CodeStar by reading the user guide. Ask questions or make 76 | suggestions on our forum. 77 | 78 | User Guide: http://docs.aws.amazon.com/codestar/latest/userguide/welcome.html 79 | 80 | Forum: https://forums.aws.amazon.com/forum.jspa?forumID=248 81 | 82 | How Do I Add Template Resources to My Project? 83 | ------------------ 84 | 85 | To add AWS resources to your project, you'll need to edit the `template.yml` 86 | file in your project's repository. You may also need to modify permissions for 87 | your project's worker roles. After you push the template change, AWS CodeStar 88 | and AWS CloudFormation provision the resources for you. 89 | 90 | See the AWS CodeStar user guide for instructions to modify your template: 91 | https://docs.aws.amazon.com/codestar/latest/userguide/how-to-change-project#customize-project-template.html 92 | 93 | What Should I Do Before Running My Project in Production? 94 | ------------------ 95 | 96 | AWS recommends you review the security best practices recommended by the framework 97 | author of your selected sample application before running it in production. You 98 | should also regularly review and apply any available patches or associated security 99 | advisories for dependencies used within your application. 100 | 101 | Best Practices: https://docs.aws.amazon.com/codestar/latest/userguide/best-practices.html?icmpid=docs_acs_rm_sec 102 | -------------------------------------------------------------------------------- /WebApp/app.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: MIT-0 3 | 4 | var port = process.env.PORT || 3000, 5 | http = require('http'), 6 | fs = require('fs'); 7 | 8 | var app = http.createServer(function (req, res) { 9 | if (req.url.indexOf('/img') != -1) { 10 | var filePath = req.url.split('/img')[1]; 11 | fs.readFile(__dirname + '/public/img' + filePath, function (err, data) { 12 | if (err) { 13 | res.writeHead(404, {'Content-Type': 'text/plain'}); 14 | res.write('Error 404: Resource not found.'); 15 | console.log(err); 16 | } else { 17 | res.writeHead(200, {'Content-Type': 'image/svg+xml'}); 18 | res.write(data); 19 | } 20 | res.end(); 21 | }); 22 | } else if (req.url.indexOf('/js') != -1) { 23 | var filePath = req.url.split('/js')[1]; 24 | fs.readFile(__dirname + '/public/js' + filePath, function (err, data) { 25 | if (err) { 26 | res.writeHead(404, {'Content-Type': 'text/plain'}); 27 | res.write('Error 404: Resource not found.'); 28 | console.log(err); 29 | } else { 30 | res.writeHead(200, {'Content-Type': 'text/javascript'}); 31 | res.write(data); 32 | } 33 | res.end(); 34 | }); 35 | } else if(req.url.indexOf('/css') != -1) { 36 | var filePath = req.url.split('/css')[1]; 37 | fs.readFile(__dirname + '/public/css' + filePath, function (err, data) { 38 | if (err) { 39 | res.writeHead(404, {'Content-Type': 'text/plain'}); 40 | res.write('Error 404: Resource not found.'); 41 | console.log(err); 42 | } else { 43 | res.writeHead(200, {'Content-Type': 'text/css'}); 44 | res.write(data); 45 | } 46 | res.end(); 47 | }); 48 | } else { 49 | fs.readFile(__dirname + '/public/index.html', function (err, data) { 50 | if (err) { 51 | res.writeHead(404, {'Content-Type': 'text/plain'}); 52 | res.write('Error 404: Resource not found.'); 53 | console.log(err); 54 | } else { 55 | res.writeHead(200, {'Content-Type': 'text/html'}); 56 | res.write(data); 57 | } 58 | res.end(); 59 | }); 60 | } 61 | }).listen(port, '0.0.0.0'); 62 | 63 | module.exports = app; 64 | -------------------------------------------------------------------------------- /WebApp/appspec.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | version: 0.0 4 | os: linux 5 | files: 6 | - source: /app.js 7 | destination: /home/ec2-user/node-website 8 | - source: /package.json 9 | destination: /home/ec2-user/node-website 10 | - source: /public/ 11 | destination: /home/ec2-user/node-website/public 12 | hooks: 13 | BeforeInstall: 14 | - location: scripts/stop_server.sh 15 | timeout: 180 16 | - location: scripts/beforeInstall.sh 17 | timeout: 180 18 | AfterInstall: 19 | - location: scripts/start_server.sh 20 | timeout: 180 -------------------------------------------------------------------------------- /WebApp/buildspec.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | version: 0.2 4 | 5 | phases: 6 | install: 7 | runtime-versions: 8 | nodejs: 10 9 | commands: 10 | # Install dependencies needed for running tests 11 | - npm install 12 | 13 | # Upgrade AWS CLI to the latest version 14 | - pip install --upgrade awscli 15 | pre_build: 16 | commands: 17 | # Discover and run unit tests in the 'tests' directory 18 | - npm test 19 | post_build: 20 | commands: 21 | # Remove existing node_modules to clear dev dependencies 22 | - rm -r node_modules 23 | 24 | # Install runtime dependencies 25 | - npm install --production 26 | artifacts: 27 | type: zip 28 | files: 29 | - template.yml 30 | - README.md 31 | - package.json 32 | - app.js 33 | - appspec.yml 34 | - scripts/* 35 | - node_modules/**/* 36 | - public/**/* 37 | -------------------------------------------------------------------------------- /WebApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node-Website-EC2-Sample-App", 3 | "description": "Sample NodeJs web application", 4 | "version": "0.0.1", 5 | "private": true, 6 | "devDependencies": { 7 | "mocha": "5.0.0", 8 | "unit.js": "2.0.0", 9 | "supertest": "3.0.0" 10 | }, 11 | "scripts": { 12 | "test": "mocha --recursive tests --exit" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WebApp/public/css/gradients.css: -------------------------------------------------------------------------------- 1 | /* Gradients */ 2 | .heaven-0 { background: #00000c; } 3 | .heaven-1 { background: linear-gradient(to bottom, #020111 85%, #191621 100%); } 4 | .heaven-2 { background: linear-gradient(to bottom, #020111 60%, #20202c 100%); } 5 | .heaven-3 { background: linear-gradient(to bottom, #020111 10%, #3a3a52 100%); } 6 | .heaven-4 { background: linear-gradient(to bottom, #20202c 0%, #515175 100%); } 7 | .heaven-5 { background: linear-gradient(to bottom, #40405c 0%, #6f71aa 80%, #8a76ab 100%); } 8 | .heaven-6 { background: linear-gradient(to bottom, #4a4969 0%, #7072ab 50%, #cd82a0 100%); } 9 | .heaven-7 { background: linear-gradient(to bottom, #757abf 0%, #8583be 60%, #eab0d1 100%); } 10 | .heaven-8 { background: linear-gradient(to bottom, #82addb 0%, #ebb2b1 100%); } 11 | .heaven-9 { background: linear-gradient(to bottom, #94c5f8 1%, #a6e6ff 70%, #b1b5ea 100%); } 12 | .heaven-10 { background: linear-gradient(to bottom, #b7eaff 0%, #94dfff 100%); } 13 | .heaven-11 { background: linear-gradient(to bottom, #9be2fe 0%, #67d1fb 100%); } 14 | .heaven-12 { background: linear-gradient(to bottom, #90dffe 0%, #38a3d1 100%); } 15 | .heaven-13 { background: linear-gradient(to bottom, #57c1eb 0%, #246fa8 100%); } 16 | .heaven-14 { background: linear-gradient(to bottom, #2d91c2 0%, #1e528e 100%); } 17 | .heaven-15 { background: linear-gradient(to bottom, #2473ab 0%, #1e528e 70%, #5b7983 100%); } 18 | .heaven-16 { background: linear-gradient(to bottom, #1e528e 0%, #265889 50%, #9da671 100%); } 19 | .heaven-17 { background: linear-gradient(to bottom, #1e528e 0%, #728a7c 50%, #e9ce5d 100%); } 20 | .heaven-18 { background: linear-gradient(to bottom, #154277 0%, #576e71 30%, #e1c45e 70%, #b26339 100%); } 21 | .heaven-19 { background: linear-gradient(to bottom, #163c52 0%, #4f4f47 30%, #c5752d 60%, #b7490f 80%, #2f1107 100%); } 22 | .heaven-20 { background: linear-gradient(to bottom, #071b26 0%, #071b26 30%, #8a3b12 80%, #240e03 100%); } 23 | .heaven-21 { background: linear-gradient(to bottom, #010a10 30%, #59230b 80%, #2f1107 100%); } 24 | .heaven-22 { background: linear-gradient(to bottom, #090401 50%, #4B1d06 100%); } 25 | .heaven-23 { background: linear-gradient(to bottom, #00000c 80%, #150800 100%); } 26 | -------------------------------------------------------------------------------- /WebApp/public/css/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | } 4 | 5 | html, body { 6 | height: 100%; 7 | } 8 | 9 | html { 10 | margin: 0; 11 | padding: 0; 12 | font-family: "Helvetica Neue", Roboto, Arial, sans-serif; 13 | font-size: 62.5%; 14 | color: white; 15 | background: linear-gradient(to bottom, #2473ab 0%,#1e528e 70%,#5b7983 100%); 16 | } 17 | 18 | body { 19 | font-size: 1.8rem; 20 | } 21 | 22 | h1, h2, h3 { 23 | font-weight: normal; 24 | } 25 | 26 | h1 { 27 | font-size: 3.5rem; 28 | margin-bottom: 0.5rem; 29 | } 30 | 31 | a { 32 | color: white; 33 | text-decoration: none; 34 | } 35 | 36 | .wrapper { 37 | min-height: 100%; 38 | height: auto !important; 39 | height: 100%; 40 | margin: 0 auto -7rem; 41 | position: relative; 42 | } 43 | 44 | footer, .push { 45 | height: 7rem; 46 | } 47 | 48 | footer .footer-contents { 49 | padding: 0 5rem; 50 | position: relative; 51 | } 52 | 53 | .website-nav { 54 | position: relative; 55 | padding: 5rem; 56 | } 57 | 58 | .website-nav ul { 59 | list-style: none; 60 | margin: 0; 61 | padding: 0; 62 | } 63 | 64 | .website-nav ul li { 65 | float: left; 66 | padding: 0.5rem 2rem 0.5rem 0; 67 | line-height: 21px; 68 | } 69 | 70 | .website-nav ul li a { 71 | color: white; 72 | text-decoration: none; 73 | } 74 | 75 | .home-link { 76 | font-weight: bold; 77 | } 78 | 79 | .message { 80 | position: relative; 81 | padding: 0 5rem; 82 | margin-bottom: 3rem; 83 | width: auto; 84 | } 85 | 86 | .message .twitter-link { 87 | float: left; 88 | margin-right: 20px; 89 | } 90 | 91 | .message .twitter-link img { 92 | width: 40px; 93 | height: 40px; 94 | } 95 | 96 | .message .text { 97 | float: left; 98 | } 99 | 100 | .message:after, .website-nav:after { 101 | content: " "; 102 | display: table; 103 | clear: both; 104 | } 105 | 106 | .graphics { 107 | display: none; 108 | position: absolute; 109 | bottom: 0; 110 | left: 0; 111 | margin-bottom: 0; 112 | } 113 | 114 | .graphics .tower svg { 115 | width: calc(100vw); 116 | height: calc(90vh); 117 | } 118 | 119 | .graphics .cloud { 120 | top: 30rem; 121 | position: relative; 122 | } 123 | 124 | .page-content { 125 | padding: 1rem 5rem; 126 | } 127 | 128 | .page-content p { 129 | margin-bottom: 1rem; 130 | } 131 | 132 | .path { 133 | stroke-dasharray: 4000; 134 | stroke-dashoffset: 4000; 135 | animation: dash 5s linear forwards; 136 | } 137 | 138 | @keyframes dash { 139 | to { 140 | stroke-dashoffset: 0; 141 | } 142 | } 143 | 144 | @media (min-height: 500px) and (min-width: 700px) { 145 | .message { 146 | padding: 0; 147 | width: 50%; 148 | left: calc(50vw - 5rem); 149 | top: calc(15vh - 5rem); 150 | } 151 | 152 | .message .text { 153 | padding-right: 0rem; 154 | } 155 | 156 | .graphics { 157 | display: block; 158 | margin-bottom: 6rem; 159 | } 160 | 161 | .message .twitter-link img { 162 | width: 70%; 163 | height: 70%; 164 | } 165 | 166 | .page-content { 167 | padding: 3rem 5rem; 168 | } 169 | } 170 | 171 | @media (min-height: 500px) and (min-width: 1240px) { 172 | .message { 173 | left: calc(50vw - 10rem); 174 | top: calc(25vh - 5rem); 175 | } 176 | 177 | h1 { 178 | font-size: 5rem; 179 | } 180 | 181 | .message .twitter-link img { 182 | width: 80%; 183 | height: 80%; 184 | } 185 | } 186 | 187 | @media (min-aspect-ratio: 11/5) { 188 | .graphics { 189 | display: none; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /WebApp/public/img/tweet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 16 | -------------------------------------------------------------------------------- /WebApp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Example app 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 18 | 26 | 30 | 34 | 38 | 42 | 43 | 44 |
45 |
46 | 47 |
48 | 56 |
57 | 58 |
59 | 60 |
61 |

Congratulations!

62 |

You just created a Node.js web application.

63 |
64 |
65 |
66 | 67 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /WebApp/public/js/set-background.js: -------------------------------------------------------------------------------- 1 | var idx = Math.floor((new Date().getHours())); 2 | var body = document.getElementsByTagName("body")[0]; 3 | body.className = "heaven-" + idx; 4 | -------------------------------------------------------------------------------- /WebApp/scripts/beforeInstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: MIT-0 5 | 6 | # I want to make sure that the directory is clean and has nothing left over from 7 | # previous deployments. The servers auto scale so the directory may or may not 8 | # exist. 9 | 10 | cd /home/ec2-user/node-website 11 | 12 | if [ -d /home/ec2-user/node-website ]; then 13 | rm -rf /home/ec2-user/node-website 14 | fi 15 | mkdir -vp /home/ec2-user/node-website 16 | -------------------------------------------------------------------------------- /WebApp/scripts/start_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: MIT-0 4 | 5 | cd /home/ec2-user/node-website 6 | export PORT=80 7 | forever start app.js 8 | -------------------------------------------------------------------------------- /WebApp/scripts/stop_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: MIT-0 4 | # 5 | service=node 6 | if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 )) 7 | then 8 | killall node 9 | fi 10 | -------------------------------------------------------------------------------- /WebApp/template.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | AWSTemplateFormatVersion: 2010-09-09 4 | Description: >- 5 | AWS CloudFormation Sample Template ELBWithLockedDownAutoScaledInstances: 6 | Create a load balanced, Auto Scaled sample website where the instances are 7 | locked down to only accept traffic from the load balancer. This example 8 | creates an Auto Scaling group behind a load balancer with a simple health 9 | check. **WARNING** This template 10 | creates one or more Amazon EC2 instances and an Application Load Balancer. You 11 | will be billed for the AWS resources used if you create a stack from this 12 | template. 13 | 14 | Mappings: 15 | VPCIpSpace: 16 | us-east-1: 17 | RANGE: '10.42' 18 | us-east-2: 19 | RANGE: '10.43' 20 | us-west-2: 21 | RANGE: '10.42' 22 | us-west-1: 23 | RANGE: '10.43' 24 | ap-northeast-1: 25 | RANGE: '10.42' 26 | ap-northeast-2: 27 | RANGE: '10.43' 28 | ap-south-1: 29 | RANGE: '10.44' 30 | ap-southeast-1: 31 | RANGE: '10.42' 32 | ap-southeast-2: 33 | RANGE: '10.43' 34 | ca-central-1: 35 | RANGE: '10.42' 36 | eu-central-1: 37 | RANGE: '10.42' 38 | eu-west-1: 39 | RANGE: '10.42' 40 | eu-west-2: 41 | RANGE: '10.43' 42 | sa-east-1: 43 | RANGE: '10.42' 44 | SubnetTypeIpRanges: 45 | public: 46 | RANGE: 0.0/17 47 | publicSubnetConfig: 48 | publicSubnet01: 49 | CIDR: 10.0/24 50 | publicSubnet02: 51 | CIDR: 11.0/24 52 | privateSubnetConfig: 53 | privateSubnet01: 54 | CIDR: 20.0/24 55 | privateSubnet02: 56 | CIDR: 21.0/24 57 | instancesTypes: 58 | Demo: 59 | INST: t2.small 60 | AWSInstanceType2Arch: 61 | t1.micro: 62 | Arch: HVM64 63 | t2.nano: 64 | Arch: HVM64 65 | t2.micro: 66 | Arch: HVM64 67 | t2.small: 68 | Arch: HVM64 69 | t2.medium: 70 | Arch: HVM64 71 | t2.large: 72 | Arch: HVM64 73 | AWSRegionArch2AMI: 74 | us-east-1: 75 | HVM64: ami-0ff8a91507f77f867 76 | HVMG2: ami-0a584ac55a7631c0c 77 | us-west-2: 78 | HVM64: ami-0bb5806b2e825a199 79 | HVMG2: ami-01bbe152bf19d0289 80 | us-west-1: 81 | HVM64: ami-0bdb828fd58c52235 82 | HVMG2: ami-066ee5fd4a9ef77f1 83 | eu-west-1: 84 | HVM64: ami-031a3db8bacbcdc20 85 | HVMG2: ami-09693313102a30b2c 86 | eu-west-2: 87 | HVM64: ami-f976839e 88 | HVMG2: NOT_SUPPORTED 89 | eu-west-3: 90 | HVM64: ami-0ebc281c20e89ba4b 91 | HVMG2: NOT_SUPPORTED 92 | eu-central-1: 93 | HVM64: ami-0233214e13e500f77 94 | HVMG2: ami-06223d46a6d0661c7 95 | ap-northeast-1: 96 | HVM64: ami-06cd52961ce9f0d85 97 | HVMG2: ami-053cdd503598e4a9d 98 | ap-northeast-2: 99 | HVM64: ami-0a10b2721688ce9d2 100 | HVMG2: NOT_SUPPORTED 101 | ap-northeast-3: 102 | HVM64: ami-0d98120a9fb693f07 103 | HVMG2: NOT_SUPPORTED 104 | ap-southeast-1: 105 | HVM64: ami-07ad70c269d8a418c 106 | HVMG2: ami-0b84d2c53ad5250c2 107 | ap-southeast-2: 108 | HVM64: ami-09b42976632b27e9b 109 | HVMG2: ami-0a9ce9fecc3d1daf8 110 | ap-south-1: 111 | HVM64: ami-0912f71e06545ad88 112 | HVMG2: ami-097b15e89dbdcfcf4 113 | us-east-2: 114 | HVM64: ami-0b59bfac6be064b78 115 | HVMG2: NOT_SUPPORTED 116 | ca-central-1: 117 | HVM64: ami-0b18956f 118 | HVMG2: NOT_SUPPORTED 119 | sa-east-1: 120 | HVM64: ami-07b14488da8ea02a0 121 | HVMG2: NOT_SUPPORTED 122 | cn-north-1: 123 | HVM64: ami-0a4eaf6c4454eda75 124 | HVMG2: NOT_SUPPORTED 125 | cn-northwest-1: 126 | HVM64: ami-6b6a7d09 127 | HVMG2: NOT_SUPPORTED 128 | Resources: 129 | VPC: 130 | Type: AWS::EC2::VPC 131 | Properties: 132 | CidrBlock: 133 | Fn::Join: 134 | - '' 135 | - - Fn::FindInMap: 136 | - VPCIpSpace 137 | - Ref: 'AWS::Region' 138 | - RANGE 139 | - . 140 | - 0.0/16 141 | EnableDnsSupport: 'true' 142 | EnableDnsHostnames: 'true' 143 | InstanceTenancy: default 144 | Tags: 145 | - Key: Name 146 | Value: 147 | Fn::Sub: ${AWS::StackName}-vpc 148 | PublicSubnet01: 149 | Type: AWS::EC2::Subnet 150 | Properties: 151 | VpcId: 152 | Ref: VPC 153 | CidrBlock: 154 | Fn::Join: 155 | - '' 156 | - - Fn::FindInMap: 157 | - VPCIpSpace 158 | - Ref: 'AWS::Region' 159 | - RANGE 160 | - . 161 | - Fn::FindInMap: 162 | - publicSubnetConfig 163 | - publicSubnet01 164 | - CIDR 165 | AvailabilityZone: 166 | Fn::Select: 167 | - '0' 168 | - Fn::GetAZs: 169 | Ref: AWS::Region 170 | Tags: 171 | - Key: Name 172 | Value: 173 | Fn::Sub: ${AWS::StackName}-subnetpublic01 174 | PublicSubnet02: 175 | Type: AWS::EC2::Subnet 176 | Properties: 177 | VpcId: 178 | Ref: VPC 179 | CidrBlock: 180 | Fn::Join: 181 | - '' 182 | - - Fn::FindInMap: 183 | - VPCIpSpace 184 | - Ref: 'AWS::Region' 185 | - RANGE 186 | - . 187 | - Fn::FindInMap: 188 | - publicSubnetConfig 189 | - publicSubnet02 190 | - CIDR 191 | AvailabilityZone: 192 | Fn::Select: 193 | - '1' 194 | - Fn::GetAZs: 195 | Ref: AWS::Region 196 | Tags: 197 | - Key: Name 198 | Value: 199 | Fn::Sub: ${AWS::StackName}-subnetpublic02 200 | InternetGateway: 201 | Type: 'AWS::EC2::InternetGateway' 202 | Properties: 203 | Tags: 204 | - Key: Name 205 | Value: 206 | Fn::Sub: ${AWS::StackName}-vpcigw 207 | AttachGateway: 208 | Type: 'AWS::EC2::VPCGatewayAttachment' 209 | Properties: 210 | VpcId: 211 | Ref: VPC 212 | InternetGatewayId: 213 | Ref: InternetGateway 214 | PublicRouteTable: 215 | Type: 'AWS::EC2::RouteTable' 216 | Properties: 217 | VpcId: 218 | Ref: VPC 219 | Tags: 220 | - Key: Name 221 | Value: 222 | Fn::Sub: ${AWS::StackName}-PublicRouteTable 223 | PublicRoute: 224 | Type: 'AWS::EC2::Route' 225 | Properties: 226 | RouteTableId: 227 | Ref: PublicRouteTable 228 | DestinationCidrBlock: 0.0.0.0/0 229 | GatewayId: 230 | Ref: InternetGateway 231 | PublicSubnetRTAssociation01: 232 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 233 | Properties: 234 | SubnetId: 235 | Ref: PublicSubnet01 236 | RouteTableId: 237 | Ref: PublicRouteTable 238 | PublicSubnetRTAssociation02: 239 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 240 | Properties: 241 | SubnetId: 242 | Ref: PublicSubnet02 243 | RouteTableId: 244 | Ref: PublicRouteTable 245 | PublicNetworkAcl: 246 | Type: 'AWS::EC2::NetworkAcl' 247 | Properties: 248 | VpcId: 249 | Ref: VPC 250 | Tags: 251 | - Key: Name 252 | Value: 253 | Fn::Sub: ${AWS::StackName}-PublicNetworkAcl 254 | InboundPublicNAclEntry: 255 | Type: 'AWS::EC2::NetworkAclEntry' 256 | Properties: 257 | NetworkAclId: 258 | Ref: PublicNetworkAcl 259 | RuleNumber: '2000' 260 | Protocol: '-1' 261 | RuleAction: allow 262 | Egress: 'false' 263 | CidrBlock: 0.0.0.0/0 264 | PortRange: 265 | From: '0' 266 | To: '65535' 267 | OutboundPublicNetworkAclEntry: 268 | Type: 'AWS::EC2::NetworkAclEntry' 269 | Properties: 270 | NetworkAclId: 271 | Ref: PublicNetworkAcl 272 | RuleNumber: '2000' 273 | Protocol: '-1' 274 | RuleAction: allow 275 | Egress: 'true' 276 | CidrBlock: 0.0.0.0/0 277 | PortRange: 278 | From: '0' 279 | To: '65535' 280 | PublicSubnetNetworkAclAssociation01: 281 | Type: 'AWS::EC2::SubnetNetworkAclAssociation' 282 | Properties: 283 | SubnetId: 284 | Ref: PublicSubnet01 285 | NetworkAclId: 286 | Ref: PublicNetworkAcl 287 | PublicSubnetNetworkAclAssociation02: 288 | Type: 'AWS::EC2::SubnetNetworkAclAssociation' 289 | Properties: 290 | SubnetId: 291 | Ref: PublicSubnet02 292 | NetworkAclId: 293 | Ref: PublicNetworkAcl 294 | PrivateSubnet01: 295 | Type: AWS::EC2::Subnet 296 | Properties: 297 | VpcId: 298 | Ref: VPC 299 | CidrBlock: 300 | Fn::Join: 301 | - '' 302 | - - Fn::FindInMap: 303 | - VPCIpSpace 304 | - Ref: 'AWS::Region' 305 | - RANGE 306 | - . 307 | - Fn::FindInMap: 308 | - privateSubnetConfig 309 | - privateSubnet01 310 | - CIDR 311 | AvailabilityZone: 312 | Fn::Select: 313 | - '0' 314 | - Fn::GetAZs: 315 | Ref: AWS::Region 316 | Tags: 317 | - Key: Name 318 | Value: 319 | Fn::Sub: ${AWS::StackName}-subnetprivate1 320 | PrivateSubnet02: 321 | Type: AWS::EC2::Subnet 322 | Properties: 323 | VpcId: 324 | Ref: VPC 325 | CidrBlock: 326 | Fn::Join: 327 | - '' 328 | - - Fn::FindInMap: 329 | - VPCIpSpace 330 | - Ref: 'AWS::Region' 331 | - RANGE 332 | - . 333 | - Fn::FindInMap: 334 | - privateSubnetConfig 335 | - privateSubnet02 336 | - CIDR 337 | AvailabilityZone: 338 | Fn::Select: 339 | - '1' 340 | - Fn::GetAZs: 341 | Ref: AWS::Region 342 | Tags: 343 | - Key: Name 344 | Value: 345 | Fn::Sub: ${AWS::StackName}-subnetprivate2 346 | NAT: 347 | DependsOn: PublicSubnetNetworkAclAssociation01 348 | Type: AWS::EC2::NatGateway 349 | Properties: 350 | AllocationId: 351 | Fn::GetAtt: 352 | - EIP 353 | - AllocationId 354 | SubnetId: 355 | Ref: PublicSubnet01 356 | Tags: 357 | - Key: Name 358 | Value: 359 | Fn::Sub: ${AWS::StackName}-NATGateway 360 | EIP: 361 | Type: AWS::EC2::EIP 362 | Properties: 363 | Domain: vpc 364 | PrivateRouteTable: 365 | Type: 'AWS::EC2::RouteTable' 366 | Properties: 367 | VpcId: 368 | Ref: VPC 369 | Tags: 370 | - Key: Name 371 | Value: 372 | Fn::Sub: ${AWS::StackName}-PrivateRouteTable 373 | Route: 374 | Type: AWS::EC2::Route 375 | Properties: 376 | RouteTableId: 377 | Ref: PrivateRouteTable 378 | DestinationCidrBlock: 0.0.0.0/0 379 | NatGatewayId: 380 | Ref: NAT 381 | PrivateSubnetRTAssociation01: 382 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 383 | Properties: 384 | SubnetId: 385 | Ref: PrivateSubnet01 386 | RouteTableId: 387 | Ref: PrivateRouteTable 388 | PrivateSubnetRTAssociation02: 389 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 390 | Properties: 391 | SubnetId: 392 | Ref: PrivateSubnet02 393 | RouteTableId: 394 | Ref: PrivateRouteTable 395 | WebAppRole: 396 | Type: 'AWS::IAM::Role' 397 | Properties: 398 | AssumeRolePolicyDocument: 399 | Statement: 400 | - Sid: '' 401 | Effect: Allow 402 | Principal: 403 | Service: ec2.amazonaws.com 404 | Action: 'sts:AssumeRole' 405 | ManagedPolicyArns: 406 | - 'arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole' 407 | - 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' 408 | - 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess' 409 | - 'arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM' 410 | - 'arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess' 411 | Path: / 412 | S3EncryptionRolePolicies: 413 | Type: 'AWS::IAM::Policy' 414 | Properties: 415 | PolicyName: BackendRole 416 | PolicyDocument: 417 | Statement: 418 | - Effect: Allow 419 | Action: 420 | - 'elasticloadbalancing:Describe*' 421 | - 'elasticloadbalancing:DeregisterTargets' 422 | - 'elasticloadbalancing:RegisterTargets' 423 | - 'autoscaling:Describe*' 424 | - 'autoscaling:EnterStandby' 425 | - 'autoscaling:ExitStandby' 426 | - 'autoscaling:UpdateAutoScalingGroup' 427 | - 'autoscaling:SuspendProcesses' 428 | - 'autoscaling:ResumeProcesses' 429 | Resource: '*' 430 | Roles: 431 | - Ref: WebAppRole 432 | WebAppInstanceProfile: 433 | Type: 'AWS::IAM::InstanceProfile' 434 | Properties: 435 | Path: / 436 | Roles: 437 | - Ref: WebAppRole 438 | WebServerGroup: 439 | Type: 'AWS::AutoScaling::AutoScalingGroup' 440 | Properties: 441 | AutoScalingGroupName: BlueGreenASGroup 442 | VPCZoneIdentifier: 443 | - Ref: PrivateSubnet01 444 | - Ref: PrivateSubnet02 445 | LaunchConfigurationName: 446 | Ref: LaunchConfig 447 | MinSize: '2' 448 | MaxSize: '4' 449 | TargetGroupARNs: 450 | - Ref: ALBTargetGroup 451 | DesiredCapacity: '2' 452 | Tags: 453 | - Key: Name 454 | Value: BlueGreenWebHost 455 | PropagateAtLaunch: 'true' 456 | CreationPolicy: 457 | ResourceSignal: 458 | Count: '2' 459 | Timeout: PT5M 460 | UpdatePolicy: 461 | AutoScalingRollingUpdate: 462 | MinInstancesInService: '1' 463 | MaxBatchSize: '1' 464 | PauseTime: PT10M 465 | WaitOnResourceSignals: 'true' 466 | LaunchConfig: 467 | Type: AWS::AutoScaling::LaunchConfiguration 468 | Metadata: 469 | Comment: Install a simple application 470 | 'AWS::CloudFormation::Init': 471 | config: 472 | packages: 473 | yum: 474 | httpd: [] 475 | files: 476 | /home/ec2-user/node-website/app.js: 477 | content: 478 | 'Fn::Join': 479 | - |+ 480 | 481 | - - var http = require('http'); 482 | - http.createServer(function (req, res) { 483 | - >- 484 | res.writeHead(200, {'Content-Type': 'text/plain'}); 485 | res.end('Hello World!'); 486 | - >- 487 | }).listen(80); 488 | mode: '000644' 489 | owner: root 490 | group: root 491 | /etc/cfn/cfn-hup.conf: 492 | content: 493 | 'Fn::Join': 494 | - '' 495 | - - | 496 | [main] 497 | - stack= 498 | - Ref: 'AWS::StackId' 499 | - |+ 500 | 501 | - role= 502 | - Ref: 'WebAppRole' 503 | - |+ 504 | 505 | - region= 506 | - Ref: 'AWS::Region' 507 | - |+ 508 | 509 | mode: '000400' 510 | owner: root 511 | group: root 512 | /etc/cfn/hooks.d/cfn-auto-reloader.conf: 513 | content: 514 | 'Fn::Join': 515 | - '' 516 | - - | 517 | [cfn-auto-reloader-hook] 518 | - | 519 | triggers=post.update 520 | - > 521 | path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init 522 | - 'action=/opt/aws/bin/cfn-init -v ' 523 | - ' --stack ' 524 | - Ref: 'AWS::StackName' 525 | - ' --resource LaunchConfig ' 526 | - ' --role ' 527 | - Ref: 'WebAppRole' 528 | - ' --region ' 529 | - Ref: 'AWS::Region' 530 | - |+ 531 | 532 | - | 533 | runas=root 534 | mode: '000400' 535 | owner: root 536 | group: root 537 | services: 538 | cfn-hup: 539 | enabled: 'true' 540 | ensureRunning: 'true' 541 | files: 542 | - /etc/cfn/cfn-hup.conf 543 | - /etc/cfn/hooks.d/cfn-auto-reloader.conf 544 | Properties: 545 | IamInstanceProfile: 546 | Ref: WebAppInstanceProfile 547 | ImageId: 548 | Fn::FindInMap: 549 | - "AWSRegionArch2AMI" 550 | - Ref: "AWS::Region" 551 | - Fn::FindInMap: 552 | - "AWSInstanceType2Arch" 553 | - Fn::FindInMap: 554 | - instancesTypes 555 | - Demo 556 | - INST 557 | - Arch 558 | UserData: 559 | 'Fn::Base64': 560 | 'Fn::Join': 561 | - '' 562 | - - | 563 | #!/bin/bash -xe 564 | - | 565 | yum install -y git 566 | - | 567 | yum install -y ruby 568 | - | 569 | yum update -y aws-cfn-bootstrap 570 | - | 571 | # Install pip and python dev libraries. 572 | yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 573 | - | 574 | yum install -y python27-devel python27-pip gcc 575 | - | 576 | yum install -y python-pip 577 | - | 578 | yum install -y wget 579 | - | 580 | cd /home/ec2-user/ 581 | - 'wget https://aws-codedeploy-' 582 | - !Ref 'AWS::Region' 583 | - | 584 | .s3.amazonaws.com/latest/install 585 | - | 586 | chmod +x ./install 587 | - | 588 | ./install auto 589 | - | 590 | service codedeploy-agent start 591 | - | 592 | # making the website 593 | mkdir /home/ec2-user/node-website 594 | - |+ 595 | - '/opt/aws/bin/cfn-init -v ' 596 | - ' --stack ' 597 | - Ref: 'AWS::StackName' 598 | - ' --resource LaunchConfig ' 599 | - ' --role ' 600 | - Ref: 'WebAppRole' 601 | - ' --region ' 602 | - Ref: 'AWS::Region' 603 | - |+ 604 | 605 | - | 606 | #!/bin/bash -xe 607 | cd /home/ec2-user/node-website 608 | - | 609 | curl -sL https://rpm.nodesource.com/setup_8.x | bash - 610 | - | 611 | yum install -y nodejs 612 | - | 613 | npm install forever -g 614 | - | 615 | export PORT=80 616 | - | 617 | forever start app.js 618 | - |+ 619 | 620 | - '/opt/aws/bin/cfn-signal -e $? ' 621 | - ' --stack ' 622 | - Ref: 'AWS::StackName' 623 | - ' --resource WebServerGroup ' 624 | - ' --region ' 625 | - Ref: 'AWS::Region' 626 | - |+ 627 | SecurityGroups: 628 | - Ref: "InstanceSecurityGroup" 629 | InstanceType: t2.small 630 | ApplicationLoadBalancer: 631 | Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' 632 | Properties: 633 | Scheme: internet-facing 634 | Subnets: 635 | - Ref: PublicSubnet01 636 | - Ref: PublicSubnet02 637 | SecurityGroups: 638 | - Fn::GetAtt: LoadBalancerSecurityGroup.GroupId 639 | Tags: 640 | - Key: Name 641 | Value: 642 | Fn::Sub: ${AWS::StackName}-ALB 643 | ALBListener: 644 | Type: 'AWS::ElasticLoadBalancingV2::Listener' 645 | Properties: 646 | DefaultActions: 647 | - Type: forward 648 | TargetGroupArn: 649 | Ref: ALBTargetGroup 650 | LoadBalancerArn: 651 | Ref: ApplicationLoadBalancer 652 | Port: '80' 653 | Protocol: HTTP 654 | ALBTargetGroup: 655 | Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' 656 | Properties: 657 | Name: 'BlueGreenTG' 658 | HealthCheckIntervalSeconds: 30 659 | HealthCheckTimeoutSeconds: 5 660 | HealthyThresholdCount: 3 661 | Port: 80 662 | Protocol: HTTP 663 | UnhealthyThresholdCount: 5 664 | VpcId: 665 | Ref: VPC 666 | Tags: 667 | - Key: Name 668 | Value: 669 | Fn::Sub: ${AWS::StackName}-TG 670 | LoadBalancerSecurityGroup: 671 | Type: 'AWS::EC2::SecurityGroup' 672 | Properties: 673 | GroupDescription: Enable SSH access and HTTP access on the inbound port 674 | SecurityGroupIngress: 675 | - IpProtocol: tcp 676 | FromPort: '80' 677 | ToPort: '80' 678 | CidrIp: 0.0.0.0/0 679 | VpcId: 680 | Ref: VPC 681 | InstanceSecurityGroup: 682 | Type: 'AWS::EC2::SecurityGroup' 683 | Properties: 684 | GroupDescription: Enable SSH access and HTTP access on the inbound port 685 | SecurityGroupIngress: 686 | - IpProtocol: tcp 687 | FromPort: '80' 688 | ToPort: '80' 689 | SourceSecurityGroupId: 690 | 'Fn::Select': 691 | - 0 692 | - 'Fn::GetAtt': 693 | - ApplicationLoadBalancer 694 | - SecurityGroups 695 | - IpProtocol: tcp 696 | FromPort: '22' 697 | ToPort: '22' 698 | CidrIp: 0.0.0.0/0 699 | VpcId: 700 | Ref: VPC 701 | S3Bucket: 702 | Type: 'AWS::S3::Bucket' 703 | Properties: 704 | BucketName: 705 | 'Fn::Join' : 706 | - '' 707 | - - build-artifact-bluegreenbucket 708 | - '-' 709 | - Ref: 'AWS::Region' 710 | - '-' 711 | - Ref: 'AWS::AccountId' 712 | 713 | VersioningConfiguration: 714 | Status: Enabled 715 | Tags: 716 | - Key: Name 717 | Value: BlueGreen-S3Bucket 718 | DeployTrustRole: 719 | Type: 'AWS::IAM::Role' 720 | Properties: 721 | AssumeRolePolicyDocument: 722 | Statement: 723 | - Sid: '' 724 | Effect: Allow 725 | Principal: 726 | Service: 727 | - codedeploy.amazonaws.com 728 | Action: 'sts:AssumeRole' 729 | ManagedPolicyArns: 730 | - 'arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole' 731 | Path: / 732 | Outputs: 733 | URL: 734 | Description: URL of the website 735 | Value: 736 | 'Fn::Join': 737 | - '' 738 | - - 'http://' 739 | - 'Fn::GetAtt': 740 | - ApplicationLoadBalancer 741 | - DNSName 742 | S3BucketName: 743 | Value: 744 | Ref: S3Bucket 745 | Description: Bucket to for storing artifacts 746 | DeployRoleArn: 747 | Value: 748 | Ref: DeployTrustRole 749 | Description: CodeDeploy role Arn 750 | ALBTargetGroup: 751 | Value: 752 | 'Fn::GetAtt' : ALBTargetGroup.TargetGroupName 753 | Description: TargetGroup Name 754 | ASGroup: 755 | Value: 756 | Ref: WebServerGroup 757 | Description: AutoScaling Group Name -------------------------------------------------------------------------------- /WebApp/tests/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const supertest = require('supertest'); 4 | const test = require('unit.js'); 5 | const app = require('../app.js'); 6 | 7 | const request = supertest(app); 8 | 9 | describe('Tests app', function() { 10 | it('verifies get', function(done) { 11 | request.get('/').expect(200).end(function(err, result) { 12 | test.string(result.text).contains('Congratulations'); 13 | test.value(result).hasHeader('content-type', 'text/html'); 14 | done(err); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | # -*-perl-*- 4 | 5 | package.BlueGreenWebApp = { 6 | interfaces = (1.0); 7 | 8 | deploy = { 9 | generic = true; 10 | }; 11 | 12 | build-environment = { 13 | chroot = basic; 14 | network-access = blocked; 15 | }; 16 | 17 | # Use NoOpBuild. See https://w.amazon.com/index.php/BrazilBuildSystem/NoOpBuild 18 | build-system = no-op; 19 | build-tools = { 20 | 1.0 = { 21 | NoOpBuild = 1.0; 22 | }; 23 | }; 24 | 25 | # Use runtime-dependencies for when you want to bring in additional 26 | # packages when deploying. 27 | # Use dependencies instead if you intend for these dependencies to 28 | # be exported to other packages that build against you. 29 | dependencies = { 30 | 1.0 = { 31 | }; 32 | }; 33 | 34 | runtime-dependencies = { 35 | 1.0 = { 36 | }; 37 | }; 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /images/bg-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-1.png -------------------------------------------------------------------------------- /images/bg-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-10.png -------------------------------------------------------------------------------- /images/bg-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-11.png -------------------------------------------------------------------------------- /images/bg-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-2.png -------------------------------------------------------------------------------- /images/bg-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-3.png -------------------------------------------------------------------------------- /images/bg-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-4.png -------------------------------------------------------------------------------- /images/bg-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-5.png -------------------------------------------------------------------------------- /images/bg-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-6.png -------------------------------------------------------------------------------- /images/bg-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-7.png -------------------------------------------------------------------------------- /images/bg-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/bg-9.png -------------------------------------------------------------------------------- /images/codecommit-iam-gc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codecommit-iam-gc1.png -------------------------------------------------------------------------------- /images/codestar1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codestar1.png -------------------------------------------------------------------------------- /images/codestar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codestar2.png -------------------------------------------------------------------------------- /images/codestar3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codestar3.png -------------------------------------------------------------------------------- /images/codestar4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codestar4.png -------------------------------------------------------------------------------- /images/codestar5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cicd-bluegreen/530a62eb932f350e45497e1d41742b68154be6d4/images/codestar5.png --------------------------------------------------------------------------------