From 0255b8d9735938516b7c71dc9f0f2eb1ac1462f0 Mon Sep 17 00:00:00 2001 From: Levi Blackstone Date: Thu, 30 Sep 2021 16:55:20 -0600 Subject: [PATCH] Add aws-native ECS example (#1086) --- aws-native-ts-ecs/.gitignore | 2 + aws-native-ts-ecs/Pulumi.yaml | 3 + aws-native-ts-ecs/README.md | 108 ++++++++++++++++++++++++++++++ aws-native-ts-ecs/classic.ts | 66 ++++++++++++++++++ aws-native-ts-ecs/index.ts | 58 ++++++++++++++++ aws-native-ts-ecs/package.json | 11 +++ aws-native-ts-ecs/tsconfig.json | 19 ++++++ aws-native-ts-s3-folder/README.md | 2 +- aws-native-ts-s3-folder/index.ts | 2 +- 9 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 aws-native-ts-ecs/.gitignore create mode 100644 aws-native-ts-ecs/Pulumi.yaml create mode 100644 aws-native-ts-ecs/README.md create mode 100644 aws-native-ts-ecs/classic.ts create mode 100644 aws-native-ts-ecs/index.ts create mode 100644 aws-native-ts-ecs/package.json create mode 100644 aws-native-ts-ecs/tsconfig.json diff --git a/aws-native-ts-ecs/.gitignore b/aws-native-ts-ecs/.gitignore new file mode 100644 index 000000000..c6958891d --- /dev/null +++ b/aws-native-ts-ecs/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/node_modules/ diff --git a/aws-native-ts-ecs/Pulumi.yaml b/aws-native-ts-ecs/Pulumi.yaml new file mode 100644 index 000000000..13460d061 --- /dev/null +++ b/aws-native-ts-ecs/Pulumi.yaml @@ -0,0 +1,3 @@ +name: aws-native-ts-ecs +runtime: nodejs +description: A TypeScript Pulumi program with AWS Native provider that provisions an ECS Cluster diff --git a/aws-native-ts-ecs/README.md b/aws-native-ts-ecs/README.md new file mode 100644 index 000000000..2620daa36 --- /dev/null +++ b/aws-native-ts-ecs/README.md @@ -0,0 +1,108 @@ +[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new) + +# Create an ECS cluster on AWS + +Create an ECS cluster, and deploy a task and service. + +Note: Some resources are not yet supported by the Native AWS provider, so we are using both the Native +and Classic provider in this example. The resources will be updated to use native resources as they are +available in AWS's Cloud Control API. + +## Deploying and running the program + +Note: some values in this example will be different from run to run. These values are indicated +with `***`. + +1. Create a new stack: + + ```bash + $ pulumi stack init dev + ``` + +1. Set the AWS region: + + Either using an environment variable + ```bash + $ export AWS_REGION=us-west-2 + ``` + + Or with the stack config + ```bash + $ pulumi config set aws:region us-west-2 + $ pulumi config set aws-native:region us-west-2 + ``` + +1. Restore NPM modules via `npm install` or `yarn install`. + +1. Run `pulumi up` to preview and deploy changes. After the preview is shown you will be + prompted if you want to continue or not. + + ```bash + $ pulumi up + Previewing update (dev) + ... + + Updating (dev) + + View Live: https://app.pulumi.com/***/aws-native-ts-ecs/dev/updates/1 + + Type Name Status + + pulumi:pulumi:Stack aws-native-ts-ecs-dev created + + ├─ aws:iam:Role task-exec-role created + + ├─ aws-native:ecs:Cluster cluster created + + ├─ aws:lb:TargetGroup app-tg created + + ├─ aws:ec2:SecurityGroup web-secgrp created + + ├─ aws:iam:RolePolicyAttachment task-exec-policy created + + ├─ aws-native:ecs:TaskDefinition app-task created + + ├─ aws:lb:LoadBalancer app-lb created + + ├─ aws-native:elasticloadbalancingv2:Listener web created + + └─ aws-native:ecs:Service app-svc created + + Outputs: + url: "app-lb-***.us-west-2.elb.amazonaws.com" + + Resources: + + 10 created + + Duration: *** + ``` + +1. To see the resources that were created, run `pulumi stack output`: + + ```bash + $ pulumi stack output + Current stack outputs (1): + OUTPUT VALUE + url app-lb-***.us-west-2.elb.amazonaws.com + ``` + +1. Use curl to confirm that NGINX was deployed successfully: + + ```bash + $ curl $(pulumi stack output url) + + + + Welcome to nginx! + + + +

Welcome to nginx!

+

If you see this page, the nginx web server is successfully installed and + working. Further configuration is required.

+ +

For online documentation and support please refer to + nginx.org.
+ Commercial support is available at + nginx.com.

+ +

Thank you for using nginx.

+ + + ``` + +1. To clean up resources, run `pulumi destroy` and answer the confirmation question at the prompt. diff --git a/aws-native-ts-ecs/classic.ts b/aws-native-ts-ecs/classic.ts new file mode 100644 index 000000000..10fa369d9 --- /dev/null +++ b/aws-native-ts-ecs/classic.ts @@ -0,0 +1,66 @@ +// Copyright 2016-2021, Pulumi Corporation. + +import * as aws from "@pulumi/aws"; +import * as pulumi from "@pulumi/pulumi"; + +// Note: Some resources are not yet supported by the Native AWS provider, so we are using both the Native +// and Classic provider in this example. The resources will be updated to use native resources as they are +// available in AWS's Cloud Control API. + +const defaultVpc = pulumi.output(aws.ec2.getVpc({default: true})); +const defaultVpcSubnets = defaultVpc.id.apply(id => aws.ec2.getSubnetIds({vpcId: id})); + +const group = new aws.ec2.SecurityGroup("web-secgrp", { + vpcId: defaultVpc.id, + description: "Enable HTTP access", + ingress: [{ + protocol: "tcp", + fromPort: 80, + toPort: 80, + cidrBlocks: ["0.0.0.0/0"], + }], + egress: [{ + protocol: "-1", + fromPort: 0, + toPort: 0, + cidrBlocks: ["0.0.0.0/0"], + }], +}); + +const alb = new aws.lb.LoadBalancer("app-lb", { + securityGroups: [group.id], + subnets: defaultVpcSubnets.ids, +}); + +const atg = new aws.lb.TargetGroup("app-tg", { + port: 80, + protocol: "HTTP", + targetType: "ip", + vpcId: defaultVpc.id, +}); + +const role = new aws.iam.Role("task-exec-role", { + assumeRolePolicy: { + Version: "2008-10-17", + Statement: [{ + Sid: "", + Effect: "Allow", + Principal: { + Service: "ecs-tasks.amazonaws.com", + }, + Action: "sts:AssumeRole", + }], + }, +}); + +const rpa = new aws.iam.RolePolicyAttachment("task-exec-policy", { + role: role.name, + policyArn: "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", +}); + +export const albArn = alb.arn; +export const albDnsName = alb.dnsName; +export const atgArn = atg.arn; +export const roleArn = role.arn; +export const subnetIds = defaultVpcSubnets.ids; +export const securityGroupId = group.id; diff --git a/aws-native-ts-ecs/index.ts b/aws-native-ts-ecs/index.ts new file mode 100644 index 000000000..7bc070938 --- /dev/null +++ b/aws-native-ts-ecs/index.ts @@ -0,0 +1,58 @@ +// Copyright 2016-2021, Pulumi Corporation. + +import * as awsnative from "@pulumi/aws-native"; +import * as classic from "./classic"; + +const cluster = new awsnative.ecs.Cluster("cluster", { + clusterName: "cloud-api-cluster", +}); + +const wl = new awsnative.elasticloadbalancingv2.Listener("web", { + loadBalancerArn: classic.albArn, + port: 80, + protocol: "HTTP", + defaultActions: [{ + type: "forward", + targetGroupArn: classic.atgArn, + }], +}); + +const taskDefinition = new awsnative.ecs.TaskDefinition("app-task", { + family: "fargate-task-definition", + cpu: "256", + memory: "512", + networkMode: "awsvpc", + requiresCompatibilities: ["FARGATE"], + executionRoleArn: classic.roleArn, + containerDefinitions: [{ + name: "my-app", + image: "nginx", + portMappings: [{ + containerPort: 80, + hostPort: 80, + protocol: "tcp", + }], + }], +}); + +const service = new awsnative.ecs.Service("app-svc", { + serviceName: "app-svc-cloud-api", + cluster: cluster.arn, + desiredCount: 1, + launchType: "FARGATE", + taskDefinition: taskDefinition.taskDefinitionArn, + networkConfiguration: { + awsvpcConfiguration: { + assignPublicIp: "ENABLED", + subnets: classic.subnetIds, + securityGroups: [classic.securityGroupId], + }, + }, + loadBalancers: [{ + targetGroupArn: classic.atgArn, + containerName: "my-app", + containerPort: 80, + }], +}, {dependsOn: [wl]}); + +export const url = classic.albDnsName; diff --git a/aws-native-ts-ecs/package.json b/aws-native-ts-ecs/package.json new file mode 100644 index 000000000..484a92be0 --- /dev/null +++ b/aws-native-ts-ecs/package.json @@ -0,0 +1,11 @@ +{ + "name": "aws-native-ts-ecs", + "devDependencies": { + "@types/node": "^8.0.0" + }, + "dependencies": { + "@pulumi/aws": "^4.0.0", + "@pulumi/aws-native": "^0.1.0", + "@pulumi/pulumi": "^3.0.0" + } +} diff --git a/aws-native-ts-ecs/tsconfig.json b/aws-native-ts-ecs/tsconfig.json new file mode 100644 index 000000000..6e3a8df78 --- /dev/null +++ b/aws-native-ts-ecs/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "strict": true, + "outDir": "bin", + "target": "es2016", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "pretty": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.ts", + "classic.ts" + ] +} diff --git a/aws-native-ts-s3-folder/README.md b/aws-native-ts-s3-folder/README.md index 8d066c452..06d07b397 100644 --- a/aws-native-ts-s3-folder/README.md +++ b/aws-native-ts-s3-folder/README.md @@ -5,7 +5,7 @@ A static website that uses [S3's website support](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html). For a detailed walkthrough of this example, see the tutorial [Static Website on AWS S3](https://www.pulumi.com/docs/tutorials/aws/s3-website/). -Note: Some of the resources are not yet supported by the Native AWS provider, so we are using both the Native +Note: Some resources are not yet supported by the Native AWS provider, so we are using both the Native and Classic provider in this example. The resources will be updated to use native resources as they are available in AWS's Cloud Control API. diff --git a/aws-native-ts-s3-folder/index.ts b/aws-native-ts-s3-folder/index.ts index f1cd98a53..0ef1c8e31 100644 --- a/aws-native-ts-s3-folder/index.ts +++ b/aws-native-ts-s3-folder/index.ts @@ -3,7 +3,7 @@ import * as aws from "@pulumi/aws"; import * as awsnative from "@pulumi/aws-native"; import * as pulumi from "@pulumi/pulumi"; -import * as fs from 'fs'; +import * as fs from "fs"; import * as mime from "mime"; // Create a bucket and expose a website index document