Skip to content

Commit

Permalink
Updated to reflect review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
otterley committed May 12, 2021
1 parent 3627bd9 commit ecc9966
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 79 deletions.
41 changes: 23 additions & 18 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -725,15 +725,19 @@ ecsService.associateCloudMapService({

## Capacity Providers

There are two major families of Capacity Providers: [AWS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-capacity-providers.html) (including Fargate Spot) and EC2 [Auto
Scaling Group](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/asg-capacity-providers.html) Capacity Providers. Both are supported.
There are two major families of Capacity Providers: [AWS
Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-capacity-providers.html)
(including Fargate Spot) and EC2 [Auto Scaling
Group](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/asg-capacity-providers.html)
Capacity Providers. Both are supported.

### Fargate Capacity Providers

To enable Fargate capacity providers, you can either set
`enableFargateCapacityProviders` to `true` when creating your cluster, or by
invoking the `enableFargateCapacityProviders()` method after creating your
cluster. This will add both `FARGATE` and `FARGATE_SPOT` as available capacity providers on your cluster.
cluster. This will add both `FARGATE` and `FARGATE_SPOT` as available capacity
providers on your cluster.

```ts
const cluster = new ecs.Cluster(stack, 'FargateCPCluster', {
Expand Down Expand Up @@ -765,17 +769,17 @@ new ecs.FargateService(stack, 'FargateService', {

### Auto Scaling Group Capacity Providers

To add an Auto Scaling Group Capacity Provider, first create an EC2 Auto Scaling Group. Then,
create an `AsgCapacityProvider` and pass the Auto Scaling Group to it in the
constructor. Then add the Capacity Provider to the cluster. Finally, you can
refer to the Provider by its name in your service's or task's Capacity Provider
strategy.
To add an Auto Scaling Group Capacity Provider, first create an EC2 Auto Scaling
Group. Then, create an `AsgCapacityProvider` and pass the Auto Scaling Group to
it in the constructor. Then add the Capacity Provider to the cluster. Finally,
you can refer to the Provider by its name in your service's or task's Capacity
Provider strategy.

By default, an Auto Scaling Group Capacity Provider will manage the Auto Scaling Group's size
for you. It will also enable managed termination protection, in order to prevent
EC2 Auto Scaling from terminating EC2 instances that have tasks running on
them. If you want to disable this behavior, set both `enableManagedScaling` to
and `enableManagedTerminationProtection` to `false`.
By default, an Auto Scaling Group Capacity Provider will manage the Auto Scaling
Group's size for you. It will also enable managed termination protection, in
order to prevent EC2 Auto Scaling from terminating EC2 instances that have tasks
running on them. If you want to disable this behavior, set both
`enableManagedScaling` to and `enableManagedTerminationProtection` to `false`.

```ts
const cluster = new ecs.Cluster(stack, 'Cluster', {
Expand All @@ -790,15 +794,16 @@ const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'ASG', {
maxCapacity: 100,
});

const capacityProvider = new ecs.EC2CapacityProvider(stack, 'EC2CapacityProvider', {
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'AsgCapacityProvider', {
autoScalingGroup,
});
cluster.addEC2CapacityProvider(capacityProvider);
cluster.addAsgCapacityProvider(capacityProvider);

const taskDefinition = new ecs.EC2TaskDefinition(stack, 'TaskDef');
const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef');

taskDefinition.addContainer('web', {
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryReservationMiB: 256,
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample',
memoryReservationMiB: 256,
});

new ecs.Ec2Service(stack, 'EC2Service', {
Expand All @@ -818,7 +823,7 @@ new ecs.Ec2Service(stack, 'EC2Service', {
Currently, this feature is only supported for services with EC2 launch types.
To add elastic inference accelerators to your EC2 instance, first add
`inferenceAccelerators` field to the EC2TaskDefinition and set the `deviceName`
`inferenceAccelerators` field to the Ec2TaskDefinition and set the `deviceName`
and `deviceType` properties.
```ts
Expand Down
87 changes: 44 additions & 43 deletions packages/@aws-cdk/aws-ecs/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ export class Cluster extends Resource implements ICluster {
/**
* The cluster-level (FARGATE, FARGATE_SPOT) capacity providers.
*/
private _clusterCapacityProviders: string[] = [];
private _fargateCapacityProviders: string[] = [];

/**
* The EC2 Auto Scaling Group capacity providers associated with the cluster.
*/
private _ec2CapacityProviders: EC2CapacityProvider[] = [];
private _asgCapacityProviders: AsgCapacityProvider[] = [];

/**
* The AWS Cloud Map namespace to associate with the cluster.
Expand Down Expand Up @@ -159,15 +159,15 @@ export class Cluster extends Resource implements ICluster {
clusterSettings = [{ name: 'containerInsights', value: props.containerInsights ? ContainerInsights.ENABLED : ContainerInsights.DISABLED }];
}

this._clusterCapacityProviders = props.capacityProviders ?? [];
this._fargateCapacityProviders = props.capacityProviders ?? [];
if (props.enableFargateCapacityProviders) {
this.enableFargateCapacityProviders();
}

const cluster = new CfnCluster(this, 'Resource', {
clusterName: this.physicalName,
clusterSettings,
capacityProviders: Lazy.list({ produce: () => this._clusterCapacityProviders }, { omitEmpty: true }),
capacityProviders: Lazy.list({ produce: () => this._fargateCapacityProviders }, { omitEmpty: true }),
});

this.clusterArn = this.getResourceArnAttribute(cluster.attrArn, {
Expand All @@ -193,16 +193,16 @@ export class Cluster extends Resource implements ICluster {
// since it's harmless, but we'd prefer not to add unexpected new
// resources to the stack which could surprise users working with
// brown-field CDK apps and stacks.
Aspects.of(this).add(new MaybeCreateCapacityProviderAssociations(this, id, this._ec2CapacityProviders));
Aspects.of(this).add(new MaybeCreateCapacityProviderAssociations(this, id, this._asgCapacityProviders));
}

/**
* Enable the Fargate capacity providers for this cluster.
*/
public enableFargateCapacityProviders() {
for (const provider of ['FARGATE', 'FARGATE_SPOT']) {
if (!this._clusterCapacityProviders.includes(provider)) {
this._clusterCapacityProviders.push(provider);
if (!this._fargateCapacityProviders.includes(provider)) {
this._fargateCapacityProviders.push(provider);
}
}
}
Expand Down Expand Up @@ -247,7 +247,7 @@ export class Cluster extends Resource implements ICluster {
*
* Returns the AutoScalingGroup so you can add autoscaling settings to it.
*
* @deprecated Use {@link Cluster.addCapacityProvider} instead.
* @deprecated Use {@link Cluster.addAsgCapacityProvider} instead.
*/
public addCapacity(id: string, options: AddCapacityOptions): autoscaling.AutoScalingGroup {
if (options.machineImage && options.machineImageType) {
Expand All @@ -273,29 +273,13 @@ export class Cluster extends Resource implements ICluster {
}

/**
* This method adds compute capacity to a cluster using the specified EC2 Capacity Provider.
* This method adds an Auto Scaling Group Capacity Provider to a cluster.
*
* @param provider the capacity provider to add to this cluster.
*/
public addCapacityProvider(provider: string) {
if (!(provider === 'FARGATE' || provider === 'FARGATE_SPOT')) {
throw new Error('CapacityProvider not supported');
}

if (!this._clusterCapacityProviders.includes(provider)) {
this._clusterCapacityProviders.push(provider);
}
}

/**
* This method adds an Auto Scaling Group Capacity Provider to a cluster using
* the specified EC2 Capacity Provider.
*
* @param provider the capacity provider to add to this cluster.
*/
public addEC2CapacityProvider(provider: EC2CapacityProvider, options: AddAutoScalingGroupCapacityOptions = {}) {
public addAsgCapacityProvider(provider: AsgCapacityProvider, options: AddAutoScalingGroupCapacityOptions = {}) {
// Don't add the same capacity provider more than once.
if (this._ec2CapacityProviders.includes(provider)) {
if (this._asgCapacityProviders.includes(provider)) {
return;
}

Expand All @@ -306,13 +290,13 @@ export class Cluster extends Resource implements ICluster {
taskDrainTime: provider.enableManagedTerminationProtection ? Duration.seconds(0) : options.taskDrainTime,
});

this._ec2CapacityProviders.push(provider);
this._asgCapacityProviders.push(provider);
}

/**
* This method adds compute capacity to a cluster using the specified AutoScalingGroup.
*
* @deprecated Use {@link Cluster.addCapacityProvider} instead.
* @deprecated Use {@link Cluster.addAsgCapacityProvider} instead.
* @param autoScalingGroup the ASG to add to this cluster.
* [disable-awslint:ref-via-interface] is needed in order to install the ECS
* agent by updating the ASGs user data.
Expand Down Expand Up @@ -416,6 +400,23 @@ export class Cluster extends Resource implements ICluster {
}
}

/**
* This method enables the Fargate or Fargate Spot capacity providers on the cluster.
*
* @param provider the capacity provider to add to this cluster.
* @deprecated Use {@link enableFargateCapacityProviders} instead.
* @see {@link addAsgCapacityProvider} to add an Auto Scaling Group capacity provider to the cluster.
*/
public addCapacityProvider(provider: string) {
if (!(provider === 'FARGATE' || provider === 'FARGATE_SPOT')) {
throw new Error('CapacityProvider not supported');
}

if (!this._fargateCapacityProviders.includes(provider)) {
this._fargateCapacityProviders.push(provider);
}
}

private configureWindowsAutoScalingGroup(autoScalingGroup: autoscaling.AutoScalingGroup, options: AddAutoScalingGroupCapacityOptions = {}) {
// clear the cache of the agent
autoScalingGroup.addUserData('Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache');
Expand Down Expand Up @@ -1036,7 +1037,7 @@ enum ContainerInsights {
*/
export interface CapacityProviderStrategy {
/**
* The name of the capacity provider
* The name of the capacity provider.
*/
readonly capacityProvider: string;

Expand All @@ -1060,9 +1061,9 @@ capacity provider. The weight value is taken into consideration after the base v
}

/**
* The options for creating an EC2 Capacity Provider.
* The options for creating an Auto Scaling Group Capacity Provider.
*/
export interface EC2CapacityProviderProps extends AddAutoScalingGroupCapacityOptions {
export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOptions {
/**
* The name for the capacity provider.
*
Expand Down Expand Up @@ -1112,13 +1113,13 @@ export interface EC2CapacityProviderProps extends AddAutoScalingGroupCapacityOpt
}

/**
* An EC2 Capacity Provider. This allows an ECS cluster to target a specific
* EC2 Auto Scaling Group for the placement of tasks. Optionally (and recommended),
* ECS can manage the number of instances in the ASG to fit the tasks, and can
* ensure that instances are not prematurely terminated while there are still tasks
* running on them.
* An Auto Scaling Group Capacity Provider. This allows an ECS cluster to target
* a specific EC2 Auto Scaling Group for the placement of tasks. Optionally (and
* recommended), ECS can manage the number of instances in the ASG to fit the
* tasks, and can ensure that instances are not prematurely terminated while
* there are still tasks running on them.
*/
export class EC2CapacityProvider extends CoreConstruct {
export class AsgCapacityProvider extends CoreConstruct {
/**
* Capacity provider name
* @default Chosen by CloudFormation
Expand All @@ -1135,7 +1136,7 @@ export class EC2CapacityProvider extends CoreConstruct {
*/
readonly enableManagedTerminationProtection?: boolean;

constructor(scope: Construct, id: string, props: EC2CapacityProviderProps) {
constructor(scope: Construct, id: string, props: AsgCapacityProviderProps) {
super(scope, id);

this.autoScalingGroup = props.autoScalingGroup as autoscaling.AutoScalingGroup;
Expand All @@ -1151,8 +1152,8 @@ export class EC2CapacityProvider extends CoreConstruct {
name: props.capacityProviderName,
autoScalingGroupProvider: {
autoScalingGroupArn: this.autoScalingGroup.autoScalingGroupName,
managedScaling: {
status: props.enableManagedScaling === false ? 'DISABLED' : 'ENABLED',
managedScaling: props.enableManagedScaling === false ? undefined : {
status: 'ENABLED',
targetCapacity: props.targetCapacityPercent || 100,
maximumScalingStepSize: props.maximumScalingStepSize,
minimumScalingStepSize: props.minimumScalingStepSize,
Expand All @@ -1172,9 +1173,9 @@ export class EC2CapacityProvider extends CoreConstruct {
class MaybeCreateCapacityProviderAssociations implements IAspect {
private scope: CoreConstruct;
private id: string;
private capacityProviders: EC2CapacityProvider[]
private capacityProviders: AsgCapacityProvider[]

constructor(scope: CoreConstruct, id: string, capacityProviders: EC2CapacityProvider[]) {
constructor(scope: CoreConstruct, id: string, capacityProviders: AsgCapacityProvider[]) {
this.scope = scope;
this.id = id;
this.capacityProviders = capacityProviders;
Expand Down
24 changes: 11 additions & 13 deletions packages/@aws-cdk/aws-ecs/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
haveResource,
haveResourceLike,
ResourcePart,
ABSENT,
} from '@aws-cdk/assert-internal';
import * as autoscaling from '@aws-cdk/aws-autoscaling';
import * as ec2 from '@aws-cdk/aws-ec2';
Expand Down Expand Up @@ -1809,7 +1810,7 @@ nodeunitShim({
});

// WHEN
new ecs.EC2CapacityProvider(stack, 'provider', {
new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
});

Expand All @@ -1829,7 +1830,7 @@ nodeunitShim({
test.done();
},

'can disable managed scaling for EC2 capacity provider'(test: Test) {
'can disable managed scaling for ASG capacity provider'(test: Test) {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
Expand All @@ -1841,7 +1842,7 @@ nodeunitShim({
});

// WHEN
new ecs.EC2CapacityProvider(stack, 'provider', {
new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
enableManagedScaling: false,
});
Expand All @@ -1852,10 +1853,7 @@ nodeunitShim({
AutoScalingGroupArn: {
Ref: 'asgASG4D014670',
},
ManagedScaling: {
Status: 'DISABLED',
TargetCapacity: 100,
},
ManagedScaling: ABSENT,
ManagedTerminationProtection: 'ENABLED',
},
}));
Expand All @@ -1874,7 +1872,7 @@ nodeunitShim({
});

// WHEN
new ecs.EC2CapacityProvider(stack, 'provider', {
new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
});

Expand All @@ -1897,7 +1895,7 @@ nodeunitShim({
});

// WHEN
new ecs.EC2CapacityProvider(stack, 'provider', {
new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
enableManagedTerminationProtection: false,
});
Expand All @@ -1909,7 +1907,7 @@ nodeunitShim({
test.done();
},

'can add EC2 capacity via Capacity Provider'(test: Test) {
'can add ASG capacity via Capacity Provider'(test: Test) {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
Expand All @@ -1923,7 +1921,7 @@ nodeunitShim({
});

// WHEN
const capacityProvider = new ecs.EC2CapacityProvider(stack, 'provider', {
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
enableManagedTerminationProtection: false,
});
Expand All @@ -1932,8 +1930,8 @@ nodeunitShim({
cluster.enableFargateCapacityProviders();

// Ensure not added twice
cluster.addEC2CapacityProvider(capacityProvider);
cluster.addEC2CapacityProvider(capacityProvider);
cluster.addAsgCapacityProvider(capacityProvider);
cluster.addAsgCapacityProvider(capacityProvider);

// THEN
expect(stack).to(haveResource('AWS::ECS::ClusterCapacityProviderAssociations', {
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-ecs/test/ec2/ec2-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ nodeunitShim({
});

// WHEN
const capacityProvider = new ecs.EC2CapacityProvider(stack, 'provider', {
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'provider', {
autoScalingGroup,
enableManagedTerminationProtection: false,
});
cluster.addEC2CapacityProvider(capacityProvider);
cluster.addAsgCapacityProvider(capacityProvider);

const taskDefinition = new ecs.TaskDefinition(stack, 'ServerTask', {
compatibility: ecs.Compatibility.EC2,
Expand Down
Loading

0 comments on commit ecc9966

Please sign in to comment.