Skip to content

Commit

Permalink
Refactor high level AWS ECS constructs into the aws-ecs-patterns module
Browse files Browse the repository at this point in the history
  • Loading branch information
piradeepk committed May 24, 2019
1 parent 9b4db42 commit 6fa74cf
Show file tree
Hide file tree
Showing 27 changed files with 168 additions and 83 deletions.
File renamed without changes.
File renamed without changes.
43 changes: 43 additions & 0 deletions packages/@aws-cdk/aws-ecs-patterns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,51 @@

This library provides higher-level ECS constructs which follow common architectural patterns. It contains:

* Queue Worker Services
* Scheduled Tasks (cron jobs)

## Queue Worker Services

To define a service that creates a queue and reads from that queue, instantiate one of the following:

* `Ec2QueueWorkerService`

```ts
const ecsQueueWorkerService = new Ec2QueueWorkerService(stack, 'Service', {
cluster,
memoryLimitMiB: 1024,
image: ecs.ContainerImage.fromRegistry('test'),
command: ["-c", "4", "amazon.com"],
enableLogging: false,
desiredTaskCount: 2,
environment: {
TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value",
TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value"
},
queue,
maxScalingCapacity: 5
});
```

* `FargateQueueWorkerService`

```ts
const fargateQueueWorkerService = new FargateQueueWorkerService(stack, 'Service', {
cluster,
memoryMiB: '512',
image: ecs.ContainerImage.fromRegistry('test'),
command: ["-c", "4", "amazon.com"],
enableLogging: false,
desiredTaskCount: 2,
environment: {
TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value",
TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value"
},
queue,
maxScalingCapacity: 5
});
```

## Scheduled Tasks

To define a task that runs periodically, instantiate an `ScheduledEc2Task`:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { ICertificate } from '@aws-cdk/aws-certificatemanager';
import ecs = require('@aws-cdk/aws-ecs');
import elbv2 = require('@aws-cdk/aws-elasticloadbalancingv2');
import cdk = require('@aws-cdk/cdk');
import { BaseService } from './base/base-service';
import { ICluster } from './cluster';
import { ContainerImage } from './container-image';

