diff --git a/packages/@aws-cdk/aws-ecs-patterns/README.md b/packages/@aws-cdk/aws-ecs-patterns/README.md index 4e5395eda694f..cbc65741dfa43 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/README.md +++ b/packages/@aws-cdk/aws-ecs-patterns/README.md @@ -32,12 +32,14 @@ To define an Amazon ECS service that is behind an application load balancer, ins const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { cluster, memoryLimitMiB: 1024, - image: ecs.ContainerImage.fromRegistry('test'), + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('test'), + environment: { + TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + }, + }, desiredCount: 2, - environment: { - TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" - } }); ``` @@ -48,7 +50,9 @@ const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargat cluster, memoryLimitMiB: 1024, cpu: 512, - image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + }, }); ``` @@ -67,12 +71,14 @@ To define an Amazon ECS service that is behind a network load balancer, instanti const loadBalancedEcsService = new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', { cluster, memoryLimitMiB: 1024, - image: ecs.ContainerImage.fromRegistry('test'), + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('test'), + environment: { + TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + }, + }, desiredCount: 2, - environment: { - TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" - } }); ``` @@ -83,7 +89,9 @@ const loadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateSer cluster, memoryLimitMiB: 1024, cpu: 512, - image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + }, }); ``` @@ -139,11 +147,13 @@ To define a task that runs periodically, instantiate an `ScheduledEc2Task`: ```ts // Instantiate an Amazon EC2 Task to run at a scheduled interval -const ecsScheduledTask = new ScheduledEc2Task(this, 'ScheduledTask', { +const ecsScheduledTask = new ScheduledEc2Task(stack, 'ScheduledTask', { cluster, - image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), - scheduleExpression: 'rate(1 minute)', - environment: [{ name: 'TRIGGER', value: 'CloudWatch Events' }], - memoryLimitMiB: 256 + scheduledEc2TaskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 256, + environment: { name: 'TRIGGER', value: 'CloudWatch Events' }, + }, + schedule: events.Schedule.expression('rate(1 minute)') }); ``` diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index 27723c3fd90de..18d87de9b85eb 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -1,6 +1,6 @@ import { DnsValidatedCertificate, ICertificate } from '@aws-cdk/aws-certificatemanager'; import { IVpc } from '@aws-cdk/aws-ec2'; -import { AwsLogDriver, BaseService, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; +import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; import { IRole } from '@aws-cdk/aws-iam'; import { AddressRecordTarget, ARecord, IHostedZone } from '@aws-cdk/aws-route53'; @@ -122,6 +122,13 @@ export interface ApplicationLoadBalancedServiceBaseProps { * @default false */ readonly enableECSManagedTags?: boolean; + + /** + * The options for configuring an Amazon ECS service to use service discovery. + * + * @default - AWS Cloud Map service discovery is not enabled. + */ + readonly cloudMapOptions?: CloudMapOptions; } export interface ApplicationLoadBalancedTaskImageOptions { diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts index d5d143a947979..0757bf9117e3e 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts @@ -1,5 +1,5 @@ import { IVpc } from '@aws-cdk/aws-ec2'; -import { AwsLogDriver, BaseService, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; +import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; import { NetworkListener, NetworkLoadBalancer, NetworkTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; import { IRole } from '@aws-cdk/aws-iam'; import { AddressRecordTarget, ARecord, IHostedZone } from '@aws-cdk/aws-route53'; @@ -100,6 +100,13 @@ export interface NetworkLoadBalancedServiceBaseProps { * @default false */ readonly enableECSManagedTags?: boolean; + + /** + * The options for configuring an Amazon ECS service to use service discovery. + * + * @default - AWS Cloud Map service discovery is not enabled. + */ + readonly cloudMapOptions?: CloudMapOptions; } export interface NetworkLoadBalancedTaskImageOptions { diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts index 5d8aa60fb3778..38e03326f9b26 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/application-load-balanced-ecs-service.ts @@ -127,6 +127,7 @@ export class ApplicationLoadBalancedEc2Service extends ApplicationLoadBalancedSe healthCheckGracePeriod: props.healthCheckGracePeriod, propagateTags: props.propagateTags, enableECSManagedTags: props.enableECSManagedTags, + cloudMapOptions: props.cloudMapOptions, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts index 6d25f10c008fd..2415ede78a4e1 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/ecs/network-load-balanced-ecs-service.ts @@ -125,6 +125,7 @@ export class NetworkLoadBalancedEc2Service extends NetworkLoadBalancedServiceBas healthCheckGracePeriod: props.healthCheckGracePeriod, propagateTags: props.propagateTags, enableECSManagedTags: props.enableECSManagedTags, + cloudMapOptions: props.cloudMapOptions, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts index e3c86b0ece4c4..5f38ee8ede9e5 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts @@ -135,6 +135,7 @@ export class ApplicationLoadBalancedFargateService extends ApplicationLoadBalanc healthCheckGracePeriod: props.healthCheckGracePeriod, propagateTags: props.propagateTags, enableECSManagedTags: props.enableECSManagedTags, + cloudMapOptions: props.cloudMapOptions, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts index 550cff52ea32b..9579de0382654 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts @@ -131,6 +131,7 @@ export class NetworkLoadBalancedFargateService extends NetworkLoadBalancedServic healthCheckGracePeriod: props.healthCheckGracePeriod, propagateTags: props.propagateTags, enableECSManagedTags: props.enableECSManagedTags, + cloudMapOptions: props.cloudMapOptions, }); this.addServiceAsTarget(this.service); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/package.json b/packages/@aws-cdk/aws-ecs-patterns/package.json index c2ca566a83413..66580e5a410b9 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/package.json +++ b/packages/@aws-cdk/aws-ecs-patterns/package.json @@ -79,6 +79,7 @@ "@aws-cdk/aws-iam": "^1.11.0", "@aws-cdk/aws-route53": "^1.11.0", "@aws-cdk/aws-route53-targets": "^1.11.0", + "@aws-cdk/aws-servicediscovery": "^1.11.0", "@aws-cdk/aws-sqs": "^1.11.0", "@aws-cdk/core": "^1.11.0" }, @@ -94,6 +95,7 @@ "@aws-cdk/aws-iam": "^1.11.0", "@aws-cdk/aws-route53": "^1.11.0", "@aws-cdk/aws-route53-targets": "^1.11.0", + "@aws-cdk/aws-servicediscovery": "^1.11.0", "@aws-cdk/aws-sqs": "^1.11.0", "@aws-cdk/core": "^1.11.0" }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts index d8533caeb12b9..90582375c01ea 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts @@ -5,6 +5,7 @@ import ecs = require('@aws-cdk/aws-ecs'); import { AwsLogDriver } from '@aws-cdk/aws-ecs'; import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; import { PublicHostedZone } from '@aws-cdk/aws-route53'; +import cloudmap = require('@aws-cdk/aws-servicediscovery'); import cdk = require('@aws-cdk/core'); import { Test } from 'nodeunit'; import ecsPatterns = require('../../lib'); @@ -135,6 +136,148 @@ export = { test.done(); }, + 'creates AWS Cloud Map service for Private DNS namespace with application load balanced ec2 service'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // WHEN + cluster.addDefaultCloudMapNamespace({ + name: 'foo.com', + type: cloudmap.NamespaceType.DNS_PRIVATE + }); + + new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { + cluster, + taskImageOptions: { + containerPort: 8000, + image: ecs.ContainerImage.fromRegistry('hello'), + }, + cloudMapOptions: { + name: 'myApp', + }, + memoryLimitMiB: 512, + }); + + // THEN + expect(stack).to(haveResource("AWS::ECS::Service", { + ServiceRegistries: [ + { + ContainerName: "web", + ContainerPort: 8000, + RegistryArn: { + "Fn::GetAtt": [ + "ServiceCloudmapServiceDE76B29D", + "Arn" + ] + } + } + ] + })); + + expect(stack).to(haveResource('AWS::ServiceDiscovery::Service', { + DnsConfig: { + DnsRecords: [ + { + TTL: 60, + Type: "SRV" + } + ], + NamespaceId: { + 'Fn::GetAtt': [ + 'EcsClusterDefaultServiceDiscoveryNamespaceB0971B2F', + 'Id' + ] + }, + RoutingPolicy: 'MULTIVALUE' + }, + HealthCheckCustomConfig: { + FailureThreshold: 1 + }, + Name: "myApp", + NamespaceId: { + 'Fn::GetAtt': [ + 'EcsClusterDefaultServiceDiscoveryNamespaceB0971B2F', + 'Id' + ] + } + })); + + test.done(); + }, + + 'creates AWS Cloud Map service for Private DNS namespace with network load balanced fargate service'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // WHEN + cluster.addDefaultCloudMapNamespace({ + name: 'foo.com', + type: cloudmap.NamespaceType.DNS_PRIVATE + }); + + new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', { + cluster, + taskImageOptions: { + containerPort: 8000, + image: ecs.ContainerImage.fromRegistry('hello'), + }, + cloudMapOptions: { + name: 'myApp', + }, + memoryLimitMiB: 512, + }); + + // THEN + expect(stack).to(haveResource("AWS::ECS::Service", { + ServiceRegistries: [ + { + RegistryArn: { + "Fn::GetAtt": [ + "ServiceCloudmapServiceDE76B29D", + "Arn" + ] + } + } + ] + })); + + expect(stack).to(haveResource('AWS::ServiceDiscovery::Service', { + DnsConfig: { + DnsRecords: [ + { + TTL: 60, + Type: "A" + } + ], + NamespaceId: { + 'Fn::GetAtt': [ + 'EcsClusterDefaultServiceDiscoveryNamespaceB0971B2F', + 'Id' + ] + }, + RoutingPolicy: 'MULTIVALUE' + }, + HealthCheckCustomConfig: { + FailureThreshold: 1 + }, + Name: "myApp", + NamespaceId: { + 'Fn::GetAtt': [ + 'EcsClusterDefaultServiceDiscoveryNamespaceB0971B2F', + 'Id' + ] + } + })); + + test.done(); + }, + 'test Fargate loadbalanced construct'(test: Test) { // GIVEN const stack = new cdk.Stack();