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 605bc9db0f103..d8761ff8e6e13 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 @@ -43,6 +43,7 @@ export interface ApplicationLoadBalancedServiceBaseProps { /** * The desired number of instantiations of the task definition to keep running on the service. + * The minimum value is 1 * * @default 1 */ @@ -258,6 +259,9 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { } this.cluster = props.cluster || this.getDefaultCluster(this, props.vpc); + if (props.desiredCount !== undefined && props.desiredCount < 1) { + throw new Error('You must specify a desiredCount greater than 0'); + } this.desiredCount = props.desiredCount || 1; const internetFacing = props.publicLoadBalancer !== undefined ? props.publicLoadBalancer : true; 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 d3a92f867168a..dd9a5818c7b1c 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 @@ -42,6 +42,7 @@ export interface NetworkLoadBalancedServiceBaseProps { /** * The desired number of instantiations of the task definition to keep running on the service. + * The minimum value is 1 * * @default 1 */ @@ -230,6 +231,9 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { } this.cluster = props.cluster || this.getDefaultCluster(this, props.vpc); + if (props.desiredCount !== undefined && props.desiredCount < 1) { + throw new Error('You must specify a desiredCount greater than 0'); + } this.desiredCount = props.desiredCount || 1; const internetFacing = props.publicLoadBalancer !== undefined ? props.publicLoadBalancer : true; diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts index 2954881272b8a..bf98104932aaa 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/queue-processing-service-base.ts @@ -211,9 +211,13 @@ export abstract class QueueProcessingServiceBase extends Construct { this.secrets = props.secrets; // Determine the desired task count (minimum) and maximum scaling capacity - this.desiredCount = props.desiredTaskCount || 1; + this.desiredCount = props.desiredTaskCount !== undefined ? props.desiredTaskCount : 1; this.maxCapacity = props.maxScalingCapacity || (2 * this.desiredCount); + if (!this.desiredCount && !this.maxCapacity) { + throw new Error(`maxScalingCapacity must be set and greater than 0 if desiredCount is 0`); + } + new CfnOutput(this, 'SQSQueue', { value: this.sqsQueue.queueName }); new CfnOutput(this, 'SQSQueueArn', { value: this.sqsQueue.queueArn }); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/scheduled-task-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/scheduled-task-base.ts index b983dfce51058..315f03066fae4 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/scheduled-task-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/scheduled-task-base.ts @@ -90,6 +90,8 @@ export abstract class ScheduledTaskBase extends Construct { public readonly cluster: ICluster; /** * The desired number of instantiations of the task definition to keep running on the service. + * + * The minimum value is 1 */ public readonly desiredTaskCount: number; @@ -105,6 +107,9 @@ export abstract class ScheduledTaskBase extends Construct { super(scope, id); this.cluster = props.cluster || this.getDefaultCluster(this, props.vpc); + if (props.desiredTaskCount !== undefined && props.desiredTaskCount < 1) { + throw new Error('You must specify a desiredTaskCount greater than 0'); + } this.desiredTaskCount = props.desiredTaskCount || 1; // An EventRule that describes the event trigger (in this case a scheduled run) 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 90582375c01ea..2d2d53ed3b5cd 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 @@ -729,4 +729,48 @@ export = { test.done(); }, + + 'ALB - throws if desiredTaskCount is 0'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // THEN + test.throws(() => + new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { + cluster, + memoryLimitMiB: 1024, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('test'), + }, + desiredCount: 0, + }) + , /You must specify a desiredCount greater than 0/); + + test.done(); + }, + + 'NLB - throws if desiredTaskCount is 0'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // THEN + test.throws(() => + new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', { + cluster, + memoryLimitMiB: 1024, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('test'), + }, + desiredCount: 0, + }) + , /You must specify a desiredCount greater than 0/); + + test.done(); + }, }; diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts index f607cc6a458dd..90419827735d7 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.queue-processing-ecs-service.ts @@ -140,5 +140,50 @@ export = { })); test.done(); - } + }, + + 'can set desiredTaskCount to 0'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // WHEN + new ecsPatterns.QueueProcessingEc2Service(stack, 'Service', { + cluster, + desiredTaskCount: 0, + maxScalingCapacity: 2, + memoryLimitMiB: 512, + image: ecs.ContainerImage.fromRegistry('test') + }); + + // THEN - QueueWorker is of EC2 launch type, an SQS queue is created and all default properties are set. + expect(stack).to(haveResource("AWS::ECS::Service", { + DesiredCount: 0, + LaunchType: "EC2", + })); + + test.done(); + }, + + 'throws if desiredTaskCount and maxScalingCapacity are 0'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + + // THEN + test.throws(() => + new ecsPatterns.QueueProcessingEc2Service(stack, 'Service', { + cluster, + desiredTaskCount: 0, + memoryLimitMiB: 512, + image: ecs.ContainerImage.fromRegistry('test') + }) + , /maxScalingCapacity must be set and greater than 0 if desiredCount is 0/); + + test.done(); + }, }; diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.scheduled-ecs-task.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.scheduled-ecs-task.ts index 28e921fa51fa3..fc8e564640270 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.scheduled-ecs-task.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.scheduled-ecs-task.ts @@ -232,4 +232,29 @@ export = { test.done(); }, + + "throws if desiredTaskCount is 0"(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1 }); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { + instanceType: new ec2.InstanceType('t2.micro') + }); + + // THEN + test.throws(() => + new ScheduledEc2Task(stack, 'ScheduledEc2Task', { + cluster, + scheduledEc2TaskImageOptions: { + image: ecs.ContainerImage.fromRegistry('henk'), + memoryLimitMiB: 512, + }, + schedule: events.Schedule.expression('rate(1 minute)'), + desiredTaskCount: 0, + }), + /You must specify a desiredTaskCount greater than 0/); + + test.done(); + }, };