├── backups ├── .env ├── cdk.json ├── tsconfig.json ├── package.json └── index.ts ├── batch ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json ├── lambdaHandler.js └── index.ts ├── docdb-lambda-api ├── .gitignore ├── cdk.json ├── .env ├── README.md ├── src │ ├── package.json │ ├── getLongURL.ts │ ├── urlShortener.ts │ └── lib.ts ├── tsconfig.json ├── package.json └── index.ts ├── sagemaker ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── ec2-basics ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── ec2-jenkins ├── .env ├── cdk.json ├── tsconfig.json ├── package.json ├── README.md ├── lib.ts └── index.ts ├── ecs-go-api ├── .env ├── cdk.json ├── api │ ├── go.mod │ ├── go.sum │ ├── Dockerfile │ └── main.go ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── eks-cluster ├── .env ├── graphql-api │ ├── start │ ├── Dockerfile │ ├── package.json │ └── app.js ├── cdk.json ├── go-api │ ├── go.mod │ ├── go.sum │ ├── Dockerfile │ └── main.go ├── package.json ├── tsconfig.json ├── README.md ├── templates.ts └── index.ts ├── elb-lambda-api ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json ├── index.ts └── lambda-handler.py ├── empty-template ├── .env ├── cdk.json ├── index.ts ├── package.json └── tsconfig.json ├── rds-proxy ├── cdk.json ├── .env ├── src │ ├── lib.js │ ├── package.json │ └── handler.js ├── package.json ├── tsconfig.json └── index.ts ├── serverless-eks ├── .env ├── graphql-api │ ├── start │ ├── Dockerfile │ ├── package.json │ └── app.js ├── cdk.json ├── go-api │ ├── go.mod │ ├── go.sum │ ├── Dockerfile │ └── main.go ├── package.json ├── tsconfig.json ├── templates.ts ├── README.md └── index.ts ├── cognito-userpool ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── keyspaces-cassandra ├── .env ├── cdk.json ├── package.json ├── tsconfig.json └── index.ts ├── lambda-functionURL ├── .env ├── cdk.json ├── src │ └── lambdaHandler.mjs ├── package.json ├── tsconfig.json └── index.ts ├── lambda-python-api ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json ├── lib.ts ├── index.ts └── lambda-handler.py ├── sqs-lambda-dynamodb ├── .env ├── cdk.json ├── package.json ├── tsconfig.json ├── README.md ├── lambdaHandler.js └── index.ts ├── transit-gateway ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── wordpress-ha ├── cdk.json ├── README.md ├── .env ├── package.json ├── tsconfig.json └── index.ts ├── dynamo-streams-lambda ├── .env ├── cdk.json ├── README.md ├── stream-handler.py ├── package.json ├── tsconfig.json └── index.ts ├── elasticsearch-cluster ├── .env ├── cdk.json ├── README.md ├── package.json ├── tsconfig.json └── index.ts ├── assets ├── sagemaker1.png ├── sagemaker2.png ├── lambda-api-python.png └── sqs-lambda-dynamo.png ├── .gitignore └── README.md /backups/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /batch/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /docdb-lambda-api/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | *.d.ts 3 | *.pem 4 | -------------------------------------------------------------------------------- /sagemaker/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /backups/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /batch/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /ec2-basics/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /ec2-jenkins/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /ecs-go-api/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /eks-cluster/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /eks-cluster/graphql-api/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | npm start -------------------------------------------------------------------------------- /elb-lambda-api/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /empty-template/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /rds-proxy/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /sagemaker/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /serverless-eks/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /serverless-eks/graphql-api/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | npm start -------------------------------------------------------------------------------- /cognito-userpool/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /ec2-basics/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /ec2-jenkins/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /ecs-go-api/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /eks-cluster/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /elb-lambda-api/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /empty-template/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /keyspaces-cassandra/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /lambda-functionURL/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /lambda-python-api/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /serverless-eks/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /transit-gateway/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /wordpress-ha/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /cognito-userpool/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /docdb-lambda-api/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /dynamo-streams-lambda/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /elasticsearch-cluster/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" -------------------------------------------------------------------------------- /keyspaces-cassandra/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /lambda-functionURL/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /lambda-python-api/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /transit-gateway/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /dynamo-streams-lambda/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /elasticsearch-cluster/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node index" 3 | } 4 | -------------------------------------------------------------------------------- /docdb-lambda-api/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" 3 | MASTER_USER_PASSWORD="" -------------------------------------------------------------------------------- /assets/sagemaker1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TysonWorks/cdk-examples/HEAD/assets/sagemaker1.png -------------------------------------------------------------------------------- /assets/sagemaker2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TysonWorks/cdk-examples/HEAD/assets/sagemaker2.png -------------------------------------------------------------------------------- /rds-proxy/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="" 3 | DB_USER="myuser" 4 | DB_PORT="3306" 5 | DB_NAME="proxy" -------------------------------------------------------------------------------- /assets/lambda-api-python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TysonWorks/cdk-examples/HEAD/assets/lambda-api-python.png -------------------------------------------------------------------------------- /assets/sqs-lambda-dynamo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TysonWorks/cdk-examples/HEAD/assets/sqs-lambda-dynamo.png -------------------------------------------------------------------------------- /wordpress-ha/README.md: -------------------------------------------------------------------------------- 1 | # Wordpress on AWS 2 | 3 | Highly available, horizontally scalable Wordpress installation using ECS and RDS. -------------------------------------------------------------------------------- /ecs-go-api/api/go.mod: -------------------------------------------------------------------------------- 1 | module cdk-examples/typescript/ecs-go-api/api 2 | 3 | go 1.12 4 | 5 | require github.com/gorilla/mux v1.7.2 6 | -------------------------------------------------------------------------------- /wordpress-ha/.env: -------------------------------------------------------------------------------- 1 | AWS_ACCOUNT_ID="" 2 | AWS_REGION="us-east-1" 3 | DB_USER="" 4 | DB_PASSWORD="" 5 | DB_PORT="3306" 6 | DB_NAME="wordpress" -------------------------------------------------------------------------------- /batch/README.md: -------------------------------------------------------------------------------- 1 | ## AWS Batch 2 | 3 | ### Accompanying blog post 4 | https://medium.com/tysonworks/manage-batch-jobs-with-aws-batch-1f91229b1b6e -------------------------------------------------------------------------------- /eks-cluster/go-api/go.mod: -------------------------------------------------------------------------------- 1 | module cdk-examples/typescript/ecs-go-api/api 2 | 3 | go 1.12 4 | 5 | require github.com/gorilla/mux v1.7.2 6 | -------------------------------------------------------------------------------- /serverless-eks/go-api/go.mod: -------------------------------------------------------------------------------- 1 | module cdk-examples/typescript/ecs-go-api/api 2 | 3 | go 1.12 4 | 5 | require github.com/gorilla/mux v1.7.2 6 | -------------------------------------------------------------------------------- /cognito-userpool/README.md: -------------------------------------------------------------------------------- 1 | ## Cognito User Pool 2 | 3 | This example will deploy a Cognito User Pool and User Pool Client for interacting with the User Pool. -------------------------------------------------------------------------------- /rds-proxy/src/lib.js: -------------------------------------------------------------------------------- 1 | function sleep(ms) { 2 | return new Promise(resolve => setTimeout(resolve, ms)); 3 | } 4 | 5 | module.exports = { 6 | sleep 7 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | cdk.context.json 4 | package-lock.json 5 | __pycache__ 6 | *~ 7 | .vscode 8 | node_modules 9 | .cdk.staging 10 | cdk.out 11 | notes.txt 12 | -------------------------------------------------------------------------------- /ecs-go-api/api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= 2 | github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 3 | -------------------------------------------------------------------------------- /eks-cluster/go-api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= 2 | github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 3 | -------------------------------------------------------------------------------- /serverless-eks/go-api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= 2 | github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 3 | -------------------------------------------------------------------------------- /ec2-basics/README.md: -------------------------------------------------------------------------------- 1 | ## EC2 Basics 2 | This example will deploy a EC2 instance to a new VPC and default public subnet. It will also create a new security group with SSH access and it will use the latest AMAZON Linux AMI. -------------------------------------------------------------------------------- /eks-cluster/graphql-api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY . . 6 | 7 | RUN npm i npm@latest -g 8 | RUN npm install --only=production 9 | 10 | EXPOSE 8090 11 | 12 | ENTRYPOINT ["/bin/sh", "start"] -------------------------------------------------------------------------------- /serverless-eks/graphql-api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY . . 6 | 7 | RUN npm i npm@latest -g 8 | RUN npm install --only=production 9 | 10 | EXPOSE 8090 11 | 12 | ENTRYPOINT ["/bin/sh", "start"] -------------------------------------------------------------------------------- /dynamo-streams-lambda/README.md: -------------------------------------------------------------------------------- 1 | ## DynamoDB Streams with Lambda 2 | This example will deploy a Lambda function written in Python and a DynamoDB table. Lambda function will get invoked by the changes to DynamoDB table using DynamoDB streams. -------------------------------------------------------------------------------- /docdb-lambda-api/README.md: -------------------------------------------------------------------------------- 1 | ## URL Shortener with DocumentDB, Lambda and API Gateway 2 | 3 | This example will deploy a DocumentDB cluster and Lambda functions exposed via API Gateway. 4 | 5 | ### Accompanying blog post 6 | https://medium.com/tysonworks/create-and-deploy-simple-url-shortener-with-aws-cdk-and-documentdb-875ab99d51f5 7 | -------------------------------------------------------------------------------- /lambda-functionURL/src/lambdaHandler.mjs: -------------------------------------------------------------------------------- 1 | export async function handler(event, context, callback) { 2 | try { 3 | console.log("Event:", JSON.stringify(event)); 4 | return callback(null, "Hello, function URL."); 5 | } catch(err) { 6 | console.error("Error", err); 7 | return callback("Error"); 8 | } 9 | } -------------------------------------------------------------------------------- /rds-proxy/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "src", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "handler.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "mysql": "^2.18.1", 11 | "mysql2": "^2.1.0" 12 | }, 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /dynamo-streams-lambda/stream-handler.py: -------------------------------------------------------------------------------- 1 | def handler(event, context): 2 | for record in event["Records"]: 3 | if "NewImage" in record["dynamodb"]: 4 | print("New image {}".format(record["dynamodb"]["NewImage"])) 5 | if "OldImage" in record["dynamodb"]: 6 | print("Old image {}".format(record["dynamodb"]["OldImage"])) 7 | return "done" -------------------------------------------------------------------------------- /sagemaker/README.md: -------------------------------------------------------------------------------- 1 | ## Sagemaker Notebook Example 2 | This example will deploy a VPC, Security Group, IAM Role and a Sagemaker Notebook instance. 3 | 4 | After the successful deployment, head over to the Sagemaker console 5 | 6 | 7 | Click Open Jupyter Button to launch Jupyter notebook 8 | -------------------------------------------------------------------------------- /ecs-go-api/api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Multi-stage layout 2 | FROM golang:1.12 as builder 3 | 4 | ENV GO111MODULE=on 5 | 6 | WORKDIR /app 7 | 8 | COPY go.mod . 9 | COPY go.sum . 10 | 11 | RUN go mod download 12 | 13 | COPY . . 14 | 15 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build 16 | 17 | FROM scratch 18 | COPY --from=builder /app/api /app/ 19 | EXPOSE 8080 20 | ENTRYPOINT ["/app/api"] -------------------------------------------------------------------------------- /eks-cluster/go-api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Multi-stage layout 2 | FROM golang:1.12 as builder 3 | 4 | ENV GO111MODULE=on 5 | 6 | WORKDIR /app 7 | 8 | COPY go.mod . 9 | COPY go.sum . 10 | 11 | RUN go mod download 12 | 13 | COPY . . 14 | 15 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build 16 | 17 | FROM scratch 18 | COPY --from=builder /app/api /app/ 19 | EXPOSE 8080 20 | ENTRYPOINT ["/app/api"] -------------------------------------------------------------------------------- /serverless-eks/go-api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Multi-stage layout 2 | FROM golang:1.12 as builder 3 | 4 | ENV GO111MODULE=on 5 | 6 | WORKDIR /app 7 | 8 | COPY go.mod . 9 | COPY go.sum . 10 | 11 | RUN go mod download 12 | 13 | COPY . . 14 | 15 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build 16 | 17 | FROM scratch 18 | COPY --from=builder /app/api /app/ 19 | EXPOSE 8080 20 | ENTRYPOINT ["/app/api"] -------------------------------------------------------------------------------- /eks-cluster/graphql-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node app.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "apollo-server-express": "^2.9.3", 14 | "express": "^4.17.1", 15 | "helmet": "^3.21.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /serverless-eks/graphql-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node app.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "apollo-server-express": "^2.9.3", 14 | "express": "^4.17.1", 15 | "helmet": "^3.21.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docdb-lambda-api/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "src", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "getLongURL.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "mongodb": "^3.3.0-beta2", 14 | "shortid": "^2.2.14" 15 | }, 16 | "devDependencies": { 17 | "@types/shortid": "0.0.29" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ecs-go-api/README.md: -------------------------------------------------------------------------------- 1 | ## ECS GO API Example 2 | 3 | For this example, you have to bootstrap the CDK project for building and pushing the local container image to ECR. 4 | 5 | After installing the dependencies and setting up the environment variables, run 6 | `cdk bootstrap` 7 | 8 | You can deploy the stack after the bootstrap step 9 | `cdk deploy` 10 | 11 | ### Accompanying blog post 12 | https://medium.com/tysonworks/deploy-go-applications-to-ecs-using-aws-cdk-1a97d85bb4cb 13 | -------------------------------------------------------------------------------- /elb-lambda-api/README.md: -------------------------------------------------------------------------------- 1 | ## Elastic Load Balancer Lambda API 2 | This example will deploy a Lambda function written in Python and Application Load Balancer using Lambda Function as a target. Lambda function will return a random poem from external API (http://poetrydb.org) as a JSON response. 3 | 4 | 5 | After the successful deployment you will get an url similiar to this. 6 | `Lambd-alb8A-1OC475PK74UO8-801587863.us-west-1.elb.amazonaws.com` 7 | 8 | 9 | Hit the URL and you should get a successful JSON response. 10 | -------------------------------------------------------------------------------- /empty-template/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import { config } from "dotenv"; 3 | import { Construct } from "constructs"; 4 | config(); 5 | 6 | class EmptyStack extends cdk.Stack { 7 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 8 | super(scope, id, props); 9 | } 10 | } 11 | 12 | const app = new cdk.App(); 13 | new EmptyStack(app, "EmptyStack", { 14 | env: { 15 | account: process.env.AWS_ACCOUNT_ID, 16 | region: process.env.AWS_REGION 17 | } 18 | }); -------------------------------------------------------------------------------- /lambda-python-api/README.md: -------------------------------------------------------------------------------- 1 | ## Lambda API Gateway 2 | This example will deploy a Lambda function written in Python and API Gateway with one resource. Lambda function will return one random poem from external API (http://poetrydb.org) as a JSON response. 3 | 4 | 5 | 6 | 7 | After the successful deployment you will get an url similiar to this. 8 | `https://ygnbp5okp4.execute-api.us-west-1.amazonaws.com/prod/` 9 | 10 | Append `poems` to this url and try to reach it. You'll get a poem with details as a JSON response. -------------------------------------------------------------------------------- /transit-gateway/README.md: -------------------------------------------------------------------------------- 1 | ## Transit Gateway 2 | This example will demonstrate the Transit Gateway offering from AWS. This stack will create three different VPCs, three different instances in those VPCs and a Transit Gateway with necessary resources to connect these networks. 3 | 4 | Two of the instances will include the user-data script, which includes Nginx installation and starting the Nginx service. We will connect to the second instance via EC2 Instance Connect on the EC2 console, then we will try to reach private DNS addresses of the other two instances(instance1 and instance3) via curl command, which should work as expected. -------------------------------------------------------------------------------- /ec2-basics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ec2-basics", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk" 8 | }, 9 | "devDependencies": { 10 | "aws-cdk": "2.53.0", 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "jest": "^27.5.1", 16 | "ts-jest": "^27.1.4", 17 | "ts-node": "^10.9.1", 18 | "typescript": "~3.9.7" 19 | }, 20 | "dependencies": { 21 | "aws-cdk-lib": "2.53.0", 22 | "constructs": "^10.0.0", 23 | "dotenv": "^8.2.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /batch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "batch", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sagemaker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sagemaker", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } -------------------------------------------------------------------------------- /ecs-go-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecs-go-api", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /elasticsearch-cluster/README.md: -------------------------------------------------------------------------------- 1 | ## ElasticSearch Cluster 2 | This example will deploy an ElasticSearch cluster using AWS CDK. 3 | 4 | 5 | For enabling VPC, you need to comment out necessary lines and create a VPN connection to VPC for interacting with Kibana and ElasticSearch API. 6 | 7 | 8 | After the successful deployment you will get an output similiar to this. 9 | 10 | ```ElasticSearchStack.domain = search-es-domain-zq3r5qgq2b5ecvctp7pry6vupu.us-east-1.es.amazonaws.com``` 11 | ```ElasticSearchStack.kibana = search-es-domain-zq3r5qgq2b5ecvctp7pry6vupu.us-east-1.es.amazonaws.com/_plugin/kibana/``` 12 | 13 | Go to Kibana URL, you should see the Kibana setup page. 14 | -------------------------------------------------------------------------------- /rds-proxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rds-proxy", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cognito-userpool/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cognito-userpool", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "aws-cdk": "2.53.0", 12 | "@types/babel__traverse": "7.18.2", 13 | "@types/jest": "^27.5.2", 14 | "@types/node": "10.17.27", 15 | "@types/prettier": "2.6.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } -------------------------------------------------------------------------------- /eks-cluster/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eks-cluster", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /empty-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "empty-template", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "aws-cdk": "2.53.0", 12 | "@types/babel__traverse": "7.18.2", 13 | "@types/jest": "^27.5.2", 14 | "@types/node": "10.17.27", 15 | "@types/prettier": "2.6.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } -------------------------------------------------------------------------------- /wordpress-ha/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wordpress-ha", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /elb-lambda-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elb-lambda-api", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lambda-functionURL/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda-functionURL", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "aws-cdk": "2.53.0", 12 | "@types/babel__traverse": "7.18.2", 13 | "@types/jest": "^27.5.2", 14 | "@types/node": "10.17.27", 15 | "@types/prettier": "2.6.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } -------------------------------------------------------------------------------- /serverless-eks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-eks", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /transit-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "transit-gateway", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /keyspaces-cassandra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "keyspaces-cassandra", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "aws-cdk": "2.53.0", 12 | "@types/babel__traverse": "7.18.2", 13 | "@types/jest": "^27.5.2", 14 | "@types/node": "10.17.27", 15 | "@types/prettier": "2.6.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } -------------------------------------------------------------------------------- /lambda-python-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda-python-api", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /backups/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /batch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sqs-lambda-dynamodb", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /batch/lambdaHandler.js: -------------------------------------------------------------------------------- 1 | const Batch = require("aws-sdk").Batch; 2 | 3 | const batch = new Batch({ 4 | region: process.env.REGION 5 | }); 6 | 7 | async function handler(event, context, callback) { 8 | try { 9 | const jobName = `job_${Date.now()}`; 10 | await batch.submitJob({ 11 | jobDefinition: process.env.JOB_DEFINITION, 12 | jobQueue: process.env.JOB_QUEUE, 13 | jobName 14 | }).promise(); 15 | console.log("Job submitted", jobName); 16 | callback(null, "done"); 17 | } catch(err) { 18 | console.error(err); 19 | callback("Internal error"); 20 | } 21 | } 22 | 23 | module.exports.handler = handler; -------------------------------------------------------------------------------- /dynamo-streams-lambda/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dynamo-streams-lambda", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ec2-basics/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /ec2-jenkins/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /ecs-go-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /eks-cluster/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /elasticsearch-cluster/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elasticsearch-cluster", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /rds-proxy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /sagemaker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /wordpress-ha/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /cognito-userpool/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /docdb-lambda-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /elb-lambda-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /empty-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /lambda-python-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /serverless-eks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /transit-gateway/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /backups/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backups", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "cdk-backup-plan": "^0.0.3", 24 | "constructs": "^10.0.0", 25 | "dotenv": "^8.2.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dynamo-streams-lambda/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /elasticsearch-cluster/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /keyspaces-cassandra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /lambda-functionURL/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2016", "es2017.object", "es2017.string"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false 20 | }, 21 | "exclude": ["cdk.out"] 22 | } 23 | -------------------------------------------------------------------------------- /eks-cluster/graphql-api/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { ApolloServer, gql } = require("apollo-server-express"); 3 | const helmet = require("helmet"); 4 | 5 | const typeDefs = gql` 6 | type Query { 7 | hello: String 8 | date: String 9 | } 10 | `; 11 | 12 | const resolvers = { 13 | Query: { 14 | hello: () => "Hello from EKS example", 15 | date: () => new Date().toISOString() 16 | }, 17 | }; 18 | 19 | const server = new ApolloServer({ typeDefs, resolvers }); 20 | 21 | const app = express(); 22 | app.use(helmet()); 23 | server.applyMiddleware({ app }); 24 | 25 | app.listen({ port: 8090 }, () => 26 | console.log(`Server started on port 8090, ${server.graphqlPath}`) 27 | ); -------------------------------------------------------------------------------- /docdb-lambda-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docdb-lambda-api", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "constructs": "^10.0.0", 24 | "dotenv": "^8.2.0", 25 | "mongodb": "^5.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /serverless-eks/graphql-api/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { ApolloServer, gql } = require("apollo-server-express"); 3 | const helmet = require("helmet"); 4 | 5 | const typeDefs = gql` 6 | type Query { 7 | hello: String 8 | date: String 9 | } 10 | `; 11 | 12 | const resolvers = { 13 | Query: { 14 | hello: () => "Hello from EKS example", 15 | date: () => new Date().toISOString() 16 | }, 17 | }; 18 | 19 | const server = new ApolloServer({ typeDefs, resolvers }); 20 | 21 | const app = express(); 22 | app.use(helmet()); 23 | server.applyMiddleware({ app }); 24 | 25 | app.listen({ port: 8090 }, () => 26 | console.log(`Server started on port 8090, ${server.graphqlPath}`) 27 | ); -------------------------------------------------------------------------------- /ec2-jenkins/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ec2-jenkins", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "build": "tsc", 6 | "watch": "tsc -w", 7 | "cdk": "cdk", 8 | "test": "jest" 9 | }, 10 | "devDependencies": { 11 | "@types/babel__traverse": "7.18.2", 12 | "@types/jest": "^27.5.2", 13 | "@types/node": "10.17.27", 14 | "@types/prettier": "2.6.0", 15 | "aws-cdk": "2.53.0", 16 | "jest": "^27.5.1", 17 | "ts-jest": "^27.1.4", 18 | "ts-node": "^10.9.1", 19 | "typescript": "~3.9.7" 20 | }, 21 | "dependencies": { 22 | "aws-cdk-lib": "2.53.0", 23 | "axios": "^1.3.1", 24 | "cheerio": "^1.0.0-rc.12", 25 | "constructs": "^10.0.0", 26 | "dotenv": "^8.2.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ec2-jenkins/README.md: -------------------------------------------------------------------------------- 1 | ## EC2 Jenkins Example 2 | This example will deploy an EC2 instance to a new VPC & default public subnet and a 100 gb EBS volume. It will get the latest `Jenkins Public Bitnami AMI` from the Bitnami website using `cheerio`. 3 | 4 | You will see the output url after the successful deployment. Open the URL in browser and you will see a login screen. In order to get pre-configured user credentials, head over to the EC2 console. Right click on `jenkins-instance` -> Instance Settings -> Get System Log 5 | 6 | 7 | 8 | 9 | 10 | Use these credentials to login. 11 | -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/README.md: -------------------------------------------------------------------------------- 1 | ## SQS Lambda and DynamoDB Stack 2 | This example will deploy a SQS queue, a DynamoDB table and a Lambda function written in Javacript. Lambda function will get triggered by incoming SQS messages. It will process the incoming message and processed data will be added to DynamoDB table. 3 | 4 | 5 | 6 | You will see a SQS URL after the successful deployment. Use `aws-cli` to send basic message for testing the CDK Stack. 7 | 8 | ``` 9 | aws sqs send-message --queue-url https://sqs.us-west-1.amazonaws.com/[ACCOUNT_ID]/Orders --message-body "{\"items\": [\"coffee\", \"gum\"], \"customerId\": \"qm1h324k\"}" --delay-seconds 2 --profile your_profile --region us-west-1 10 | ``` 11 | 12 | You should be seeing the new item in DynamoDB table. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Examples using AWS CDK (Cloud Development Kit) 2 | 3 | ### How to Deploy Examples 4 | 5 | Install the CDK CLI globally 6 | `npm install -g aws-cdk` 7 | 8 | Change directory to any example 9 | `cd sagemaker` 10 | 11 | Install dependencies 12 | `npm install` 13 | 14 | Set environment variables 15 | `vim .env` 16 | 17 | Deploy using the CDK CLI 18 | `cdk deploy` 19 | 20 | or deploy to non-default AWS profile 21 | `cdk deploy --profile my_profile` 22 | 23 | ### Other CLI Commands 24 | 25 | - `cdk diff` Prints out the difference in stacks 26 | 27 | - `cdk destroy` Removes the stack 28 | 29 | - `cdk list` List the applications in given folder 30 | 31 | - `cdk synth` Synthesizes and prints the CloudFormation template for the stack 32 | 33 | - `cdk init` Generates a new cdk project 34 | 35 | - `cdk doctor` Checks the CDK setup 36 | -------------------------------------------------------------------------------- /docdb-lambda-api/src/getLongURL.ts: -------------------------------------------------------------------------------- 1 | 2 | import { APIGatewayEvent, Context, Callback } from "aws-lambda"; 3 | 4 | import { connectToDB, success, redirect, notFound } from "./lib"; 5 | import { MongoClient } from "mongodb"; 6 | 7 | const DB_NAME = process.env.DB_NAME as string; 8 | 9 | let dbClient: MongoClient; 10 | 11 | export async function handler(event: APIGatewayEvent, context: Context, callback: Callback) { 12 | try { 13 | dbClient = await connectToDB(); 14 | const db = dbClient.db(DB_NAME); 15 | const id = event.pathParameters!["id"]; 16 | const dbItem = await db.collection("urls").findOne({shortId: id}); 17 | if(!dbItem) { 18 | return callback(null, notFound({})); 19 | } 20 | return callback(null, redirect(dbItem.url)); 21 | } catch(err) { 22 | console.error(err); 23 | return callback("Internal error"); 24 | } finally { 25 | await dbClient.close(); 26 | } 27 | } -------------------------------------------------------------------------------- /serverless-eks/templates.ts: -------------------------------------------------------------------------------- 1 | export function getKubernetesTemplates( 2 | repo: any, 3 | name: string, 4 | containerPort: number, 5 | replicaNumber: number 6 | ) { 7 | return [ 8 | { 9 | apiVersion: "apps/v1", 10 | kind: "Deployment", 11 | metadata: { name }, 12 | spec: { 13 | replicas: replicaNumber, 14 | selector: { matchLabels: { app: name } }, 15 | template: { 16 | metadata: { 17 | labels: { app: name } 18 | }, 19 | spec: { 20 | containers: [ 21 | { 22 | name: name, 23 | image: repo.imageUri, 24 | ports: [{ containerPort }] 25 | } 26 | ] 27 | } 28 | } 29 | } 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/lambdaHandler.js: -------------------------------------------------------------------------------- 1 | const DynamoDB = require("aws-sdk").DynamoDB 2 | 3 | const dynamoDb = new DynamoDB.DocumentClient({ 4 | region: process.env.REGION 5 | }); 6 | 7 | async function handler(event, context, callback) { 8 | try { 9 | for(const record of event.Records) { 10 | const input = JSON.parse(JSON.parse(JSON.stringify(record.body))); 11 | const item = { 12 | id: record.messageId, 13 | timestamp: Date.now(), 14 | items: input.items, 15 | customerId: input.customerId, 16 | sqsMessageAttributes: record.attributes 17 | } 18 | const dbParams = { 19 | TableName: process.env.TABLE_NAME, 20 | Item: item 21 | } 22 | await dynamoDb.put(dbParams).promise(); 23 | } 24 | callback(null, "done"); 25 | } catch(err) { 26 | console.error(err); 27 | callback("Internal server error"); 28 | } 29 | } 30 | 31 | module.exports.handler = handler; -------------------------------------------------------------------------------- /serverless-eks/README.md: -------------------------------------------------------------------------------- 1 | ## EKS Fargate Example 2 | This example will deploy an EKS cluster with Fargate capability. 3 | 4 | `go-api` folder consist of sample REST API written in Go 5 | `graphql-api` folder consists of GraphQL server written in Nodejs 6 | 7 | After the successful deployment you will see two commands. Use first one to setup your `kubectl` config 8 | `aws eks update-kubeconfig --name ekscluster --region us-east-1 --role-arn arn:aws:iam::111111111111:role/EKSClusterStack-masterroleEF831F2F-8ZOJQU6ROPCT --profile your_profile` 9 | 10 | This command will set the Kubernetes config needed for you to use `kubectl` to control your cluster 11 | 12 | After the initial deployment, pods in all namespaces would stuck in "Pending" state. We need to manually restart all deployments to schedule them on Fargate nodes. 13 | `kubectl rollout restart deployments -n kube-system` 14 | `kubectl rollout restart deployments` 15 | 16 | After that, try getting the running pods in default namespace 17 | `kubectl get pods` 18 | 19 | Forward ports to localhost 20 | `kubectl port-forward deployment/go-api 8080:8080` -------------------------------------------------------------------------------- /docdb-lambda-api/src/urlShortener.ts: -------------------------------------------------------------------------------- 1 | 2 | import { APIGatewayEvent, Context, Callback } from "aws-lambda"; 3 | import { MongoClient } from "mongodb"; 4 | import { generate } from "shortid"; 5 | import { connectToDB, success } from "./lib"; 6 | 7 | const DB_NAME = process.env.DB_NAME as string; 8 | let dbClient: MongoClient; 9 | 10 | export async function handler(event: APIGatewayEvent, context: Context, callback: Callback){ 11 | try { 12 | console.log(event); 13 | dbClient = await connectToDB(); 14 | const body = JSON.parse(event.body as string); 15 | const db = dbClient.db(DB_NAME); 16 | const shortId = generate(); 17 | await db.collection("urls").insertOne({ 18 | url: body.url, 19 | createdAt: new Date().toUTCString(), 20 | shortId, 21 | requesterIP: event.requestContext.identity.sourceIp 22 | }); 23 | const baseURL = `https://${event.requestContext.domainName}${event.requestContext.path}`; 24 | callback(null, success({shortUrl: `${baseURL}/${shortId}`})); 25 | } catch(err) { 26 | console.error(err); 27 | callback("Internal error"); 28 | } finally { 29 | await dbClient.close(); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /lambda-functionURL/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as lambda from "aws-cdk-lib/aws-lambda"; 3 | import { config } from "dotenv"; 4 | import { Construct } from "constructs"; 5 | config(); 6 | 7 | class LambdaFunctionURLStack extends cdk.Stack { 8 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 9 | super(scope, id, props); 10 | 11 | const lambdaFunction = new lambda.Function(this, "function-url", { 12 | functionName: "function-url", 13 | runtime: lambda.Runtime.NODEJS_18_X, 14 | code: new lambda.AssetCode("src"), 15 | handler: "lambdaHandler.handler", 16 | timeout: cdk.Duration.seconds(60) 17 | }); 18 | 19 | const cors = { 20 | allowedOrigins: ['*'], 21 | }; 22 | const functionURL = lambdaFunction.addFunctionUrl({authType: lambda.FunctionUrlAuthType.NONE, cors}); 23 | 24 | new cdk.CfnOutput(this, "URLS", { 25 | value: functionURL.url 26 | }); 27 | 28 | } 29 | } 30 | 31 | const app = new cdk.App(); 32 | new LambdaFunctionURLStack(app, "LambdaFunctionURLStack", { 33 | env: { 34 | account: process.env.AWS_ACCOUNT_ID, 35 | region: process.env.AWS_REGION 36 | } 37 | }); -------------------------------------------------------------------------------- /eks-cluster/README.md: -------------------------------------------------------------------------------- 1 | ## EKS Cluster Example 2 | This example will deploy an EKS cluster, worker nodes, ECR repositories and two services written in Python and NodeJs. Services include Kubernetes resources such as Service, Deployment and Horizontal Pod Scaler templates. 3 | 4 | `go-api` folder consist of sample REST API written in Go 5 | 6 | `graphql-api` folder consists of GraphQL server written in Nodejs 7 | 8 | 9 | After the successful deployment you will see two commands. Use first one to setup your `kubectl` config 10 | 11 | `aws eks update-kubeconfig --name ekscluster --region us-east-1 --role-arn arn:aws:iam::111111111111:role/EKSClusterStack-masterroleEF831F2F-8ZOJQU6ROPCT --profile your_profile` 12 | 13 | This command will set the Kubernetes config needed for you to use `kubectl` to control your cluster 14 | 15 | `kubectl get svc` 16 | 17 | This will show Service resources and external domain information. 18 | 19 | For trying out grapql-api service go to: `{DOMAIN_URL}/graphql` 20 | 21 | For trying out go-api service go to : `{DOMAIN_URL}/dogs` 22 | 23 | You will need to deploy Metrics Server to get HPA working correctly. 24 | https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/metrics-server 25 | 26 | Destroy resources after you are done with the example 27 | `cdk destroy --profile your_profile` -------------------------------------------------------------------------------- /docdb-lambda-api/src/lib.ts: -------------------------------------------------------------------------------- 1 | import { MongoClient } from "mongodb"; 2 | import { readFileSync } from "fs" 3 | 4 | const DB_URL = process.env.DB_URL as string; 5 | const ca = [readFileSync(`${__dirname}/rds-combined-ca-bundle.pem`)]; 6 | 7 | export async function connectToDB() { 8 | const client = await MongoClient.connect(DB_URL as string, { ssl: true, sslValidate: true, sslCA: ca, useNewUrlParser: true }); 9 | return client; 10 | } 11 | 12 | export function success(body: object): object { 13 | return buildResponse(200, body); 14 | } 15 | 16 | export function failure(body: object): object { 17 | return buildResponse(500, body); 18 | } 19 | 20 | export function notFound(body: object): object { 21 | return buildResponse(404, body); 22 | } 23 | 24 | export function redirect(location: string) { 25 | return { 26 | statusCode: 302, 27 | headers: { 28 | "Access-Control-Allow-Origin": "*", 29 | "Access-Control-Allow-Credentials": true, 30 | Location: location, 31 | } 32 | } 33 | } 34 | 35 | function buildResponse(statusCode: number, body: object): object { 36 | return { 37 | statusCode: statusCode, 38 | headers: { 39 | "Access-Control-Allow-Origin": "*", 40 | "Access-Control-Allow-Credentials": true 41 | }, 42 | body: JSON.stringify(body) 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /lambda-python-api/lib.ts: -------------------------------------------------------------------------------- 1 | import apigateway = require("aws-cdk-lib/aws-apigateway"); 2 | 3 | export function addCorsOptions(apiResource: apigateway.IResource) { 4 | apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({ 5 | integrationResponses: [{ 6 | statusCode: '200', 7 | responseParameters: { 8 | 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", 9 | 'method.response.header.Access-Control-Allow-Origin': "'*'", 10 | 'method.response.header.Access-Control-Allow-Credentials': "'false'", 11 | 'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'", 12 | }, 13 | }], 14 | passthroughBehavior: apigateway.PassthroughBehavior.NEVER, 15 | requestTemplates: { 16 | "application/json": "{\"statusCode\": 200}" 17 | }, 18 | }), { 19 | methodResponses: [{ 20 | statusCode: '200', 21 | responseParameters: { 22 | 'method.response.header.Access-Control-Allow-Headers': true, 23 | 'method.response.header.Access-Control-Allow-Methods': true, 24 | 'method.response.header.Access-Control-Allow-Credentials': true, 25 | 'method.response.header.Access-Control-Allow-Origin': true, 26 | }, 27 | }] 28 | }) 29 | } -------------------------------------------------------------------------------- /ecs-go-api/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib/core"; 2 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 3 | import * as ecs from 'aws-cdk-lib/aws-ecs'; 4 | import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns'; 5 | import { Construct } from "constructs"; 6 | import { config } from "dotenv"; 7 | config(); 8 | 9 | class EcsGoAPIStack extends cdk.Stack { 10 | constructor(scope: Construct, id: string, props?: cdk.StackProps){ 11 | super(scope, id, props); 12 | 13 | const vpc = new ec2.Vpc(this, 'vpc', { maxAzs: 2 }); 14 | 15 | const cluster = new ecs.Cluster(this, 'Cluster', { vpc }); 16 | 17 | const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, "FargateService", { 18 | cluster, 19 | taskImageOptions: { 20 | image: ecs.ContainerImage.fromAsset(`${__dirname}/api`), 21 | containerPort: 8080, 22 | environment: { 23 | DEPLOYED_DATE: Date.now().toLocaleString() 24 | } 25 | }, 26 | desiredCount: 1 27 | }); 28 | 29 | new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: fargateService.loadBalancer.loadBalancerDnsName }); 30 | } 31 | } 32 | 33 | const app = new cdk.App(); 34 | new EcsGoAPIStack(app, "EcsGoAPIStack", { 35 | env: { 36 | account: process.env.AWS_ACCOUNT_ID, 37 | region: process.env.AWS_REGION, 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /lambda-python-api/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import * as lambda from 'aws-cdk-lib/aws-lambda'; 3 | import * as apigateway from "aws-cdk-lib/aws-apigateway"; 4 | import { readFileSync } from "fs"; 5 | import { addCorsOptions } from "./lib"; 6 | import { Construct } from "constructs"; 7 | import { config } from "dotenv"; 8 | config(); 9 | 10 | class LambdaPythonAPIStack extends cdk.Stack { 11 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 12 | super(scope, id, props); 13 | 14 | const srcPath = `${__dirname}/lambda-handler.py`; 15 | const lambdaFunction = new lambda.Function(this, "FindPoems", { 16 | code: new lambda.InlineCode(readFileSync(srcPath, { encoding: 'utf-8' })), 17 | handler: 'index.handler', 18 | timeout: cdk.Duration.seconds(30), 19 | runtime: lambda.Runtime.PYTHON_3_7 20 | }); 21 | 22 | const api = new apigateway.RestApi(this, 'FindPoemsAPI', { 23 | restApiName: 'Find Poems API' 24 | }); 25 | const poems = api.root.addResource("poems"); 26 | const lambdaIntegration = new apigateway.LambdaIntegration(lambdaFunction); 27 | poems.addMethod('GET', lambdaIntegration); 28 | addCorsOptions(poems) 29 | } 30 | } 31 | 32 | const app = new cdk.App(); 33 | new LambdaPythonAPIStack(app, "LambdaPythonAPIStack", { 34 | env: { 35 | region: process.env.AWS_REGION, 36 | account: process.env.AWS_ACCOUNT_ID 37 | } 38 | }); -------------------------------------------------------------------------------- /keyspaces-cassandra/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as cassandra from "aws-cdk-lib/aws-cassandra" 3 | import { config } from "dotenv"; 4 | import { Construct } from "constructs"; 5 | config(); 6 | 7 | class CassandraStack extends cdk.Stack { 8 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 9 | super(scope, id, props); 10 | 11 | const keyspace = new cassandra.CfnKeyspace(this, "keyspace", { 12 | keyspaceName: "cdkkeyspace" 13 | }); 14 | 15 | const table = new cassandra.CfnTable(this, "table", { 16 | keyspaceName: keyspace.keyspaceName as string, 17 | tableName: "cdktable", 18 | partitionKeyColumns: [ 19 | {columnName: "id", columnType: "text"}, 20 | {columnName: "name", columnType: "text"}, 21 | {columnName: "region", columnType: "text"}, 22 | {columnName: "role", columnType: "text"} 23 | ] 24 | }); 25 | 26 | table.addDependsOn(keyspace); 27 | 28 | new cdk.CfnOutput(this, "keyspace-name", { 29 | value: keyspace.keyspaceName as string 30 | }); 31 | 32 | new cdk.CfnOutput(this, "table-name", { 33 | value: table.tableName as string 34 | }); 35 | 36 | } 37 | } 38 | 39 | const app = new cdk.App(); 40 | new CassandraStack(app, "CassandraStack", { 41 | env: { 42 | account: process.env.AWS_ACCOUNT_ID, 43 | region: process.env.AWS_REGION 44 | } 45 | }); -------------------------------------------------------------------------------- /cognito-userpool/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as cognito from "aws-cdk-lib/aws-cognito"; 3 | import { Construct } from 'constructs'; 4 | import { config } from "dotenv"; 5 | config(); 6 | 7 | class CognitoUserPoolStack extends cdk.Stack { 8 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 9 | super(scope, id, props); 10 | 11 | const userPool = new cognito.CfnUserPool(this, "user-pool", { 12 | userPoolName: "user-pool", 13 | usernameAttributes: [ 14 | "email", 15 | "phone_number" 16 | ], 17 | policies: { 18 | passwordPolicy: { 19 | minimumLength: 6, 20 | requireLowercase: false, 21 | requireNumbers: true, 22 | requireUppercase: false, 23 | temporaryPasswordValidityDays: 7 24 | } 25 | }, 26 | }); 27 | const userPoolClient = new cognito.CfnUserPoolClient(this, "user-pool-client", { 28 | userPoolId: userPool.ref, 29 | clientName: "web-client", 30 | generateSecret: false 31 | }); 32 | userPoolClient.addDependsOn(userPool); 33 | new cdk.CfnOutput(this, "userpool-name", {value: userPool.userPoolName as string}); 34 | } 35 | } 36 | 37 | const app = new cdk.App(); 38 | new CognitoUserPoolStack(app, "CognitoUserPoolStack", { 39 | env: { 40 | account: process.env.AWS_ACCOUNT_ID, 41 | region: process.env.AWS_REGION 42 | } 43 | }); -------------------------------------------------------------------------------- /ec2-basics/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 3 | import { config } from "dotenv"; 4 | import { Construct } from 'constructs'; 5 | config(); 6 | 7 | class EC2BasicsStack extends cdk.Stack { 8 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 9 | super(scope, id, props); 10 | 11 | // Create a new VPC 12 | const vpc = new ec2.Vpc(this, 'VPC'); 13 | 14 | // Open port 22 for SSH connection from anywhere 15 | const mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', { 16 | vpc, 17 | securityGroupName: "my-test-sg", 18 | description: 'Allow ssh access to ec2 instances from anywhere', 19 | allowAllOutbound: true 20 | }); 21 | mySecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow public ssh access') 22 | 23 | // We are using the latest AMAZON LINUX AMI 24 | const awsAMI = new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }); 25 | 26 | // We define the instance details here 27 | const ec2Instance = new ec2.Instance(this, 'Instance', { 28 | vpc, 29 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 30 | machineImage: awsAMI, 31 | securityGroup: mySecurityGroup, 32 | vpcSubnets: { 33 | subnetType: ec2.SubnetType.PUBLIC 34 | }, 35 | }); 36 | 37 | new cdk.CfnOutput(this, "ip-address", {value: ec2Instance.instancePublicIp}); 38 | } 39 | } 40 | 41 | const app = new cdk.App(); 42 | new EC2BasicsStack(app, "EC2BasicsStack", { 43 | env: { 44 | region: process.env.AWS_REGION, 45 | account: process.env.AWS_ACCOUNT_ID 46 | } 47 | }); -------------------------------------------------------------------------------- /sagemaker/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as sagemaker from "aws-cdk-lib/aws-sagemaker"; 3 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 4 | import * as iam from "aws-cdk-lib/aws-iam"; 5 | import { Construct } from "constructs"; 6 | import { config } from "dotenv"; 7 | config(); 8 | 9 | class SagemakerStack extends cdk.Stack { 10 | constructor(construct: Construct, id: string, props?: cdk.StackProps) { 11 | super(construct, id, props); 12 | 13 | const vpc = new ec2.Vpc(this, "vpc", { 14 | maxAzs: 3 15 | }); 16 | 17 | const sg = new ec2.SecurityGroup(this, "sg", { 18 | vpc 19 | }); 20 | 21 | const role = new iam.Role(this, "service-role", { 22 | assumedBy: new iam.ServicePrincipal("sagemaker.amazonaws.com"), 23 | managedPolicies: [ 24 | iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess"), 25 | iam.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchLogsFullAccess") 26 | ], 27 | }); 28 | 29 | const notebook = new sagemaker.CfnNotebookInstance(this, "notebook", { 30 | notebookInstanceName: "cdk-notebook", 31 | directInternetAccess: "Enabled", 32 | securityGroupIds: [sg.securityGroupId], 33 | instanceType: "ml.t3.medium", 34 | roleArn: role.roleArn, 35 | rootAccess: "Enabled", 36 | subnetId: vpc.publicSubnets[0].subnetId 37 | }); 38 | new cdk.CfnOutput(this, "sagemaker", {value: notebook.ref}); 39 | } 40 | } 41 | 42 | const app = new cdk.App(); 43 | new SagemakerStack(app, "SagemakerStack", { 44 | env: { 45 | account: process.env.ACCOUNT_ID, 46 | region: process.env.AWS_REGION 47 | } 48 | }); -------------------------------------------------------------------------------- /dynamo-streams-lambda/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; 3 | import * as lambda from "aws-cdk-lib/aws-lambda"; 4 | import {readFileSync} from "fs"; 5 | import { Construct } from "constructs"; 6 | import { config } from "dotenv"; 7 | config(); 8 | 9 | class DynamoStreamsLambdaStack extends cdk.Stack { 10 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 11 | super(scope, id, props); 12 | 13 | const srcPath = `${__dirname}/stream-handler.py`; 14 | const streamLambda = new lambda.Function(this, "StreamHandler", { 15 | functionName: "StreamHandler", 16 | code: new lambda.InlineCode(readFileSync(srcPath, { encoding: 'utf-8' })), 17 | handler: 'index.handler', 18 | timeout: cdk.Duration.seconds(30), 19 | runtime: lambda.Runtime.PYTHON_3_7 20 | }) 21 | 22 | const dogsTable = new dynamodb.Table(this, "DogsTable", { 23 | tableName: "DogsTable", 24 | partitionKey: {name: "id", type: dynamodb.AttributeType.STRING}, 25 | billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, 26 | stream: dynamodb.StreamViewType.NEW_AND_OLD_IMAGES 27 | }); 28 | dogsTable.grantStreamRead(streamLambda); 29 | streamLambda.addEventSourceMapping("EventSourceMapping", { 30 | eventSourceArn: dogsTable.tableStreamArn as string, 31 | enabled: true, 32 | startingPosition: lambda.StartingPosition.LATEST 33 | }) 34 | } 35 | } 36 | 37 | const app = new cdk.App(); 38 | new DynamoStreamsLambdaStack(app, "DynamoStreamsLambdaStack", { 39 | env: { 40 | region: process.env.AWS_REGION, 41 | account: process.env.AWS_ACCOUNT_ID 42 | } 43 | }); -------------------------------------------------------------------------------- /elb-lambda-api/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import * as lambda from 'aws-cdk-lib/aws-lambda'; 3 | import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; 4 | import * as elbv2Targets from "aws-cdk-lib/aws-elasticloadbalancingv2-targets"; 5 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 6 | import { readFileSync } from 'fs'; 7 | import { Construct } from "constructs"; 8 | import { config } from "dotenv"; 9 | config(); 10 | 11 | class ElbLambdaStack extends cdk.Stack { 12 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 13 | super(scope, id, props); 14 | 15 | const vpc = new ec2.Vpc(this, 'VPC', { maxAzs: 2 }); 16 | 17 | const srcPath = `${__dirname}/lambda-handler.py`; 18 | const lambdaFunction = new lambda.Function(this, 'random-word-generator', { 19 | code: new lambda.InlineCode(readFileSync(srcPath, { encoding: 'utf-8' })), 20 | handler: 'index.handler', 21 | timeout: cdk.Duration.seconds(300), 22 | runtime: lambda.Runtime.PYTHON_3_7, 23 | vpc 24 | }); 25 | 26 | const alb = new elbv2.ApplicationLoadBalancer(this, "alb", { 27 | vpc, 28 | internetFacing: true 29 | }); 30 | 31 | const lambdaTarget = new elbv2Targets.LambdaTarget(lambdaFunction); 32 | 33 | const listener = alb.addListener("listener", { 34 | port: 80 35 | }); 36 | 37 | listener.addTargets("targets", { 38 | targets: [lambdaTarget] 39 | }); 40 | 41 | listener.connections.allowDefaultPortFromAnyIpv4('Open to the world'); 42 | 43 | new cdk.CfnOutput(this, "ElbDomain", {value: alb.loadBalancerDnsName}); 44 | } 45 | } 46 | 47 | 48 | const app = new cdk.App(); 49 | new ElbLambdaStack(app, "ElbLambdaStack", { 50 | env: { 51 | account: process.env.AWS_ACCOUNT_ID, 52 | region: process.env.AWS_REGION 53 | } 54 | }); -------------------------------------------------------------------------------- /rds-proxy/src/handler.js: -------------------------------------------------------------------------------- 1 | const mysql = require("mysql2/promise"); 2 | const { RDS } = require("aws-sdk"); 3 | const { sleep } = require("./lib"); 4 | 5 | async function handler(event, context, callback) { 6 | console.log(process.env); 7 | try { 8 | const { REGION, DB_HOST, DB_PORT, DB_USER, PROXY_HOST, DB_NAME } = process.env; 9 | const rdsSigner = new RDS.Signer({ 10 | region: REGION, 11 | hostname: PROXY_HOST, 12 | port: +DB_PORT, 13 | username: DB_USER, 14 | }); 15 | 16 | const authToken = rdsSigner.getAuthToken({ 17 | username: DB_USER, 18 | }); 19 | 20 | for (let i = 0; i < 120; i++) { 21 | const connection = await mysql.createConnection({ 22 | host: PROXY_HOST, 23 | user: DB_USER, 24 | database: DB_NAME, 25 | port: +DB_PORT, 26 | password: authToken, 27 | ssl: { rejectUnauthorized: false }, 28 | authSwitchHandler: function (data, callback) { 29 | if (data.pluginName === "mysql_clear_password") { 30 | let password = authToken + "\0"; 31 | let buffer = Buffer.from(password); 32 | callback(null, password); 33 | } 34 | }, 35 | }); 36 | 37 | connection.on("connect", () => { 38 | console.log("Connected to database"); 39 | }); 40 | 41 | connection.on("end", () => { 42 | console.log("Connection closed"); 43 | }); 44 | 45 | connection.on("error", (err) => { 46 | console.error("Error", err); 47 | }); 48 | await connection.execute("SHOW DATABASES") 49 | await sleep(1000); 50 | connection.end(); 51 | } 52 | 53 | callback(null, "done"); 54 | } catch (err) { 55 | console.error(err); 56 | callback(err); 57 | } 58 | } 59 | 60 | module.exports = { 61 | handler, 62 | }; 63 | -------------------------------------------------------------------------------- /eks-cluster/templates.ts: -------------------------------------------------------------------------------- 1 | export function getKubernetesTemplates( 2 | repo: any, 3 | name: string, 4 | containerPort: number, 5 | replicaNumber: number, 6 | minReplicas: number, 7 | maxReplicas: number, 8 | targetCPUUtilizationPercentage: number 9 | ) { 10 | return [ 11 | { 12 | apiVersion: "v1", 13 | kind: "Service", 14 | metadata: { name }, 15 | spec: { 16 | type: "LoadBalancer", 17 | ports: [{ port: 80, targetPort: containerPort }], 18 | selector: { app: name } 19 | } 20 | }, 21 | { 22 | apiVersion: "apps/v1", 23 | kind: "Deployment", 24 | metadata: { name }, 25 | spec: { 26 | replicas: replicaNumber, 27 | selector: { matchLabels: { app: name } }, 28 | template: { 29 | metadata: { 30 | labels: { app: name } 31 | }, 32 | spec: { 33 | containers: [ 34 | { 35 | name: name, 36 | image: repo.imageUri, 37 | ports: [{ containerPort }] 38 | } 39 | ] 40 | } 41 | } 42 | } 43 | }, 44 | { 45 | apiVersion: "autoscaling/v1", 46 | kind: "HorizontalPodAutoscaler", 47 | metadata: { name }, 48 | spec: { 49 | maxReplicas, 50 | minReplicas, 51 | targetCPUUtilizationPercentage, 52 | scaleTargetRef: { 53 | apiVersion: "extensions/v1beta1", 54 | kind: "Deployment", 55 | name 56 | } 57 | } 58 | } 59 | ] 60 | } -------------------------------------------------------------------------------- /sqs-lambda-dynamodb/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as sqs from 'aws-cdk-lib/aws-sqs'; 3 | import * as lambda from "aws-cdk-lib/aws-lambda"; 4 | import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; 5 | import { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources'; 6 | import { readFileSync } from "fs"; 7 | import { Construct } from "constructs"; 8 | import { config } from "dotenv"; 9 | config(); 10 | 11 | class SQSLambdaDynamodbStack extends cdk.Stack { 12 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 13 | super(scope, id, props); 14 | 15 | const queue = new sqs.Queue(this, "Orders", { 16 | queueName: "Orders" 17 | }); 18 | 19 | const table = new dynamodb.Table(this, "OrdersTable", { 20 | tableName: "OrdersTable", 21 | partitionKey: {name: "id", type: dynamodb.AttributeType.STRING}, 22 | billingMode: dynamodb.BillingMode.PAY_PER_REQUEST 23 | }); 24 | 25 | const srcPath = `${__dirname}/lambdaHandler.js`; 26 | const lambdaFunction = new lambda.Function(this, "ProcessOrder", { 27 | functionName: "ProcessOrder", 28 | code: new lambda.InlineCode(readFileSync(srcPath, {encoding: "utf-8"})), 29 | handler: "index.handler", 30 | timeout: cdk.Duration.seconds(30), 31 | runtime: lambda.Runtime.NODEJS_8_10, 32 | environment: { 33 | TABLE_NAME: table.tableName, 34 | REGION: process.env.AWS_REGION as string 35 | }, 36 | events: [ 37 | new SqsEventSource(queue) 38 | ] 39 | }); 40 | table.grantWriteData(lambdaFunction); 41 | new cdk.CfnOutput(this, 'QueueURL', { 42 | value: queue.queueUrl 43 | }); 44 | } 45 | } 46 | 47 | const app = new cdk.App(); 48 | new SQSLambdaDynamodbStack(app, "SQSLambdaDynamodbStack", { 49 | env: { 50 | account: process.env.AWS_ACCOUNT_ID, 51 | region: process.env.AWS_REGION 52 | } 53 | }) 54 | 55 | -------------------------------------------------------------------------------- /ec2-jenkins/lib.ts: -------------------------------------------------------------------------------- 1 | import cheerio = require("cheerio"); 2 | import axios from "axios"; 3 | 4 | const bitnamiURL = "https://bitnami.com/stack/jenkins/cloud/aws/amis"; 5 | 6 | export async function getLatestJenkinsAMI(region: string): Promise { 7 | try { 8 | const regionSelection = mapRegionSelector(region) 9 | const selector = `${regionSelection} > table > tbody > tr > td:nth-child(3) > span.clouds__amis__link > a`; 10 | const result = await axios.get(bitnamiURL); 11 | const $ = cheerio.load(result.data); 12 | const res = $(selector).text(); 13 | return res; 14 | } catch(err) { 15 | console.error(err); 16 | return "error"; 17 | } 18 | } 19 | 20 | function mapRegionSelector(region: string): string { 21 | switch(region) { 22 | case "us-west-1": 23 | return "#us-west-\\(n\\.-california\\)"; 24 | case "us-west-2": 25 | return "#us-west-\\(oregon\\)"; 26 | case "us-east-1": 27 | return "#us-east-\\(n\\.-virginia\\)"; 28 | case "us-east-2": 29 | return "#us-east-\\(ohio\\)"; 30 | case "ca-central-1": 31 | return "#canada-\\(central\\)"; 32 | case "eu-central-1": 33 | return "#eu-\\(frankfurt\\)"; 34 | case "eu-west-1": 35 | return "#eu-\\(ireland\\)"; 36 | case "eu-west-2": 37 | return "#eu-\\(london\\)"; 38 | case "eu-west-3": 39 | return "#eu-\\(paris\\)"; 40 | case "eu-north-1": 41 | return "#eu-\\(stockholm\\)"; 42 | case "ap-east-1": 43 | return "#asia-pacific-\\(hong-kong\\)"; 44 | case "ap-southeast-1": 45 | return "#asia-pacific-\\(singapore\\)"; 46 | case "ap-southeast-2": 47 | return "#asia-pacific-\\(sydney\\)"; 48 | case "ap-south-1": 49 | return "#asia-pacific-\\(mumbai\\)"; 50 | case "ap-northeast-1": 51 | return "#asia-pacific-\\(tokyo\\)"; 52 | case "ap-northeast-2": 53 | return "#asia-pacific-\\(seoul\\)"; 54 | case "sa-east-1": 55 | return "#south-america-\\(sao-paulo\\)"; 56 | case "me-south-1": 57 | return "#middle-east-\\(bahrain\\)"; 58 | default: 59 | return "#us-west-\\(oregon\\)"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ec2-jenkins/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 3 | import { getLatestJenkinsAMI } from "./lib"; 4 | import { Construct } from "constructs"; 5 | import { config } from "dotenv"; 6 | config(); 7 | 8 | interface EC2JenkinsStackProps { 9 | env: any; 10 | ami: string; 11 | } 12 | 13 | class EC2JenkinsStack extends cdk.Stack { 14 | constructor(scope: Construct, id: string, props: EC2JenkinsStackProps) { 15 | super(scope, id, props); 16 | 17 | // Create a new VPC 18 | const vpc = new ec2.Vpc(this, 'VPC'); 19 | 20 | const mySecurityGroup = new ec2.SecurityGroup(this, 'jenkins-sg', { 21 | vpc, 22 | securityGroupName: "jenkins-sg", 23 | allowAllOutbound: true 24 | }); 25 | mySecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow public ssh access') 26 | mySecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), "Jenkins port"); 27 | 28 | const region = props.env.region as string; 29 | const ec2Instance = new ec2.Instance(this, 'Instance', { 30 | vpc, 31 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 32 | machineImage: ec2.MachineImage.genericLinux({ 33 | [region]: props.ami 34 | }), 35 | securityGroup: mySecurityGroup, 36 | vpcSubnets: { 37 | subnetType: ec2.SubnetType.PUBLIC 38 | }, 39 | blockDevices: [{ 40 | deviceName: "/dev/xvdb", 41 | volume: ec2.BlockDeviceVolume.ebs(100, { 42 | deleteOnTermination: true, 43 | encrypted: true 44 | }), 45 | mappingEnabled: true 46 | }] 47 | }); 48 | 49 | new cdk.CfnOutput(this, "EC2 URL", { 50 | value: ec2Instance.instancePublicDnsName 51 | }); 52 | 53 | } 54 | } 55 | 56 | (async()=>{ 57 | const jenkinsAMI = await getLatestJenkinsAMI(process.env.AWS_REGION as string); 58 | const app = new cdk.App(); 59 | new EC2JenkinsStack(app, "EC2JenkinsStack", { 60 | env: { 61 | account: process.env.AWS_ACCOUNT_ID, 62 | region: process.env.AWS_REGION, 63 | }, 64 | ami: jenkinsAMI 65 | }) 66 | })(); -------------------------------------------------------------------------------- /ecs-go-api/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "fmt" 5 | "net/http" 6 | "encoding/json" 7 | "math/rand" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | "context" 13 | "log" 14 | 15 | "github.com/gorilla/mux" 16 | ) 17 | 18 | type Dog struct { 19 | Name string `json:"name"` 20 | Age int `json:"age"` 21 | Toy *Toy `json:"toy,omitempty"` 22 | } 23 | 24 | type Toy struct { 25 | Name string `json:"name"` 26 | Color string `json:"color"` 27 | } 28 | 29 | var dogNames = []string{"Rex", "Max", "Molly", "Loki", "Jax"} 30 | var toyNames = []string{"Tennis Ball", "Rope", "Bear", "Dumbell"} 31 | var toyColors = []string{"Red", "Yellow", "Blue", "Green", "Brown"} 32 | 33 | func main() { 34 | r := mux.NewRouter() 35 | r.HandleFunc("/dogs/{name}", handleGetDog).Methods("GET") 36 | r.HandleFunc("/dogs", handleGetDogs).Methods("GET") 37 | server := &http.Server{ 38 | Handler: r, 39 | Addr: ":8080", 40 | ReadTimeout: 5 * time.Second, 41 | WriteTimeout: 5 * time.Second, 42 | } 43 | 44 | go func() { 45 | log.Println("Starting server") 46 | if err := server.ListenAndServe(); err != nil { 47 | log.Fatal(err) 48 | } 49 | }() 50 | 51 | waitForShutdown(server) 52 | } 53 | 54 | func handleGetDog(w http.ResponseWriter, r *http.Request) { 55 | vars := mux.Vars(r) 56 | name := vars["name"] 57 | dog := Dog { 58 | Name: name, 59 | Age: rand.Intn(20), 60 | Toy: &Toy{ 61 | Name: toyNames[rand.Intn(len(toyNames))], 62 | Color: toyColors[rand.Intn(len(toyColors))], 63 | }, 64 | } 65 | res, err := json.Marshal(dog) 66 | if (err != nil) { 67 | panic(err) 68 | } 69 | 70 | w.Header().Set("Content-Type", "application/json") 71 | w.Write(res) 72 | } 73 | 74 | func handleGetDogs(w http.ResponseWriter, r *http.Request) { 75 | dogs := []Dog{} 76 | for _, dogName := range dogNames { 77 | dogs = append(dogs, 78 | Dog{ 79 | Name: dogName, 80 | Age: rand.Intn(20), 81 | }, 82 | ) 83 | } 84 | res, err := json.Marshal(dogs) 85 | if (err != nil) { 86 | panic(err) 87 | } 88 | w.Header().Set("Content-Type", "application/json") 89 | w.Write(res) 90 | } 91 | 92 | func waitForShutdown(server *http.Server) { 93 | interruptChan := make(chan os.Signal, 1) 94 | signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 95 | 96 | <-interruptChan 97 | 98 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) 99 | defer cancel() 100 | server.Shutdown(ctx) 101 | 102 | log.Println("Shutting down") 103 | os.Exit(0) 104 | } -------------------------------------------------------------------------------- /eks-cluster/go-api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "fmt" 5 | "net/http" 6 | "encoding/json" 7 | "math/rand" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | "context" 13 | "log" 14 | 15 | "github.com/gorilla/mux" 16 | ) 17 | 18 | type Dog struct { 19 | Name string `json:"name"` 20 | Age int `json:"age"` 21 | Toy *Toy `json:"toy,omitempty"` 22 | } 23 | 24 | type Toy struct { 25 | Name string `json:"name"` 26 | Color string `json:"color"` 27 | } 28 | 29 | var dogNames = []string{"Rex", "Max", "Molly", "Loki", "Jax"} 30 | var toyNames = []string{"Tennis Ball", "Rope", "Bear", "Dumbell"} 31 | var toyColors = []string{"Red", "Yellow", "Blue", "Green", "Brown"} 32 | 33 | func main() { 34 | r := mux.NewRouter() 35 | r.HandleFunc("/dogs/{name}", handleGetDog).Methods("GET") 36 | r.HandleFunc("/dogs", handleGetDogs).Methods("GET") 37 | server := &http.Server{ 38 | Handler: r, 39 | Addr: ":8080", 40 | ReadTimeout: 5 * time.Second, 41 | WriteTimeout: 5 * time.Second, 42 | } 43 | 44 | go func() { 45 | log.Println("Starting server") 46 | if err := server.ListenAndServe(); err != nil { 47 | log.Fatal(err) 48 | } 49 | }() 50 | 51 | waitForShutdown(server) 52 | } 53 | 54 | func handleGetDog(w http.ResponseWriter, r *http.Request) { 55 | vars := mux.Vars(r) 56 | name := vars["name"] 57 | dog := Dog { 58 | Name: name, 59 | Age: rand.Intn(20), 60 | Toy: &Toy{ 61 | Name: toyNames[rand.Intn(len(toyNames))], 62 | Color: toyColors[rand.Intn(len(toyColors))], 63 | }, 64 | } 65 | res, err := json.Marshal(dog) 66 | if (err != nil) { 67 | panic(err) 68 | } 69 | 70 | w.Header().Set("Content-Type", "application/json") 71 | w.Write(res) 72 | } 73 | 74 | func handleGetDogs(w http.ResponseWriter, r *http.Request) { 75 | dogs := []Dog{} 76 | for _, dogName := range dogNames { 77 | dogs = append(dogs, 78 | Dog{ 79 | Name: dogName, 80 | Age: rand.Intn(20), 81 | }, 82 | ) 83 | } 84 | res, err := json.Marshal(dogs) 85 | if (err != nil) { 86 | panic(err) 87 | } 88 | w.Header().Set("Content-Type", "application/json") 89 | w.Write(res) 90 | } 91 | 92 | func waitForShutdown(server *http.Server) { 93 | interruptChan := make(chan os.Signal, 1) 94 | signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 95 | 96 | <-interruptChan 97 | 98 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) 99 | defer cancel() 100 | server.Shutdown(ctx) 101 | 102 | log.Println("Shutting down") 103 | os.Exit(0) 104 | } -------------------------------------------------------------------------------- /serverless-eks/go-api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "fmt" 5 | "net/http" 6 | "encoding/json" 7 | "math/rand" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | "context" 13 | "log" 14 | 15 | "github.com/gorilla/mux" 16 | ) 17 | 18 | type Dog struct { 19 | Name string `json:"name"` 20 | Age int `json:"age"` 21 | Toy *Toy `json:"toy,omitempty"` 22 | } 23 | 24 | type Toy struct { 25 | Name string `json:"name"` 26 | Color string `json:"color"` 27 | } 28 | 29 | var dogNames = []string{"Rex", "Max", "Molly", "Loki", "Jax"} 30 | var toyNames = []string{"Tennis Ball", "Rope", "Bear", "Dumbell"} 31 | var toyColors = []string{"Red", "Yellow", "Blue", "Green", "Brown"} 32 | 33 | func main() { 34 | r := mux.NewRouter() 35 | r.HandleFunc("/dogs/{name}", handleGetDog).Methods("GET") 36 | r.HandleFunc("/dogs", handleGetDogs).Methods("GET") 37 | server := &http.Server{ 38 | Handler: r, 39 | Addr: ":8080", 40 | ReadTimeout: 5 * time.Second, 41 | WriteTimeout: 5 * time.Second, 42 | } 43 | 44 | go func() { 45 | log.Println("Starting server") 46 | if err := server.ListenAndServe(); err != nil { 47 | log.Fatal(err) 48 | } 49 | }() 50 | 51 | waitForShutdown(server) 52 | } 53 | 54 | func handleGetDog(w http.ResponseWriter, r *http.Request) { 55 | vars := mux.Vars(r) 56 | name := vars["name"] 57 | dog := Dog { 58 | Name: name, 59 | Age: rand.Intn(20), 60 | Toy: &Toy{ 61 | Name: toyNames[rand.Intn(len(toyNames))], 62 | Color: toyColors[rand.Intn(len(toyColors))], 63 | }, 64 | } 65 | res, err := json.Marshal(dog) 66 | if (err != nil) { 67 | panic(err) 68 | } 69 | 70 | w.Header().Set("Content-Type", "application/json") 71 | w.Write(res) 72 | } 73 | 74 | func handleGetDogs(w http.ResponseWriter, r *http.Request) { 75 | dogs := []Dog{} 76 | for _, dogName := range dogNames { 77 | dogs = append(dogs, 78 | Dog{ 79 | Name: dogName, 80 | Age: rand.Intn(20), 81 | }, 82 | ) 83 | } 84 | res, err := json.Marshal(dogs) 85 | if (err != nil) { 86 | panic(err) 87 | } 88 | w.Header().Set("Content-Type", "application/json") 89 | w.Write(res) 90 | } 91 | 92 | func waitForShutdown(server *http.Server) { 93 | interruptChan := make(chan os.Signal, 1) 94 | signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 95 | 96 | <-interruptChan 97 | 98 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) 99 | defer cancel() 100 | server.Shutdown(ctx) 101 | 102 | log.Println("Shutting down") 103 | os.Exit(0) 104 | } -------------------------------------------------------------------------------- /eks-cluster/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib/core"; 2 | import * as eks from "aws-cdk-lib/aws-eks"; 3 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 4 | import * as iam from "aws-cdk-lib/aws-iam"; 5 | import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"; 6 | import { getKubernetesTemplates } from "./templates"; 7 | import { Construct } from "constructs"; 8 | import { config } from "dotenv"; 9 | config(); 10 | 11 | class EKSClusterStack extends cdk.Stack { 12 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 13 | super(scope, id, props); 14 | 15 | const vpc = new ec2.Vpc(this, "vpc", { 16 | maxAzs: 3 17 | }); 18 | 19 | const mastersRole = new iam.Role(this, 'master-role', { 20 | assumedBy: new iam.AccountRootPrincipal() 21 | }); 22 | 23 | const cluster = new eks.Cluster(this, "cluster", { 24 | version: eks.KubernetesVersion.V1_23, 25 | defaultCapacityInstance: new ec2.InstanceType("m5.large"), 26 | defaultCapacity: 2, 27 | clusterName: "ekscluster", 28 | vpc, 29 | mastersRole 30 | }); 31 | 32 | const goAPIRepo = new ecrAssets.DockerImageAsset(this, "go-api-repo", { 33 | directory: "go-api", 34 | }); 35 | 36 | const graphqlAPIRepo = new ecrAssets.DockerImageAsset(this, "graphql-api-repo", { 37 | directory: "graphql-api" 38 | }); 39 | 40 | const goAPIResource = new eks.KubernetesManifest(this, "go-api-resource", { 41 | cluster, 42 | manifest: getKubernetesTemplates( 43 | goAPIRepo, //repo 44 | "go-api", //resource name 45 | 8080, //container port 46 | 2, //replica number 47 | 2, // min replicas for hpa 48 | 4, // max replicas for hpa 49 | 70 // hpa cpu util. target 50 | ) 51 | }); 52 | 53 | const graphqlAPIResource = new eks.KubernetesManifest(this, "graphql-api-resource", { 54 | cluster, 55 | manifest: getKubernetesTemplates( 56 | graphqlAPIRepo, //repo 57 | "graphql-api", //resource name 58 | 8090, //container port 59 | 2, //replica number 60 | 2, // min replicas for hpa 61 | 4, // max replicas for hpa 62 | 70 // hpa cpu util. target 63 | ) 64 | }); 65 | 66 | } 67 | } 68 | 69 | const app = new cdk.App(); 70 | const stack = new EKSClusterStack(app, "EKSClusterStack", { 71 | env: { 72 | region: process.env.AWS_REGION, 73 | account: process.env.AWS_ACCOUNT_ID 74 | } 75 | }); -------------------------------------------------------------------------------- /serverless-eks/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as eks from "aws-cdk-lib/aws-eks"; 3 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 4 | import * as iam from "aws-cdk-lib/aws-iam"; 5 | import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"; 6 | import { getKubernetesTemplates } from "./templates"; 7 | import { Construct } from "constructs"; 8 | import { config } from "dotenv"; 9 | config(); 10 | 11 | class ServerlessEKSStack extends cdk.Stack { 12 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 13 | super(scope, id, props); 14 | 15 | const vpc = new ec2.Vpc(this, "vpc", { 16 | maxAzs: 3 17 | }); 18 | 19 | const mastersRole = new iam.Role(this, 'masters-role', { 20 | assumedBy: new iam.AccountRootPrincipal() 21 | }); 22 | 23 | const fargateProfileRole = new iam.Role(this, "fargate-profile-role", { 24 | assumedBy: new iam.ServicePrincipal("eks-fargate-pods.amazonaws.com"), 25 | managedPolicies: [ 26 | iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEKSFargatePodExecutionRolePolicy") 27 | ] 28 | }) 29 | 30 | const cluster = new eks.FargateCluster(this, "fargate-cluster", { 31 | version: eks.KubernetesVersion.V1_19, 32 | clusterName: "sls-eks", 33 | vpc, 34 | mastersRole, 35 | coreDnsComputeType: eks.CoreDnsComputeType.FARGATE, 36 | defaultProfile: { 37 | fargateProfileName: "default-profile", 38 | selectors: [ 39 | { namespace: "default" }, 40 | { namespace: "kube-system" } 41 | ], 42 | podExecutionRole: fargateProfileRole 43 | } 44 | }); 45 | 46 | const goAPIRepo = new ecrAssets.DockerImageAsset(this, "go-api-docker", { 47 | directory: "go-api" 48 | }); 49 | 50 | const graphqlAPIRepo = new ecrAssets.DockerImageAsset(this, "graphql-docker", { 51 | directory: "graphql-api" 52 | }); 53 | 54 | const apiTemplates = getKubernetesTemplates( 55 | goAPIRepo, //repo 56 | "go-api", //resource name 57 | 8080, //container port, 58 | 2 //replica number 59 | ); 60 | cluster.addManifest("api-resource", ...apiTemplates); 61 | 62 | const graphqlTemplates = getKubernetesTemplates( 63 | graphqlAPIRepo, //repo 64 | "graphql-api", //resource name 65 | 8090, //container port, 66 | 2 //replica number 67 | ); 68 | cluster.addManifest("graphql-resource", ...graphqlTemplates); 69 | } 70 | } 71 | 72 | const app = new cdk.App(); 73 | const stack = new ServerlessEKSStack(app, "ServerlessEksStack", { 74 | env: { 75 | region: process.env.AWS_REGION, 76 | account: process.env.AWS_ACCOUNT_ID 77 | } 78 | }); -------------------------------------------------------------------------------- /elasticsearch-cluster/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as es from "aws-cdk-lib/aws-elasticsearch"; 3 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 4 | import { Construct } from "constructs"; 5 | import { config } from "dotenv"; 6 | config(); 7 | 8 | const DOMAIN_NAME = "es-domain"; 9 | 10 | export class ElasticSearchStack extends cdk.Stack { 11 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 12 | super(scope, id, props); 13 | 14 | // Comment out for enabling VPC 15 | const vpc = new ec2.Vpc(this, "vpc", { 16 | maxAzs: 3 17 | }); 18 | const sg = new ec2.SecurityGroup(this, "sg", { 19 | vpc, 20 | allowAllOutbound: true, 21 | securityGroupName: "es-sg" 22 | }); 23 | sg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), "Allow access to port 80"); 24 | sg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), "Allow access to port 443"); 25 | 26 | const domain = new es.CfnDomain(this, "es-domain", { 27 | vpcOptions: { 28 | subnetIds: vpc.publicSubnets.slice(0,2).map(subnet=>subnet.subnetId), 29 | securityGroupIds: [sg.securityGroupId] 30 | }, 31 | domainName: DOMAIN_NAME, 32 | elasticsearchVersion: "6.8", 33 | elasticsearchClusterConfig: { 34 | instanceType: "t2.medium.elasticsearch", 35 | dedicatedMasterEnabled: true, 36 | dedicatedMasterCount: 2, 37 | dedicatedMasterType: "t2.medium.elasticsearch", 38 | instanceCount: 2, 39 | zoneAwarenessEnabled: true, 40 | zoneAwarenessConfig: { 41 | availabilityZoneCount: 2 42 | } 43 | }, 44 | ebsOptions: { 45 | ebsEnabled: true, 46 | volumeSize: 35, 47 | volumeType: "io1", 48 | iops: 1000 49 | }, 50 | accessPolicies: { 51 | Version: "2012-10-17", 52 | Statement: [ 53 | { 54 | Effect: "Allow", 55 | Principal: { 56 | "AWS": "*" 57 | }, 58 | "Action":"es:*", 59 | "Resource":`arn:aws:es:${process.env.AWS_REGION}:${process.env.ACCOUNT_ID}:domain/${DOMAIN_NAME}/*` 60 | } 61 | ] 62 | } 63 | }); 64 | 65 | new cdk.CfnOutput(this, "domain", {value: domain.attrDomainEndpoint as string}) 66 | new cdk.CfnOutput(this, "kibana", {value: `${domain.attrDomainEndpoint}/_plugin/kibana/` as string}) 67 | } 68 | } 69 | 70 | const app = new cdk.App(); 71 | new ElasticSearchStack(app, "ElasticSearchStack", { 72 | env: { 73 | account: process.env.AWS_ACCOUNT_ID, 74 | region: process.env.AWS_REGION 75 | } 76 | }); -------------------------------------------------------------------------------- /wordpress-ha/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 3 | import * as rds from "aws-cdk-lib/aws-rds"; 4 | import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns"; 5 | import * as ecs from "aws-cdk-lib/aws-ecs"; 6 | import { Construct } from "constructs"; 7 | require('dotenv').config(); 8 | 9 | const DB_PORT = +(process.env["DB_PORT"] as string); 10 | const DB_NAME = process.env["DB_NAME"] as string; 11 | const DB_USER = process.env["DB_USER"] as string 12 | const DB_PASSWORD = process.env["DB_PASSWORD"] as string; 13 | 14 | class WordpressHAStack extends cdk.Stack { 15 | constructor(construct: Construct, id: string, props?: cdk.StackProps) { 16 | super(construct, id, props); 17 | 18 | const vpc = new ec2.Vpc(this, "vpc", { 19 | maxAzs: 3 20 | }); 21 | 22 | const wordpressSg = new ec2.SecurityGroup(this, "wp-sg", { 23 | vpc: vpc, 24 | description: 'Wordpress SG' 25 | }); 26 | 27 | const dbCluster = new rds.DatabaseCluster(this, "db-cluster", { 28 | clusterIdentifier: "db-cluster", 29 | defaultDatabaseName: DB_NAME, 30 | engine: rds.DatabaseClusterEngine.AURORA, 31 | port: DB_PORT, 32 | credentials: { 33 | username: DB_USER, 34 | password: cdk.SecretValue.plainText(DB_PASSWORD) 35 | }, 36 | instanceProps: { 37 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), 38 | vpc, 39 | securityGroups: [wordpressSg] 40 | } 41 | }); 42 | 43 | const cluster = new ecs.Cluster(this, "ecs-cluster", { 44 | vpc, 45 | }); 46 | 47 | cluster.connections.addSecurityGroup(wordpressSg); 48 | 49 | const wordpressService = new ecs_patterns.ApplicationLoadBalancedEc2Service(this, "wordpress-service", { 50 | cluster, 51 | memoryLimitMiB: 1024, 52 | taskImageOptions: { 53 | image: ecs.ContainerImage.fromRegistry('wordpress'), 54 | environment: { 55 | WORDPRESS_DB_HOST: dbCluster.clusterEndpoint.socketAddress, 56 | WORDPRESS_DB_USER: DB_USER, 57 | WORDPRESS_DB_PASSWORD: DB_PASSWORD, 58 | WORDPRESS_DB_NAME: DB_NAME, 59 | }, 60 | }, 61 | desiredCount: 2, 62 | }); 63 | 64 | const scalableTarget = wordpressService.service.autoScaleTaskCount({ 65 | minCapacity: 2, 66 | maxCapacity: 5 67 | }); 68 | scalableTarget.scaleOnCpuUtilization('task-cpu-scaling', { 69 | targetUtilizationPercent: 20, 70 | }); 71 | } 72 | } 73 | 74 | const app = new cdk.App(); 75 | new WordpressHAStack(app, "WordpressStack", { 76 | env: { 77 | account: process.env.AWS_ACCOUNT_ID, 78 | region: process.env.AWS_REGION 79 | } 80 | }) 81 | 82 | -------------------------------------------------------------------------------- /backups/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as rds from "aws-cdk-lib/aws-rds"; 3 | import * as backup from "aws-cdk-lib/aws-backup"; 4 | import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; 5 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 6 | import { Backup, BackupProps } from "cdk-backup-plan"; 7 | import { config } from "dotenv"; 8 | import { Construct } from "constructs"; 9 | config(); 10 | 11 | class AWSBackupStack extends cdk.Stack { 12 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 13 | super(scope, id, props); 14 | 15 | const dynamoTable = new dynamodb.Table(this, "dynamo-table", { 16 | tableName: "dynamo-table", 17 | partitionKey: { name: "id", type: dynamodb.AttributeType.STRING }, 18 | billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, 19 | removalPolicy: cdk.RemovalPolicy.DESTROY 20 | }); 21 | 22 | const vpc = ec2.Vpc.fromLookup(this, "vpc", { 23 | isDefault: true, 24 | }); 25 | 26 | // We define the instance details here 27 | const ec2Instance = new ec2.Instance(this, 'Instance', { 28 | vpc, 29 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 30 | machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }) 31 | }); 32 | 33 | 34 | const auroraCluster = new rds.ServerlessCluster(this, "rds-cluster", { 35 | engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL, 36 | enableDataApi: true, 37 | parameterGroup: rds.ParameterGroup.fromParameterGroupName(this, 'ParameterGroup', "default.aurora-postgresql10"), 38 | }); 39 | 40 | const dynamoBackup = new Backup(this, "dynamo-backup", { 41 | backupPlanName: "dynamo-backup", 42 | backupRateHour: 2, 43 | backupCompletionWindow: cdk.Duration.hours(2), 44 | resources: [backup.BackupResource.fromDynamoDbTable(dynamoTable)], 45 | }); 46 | 47 | const auroraBackup = new Backup(this, "aurora-backup", { 48 | backupPlanName: "aurora-backup", 49 | backupRateHour: 2, 50 | backupCompletionWindow: cdk.Duration.hours(2), 51 | resources: [backup.BackupResource.fromRdsServerlessCluster(auroraCluster)] 52 | }); 53 | 54 | 55 | const ec2Backup = new Backup(this, "ec2-backup", { 56 | backupPlanName: "ec2-backup", 57 | backupRateHour: 2, 58 | backupCompletionWindow: cdk.Duration.hours(2), 59 | resources: [backup.BackupResource.fromEc2Instance(ec2Instance)] 60 | }); 61 | 62 | new cdk.CfnOutput(this, "dynamo-backup-id", { 63 | value: dynamoBackup.backupPlan.backupPlanId 64 | }); 65 | 66 | new cdk.CfnOutput(this, "aurora-backup-id", { 67 | value: auroraBackup.backupPlan.backupPlanId 68 | }); 69 | 70 | new cdk.CfnOutput(this, "ec2-backup-id", { 71 | value: ec2Backup.backupPlan.backupPlanId 72 | }); 73 | 74 | } 75 | } 76 | 77 | const app = new cdk.App(); 78 | new AWSBackupStack(app, "AWSBackupStack", { 79 | env: { 80 | account: process.env.AWS_ACCOUNT_ID, 81 | region: process.env.AWS_REGION 82 | } 83 | }); -------------------------------------------------------------------------------- /lambda-python-api/lambda-handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | import urllib.request 3 | import random 4 | 5 | authors = [ 6 | "Adam Lindsay Gordon", 7 | "Alan Seeger", 8 | "Alexander Pope", 9 | "Algernon Charles Swinburne", 10 | "Ambrose Bierce", 11 | "Amy Levy", 12 | "Andrew Marvell", 13 | "Ann Taylor", 14 | "Anne Bradstreet", 15 | "Anne Bronte", 16 | "Anne Killigrew", 17 | "Anne Kingsmill Finch", 18 | "Annie Louisa Walker", 19 | "Arthur Hugh Clough", 20 | "Ben Jonson", 21 | "Charles Kingsley", 22 | "Charles Sorley", 23 | "Charlotte Bronte", 24 | "Charlotte Smith", 25 | "Christina Rossetti", 26 | "Christopher Marlowe", 27 | "Christopher Smart", 28 | "Coventry Patmore", 29 | "Edgar Allan Poe", 30 | "Edmund Spenser", 31 | "Edward Fitzgerald", 32 | "Edward Lear", 33 | "Edward Taylor", 34 | "Edward Thomas", 35 | "Eliza Cook", 36 | "Elizabeth Barrett Browning", 37 | "Emily Bronte", 38 | "Emily Dickinson", 39 | "Emma Lazarus", 40 | "Ernest Dowson", 41 | "Eugene Field", 42 | "Francis Thompson", 43 | "Geoffrey Chaucer", 44 | "George Eliot", 45 | "George Gordon, Lord Byron", 46 | "George Herbert", 47 | "George Meredith", 48 | "Gerard Manley Hopkins", 49 | "Helen Hunt Jackson", 50 | "Henry David Thoreau", 51 | "Henry Vaughan", 52 | "Henry Wadsworth Longfellow", 53 | "Hugh Henry Brackenridge", 54 | "Isaac Watts", 55 | "James Henry Leigh Hunt", 56 | "James Thomson", 57 | "James Whitcomb Riley", 58 | "Jane Austen", 59 | "Jane Taylor", 60 | "John Clare", 61 | "John Donne", 62 | "John Dryden", 63 | "John Greenleaf Whittier", 64 | "John Keats", 65 | "John McCrae", 66 | "John Milton", 67 | "John Trumbull", 68 | "John Wilmot", 69 | "Jonathan Swift", 70 | "Joseph Warton", 71 | "Joyce Kilmer", 72 | "Julia Ward Howe", 73 | "Jupiter Hammon", 74 | "Katherine Philips", 75 | "Lady Mary Chudleigh", 76 | "Lewis Carroll", 77 | "Lord Alfred Tennyson", 78 | "Louisa May Alcott", 79 | "Major Henry Livingston, Jr.", 80 | "Mark Twain", 81 | "Mary Elizabeth Coleridge", 82 | "Matthew Arnold", 83 | "Matthew Prior", 84 | "Michael Drayton", 85 | "Oliver Goldsmith", 86 | "Oliver Wendell Holmes", 87 | "Oscar Wilde", 88 | "Paul Laurence Dunbar", 89 | "Percy Bysshe Shelley", 90 | "Philip Freneau", 91 | "Phillis Wheatley", 92 | "Ralph Waldo Emerson", 93 | "Richard Crashaw", 94 | "Richard Lovelace", 95 | "Robert Browning", 96 | "Robert Burns", 97 | "Robert Herrick", 98 | "Robert Louis Stevenson", 99 | "Robert Southey", 100 | "Robinson", 101 | "Rupert Brooke", 102 | "Samuel Coleridge", 103 | "Samuel Johnson", 104 | "Sarah Flower Adams", 105 | "Sidney Lanier", 106 | "Sir John Suckling", 107 | "Sir Philip Sidney", 108 | "Sir Thomas Wyatt", 109 | "Sir Walter Raleigh", 110 | "Sir Walter Scott", 111 | "Stephen Crane", 112 | "Thomas Campbell", 113 | "Thomas Chatterton", 114 | "Thomas Flatman", 115 | "Thomas Gray", 116 | "Thomas Hood", 117 | "Thomas Moore", 118 | "Thomas Warton", 119 | "Walt Whitman", 120 | "Walter Savage Landor", 121 | "Wilfred Owen", 122 | "William Allingham", 123 | "William Barnes", 124 | "William Blake", 125 | "William Browne", 126 | "William Cowper", 127 | "William Cullen Bryant", 128 | "William Ernest Henley", 129 | "William Lisle Bowles", 130 | "William Morris", 131 | "William Shakespeare", 132 | "William Topaz McGonagall", 133 | "William Vaughn Moody", 134 | "William Wordsworth" 135 | ] 136 | 137 | poet_api_url = "poetrydb.org" 138 | 139 | def handler(event, context): 140 | author = authors[random.randint(0, len(authors)-1)] 141 | url = urllib.parse.quote("{}/author/{}".format(poet_api_url, author)) 142 | url = "http://{}".format(url) 143 | response = json.loads(urllib.request.urlopen(url).read()) 144 | return { 145 | "statusCode": 200, 146 | "body": json.dumps(response[random.randint(0, len(response)-1)]) 147 | } -------------------------------------------------------------------------------- /elb-lambda-api/lambda-handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | import urllib.request 3 | import random 4 | 5 | authors = [ 6 | "Adam Lindsay Gordon", 7 | "Alan Seeger", 8 | "Alexander Pope", 9 | "Algernon Charles Swinburne", 10 | "Ambrose Bierce", 11 | "Amy Levy", 12 | "Andrew Marvell", 13 | "Ann Taylor", 14 | "Anne Bradstreet", 15 | "Anne Bronte", 16 | "Anne Killigrew", 17 | "Anne Kingsmill Finch", 18 | "Annie Louisa Walker", 19 | "Arthur Hugh Clough", 20 | "Ben Jonson", 21 | "Charles Kingsley", 22 | "Charles Sorley", 23 | "Charlotte Bronte", 24 | "Charlotte Smith", 25 | "Christina Rossetti", 26 | "Christopher Marlowe", 27 | "Christopher Smart", 28 | "Coventry Patmore", 29 | "Edgar Allan Poe", 30 | "Edmund Spenser", 31 | "Edward Fitzgerald", 32 | "Edward Lear", 33 | "Edward Taylor", 34 | "Edward Thomas", 35 | "Eliza Cook", 36 | "Elizabeth Barrett Browning", 37 | "Emily Bronte", 38 | "Emily Dickinson", 39 | "Emma Lazarus", 40 | "Ernest Dowson", 41 | "Eugene Field", 42 | "Francis Thompson", 43 | "Geoffrey Chaucer", 44 | "George Eliot", 45 | "George Gordon, Lord Byron", 46 | "George Herbert", 47 | "George Meredith", 48 | "Gerard Manley Hopkins", 49 | "Helen Hunt Jackson", 50 | "Henry David Thoreau", 51 | "Henry Vaughan", 52 | "Henry Wadsworth Longfellow", 53 | "Hugh Henry Brackenridge", 54 | "Isaac Watts", 55 | "James Henry Leigh Hunt", 56 | "James Thomson", 57 | "James Whitcomb Riley", 58 | "Jane Austen", 59 | "Jane Taylor", 60 | "John Clare", 61 | "John Donne", 62 | "John Dryden", 63 | "John Greenleaf Whittier", 64 | "John Keats", 65 | "John McCrae", 66 | "John Milton", 67 | "John Trumbull", 68 | "John Wilmot", 69 | "Jonathan Swift", 70 | "Joseph Warton", 71 | "Joyce Kilmer", 72 | "Julia Ward Howe", 73 | "Jupiter Hammon", 74 | "Katherine Philips", 75 | "Lady Mary Chudleigh", 76 | "Lewis Carroll", 77 | "Lord Alfred Tennyson", 78 | "Louisa May Alcott", 79 | "Major Henry Livingston, Jr.", 80 | "Mark Twain", 81 | "Mary Elizabeth Coleridge", 82 | "Matthew Arnold", 83 | "Matthew Prior", 84 | "Michael Drayton", 85 | "Oliver Goldsmith", 86 | "Oliver Wendell Holmes", 87 | "Oscar Wilde", 88 | "Paul Laurence Dunbar", 89 | "Percy Bysshe Shelley", 90 | "Philip Freneau", 91 | "Phillis Wheatley", 92 | "Ralph Waldo Emerson", 93 | "Richard Crashaw", 94 | "Richard Lovelace", 95 | "Robert Browning", 96 | "Robert Burns", 97 | "Robert Herrick", 98 | "Robert Louis Stevenson", 99 | "Robert Southey", 100 | "Robinson", 101 | "Rupert Brooke", 102 | "Samuel Coleridge", 103 | "Samuel Johnson", 104 | "Sarah Flower Adams", 105 | "Sidney Lanier", 106 | "Sir John Suckling", 107 | "Sir Philip Sidney", 108 | "Sir Thomas Wyatt", 109 | "Sir Walter Raleigh", 110 | "Sir Walter Scott", 111 | "Stephen Crane", 112 | "Thomas Campbell", 113 | "Thomas Chatterton", 114 | "Thomas Flatman", 115 | "Thomas Gray", 116 | "Thomas Hood", 117 | "Thomas Moore", 118 | "Thomas Warton", 119 | "Walt Whitman", 120 | "Walter Savage Landor", 121 | "Wilfred Owen", 122 | "William Allingham", 123 | "William Barnes", 124 | "William Blake", 125 | "William Browne", 126 | "William Cowper", 127 | "William Cullen Bryant", 128 | "William Ernest Henley", 129 | "William Lisle Bowles", 130 | "William Morris", 131 | "William Shakespeare", 132 | "William Topaz McGonagall", 133 | "William Vaughn Moody", 134 | "William Wordsworth" 135 | ] 136 | 137 | poet_api_url = "poetrydb.org" 138 | 139 | def handler(event, context): 140 | author = authors[random.randint(0, len(authors)-1)] 141 | url = urllib.parse.quote("{}/author/{}".format(poet_api_url, author)) 142 | url = "http://{}".format(url) 143 | response = json.loads(urllib.request.urlopen(url).read()) 144 | return { 145 | "statusCode": 200, 146 | "body": json.dumps(response[random.randint(0, len(response)-1)]), 147 | "statusDescription": "200 OK", 148 | "isBase64Encoded": False, 149 | "headers": { 150 | "Content-Type": "application/json" 151 | }, 152 | } -------------------------------------------------------------------------------- /docdb-lambda-api/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as lambda from "aws-cdk-lib/aws-lambda"; 3 | import * as apigateway from "aws-cdk-lib/aws-apigateway"; 4 | import * as docdb from "aws-cdk-lib/aws-docdb"; 5 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 6 | import { Construct } from "constructs"; 7 | import { config } from "dotenv"; 8 | config(); 9 | 10 | class DocdbLambdaAPIStack extends cdk.Stack { 11 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 12 | super(scope, id, props); 13 | 14 | const vpcCidr = "10.0.0.0/21"; 15 | const port = 27017; 16 | 17 | const vpc = new ec2.Vpc(this, "vpc", { 18 | cidr: vpcCidr, 19 | subnetConfiguration: [ 20 | { 21 | subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, 22 | cidrMask: 24, 23 | name: "PrivateSubnet1" 24 | }, 25 | { 26 | subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, 27 | cidrMask: 24, 28 | name: "PrivateSubnet2" 29 | }, 30 | { 31 | subnetType: ec2.SubnetType.PUBLIC, 32 | cidrMask: 28, 33 | name: "PublicSubnet1" 34 | } 35 | ] 36 | }); 37 | 38 | const sg = new ec2.SecurityGroup(this, "docdb-lambda-sg", { 39 | vpc, 40 | securityGroupName: "docdb-lambda-sg" 41 | }); 42 | 43 | const subnetGroup = new docdb.CfnDBSubnetGroup(this, "subnet-group", { 44 | subnetIds: vpc.privateSubnets.map(x=>x.subnetId), 45 | dbSubnetGroupName: "subnet-group", 46 | dbSubnetGroupDescription: "Subnet Group for DocDB" 47 | }); 48 | 49 | const dbCluster = new docdb.CfnDBCluster(this, "db-cluster", { 50 | storageEncrypted: true, 51 | availabilityZones: vpc.availabilityZones.splice(3), 52 | dbClusterIdentifier: "docdb", 53 | masterUsername: "dbuser", 54 | masterUserPassword: process.env.MASTER_USER_PASSWORD as string, 55 | vpcSecurityGroupIds: [sg.securityGroupId], 56 | dbSubnetGroupName: subnetGroup.dbSubnetGroupName, 57 | port 58 | }); 59 | dbCluster.addDependsOn(subnetGroup) 60 | 61 | const dbInstance = new docdb.CfnDBInstance(this, "db-instance", { 62 | dbClusterIdentifier: dbCluster.ref, 63 | autoMinorVersionUpgrade: true, 64 | dbInstanceClass: "db.r5.large", 65 | dbInstanceIdentifier: "staging" 66 | }); 67 | dbInstance.addDependsOn(dbCluster); 68 | 69 | sg.addIngressRule(ec2.Peer.ipv4(vpcCidr), ec2.Port.tcp(port)); 70 | 71 | const DB_URL = `mongodb://${dbCluster.masterUsername}:${dbCluster.masterUserPassword}@${dbCluster.attrEndpoint}:${dbCluster.attrPort}` 72 | const DB_NAME = dbInstance.dbInstanceIdentifier as string; 73 | 74 | const urlShortener = new lambda.Function(this, "urlShortener", { 75 | functionName: "urlShortener", 76 | runtime: lambda.Runtime.NODEJS_10_X, 77 | vpc, 78 | code: new lambda.AssetCode("src"), 79 | handler: "urlShortener.handler", 80 | timeout: cdk.Duration.seconds(60), 81 | securityGroups: [sg], 82 | environment: { 83 | DB_URL, 84 | DB_NAME 85 | }, 86 | }); 87 | 88 | const getLongURL = new lambda.Function(this, "getLongURL", { 89 | functionName: "getLongURL", 90 | runtime: lambda.Runtime.NODEJS_10_X, 91 | vpc, 92 | code: new lambda.AssetCode("src"), 93 | handler: "getLongURL.handler", 94 | timeout: cdk.Duration.seconds(60), 95 | securityGroups: [sg], 96 | environment: { 97 | DB_URL, 98 | DB_NAME 99 | } 100 | }); 101 | 102 | const api = new apigateway.RestApi(this, "api", { 103 | restApiName: "url-shortener" 104 | }); 105 | 106 | const urls = api.root.addResource("urls") 107 | const urlShortenerLambdaIntegration = new apigateway.LambdaIntegration(urlShortener); 108 | urls.addMethod("POST", urlShortenerLambdaIntegration); 109 | 110 | const singleURL = urls.addResource(`{id}`); 111 | const getLongURLLambdaIntegration = new apigateway.LambdaIntegration(getLongURL); 112 | singleURL.addMethod("GET", getLongURLLambdaIntegration); 113 | 114 | new cdk.CfnOutput(this, "db-url", { 115 | value: DB_URL 116 | }); 117 | } 118 | } 119 | 120 | const app = new cdk.App(); 121 | new DocdbLambdaAPIStack(app, "DocdbLambdaAPIStack", { 122 | env: { 123 | region: process.env.AWS_REGION, 124 | account: process.env.AWS_ACCOUNT_ID 125 | } 126 | }); -------------------------------------------------------------------------------- /rds-proxy/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as rds from "aws-cdk-lib/aws-rds"; 3 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 4 | import * as iam from "aws-cdk-lib/aws-iam"; 5 | import * as lambda from "aws-cdk-lib/aws-lambda"; 6 | import { config } from "dotenv"; 7 | config(); 8 | 9 | const DB_PORT = process.env["DB_PORT"] as string; 10 | const DB_NAME = process.env["DB_NAME"] as string; 11 | const DB_USER = process.env["DB_USER"] as string 12 | const NUM_OF_LAMBDA_FUNCTIONS = 10; 13 | 14 | class RdsProxyStack extends cdk.Stack { 15 | constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { 16 | super(scope, id, props); 17 | 18 | const vpc = new ec2.Vpc(this, "vpc", { 19 | maxAzs: 3 20 | }); 21 | 22 | const dbClusterSg = new ec2.SecurityGroup(this, "db-instance-sg", { 23 | vpc, 24 | description: 'RDS Cluster SG' 25 | }); 26 | 27 | const lambdaSg = new ec2.SecurityGroup(this, "lambda-sg", { 28 | vpc, 29 | description: "Lambda SG" 30 | }); 31 | 32 | const dbProxySg = new ec2.SecurityGroup(this, "db-proxy-sg", { 33 | vpc, 34 | description: "RDS Proxy SG" 35 | }); 36 | 37 | dbClusterSg.addIngressRule(lambdaSg, ec2.Port.tcp(+DB_PORT)); 38 | dbProxySg.addIngressRule(lambdaSg, ec2.Port.tcp(+DB_PORT)); 39 | dbClusterSg.addIngressRule(dbProxySg, ec2.Port.tcp(+DB_PORT)); 40 | 41 | 42 | const dbCluster = new rds.DatabaseCluster(this, "db-cluster", { 43 | clusterIdentifier: "db-cluster", 44 | defaultDatabaseName: DB_NAME, 45 | engine: rds.DatabaseClusterEngine.AURORA_MYSQL, 46 | port: +DB_PORT, 47 | instanceProps: { 48 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), 49 | vpc, 50 | securityGroups: [dbClusterSg] 51 | }, 52 | removalPolicy: cdk.RemovalPolicy.DESTROY, 53 | instanceIdentifierBase: "dbcluster", 54 | credentials: { 55 | username: DB_USER 56 | } 57 | }); 58 | 59 | const dbProxy = new rds.DatabaseProxy(this, "db-proxy", { 60 | vpc, 61 | vpcSubnets: { 62 | subnetType: ec2.SubnetType.PUBLIC 63 | }, 64 | borrowTimeout: cdk.Duration.seconds(30), 65 | proxyTarget: rds.ProxyTarget.fromCluster(dbCluster), 66 | secrets: [dbCluster.secret!], 67 | dbProxyName: "db-proxy", 68 | securityGroups: [dbProxySg], 69 | requireTLS: true, 70 | iamAuth: true 71 | }); 72 | 73 | const lambdaRole = new iam.Role(this, "lambda-role", { 74 | roleName: "lambda-role", 75 | assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"), 76 | inlinePolicies: { 77 | "rds-connect": new iam.PolicyDocument({ 78 | statements: [ 79 | new iam.PolicyStatement({ 80 | actions: [ "rds-db:connect" ], 81 | resources: ["*"] 82 | }), 83 | new iam.PolicyStatement({ 84 | actions: [ 85 | "logs:CreateLogGroup", 86 | "logs:CreateLogStream", 87 | "logs:PutLogEvents", 88 | "ec2:CreateNetworkInterface", 89 | "ec2:DescribeNetworkInterfaces", 90 | "ec2:DeleteNetworkInterface" 91 | ], 92 | resources: ["*"] 93 | }) 94 | ] 95 | }) 96 | } 97 | }); 98 | 99 | for(let i=0; ix.subnetId), 95 | securityGroupIds: [sg.securityGroupId] 96 | }, 97 | serviceRole: batchServiceRole.roleArn, 98 | type: "MANAGED", 99 | state: "ENABLED" 100 | }); 101 | computeEnvironemnt.addDependsOn(instanceProfile); 102 | 103 | const jobQueue = new batch.CfnJobQueue(this, "job-queue", { 104 | jobQueueName, 105 | priority: 1, 106 | state: "ENABLED", 107 | computeEnvironmentOrder: [ 108 | {order: 1, computeEnvironment: computeEnvironemnt.computeEnvironmentName as string} 109 | ] 110 | }); 111 | jobQueue.addDependsOn(computeEnvironemnt); 112 | 113 | const lambdaFunction = new lambda.Function(this, "lambda-function", { 114 | functionName, 115 | code: new lambda.InlineCode(readFileSync(srcPath, {encoding: "utf-8"})), 116 | handler: "index.handler", 117 | timeout: cdk.Duration.seconds(30), 118 | runtime: lambda.Runtime.NODEJS_8_10, 119 | environment: { 120 | REGION: process.env.AWS_REGION as string, 121 | JOB_DEFINITION: jobDefinitionName, 122 | JOB_QUEUE: jobQueueName 123 | }, 124 | initialPolicy: [jobSubmitStatement] 125 | }); 126 | const rule = new events.Rule(this, 'event-rule', { 127 | schedule: events.Schedule.expression('rate(4 hours)') 128 | }); 129 | rule.addTarget(new targets.LambdaFunction(lambdaFunction)); 130 | } 131 | } 132 | 133 | const app = new cdk.App(); 134 | new BatchStack(app, "BatchStack", { 135 | env: { 136 | account: process.env.AWS_ACCOUNT_ID, 137 | region: process.env.AWS_REGION, 138 | } 139 | }); -------------------------------------------------------------------------------- /transit-gateway/index.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from "aws-cdk-lib"; 2 | import * as ec2 from "aws-cdk-lib/aws-ec2"; 3 | import { Construct } from "constructs"; 4 | import { config } from "dotenv"; 5 | config(); 6 | 7 | class TransitGatewayStack extends cdk.Stack { 8 | constructor(scope: Construct, id: string, props?: cdk.StackProps) { 9 | super(scope, id, props); 10 | 11 | const vpc1 = new ec2.Vpc(this, "vpc1", { 12 | maxAzs: 2, 13 | cidr: "10.10.0.0/24", 14 | enableDnsSupport: true, 15 | natGateways: 1 16 | }); 17 | 18 | const vpc2 = new ec2.Vpc(this, "vpc2", { 19 | maxAzs: 2, 20 | cidr: "192.168.1.0/24", 21 | enableDnsSupport: true, 22 | natGateways: 1 23 | }); 24 | 25 | const vpc3 = new ec2.Vpc(this, "vpc3", { 26 | maxAzs: 2, 27 | cidr: "172.168.1.0/24", 28 | enableDnsSupport: true, 29 | natGateways: 1 30 | }); 31 | 32 | const sg1 = new ec2.SecurityGroup(this, 'sg1', { 33 | vpc: vpc1, 34 | securityGroupName: "sg1", 35 | }); 36 | sg1.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), 'allow port 80'); 37 | sg1.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow port 22'); 38 | 39 | const sg2 = new ec2.SecurityGroup(this, 'sg2', { 40 | vpc: vpc2, 41 | securityGroupName: "sg2", 42 | }); 43 | sg2.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow port 22'); 44 | 45 | const sg3 = new ec2.SecurityGroup(this, "sg3", { 46 | vpc: vpc3, 47 | securityGroupName: "sg3" 48 | }); 49 | sg3.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), 'allow port 80'); 50 | sg3.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow port 22'); 51 | 52 | const userData = ec2.UserData.forLinux(); 53 | userData.addCommands("sudo amazon-linux-extras install nginx1.12 -y"); 54 | userData.addCommands("sudo chkconfig nginx on"); 55 | userData.addCommands("sudo service nginx start"); 56 | 57 | const instance1 = new ec2.Instance(this, "instance1", { 58 | instanceName: "instance1", 59 | vpc: vpc1, 60 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 61 | machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), 62 | vpcSubnets: { 63 | subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, 64 | }, 65 | securityGroup: sg1, 66 | userData 67 | }); 68 | 69 | const instance2 = new ec2.Instance(this, "instance2", { 70 | instanceName: "instance2", 71 | vpc: vpc2, 72 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 73 | machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), 74 | vpcSubnets: { 75 | subnetType: ec2.SubnetType.PUBLIC, 76 | }, 77 | securityGroup: sg2 78 | }); 79 | 80 | const instance3 = new ec2.Instance(this, "instance3", { 81 | instanceName: "instance3", 82 | vpc: vpc3, 83 | instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), 84 | machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), 85 | vpcSubnets: { 86 | subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, 87 | }, 88 | securityGroup: sg3, 89 | userData 90 | }); 91 | 92 | const transitGateway = new ec2.CfnTransitGateway(this, "transit-gateway", { 93 | autoAcceptSharedAttachments: "enable", 94 | defaultRouteTableAssociation: "enable", 95 | dnsSupport: "enable" 96 | }); 97 | 98 | const attachment1 = new ec2.CfnTransitGatewayAttachment(this, "tg-attachment1", { 99 | vpcId: vpc1.vpcId, 100 | transitGatewayId: transitGateway.ref, 101 | subnetIds: [vpc1.privateSubnets[0].subnetId, vpc1.privateSubnets[1].subnetId] 102 | }); 103 | attachment1.addDependsOn(transitGateway); 104 | const attachment2 = new ec2.CfnTransitGatewayAttachment(this, "tg-attachment2", { 105 | vpcId: vpc2.vpcId, 106 | transitGatewayId: transitGateway.ref, 107 | subnetIds: [vpc2.privateSubnets[0].subnetId, vpc2.privateSubnets[1].subnetId] 108 | }); 109 | attachment2.addDependsOn(transitGateway); 110 | const attachment3 = new ec2.CfnTransitGatewayAttachment(this, "tg-attachment3", { 111 | vpcId: vpc3.vpcId, 112 | transitGatewayId: transitGateway.ref, 113 | subnetIds: [vpc3.privateSubnets[0].subnetId, vpc3.privateSubnets[1].subnetId] 114 | }); 115 | attachment3.addDependsOn(transitGateway); 116 | 117 | const vpc1Subnets = [...vpc1.privateSubnets, ...vpc1.publicSubnets]; 118 | const vpc2Subnets = [...vpc2.privateSubnets, ...vpc2.publicSubnets]; 119 | const vpc3Subnets = [...vpc3.privateSubnets, ...vpc3.publicSubnets]; 120 | 121 | // Add routes to every subnet 122 | vpc1Subnets.map((subnet, i)=>{ 123 | new ec2.CfnRoute(this, `vpc1.2-${i}`, { 124 | routeTableId: subnet.routeTable.routeTableId, 125 | destinationCidrBlock: vpc2.vpcCidrBlock, 126 | transitGatewayId: transitGateway.ref 127 | }).addDependsOn(attachment1); 128 | 129 | new ec2.CfnRoute(this, `vpc1.3-${i}`, { 130 | routeTableId: subnet.routeTable.routeTableId, 131 | destinationCidrBlock: vpc3.vpcCidrBlock, 132 | transitGatewayId: transitGateway.ref 133 | }).addDependsOn(attachment1); 134 | }); 135 | 136 | // Add routes to every subnet 137 | vpc2Subnets.map((subnet, i)=>{ 138 | new ec2.CfnRoute(this, `vpc2.1-${i}`, { 139 | routeTableId: subnet.routeTable.routeTableId, 140 | destinationCidrBlock: vpc1.vpcCidrBlock, 141 | transitGatewayId: transitGateway.ref 142 | }).addDependsOn(attachment2); 143 | new ec2.CfnRoute(this, `vpc2.3-${i}`, { 144 | routeTableId: subnet.routeTable.routeTableId, 145 | destinationCidrBlock: vpc3.vpcCidrBlock, 146 | transitGatewayId: transitGateway.ref 147 | }).addDependsOn(attachment2); 148 | }); 149 | 150 | // Add routes to every subnet 151 | vpc3Subnets.map((subnet, i)=>{ 152 | new ec2.CfnRoute(this, `vpc3.1-${i}`, { 153 | routeTableId: subnet.routeTable.routeTableId, 154 | destinationCidrBlock: vpc1.vpcCidrBlock, 155 | transitGatewayId: transitGateway.ref 156 | }).addDependsOn(attachment3); 157 | new ec2.CfnRoute(this, `vpc3.2-${i}`, { 158 | routeTableId: subnet.routeTable.routeTableId, 159 | destinationCidrBlock: vpc2.vpcCidrBlock, 160 | transitGatewayId: transitGateway.ref 161 | }).addDependsOn(attachment3); 162 | }); 163 | 164 | new cdk.CfnOutput(this, "instance1-dns", {value: instance1.instancePrivateDnsName}); 165 | new cdk.CfnOutput(this, "instance2-dns", {value: instance2.instancePrivateDnsName}); 166 | new cdk.CfnOutput(this, "instance3-dns", {value: instance3.instancePrivateDnsName}); 167 | } 168 | } 169 | 170 | const app = new cdk.App(); 171 | new TransitGatewayStack(app, "TransitGatewayStack", { 172 | env: { 173 | account: process.env.AWS_ACCOUNT_ID, 174 | region: process.env.AWS_REGION 175 | } 176 | }); --------------------------------------------------------------------------------