From 52b3fa2a7a49850d5c908a612ce40ad06472ceda Mon Sep 17 00:00:00 2001 From: Hsing-Hui Hsu Date: Thu, 16 May 2019 19:10:49 -0700 Subject: [PATCH] feat(aws-autoscaling): allow setting spotPrice Fixes #2208. --- .../aws-autoscaling/lib/auto-scaling-group.ts | 9 ++++++ .../test/test.auto-scaling-group.ts | 28 +++++++++++++++++++ packages/@aws-cdk/aws-ecs/lib/cluster.ts | 8 ++++++ .../@aws-cdk/aws-ecs/test/test.ecs-cluster.ts | 20 +++++++++++++ 4 files changed, 65 insertions(+) diff --git a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts index 8e88c3626c5ac..d788f3ec757e5 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts @@ -174,6 +174,14 @@ export interface AutoScalingGroupProps extends CommonAutoScalingGroupProps { * @default A role will automatically be created, it can be accessed via the `role` property */ readonly role?: iam.IRole; + + /** + * The maximum hourly price to be paid for any Spot Instance launched to fulfill the request. Spot Instances are + * launched when the price you specify exceeds the current Spot market price. + * + * @default none + */ + readonly spotPrice?: string; } abstract class AutoScalingGroupBase extends Resource implements IAutoScalingGroup { @@ -369,6 +377,7 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements iamInstanceProfile: iamProfile.ref, userData: userDataToken, associatePublicIpAddress: props.associatePublicIpAddress, + spotPrice: props.spotPrice, }); launchConfig.node.addDependency(this.role); diff --git a/packages/@aws-cdk/aws-autoscaling/test/test.auto-scaling-group.ts b/packages/@aws-cdk/aws-autoscaling/test/test.auto-scaling-group.ts index 86885a37f1f60..c8de2147ec4ba 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/test.auto-scaling-group.ts +++ b/packages/@aws-cdk/aws-autoscaling/test/test.auto-scaling-group.ts @@ -339,6 +339,7 @@ export = { test.done(); }, + 'can add Security Group to Fleet'(test: Test) { // GIVEN const stack = new cdk.Stack(undefined, 'MyStack', { env: { region: 'us-east-1', account: '1234' }}); @@ -363,6 +364,7 @@ export = { })); test.done(); }, + 'can set tags'(test: Test) { // GIVEN const stack = getTestStack(); @@ -405,6 +407,29 @@ export = { })); test.done(); }, + + 'allows setting spot price'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = mockVpc(stack); + + // WHEN + new autoscaling.AutoScalingGroup(stack, 'MyStack', { + instanceType: new ec2.InstanceTypePair(ec2.InstanceClass.M4, ec2.InstanceSize.Micro), + machineImage: new ec2.AmazonLinuxImage(), + vpc, + + spotPrice: "0.05", + }); + + // THEN + expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", { + SpotPrice: "0.05", + })); + + test.done(); + }, + 'allows association of public IP address'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -430,6 +455,7 @@ export = { )); test.done(); }, + 'association of public IP address requires public subnet'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -449,6 +475,7 @@ export = { }); test.done(); }, + 'allows disassociation of public IP address'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -472,6 +499,7 @@ export = { )); test.done(); }, + 'does not specify public IP address association by default'(test: Test) { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 7e37bb6a3b699..7a90d52b18b2b 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -453,6 +453,14 @@ export interface AddCapacityOptions extends AddAutoScalingGroupCapacityOptions, * The type of EC2 instance to launch into your Autoscaling Group */ readonly instanceType: ec2.InstanceType; + + /** + * The maximum hourly price to be paid for any Spot Instance launched to fulfill the request. Spot Instances are + * launched when the price you specify exceeds the current Spot market price. + * + * @default none + */ + readonly spotPrice?: string; } export interface NamespaceOptions { 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 9cdec4cfa9dba..e2a1941d0dcdf 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.ecs-cluster.ts @@ -220,6 +220,26 @@ export = { test.done(); }, + "allows specifying spot fleet"(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.VpcNetwork(stack, 'MyVpc', {}); + + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { + instanceType: new ec2.InstanceType('t2.micro'), + spotPrice: "0.31" + }); + + // THEN + expect(stack).to(haveResource("AWS::AutoScaling::LaunchConfiguration", { + SpotPrice: "0.31" + })); + + test.done(); + }, + + "allows adding default service discovery namespace"(test: Test) { // GIVEN const stack = new cdk.Stack();