Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing a Deployment solution for AWS #152

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions deploy/aws/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out

# Parcel default cache directory
.parcel-cache
6 changes: 6 additions & 0 deletions deploy/aws/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
15 changes: 15 additions & 0 deletions deploy/aws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This is the deployment Infrastructure as code for use with AWS

## configuration, please set them as env var
* `LOCALTUNNEL_BASE_DOMAIN` the root domain in route53
* `LOCALTUNNEL_ROUTE53_ID` the ID of the route53 hosted zone for the domain
* `LOCALTUNNEL_DOMAIN` the domain of the localtunnel server
## After setting the environment variables, simply run:
```npm i && cdk deploy```

## Deployed Architecture
1. This Architecture brings up a ECS fargate cluster and 2 public subnets

2. It spins up a container that runs using fargate runtype with the upstream docker image

3. the container image is placed in one of the two private subnets
8 changes: 8 additions & 0 deletions deploy/aws/bin/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { DeployStack } from '../lib/deploy-stack';

let app = new cdk.App();
// replace them with HostedZoneID in route53, the domain name for the localtunnel, and the hosted zone domain
new DeployStack(app, 'DeployStack', process.env.LOCALTUNNEL_ROUTE53_ID as string , process.env.LOCALTUNNEL_BASE_DOMAIN as string, process.env.LOCALTUNNEL_DOMAIN as string);
9 changes: 9 additions & 0 deletions deploy/aws/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"app": "npx ts-node --prefer-ts-exts bin/deploy.ts",
"context": {
"@aws-cdk/core:enableStackNameDuplicates": "true",
"aws-cdk:enableDiffNoFail": "true",
"@aws-cdk/core:stackRelativeExports": "true",
"@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true
}
}
7 changes: 7 additions & 0 deletions deploy/aws/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
77 changes: 77 additions & 0 deletions deploy/aws/lib/deploy-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as cdk from '@aws-cdk/core';

// import dependencies for ECS and building a VPC
import * as ec2 from "@aws-cdk/aws-ec2";
import * as ecs from "@aws-cdk/aws-ecs";
import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns";

// tls certificate with ACM
import * as route53 from '@aws-cdk/aws-route53';
import * as acm from '@aws-cdk/aws-certificatemanager';
import { FargateTaskDefinition } from '@aws-cdk/aws-ecs';
export class DeployStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, hostedZoneID: string, zoneName: string, domainName: string, props?: cdk.StackProps) {
super(scope, id, props);
// create vpc with 3 subnets
const vpc = new ec2.Vpc(this, "LocalTunnelVPC", {
maxAzs: 3,
natGateways: 0
})
// create the ecs cluster
const cluster = new ecs.Cluster(this, "LocalTunnelCluster", {
vpc: vpc
})
// create acm cert
const DNSZone = route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
zoneName: domainName,
hostedZoneId: hostedZoneID
})
// add wildcard CNAME
new route53.CnameRecord(this, 'CnameRecordWildcard', {
zone: DNSZone,
recordName: "*",
domainName: domainName
})
const cert = new acm.Certificate(this, 'Cert', {
domainName: domainName,
subjectAlternativeNames: ["*."+domainName],
validation: acm.CertificateValidation.fromDns(DNSZone)
})


// task definition
let FgTask = new FargateTaskDefinition(this, "LocaltunnelDefinition", {
cpu: 256,
memoryLimitMiB: 512,
})
FgTask.addContainer("localtunnel", {
image: ecs.ContainerImage.fromRegistry("defunctzombie/localtunnel-server:latest"),
cpu: 128,
entryPoint: ["node", "-r", "esm", "./bin/server", "--domain", domainName],

}).addPortMappings({
containerPort: 80
})

// create LBed Fargate service
let localtunnelsvc = new ecs_patterns.ApplicationLoadBalancedFargateService(this, "LocalTunnelService", {
cluster: cluster,
cpu: 512,
desiredCount: 1,
taskDefinition: FgTask,
memoryLimitMiB: 2048,
publicLoadBalancer: true,
certificate: cert,
redirectHTTP: true,
recordType: ecs_patterns.ApplicationLoadBalancedServiceRecordType.ALIAS,
listenerPort: 443,
domainName: domainName,
domainZone: DNSZone,
assignPublicIp: true
})
// set health route
localtunnelsvc.targetGroup.configureHealthCheck({
path: "/api/status"
})
}
}
32 changes: 32 additions & 0 deletions deploy/aws/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "deploy",
"version": "0.1.0",
"bin": {
"deploy": "bin/deploy.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "jest",
"cdk": "cdk"
},
"devDependencies": {
"@aws-cdk/assert": "1.75.0",
"@types/jest": "^26.0.10",
"@types/node": "10.17.27",
"jest": "^26.4.2",
"ts-jest": "^26.2.0",
"aws-cdk": "1.75.0",
"ts-node": "^9.0.0",
"typescript": "~3.9.7"
},
"dependencies": {
"@aws-cdk/aws-certificatemanager": "^1.91.0",
"@aws-cdk/aws-ec2": "^1.91.0",
"@aws-cdk/aws-ecs": "^1.91.0",
"@aws-cdk/aws-ecs-patterns": "^1.91.0",
"@aws-cdk/aws-route53": "^1.91.0",
"@aws-cdk/core": "1.75.0",
"source-map-support": "^0.5.16"
}
}
13 changes: 13 additions & 0 deletions deploy/aws/test/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { expect as expectCDK, matchTemplate, MatchStyle } from '@aws-cdk/assert';
import * as cdk from '@aws-cdk/core';
import * as Deploy from '../lib/deploy-stack';

test('Empty Stack', () => {
const app = new cdk.App();
// WHEN
const stack = new Deploy.DeployStack(app, 'MyTestStack');
// THEN
expectCDK(stack).to(matchTemplate({
"Resources": {}
}, MatchStyle.EXACT))
});
23 changes: 23 additions & 0 deletions deploy/aws/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"lib": ["es2018"],
"declaration": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": false,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"typeRoots": ["./node_modules/@types"]
},
"exclude": ["cdk.out"]
}