From eb63ce408cc5f0d1539551c36a72ad817a76298e Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Mon, 22 Jul 2019 11:33:45 +0200 Subject: [PATCH 01/13] feat(ecs): support windows images --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 26 +++++++++-- .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 44 +++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index d0b5883d972ae..c62c1213d033b 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -231,6 +231,11 @@ export class Cluster extends Resource implements ICluster { } } +export enum WindowsOptimizedVersion { + SERVER_2019 = '2019', + SERVER_2016 = '2016', +} + /** * The properties that define which ECS-optimized AMI is used. */ @@ -242,6 +247,13 @@ export interface EcsOptimizedAmiProps { */ readonly generation?: ec2.AmazonLinuxGeneration; + /** + * The Windows Server version to use. + * + * @default none, uses Linux generation + */ + readonly windowsVersion?: WindowsOptimizedVersion; + /** * The ECS-optimized AMI variant to use. * @@ -251,10 +263,11 @@ export interface EcsOptimizedAmiProps { } /** - * Construct a Linux machine image from the latest ECS Optimized AMI published in SSM + * Construct a Linux or Windows machine image from the latest ECS Optimized AMI published in SSM */ export class EcsOptimizedAmi implements ec2.IMachineImage { - private readonly generation: ec2.AmazonLinuxGeneration; + private readonly generation?: ec2.AmazonLinuxGeneration; + private readonly windowsVersion?: WindowsOptimizedVersion; private readonly hwType: AmiHardwareType; private readonly amiParameterName: string; @@ -270,6 +283,10 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { } else { this.generation = props.generation; } + } else if (props && props.windowsVersion) { + if (this.hwType !== AmiHardwareType.STANDARD) { + throw new Error('Windows Server does not support special hardware type. Use Amazon Linux 2 instead'); + } } else { // generation not defined in props object // always default to Amazon Linux v2 regardless of HW this.generation = ec2.AmazonLinuxGeneration.AMAZON_LINUX_2; @@ -279,6 +296,7 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { 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"; @@ -291,7 +309,7 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { const ami = ssm.StringParameter.valueForStringParameter(scope, this.amiParameterName); return { imageId: ami, - osType: ec2.OperatingSystemType.LINUX + osType: this.windowsVersion ? ec2.OperatingSystemType.WINDOWS : ec2.OperatingSystemType.LINUX }; } } @@ -510,7 +528,7 @@ export interface CloudMapNamespaceOptions { export enum AmiHardwareType { /** - * Use the Amazon ECS-optimized Amazon Linux 2 AMI. + * Use the standard Amazon ECS-optimized AMI. */ STANDARD = 'Standard', diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 961d93c38c2d8..9d17c047a78c4 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -274,8 +274,52 @@ export = { hardwareType: ecs.AmiHardwareType.GPU, }), }); + }, /Amazon Linux does not support special hardware type/); + + test.done(); + }, + + "allows specifying windows image"(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('WindowsAutoScalingGroup', { + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: new ecs.EcsOptimizedAmi({ + windowsVersion: ecs.WindowsOptimizedVersion.SERVER_2019, + }), }); + // THEN + expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", { + ImageId: { + Ref: "SsmParameterValueawsserviceecsoptimizedamirecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + } + })); + + test.done(); + }, + + "errors if windows given with special HW type"(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + + // THEN + test.throws(() => { + cluster.addCapacity('WindowsGpuAutoScalingGroup', { + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: new ecs.EcsOptimizedAmi({ + windowsVersion: ecs.WindowsOptimizedVersion.SERVER_2019, + hardwareType: ecs.AmiHardwareType.GPU, + }), + }); + }, /Windows Server does not support special hardware type/); + test.done(); }, From 48780fbdb27b185e8e491592f9cc991369c5485e Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Tue, 23 Jul 2019 13:49:50 +0200 Subject: [PATCH 02/13] fix(ecs): throw if both windowsVersion and generation props are set --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 2 ++ .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index c62c1213d033b..d44f1bfb694d8 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -280,6 +280,8 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { if (props && props.generation) { // generation defined in the props object if (props.generation === ec2.AmazonLinuxGeneration.AMAZON_LINUX && this.hwType !== AmiHardwareType.STANDARD) { throw new Error(`Amazon Linux does not support special hardware type. Use Amazon Linux 2 instead`); + } else if (props.windowsVersion) { + throw new Error('"windowsVersion" and Linux image "generation" cannot be both set'); } else { this.generation = props.generation; } diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 9d17c047a78c4..411049431adff 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -323,6 +323,27 @@ export = { test.done(); }, + "errors if windowsVersion and linux generation are set"(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + + // THEN + test.throws(() => { + cluster.addCapacity('WindowsScalingGroup', { + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: new ecs.EcsOptimizedAmi({ + windowsVersion: ecs.WindowsOptimizedVersion.SERVER_2019, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX + }), + }); + }, /"windowsVersion" and Linux image "generation" cannot be both set/); + + test.done(); + }, + "allows specifying spot fleet"(test: Test) { // GIVEN const stack = new cdk.Stack(); From 47e81a63ff4b9d4326d56da2ac3b3fc04786cdd7 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Tue, 23 Jul 2019 13:57:56 +0200 Subject: [PATCH 03/13] fix(ecs): remove linux mention in windows hardware error --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index d44f1bfb694d8..2a239163f14ad 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -287,7 +287,7 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { } } else if (props && props.windowsVersion) { if (this.hwType !== AmiHardwareType.STANDARD) { - throw new Error('Windows Server does not support special hardware type. Use Amazon Linux 2 instead'); + throw new Error('Windows Server does not support special hardware type'); } } else { // generation not defined in props object // always default to Amazon Linux v2 regardless of HW From e3e5739c10f5f321e0c445c71105a9767776f714 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Tue, 23 Jul 2019 15:51:46 +0200 Subject: [PATCH 04/13] fix(ecs): fix windowsVersion assignation, update test * incomplete test, stack incomplete --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 2 ++ packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 2a239163f14ad..d9a1fb136a5fa 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -288,6 +288,8 @@ export class EcsOptimizedAmi implements ec2.IMachineImage { } else if (props && props.windowsVersion) { if (this.hwType !== AmiHardwareType.STANDARD) { throw new Error('Windows Server does not support special hardware type'); + } else { + this.windowsVersion = props.windowsVersion; } } else { // generation not defined in props object // always default to Amazon Linux v2 regardless of HW diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 411049431adff..c623088cd6d7f 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -293,11 +293,14 @@ export = { }); // THEN - expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", { - ImageId: { - Ref: "SsmParameterValueawsserviceecsoptimizedamirecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + expect(stack).toMatch({ + "Parameters": { + "SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id" + } } - })); + }); test.done(); }, From 5c01a39ceb3f61832c743795ee68205c414ce53c Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Tue, 23 Jul 2019 16:18:25 +0200 Subject: [PATCH 05/13] fix(ecs): windowsVersion test deepEqual --- .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index c623088cd6d7f..38390d4919ba6 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -5,6 +5,7 @@ import cloudmap = require('@aws-cdk/aws-servicediscovery'); import cdk = require('@aws-cdk/core'); import { Test } from 'nodeunit'; import ecs = require('../lib'); +import { App } from '@aws-cdk/core'; export = { "When creating an ECS Cluster": { @@ -281,7 +282,8 @@ export = { "allows specifying windows image"(test: Test) { // GIVEN - const stack = new cdk.Stack(); + const app = new App(); + const stack = new cdk.Stack(app, 'test'); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); @@ -293,12 +295,12 @@ export = { }); // THEN - expect(stack).toMatch({ - "Parameters": { - "SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { - "Type": "AWS::SSM::Parameter::Value", - "Default": "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id" - } + const assembly = app.synth(); + const template = assembly.getStack(stack.stackName).template; + test.deepEqual(template.Parameters, { + "SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id" } }); From b1f003bd44307b3066e578ac2902edfc9ed452dc Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Tue, 23 Jul 2019 16:50:09 +0200 Subject: [PATCH 06/13] fix(ecs): test linux ami ssm parameter --- packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 38390d4919ba6..c81c53f425a4f 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -238,7 +238,8 @@ export = { "allows specifying special HW AMI Type"(test: Test) { // GIVEN - const stack = new cdk.Stack(); + const app = new App(); + const stack = new cdk.Stack(app, 'test'); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); @@ -250,12 +251,21 @@ export = { }); // 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", + "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended/image_id" + } + }); + test.done(); }, From 0309b8772bbc4b0f22aa730c813b20b32e38439d Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Wed, 24 Jul 2019 15:20:10 +0200 Subject: [PATCH 07/13] fix(ecs): remove duplicate core import --- packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index c81c53f425a4f..246c917552a3d 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -5,7 +5,6 @@ import cloudmap = require('@aws-cdk/aws-servicediscovery'); import cdk = require('@aws-cdk/core'); import { Test } from 'nodeunit'; import ecs = require('../lib'); -import { App } from '@aws-cdk/core'; export = { "When creating an ECS Cluster": { @@ -238,7 +237,7 @@ export = { "allows specifying special HW AMI Type"(test: Test) { // GIVEN - const app = new App(); + const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); @@ -292,7 +291,7 @@ export = { "allows specifying windows image"(test: Test) { // GIVEN - const app = new App(); + const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); From 9bc06bfcf677da96b5710ec68291b65da4f8abdf Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Wed, 24 Jul 2019 15:20:17 +0200 Subject: [PATCH 08/13] fix(ecs): tslint --- packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 246c917552a3d..463f9677b973d 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -259,9 +259,9 @@ export = { })); test.deepEqual(template.Parameters, { - "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { - "Type": "AWS::SSM::Parameter::Value", - "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended/image_id" + SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter: { + Type: "AWS::SSM::Parameter::Value", + Default: "/aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended/image_id" } }); @@ -307,9 +307,9 @@ export = { const assembly = app.synth(); const template = assembly.getStack(stack.stackName).template; test.deepEqual(template.Parameters, { - "SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { - "Type": "AWS::SSM::Parameter::Value", - "Default": "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id" + SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter: { + Type: "AWS::SSM::Parameter::Value", + Default: "/aws/service/ecs/optimized-ami/windows_server/2019/english/full/recommended/image_id" } }); From 12d99eb56d510531e0d3781c60d6bb7652f462a8 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Wed, 24 Jul 2019 16:37:06 +0200 Subject: [PATCH 09/13] feat(ecs): EcsOptimizedAmi refactor, use static constructors * EcsOptimizedAmi -> EcsOptimizedAmiStatic * deprecate EcsOptimizedAmi, EcsOptimizedAmiProps --- packages/@aws-cdk/aws-ecs/README.md | 4 +- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 119 +++++++++++++++++- .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 94 ++++++++++++++ 3 files changed, 212 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index f471ab3233581..42a916c01e431 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -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 ... }); diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index d9a1fb136a5fa..2b9c3bf09b0be 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -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. @@ -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 { /** @@ -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; @@ -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. */ diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 463f9677b973d..46760f2048130 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -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(); @@ -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", + 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", + 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", + 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(); From 450b507443f3e0fb97368cebeb9d709506b71219 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Wed, 24 Jul 2019 16:45:29 +0200 Subject: [PATCH 10/13] fix(ecs): remove unused interfaces --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 28 +----------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 2b9c3bf09b0be..cb8d42d32dc0d 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -248,7 +248,7 @@ export enum WindowsOptimizedVersion { /** * The properties that define which ECS-optimized AMI is used. * - * @deprecated see {@link EcsOptimizedAmazonLinuxAmiProps} and {@link EcsOptimizedAmazonLinuxAmiProps} + * @deprecated see {@link EcsOptimizedAmiStatic} */ export interface EcsOptimizedAmiProps { /** @@ -273,32 +273,6 @@ 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 */ From 42bfb0b73a12e732b00d01abbf661a68a87394e7 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Thu, 25 Jul 2019 08:30:10 +0200 Subject: [PATCH 11/13] fix(ecs): remove duplicate import --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index cb8d42d32dc0d..4afaac03b892e 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -4,7 +4,6 @@ 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 {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'; @@ -350,14 +349,14 @@ export class EcsOptimizedAmiStatic implements ec2.IMachineImage { * @param hardwareType ECS-optimized AMI variant to use */ public static amazonLinux2(hardwareType = AmiHardwareType.STANDARD): EcsOptimizedAmiStatic { - return new EcsOptimizedAmiStatic({generation: AmazonLinuxGeneration.AMAZON_LINUX_2, hardwareType}); + return new EcsOptimizedAmiStatic({generation: ec2.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}); + return new EcsOptimizedAmiStatic({generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX}); } /** From 3cbeb5f8fee31b7b1abe0959e3d8afda332b5aa2 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Thu, 25 Jul 2019 09:04:50 +0200 Subject: [PATCH 12/13] fix(ecs): fix property ordering --- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 4afaac03b892e..a6a091365d993 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -337,12 +337,6 @@ 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 * @@ -368,6 +362,12 @@ export class EcsOptimizedAmiStatic implements ec2.IMachineImage { return new EcsOptimizedAmiStatic({windowsVersion}); } + private readonly generation?: ec2.AmazonLinuxGeneration; + private readonly windowsVersion?: WindowsOptimizedVersion; + private readonly hwType?: AmiHardwareType; + + private readonly amiParameterName: string; + /** * Constructs a new instance of the EcsOptimizedAmi class. */ From 19e874d6c13300b22558bc775698417b37e83c3d Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Thu, 25 Jul 2019 14:30:57 +0200 Subject: [PATCH 13/13] fix(ecs): refactor EcsOptimizedImage * EcsOptimizedAmiStatic -> EcsOptimizedImage --- packages/@aws-cdk/aws-ecs/README.md | 4 ++-- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 18 +++++++++--------- .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index 42a916c01e431..59813655ed116 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -111,9 +111,9 @@ cluster.addCapacity('DefaultAutoScalingGroupCapacity', { const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'ASG', { vpc, instanceType: new ec2.InstanceType('t2.xlarge'), - machineImage: EcsOptimizedAmiStatic.amazonLinux(), + machineImage: EcsOptimizedImage.amazonLinux(), // Or use Amazon ECS-Optimized Amazon Linux 2 AMI - // machineImage: EcsOptimizedAmiStatic.amazonLinux2(), + // machineImage: EcsOptimizedImage.amazonLinux2(), desiredCapacity: 3, // ... other options here ... }); diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index a6a091365d993..d23fc77f99e76 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -247,7 +247,7 @@ export enum WindowsOptimizedVersion { /** * The properties that define which ECS-optimized AMI is used. * - * @deprecated see {@link EcsOptimizedAmiStatic} + * @deprecated see {@link EcsOptimizedImage} */ export interface EcsOptimizedAmiProps { /** @@ -278,7 +278,7 @@ export interface EcsOptimizedAmiProps { /** * 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} + * @deprecated see {@link EcsOptimizedImage#amazonLinux}, {@link EcsOptimizedImage#amazonLinux} and {@link EcsOptimizedImage#windows} */ export class EcsOptimizedAmi implements ec2.IMachineImage { private readonly generation?: ec2.AmazonLinuxGeneration; @@ -336,21 +336,21 @@ 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 { +export class EcsOptimizedImage implements ec2.IMachineImage { /** * 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: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, hardwareType}); + public static amazonLinux2(hardwareType = AmiHardwareType.STANDARD): EcsOptimizedImage { + return new EcsOptimizedImage({generation: ec2.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: ec2.AmazonLinuxGeneration.AMAZON_LINUX}); + public static amazonLinux(): EcsOptimizedImage { + return new EcsOptimizedImage({generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX}); } /** @@ -358,8 +358,8 @@ export class EcsOptimizedAmiStatic implements ec2.IMachineImage { * * @param windowsVersion Windows Version to use */ - public static windows(windowsVersion: WindowsOptimizedVersion): EcsOptimizedAmiStatic { - return new EcsOptimizedAmiStatic({windowsVersion}); + public static windows(windowsVersion: WindowsOptimizedVersion): EcsOptimizedImage { + return new EcsOptimizedImage({windowsVersion}); } private readonly generation?: ec2.AmazonLinuxGeneration; diff --git a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts index 46760f2048130..8007c40d2d51e 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -365,7 +365,7 @@ export = { * TODO:v2.0.0 END OF OBSOLETE BLOCK */ - "allows specifying special HW AMI Type statically"(test: Test) { + "allows specifying special HW AMI Type v2"(test: Test) { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); @@ -374,7 +374,7 @@ export = { const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); cluster.addCapacity('GpuAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro'), - machineImage: ecs.EcsOptimizedAmiStatic.amazonLinux2(ecs.AmiHardwareType.GPU) + machineImage: ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.GPU) }); // THEN @@ -405,7 +405,7 @@ export = { const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); cluster.addCapacity('GpuAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro'), - machineImage: ecs.EcsOptimizedAmiStatic.amazonLinux() + machineImage: ecs.EcsOptimizedImage.amazonLinux() }); // THEN @@ -427,7 +427,7 @@ export = { test.done(); }, - "allows specifying windows image statically"(test: Test) { + "allows specifying windows image v2"(test: Test) { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); @@ -436,7 +436,7 @@ export = { 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), + machineImage: ecs.EcsOptimizedImage.windows(ecs.WindowsOptimizedVersion.SERVER_2019), }); // THEN