Skip to content

Commit

Permalink
feat(ecs): EcsOptimizedAmi refactor, use static constructors
Browse files Browse the repository at this point in the history
* EcsOptimizedAmi -> EcsOptimizedAmiStatic
* deprecate EcsOptimizedAmi, EcsOptimizedAmiProps
  • Loading branch information
Jimmy Gaussen committed Jul 24, 2019
1 parent 9bc06bf commit 12d99eb
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 5 deletions.
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ cluster.addCapacity('DefaultAutoScalingGroupCapacity', {
const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'ASG', {
vpc,
instanceType: new ec2.InstanceType('t2.xlarge'),
machineImage: new EcsOptimizedAmi(),
machineImage: EcsOptimizedAmiStatic.amazonLinux(),
// Or use Amazon ECS-Optimized Amazon Linux 2 AMI
// machineImage: new EcsOptimizedAmi({ generation: ec2.AmazonLinuxGeneration.AmazonLinux2 }),
// machineImage: EcsOptimizedAmiStatic.amazonLinux2(),
desiredCapacity: 3,
// ... other options here ...
});
Expand Down
119 changes: 116 additions & 3 deletions packages/@aws-cdk/aws-ecs/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import ec2 = require('@aws-cdk/aws-ec2');
import iam = require('@aws-cdk/aws-iam');
import cloudmap = require('@aws-cdk/aws-servicediscovery');
import ssm = require('@aws-cdk/aws-ssm');
import { Construct, Duration, IResource, Resource, Stack } from '@aws-cdk/core';
import { InstanceDrainHook } from './drain-hook/instance-drain-hook';
import { CfnCluster } from './ecs.generated';
import {AmazonLinuxGeneration} from "@aws-cdk/aws-ec2";
import {Construct, Duration, IResource, Resource, Stack} from '@aws-cdk/core';
import {InstanceDrainHook} from './drain-hook/instance-drain-hook';
import {CfnCluster} from './ecs.generated';

/**
* The properties used to define an ECS cluster.
Expand Down Expand Up @@ -231,13 +232,23 @@ export class Cluster extends Resource implements ICluster {
}
}

/**
* ECS-optimized Windows version list
*/
export enum WindowsOptimizedVersion {
SERVER_2019 = '2019',
SERVER_2016 = '2016',
}

/*
* TODO:v2.0.0
* * remove `export` keyword
* * remove @depracted
*/
/**
* The properties that define which ECS-optimized AMI is used.
*
* @deprecated see {@link EcsOptimizedAmazonLinuxAmiProps} and {@link EcsOptimizedAmazonLinuxAmiProps}
*/
export interface EcsOptimizedAmiProps {
/**
Expand All @@ -262,8 +273,39 @@ export interface EcsOptimizedAmiProps {
readonly hardwareType?: AmiHardwareType;
}

/**
* The properties that define which ECS-optimized AMI is used.
*/
export interface EcsOptimizedAmazonLinuxAmiProps {
/**
* The Amazon Linux generation to use.
*
* @default AmazonLinuxGeneration.AmazonLinux2
*/
readonly generation?: ec2.AmazonLinuxGeneration;

/**
* The ECS-optimized AMI variant to use.
*
* @default AmiHardwareType.Standard
*/
readonly hardwareType?: AmiHardwareType;
}

export interface EcsOptimizedWindowsAmiProps {
/**
* The Windows Server version to use.
*/
readonly windowsVersion: WindowsOptimizedVersion;
}

/*
* TODO:v2.0.0 remove EcsOptimizedAmi
*/
/**
* Construct a Linux or Windows machine image from the latest ECS Optimized AMI published in SSM
*
* @deprecated see {@link EcsOptimizedAmiStatic#amazonLinux}, {@link EcsOptimizedAmiStatic#amazonLinux} and {@link EcsOptimizedAmiStatic#windows}
*/
export class EcsOptimizedAmi implements ec2.IMachineImage {
private readonly generation?: ec2.AmazonLinuxGeneration;
Expand Down Expand Up @@ -318,6 +360,77 @@ export class EcsOptimizedAmi implements ec2.IMachineImage {
}
}

/**
* Construct a Linux or Windows machine image from the latest ECS Optimized AMI published in SSM
*/
export class EcsOptimizedAmiStatic implements ec2.IMachineImage {
private readonly generation?: ec2.AmazonLinuxGeneration;
private readonly windowsVersion?: WindowsOptimizedVersion;
private readonly hwType?: AmiHardwareType;

private readonly amiParameterName: string;

/**
* Construct an Amazon Linux 2 image from the latest ECS Optimized AMI published in SSM
*
* @param hardwareType ECS-optimized AMI variant to use
*/
public static amazonLinux2(hardwareType = AmiHardwareType.STANDARD): EcsOptimizedAmiStatic {
return new EcsOptimizedAmiStatic({generation: AmazonLinuxGeneration.AMAZON_LINUX_2, hardwareType});
}

/**
* Construct an Amazon Linux AMI image from the latest ECS Optimized AMI published in SSM
*/
public static amazonLinux(): EcsOptimizedAmiStatic {
return new EcsOptimizedAmiStatic({generation: AmazonLinuxGeneration.AMAZON_LINUX});
}

/**
* Construct a Windows image from the latest ECS Optimized AMI published in SSM
*
* @param windowsVersion Windows Version to use
*/
public static windows(windowsVersion: WindowsOptimizedVersion): EcsOptimizedAmiStatic {
return new EcsOptimizedAmiStatic({windowsVersion});
}

/**
* Constructs a new instance of the EcsOptimizedAmi class.
*/
private constructor(props: EcsOptimizedAmiProps) {
this.hwType = props && props.hardwareType;

if (props.windowsVersion) {
this.windowsVersion = props.windowsVersion;
} else if (props.generation) {
this.generation = props.generation;
} else {
throw new Error('This error should never be thrown');
}

// set the SSM parameter name
this.amiParameterName = "/aws/service/ecs/optimized-ami/"
+ ( this.generation === ec2.AmazonLinuxGeneration.AMAZON_LINUX ? "amazon-linux/" : "" )
+ ( this.generation === ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 ? "amazon-linux-2/" : "" )
+ ( this.windowsVersion ? `windows_server/${this.windowsVersion}/english/full/` : "" )
+ ( this.hwType === AmiHardwareType.GPU ? "gpu/" : "" )
+ ( this.hwType === AmiHardwareType.ARM ? "arm64/" : "" )
+ "recommended/image_id";
}

/**
* Return the correct image
*/
public getImage(scope: Construct): ec2.MachineImageConfig {
const ami = ssm.StringParameter.valueForStringParameter(scope, this.amiParameterName);
return {
imageId: ami,
osType: this.windowsVersion ? ec2.OperatingSystemType.WINDOWS : ec2.OperatingSystemType.LINUX
};
}
}

/**
* A regional grouping of one or more container instances on which you can run tasks and services.
*/
Expand Down
94 changes: 94 additions & 0 deletions packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ export = {
test.done();
},

/*
* TODO:v2.0.0 BEGINNING OF OBSOLETE BLOCK
*/
"allows specifying special HW AMI Type"(test: Test) {
// GIVEN
const app = new cdk.App();
Expand Down Expand Up @@ -358,6 +361,97 @@ export = {
test.done();
},

/*
* TODO:v2.0.0 END OF OBSOLETE BLOCK
*/

"allows specifying special HW AMI Type statically"(test: Test) {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const vpc = new ec2.Vpc(stack, 'MyVpc', {});

const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc });
cluster.addCapacity('GpuAutoScalingGroup', {
instanceType: new ec2.InstanceType('t2.micro'),
machineImage: ecs.EcsOptimizedAmiStatic.amazonLinux2(ecs.AmiHardwareType.GPU)
});

// THEN
const assembly = app.synth();
const template = assembly.getStack(stack.stackName).template;
expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", {
ImageId: {
Ref: "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter"
}
}));

