├── 601-Build-An-ECR-Repo ├── .gitignore └── README.md ├── .gitignore ├── 604-Deploy-Container-With-Copilot-CLI ├── .gitignore ├── index.html ├── Dockerfile └── README.md ├── 607-Fargate-Task-With-Event ├── cdk-AWS-Cookbook-607 │ ├── cdk_aws_cookbook_607 │ │ ├── __init__.py │ │ └── cdk_aws_cookbook_607_stack.py │ ├── requirements.txt │ ├── .gitignore │ ├── cdk.json │ ├── app.py │ ├── source.bat │ ├── setup.py │ ├── helper.py │ └── README.md ├── .gitignore ├── maze.jpg ├── LaunchingFargateTaskOnEvent.png ├── task-execution-assume-role.json ├── policy1.json ├── Docker │ ├── Dockerfile │ └── cmd.sh ├── policy2.json ├── targets-template.json └── README.md ├── 606-Autoscaling-Container-Workloads ├── cdk-AWS-Cookbook-606 │ ├── requirements.txt │ ├── cdk_aws_cookbook_606 │ │ ├── __init__.py │ │ └── cdk_aws_cookbook_606_stack.py │ ├── Docker │ │ ├── build.sh │ │ ├── Dockerfile │ │ ├── README.md │ │ └── app │ │ │ ├── WebContent │ │ │ └── WEB-INF │ │ │ │ └── web.xml │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── net │ │ │ └── zengineering │ │ │ └── LoadtestServlet.java │ ├── .gitignore │ ├── cdk.json │ ├── app.py │ ├── source.bat │ ├── setup.py │ ├── helper.py │ └── README.md ├── scaling-policy.json ├── task-execution-assume-role.json └── README.md ├── 605-Updating-Containers-With-BlueGreen ├── cdk-AWS-Cookbook-605 │ ├── cdk_aws_cookbook_605 │ │ ├── __init__.py │ │ └── cdk_aws_cookbook_605_stack.py │ ├── requirements.txt │ ├── DockerBlue │ │ ├── Dockerfile │ │ └── index.html │ ├── DockerGreen │ │ ├── Dockerfile │ │ └── index.html │ ├── .gitignore │ ├── cdk.json │ ├── app.py │ ├── source.bat │ ├── setup.py │ ├── helper.py │ └── README.md ├── .gitignore ├── assume-role-policy.json ├── appspec-template.yaml ├── deployment-template.json ├── codedeploy-template.json └── README.md ├── 608-Capturing-Logs-From-Containers-Running-On-ECS ├── cdk-AWS-Cookbook-608 │ ├── cdk_aws_cookbook_608 │ │ ├── __init__.py │ │ └── cdk_aws_cookbook_608_stack.py │ ├── requirements.txt │ ├── .gitignore │ ├── cdk.json │ ├── app.py │ ├── source.bat │ ├── setup.py │ ├── helper.py │ └── README.md ├── task-execution-assume-role.json ├── taskdef.json └── README.md ├── 602-Image-Scanning-In-ECR ├── ContainerImageScanningSolutionWorkflow.png └── README.md ├── README.md ├── 603-Deploy-Container-With-Lightsail ├── README.md └── lightsail.json ├── .github └── ISSUE_TEMPLATE │ ├── recipe-request.md │ └── bug_report.md └── LICENSE /601-Build-An-ECR-Repo/.gitignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | output.jpg 3 | targets.json -------------------------------------------------------------------------------- /604-Deploy-Container-With-Copilot-CLI/.gitignore: -------------------------------------------------------------------------------- 1 | copilot/ 2 | -------------------------------------------------------------------------------- /604-Deploy-Container-With-Copilot-CLI/index.html: -------------------------------------------------------------------------------- 1 | Hello AWS Cookbook Reader! 2 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/cdk_aws_cookbook_607/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | boto3 -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | boto3 -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/.gitignore: -------------------------------------------------------------------------------- 1 | bucketpolicy.json 2 | targets.json 3 | output.jpg -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/cdk_aws_cookbook_605/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | boto3 -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/cdk_aws_cookbook_606/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/cdk_aws_cookbook_608/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | boto3 -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/.gitignore: -------------------------------------------------------------------------------- 1 | codedeploy.json 2 | deployment.json 3 | appspec.yaml 4 | -------------------------------------------------------------------------------- /604-Deploy-Container-With-Copilot-CLI/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | COPY index.html /usr/share/nginx/html 3 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/maze.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AWSCookbook/Containers/HEAD/607-Fargate-Task-With-Event/maze.jpg -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | docker build -t mzazon/loadtest:latest . -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/DockerBlue/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd:latest 2 | COPY index.html /usr/local/apache2/htdocs/index.html -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/DockerGreen/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd:latest 2 | COPY index.html /usr/local/apache2/htdocs/index.html -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/LaunchingFargateTaskOnEvent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AWSCookbook/Containers/HEAD/607-Fargate-Task-With-Event/LaunchingFargateTaskOnEvent.png -------------------------------------------------------------------------------- /602-Image-Scanning-In-ECR/ContainerImageScanningSolutionWorkflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AWSCookbook/Containers/HEAD/602-Image-Scanning-In-ECR/ContainerImageScanningSolutionWorkflow.png -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | package-lock.json 3 | __pycache__ 4 | .pytest_cache 5 | .env 6 | .venv 7 | *.egg-info 8 | 9 | # CDK asset staging directory 10 | .cdk.staging 11 | cdk.out 12 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | package-lock.json 3 | __pycache__ 4 | .pytest_cache 5 | .env 6 | .venv 7 | *.egg-info 8 | 9 | # CDK asset staging directory 10 | .cdk.staging 11 | cdk.out 12 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | package-lock.json 3 | __pycache__ 4 | .pytest_cache 5 | .env 6 | .venv 7 | *.egg-info 8 | 9 | # CDK asset staging directory 10 | .cdk.staging 11 | cdk.out 12 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | package-lock.json 3 | __pycache__ 4 | .pytest_cache 5 | .env 6 | .venv 7 | *.egg-info 8 | 9 | # CDK asset staging directory 10 | .cdk.staging 11 | cdk.out 12 | -------------------------------------------------------------------------------- /604-Deploy-Container-With-Copilot-CLI/README.md: -------------------------------------------------------------------------------- 1 | # Deploying containers using AWS Copilot CLI 2 | ## Preparation 3 | ### Install Copilot cli tool 4 | brew install aws/tap/copilot-cli 5 | 6 | 7 | ## Clean up 8 | ### Delete the App 9 | copilot app delete -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/scaling-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "TargetValue": 50.0, 3 | "PredefinedMetricSpecification": { 4 | "PredefinedMetricType": "ECSServiceAverageCPUUtilization" 5 | }, 6 | "ScaleOutCooldown": 10, 7 | "ScaleInCooldown": 10 8 | } -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "python3 app.py", 3 | "context": { 4 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, 5 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, 6 | "@aws-cdk/core:stackRelativeExports": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "python3 app.py", 3 | "context": { 4 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, 5 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, 6 | "@aws-cdk/core:stackRelativeExports": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "python3 app.py", 3 | "context": { 4 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, 5 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, 6 | "@aws-cdk/core:stackRelativeExports": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import aws_cdk as cdk 4 | 5 | from cdk_aws_cookbook_607.cdk_aws_cookbook_607_stack import CdkAwsCookbook607Stack 6 | 7 | 8 | app = cdk.App() 9 | CdkAwsCookbook607Stack(app, "cdk-aws-cookbook-607") 10 | 11 | app.synth() 12 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import aws_cdk as cdk 4 | 5 | from cdk_aws_cookbook_606.cdk_aws_cookbook_606_stack import CdkAwsCookbook606Stack 6 | 7 | 8 | app = cdk.App() 9 | CdkAwsCookbook606Stack(app, "cdk-aws-cookbook-606") 10 | 11 | app.synth() 12 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "python3 app.py", 3 | "context": { 4 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, 5 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, 6 | "@aws-cdk/core:stackRelativeExports": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chapter 6 2 | ## Set and export your default region: 3 | 4 | `export AWS_REGION=us-east-1` 5 | 6 | ## Set your AWS ACCOUNT ID:: 7 | 8 | `AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)` 9 | 10 | ## Validate AWS Cli Setup and access: 11 | 12 | `aws ec2 describe-instances` 13 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import aws_cdk as cdk 4 | 5 | from cdk_aws_cookbook_605.cdk_aws_cookbook_605_stack import CdkAwsCookbook605Stack 6 | 7 | 8 | app = cdk.App() 9 | CdkAwsCookbook605Stack(app, "cdk-aws-cookbook-605") 10 | 11 | app.synth() 12 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.6.3-jdk-8 AS build 2 | COPY app/ /opt/app 3 | RUN cd /opt/app && mvn clean install 4 | 5 | FROM tomcat:8.5-jdk8-slim 6 | RUN rm -rf /usr/local/tomcat/webapps/ROOT 7 | COPY --from=build /opt/app/target/loadtest.war /usr/local/tomcat/webapps/ROOT.war -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/task-execution-assume-role.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "ecs-tasks.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/task-execution-assume-role.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "ecs-tasks.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/policy1.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": "events.amazonaws.com" 8 | }, 9 | "Action": "sts:AssumeRole" 10 | } 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import aws_cdk as cdk 4 | 5 | from cdk_aws_cookbook_608.cdk_aws_cookbook_608_stack import CdkAwsCookbook608Stack 6 | 7 | 8 | app = cdk.App() 9 | CdkAwsCookbook608Stack(app, "cdk-aws-cookbook-608") 10 | 11 | app.synth() 12 | -------------------------------------------------------------------------------- /603-Deploy-Container-With-Lightsail/README.md: -------------------------------------------------------------------------------- 1 | # Deploying a container using Amazon Lightsail 2 | 3 | ## Clean up 4 | ### Delete the local image from your workstation: 5 | 6 | `docker image rm nginx` 7 | 8 | ### Delete the container service: 9 | 10 | `aws lightsail delete-container-service --service-name awscookbook` 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/task-execution-assume-role.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "ecs-tasks.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/DockerBlue/index.html: -------------------------------------------------------------------------------- 1 | AWSCookbook

AWS Cookbook BLUE

This HTML is running in an apache container on Fargate!

-------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/DockerGreen/index.html: -------------------------------------------------------------------------------- 1 | AWSCookbook

AWS Cookbook GREEN

This HTML is running in an apache container on Fargate!