export enum LoadBalancerType {
Application,
Expand All @@ -14,12 +12,12 @@ export interface LoadBalancedServiceBaseProps {
/**
* The cluster where your service will be deployed
*/
readonly cluster: ICluster;
readonly cluster: ecs.ICluster;

/**
* The image to start.
*/
readonly image: ContainerImage;
readonly image: ecs.ContainerImage;

/**
* The container port of the application load balancer attached to your Fargate service. Corresponds to container port mapping.
Expand Down Expand Up @@ -127,7 +125,7 @@ export abstract class LoadBalancedServiceBase extends cdk.Construct {
new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: this.loadBalancer.loadBalancerDnsName });
}

protected addServiceAsTarget(service: BaseService) {
protected addServiceAsTarget(service: ecs.BaseService) {
if (this.loadBalancerType === LoadBalancerType.Application) {
(this.targetGroup as elbv2.ApplicationTargetGroup).addTarget(service);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import autoscaling = require('@aws-cdk/aws-applicationautoscaling');
import ecs = require('@aws-cdk/aws-ecs');
import sqs = require('@aws-cdk/aws-sqs');
import { IQueue } from '@aws-cdk/aws-sqs';
import cdk = require('@aws-cdk/cdk');
import { BaseService } from './base/base-service';
import { ICluster } from './cluster';
import { ContainerImage } from './container-image';
import { AwsLogDriver } from './log-drivers/aws-log-driver';
import { LogDriver } from './log-drivers/log-driver';

/**
* Properties to define a Query Worker service
Expand All @@ -15,12 +10,12 @@ export interface QueueWorkerServiceBaseProps {
/**
* Cluster where service will be deployed
*/
readonly cluster: ICluster;
readonly cluster: ecs.ICluster;

/**
* The image to start.
*/
readonly image: ContainerImage;
readonly image: ecs.ContainerImage;

/**
* The CMD value to pass to the container. A string with commands delimited by commas.
Expand Down Expand Up @@ -58,7 +53,7 @@ export interface QueueWorkerServiceBaseProps {
*
* @default 'SQSQueue with CloudFormation-generated name'
*/
readonly queue?: IQueue;
readonly queue?: sqs.IQueue;

/**
* Maximum capacity to scale to.
Expand All @@ -85,7 +80,7 @@ export abstract class QueueWorkerServiceBase extends cdk.Construct {
/**
* The SQS queue that the worker service will process from
*/
public readonly sqsQueue: IQueue;
public readonly sqsQueue: sqs.IQueue;

// Properties that have defaults defined. The Queue Worker will handle assigning undefined properties with default
// values so that derived classes do not need to maintain the same logic.
Expand All @@ -109,7 +104,7 @@ export abstract class QueueWorkerServiceBase extends cdk.Construct {
/**
* The AwsLogDriver to use for logging if logging is enabled.
*/
public readonly logDriver?: LogDriver;
public readonly logDriver?: ecs.LogDriver;

constructor(scope: cdk.Construct, id: string, props: QueueWorkerServiceBaseProps) {
super(scope, id);
Expand Down Expand Up @@ -141,7 +136,7 @@ export abstract class QueueWorkerServiceBase extends cdk.Construct {
*
* @param service the ECS/Fargate service for which to apply the autoscaling rules to
*/
protected configureAutoscalingForService(service: BaseService) {
protected configureAutoscalingForService(service: ecs.BaseService) {
const scalingTarget = service.autoScaleTaskCount({ maxCapacity: this.maxCapacity, minCapacity: this.desiredCount });
scalingTarget.scaleOnCpuUtilization('CpuScaling', {
targetUtilizationPercent: 50,
Expand All @@ -157,7 +152,7 @@ export abstract class QueueWorkerServiceBase extends cdk.Construct {
*
* @param prefix the Cloudwatch logging prefix
*/
private createAwsLogDriver(prefix: string): AwsLogDriver {
return new AwsLogDriver(this, 'QueueWorkerLogging', { streamPrefix: prefix });
private createAwsLogDriver(prefix: string): ecs.AwsLogDriver {
return new ecs.AwsLogDriver(this, 'QueueWorkerLogging', { streamPrefix: prefix });
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ecs = require('@aws-cdk/aws-ecs');
import cdk = require('@aws-cdk/cdk');
import { Ec2Service } from './ec2/ec2-service';
import { Ec2TaskDefinition } from './ec2/ec2-task-definition';
import { QueueWorkerServiceBase, QueueWorkerServiceBaseProps } from './queue-worker-service-base';
import { QueueWorkerServiceBase, QueueWorkerServiceBaseProps } from '../base/queue-worker-service-base';

/**
* Properties to define an Ec2 query worker service
Expand Down Expand Up @@ -49,7 +48,7 @@ export class Ec2QueueWorkerService extends QueueWorkerServiceBase {
super(scope, id, props);

// Create a Task Definition for the container to start
const taskDefinition = new Ec2TaskDefinition(this, 'QueueWorkerTaskDef');
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'QueueWorkerTaskDef');
taskDefinition.addContainer('QueueWorkerContainer', {
image: props.image,
memoryLimitMiB: props.memoryLimitMiB,
Expand All @@ -62,7 +61,7 @@ export class Ec2QueueWorkerService extends QueueWorkerServiceBase {

// Create an ECS service with the previously defined Task Definition and configure
// autoscaling based on cpu utilization and number of messages visible in the SQS queue.
const ecsService = new Ec2Service(this, 'QueueWorkerService', {
const ecsService = new ecs.Ec2Service(this, 'QueueWorkerService', {
cluster: props.cluster,
desiredCount: this.desiredCount,
taskDefinition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ecs = require('@aws-cdk/aws-ecs');
import cdk = require('@aws-cdk/cdk');
import { Ec2Service } from './ec2/ec2-service';
import { Ec2TaskDefinition } from './ec2/ec2-task-definition';
import { LoadBalancedServiceBase, LoadBalancedServiceBaseProps } from './load-balanced-service-base';
import { LoadBalancedServiceBase, LoadBalancedServiceBaseProps } from '../base/load-balanced-service-base';

/**
* Properties for a LoadBalancedEc2Service
Expand Down Expand Up @@ -42,12 +41,12 @@ export class LoadBalancedEc2Service extends LoadBalancedServiceBase {
/**
* The ECS service in this construct
*/
public readonly service: Ec2Service;
public readonly service: ecs.Ec2Service;

constructor(scope: cdk.Construct, id: string, props: LoadBalancedEc2ServiceProps) {
super(scope, id, props);

const taskDefinition = new Ec2TaskDefinition(this, 'TaskDef', {});
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef', {});

const container = taskDefinition.addContainer('web', {
image: props.image,
Expand All @@ -60,7 +59,7 @@ export class LoadBalancedEc2Service extends LoadBalancedServiceBase {
containerPort: props.containerPort || 80
});

const service = new Ec2Service(this, "Service", {
const service = new ecs.Ec2Service(this, "Service", {
cluster: props.cluster,
desiredCount: props.desiredCount || 1,
taskDefinition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ecs = require('@aws-cdk/aws-ecs');
import cdk = require('@aws-cdk/cdk');
import { FargateService } from './fargate/fargate-service';
import { FargateTaskDefinition } from './fargate/fargate-task-definition';
import { QueueWorkerServiceBase, QueueWorkerServiceBaseProps } from './queue-worker-service-base';
import { QueueWorkerServiceBase, QueueWorkerServiceBaseProps } from '../base/queue-worker-service-base';

/**
* Properties to define a Fargate queue worker service
Expand Down Expand Up @@ -53,7 +52,7 @@ export class FargateQueueWorkerService extends QueueWorkerServiceBase {
super(scope, id, props);

// Create a Task Definition for the container to start
const taskDefinition = new FargateTaskDefinition(this, 'QueueWorkerTaskDef', {
const taskDefinition = new ecs.FargateTaskDefinition(this, 'QueueWorkerTaskDef', {
memoryMiB: props.memoryMiB !== undefined ? props.memoryMiB : '512',
cpu: props.cpu !== undefined ? props.cpu : '256',
});
Expand All @@ -66,7 +65,7 @@ export class FargateQueueWorkerService extends QueueWorkerServiceBase {

// Create a Fargate service with the previously defined Task Definition and configure
// autoscaling based on cpu utilization and number of messages visible in the SQS queue.
const fargateService = new FargateService(this, 'FargateQueueWorkerService', {
const fargateService = new ecs.FargateService(this, 'FargateQueueWorkerService', {
cluster: props.cluster,
desiredCount: this.desiredCount,
taskDefinition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Certificate } from '@aws-cdk/aws-certificatemanager';
import { Vpc } from '@aws-cdk/aws-ec2';
import { Cluster, ContainerImage } from '@aws-cdk/aws-ecs';
import { HostedZoneProvider } from '@aws-cdk/aws-route53';
import cdk = require('@aws-cdk/cdk');
import { Cluster } from './cluster';
import { ContainerImage } from './container-image';
import { LoadBalancedFargateService } from './load-balanced-fargate-service';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import ecs = require('@aws-cdk/aws-ecs');
import { AliasRecord, IHostedZone } from '@aws-cdk/aws-route53';
import targets = require('@aws-cdk/aws-route53-targets');
import cdk = require('@aws-cdk/cdk');
import { FargateService } from './fargate/fargate-service';
import { FargateTaskDefinition } from './fargate/fargate-task-definition';
import { LoadBalancedServiceBase, LoadBalancedServiceBaseProps } from './load-balanced-service-base';
import { AwsLogDriver } from './log-drivers/aws-log-driver';
import { LoadBalancedServiceBase, LoadBalancedServiceBaseProps } from '../base/load-balanced-service-base';

/**
* Properties for a LoadBalancedEcsService
Expand Down Expand Up @@ -84,12 +82,12 @@ export class LoadBalancedFargateService extends LoadBalancedServiceBase {
/**
* The Fargate service in this construct
*/
public readonly service: FargateService;
public readonly service: ecs.FargateService;

constructor(scope: cdk.Construct, id: string, props: LoadBalancedFargateServiceProps) {
super(scope, id, props);

const taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
memoryMiB: props.memoryMiB,
cpu: props.cpu
});
Expand All @@ -107,7 +105,7 @@ export class LoadBalancedFargateService extends LoadBalancedServiceBase {
});

const assignPublicIp = props.publicTasks !== undefined ? props.publicTasks : false;
const service = new FargateService(this, "Service", {
const service = new ecs.FargateService(this, "Service", {
cluster: props.cluster,
desiredCount: props.desiredCount || 1,
taskDefinition,
Expand All @@ -130,7 +128,7 @@ export class LoadBalancedFargateService extends LoadBalancedServiceBase {
}
}

private createAWSLogDriver(prefix: string): AwsLogDriver {
return new AwsLogDriver(this, 'Logging', { streamPrefix: prefix });
private createAWSLogDriver(prefix: string): ecs.AwsLogDriver {
return new ecs.AwsLogDriver(this, 'Logging', { streamPrefix: prefix });
}
}
12 changes: 10 additions & 2 deletions packages/@aws-cdk/aws-ecs-patterns/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
// AWS::ECS-PATTERNS CloudFormation Resources:
export * from './scheduled-ecs-task';
export * from './ecs/ecs-queue-worker-service';
export * from './fargate/fargate-queue-worker-service';
export * from './base/queue-worker-service-base';

export * from './ecs/load-balanced-ecs-service';
export * from './fargate/load-balanced-fargate-service';
export * from './fargate/load-balanced-fargate-service-applet';
export * from './base/load-balanced-service-base';

export * from './ecs/scheduled-ecs-task';
12 changes: 12 additions & 0 deletions packages/@aws-cdk/aws-ecs-patterns/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,32 @@
"jest": "^24.7.1"
},
"dependencies": {
"@aws-cdk/aws-applicationautoscaling": "^0.31.0",
"@aws-cdk/aws-certificatemanager": "^0.31.0",
"@aws-cdk/aws-ec2": "^0.31.0",
"@aws-cdk/aws-ecs": "^0.31.0",
"@aws-cdk/aws-elasticloadbalancingv2": "^0.31.0",
"@aws-cdk/aws-events": "^0.31.0",
"@aws-cdk/aws-events-targets": "^0.31.0",
"@aws-cdk/aws-iam": "^0.31.0",
"@aws-cdk/aws-route53": "^0.31.0",
"@aws-cdk/aws-route53-targets": "^0.31.0",
"@aws-cdk/aws-sqs": "^0.31.0",
"@aws-cdk/cdk": "^0.31.0"
},
"homepage": "https://github.com/awslabs/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-applicationautoscaling": "^0.31.0",
"@aws-cdk/aws-certificatemanager": "^0.31.0",
"@aws-cdk/aws-ec2": "^0.31.0",
"@aws-cdk/aws-ecs": "^0.31.0",
"@aws-cdk/aws-elasticloadbalancingv2": "^0.31.0",
"@aws-cdk/aws-events": "^0.31.0",
"@aws-cdk/aws-events-targets": "^0.31.0",
"@aws-cdk/aws-iam": "^0.31.0",
"@aws-cdk/aws-route53": "^0.31.0",
"@aws-cdk/aws-route53-targets": "^0.31.0",
"@aws-cdk/aws-sqs": "^0.31.0",
"@aws-cdk/cdk": "^0.31.0"
},
"engines": {
Expand Down
5 changes: 5 additions & 0 deletions packages/@aws-cdk/aws-ecs-patterns/test/demo-image/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM python:3.6
EXPOSE 8000
WORKDIR /src
ADD . /src
CMD python3 index.py
33 changes: 33 additions & 0 deletions packages/@aws-cdk/aws-ecs-patterns/test/demo-image/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/python
import sys
import textwrap
import http.server
import socketserver

PORT = 8000


class Handler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
self.wfile.write(textwrap.dedent('''\
<!doctype html>
<html><head><title>It works</title></head>
<body>
<h1>Hello from the integ test container</h1>
<p>This container got built and started as part of the integ test.</p>
<img src="https://media.giphy.com/media/nFjDu1LjEADh6/giphy.gif">
</body>
''').encode('utf-8'))


def main():
httpd = http.server.HTTPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()


if __name__ == '__main__':
main()
Loading

0 comments on commit 6fa74cf

Please sign in to comment.