test.deepEqual(template.Parameters, {
SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter: {
Type: "AWS::SSM::Parameter::Value<String>",
Default: "/aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended/image_id"
}
});

test.done();
},

"allows specifying Amazon Linux v1 AMI"(test: Test) {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const vpc = new ec2.Vpc(stack, 'MyVpc', {});

const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc });
cluster.addCapacity('GpuAutoScalingGroup', {
instanceType: new ec2.InstanceType('t2.micro'),
machineImage: ecs.EcsOptimizedAmiStatic.amazonLinux()
});

// THEN
const assembly = app.synth();
const template = assembly.getStack(stack.stackName).template;
expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", {
ImageId: {
Ref: "SsmParameterValueawsserviceecsoptimizedamiamazonlinuxrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter"
}
}));

test.deepEqual(template.Parameters, {
SsmParameterValueawsserviceecsoptimizedamiamazonlinuxrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter: {
Type: "AWS::SSM::Parameter::Value<String>",
Default: "/aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id"
}
});

test.done();
},

"allows specifying windows image statically"(test: Test) {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const vpc = new ec2.Vpc(stack, 'MyVpc', {});

const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc });
cluster.addCapacity('WindowsAutoScalingGroup', {
instanceType: new ec2.InstanceType('t2.micro'),
machineImage: ecs.EcsOptimizedAmiStatic.windows(ecs.WindowsOptimizedVersion.SERVER_2019),
});

// THEN
const assembly = app.synth();
const template = assembly.getStack(stack.stackName).template;
test.deepEqual(template.Parameters, {
SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter: {
Type: "AWS::SSM::Parameter::Value<String>",
Default: "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id"
}
});

test.done();
},

"allows specifying spot fleet"(test: Test) {
// GIVEN
const stack = new cdk.Stack();
Expand Down

0 comments on commit 12d99eb

Please sign in to comment.