-------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/assume-role-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": "codedeploy.amazonaws.com" 8 | }, 9 | "Action": "sts:AssumeRole" 10 | } 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/appspec-template.yaml: -------------------------------------------------------------------------------- 1 | version: 0.0 2 | Resources: 3 | - TargetService: 4 | Type: AWS::ECS::Service 5 | Properties: 6 | TaskDefinition: "FargateTaskGreenArn" 7 | LoadBalancerInfo: 8 | ContainerName: "ContainerDefGreen" 9 | ContainerPort: 80 10 | PlatformVersion: "LATEST" -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/deployment-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "applicationName": "awscookbook-605", 3 | "deploymentGroupName": "awscookbook-605-dg", 4 | "revision": { 5 | "revisionType": "S3", 6 | "s3Location": { 7 | "bucket": "S3BucketName", 8 | "key": "appspec.yaml", 9 | "bundleType": "YAML" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /603-Deploy-Container-With-Lightsail/lightsail.json: -------------------------------------------------------------------------------- 1 | { 2 | "serviceName": "awscookbook", 3 | "containers": { 4 | "awscookbook": { 5 | "image": ":awscookbook.awscookbook.1", 6 | "ports": { 7 | "80": "HTTP" 8 | } 9 | } 10 | }, 11 | "publicEndpoint": { 12 | "containerName": "awscookbook", 13 | "containerPort": 80 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/Docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-cli:latest 2 | #ENV BucketName $S3_BUCKET 3 | #ENV ObjectKey $S3_KEY 4 | RUN yum -y update && yum -y install python3 5 | RUN pip3 install mazesolver --user 6 | WORKDIR /root/ 7 | COPY cmd.sh /root/ 8 | RUN chmod +x cmd.sh 9 | CMD ["/bin/bash", "-c", "/root/cmd.sh $S3_BUCKET $S3_KEY"] 10 | #CMD ["cmd.sh"] 11 | ENTRYPOINT ["/bin/bash", "-c", "/root/cmd.sh $S3_BUCKET $S3_KEY"] -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/source.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem The sole purpose of this script is to make the command 4 | rem 5 | rem source .venv/bin/activate 6 | rem 7 | rem (which activates a Python virtualenv on Linux or Mac OS X) work on Windows. 8 | rem On Windows, this command just runs this batch file (the argument is ignored). 9 | rem 10 | rem Now we don't need to document a Windows command for activating a virtualenv. 11 | 12 | echo Executing .venv\Scripts\activate.bat for you 13 | .venv\Scripts\activate.bat 14 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/source.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem The sole purpose of this script is to make the command 4 | rem 5 | rem source .venv/bin/activate 6 | rem 7 | rem (which activates a Python virtualenv on Linux or Mac OS X) work on Windows. 8 | rem On Windows, this command just runs this batch file (the argument is ignored). 9 | rem 10 | rem Now we don't need to document a Windows command for activating a virtualenv. 11 | 12 | echo Executing .venv\Scripts\activate.bat for you 13 | .venv\Scripts\activate.bat 14 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/source.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem The sole purpose of this script is to make the command 4 | rem 5 | rem source .venv/bin/activate 6 | rem 7 | rem (which activates a Python virtualenv on Linux or Mac OS X) work on Windows. 8 | rem On Windows, this command just runs this batch file (the argument is ignored). 9 | rem 10 | rem Now we don't need to document a Windows command for activating a virtualenv. 11 | 12 | echo Executing .venv\Scripts\activate.bat for you 13 | .venv\Scripts\activate.bat 14 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/source.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem The sole purpose of this script is to make the command 4 | rem 5 | rem source .venv/bin/activate 6 | rem 7 | rem (which activates a Python virtualenv on Linux or Mac OS X) work on Windows. 8 | rem On Windows, this command just runs this batch file (the argument is ignored). 9 | rem 10 | rem Now we don't need to document a Windows command for activating a virtualenv. 11 | 12 | echo Executing .venv\Scripts\activate.bat for you 13 | .venv\Scripts\activate.bat 14 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/README.md: -------------------------------------------------------------------------------- 1 | # aws loadtest api 2 | java servlet and tomcat 8.5 implementation of a load test API for containers 3 | java sdk8 and maven 3.x for build 4 | 5 | Easily demonstrate ECS AutoScaling and simulate container CPU, Memory and request loads on container infrastructure 6 | 7 | ## Usage 8 | * Run locally using "docker run -rm --it -p 8080:8080 mzazon/loadtest" 9 | * HTTP GET "/loadtest/cpu" 10 | * Initiates an HTTP call which will load CPU to 100% 11 | * Returns JSON 12 | * Healthcheck path for load balancers HTTP GET "/loadtest/healthcheck" -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/recipe-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Recipe request 3 | about: Suggest a recipe for this Chapter 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your recipe request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe what you'd like to learn** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/Docker/cmd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # script takes parameters 3 | # $1 aws s3 bucket name 4 | # $2 input file path on s3 5 | # TODO: get bucket name from SSM or CloudFormation or DynamoDB or SQS 6 | set -x 7 | #printenv 8 | echo "Downloading input file from S3..." 9 | echo $1 10 | echo $2 11 | aws s3 cp s3://$1/$2 /root/$2 12 | #aws s3 cp s3://cdk-aws-cookbook-407-awscookbokrecipe407f6cd7422-1kmigiv1e331u/input/maze.jpg /root/ 13 | #mv /root/maze.jpg /root/input.jpg 14 | echo "Processing Input... This may take a while depending on size." 15 | python3 /root/.local/bin/mazesolver -i /root/$2 -o /root/ 16 | ls -al 17 | aws s3 cp /root/maze_out.jpg s3://$1/output/output.jpg 18 | echo "Completed." 19 | exit 0 -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/policy2.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "ecs:RunTask" 8 | ], 9 | "Resource": [ 10 | "arn:aws:ecs:*:*:task-definition/*" 11 | ] 12 | }, 13 | { 14 | "Effect": "Allow", 15 | "Action": "iam:PassRole", 16 | "Resource": [ 17 | "*" 18 | ], 19 | "Condition": { 20 | "StringLike": { 21 | "iam:PassedToService": "ecs-tasks.amazonaws.com" 22 | } 23 | } 24 | } 25 | ] 26 | } 27 | 28 | -------------------------------------------------------------------------------- /601-Build-An-ECR-Repo/README.md: -------------------------------------------------------------------------------- 1 | # Building and Pushing a Container Image to ECR 2 | 3 | 4 | ## Cleanup 5 | ### Remove the image from ECR: 6 | ``` 7 | aws ecr batch-delete-image --repository-name aws-cookbook-repo \ 8 | --image-ids imageTag=latest 9 | 10 | aws ecr batch-delete-image --repository-name aws-cookbook-repo \ 11 | --image-ids imageTag=1.0 12 | ``` 13 | 14 | 15 | ### Delete the image from your local machine: 16 | ``` 17 | docker image rm \ 18 | $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-repo:1.0 19 | docker image rm \ 20 | $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-repo:latest 21 | ``` 22 | 23 | ### Delete the repository: 24 | 25 | `aws ecr delete-repository --repository-name aws-cookbook-repo` 26 | 27 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/app/WebContent/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | loadtest 4 | 5 | 6 | LoadtestServlet 7 | LoadtestServlet 8 | net.zengineering.java.loadtest.LoadtestServlet 9 | 10 | 11 | LoadtestServlet 12 | /* 13 | 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/targets-template.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "AWSCookbookRuleID", 4 | "Arn": "ECSClusterARN", 5 | "RoleArn": "arn:aws:iam::AWS_ACCOUNT_ID:role/AWSCookbook607RuleRole", 6 | "EcsParameters": { 7 | "TaskDefinitionArn": "TaskDefinitionARN", 8 | "TaskCount": 1, 9 | "LaunchType": "FARGATE", 10 | "NetworkConfiguration": { 11 | "awsvpcConfiguration": { 12 | "Subnets": [VPCPrivateSubnets], 13 | "SecurityGroups": ["VPCDefaultSecurityGroup"], 14 | "AssignPublicIp": "ENABLED" 15 | } 16 | } 17 | }, 18 | "InputTransformer": { 19 | "InputPathsMap": {"s3_bucket": "$.detail.requestParameters.bucketName","s3_key": "$.detail.requestParameters.key"}, 20 | "InputTemplate": "{ \"containerOverrides\": [{\"name\": \"AWS-Cookbook-ContainerDefinition\",\"environment\": [{ \"name\": \"S3_BUCKET\", \"value\": },{ \"name\": \"S3_KEY\", \"value\": }]}]}" 21 | } 22 | } 23 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AWS Cookbook 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/taskdef.json: -------------------------------------------------------------------------------- 1 | { 2 | "networkMode": "awsvpc", 3 | "containerDefinitions": [ 4 | { 5 | "portMappings": [ 6 | { 7 | "hostPort": 80, 8 | "containerPort": 80, 9 | "protocol": "tcp" 10 | } 11 | ], 12 | "essential": true, 13 | "entryPoint": [ 14 | "sh", 15 | "-c" 16 | ], 17 | "logConfiguration": { 18 | "logDriver": "awslogs", 19 | "options": { 20 | "awslogs-group": "AWSCookbook608ECS", 21 | "awslogs-region": "us-east-1", 22 | "awslogs-stream-prefix": "LogStream" 23 | } 24 | }, 25 | "name": "awscookbook608", 26 | "image": "httpd:2.4", 27 | "command": [ 28 | "/bin/sh -c \"echo 'Hello AWS Cookbook Reader, this container is running on ECS!' > /usr/local/apache2/htdocs/index.html && httpd-foreground\"" 29 | ] 30 | } 31 | ], 32 | "family": "awscookbook608", 33 | "requiresCompatibilities": [ 34 | "FARGATE" 35 | ], 36 | "cpu": "256", 37 | "memory": "512" 38 | } 39 | 40 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | with open("README.md") as fp: 5 | long_description = fp.read() 6 | 7 | 8 | setuptools.setup( 9 | name="cdk_aws_cookbook_607", 10 | version="0.0.1", 11 | 12 | description="An empty CDK Python app", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | 16 | author="author", 17 | 18 | package_dir={"": "cdk_aws_cookbook_607"}, 19 | packages=setuptools.find_packages(where="cdk_aws_cookbook_607"), 20 | 21 | install_requires=[ 22 | "aws-cdk-lib>=2.0.0rc1", 23 | "constructs>=10.0.0", 24 | ], 25 | 26 | python_requires=">=3.6", 27 | 28 | classifiers=[ 29 | "Development Status :: 4 - Beta", 30 | 31 | "Intended Audience :: Developers", 32 | 33 | "License :: OSI Approved :: Apache Software License", 34 | 35 | "Programming Language :: JavaScript", 36 | "Programming Language :: Python :: 3 :: Only", 37 | "Programming Language :: Python :: 3.6", 38 | "Programming Language :: Python :: 3.7", 39 | "Programming Language :: Python :: 3.8", 40 | 41 | "Topic :: Software Development :: Code Generators", 42 | "Topic :: Utilities", 43 | 44 | "Typing :: Typed", 45 | ], 46 | ) 47 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | with open("README.md") as fp: 5 | long_description = fp.read() 6 | 7 | 8 | setuptools.setup( 9 | name="cdk_aws_cookbook_605", 10 | version="0.0.1", 11 | 12 | description="An empty CDK Python app", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | 16 | author="author", 17 | 18 | package_dir={"": "cdk_aws_cookbook_605"}, 19 | packages=setuptools.find_packages(where="cdk_aws_cookbook_605"), 20 | 21 | install_requires=[ 22 | "aws-cdk-lib>=2.0.0rc1", 23 | "constructs>=10.0.0", 24 | ], 25 | 26 | python_requires=">=3.6", 27 | 28 | classifiers=[ 29 | "Development Status :: 4 - Beta", 30 | 31 | "Intended Audience :: Developers", 32 | 33 | "License :: OSI Approved :: Apache Software License", 34 | 35 | "Programming Language :: JavaScript", 36 | "Programming Language :: Python :: 3 :: Only", 37 | "Programming Language :: Python :: 3.6", 38 | "Programming Language :: Python :: 3.7", 39 | "Programming Language :: Python :: 3.8", 40 | 41 | "Topic :: Software Development :: Code Generators", 42 | "Topic :: Utilities", 43 | 44 | "Typing :: Typed", 45 | ], 46 | ) 47 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | with open("README.md") as fp: 5 | long_description = fp.read() 6 | 7 | 8 | setuptools.setup( 9 | name="cdk_aws_cookbook_606", 10 | version="0.0.1", 11 | 12 | description="An empty CDK Python app", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | 16 | author="author", 17 | 18 | package_dir={"": "cdk_aws_cookbook_606"}, 19 | packages=setuptools.find_packages(where="cdk_aws_cookbook_606"), 20 | 21 | install_requires=[ 22 | "aws-cdk-lib>=2.0.0rc1", 23 | "constructs>=10.0.0", 24 | ], 25 | 26 | python_requires=">=3.6", 27 | 28 | classifiers=[ 29 | "Development Status :: 4 - Beta", 30 | 31 | "Intended Audience :: Developers", 32 | 33 | "License :: OSI Approved :: Apache Software License", 34 | 35 | "Programming Language :: JavaScript", 36 | "Programming Language :: Python :: 3 :: Only", 37 | "Programming Language :: Python :: 3.6", 38 | "Programming Language :: Python :: 3.7", 39 | "Programming Language :: Python :: 3.8", 40 | 41 | "Topic :: Software Development :: Code Generators", 42 | "Topic :: Utilities", 43 | 44 | "Typing :: Typed", 45 | ], 46 | ) 47 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | with open("README.md") as fp: 5 | long_description = fp.read() 6 | 7 | 8 | setuptools.setup( 9 | name="cdk_aws_cookbook_608", 10 | version="0.0.1", 11 | 12 | description="An empty CDK Python app", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | 16 | author="author", 17 | 18 | package_dir={"": "cdk_aws_cookbook_608"}, 19 | packages=setuptools.find_packages(where="cdk_aws_cookbook_608"), 20 | 21 | install_requires=[ 22 | "aws-cdk-lib>=2.0.0rc1", 23 | "constructs>=10.0.0", 24 | ], 25 | 26 | python_requires=">=3.6", 27 | 28 | classifiers=[ 29 | "Development Status :: 4 - Beta", 30 | 31 | "Intended Audience :: Developers", 32 | 33 | "License :: OSI Approved :: Apache Software License", 34 | 35 | "Programming Language :: JavaScript", 36 | "Programming Language :: Python :: 3 :: Only", 37 | "Programming Language :: Python :: 3.6", 38 | "Programming Language :: Python :: 3.7", 39 | "Programming Language :: Python :: 3.8", 40 | 41 | "Topic :: Software Development :: Code Generators", 42 | "Topic :: Utilities", 43 | 44 | "Typing :: Typed", 45 | ], 46 | ) 47 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/codedeploy-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "applicationName": "awscookbook-605", 3 | "autoRollbackConfiguration": { 4 | "enabled": true, 5 | "events": [ "DEPLOYMENT_FAILURE" ] 6 | }, 7 | "blueGreenDeploymentConfiguration": { 8 | "deploymentReadyOption": { 9 | "actionOnTimeout": "CONTINUE_DEPLOYMENT", 10 | "waitTimeInMinutes": 0 11 | }, 12 | "terminateBlueInstancesOnDeploymentSuccess": { 13 | "action": "TERMINATE", 14 | "terminationWaitTimeInMinutes": 5 15 | } 16 | }, 17 | "deploymentGroupName": "awscookbook-605-dg", 18 | "deploymentStyle": { 19 | "deploymentOption": "WITH_TRAFFIC_CONTROL", 20 | "deploymentType": "BLUE_GREEN" 21 | }, 22 | "loadBalancerInfo": { 23 | "targetGroupPairInfoList": [ 24 | { 25 | "targetGroups": [ 26 | { 27 | "name": "BlueTG" 28 | }, 29 | { 30 | "name": "GreenTG" 31 | } 32 | ], 33 | "prodTrafficRoute": { 34 | "listenerArns": [ 35 | "PROD_LISTENER_ARN" 36 | ] 37 | }, 38 | "testTrafficRoute": { 39 | "listenerArns": [ 40 | "TEST_LISTENER_ARN" 41 | ] 42 | } 43 | } 44 | ] 45 | }, 46 | "serviceRoleArn": "arn:aws:iam::AWS_ACCOUNT_ID:role/ecsCodeDeployRole", 47 | "ecsServices": [ 48 | { 49 | "serviceName": "AWSCookbook605", 50 | "clusterName": "awscookbook605" 51 | } 52 | ] 53 | } -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | import argparse 4 | 5 | 6 | def change_case(str): 7 | res = [str[0]] 8 | for c in str[1:]: 9 | if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): 10 | res.append('_') 11 | res.append(c) 12 | elif c in ('123456789'): 13 | res.append('_') 14 | res.append(c) 15 | else: 16 | res.append(c.upper()) 17 | 18 | return ''.join(res) 19 | 20 | 21 | parser = argparse.ArgumentParser(description="Generate commands to set and unset environment variables") 22 | parser.add_argument('--unset', action='store_true', help="Generate commands to unset environment variables by setting this flag") 23 | 24 | args = parser.parse_args() 25 | 26 | os.environ['AWS_DEFAULT_REGION'] = os.environ.get('AWS_REGION') 27 | 28 | cfn = boto3.client('cloudformation') 29 | stackname = os.path.basename(os.getcwd()).lower() 30 | response = cfn.describe_stacks(StackName=stackname) 31 | unsets = [] 32 | sets = [] 33 | 34 | outputs = response["Stacks"][0]["Outputs"] 35 | print("Copy and paste the commands below into your terminal") 36 | print("") 37 | for output in outputs: 38 | if ', ' in output["OutputValue"]: 39 | sets.append(change_case(output["OutputKey"]) + "='" + ', '.join('"{}"'.format(word) for word in output["OutputValue"].split(", ")) + "'") 40 | else: 41 | sets.append(change_case(output["OutputKey"]) + "='" + output["OutputValue"] + "'") 42 | unsets.append("unset " + change_case(output["OutputKey"])) 43 | 44 | if (args.unset): 45 | print('\n'.join(map(str, unsets))) 46 | else: 47 | print('\n'.join(map(str, sets))) 48 | 49 | print("") 50 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | import argparse 4 | 5 | 6 | def change_case(str): 7 | res = [str[0]] 8 | for c in str[1:]: 9 | if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): 10 | res.append('_') 11 | res.append(c) 12 | elif c in ('123456789'): 13 | res.append('_') 14 | res.append(c) 15 | else: 16 | res.append(c.upper()) 17 | 18 | return ''.join(res) 19 | 20 | 21 | parser = argparse.ArgumentParser(description="Generate commands to set and unset environment variables") 22 | parser.add_argument('--unset', action='store_true', help="Generate commands to unset environment variables by setting this flag") 23 | 24 | args = parser.parse_args() 25 | 26 | os.environ['AWS_DEFAULT_REGION'] = os.environ.get('AWS_REGION') 27 | 28 | cfn = boto3.client('cloudformation') 29 | stackname = os.path.basename(os.getcwd()).lower() 30 | response = cfn.describe_stacks(StackName=stackname) 31 | unsets = [] 32 | sets = [] 33 | 34 | outputs = response["Stacks"][0]["Outputs"] 35 | print("Copy and paste the commands below into your terminal") 36 | print("") 37 | for output in outputs: 38 | if ', ' in output["OutputValue"]: 39 | sets.append(change_case(output["OutputKey"]) + "='" + ', '.join('"{}"'.format(word) for word in output["OutputValue"].split(", ")) + "'") 40 | else: 41 | sets.append(change_case(output["OutputKey"]) + "='" + output["OutputValue"] + "'") 42 | unsets.append("unset " + change_case(output["OutputKey"])) 43 | 44 | if (args.unset): 45 | print('\n'.join(map(str, unsets))) 46 | else: 47 | print('\n'.join(map(str, sets))) 48 | 49 | print("") 50 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | import argparse 4 | 5 | 6 | def change_case(str): 7 | res = [str[0]] 8 | for c in str[1:]: 9 | if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): 10 | res.append('_') 11 | res.append(c) 12 | elif c in ('123456789'): 13 | res.append('_') 14 | res.append(c) 15 | else: 16 | res.append(c.upper()) 17 | 18 | return ''.join(res) 19 | 20 | 21 | parser = argparse.ArgumentParser(description="Generate commands to set and unset environment variables") 22 | parser.add_argument('--unset', action='store_true', help="Generate commands to unset environment variables by setting this flag") 23 | 24 | args = parser.parse_args() 25 | 26 | os.environ['AWS_DEFAULT_REGION'] = os.environ.get('AWS_REGION') 27 | 28 | cfn = boto3.client('cloudformation') 29 | stackname = os.path.basename(os.getcwd()).lower() 30 | response = cfn.describe_stacks(StackName=stackname) 31 | unsets = [] 32 | sets = [] 33 | 34 | outputs = response["Stacks"][0]["Outputs"] 35 | print("Copy and paste the commands below into your terminal") 36 | print("") 37 | for output in outputs: 38 | if ', ' in output["OutputValue"]: 39 | sets.append(change_case(output["OutputKey"]) + "='" + ', '.join('"{}"'.format(word) for word in output["OutputValue"].split(", ")) + "'") 40 | else: 41 | sets.append(change_case(output["OutputKey"]) + "='" + output["OutputValue"] + "'") 42 | unsets.append("unset " + change_case(output["OutputKey"])) 43 | 44 | if (args.unset): 45 | print('\n'.join(map(str, unsets))) 46 | else: 47 | print('\n'.join(map(str, sets))) 48 | 49 | print("") 50 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | import argparse 4 | 5 | 6 | def change_case(str): 7 | res = [str[0]] 8 | for c in str[1:]: 9 | if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): 10 | res.append('_') 11 | res.append(c) 12 | elif c in ('123456789'): 13 | res.append('_') 14 | res.append(c) 15 | else: 16 | res.append(c.upper()) 17 | 18 | return ''.join(res) 19 | 20 | 21 | parser = argparse.ArgumentParser(description="Generate commands to set and unset environment variables") 22 | parser.add_argument('--unset', action='store_true', help="Generate commands to unset environment variables by setting this flag") 23 | 24 | args = parser.parse_args() 25 | 26 | os.environ['AWS_DEFAULT_REGION'] = os.environ.get('AWS_REGION') 27 | 28 | cfn = boto3.client('cloudformation') 29 | stackname = os.path.basename(os.getcwd()).lower() 30 | response = cfn.describe_stacks(StackName=stackname) 31 | unsets = [] 32 | sets = [] 33 | 34 | outputs = response["Stacks"][0]["Outputs"] 35 | print("Copy and paste the commands below into your terminal") 36 | print("") 37 | for output in outputs: 38 | if ', ' in output["OutputValue"]: 39 | sets.append(change_case(output["OutputKey"]) + "='" + ', '.join('"{}"'.format(word) for word in output["OutputValue"].split(", ")) + "'") 40 | else: 41 | sets.append(change_case(output["OutputKey"]) + "='" + output["OutputValue"] + "'") 42 | unsets.append("unset " + change_case(output["OutputKey"])) 43 | 44 | if (args.unset): 45 | print('\n'.join(map(str, unsets))) 46 | else: 47 | print('\n'.join(map(str, sets))) 48 | 49 | print("") 50 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | net.zengineering.java.loadtest 4 | loadtest 5 | 2.1 6 | war 7 | 8 | loadtest 9 | 10 | 11 | maven-war-plugin 12 | 2.3 13 | 14 | WebContent 15 | false 16 | 17 | 18 | 19 | 20 | 21 | 22 | javax.servlet 23 | servlet-api 24 | 2.5 25 | provided 26 | 27 | 37 | 38 | 51 | 52 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Welcome to your CDK Python project! 3 | 4 | This is a blank project for Python development with CDK. 5 | 6 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 7 | 8 | This project is set up like a standard Python project. The initialization 9 | process also creates a virtualenv within this project, stored under the `.venv` 10 | directory. To create the virtualenv it assumes that there is a `python3` 11 | (or `python` for Windows) executable in your path with access to the `venv` 12 | package. If for any reason the automatic creation of the virtualenv fails, 13 | you can create the virtualenv manually. 14 | 15 | To manually create a virtualenv on MacOS and Linux: 16 | 17 | ``` 18 | $ python3 -m venv .venv 19 | ``` 20 | 21 | After the init process completes and the virtualenv is created, you can use the following 22 | step to activate your virtualenv. 23 | 24 | ``` 25 | $ source .venv/bin/activate 26 | ``` 27 | 28 | If you are a Windows platform, you would activate the virtualenv like this: 29 | 30 | ``` 31 | % .venv\Scripts\activate.bat 32 | ``` 33 | 34 | Once the virtualenv is activated, you can install the required dependencies. 35 | 36 | ``` 37 | $ pip install -r requirements.txt 38 | ``` 39 | 40 | At this point you can now synthesize the CloudFormation template for this code. 41 | 42 | ``` 43 | $ cdk synth 44 | ``` 45 | 46 | To add additional dependencies, for example other CDK libraries, just add 47 | them to your `setup.py` file and rerun the `pip install -r requirements.txt` 48 | command. 49 | 50 | ## Useful commands 51 | 52 | * `cdk ls` list all stacks in the app 53 | * `cdk synth` emits the synthesized CloudFormation template 54 | * `cdk deploy` deploy this stack to your default AWS account/region 55 | * `cdk diff` compare deployed stack with current state 56 | * `cdk docs` open CDK documentation 57 | 58 | Enjoy! 59 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Welcome to your CDK Python project! 3 | 4 | This is a blank project for Python development with CDK. 5 | 6 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 7 | 8 | This project is set up like a standard Python project. The initialization 9 | process also creates a virtualenv within this project, stored under the `.venv` 10 | directory. To create the virtualenv it assumes that there is a `python3` 11 | (or `python` for Windows) executable in your path with access to the `venv` 12 | package. If for any reason the automatic creation of the virtualenv fails, 13 | you can create the virtualenv manually. 14 | 15 | To manually create a virtualenv on MacOS and Linux: 16 | 17 | ``` 18 | $ python3 -m venv .venv 19 | ``` 20 | 21 | After the init process completes and the virtualenv is created, you can use the following 22 | step to activate your virtualenv. 23 | 24 | ``` 25 | $ source .venv/bin/activate 26 | ``` 27 | 28 | If you are a Windows platform, you would activate the virtualenv like this: 29 | 30 | ``` 31 | % .venv\Scripts\activate.bat 32 | ``` 33 | 34 | Once the virtualenv is activated, you can install the required dependencies. 35 | 36 | ``` 37 | $ pip install -r requirements.txt 38 | ``` 39 | 40 | At this point you can now synthesize the CloudFormation template for this code. 41 | 42 | ``` 43 | $ cdk synth 44 | ``` 45 | 46 | To add additional dependencies, for example other CDK libraries, just add 47 | them to your `setup.py` file and rerun the `pip install -r requirements.txt` 48 | command. 49 | 50 | ## Useful commands 51 | 52 | * `cdk ls` list all stacks in the app 53 | * `cdk synth` emits the synthesized CloudFormation template 54 | * `cdk deploy` deploy this stack to your default AWS account/region 55 | * `cdk diff` compare deployed stack with current state 56 | * `cdk docs` open CDK documentation 57 | 58 | Enjoy! 59 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Welcome to your CDK Python project! 3 | 4 | This is a blank project for Python development with CDK. 5 | 6 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 7 | 8 | This project is set up like a standard Python project. The initialization 9 | process also creates a virtualenv within this project, stored under the `.venv` 10 | directory. To create the virtualenv it assumes that there is a `python3` 11 | (or `python` for Windows) executable in your path with access to the `venv` 12 | package. If for any reason the automatic creation of the virtualenv fails, 13 | you can create the virtualenv manually. 14 | 15 | To manually create a virtualenv on MacOS and Linux: 16 | 17 | ``` 18 | $ python3 -m venv .venv 19 | ``` 20 | 21 | After the init process completes and the virtualenv is created, you can use the following 22 | step to activate your virtualenv. 23 | 24 | ``` 25 | $ source .venv/bin/activate 26 | ``` 27 | 28 | If you are a Windows platform, you would activate the virtualenv like this: 29 | 30 | ``` 31 | % .venv\Scripts\activate.bat 32 | ``` 33 | 34 | Once the virtualenv is activated, you can install the required dependencies. 35 | 36 | ``` 37 | $ pip install -r requirements.txt 38 | ``` 39 | 40 | At this point you can now synthesize the CloudFormation template for this code. 41 | 42 | ``` 43 | $ cdk synth 44 | ``` 45 | 46 | To add additional dependencies, for example other CDK libraries, just add 47 | them to your `setup.py` file and rerun the `pip install -r requirements.txt` 48 | command. 49 | 50 | ## Useful commands 51 | 52 | * `cdk ls` list all stacks in the app 53 | * `cdk synth` emits the synthesized CloudFormation template 54 | * `cdk deploy` deploy this stack to your default AWS account/region 55 | * `cdk diff` compare deployed stack with current state 56 | * `cdk docs` open CDK documentation 57 | 58 | Enjoy! 59 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Welcome to your CDK Python project! 3 | 4 | This is a blank project for Python development with CDK. 5 | 6 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 7 | 8 | This project is set up like a standard Python project. The initialization 9 | process also creates a virtualenv within this project, stored under the `.venv` 10 | directory. To create the virtualenv it assumes that there is a `python3` 11 | (or `python` for Windows) executable in your path with access to the `venv` 12 | package. If for any reason the automatic creation of the virtualenv fails, 13 | you can create the virtualenv manually. 14 | 15 | To manually create a virtualenv on MacOS and Linux: 16 | 17 | ``` 18 | $ python3 -m venv .venv 19 | ``` 20 | 21 | After the init process completes and the virtualenv is created, you can use the following 22 | step to activate your virtualenv. 23 | 24 | ``` 25 | $ source .venv/bin/activate 26 | ``` 27 | 28 | If you are a Windows platform, you would activate the virtualenv like this: 29 | 30 | ``` 31 | % .venv\Scripts\activate.bat 32 | ``` 33 | 34 | Once the virtualenv is activated, you can install the required dependencies. 35 | 36 | ``` 37 | $ pip install -r requirements.txt 38 | ``` 39 | 40 | At this point you can now synthesize the CloudFormation template for this code. 41 | 42 | ``` 43 | $ cdk synth 44 | ``` 45 | 46 | To add additional dependencies, for example other CDK libraries, just add 47 | them to your `setup.py` file and rerun the `pip install -r requirements.txt` 48 | command. 49 | 50 | ## Useful commands 51 | 52 | * `cdk ls` list all stacks in the app 53 | * `cdk synth` emits the synthesized CloudFormation template 54 | * `cdk deploy` deploy this stack to your default AWS account/region 55 | * `cdk diff` compare deployed stack with current state 56 | * `cdk docs` open CDK documentation 57 | 58 | Enjoy! 59 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/README.md: -------------------------------------------------------------------------------- 1 | # Auto Scaling container workloads on Amazon ECS 2 | ## Preparation 3 | 4 | This recipe requires some “prep work” which deploys resources that you’ll build the solution on. You will use the AWS CDK to deploy these resources 5 | 6 | ### In the root of this Chapter’s repo cd to the “606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606” directory and follow the subsequent steps: 7 | ``` 8 | cd 606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/ 9 | test -d .venv || python3 -m venv .venv 10 | source .venv/bin/activate 11 | pip install --upgrade pip 12 | pip install -r requirements.txt 13 | cdk deploy 14 | ``` 15 | 16 | ### Wait for the cdk deploy command to complete. 17 | 18 | ### We created a helper.py script to let you easily create and export environment variables to make subsequent commands easier. Run the script, and copy the output to your terminal to export variables: 19 | 20 | `python helper.py` 21 | 22 | ### Navigate up to the main directory for this recipe (out of the “cdk-AWS-Cookbook-606” directory) 23 | 24 | `cd ..` 25 | 26 | 27 | ## Clean up 28 | ### Delete the container images: 29 | ``` 30 | aws ecr batch-delete-image --repository-name aws-cdk/assets \ 31 | --image-ids imageTag=$(echo $ECR_IMAGE | cut -d : -f 2) 32 | ``` 33 | 34 | ### Go to the cdk-AWS-Cookbook-606 directory: 35 | 36 | `cd cdk-AWS-Cookbook-606/` 37 | 38 | ### To clean up the environment variables, run the helper.py script in this recipe’s cdk- directory with the --unset flag, and copy the output to your terminal to export variables: 39 | 40 | `python helper.py --unset` 41 | 42 | ### Use the AWS CDK to destroy the resources, deactivate your Python virtual environment, and go to the root of the chapter: 43 | 44 | `cdk destroy && deactivate && rm -r .venv/ && cd ../..` 45 | 46 | ### Detach the managed Auto Scaling policy from the IAM role: 47 | ``` 48 | aws iam detach-role-policy --role-name AWSCookbook606ECS --policy-arn \ 49 | arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceAutoscaleRole 50 | ``` 51 | 52 | ### Delete the Auto Scaling IAM role: 53 | 54 | `aws iam delete-role --role-name AWSCookbook606ECS` 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608/cdk_aws_cookbook_608/cdk_aws_cookbook_608_stack.py: -------------------------------------------------------------------------------- 1 | from constructs import Construct 2 | from aws_cdk import ( 3 | aws_ec2 as ec2, 4 | aws_ecs as ecs, 5 | Stack, 6 | CfnOutput, 7 | ) 8 | 9 | 10 | class CdkAwsCookbook608Stack(Stack): 11 | 12 | def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: 13 | super().__init__(scope, construct_id, **kwargs) 14 | 15 | # create VPC 16 | vpc = ec2.Vpc( 17 | self, 18 | 'AWS-Cookbook-VPC' 19 | ) 20 | 21 | InterfaceEndpointSecurityGroup = ec2.SecurityGroup( 22 | self, 23 | 'InterfaceEndpointSecurityGroup', 24 | description='Security Group for the VPC Endpoints', 25 | allow_all_outbound=True, 26 | vpc=vpc 27 | ) 28 | 29 | InterfaceEndpointSecurityGroup.connections.allow_from( 30 | ec2.Peer.ipv4(vpc.vpc_cidr_block), ec2.Port.tcp(443), "Ingress") 31 | 32 | vpc.add_interface_endpoint( 33 | 'CloudWatchLogsEndpoint', 34 | service=ec2.InterfaceVpcEndpointAwsService('logs'), 35 | private_dns_enabled=True, 36 | security_groups=[InterfaceEndpointSecurityGroup], 37 | subnets=ec2.SubnetSelection( 38 | one_per_az=True, 39 | subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT 40 | ), 41 | ) 42 | 43 | # create ECS Cluster 44 | ecs_cluster = ecs.Cluster( 45 | self, 46 | 'AWS-Cookbook-EcsCluster', 47 | vpc=vpc 48 | ) 49 | 50 | CfnOutput( 51 | self, 52 | 'EcsClusterName', 53 | value=ecs_cluster.cluster_name 54 | ) 55 | 56 | public_subnets = vpc.select_subnets(subnet_type=ec2.SubnetType.PUBLIC) 57 | 58 | CfnOutput( 59 | self, 60 | 'VpcPublicSubnets', 61 | value=', '.join(map(str, public_subnets.subnet_ids)) 62 | ) 63 | 64 | CfnOutput( 65 | self, 66 | 'VpcDefaultSecurityGroup', 67 | value=vpc.vpc_default_security_group 68 | ) 69 | -------------------------------------------------------------------------------- /608-Capturing-Logs-From-Containers-Running-On-ECS/README.md: -------------------------------------------------------------------------------- 1 | # Capturing logs from containers running on Amazon ECS 2 | ## Preparation 3 | 4 | This recipe requires some “prep work” which deploys resources that you’ll build the solution on. You will use the AWS CDK to deploy these resources. 5 | 6 | ### In the root of this Chapter’s repo cd to the “608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608” directory and follow the subsequent steps: 7 | ``` 8 | cd 608-Capturing-Logs-From-Containers-Running-On-ECS/cdk-AWS-Cookbook-608 9 | test -d .venv || python3 -m venv .venv 10 | source .venv/bin/activate 11 | pip install --upgrade pip 12 | pip install -r requirements.txt 13 | cdk deploy 14 | ``` 15 | 16 | ### Wait for the cdk deploy command to complete. 17 | 18 | ### We created a helper.py script to let you easily create and export environment variables to make subsequent commands easier. Run the script, and copy the output to your terminal to export variables: 19 | 20 | `python helper.py` 21 | 22 | ### Navigate up to the main directory for this recipe (out of the “cdk-AWS-Cookbook-608” directory): 23 | 24 | `cd ..` 25 | 26 | ### This solution, like the others using Amazon ECS, requires an ECS service-linked role to allow ECS to perform actions on your behalf. This may already exist in your AWS account. To see if you have this role already, issue the following command: 27 | 28 | `aws iam list-roles --path-prefix /aws-service-role/ecs.amazonaws.com/` 29 | 30 | ### If the role is displayed, you can skip the creation step. 31 | 32 | ### Create the ECS service-linked role if it does not exist (it is OK if the command fails indicating that the role already exists in your account): 33 | 34 | `aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com` 35 | 36 | 37 | ## Clean up 38 | 39 | ### Stop the ECS task: 40 | 41 | `aws ecs stop-task --cluster $ECS_CLUSTER_NAME --task <>` 42 | 43 | ### Delete the IAM Policy Attachment and Role: 44 | ``` 45 | aws iam detach-role-policy --role-name AWSCookbook608ECS --policy-arn \ 46 | arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy 47 | aws iam delete-role --role-name AWSCookbook608ECS 48 | ``` 49 | 50 | ### Delete Log Group: 51 | `aws logs delete-log-group --log-group-name AWSCookbook608ECS` 52 | 53 | ### Deregister the Task Definition 54 | 55 | `aws ecs deregister-task-definition --task-definition awscookbook608:1` 56 | 57 | ### Go to the cdk-AWS-Cookbook-608 directory 58 | 59 | `cd cdk-AWS-Cookbook-608/` 60 | 61 | ### To clean up the environment variables, run the helper.py script in this recipe’s cdk- directory with the --unset flag, and copy the output to your terminal to export variables: 62 | 63 | `python helper.py --unset` 64 | 65 | ### Use the AWS CDK to destroy the resources, deactivate your Python virtual environment, and go to the root of the chapter: 66 | 67 | `cdk destroy && deactivate && rm -r .venv/ && cd ../..` 68 | 69 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/README.md: -------------------------------------------------------------------------------- 1 | # Updating containers with blue/green deployments 2 | ## Preparation 3 | 4 | This recipe requires some “prep work” which deploys resources that you’ll build the solution on. You will use the AWS CDK to deploy these resources 5 | 6 | ### In the root of this Chapter’s repo cd to the “605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605” directory: 7 | ``` 8 | cd 605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/ 9 | test -d .venv || python3 -m venv .venv 10 | source .venv/bin/activate 11 | pip install --upgrade pip 12 | pip install -r requirements.txt 13 | cdk deploy 14 | ``` 15 | 16 | ### Wait for the cdk deploy command to complete. 17 | 18 | ### We created a helper.py script to let you easily create and export environment variables to make subsequent commands easier. Run the script, and copy the output to your terminal to export variables: 19 | 20 | `python helper.py` 21 | 22 | ### Navigate up to the main directory for this recipe (out of the “cdk-AWS-Cookbook-605” directory) 23 | 24 | `cd ..` 25 | 26 | 27 | ## Clean up 28 | 29 | ### Delete the CodeDeploy deployment group and application: 30 | ``` 31 | aws deploy delete-deployment-group \ 32 | --deployment-group-name awscookbook-605-dg \ 33 | --application-name awscookbook-605 34 | 35 | aws deploy delete-application --application-name awscookbook-605 36 | ``` 37 | 38 | ### Detach the IAM policy from and delete the role used by CodeDeploy to update your application on Amazon ECS: 39 | ``` 40 | aws iam detach-role-policy --role-name ecsCodeDeployRole \ 41 | --policy-arn arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS 42 | 43 | aws iam delete-role --role-name ecsCodeDeployRole 44 | ``` 45 | 46 | ### Now remove the load balancer rules created by CodeDeploy during the deployment and the target group you created previously: 47 | ``` 48 | aws elbv2 delete-rule --rule-arn \ 49 | $(aws elbv2 describe-rules \ 50 | --listener-arn $PROD_LISTENER_ARN \ 51 | --query 'Rules[?Priority==`"1"`].RuleArn' \ 52 | --output text) 53 | 54 | aws elbv2 modify-listener --listener-arn $TEST_LISTENER_ARN \ 55 | --default-actions Type=forward,TargetGroupArn=$DEFAULT_TARGET_GROUP_ARN 56 | 57 | aws elbv2 delete-target-group --target-group-arn \ 58 | $(aws elbv2 describe-target-groups \ 59 | --names "GreenTG" \ 60 | --query 'TargetGroups[0].TargetGroupArn' \ 61 | --output text) 62 | ``` 63 | 64 | ### Delete the Blue and Green images: 65 | ``` 66 | aws ecr batch-delete-image --repository-name aws-cdk/assets \ 67 | --image-ids imageTag=$(echo $BLUE_IMAGE | cut -d : -f 2) \ 68 | imageTag=$(echo $GREEN_IMAGE | cut -d : -f 2) 69 | ` 70 | 71 | ### Go to the cdk-AWS-Cookbook-605 directory 72 | `cd cdk-AWS-Cookbook-605/` 73 | 74 | ### To clean up the environment variables, run the helper.py script in this recipe’s cdk- directory with the --unset flag, and copy the output to your terminal to export variables: 75 | 76 | `python helper.py --unset` 77 | 78 | ### Use the AWS CDK to destroy the resources, deactivate your Python virtual environment, and go to the root of the chapter: 79 | 80 | `cdk destroy && deactivate && rm -r .venv/ && cd ../..` 81 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/Docker/app/src/main/java/net/zengineering/LoadtestServlet.java: -------------------------------------------------------------------------------- 1 | package net.zengineering.java.loadtest; 2 | 3 | import java.io.IOException; 4 | import java.text.DateFormat; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Calendar; 7 | import java.util.GregorianCalendar; 8 | import java.util.Locale; 9 | import java.util.TimeZone; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.ServletInputStream; 13 | import javax.servlet.ServletOutputStream; 14 | import javax.servlet.http.HttpServlet; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | 18 | import java.net.InetAddress; 19 | import java.net.UnknownHostException; 20 | 21 | public class LoadtestServlet extends HttpServlet { 22 | private static final long serialVersionUID = 1L; 23 | private DateFormat httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); 24 | 25 | public LoadtestServlet() { 26 | httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 27 | } 28 | 29 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 30 | long now = System.currentTimeMillis(); 31 | String timeStr = request.getParameter("time"); 32 | String httpStatusStr = request.getParameter("http-status"); 33 | int httpStatus = (httpStatusStr!=null?Integer.parseInt(httpStatusStr):200); 34 | long maxTime = (timeStr != null ? Long.parseLong(timeStr) : 0L); 35 | 36 | long time = maxTime; 37 | 38 | if (request.getRequestURI().endsWith("/cpu")) { 39 | 40 | double value = 9.9; 41 | while (System.currentTimeMillis() <= (now + 99999999)) { 42 | value = value / 1.0000001; 43 | value = value * 1.00000015; 44 | if (value > Double.MAX_VALUE / 2) { 45 | value = 1.0; 46 | } 47 | } 48 | finishTest(request, response, (System.currentTimeMillis() - now), httpStatus, "success", "value=" + value); 49 | 50 | } else if (request.getRequestURI().endsWith("/healthcheck")) { 51 | // aws load balancer health check 52 | 53 | double value = 9.9; 54 | while (System.currentTimeMillis() <= (now + 3000)) { 55 | value = value / 1.0000001; 56 | value = value * 1.00000015; 57 | if (value > Double.MAX_VALUE / 2) { 58 | value = 1.0; 59 | } 60 | } 61 | finishTest(request, response, (System.currentTimeMillis() - now), httpStatus, "success", "value=" + value); 62 | 63 | } else { 64 | finishTest(request, response, (System.currentTimeMillis() - now), 400, "error", 65 | ""); 66 | } 67 | 68 | } 69 | 70 | private void finishTest(HttpServletRequest request, HttpServletResponse response, long timeElapsed, int statusCode, String result, String info) { 71 | try { 72 | response.setContentType("application/json"); 73 | response.setStatus(statusCode); 74 | ServletOutputStream responseOS = response.getOutputStream(); 75 | InetAddress ip; 76 | ip = InetAddress.getLocalHost(); 77 | String hostname = ip.getHostName(); 78 | String body = "{\n \"URL\":\"" + request.getRequestURL() + "\",\n \"ContainerLocalAddress\":\"" + request.getLocalAddr() + ":" + request.getLocalPort() + "\",\n \"ProcessingTimeTotalMilliseconds\":\"" + timeElapsed + "\",\n \"LoadBalancerPrivateIP\":\"" + request.getRemoteHost() + "\",\n \"ContainerHostname\":\"" + hostname + "\",\n \"CurrentTime\":\"" + System.currentTimeMillis() + "\"\n}"; 79 | responseOS.print(body); 80 | } catch (IOException e) { 81 | throw new RuntimeException(e); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/cdk_aws_cookbook_607/cdk_aws_cookbook_607_stack.py: -------------------------------------------------------------------------------- 1 | from constructs import Construct 2 | from aws_cdk import ( 3 | aws_ec2 as ec2, 4 | aws_ecs as ecs, 5 | aws_s3 as s3, 6 | aws_iam as iam, 7 | aws_cloudtrail as cloudtrail, 8 | Stack, 9 | CfnOutput, 10 | RemovalPolicy 11 | ) 12 | 13 | 14 | class CdkAwsCookbook607Stack(Stack): 15 | 16 | def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: 17 | super().__init__(scope, construct_id, **kwargs) 18 | 19 | cloud_trail_bucket = s3.Bucket( 20 | self, 21 | "AWS-Cookbok-Recipe607-Cloud-trail", 22 | removal_policy=RemovalPolicy.DESTROY, 23 | auto_delete_objects=True 24 | ) 25 | 26 | trail = cloudtrail.Trail( 27 | self, 28 | 'Cloudtrail', 29 | bucket=cloud_trail_bucket 30 | ) 31 | 32 | s3_Bucket = s3.Bucket( 33 | self, 34 | "AWS-Cookbok-Recipe607", 35 | removal_policy=RemovalPolicy.DESTROY, 36 | auto_delete_objects=True 37 | ) 38 | 39 | # create VPC 40 | vpc = ec2.Vpc( 41 | self, 42 | 'AWS-Cookbook-VPC' 43 | ) 44 | 45 | # create ECS Cluster 46 | ecs_cluster = ecs.Cluster( 47 | self, 48 | 'AWS-Cookbook-EcsCluster', 49 | vpc=vpc 50 | ) 51 | 52 | # create Fargate Task Definition 53 | FargateTask = ecs.FargateTaskDefinition( 54 | self, 55 | 'AWS-Cookbook-FargateTask', 56 | cpu=1024, 57 | memory_limit_mib=2048, 58 | ) 59 | 60 | # create Container Definition 61 | ContainerDefinition = ecs.ContainerDefinition( 62 | self, 63 | 'AWS-Cookbook-ContainerDefinition', 64 | image=ecs.ContainerImage.from_registry("public.ecr.aws/x4e8a6b6/mazesolver:1.0.7"), 65 | task_definition=FargateTask, 66 | ) 67 | 68 | ContainerDefinition.add_port_mappings( 69 | ecs.PortMapping( 70 | container_port=80 71 | ) 72 | ) 73 | 74 | # Grant the container access to the s3 bucket by adding an IAM policy to the execution role 75 | FargateTask.add_to_task_role_policy(iam.PolicyStatement( 76 | effect=iam.Effect.ALLOW, 77 | resources=[s3_Bucket.bucket_arn + '/*'], 78 | actions=["s3:*"]) 79 | ) 80 | 81 | CfnOutput( 82 | self, 83 | 'CloudTrailArn', 84 | value=trail.trail_arn 85 | ) 86 | 87 | CfnOutput( 88 | self, 89 | 'BucketArn', 90 | value=s3_Bucket.bucket_arn 91 | ) 92 | 93 | CfnOutput( 94 | self, 95 | 'CloudTrailBucketName', 96 | value=cloud_trail_bucket.bucket_name 97 | ) 98 | 99 | CfnOutput( 100 | self, 101 | 'BucketName', 102 | value=s3_Bucket.bucket_name 103 | ) 104 | 105 | CfnOutput( 106 | self, 107 | 'EcsClusterArn', 108 | value=ecs_cluster.cluster_arn 109 | ) 110 | 111 | CfnOutput( 112 | self, 113 | 'TaskDefinitionArn', 114 | value=FargateTask.task_definition_arn 115 | ) 116 | 117 | private_subnets = vpc.select_subnets(subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT) 118 | 119 | CfnOutput( 120 | self, 121 | 'VpcPrivateSubnets', 122 | value=', '.join(map(str, private_subnets.subnet_ids)) 123 | ) 124 | 125 | CfnOutput( 126 | self, 127 | 'VpcDefaultSecurityGroup', 128 | value=vpc.vpc_default_security_group 129 | ) 130 | -------------------------------------------------------------------------------- /602-Image-Scanning-In-ECR/README.md: -------------------------------------------------------------------------------- 1 | # Automatically Scanning Images in ECR for Security 2 | 3 | ## Problem 4 | You want to automatically scan your container images for security vulnerabilities each time you push to a repository. 5 | 6 | ## Solution 7 | Enable automatic image scanning on a repository in Amazon ECR, push an image, and observe the scan results, as shown in Figure 6-5. 8 | 9 | ![Figure 6.5](ContainerImageScanningSolutionWorkflow.png) 10 | 11 | ## Prerequisite 12 | * ECR repository 13 | 14 | ## Preparation 15 | ### Create an ECR repository: 16 | ``` 17 | aws ecr create-repository --repository-name aws-cookbook-repo 18 | ``` 19 | 20 | ## Steps 21 | 1. Rather than building a new container image from a Dockerfile (as you did in Recipe 6.1), this time you are going to pull an old NGINX container image: 22 | ``` 23 | docker pull nginx:1.14.1 24 | ``` 25 | 2. On the command line, apply the scanning configuration to the repository you created: 26 | ``` 27 | REPO=aws-cookbook-repo && \ 28 | aws ecr put-image-scanning-configuration \ 29 | --repository-name $REPO \ 30 | --image-scanning-configuration scanOnPush=true 31 | ``` 32 | 3. Get Docker login information: 33 | ``` 34 | aws ecr get-login-password | docker login --username AWS \ 35 | --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com 36 | ``` 37 | 4. Apply a tag to the image so that you can push it to the ECR repository: 38 | ``` 39 | docker tag nginx:1.14.1 \ 40 | $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-repo:old 41 | ``` 42 | 5. Push the image: 43 | ``` 44 | docker push \ 45 | $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-repo:old 46 | ``` 47 | 48 | ## Validation checks 49 | Shortly after the push is complete, you can examine the results of the security scan of the image in JSON format: 50 | ``` 51 | aws ecr describe-image-scan-findings \ 52 | --repository-name aws-cookbook-repo --image-id imageTag=old 53 | ``` 54 | You should see output similar to the following: 55 | ``` 56 | { 57 | "imageScanFindings": { 58 | "findings": [ 59 | { 60 | "name": "CVE-2019-3462", 61 | "description": "Incorrect sanitation of the 302 redirect field in HTTP 62 | transport method of apt versions 1.4.8 and earlier can lead to content injection by 63 | a MITM attacker, potentially leading to remote code execution on the target 64 | machine.", 65 | "uri": "https://security-tracker.debian.org/tracker/CVE-2019-3462", 66 | "severity": "CRITICAL", 67 | "attributes": [ 68 | { 69 | "key": "package_version", 70 | "value": "1.4.8" 71 | }, 72 | ``` 73 | 74 | ## Clean up 75 | ### Delete the image from your local machine 76 | ``` 77 | docker image rm \ 78 | $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-repo:old 79 | docker image rm nginx:1.14.1 80 | ``` 81 | 82 | ### Delete the image from ECR: 83 | ``` 84 | aws ecr batch-delete-image --repository-name aws-cookbook-repo \ 85 | --image-ids imageTag=old 86 | ``` 87 | 88 | ### Delete the repository: 89 | ``` 90 | aws ecr delete-repository --repository-name aws-cookbook-repo 91 | ``` 92 | 93 | ## Discussion 94 | The [Common Vulnerabilities and Exposures (CVEs)](https://cve.mitre.org/) database from the open source [Clair project](https://github.com/quay/clair) is used by Amazon ECR for [vulnerability scanning](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html). You are provided a Common Vulnerability Scoring System (CVSS) score to indicate the severity of any detected vulnerabilities. This helps you detect and remediate vulnerabilities in your container image. You can configure alerts for newly discovered vulnerabilities in images by using Amazon EventBridge and Amazon Simple Notification Service (Amazon SNS). 95 | 96 | > WARNING: The scanning feature does not continuously scan your images, so it is important to push your image versions routinely (or trigger a manual scan). 97 | 98 | You can retrieve the results of the last scan for an image at any time with the com‐ mand used in the last step of this recipe. Furthermore, you can use these commands as part of an automated CI/CD process that may validate whether or not an image has a certain CVSS score before deploying. 99 | 100 | ### Challenge 1 101 | Remediate the vulnerability by updating the image with the latest NGINX container image. 102 | 103 | ### Challenge 2 104 | Configure an SNS topic to send you an email when vulnerabilities are detected in your repository. 105 | -------------------------------------------------------------------------------- /606-Autoscaling-Container-Workloads/cdk-AWS-Cookbook-606/cdk_aws_cookbook_606/cdk_aws_cookbook_606_stack.py: -------------------------------------------------------------------------------- 1 | from constructs import Construct 2 | from aws_cdk import ( 3 | aws_ec2 as ec2, 4 | aws_ecs as ecs, 5 | aws_elasticloadbalancingv2 as alb, 6 | aws_ecr_assets as ecr_assets, 7 | Stack, 8 | CfnOutput, 9 | Duration 10 | ) 11 | 12 | 13 | class CdkAwsCookbook606Stack(Stack): 14 | 15 | def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: 16 | super().__init__(scope, construct_id, **kwargs) 17 | 18 | ecr_asset = ecr_assets.DockerImageAsset( 19 | self, 20 | 'ecr_asset', 21 | directory='Docker', 22 | ) 23 | 24 | # create VPC 25 | vpc = ec2.Vpc( 26 | self, 27 | 'AWS-Cookbook-VPC' 28 | ) 29 | 30 | InterfaceEndpointSecurityGroup = ec2.SecurityGroup( 31 | self, 32 | 'InterfaceEndpointSecurityGroup', 33 | description='Security Group for the VPC Endpoints', 34 | allow_all_outbound=True, 35 | vpc=vpc 36 | ) 37 | 38 | InterfaceEndpointSecurityGroup.connections.allow_from( 39 | ec2.Peer.ipv4(vpc.vpc_cidr_block), ec2.Port.tcp(443), "Ingress") 40 | 41 | vpc.add_interface_endpoint( 42 | 'CloudWatchLogsEndpoint', 43 | service=ec2.InterfaceVpcEndpointAwsService('logs'), 44 | private_dns_enabled=True, 45 | security_groups=[InterfaceEndpointSecurityGroup], 46 | subnets=ec2.SubnetSelection( 47 | one_per_az=True, 48 | subnet_type=ec2.SubnetType('PRIVATE_WITH_NAT') 49 | ), 50 | ) 51 | 52 | albSecurityGroup = ec2.SecurityGroup( 53 | self, 54 | 'albSecurityGroup', 55 | description='Security Group for the ALB', 56 | allow_all_outbound=True, 57 | vpc=vpc 58 | ) 59 | 60 | albSecurityGroup.add_ingress_rule( 61 | peer=ec2.Peer.ipv4("0.0.0.0/0"), 62 | connection=ec2.Port.tcp(80), 63 | description='Allow HTTP from the world', 64 | remote_rule=False 65 | ) 66 | 67 | fargate_service_security_group = ec2.SecurityGroup( 68 | self, 69 | 'fargate_service_security_group', 70 | description='Security Group for the Fargate Service', 71 | allow_all_outbound=True, 72 | vpc=vpc 73 | ) 74 | 75 | fargate_service_security_group.connections.allow_from( 76 | albSecurityGroup, ec2.Port.tcp(8080), "Ingress") 77 | 78 | # create ECS Cluster 79 | ecs_cluster = ecs.Cluster( 80 | self, 81 | 'AWS-Cookbook-EcsCluster', 82 | vpc=vpc 83 | ) 84 | 85 | FargateTask = ecs.FargateTaskDefinition( 86 | self, 87 | 'FargateTask', 88 | cpu=256, 89 | memory_limit_mib=512, 90 | ) 91 | 92 | ContainerDef = ecs.ContainerDefinition( 93 | self, 94 | 'ContainerDef', 95 | image=ecs.ContainerImage.from_docker_image_asset(ecr_asset), 96 | task_definition=FargateTask, 97 | ) 98 | 99 | ContainerDef.add_port_mappings( 100 | ecs.PortMapping( 101 | container_port=8080 102 | ) 103 | ) 104 | 105 | FargateService = ecs.FargateService( 106 | self, 107 | 'awscookbook606', 108 | cluster=ecs_cluster, 109 | task_definition=FargateTask, 110 | assign_public_ip=False, 111 | desired_count=2, 112 | enable_ecs_managed_tags=False, 113 | max_healthy_percent=100, 114 | min_healthy_percent=0, 115 | platform_version=ecs.FargatePlatformVersion('LATEST'), 116 | security_groups=[fargate_service_security_group], 117 | service_name='AWSCookbook606', 118 | vpc_subnets=ec2.SubnetSelection( 119 | one_per_az=False, 120 | subnet_type=ec2.SubnetType('PRIVATE_WITH_NAT') 121 | ) 122 | ) 123 | 124 | lb = alb.ApplicationLoadBalancer( 125 | self, 126 | 'LB', 127 | vpc=vpc, 128 | deletion_protection=False, 129 | http2_enabled=True, 130 | idle_timeout=Duration.seconds(60), 131 | internet_facing=True, 132 | ip_address_type=alb.IpAddressType('IPV4'), 133 | load_balancer_name='FargateServiceALB', 134 | security_group=albSecurityGroup, 135 | vpc_subnets=ec2.SubnetSelection( 136 | one_per_az=False, 137 | subnet_type=ec2.SubnetType('PUBLIC') 138 | ) 139 | ) 140 | 141 | DefaultTargetGroup = alb.ApplicationTargetGroup( 142 | self, 143 | "DefaultTargetGroup", 144 | deregistration_delay=Duration.seconds(60), 145 | health_check=alb.HealthCheck( 146 | healthy_http_codes='200', 147 | healthy_threshold_count=2, 148 | interval=Duration.seconds(10), 149 | path='/loadtest/healthcheck', 150 | port='traffic-port', 151 | protocol=alb.Protocol('HTTP'), 152 | unhealthy_threshold_count=10 153 | ), 154 | port=80, 155 | vpc=vpc, 156 | target_group_name="DefaultTG", 157 | target_type=alb.TargetType('IP'), 158 | targets=[FargateService] 159 | ) 160 | 161 | alb.ApplicationListener( 162 | self, 163 | 'listener80', 164 | load_balancer=lb, 165 | open=False, 166 | port=80, 167 | protocol=alb.ApplicationProtocol('HTTP'), 168 | default_target_groups=[DefaultTargetGroup] 169 | ) 170 | 171 | CfnOutput( 172 | self, 'LoadBalancerDns', 173 | value=lb.load_balancer_dns_name 174 | ) 175 | 176 | CfnOutput( 177 | self, 'EcsClusterName', 178 | value=ecs_cluster.cluster_name 179 | ) 180 | 181 | CfnOutput( 182 | self, 183 | 'EcrImage', 184 | value=ecr_asset.image_uri 185 | ) 186 | -------------------------------------------------------------------------------- /607-Fargate-Task-With-Event/README.md: -------------------------------------------------------------------------------- 1 | # Launching a Fargate container task in response to an event 2 | 3 | ## Problem 4 | You need to launch a container task to process incoming files. 5 | 6 | ![Figure 6.12](LaunchingFargateTaskOnEvent.png) 7 | 8 | ### Prerequisites 9 | * Amazon Virtual Private Cloud (VPC) with isolated or private subnets and associated route tables 10 | * Two Simple Storage Service (S3) Buckets 11 | * CloudTrail Enabled 12 | * An Elastic Container Service (ECS) Cluster for Fargate, a Fargate Task Definition, and a Container Definition 13 | * AWS CLI v2 14 | 15 | > TIP: These prerequisites are all included in the CDK code associated with this recipe. 16 | 17 | ## Preparation 18 | ### This recipe requires some “prep work” which deploys resources that you’ll build the solution on. You will use the AWS CDK to deploy these resources 19 | 20 | ### In the root of this Chapter’s repo cd to the “607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607” directory and follow the subsequent steps: 21 | ``` 22 | cd 607-Fargate-Task-With-Event/cdk-AWS-Cookbook-607/ 23 | test -d .venv || python3 -m venv .venv 24 | source .venv/bin/activate 25 | pip install --upgrade pip 26 | pip install -r requirements.txt 27 | cdk deploy 28 | ``` 29 | 30 | ### Wait for the cdk deploy command to complete. 31 | 32 | ### We created a helper.py script to let you easily create and export environment variables to make subsequent commands easier. Run the script, and copy the output to your terminal to export variables: 33 | 34 | `python helper.py` 35 | 36 | ### Navigate up to the main directory for this recipe (out of the “cdk-AWS-Cookbook-607” directory) 37 | 38 | `cd ..` 39 | 40 | ## Steps 41 | 1. Configure CloudTrail to log events on the S3 bucket: 42 | ``` 43 | aws cloudtrail put-event-selectors --trail-name $CLOUD_TRAIL_ARN --event-selectors "[{ \"ReadWriteType\": 44 | \"WriteOnly\", \"IncludeManagementEvents\":false, \"DataResources\": [{ \"Type\": \"AWS::S3::Object\", 45 | \"Values\": [\"arn:aws:s3:::$BUCKET_NAME/input/\"] }], \"ExcludeManagementEventSources\": [] }]" 46 | ``` 47 | 48 | 2. Create an assume-role policy JSON statement called policy1.json to use in the next step (this file is provided in the repository) and create the role: 49 | ``` 50 | { 51 | "Version": "2012-10-17", 52 | "Statement": [ 53 | { 54 | "Effect": "Allow", 55 | "Principal": { 56 | "Service": "events.amazonaws.com" 57 | }, 58 | "Action": "sts:AssumeRole" 59 | } 60 | ] 61 | } 62 | ``` 63 | 64 | ``` 65 | aws iam create-role --role-name AWSCookbook607RuleRole \ 66 | --assume-role-policy-document file://policy1.json 67 | ``` 68 | 69 | 3. You will also need a policy document with the following content called policy2.json (this file is provided in the repository): 70 | ``` 71 | { 72 | "Version": "2012-10-17", 73 | "Statement": [ 74 | { 75 | "Effect": "Allow", 76 | "Action": [ 77 | "ecs:RunTask" 78 | ], 79 | "Resource": [ 80 | "arn:aws:ecs:*:*:task-definition/*" 81 | ] 82 | }, 83 | { 84 | "Effect": "Allow", 85 | "Action": "iam:PassRole", 86 | "Resource": [ 87 | "*" 88 | ], 89 | "Condition": { 90 | "StringLike": { 91 | "iam:PassedToService": "ecs-tasks.amazonaws.com" 92 | } 93 | } 94 | } 95 | ] 96 | } 97 | ``` 98 | 99 | 4. Now attach the IAM policy JSON you just created to the IAM role: 100 | 101 | ``` 102 | aws iam put-role-policy --role-name AWSCookbook607RuleRole \ 103 | --policy-name ECSRunTaskPermissionsForEvents \ 104 | --policy-document file://policy2.json 105 | ``` 106 | 107 | 5. Create an EventBridge rule that monitors the S3 bucket for file uploads: 108 | 109 | ``` 110 | aws events put-rule --name "AWSCookbookRule" --role-arn "arn:aws:iam::$AWS_ACCOUNT_ID:role/AWSCookbook607RuleRole" --event-pattern "{\"source\":[\"aws.s3\"],\"detail-type\":[\"AWS API Call via CloudTrail\"],\"detail\":{\"eventSource\":[\"s3.amazonaws.com\"],\"eventName\":[\"CopyObject\",\"PutObject\",\"CompleteMultipartUpload\"],\"requestParameters\":{\"bucketName\":[\"$BUCKET_NAME\"]}}}" 111 | ``` 112 | 113 | 6. Modify the value in targets-template.json and create a targets.json for use: 114 | 115 | ``` 116 | sed -e "s|AWS_ACCOUNT_ID|${AWS_ACCOUNT_ID}|g" \ 117 | -e "s|AWS_REGION|${AWS_REGION}|g" \ 118 | -e "s|ECSClusterARN|${ECS_CLUSTER_ARN}|g" \ 119 | -e "s|TaskDefinitionARN|${TASK_DEFINITION_ARN}|g" \ 120 | -e "s|VPCPrivateSubnets|${VPC_PRIVATE_SUBNETS}|g" \ 121 | -e "s|VPCDefaultSecurityGroup|${VPC_DEFAULT_SECURITY_GROUP}|g" \ 122 | targets-template.json > targets.json 123 | ``` 124 | 125 | 7. Create a rule target that specifies the ECS cluster, ECS task definition, IAM role, and networking parameters. This specifies what the rule will trigger; in this case, launch a container on Fargate: 126 | 127 | ``` 128 | aws events put-targets --rule AWSCookbookRule \ 129 | --targets file://targets.json 130 | ``` 131 | 132 | 8. Check the S3 bucket to verify that it’s empty before we populate it: 133 | 134 | `aws s3 ls s3://$BUCKET_NAME/` 135 | 136 | 9. Copy the provided maze.jpg file to the S3 bucket. This will trigger the ECS task that launches a container with a Python library to process the file: 137 | 138 | 139 | `aws s3 cp maze.jpg s3://$BUCKET_NAME/input/maze.jpg` 140 | 141 | This will trigger an ECS task to process the image file. Quickly, check the task with the ecs list-tasks command. The task will run for about two to three minutes: 142 | 143 | `aws ecs list-tasks --cluster $ECS_CLUSTER_ARN` 144 | 145 | ## Validation checks 146 | 147 | After a few minutes, observe the output directory created in the S3 bucket: 148 | 149 | `aws s3 ls s3://$BUCKET_NAME/output/` 150 | 151 | Download and view the output file: 152 | 153 | `aws s3 cp s3://$BUCKET_NAME/output/output.jpg ./output.jpg` 154 | 155 | Open output.jpg with a file viewer of your choice to view the file that was processed. 156 | 157 | 158 | ## Clean up 159 | ### Remove the EventBridge targets from the EventBridge rule: 160 | 161 | `aws events remove-targets --rule AWSCookbookRule --ids AWSCookbookRuleID` 162 | 163 | ### Delete the EventBridge rule: 164 | 165 | `aws events delete-rule --name "AWSCookbookRule"` 166 | 167 | ### Detach the policies and delete the EventBridge Rule IAM role: 168 | ``` 169 | aws iam delete-role-policy --role-name AWSCookbook607RuleRole \ 170 | --policy-name ECSRunTaskPermissionsForEvents 171 | 172 | aws iam delete-role --role-name AWSCookbook607RuleRole 173 | ``` 174 | 175 | ### Stop the Cloudtrail 176 | 177 | `aws cloudtrail stop-logging --name $CLOUD_TRAIL_ARN` 178 | 179 | ### Go to the cdk-AWS-Cookbook-607 directory 180 | 181 | `cd cdk-AWS-Cookbook-607/` 182 | 183 | ### To clean up the environment variables, run the helper.py script in this recipe’s cdk- directory with the --unset flag, and copy the output to your terminal to export variables: 184 | 185 | `python helper.py --unset` 186 | 187 | ### Use the AWS CDK to destroy the resources, deactivate your Python virtual environment, and go to the root of the chapter: 188 | 189 | `cdk destroy && deactivate && rm -r .venv/ && cd ../..` 190 | 191 | ## Discussion 192 | 193 | Event-driven architecture is an important approach to application and process design in the cloud. This type of design allows for removing long-running application workloads in favor of serverless architectures, which can be more resilient and easily scale to peaks of higher usage when needed. When there are no events to handle in your application, you generally do not pay much for compute resources (if at all), so potential cost savings is also a point to consider when choosing an application architecture. 194 | 195 | > NOTE: It is common to use Lambda functions with S3 for event-driven architectures, but for longer-running data-processing jobs and computational jobs like this one, Fargate is a better choice because the runtime is essentially infinite, while the maximum runtime for Lambda functions is limited. 196 | 197 | Amazon ECS can run tasks and services. Services are made up of tasks, and generally, are long-running in that a service keeps a specific set of tasks running. Tasks can be short-lived; a container may start, process some data, and then gracefully exit after the task is complete. This is what you have achieved in this solution: a task was launched in response to an S3 event signaling a new object, and the container read the object, processed the file, and exited. 198 | 199 | ### Challenge 200 | 201 | While EventBridge is a powerful solution that can be used to orchestrate many types of event-driven solutions, you can achieve similar functionality with S3’s triggers. Try to deploy and configure a Lambda function to be invoked directly from S3 events. [Here is a hint](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html) 202 | 203 | 204 | -------------------------------------------------------------------------------- /605-Updating-Containers-With-BlueGreen/cdk-AWS-Cookbook-605/cdk_aws_cookbook_605/cdk_aws_cookbook_605_stack.py: -------------------------------------------------------------------------------- 1 | from constructs import Construct 2 | from aws_cdk import ( 3 | aws_ec2 as ec2, 4 | aws_ecs as ecs, 5 | aws_s3 as s3, 6 | aws_ecr_assets as ecr_assets, 7 | aws_elasticloadbalancingv2 as alb, 8 | Stack, 9 | CfnOutput, 10 | Duration, 11 | RemovalPolicy 12 | ) 13 | 14 | 15 | class CdkAwsCookbook605Stack(Stack): 16 | 17 | def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: 18 | super().__init__(scope, construct_id, **kwargs) 19 | 20 | ecr_asset_blue = ecr_assets.DockerImageAsset( 21 | self, 22 | 'ecr_asset_blue', 23 | directory='DockerBlue', 24 | ) 25 | 26 | ecr_asset_green = ecr_assets.DockerImageAsset( 27 | self, 28 | 'ecr_asset_green', 29 | directory='DockerGreen', 30 | ) 31 | 32 | # create VPC 33 | vpc = ec2.Vpc( 34 | self, 35 | 'AWS-Cookbook-VPC' 36 | ) 37 | 38 | albSecurityGroup = ec2.SecurityGroup( 39 | self, 40 | 'albSecurityGroup', 41 | description='Security Group for the ALB', 42 | allow_all_outbound=True, 43 | vpc=vpc 44 | ) 45 | 46 | albSecurityGroup.add_ingress_rule( 47 | peer=ec2.Peer.ipv4("0.0.0.0/0"), 48 | connection=ec2.Port.tcp(80), 49 | description='Allow HTTP from the world', 50 | remote_rule=False 51 | ) 52 | 53 | albSecurityGroup.add_ingress_rule( 54 | peer=ec2.Peer.ipv4("0.0.0.0/0"), 55 | connection=ec2.Port.tcp(8080), 56 | description='Allow 8080 from the world', 57 | remote_rule=False 58 | ) 59 | 60 | fargate_service_security_group = ec2.SecurityGroup( 61 | self, 62 | 'fargate_service_security_group', 63 | description='Security Group for the Fargate Service', 64 | allow_all_outbound=True, 65 | vpc=vpc 66 | ) 67 | 68 | fargate_service_security_group.connections.allow_from( 69 | albSecurityGroup, ec2.Port.tcp(80), "Ingress") 70 | 71 | # create ECS Cluster 72 | ecs_cluster = ecs.Cluster( 73 | self, 74 | 'AWS-Cookbook-EcsCluster', 75 | cluster_name='awscookbook605', 76 | vpc=vpc 77 | ) 78 | 79 | FargateTaskBlue = ecs.FargateTaskDefinition( 80 | self, 81 | 'FargateTaskBlue', 82 | cpu=256, 83 | memory_limit_mib=512, 84 | ) 85 | 86 | ContainerDefBlue = ecs.ContainerDefinition( 87 | self, 88 | 'ContainerDefBlue', 89 | image=ecs.ContainerImage.from_docker_image_asset(ecr_asset_blue), 90 | task_definition=FargateTaskBlue, 91 | ) 92 | 93 | ContainerDefBlue.add_port_mappings( 94 | ecs.PortMapping( 95 | container_port=80 96 | ) 97 | ) 98 | 99 | FargateTaskGreen = ecs.FargateTaskDefinition( 100 | self, 101 | 'FargateTaskGreen', 102 | cpu=256, 103 | memory_limit_mib=512, 104 | ) 105 | 106 | ContainerDefGreen = ecs.ContainerDefinition( 107 | self, 108 | 'ContainerDefGreen', 109 | image=ecs.ContainerImage.from_docker_image_asset(ecr_asset_green), 110 | task_definition=FargateTaskGreen, 111 | ) 112 | 113 | ContainerDefGreen.add_port_mappings( 114 | ecs.PortMapping( 115 | container_port=80 116 | ) 117 | ) 118 | 119 | FargateService = ecs.FargateService( 120 | self, 121 | 'awscookbook605', 122 | cluster=ecs_cluster, 123 | task_definition=FargateTaskBlue, 124 | assign_public_ip=False, 125 | desired_count=2, 126 | enable_ecs_managed_tags=False, 127 | # health_check_grace_period=Duration.seconds(60), 128 | max_healthy_percent=100, 129 | min_healthy_percent=0, 130 | platform_version=ecs.FargatePlatformVersion('LATEST'), 131 | security_groups=[fargate_service_security_group], 132 | service_name='AWSCookbook605', 133 | deployment_controller=ecs.DeploymentController( 134 | type=ecs.DeploymentControllerType('CODE_DEPLOY') 135 | ), 136 | vpc_subnets=ec2.SubnetSelection( 137 | one_per_az=False, 138 | subnet_type=ec2.SubnetType('PRIVATE_WITH_NAT') 139 | ) 140 | ) 141 | 142 | lb = alb.ApplicationLoadBalancer( 143 | self, 144 | 'LB', 145 | vpc=vpc, 146 | deletion_protection=False, 147 | http2_enabled=True, 148 | idle_timeout=Duration.seconds(60), 149 | internet_facing=True, 150 | ip_address_type=alb.IpAddressType('IPV4'), 151 | load_balancer_name='FargateServiceALB', 152 | security_group=albSecurityGroup, 153 | vpc_subnets=ec2.SubnetSelection( 154 | one_per_az=False, 155 | subnet_type=ec2.SubnetType('PUBLIC') 156 | ) 157 | ) 158 | 159 | DefaultTargetGroup = alb.ApplicationTargetGroup( 160 | self, 161 | "DefaultTargetGroup", 162 | port=80, 163 | vpc=vpc, 164 | target_group_name="DefaultTG", 165 | target_type=alb.TargetType('IP'), 166 | ) 167 | 168 | listener80 = alb.ApplicationListener( 169 | self, 170 | 'listener80', 171 | load_balancer=lb, 172 | open=False, 173 | port=80, 174 | protocol=alb.ApplicationProtocol('HTTP'), 175 | default_target_groups=[DefaultTargetGroup] 176 | ) 177 | 178 | BlueTargetGroup = listener80.add_targets( 179 | 'BlueTargetGroup', 180 | conditions=[alb.ListenerCondition.http_header( 181 | name="All", 182 | values=['*.*.*'], 183 | )], 184 | deregistration_delay=Duration.seconds(60), 185 | health_check=alb.HealthCheck( 186 | healthy_http_codes='200', 187 | healthy_threshold_count=2, 188 | interval=Duration.seconds(10), 189 | path='/', 190 | port='traffic-port', 191 | protocol=alb.Protocol('HTTP'), 192 | unhealthy_threshold_count=2 193 | ), 194 | port=80, 195 | priority=1, 196 | protocol=alb.ApplicationProtocol('HTTP'), 197 | target_group_name="BlueTG", 198 | targets=[FargateService] 199 | ) 200 | 201 | listener8080 = alb.ApplicationListener( 202 | self, 203 | 'listener8080', 204 | load_balancer=lb, 205 | open=False, 206 | port=8080, 207 | protocol=alb.ApplicationProtocol('HTTP'), 208 | default_target_groups=[BlueTargetGroup] 209 | ) 210 | 211 | # create s3 bucket 212 | s3_Bucket = s3.Bucket( 213 | self, 214 | "AWS-Cookbook-Recipe605", 215 | removal_policy=RemovalPolicy.DESTROY, 216 | auto_delete_objects=True 217 | ) 218 | 219 | # outputs 220 | 221 | CfnOutput( 222 | self, 223 | 'BlueImage', 224 | value=ecr_asset_blue.image_uri 225 | ) 226 | 227 | CfnOutput( 228 | self, 229 | 'GreenImage', 230 | value=ecr_asset_green.image_uri 231 | ) 232 | 233 | CfnOutput( 234 | self, 235 | 'VpcId', 236 | value=vpc.vpc_id 237 | ) 238 | 239 | CfnOutput( 240 | self, 241 | 'LoadBalancerDns', 242 | value=lb.load_balancer_dns_name 243 | ) 244 | 245 | CfnOutput( 246 | self, 247 | 'EcsClusterName', 248 | value=ecs_cluster.cluster_name 249 | ) 250 | 251 | public_subnets = vpc.select_subnets(subnet_type=ec2.SubnetType.PUBLIC) 252 | 253 | CfnOutput( 254 | self, 255 | 'VpcPublicSubnets', 256 | value=', '.join(map(str, public_subnets.subnet_ids)) 257 | ) 258 | 259 | CfnOutput( 260 | self, 261 | 'VpcDefaultSecurityGroup', 262 | value=vpc.vpc_default_security_group 263 | ) 264 | 265 | CfnOutput( 266 | self, 267 | 'BucketName', 268 | value=s3_Bucket.bucket_name 269 | ) 270 | 271 | CfnOutput( 272 | self, 273 | 'BlueTargetGroupName', 274 | value=BlueTargetGroup.target_group_arn 275 | ) 276 | 277 | CfnOutput( 278 | self, 279 | 'ProdListenerArn', 280 | value=listener80.listener_arn 281 | ) 282 | 283 | CfnOutput( 284 | self, 285 | 'TestListenerArn', 286 | value=listener8080.listener_arn 287 | ) 288 | 289 | CfnOutput( 290 | self, 291 | 'DefaultTargetGroupArn', 292 | value=DefaultTargetGroup.target_group_arn 293 | ) 294 | 295 | CfnOutput( 296 | self, 297 | 'FargateTaskBlueArn', 298 | value=FargateTaskBlue.task_definition_arn 299 | ) 300 | 301 | CfnOutput( 302 | self, 303 | 'FargateTaskGreenArn', 304 | value=FargateTaskGreen.task_definition_arn 305 | ) 306 | --------------------------------------------------------------------------------