From 862e80e13255c53c336fe2ab09c56555a2654bb8 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Tue, 19 Dec 2023 10:36:48 -0800 Subject: [PATCH 1/6] ecs capacity provider managed draining --- .../cli-lib-alpha/THIRD_PARTY_LICENSES | 6 +- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 23 +- scripts/check-build-prerequisites.sh | 2 +- .../us-east-1/aws-ecs-capacityprovider.json | 546 ++++++++++++++++++ 4 files changed, 571 insertions(+), 6 deletions(-) create mode 100644 tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json diff --git a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES index 4fc8eaf268c73..ad862cd67eb28 100644 --- a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES @@ -207,7 +207,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @jsii/check-node@1.91.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.91.0 | Apache-2.0 +** @jsii/check-node@1.92.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.92.0 | Apache-2.0 jsii Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -471,7 +471,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE ---------------- -** aws-sdk@2.1492.0 - https://www.npmjs.com/package/aws-sdk/v/2.1492.0 | Apache-2.0 +** aws-sdk@2.1498.0 - https://www.npmjs.com/package/aws-sdk/v/2.1498.0 | Apache-2.0 AWS SDK for JavaScript Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -668,7 +668,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** cdk-from-cfn@0.67.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.67.0 | MIT OR Apache-2.0 +** cdk-from-cfn@0.69.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.69.0 | MIT OR Apache-2.0 ---------------- diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index d4193aac5834d..893941aaf6462 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -451,8 +451,8 @@ export class Cluster extends Resource implements ICluster { this.configureAutoScalingGroup(provider.autoScalingGroup, { ...options, machineImageType: provider.machineImageType, - // Don't enable the instance-draining lifecycle hook if managed termination protection is enabled - taskDrainTime: provider.enableManagedTerminationProtection ? Duration.seconds(0) : options.taskDrainTime, + // Don't enable the instance-draining lifecycle hook if managed termination protection or managed draining is enabled + taskDrainTime: (provider.enableManagedTerminationProtection || provider.enableManagedDraining)? Duration.seconds(0) : options.taskDrainTime, canContainersAccessInstanceRole: options.canContainersAccessInstanceRole ?? provider.canContainersAccessInstanceRole, }); @@ -1167,6 +1167,13 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt */ readonly enableManagedTerminationProtection?: boolean; + /** + * PLACEHOLDER FOR DOC + * + * @default true + */ + readonly enableManagedDraining?: boolean; + /** * Maximum scaling step size. In most cases this should be left alone. * @@ -1218,6 +1225,11 @@ export class AsgCapacityProvider extends Construct { */ readonly enableManagedTerminationProtection?: boolean; + /** + * Whether managed draining is enabled. + */ + readonly enableManagedDraining?: boolean; + /** * Specifies whether the containers can access the container instance role. * @@ -1231,6 +1243,12 @@ export class AsgCapacityProvider extends Construct { this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2; this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole; this.enableManagedTerminationProtection = props.enableManagedTerminationProtection ?? true; + this.enableManagedDraining = props.enableManagedDraining ?? undefined; + + let managedDraining = undefined; + if (this.enableManagedDraining != undefined) { + managedDraining = this.enableManagedDraining ? 'ENABLED' : 'DISABLED'; + } if (this.enableManagedTerminationProtection && props.enableManagedScaling === false) { throw new Error('Cannot enable Managed Termination Protection on a Capacity Provider when Managed Scaling is disabled. Either enable Managed Scaling or disable Managed Termination Protection.'); @@ -1255,6 +1273,7 @@ export class AsgCapacityProvider extends Construct { minimumScalingStepSize: props.minimumScalingStepSize, }, managedTerminationProtection: this.enableManagedTerminationProtection ? 'ENABLED' : 'DISABLED', + managedDraining: managedDraining, }, }); diff --git a/scripts/check-build-prerequisites.sh b/scripts/check-build-prerequisites.sh index 49d6feef733be..4a6c4fc36f16c 100755 --- a/scripts/check-build-prerequisites.sh +++ b/scripts/check-build-prerequisites.sh @@ -127,7 +127,7 @@ app_min="6.0.100" check_which $app $app_min app_v=$(${app} --list-sdks) echo -e "Checking dotnet version... \c" -if [ $(echo $app_v | grep -c -E "[67]\.[0-9]+\.[0-9]+") -eq 1 ] +if [ $(echo $app_v | grep -c -E "[678]\.[0-9]+\.[0-9]+") -eq 1 ] then echo "Ok" else diff --git a/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json b/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json new file mode 100644 index 0000000000000..3ea4aac85560f --- /dev/null +++ b/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json @@ -0,0 +1,546 @@ +{ + "tagging": { + "taggable": true, + "tagOnCreate": true, + "tagUpdatable": true, + "tagProperty": "/properties/Tags", + "cloudFormationSystemTags": true + }, + "handlers": { + "read": { + "permissions": [ + "lambda:GetFunction", + "lambda:GetFunctionCodeSigningConfig" + ] + }, + "create": { + "permissions": [ + "lambda:CreateFunction", + "lambda:GetFunction", + "lambda:PutFunctionConcurrency", + "iam:PassRole", + "s3:GetObject", + "s3:GetObjectVersion", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "elasticfilesystem:DescribeMountTargets", + "kms:CreateGrant", + "kms:Decrypt", + "kms:Encrypt", + "kms:GenerateDataKey", + "lambda:GetCodeSigningConfig", + "lambda:GetFunctionCodeSigningConfig", + "lambda:GetLayerVersion", + "lambda:GetRuntimeManagementConfig", + "lambda:PutRuntimeManagementConfig", + "lambda:TagResource", + "lambda:GetPolicy", + "lambda:AddPermission", + "lambda:RemovePermission", + "lambda:GetResourcePolicy", + "lambda:PutResourcePolicy" + ] + }, + "update": { + "permissions": [ + "lambda:DeleteFunctionConcurrency", + "lambda:GetFunction", + "lambda:PutFunctionConcurrency", + "lambda:ListTags", + "lambda:TagResource", + "lambda:UntagResource", + "lambda:UpdateFunctionConfiguration", + "lambda:UpdateFunctionCode", + "iam:PassRole", + "s3:GetObject", + "s3:GetObjectVersion", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "elasticfilesystem:DescribeMountTargets", + "kms:CreateGrant", + "kms:Decrypt", + "kms:GenerateDataKey", + "lambda:GetRuntimeManagementConfig", + "lambda:PutRuntimeManagementConfig", + "lambda:PutFunctionCodeSigningConfig", + "lambda:DeleteFunctionCodeSigningConfig", + "lambda:GetCodeSigningConfig", + "lambda:GetFunctionCodeSigningConfig", + "lambda:GetPolicy", + "lambda:AddPermission", + "lambda:RemovePermission", + "lambda:GetResourcePolicy", + "lambda:PutResourcePolicy", + "lambda:DeleteResourcePolicy" + ] + }, + "list": { + "permissions": [ + "lambda:ListFunctions" + ] + }, + "delete": { + "permissions": [ + "lambda:DeleteFunction", + "ec2:DescribeNetworkInterfaces" + ] + } + }, + "typeName": "AWS::Lambda::Function", + "readOnlyProperties": [ + "/properties/SnapStartResponse", + "/properties/SnapStartResponse/ApplyOn", + "/properties/SnapStartResponse/OptimizationStatus", + "/properties/Arn" + ], + "description": "Resource Type definition for AWS::Lambda::Function in region", + "writeOnlyProperties": [ + "/properties/SnapStart", + "/properties/SnapStart/ApplyOn", + "/properties/Code", + "/properties/Code/ImageUri", + "/properties/Code/S3Bucket", + "/properties/Code/S3Key", + "/properties/Code/S3ObjectVersion", + "/properties/Code/ZipFile", + "/properties/Policy" + ], + "createOnlyProperties": [ + "/properties/FunctionName" + ], + "additionalProperties": false, + "primaryIdentifier": [ + "/properties/FunctionName" + ], + "definitions": { + "ImageConfig": { + "additionalProperties": false, + "type": "object", + "properties": { + "WorkingDirectory": { + "description": "WorkingDirectory.", + "type": "string" + }, + "Command": { + "maxItems": 1500, + "uniqueItems": true, + "description": "Command.", + "type": "array", + "items": { + "type": "string" + } + }, + "EntryPoint": { + "maxItems": 1500, + "uniqueItems": true, + "description": "EntryPoint.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "TracingConfig": { + "description": "The function's AWS X-Ray tracing configuration. To sample and record incoming requests, set Mode to Active.", + "additionalProperties": false, + "type": "object", + "properties": { + "Mode": { + "description": "The tracing mode.", + "type": "string", + "enum": [ + "Active", + "PassThrough" + ] + } + } + }, + "VpcConfig": { + "description": "The VPC security groups and subnets that are attached to a Lambda function. When you connect a function to a VPC, Lambda creates an elastic network interface for each combination of security group and subnet in the function's VPC configuration. The function can only access resources and the internet through that VPC.", + "additionalProperties": false, + "type": "object", + "properties": { + "Ipv6AllowedForDualStack": { + "description": "A boolean indicating whether IPv6 protocols will be allowed for dual stack subnets", + "type": "boolean" + }, + "SecurityGroupIds": { + "maxItems": 5, + "uniqueItems": false, + "description": "A list of VPC security groups IDs.", + "type": "array", + "items": { + "type": "string" + } + }, + "SubnetIds": { + "maxItems": 16, + "uniqueItems": false, + "description": "A list of VPC subnet IDs.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "DeadLetterConfig": { + "description": "The dead-letter queue for failed asynchronous invocations.", + "additionalProperties": false, + "type": "object", + "properties": { + "TargetArn": { + "pattern": "^(arn:(aws[a-zA-Z-]*)?:[a-z0-9-.]+:.*)|()$", + "description": "The Amazon Resource Name (ARN) of an Amazon SQS queue or Amazon SNS topic.", + "type": "string" + } + } + }, + "RuntimeManagementConfig": { + "additionalProperties": false, + "type": "object", + "properties": { + "UpdateRuntimeOn": { + "description": "Trigger for runtime update", + "type": "string", + "enum": [ + "Auto", + "FunctionUpdate", + "Manual" + ] + }, + "RuntimeVersionArn": { + "description": "Unique identifier for a runtime version arn", + "type": "string" + } + }, + "required": [ + "UpdateRuntimeOn" + ] + }, + "SnapStart": { + "description": "The function's SnapStart setting. When set to PublishedVersions, Lambda creates a snapshot of the execution environment when you publish a function version.", + "additionalProperties": false, + "type": "object", + "properties": { + "ApplyOn": { + "description": "Applying SnapStart setting on function resource type.", + "type": "string", + "enum": [ + "PublishedVersions", + "None" + ] + } + }, + "required": [ + "ApplyOn" + ] + }, + "SnapStartResponse": { + "description": "The function's SnapStart Response. When set to PublishedVersions, Lambda creates a snapshot of the execution environment when you publish a function version.", + "additionalProperties": false, + "type": "object", + "properties": { + "OptimizationStatus": { + "description": "Indicates whether SnapStart is activated for the specified function version.", + "type": "string", + "enum": [ + "On", + "Off" + ] + }, + "ApplyOn": { + "description": "Applying SnapStart setting on function resource type.", + "type": "string", + "enum": [ + "PublishedVersions", + "None" + ] + } + } + }, + "Code": { + "additionalProperties": false, + "type": "object", + "properties": { + "S3ObjectVersion": { + "minLength": 1, + "description": "For versioned objects, the version of the deployment package object to use.", + "type": "string", + "maxLength": 1024 + }, + "S3Bucket": { + "minLength": 3, + "pattern": "^[0-9A-Za-z\\.\\-_]*(? Date: Thu, 21 Dec 2023 02:05:44 -0800 Subject: [PATCH 2/6] add tests and replace the cp schema with the correct one --- .../aws-cdk-lib/aws-ecs/test/cluster.test.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index 258696e2bfc55..02b896f169b6c 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -2090,6 +2090,7 @@ describe('cluster', () => { TargetCapacity: 100, }, ManagedTerminationProtection: 'ENABLED', + ManagedDraining: undefined, }, }); @@ -2111,6 +2112,7 @@ describe('cluster', () => { autoScalingGroup, enableManagedScaling: false, enableManagedTerminationProtection: false, + enableManagedDraining: false, }); // THEN @@ -2121,6 +2123,7 @@ describe('cluster', () => { }, ManagedScaling: Match.absent(), ManagedTerminationProtection: 'DISABLED', + ManagedDraining: 'DISABLED', }, }); }); @@ -2157,6 +2160,70 @@ describe('cluster', () => { }); }); + test('can disable Managed Draining for ASG capacity provider', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'test'); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('bogus'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + + // WHEN + new ecs.AsgCapacityProvider(stack, 'provider', { + autoScalingGroup, + enableManagedDraining: false, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ECS::CapacityProvider', { + AutoScalingGroupProvider: { + AutoScalingGroupArn: { + Ref: 'asgASG4D014670', + }, + ManagedScaling: { + Status: 'ENABLED', + TargetCapacity: 100, + }, + enableManagedDraining: 'DISABLED', + }, + }); + }); + + test('can enable Managed Draining for ASG capacity provider', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'test'); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('bogus'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + + // WHEN + new ecs.AsgCapacityProvider(stack, 'provider', { + autoScalingGroup, + enableManagedDraining: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ECS::CapacityProvider', { + AutoScalingGroupProvider: { + AutoScalingGroupArn: { + Ref: 'asgASG4D014670', + }, + ManagedScaling: { + Status: 'ENABLED', + TargetCapacity: 100, + }, + enableManagedDraining: 'ENABLED', + }, + }); + }); + test('throws error, when ASG capacity provider has Managed Scaling disabled and Managed Termination Protection is undefined (defaults to true)', () => { // GIVEN const app = new cdk.App(); From 50c0c822c72567612dcdc6c98e27365de43d38ce Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Thu, 21 Dec 2023 09:53:19 -0800 Subject: [PATCH 3/6] replace the cp schema with the correct one --- .../us-east-1/aws-ecs-capacityprovider.json | 595 +++--------------- 1 file changed, 77 insertions(+), 518 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json b/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json index 3ea4aac85560f..1df3e93899112 100644 --- a/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json +++ b/tools/@aws-cdk/spec2cdk/temporary-schemas/us-east-1/aws-ecs-capacityprovider.json @@ -1,546 +1,105 @@ { - "tagging": { - "taggable": true, - "tagOnCreate": true, - "tagUpdatable": true, - "tagProperty": "/properties/Tags", - "cloudFormationSystemTags": true + "propertyTransform" : { + "/properties/AutoScalingGroupProvider/AutoScalingGroupArn" : "$split(AutoScalingGroupProvider.AutoScalingGroupArn, \"autoScalingGroupName/\")[-1] $OR $split(AutoScalingGroupArn, \"autoScalingGroupName/\")[-1]" }, - "handlers": { - "read": { - "permissions": [ - "lambda:GetFunction", - "lambda:GetFunctionCodeSigningConfig" - ] + "tagging" : { + "taggable" : true + }, + "handlers" : { + "read" : { + "permissions" : [ "ecs:DescribeCapacityProviders" ] }, - "create": { - "permissions": [ - "lambda:CreateFunction", - "lambda:GetFunction", - "lambda:PutFunctionConcurrency", - "iam:PassRole", - "s3:GetObject", - "s3:GetObjectVersion", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "elasticfilesystem:DescribeMountTargets", - "kms:CreateGrant", - "kms:Decrypt", - "kms:Encrypt", - "kms:GenerateDataKey", - "lambda:GetCodeSigningConfig", - "lambda:GetFunctionCodeSigningConfig", - "lambda:GetLayerVersion", - "lambda:GetRuntimeManagementConfig", - "lambda:PutRuntimeManagementConfig", - "lambda:TagResource", - "lambda:GetPolicy", - "lambda:AddPermission", - "lambda:RemovePermission", - "lambda:GetResourcePolicy", - "lambda:PutResourcePolicy" - ] + "create" : { + "permissions" : [ "autoscaling:CreateOrUpdateTags", "ecs:CreateCapacityProvider", "ecs:DescribeCapacityProviders", "ecs:TagResource" ] }, - "update": { - "permissions": [ - "lambda:DeleteFunctionConcurrency", - "lambda:GetFunction", - "lambda:PutFunctionConcurrency", - "lambda:ListTags", - "lambda:TagResource", - "lambda:UntagResource", - "lambda:UpdateFunctionConfiguration", - "lambda:UpdateFunctionCode", - "iam:PassRole", - "s3:GetObject", - "s3:GetObjectVersion", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "elasticfilesystem:DescribeMountTargets", - "kms:CreateGrant", - "kms:Decrypt", - "kms:GenerateDataKey", - "lambda:GetRuntimeManagementConfig", - "lambda:PutRuntimeManagementConfig", - "lambda:PutFunctionCodeSigningConfig", - "lambda:DeleteFunctionCodeSigningConfig", - "lambda:GetCodeSigningConfig", - "lambda:GetFunctionCodeSigningConfig", - "lambda:GetPolicy", - "lambda:AddPermission", - "lambda:RemovePermission", - "lambda:GetResourcePolicy", - "lambda:PutResourcePolicy", - "lambda:DeleteResourcePolicy" - ] + "update" : { + "permissions" : [ "ecs:UpdateCapacityProvider", "ecs:DescribeCapacityProviders", "ecs:ListTagsForResource", "ecs:TagResource", "ecs:UntagResource" ] }, - "list": { - "permissions": [ - "lambda:ListFunctions" - ] + "list" : { + "permissions" : [ "ecs:DescribeCapacityProviders" ] }, - "delete": { - "permissions": [ - "lambda:DeleteFunction", - "ec2:DescribeNetworkInterfaces" - ] + "delete" : { + "permissions" : [ "ecs:DescribeCapacityProviders", "ecs:DeleteCapacityProvider" ] } }, - "typeName": "AWS::Lambda::Function", - "readOnlyProperties": [ - "/properties/SnapStartResponse", - "/properties/SnapStartResponse/ApplyOn", - "/properties/SnapStartResponse/OptimizationStatus", - "/properties/Arn" - ], - "description": "Resource Type definition for AWS::Lambda::Function in region", - "writeOnlyProperties": [ - "/properties/SnapStart", - "/properties/SnapStart/ApplyOn", - "/properties/Code", - "/properties/Code/ImageUri", - "/properties/Code/S3Bucket", - "/properties/Code/S3Key", - "/properties/Code/S3ObjectVersion", - "/properties/Code/ZipFile", - "/properties/Policy" - ], - "createOnlyProperties": [ - "/properties/FunctionName" - ], - "additionalProperties": false, - "primaryIdentifier": [ - "/properties/FunctionName" - ], - "definitions": { - "ImageConfig": { - "additionalProperties": false, - "type": "object", - "properties": { - "WorkingDirectory": { - "description": "WorkingDirectory.", - "type": "string" + "typeName" : "AWS::ECS::CapacityProvider", + "description" : "Resource Type definition for AWS::ECS::CapacityProvider.", + "createOnlyProperties" : [ "/properties/AutoScalingGroupProvider/AutoScalingGroupArn", "/properties/Name" ], + "additionalProperties" : false, + "primaryIdentifier" : [ "/properties/Name" ], + "definitions" : { + "ManagedScaling" : { + "description" : "The managed scaling settings for the Auto Scaling group capacity provider.", + "additionalProperties" : false, + "type" : "object", + "properties" : { + "Status" : { + "type" : "string", + "enum" : [ "DISABLED", "ENABLED" ] }, - "Command": { - "maxItems": 1500, - "uniqueItems": true, - "description": "Command.", - "type": "array", - "items": { - "type": "string" - } + "MinimumScalingStepSize" : { + "type" : "integer" }, - "EntryPoint": { - "maxItems": 1500, - "uniqueItems": true, - "description": "EntryPoint.", - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "TracingConfig": { - "description": "The function's AWS X-Ray tracing configuration. To sample and record incoming requests, set Mode to Active.", - "additionalProperties": false, - "type": "object", - "properties": { - "Mode": { - "description": "The tracing mode.", - "type": "string", - "enum": [ - "Active", - "PassThrough" - ] - } - } - }, - "VpcConfig": { - "description": "The VPC security groups and subnets that are attached to a Lambda function. When you connect a function to a VPC, Lambda creates an elastic network interface for each combination of security group and subnet in the function's VPC configuration. The function can only access resources and the internet through that VPC.", - "additionalProperties": false, - "type": "object", - "properties": { - "Ipv6AllowedForDualStack": { - "description": "A boolean indicating whether IPv6 protocols will be allowed for dual stack subnets", - "type": "boolean" + "InstanceWarmupPeriod" : { + "type" : "integer" }, - "SecurityGroupIds": { - "maxItems": 5, - "uniqueItems": false, - "description": "A list of VPC security groups IDs.", - "type": "array", - "items": { - "type": "string" - } + "TargetCapacity" : { + "type" : "integer" }, - "SubnetIds": { - "maxItems": 16, - "uniqueItems": false, - "description": "A list of VPC subnet IDs.", - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "DeadLetterConfig": { - "description": "The dead-letter queue for failed asynchronous invocations.", - "additionalProperties": false, - "type": "object", - "properties": { - "TargetArn": { - "pattern": "^(arn:(aws[a-zA-Z-]*)?:[a-z0-9-.]+:.*)|()$", - "description": "The Amazon Resource Name (ARN) of an Amazon SQS queue or Amazon SNS topic.", - "type": "string" + "MaximumScalingStepSize" : { + "type" : "integer" } } }, - "RuntimeManagementConfig": { - "additionalProperties": false, - "type": "object", - "properties": { - "UpdateRuntimeOn": { - "description": "Trigger for runtime update", - "type": "string", - "enum": [ - "Auto", - "FunctionUpdate", - "Manual" - ] + "AutoScalingGroupProvider" : { + "additionalProperties" : false, + "type" : "object", + "properties" : { + "ManagedScaling" : { + "$ref" : "#/definitions/ManagedScaling" }, - "RuntimeVersionArn": { - "description": "Unique identifier for a runtime version arn", - "type": "string" - } - }, - "required": [ - "UpdateRuntimeOn" - ] - }, - "SnapStart": { - "description": "The function's SnapStart setting. When set to PublishedVersions, Lambda creates a snapshot of the execution environment when you publish a function version.", - "additionalProperties": false, - "type": "object", - "properties": { - "ApplyOn": { - "description": "Applying SnapStart setting on function resource type.", - "type": "string", - "enum": [ - "PublishedVersions", - "None" - ] - } - }, - "required": [ - "ApplyOn" - ] - }, - "SnapStartResponse": { - "description": "The function's SnapStart Response. When set to PublishedVersions, Lambda creates a snapshot of the execution environment when you publish a function version.", - "additionalProperties": false, - "type": "object", - "properties": { - "OptimizationStatus": { - "description": "Indicates whether SnapStart is activated for the specified function version.", - "type": "string", - "enum": [ - "On", - "Off" - ] + "AutoScalingGroupArn" : { + "type" : "string" }, - "ApplyOn": { - "description": "Applying SnapStart setting on function resource type.", - "type": "string", - "enum": [ - "PublishedVersions", - "None" - ] - } - } - }, - "Code": { - "additionalProperties": false, - "type": "object", - "properties": { - "S3ObjectVersion": { - "minLength": 1, - "description": "For versioned objects, the version of the deployment package object to use.", - "type": "string", - "maxLength": 1024 - }, - "S3Bucket": { - "minLength": 3, - "pattern": "^[0-9A-Za-z\\.\\-_]*(? Date: Fri, 22 Dec 2023 16:52:07 -0800 Subject: [PATCH 4/6] fix test and add integ test --- ...efaultTestDeployAssert30F9785A.assets.json | 19 + ...aultTestDeployAssert30F9785A.template.json | 36 + .../cdk.out | 1 + .../integ-ec2-capacity-provider.assets.json | 19 + .../integ-ec2-capacity-provider.template.json | 1044 ++++++++++ .../integ.json | 12 + .../manifest.json | 377 ++++ .../tree.json | 1756 +++++++++++++++++ ...nteg.capacity-provider-managed-draining.ts | 60 + packages/aws-cdk-lib/aws-ecs/README.md | 5 + packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 2 +- .../aws-cdk-lib/aws-ecs/test/cluster.test.ts | 5 +- 12 files changed, 3332 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.assets.json new file mode 100644 index 0000000000000..ffd41162dab36 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "CapacityProvidersDefaultTestDeployAssert30F9785A.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/CapacityProvidersDefaultTestDeployAssert30F9785A.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c5cb2e5de6344 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"35.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json new file mode 100644 index 0000000000000..b97bfc1376de4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json @@ -0,0 +1,19 @@ +{ + "version": "35.0.0", + "files": { + "0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc": { + "source": { + "path": "integ-ec2-capacity-provider.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json new file mode 100644 index 0000000000000..b479198676a77 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json @@ -0,0 +1,1044 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677" + ] + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTableAssociationDD5762D8" + ] + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "EC2CPClusterD5F0FD32": { + "Type": "AWS::ECS::Cluster" + }, + "EC2CPCluster4CFED4DD": { + "Type": "AWS::ECS::ClusterCapacityProviderAssociations", + "Properties": { + "CapacityProviders": [ + "FARGATE", + "FARGATE_SPOT", + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "Cluster": { + "Ref": "EC2CPClusterD5F0FD32" + }, + "DefaultCapacityProviderStrategy": [] + } + }, + "TaskDefTaskRole1EDB4A67": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "TaskDef54694570": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Essential": true, + "Image": "amazon/amazon-ecs-sample", + "MemoryReservation": 256, + "Name": "web" + } + ], + "Family": "integec2capacityproviderTaskDefA6140A6B", + "NetworkMode": "bridge", + "RequiresCompatibilities": [ + "EC2" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "TaskDefTaskRole1EDB4A67", + "Arn" + ] + } + } + }, + "ASGInstanceSecurityGroup0525485D": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ASGInstanceRoleE263A41B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "ASGInstanceRoleDefaultPolicy7636D8BF": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGInstanceRoleDefaultPolicy7636D8BF", + "Roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "ASGInstanceProfile0A2834D7": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "ASGLaunchTemplate0CA92847": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "IamInstanceProfile": { + "Arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t2.micro", + "Monitoring": { + "Enabled": false + }, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\necho ECS_CLUSTER=", + { + "Ref": "EC2CPClusterD5F0FD32" + }, + " >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config" + ] + ] + } + } + }, + "TagSpecifications": [ + { + "ResourceType": "launch-template", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + } + ] + }, + "DependsOn": [ + "ASGInstanceRoleDefaultPolicy7636D8BF", + "ASGInstanceRoleE263A41B" + ] + }, + "ASG46ED3070": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "LaunchTemplate": { + "LaunchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "Version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "MaxSize": "1", + "MinSize": "0", + "Tags": [ + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "integ-ec2-capacity-provider/ASG" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + }, + "UpdatePolicy": { + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "ASGDrainECSHookFunctionServiceRoleC12963BB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "Roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "ASGDrainECSHookFunction5F24CF4D": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "Environment": { + "Variables": { + "CLUSTER": { + "Ref": "EC2CPClusterD5F0FD32" + } + } + }, + "Handler": "index.lambda_handler", + "Role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "Runtime": "python3.9", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ], + "Timeout": 310 + }, + "DependsOn": [ + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "ASGDrainECSHookFunctionServiceRoleC12963BB" + ] + }, + "ASGDrainECSHookFunctionAllowInvokeintegec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1EB63E78F": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Principal": "sns.amazonaws.com", + "SourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGDrainECSHookFunctionTopicD6FC59F7": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGLifecycleHookDrainHookTopicA8AD4ACB": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleD640316C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "Roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "ASGLifecycleHookDrainHookFE4AFEBE": { + "Type": "AWS::AutoScaling::LifecycleHook", + "Properties": { + "AutoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "DefaultResult": "CONTINUE", + "HeartbeatTimeout": 300, + "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "NotificationTargetARN": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "RoleARN": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + }, + "DependsOn": [ + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "ASGLifecycleHookDrainHookRoleD640316C" + ] + }, + "EC2CapacityProvider5A2E35CD": { + "Type": "AWS::ECS::CapacityProvider", + "Properties": { + "AutoScalingGroupProvider": { + "AutoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "ManagedScaling": { + "Status": "ENABLED", + "TargetCapacity": 100 + }, + "ManagedTerminationProtection": "DISABLED" + } + } + }, + "EC2Service5392EF94": { + "Type": "AWS::ECS::Service", + "Properties": { + "CapacityProviderStrategy": [ + { + "CapacityProvider": { + "Ref": "EC2CapacityProvider5A2E35CD" + }, + "Weight": 1 + } + ], + "Cluster": { + "Ref": "EC2CPClusterD5F0FD32" + }, + "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, + "MaximumPercent": 200, + "MinimumHealthyPercent": 50 + }, + "DesiredCount": 0, + "EnableECSManagedTags": false, + "SchedulingStrategy": "REPLICA", + "TaskDefinition": { + "Ref": "TaskDef54694570" + } + }, + "DependsOn": [ + "EC2CPCluster4CFED4DD", + "EC2CPClusterD5F0FD32", + "TaskDefTaskRole1EDB4A67" + ] + } + }, + "Parameters": { + "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json new file mode 100644 index 0000000000000..dc10e080eacf6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "35.0.0", + "testCases": { + "CapacityProviders/DefaultTest": { + "stacks": [ + "integ-ec2-capacity-provider" + ], + "assertionStack": "CapacityProviders/DefaultTest/DeployAssert", + "assertionStackName": "CapacityProvidersDefaultTestDeployAssert30F9785A" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json new file mode 100644 index 0000000000000..9d541b33823fb --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json @@ -0,0 +1,377 @@ +{ + "version": "35.0.0", + "artifacts": { + "integ-ec2-capacity-provider.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-ec2-capacity-provider.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-ec2-capacity-provider": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-ec2-capacity-provider.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-ec2-capacity-provider.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-ec2-capacity-provider.assets" + ], + "metadata": { + "/integ-ec2-capacity-provider/Vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpc8378EB38" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1Subnet5C2D37C4" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTable6C95E38E" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTableAssociation97140677" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1EIPD7E02669" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1NATGateway4D7517AA" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTable94F7E489" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTableAssociationDD5762D8" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2DefaultRoute97F91067" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2EIP3C605A87" + } + ], + "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2NATGateway9182C01D" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1Subnet536B997A" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableB2C5B500" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableAssociation70C59FA6" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1DefaultRouteBE02A9ED" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2Subnet3788AAA1" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableA678073B" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableAssociationA89CAD56" + } + ], + "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2DefaultRoute060D2087" + } + ], + "/integ-ec2-capacity-provider/Vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIGWD7BA715C" + } + ], + "/integ-ec2-capacity-provider/Vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcVPCGWBF912B6E" + } + ], + "/integ-ec2-capacity-provider/EC2CPCluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2CPClusterD5F0FD32" + } + ], + "/integ-ec2-capacity-provider/EC2CPCluster/EC2CPCluster": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2CPCluster4CFED4DD" + } + ], + "/integ-ec2-capacity-provider/TaskDef/TaskRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TaskDefTaskRole1EDB4A67" + } + ], + "/integ-ec2-capacity-provider/TaskDef/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TaskDef54694570" + } + ], + "/integ-ec2-capacity-provider/ASG/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceSecurityGroup0525485D" + } + ], + "/integ-ec2-capacity-provider/ASG/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceRoleE263A41B" + } + ], + "/integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceRoleDefaultPolicy7636D8BF" + } + ], + "/integ-ec2-capacity-provider/ASG/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceProfile0A2834D7" + } + ], + "/integ-ec2-capacity-provider/ASG/LaunchTemplate/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLaunchTemplate0CA92847" + } + ], + "/integ-ec2-capacity-provider/ASG/ASG": [ + { + "type": "aws:cdk:logicalId", + "data": "ASG46ED3070" + } + ], + "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ], + "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27" + } + ], + "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunction5F24CF4D" + } + ], + "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionAllowInvokeintegec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1EB63E78F" + } + ], + "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionTopicD6FC59F7" + } + ], + "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + ], + "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleD640316C" + } + ], + "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57" + } + ], + "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookFE4AFEBE" + } + ], + "/integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/integ-ec2-capacity-provider/EC2CapacityProvider/EC2CapacityProvider": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2CapacityProvider5A2E35CD" + } + ], + "/integ-ec2-capacity-provider/EC2Service/Service": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2Service5392EF94" + } + ], + "/integ-ec2-capacity-provider/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-ec2-capacity-provider/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-ec2-capacity-provider" + }, + "CapacityProvidersDefaultTestDeployAssert30F9785A.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "CapacityProvidersDefaultTestDeployAssert30F9785A.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "CapacityProvidersDefaultTestDeployAssert30F9785A": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "CapacityProvidersDefaultTestDeployAssert30F9785A.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "CapacityProvidersDefaultTestDeployAssert30F9785A.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "CapacityProvidersDefaultTestDeployAssert30F9785A.assets" + ], + "metadata": { + "/CapacityProviders/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/CapacityProviders/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "CapacityProviders/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json new file mode 100644 index 0000000000000..8e26a1bc932dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json @@ -0,0 +1,1756 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-ec2-capacity-provider": { + "id": "integ-ec2-capacity-provider", + "path": "integ-ec2-capacity-provider", + "children": { + "Vpc": { + "id": "Vpc", + "path": "integ-ec2-capacity-provider/Vpc", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/Vpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-ec2-capacity-provider/Vpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-ec2-capacity-provider/Vpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "EC2CPCluster": { + "id": "EC2CPCluster", + "path": "integ-ec2-capacity-provider/EC2CPCluster", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/EC2CPCluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCluster", + "version": "0.0.0" + } + }, + "EC2CPCluster": { + "id": "EC2CPCluster", + "path": "integ-ec2-capacity-provider/EC2CPCluster/EC2CPCluster", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::ClusterCapacityProviderAssociations", + "aws:cdk:cloudformation:props": { + "capacityProviders": [ + "FARGATE", + "FARGATE_SPOT", + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "cluster": { + "Ref": "EC2CPClusterD5F0FD32" + }, + "defaultCapacityProviderStrategy": [] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnClusterCapacityProviderAssociations", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Cluster", + "version": "0.0.0" + } + }, + "TaskDef": { + "id": "TaskDef", + "path": "integ-ec2-capacity-provider/TaskDef", + "children": { + "TaskRole": { + "id": "TaskRole", + "path": "integ-ec2-capacity-provider/TaskDef/TaskRole", + "children": { + "ImportTaskRole": { + "id": "ImportTaskRole", + "path": "integ-ec2-capacity-provider/TaskDef/TaskRole/ImportTaskRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/TaskDef/TaskRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/TaskDef/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::TaskDefinition", + "aws:cdk:cloudformation:props": { + "containerDefinitions": [ + { + "essential": true, + "image": "amazon/amazon-ecs-sample", + "memoryReservation": 256, + "name": "web" + } + ], + "family": "integec2capacityproviderTaskDefA6140A6B", + "networkMode": "bridge", + "requiresCompatibilities": [ + "EC2" + ], + "taskRoleArn": { + "Fn::GetAtt": [ + "TaskDefTaskRole1EDB4A67", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnTaskDefinition", + "version": "0.0.0" + } + }, + "web": { + "id": "web", + "path": "integ-ec2-capacity-provider/TaskDef/web", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.ContainerDefinition", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Ec2TaskDefinition", + "version": "0.0.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ec2-capacity-provider/ASG", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "integ-ec2-capacity-provider/ASG/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "integ-ec2-capacity-provider/ASG/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGInstanceRoleDefaultPolicy7636D8BF", + "roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "integ-ec2-capacity-provider/ASG/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "ImportedInstanceProfile": { + "id": "ImportedInstanceProfile", + "path": "integ-ec2-capacity-provider/ASG/ImportedInstanceProfile", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "LaunchTemplate": { + "id": "LaunchTemplate", + "path": "integ-ec2-capacity-provider/ASG/LaunchTemplate", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/LaunchTemplate/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::LaunchTemplate", + "aws:cdk:cloudformation:props": { + "launchTemplateData": { + "iamInstanceProfile": { + "arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t2.micro", + "monitoring": { + "enabled": false + }, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "tagSpecifications": [ + { + "resourceType": "instance", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + }, + { + "resourceType": "volume", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + } + ], + "userData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\necho ECS_CLUSTER=", + { + "Ref": "EC2CPClusterD5F0FD32" + }, + " >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config" + ] + ] + } + } + }, + "tagSpecifications": [ + { + "resourceType": "launch-template", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnLaunchTemplate", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.LaunchTemplate", + "version": "0.0.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ec2-capacity-provider/ASG/ASG", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::AutoScalingGroup", + "aws:cdk:cloudformation:props": { + "launchTemplate": { + "launchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "maxSize": "1", + "minSize": "0", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG", + "propagateAtLaunch": true + } + ], + "vpcZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.CfnAutoScalingGroup", + "version": "0.0.0" + } + }, + "DrainECSHook": { + "id": "DrainECSHook", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook", + "children": { + "Function": { + "id": "Function", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EC2CPClusterD5F0FD32", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "environment": { + "variables": { + "CLUSTER": { + "Ref": "EC2CPClusterD5F0FD32" + } + } + }, + "handler": "index.lambda_handler", + "role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "runtime": "python3.9", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ], + "timeout": 310 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + }, + "AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1": { + "id": "AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "principal": "sns.amazonaws.com", + "sourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", + "version": "0.0.0" + } + }, + "Topic": { + "id": "Topic", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", + "aws:cdk:cloudformation:props": { + "endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "protocol": "lambda", + "topicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.CfnSubscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.Subscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "LifecycleHookDrainHook": { + "id": "LifecycleHookDrainHook", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook", + "children": { + "Topic": { + "id": "Topic", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.CfnTopic", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.Topic", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-capacity-provider/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::LifecycleHook", + "aws:cdk:cloudformation:props": { + "autoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "defaultResult": "CONTINUE", + "heartbeatTimeout": 300, + "lifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "notificationTargetArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "roleArn": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.CfnLifecycleHook", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.LifecycleHook", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.AutoScalingGroup", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ec2-capacity-provider/EC2CapacityProvider", + "children": { + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ec2-capacity-provider/EC2CapacityProvider/EC2CapacityProvider", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::CapacityProvider", + "aws:cdk:cloudformation:props": { + "autoScalingGroupProvider": { + "autoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "managedScaling": { + "status": "ENABLED", + "targetCapacity": 100 + }, + "managedTerminationProtection": "DISABLED" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCapacityProvider", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.AsgCapacityProvider", + "version": "0.0.0" + } + }, + "EC2Service": { + "id": "EC2Service", + "path": "integ-ec2-capacity-provider/EC2Service", + "children": { + "Service": { + "id": "Service", + "path": "integ-ec2-capacity-provider/EC2Service/Service", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Service", + "aws:cdk:cloudformation:props": { + "capacityProviderStrategy": [ + { + "capacityProvider": { + "Ref": "EC2CapacityProvider5A2E35CD" + }, + "weight": 1 + } + ], + "cluster": { + "Ref": "EC2CPClusterD5F0FD32" + }, + "deploymentConfiguration": { + "maximumPercent": 200, + "minimumHealthyPercent": 50, + "alarms": { + "alarmNames": [], + "enable": false, + "rollback": false + } + }, + "desiredCount": 0, + "enableEcsManagedTags": false, + "schedulingStrategy": "REPLICA", + "taskDefinition": { + "Ref": "TaskDef54694570" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnService", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Ec2Service", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-ec2-capacity-provider/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-ec2-capacity-provider/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "CapacityProviders": { + "id": "CapacityProviders", + "path": "CapacityProviders", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "CapacityProviders/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "CapacityProviders/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "CapacityProviders/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "CapacityProviders/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "CapacityProviders/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts new file mode 100644 index 0000000000000..c8a9c059a983a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts @@ -0,0 +1,60 @@ +import * as autoscaling from 'aws-cdk-lib/aws-autoscaling'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as integ from '@aws-cdk/integ-tests-alpha'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-ec2-capacity-provider'); + +const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); + +const cluster = new ecs.Cluster(stack, 'EC2CPCluster', { + vpc, + enableFargateCapacityProviders: true, +}); + +const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + +taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryReservationMiB: 256, +}); + +const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'ASG', { + vpc, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + // This is to allow cdk destroy to work; otherwise deletion will hang bc ASG cannot be deleted + minCapacity: 0, +}); + +const cp = new ecs.AsgCapacityProvider(stack, 'EC2CapacityProvider', { + autoScalingGroup, + // This is to allow cdk destroy to work; otherwise deletion will hang bc ASG cannot be deleted + enableManagedTerminationProtection: false, + enableManagedDraining: true, +}); + +cluster.addAsgCapacityProvider(cp); + +const service = new ecs.Ec2Service(stack, 'EC2Service', { + cluster, + taskDefinition, + capacityProviderStrategies: [ + { + capacityProvider: cp.capacityProviderName, + weight: 1, + }, + ], + // This is to allow cdk destroy to work; otherwise deletion will hang bc ASG cannot be deleted + desiredCount: 0, +}); + +service.node.addDependency(cluster); + +new integ.IntegTest(app, 'CapacityProviders', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ecs/README.md b/packages/aws-cdk-lib/aws-ecs/README.md index 0a2ad46265cb8..d118910def3b8 100644 --- a/packages/aws-cdk-lib/aws-ecs/README.md +++ b/packages/aws-cdk-lib/aws-ecs/README.md @@ -1266,6 +1266,11 @@ Managed Termination Protection to work. > delete the Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-process-shutdown.html). > For other workarounds, see [this GitHub issue](https://github.com/aws/aws-cdk/issues/18179). +[Need to confirm with Doc team] +Additionally [Managed Draining](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-auto-scaling.html#managed-instance-draining) is enabled by default for new capacity providers to +gracefully terminate Amazon ECS instances. Setting `enableManagedDraining` to `true` will replace the instance-draining lifecycle hook +created during addAsgCapacityProvider. + ```ts declare const vpc: ec2.Vpc; diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index 893941aaf6462..f8b1e861cae46 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -1170,7 +1170,7 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt /** * PLACEHOLDER FOR DOC * - * @default true + * @default null */ readonly enableManagedDraining?: boolean; diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index 02b896f169b6c..c58ca70ae9e5e 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -2090,7 +2090,6 @@ describe('cluster', () => { TargetCapacity: 100, }, ManagedTerminationProtection: 'ENABLED', - ManagedDraining: undefined, }, }); @@ -2183,11 +2182,11 @@ describe('cluster', () => { AutoScalingGroupArn: { Ref: 'asgASG4D014670', }, + ManagedDraining: 'DISABLED', ManagedScaling: { Status: 'ENABLED', TargetCapacity: 100, }, - enableManagedDraining: 'DISABLED', }, }); }); @@ -2215,11 +2214,11 @@ describe('cluster', () => { AutoScalingGroupArn: { Ref: 'asgASG4D014670', }, + ManagedDraining: 'ENABLED', ManagedScaling: { Status: 'ENABLED', TargetCapacity: 100, }, - enableManagedDraining: 'ENABLED', }, }); }); From b849d1d95a5da56df806ce996b30c2a3c5bf5979 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Wed, 3 Jan 2024 15:26:49 -0800 Subject: [PATCH 5/6] update the description, remove redundant value assignment, rename and rerun the integ test stack, and modify some license files to build successfully --- LICENSE | 2 +- .../@aws-cdk-testing/framework-integ/LICENSE | 2 +- .../@aws-cdk-testing/framework-integ/NOTICE | 2 +- ...ity-provider-managed-draining.assets.json} | 6 +- ...y-provider-managed-draining.template.json} | 315 +-------- .../integ.json | 2 +- .../manifest.json | 146 ++--- .../tree.json | 617 +++--------------- ...nteg.capacity-provider-managed-draining.ts | 2 +- packages/aws-cdk-lib/LICENSE | 2 +- packages/aws-cdk-lib/NOTICE | 2 +- packages/aws-cdk-lib/aws-ecs/README.md | 10 +- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 7 +- 13 files changed, 178 insertions(+), 937 deletions(-) rename packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/{integ-ec2-capacity-provider.assets.json => integ-ec2-capacity-provider-managed-draining.assets.json} (63%) rename packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/{integ-ec2-capacity-provider.template.json => integ-ec2-capacity-provider-managed-draining.template.json} (58%) diff --git a/LICENSE b/LICENSE index 9b722c65c5481..dcf28b52a83af 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/@aws-cdk-testing/framework-integ/LICENSE b/packages/@aws-cdk-testing/framework-integ/LICENSE index 9b722c65c5481..dcf28b52a83af 100644 --- a/packages/@aws-cdk-testing/framework-integ/LICENSE +++ b/packages/@aws-cdk-testing/framework-integ/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/@aws-cdk-testing/framework-integ/NOTICE b/packages/@aws-cdk-testing/framework-integ/NOTICE index 0dd703eaedb4a..9d28b2500bc86 100644 --- a/packages/@aws-cdk-testing/framework-integ/NOTICE +++ b/packages/@aws-cdk-testing/framework-integ/NOTICE @@ -1,5 +1,5 @@ AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.assets.json similarity index 63% rename from packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json rename to packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.assets.json index b97bfc1376de4..ffd7cb41ad40d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.assets.json @@ -1,15 +1,15 @@ { "version": "35.0.0", "files": { - "0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc": { + "72dd1ca10064654eb4724b599868f5b0d889dc243baed9bb832226e6da869796": { "source": { - "path": "integ-ec2-capacity-provider.template.json", + "path": "integ-ec2-capacity-provider-managed-draining.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc.json", + "objectKey": "72dd1ca10064654eb4724b599868f5b0d889dc243baed9bb832226e6da869796.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.template.json similarity index 58% rename from packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json rename to packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.template.json index b479198676a77..a57a7e0b31e1d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ-ec2-capacity-provider-managed-draining.template.json @@ -10,7 +10,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc" } ] } @@ -39,7 +39,7 @@ }, { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ], "VpcId": { @@ -53,7 +53,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ], "VpcId": { @@ -94,7 +94,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ] } @@ -114,7 +114,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ] }, @@ -147,7 +147,7 @@ }, { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ], "VpcId": { @@ -161,7 +161,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ], "VpcId": { @@ -202,7 +202,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ] } @@ -222,7 +222,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ] }, @@ -255,7 +255,7 @@ }, { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1" } ], "VpcId": { @@ -269,7 +269,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1" } ], "VpcId": { @@ -324,7 +324,7 @@ }, { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2" } ], "VpcId": { @@ -338,7 +338,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2" } ], "VpcId": { @@ -375,7 +375,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/Vpc" + "Value": "integ-ec2-capacity-provider-managed-draining/Vpc" } ] } @@ -438,7 +438,7 @@ "Name": "web" } ], - "Family": "integec2capacityproviderTaskDefA6140A6B", + "Family": "integec2capacityprovidermanageddrainingTaskDef8BEF62A7", "NetworkMode": "bridge", "RequiresCompatibilities": [ "EC2" @@ -454,7 +454,7 @@ "ASGInstanceSecurityGroup0525485D": { "Type": "AWS::EC2::SecurityGroup", "Properties": { - "GroupDescription": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "GroupDescription": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceSecurityGroup", "SecurityGroupEgress": [ { "CidrIp": "0.0.0.0/0", @@ -465,7 +465,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG" } ], "VpcId": { @@ -491,7 +491,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG" } ] } @@ -597,7 +597,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] }, @@ -606,7 +606,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] } @@ -632,7 +632,7 @@ "Tags": [ { "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] } @@ -663,7 +663,7 @@ { "Key": "Name", "PropagateAtLaunch": true, - "Value": "integ-ec2-capacity-provider/ASG" + "Value": "integ-ec2-capacity-provider-managed-draining/ASG" } ], "VPCZoneIdentifier": [ @@ -681,276 +681,6 @@ } } }, - "ASGDrainECSHookFunctionServiceRoleC12963BB": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ], - "Tags": [ - { - "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ec2:DescribeHosts", - "ec2:DescribeInstanceAttribute", - "ec2:DescribeInstanceStatus", - "ec2:DescribeInstances" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": "autoscaling:CompleteLifecycleAction", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":autoscaling:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":autoScalingGroup:*:autoScalingGroupName/", - { - "Ref": "ASG46ED3070" - } - ] - ] - } - }, - { - "Action": [ - "ecs:DescribeContainerInstances", - "ecs:DescribeTasks", - "ecs:ListTasks", - "ecs:UpdateContainerInstancesState" - ], - "Condition": { - "ArnEquals": { - "ecs:cluster": { - "Fn::GetAtt": [ - "EC2CPClusterD5F0FD32", - "Arn" - ] - } - } - }, - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "ecs:ListContainerInstances", - "ecs:SubmitContainerStateChange", - "ecs:SubmitTaskStateChange" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "EC2CPClusterD5F0FD32", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", - "Roles": [ - { - "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" - } - ] - } - }, - "ASGDrainECSHookFunction5F24CF4D": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" - }, - "Environment": { - "Variables": { - "CLUSTER": { - "Ref": "EC2CPClusterD5F0FD32" - } - } - }, - "Handler": "index.lambda_handler", - "Role": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunctionServiceRoleC12963BB", - "Arn" - ] - }, - "Runtime": "python3.9", - "Tags": [ - { - "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" - } - ], - "Timeout": 310 - }, - "DependsOn": [ - "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", - "ASGDrainECSHookFunctionServiceRoleC12963BB" - ] - }, - "ASGDrainECSHookFunctionAllowInvokeintegec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1EB63E78F": { - "Type": "AWS::Lambda::Permission", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunction5F24CF4D", - "Arn" - ] - }, - "Principal": "sns.amazonaws.com", - "SourceArn": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - }, - "ASGDrainECSHookFunctionTopicD6FC59F7": { - "Type": "AWS::SNS::Subscription", - "Properties": { - "Endpoint": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunction5F24CF4D", - "Arn" - ] - }, - "Protocol": "lambda", - "TopicArn": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - }, - "ASGLifecycleHookDrainHookTopicA8AD4ACB": { - "Type": "AWS::SNS::Topic", - "Properties": { - "Tags": [ - { - "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "ASGLifecycleHookDrainHookRoleD640316C": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "autoscaling.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Tags": [ - { - "Key": "Name", - "Value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sns:Publish", - "Effect": "Allow", - "Resource": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", - "Roles": [ - { - "Ref": "ASGLifecycleHookDrainHookRoleD640316C" - } - ] - } - }, - "ASGLifecycleHookDrainHookFE4AFEBE": { - "Type": "AWS::AutoScaling::LifecycleHook", - "Properties": { - "AutoScalingGroupName": { - "Ref": "ASG46ED3070" - }, - "DefaultResult": "CONTINUE", - "HeartbeatTimeout": 300, - "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", - "NotificationTargetARN": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - }, - "RoleARN": { - "Fn::GetAtt": [ - "ASGLifecycleHookDrainHookRoleD640316C", - "Arn" - ] - } - }, - "DependsOn": [ - "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", - "ASGLifecycleHookDrainHookRoleD640316C" - ] - }, "EC2CapacityProvider5A2E35CD": { "Type": "AWS::ECS::CapacityProvider", "Properties": { @@ -958,6 +688,7 @@ "AutoScalingGroupArn": { "Ref": "ASG46ED3070" }, + "ManagedDraining": "ENABLED", "ManagedScaling": { "Status": "ENABLED", "TargetCapacity": 100 diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json index dc10e080eacf6..785f7f9f8f77b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/integ.json @@ -3,7 +3,7 @@ "testCases": { "CapacityProviders/DefaultTest": { "stacks": [ - "integ-ec2-capacity-provider" + "integ-ec2-capacity-provider-managed-draining" ], "assertionStack": "CapacityProviders/DefaultTest/DeployAssert", "assertionStackName": "CapacityProvidersDefaultTestDeployAssert30F9785A" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json index 9d541b33823fb..5658e4887a515 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/manifest.json @@ -1,28 +1,28 @@ { "version": "35.0.0", "artifacts": { - "integ-ec2-capacity-provider.assets": { + "integ-ec2-capacity-provider-managed-draining.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "integ-ec2-capacity-provider.assets.json", + "file": "integ-ec2-capacity-provider-managed-draining.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "integ-ec2-capacity-provider": { + "integ-ec2-capacity-provider-managed-draining": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "integ-ec2-capacity-provider.template.json", + "templateFile": "integ-ec2-capacity-provider-managed-draining.template.json", "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0c950bde3286e1a09807bf6c36f91f78b3f741bae09a62e8cdb0b374149894bc.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/72dd1ca10064654eb4724b599868f5b0d889dc243baed9bb832226e6da869796.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "integ-ec2-capacity-provider.assets" + "integ-ec2-capacity-provider-managed-draining.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -31,293 +31,239 @@ } }, "dependencies": [ - "integ-ec2-capacity-provider.assets" + "integ-ec2-capacity-provider-managed-draining.assets" ], "metadata": { - "/integ-ec2-capacity-provider/Vpc/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/Resource": [ { "type": "aws:cdk:logicalId", "data": "Vpc8378EB38" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/Subnet": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/Subnet": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1Subnet5C2D37C4" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTable": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/RouteTable": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1RouteTable6C95E38E" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTableAssociation": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/RouteTableAssociation": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1RouteTableAssociation97140677" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/DefaultRoute": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/DefaultRoute": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/EIP": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/EIP": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1EIPD7E02669" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet1/NATGateway": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/NATGateway": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet1NATGateway4D7517AA" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/Subnet": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/Subnet": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2Subnet691E08A3" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTable": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/RouteTable": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2RouteTable94F7E489" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTableAssociation": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/RouteTableAssociation": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2RouteTableAssociationDD5762D8" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/DefaultRoute": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/DefaultRoute": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2DefaultRoute97F91067" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/EIP": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/EIP": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2EIP3C605A87" } ], - "/integ-ec2-capacity-provider/Vpc/PublicSubnet2/NATGateway": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/NATGateway": [ { "type": "aws:cdk:logicalId", "data": "VpcPublicSubnet2NATGateway9182C01D" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Subnet": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/Subnet": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet1Subnet536B997A" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTable": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/RouteTable": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet1RouteTableB2C5B500" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTableAssociation": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/RouteTableAssociation": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet1RouteTableAssociation70C59FA6" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet1/DefaultRoute": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/DefaultRoute": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet1DefaultRouteBE02A9ED" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Subnet": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/Subnet": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet2Subnet3788AAA1" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTable": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/RouteTable": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet2RouteTableA678073B" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTableAssociation": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/RouteTableAssociation": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet2RouteTableAssociationA89CAD56" } ], - "/integ-ec2-capacity-provider/Vpc/PrivateSubnet2/DefaultRoute": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/DefaultRoute": [ { "type": "aws:cdk:logicalId", "data": "VpcPrivateSubnet2DefaultRoute060D2087" } ], - "/integ-ec2-capacity-provider/Vpc/IGW": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/IGW": [ { "type": "aws:cdk:logicalId", "data": "VpcIGWD7BA715C" } ], - "/integ-ec2-capacity-provider/Vpc/VPCGW": [ + "/integ-ec2-capacity-provider-managed-draining/Vpc/VPCGW": [ { "type": "aws:cdk:logicalId", "data": "VpcVPCGWBF912B6E" } ], - "/integ-ec2-capacity-provider/EC2CPCluster/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/EC2CPCluster/Resource": [ { "type": "aws:cdk:logicalId", "data": "EC2CPClusterD5F0FD32" } ], - "/integ-ec2-capacity-provider/EC2CPCluster/EC2CPCluster": [ + "/integ-ec2-capacity-provider-managed-draining/EC2CPCluster/EC2CPCluster": [ { "type": "aws:cdk:logicalId", "data": "EC2CPCluster4CFED4DD" } ], - "/integ-ec2-capacity-provider/TaskDef/TaskRole/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/TaskDef/TaskRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "TaskDefTaskRole1EDB4A67" } ], - "/integ-ec2-capacity-provider/TaskDef/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/TaskDef/Resource": [ { "type": "aws:cdk:logicalId", "data": "TaskDef54694570" } ], - "/integ-ec2-capacity-provider/ASG/InstanceSecurityGroup/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/InstanceSecurityGroup/Resource": [ { "type": "aws:cdk:logicalId", "data": "ASGInstanceSecurityGroup0525485D" } ], - "/integ-ec2-capacity-provider/ASG/InstanceRole/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/Resource": [ { "type": "aws:cdk:logicalId", "data": "ASGInstanceRoleE263A41B" } ], - "/integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/DefaultPolicy/Resource": [ { "type": "aws:cdk:logicalId", "data": "ASGInstanceRoleDefaultPolicy7636D8BF" } ], - "/integ-ec2-capacity-provider/ASG/InstanceProfile": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/InstanceProfile": [ { "type": "aws:cdk:logicalId", "data": "ASGInstanceProfile0A2834D7" } ], - "/integ-ec2-capacity-provider/ASG/LaunchTemplate/Resource": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate/Resource": [ { "type": "aws:cdk:logicalId", "data": "ASGLaunchTemplate0CA92847" } ], - "/integ-ec2-capacity-provider/ASG/ASG": [ + "/integ-ec2-capacity-provider-managed-draining/ASG/ASG": [ { "type": "aws:cdk:logicalId", "data": "ASG46ED3070" } ], - "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGDrainECSHookFunctionServiceRoleC12963BB" - } - ], - "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27" - } - ], - "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGDrainECSHookFunction5F24CF4D" - } - ], - "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGDrainECSHookFunctionAllowInvokeintegec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1EB63E78F" - } - ], - "/integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGDrainECSHookFunctionTopicD6FC59F7" - } - ], - "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - ], - "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGLifecycleHookDrainHookRoleD640316C" - } - ], - "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57" - } - ], - "/integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "ASGLifecycleHookDrainHookFE4AFEBE" - } - ], - "/integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + "/integ-ec2-capacity-provider-managed-draining/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ { "type": "aws:cdk:logicalId", "data": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" } ], - "/integ-ec2-capacity-provider/EC2CapacityProvider/EC2CapacityProvider": [ + "/integ-ec2-capacity-provider-managed-draining/EC2CapacityProvider/EC2CapacityProvider": [ { "type": "aws:cdk:logicalId", "data": "EC2CapacityProvider5A2E35CD" } ], - "/integ-ec2-capacity-provider/EC2Service/Service": [ + "/integ-ec2-capacity-provider-managed-draining/EC2Service/Service": [ { "type": "aws:cdk:logicalId", "data": "EC2Service5392EF94" } ], - "/integ-ec2-capacity-provider/BootstrapVersion": [ + "/integ-ec2-capacity-provider-managed-draining/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/integ-ec2-capacity-provider/CheckBootstrapVersion": [ + "/integ-ec2-capacity-provider-managed-draining/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "integ-ec2-capacity-provider" + "displayName": "integ-ec2-capacity-provider-managed-draining" }, "CapacityProvidersDefaultTestDeployAssert30F9785A.assets": { "type": "cdk:asset-manifest", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json index 8e26a1bc932dd..0dbbbf8190176 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.js.snapshot/tree.json @@ -4,17 +4,17 @@ "id": "App", "path": "", "children": { - "integ-ec2-capacity-provider": { - "id": "integ-ec2-capacity-provider", - "path": "integ-ec2-capacity-provider", + "integ-ec2-capacity-provider-managed-draining": { + "id": "integ-ec2-capacity-provider-managed-draining", + "path": "integ-ec2-capacity-provider-managed-draining", "children": { "Vpc": { "id": "Vpc", - "path": "integ-ec2-capacity-provider/Vpc", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc", "children": { "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/Vpc/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::VPC", "aws:cdk:cloudformation:props": { @@ -25,7 +25,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc" } ] } @@ -37,11 +37,11 @@ }, "PublicSubnet1": { "id": "PublicSubnet1", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1", "children": { "Subnet": { "id": "Subnet", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/Subnet", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -66,7 +66,7 @@ }, { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ], "vpcId": { @@ -81,7 +81,7 @@ }, "Acl": { "id": "Acl", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/Acl", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/Acl", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -89,14 +89,14 @@ }, "RouteTable": { "id": "RouteTable", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTable", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ], "vpcId": { @@ -111,7 +111,7 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/RouteTableAssociation", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { @@ -130,7 +130,7 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/DefaultRoute", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { @@ -150,7 +150,7 @@ }, "EIP": { "id": "EIP", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/EIP", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/EIP", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::EIP", "aws:cdk:cloudformation:props": { @@ -158,7 +158,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ] } @@ -170,7 +170,7 @@ }, "NATGateway": { "id": "NATGateway", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet1/NATGateway", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1/NATGateway", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", "aws:cdk:cloudformation:props": { @@ -186,7 +186,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet1" } ] } @@ -204,11 +204,11 @@ }, "PublicSubnet2": { "id": "PublicSubnet2", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2", "children": { "Subnet": { "id": "Subnet", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/Subnet", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -233,7 +233,7 @@ }, { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ], "vpcId": { @@ -248,7 +248,7 @@ }, "Acl": { "id": "Acl", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/Acl", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/Acl", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -256,14 +256,14 @@ }, "RouteTable": { "id": "RouteTable", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTable", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ], "vpcId": { @@ -278,7 +278,7 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/RouteTableAssociation", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { @@ -297,7 +297,7 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/DefaultRoute", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { @@ -317,7 +317,7 @@ }, "EIP": { "id": "EIP", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/EIP", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/EIP", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::EIP", "aws:cdk:cloudformation:props": { @@ -325,7 +325,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ] } @@ -337,7 +337,7 @@ }, "NATGateway": { "id": "NATGateway", - "path": "integ-ec2-capacity-provider/Vpc/PublicSubnet2/NATGateway", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2/NATGateway", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", "aws:cdk:cloudformation:props": { @@ -353,7 +353,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PublicSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PublicSubnet2" } ] } @@ -371,11 +371,11 @@ }, "PrivateSubnet1": { "id": "PrivateSubnet1", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1", "children": { "Subnet": { "id": "Subnet", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Subnet", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -400,7 +400,7 @@ }, { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1" } ], "vpcId": { @@ -415,7 +415,7 @@ }, "Acl": { "id": "Acl", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/Acl", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/Acl", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -423,14 +423,14 @@ }, "RouteTable": { "id": "RouteTable", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTable", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1" } ], "vpcId": { @@ -445,7 +445,7 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/RouteTableAssociation", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { @@ -464,7 +464,7 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet1/DefaultRoute", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet1/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { @@ -490,11 +490,11 @@ }, "PrivateSubnet2": { "id": "PrivateSubnet2", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2", "children": { "Subnet": { "id": "Subnet", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Subnet", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/Subnet", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { @@ -519,7 +519,7 @@ }, { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2" } ], "vpcId": { @@ -534,7 +534,7 @@ }, "Acl": { "id": "Acl", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/Acl", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/Acl", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -542,14 +542,14 @@ }, "RouteTable": { "id": "RouteTable", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTable", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/RouteTable", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2" } ], "vpcId": { @@ -564,7 +564,7 @@ }, "RouteTableAssociation": { "id": "RouteTableAssociation", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/RouteTableAssociation", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/RouteTableAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", "aws:cdk:cloudformation:props": { @@ -583,7 +583,7 @@ }, "DefaultRoute": { "id": "DefaultRoute", - "path": "integ-ec2-capacity-provider/Vpc/PrivateSubnet2/DefaultRoute", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/PrivateSubnet2/DefaultRoute", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { @@ -609,14 +609,14 @@ }, "IGW": { "id": "IGW", - "path": "integ-ec2-capacity-provider/Vpc/IGW", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/IGW", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", "aws:cdk:cloudformation:props": { "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/Vpc" + "value": "integ-ec2-capacity-provider-managed-draining/Vpc" } ] } @@ -628,7 +628,7 @@ }, "VPCGW": { "id": "VPCGW", - "path": "integ-ec2-capacity-provider/Vpc/VPCGW", + "path": "integ-ec2-capacity-provider-managed-draining/Vpc/VPCGW", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", "aws:cdk:cloudformation:props": { @@ -653,11 +653,11 @@ }, "EC2CPCluster": { "id": "EC2CPCluster", - "path": "integ-ec2-capacity-provider/EC2CPCluster", + "path": "integ-ec2-capacity-provider-managed-draining/EC2CPCluster", "children": { "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/EC2CPCluster/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/EC2CPCluster/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", "aws:cdk:cloudformation:props": {} @@ -669,7 +669,7 @@ }, "EC2CPCluster": { "id": "EC2CPCluster", - "path": "integ-ec2-capacity-provider/EC2CPCluster/EC2CPCluster", + "path": "integ-ec2-capacity-provider-managed-draining/EC2CPCluster/EC2CPCluster", "attributes": { "aws:cdk:cloudformation:type": "AWS::ECS::ClusterCapacityProviderAssociations", "aws:cdk:cloudformation:props": { @@ -699,15 +699,15 @@ }, "TaskDef": { "id": "TaskDef", - "path": "integ-ec2-capacity-provider/TaskDef", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef", "children": { "TaskRole": { "id": "TaskRole", - "path": "integ-ec2-capacity-provider/TaskDef/TaskRole", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef/TaskRole", "children": { "ImportTaskRole": { "id": "ImportTaskRole", - "path": "integ-ec2-capacity-provider/TaskDef/TaskRole/ImportTaskRole", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef/TaskRole/ImportTaskRole", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -715,7 +715,7 @@ }, "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/TaskDef/TaskRole/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef/TaskRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -746,7 +746,7 @@ }, "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/TaskDef/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::ECS::TaskDefinition", "aws:cdk:cloudformation:props": { @@ -758,7 +758,7 @@ "name": "web" } ], - "family": "integec2capacityproviderTaskDefA6140A6B", + "family": "integec2capacityprovidermanageddrainingTaskDef8BEF62A7", "networkMode": "bridge", "requiresCompatibilities": [ "EC2" @@ -778,7 +778,7 @@ }, "web": { "id": "web", - "path": "integ-ec2-capacity-provider/TaskDef/web", + "path": "integ-ec2-capacity-provider-managed-draining/TaskDef/web", "constructInfo": { "fqn": "aws-cdk-lib.aws_ecs.ContainerDefinition", "version": "0.0.0" @@ -792,19 +792,19 @@ }, "ASG": { "id": "ASG", - "path": "integ-ec2-capacity-provider/ASG", + "path": "integ-ec2-capacity-provider-managed-draining/ASG", "children": { "InstanceSecurityGroup": { "id": "InstanceSecurityGroup", - "path": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceSecurityGroup", "children": { "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceSecurityGroup/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", "aws:cdk:cloudformation:props": { - "groupDescription": "integ-ec2-capacity-provider/ASG/InstanceSecurityGroup", + "groupDescription": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceSecurityGroup", "securityGroupEgress": [ { "cidrIp": "0.0.0.0/0", @@ -815,7 +815,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" + "value": "integ-ec2-capacity-provider-managed-draining/ASG" } ], "vpcId": { @@ -836,11 +836,11 @@ }, "InstanceRole": { "id": "InstanceRole", - "path": "integ-ec2-capacity-provider/ASG/InstanceRole", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole", "children": { "ImportInstanceRole": { "id": "ImportInstanceRole", - "path": "integ-ec2-capacity-provider/ASG/InstanceRole/ImportInstanceRole", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/ImportInstanceRole", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -848,7 +848,7 @@ }, "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/InstanceRole/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -867,7 +867,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" + "value": "integ-ec2-capacity-provider-managed-draining/ASG" } ] } @@ -879,11 +879,11 @@ }, "DefaultPolicy": { "id": "DefaultPolicy", - "path": "integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/DefaultPolicy", "children": { "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/InstanceRole/DefaultPolicy/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceRole/DefaultPolicy/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Policy", "aws:cdk:cloudformation:props": { @@ -961,7 +961,7 @@ }, "InstanceProfile": { "id": "InstanceProfile", - "path": "integ-ec2-capacity-provider/ASG/InstanceProfile", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/InstanceProfile", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", "aws:cdk:cloudformation:props": { @@ -979,7 +979,7 @@ }, "ImportedInstanceProfile": { "id": "ImportedInstanceProfile", - "path": "integ-ec2-capacity-provider/ASG/ImportedInstanceProfile", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/ImportedInstanceProfile", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -987,11 +987,11 @@ }, "LaunchTemplate": { "id": "LaunchTemplate", - "path": "integ-ec2-capacity-provider/ASG/LaunchTemplate", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate", "children": { "Resource": { "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/LaunchTemplate/Resource", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::LaunchTemplate", "aws:cdk:cloudformation:props": { @@ -1025,7 +1025,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] }, @@ -1034,7 +1034,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] } @@ -1060,7 +1060,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG/LaunchTemplate" + "value": "integ-ec2-capacity-provider-managed-draining/ASG/LaunchTemplate" } ] } @@ -1080,7 +1080,7 @@ }, "ASG": { "id": "ASG", - "path": "integ-ec2-capacity-provider/ASG/ASG", + "path": "integ-ec2-capacity-provider-managed-draining/ASG/ASG", "attributes": { "aws:cdk:cloudformation:type": "AWS::AutoScaling::AutoScalingGroup", "aws:cdk:cloudformation:props": { @@ -1100,7 +1100,7 @@ "tags": [ { "key": "Name", - "value": "integ-ec2-capacity-provider/ASG", + "value": "integ-ec2-capacity-provider-managed-draining/ASG", "propagateAtLaunch": true } ], @@ -1118,446 +1118,6 @@ "fqn": "aws-cdk-lib.aws_autoscaling.CfnAutoScalingGroup", "version": "0.0.0" } - }, - "DrainECSHook": { - "id": "DrainECSHook", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook", - "children": { - "Function": { - "id": "Function", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function", - "children": { - "ServiceRole": { - "id": "ServiceRole", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole", - "children": { - "ImportServiceRole": { - "id": "ImportServiceRole", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/ImportServiceRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "managedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ], - "tags": [ - { - "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "ec2:DescribeHosts", - "ec2:DescribeInstanceAttribute", - "ec2:DescribeInstanceStatus", - "ec2:DescribeInstances" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": "autoscaling:CompleteLifecycleAction", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":autoscaling:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":autoScalingGroup:*:autoScalingGroupName/", - { - "Ref": "ASG46ED3070" - } - ] - ] - } - }, - { - "Action": [ - "ecs:DescribeContainerInstances", - "ecs:DescribeTasks", - "ecs:ListTasks", - "ecs:UpdateContainerInstancesState" - ], - "Condition": { - "ArnEquals": { - "ecs:cluster": { - "Fn::GetAtt": [ - "EC2CPClusterD5F0FD32", - "Arn" - ] - } - } - }, - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "ecs:ListContainerInstances", - "ecs:SubmitContainerStateChange", - "ecs:SubmitTaskStateChange" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "EC2CPClusterD5F0FD32", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", - "roles": [ - { - "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::Lambda::Function", - "aws:cdk:cloudformation:props": { - "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" - }, - "environment": { - "variables": { - "CLUSTER": { - "Ref": "EC2CPClusterD5F0FD32" - } - } - }, - "handler": "index.lambda_handler", - "role": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunctionServiceRoleC12963BB", - "Arn" - ] - }, - "runtime": "python3.9", - "tags": [ - { - "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" - } - ], - "timeout": 310 - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", - "version": "0.0.0" - } - }, - "AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1": { - "id": "AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/AllowInvoke:integec2capacityproviderASGLifecycleHookDrainHookTopic4714B3C1", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", - "aws:cdk:cloudformation:props": { - "action": "lambda:InvokeFunction", - "functionName": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunction5F24CF4D", - "Arn" - ] - }, - "principal": "sns.amazonaws.com", - "sourceArn": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", - "version": "0.0.0" - } - }, - "Topic": { - "id": "Topic", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/DrainECSHook/Function/Topic/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", - "aws:cdk:cloudformation:props": { - "endpoint": { - "Fn::GetAtt": [ - "ASGDrainECSHookFunction5F24CF4D", - "Arn" - ] - }, - "protocol": "lambda", - "topicArn": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_sns.CfnSubscription", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_sns.Subscription", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_lambda.Function", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "LifecycleHookDrainHook": { - "id": "LifecycleHookDrainHook", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook", - "children": { - "Topic": { - "id": "Topic", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Topic/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SNS::Topic", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_sns.CfnTopic", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_sns.Topic", - "version": "0.0.0" - } - }, - "Role": { - "id": "Role", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role", - "children": { - "ImportRole": { - "id": "ImportRole", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/ImportRole", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "autoscaling.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "tags": [ - { - "key": "Name", - "value": "integ-ec2-capacity-provider/ASG" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": "sns:Publish", - "Effect": "Allow", - "Resource": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", - "roles": [ - { - "Ref": "ASGLifecycleHookDrainHookRoleD640316C" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-ec2-capacity-provider/ASG/LifecycleHookDrainHook/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::AutoScaling::LifecycleHook", - "aws:cdk:cloudformation:props": { - "autoScalingGroupName": { - "Ref": "ASG46ED3070" - }, - "defaultResult": "CONTINUE", - "heartbeatTimeout": 300, - "lifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", - "notificationTargetArn": { - "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" - }, - "roleArn": { - "Fn::GetAtt": [ - "ASGLifecycleHookDrainHookRoleD640316C", - "Arn" - ] - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_autoscaling.CfnLifecycleHook", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_autoscaling.LifecycleHook", - "version": "0.0.0" - } } }, "constructInfo": { @@ -1567,7 +1127,7 @@ }, "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", - "path": "integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ec2-capacity-provider-managed-draining/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", "constructInfo": { "fqn": "aws-cdk-lib.CfnParameter", "version": "0.0.0" @@ -1575,7 +1135,7 @@ }, "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118": { "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", - "path": "integ-ec2-capacity-provider/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ec2-capacity-provider-managed-draining/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -1583,11 +1143,11 @@ }, "EC2CapacityProvider": { "id": "EC2CapacityProvider", - "path": "integ-ec2-capacity-provider/EC2CapacityProvider", + "path": "integ-ec2-capacity-provider-managed-draining/EC2CapacityProvider", "children": { "EC2CapacityProvider": { "id": "EC2CapacityProvider", - "path": "integ-ec2-capacity-provider/EC2CapacityProvider/EC2CapacityProvider", + "path": "integ-ec2-capacity-provider-managed-draining/EC2CapacityProvider/EC2CapacityProvider", "attributes": { "aws:cdk:cloudformation:type": "AWS::ECS::CapacityProvider", "aws:cdk:cloudformation:props": { @@ -1599,7 +1159,8 @@ "status": "ENABLED", "targetCapacity": 100 }, - "managedTerminationProtection": "DISABLED" + "managedTerminationProtection": "DISABLED", + "managedDraining": "ENABLED" } } }, @@ -1616,11 +1177,11 @@ }, "EC2Service": { "id": "EC2Service", - "path": "integ-ec2-capacity-provider/EC2Service", + "path": "integ-ec2-capacity-provider-managed-draining/EC2Service", "children": { "Service": { "id": "Service", - "path": "integ-ec2-capacity-provider/EC2Service/Service", + "path": "integ-ec2-capacity-provider-managed-draining/EC2Service/Service", "attributes": { "aws:cdk:cloudformation:type": "AWS::ECS::Service", "aws:cdk:cloudformation:props": { @@ -1665,7 +1226,7 @@ }, "BootstrapVersion": { "id": "BootstrapVersion", - "path": "integ-ec2-capacity-provider/BootstrapVersion", + "path": "integ-ec2-capacity-provider-managed-draining/BootstrapVersion", "constructInfo": { "fqn": "aws-cdk-lib.CfnParameter", "version": "0.0.0" @@ -1673,7 +1234,7 @@ }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", - "path": "integ-ec2-capacity-provider/CheckBootstrapVersion", + "path": "integ-ec2-capacity-provider-managed-draining/CheckBootstrapVersion", "constructInfo": { "fqn": "aws-cdk-lib.CfnRule", "version": "0.0.0" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts index c8a9c059a983a..1973186dbc4ed 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts @@ -5,7 +5,7 @@ import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as integ from '@aws-cdk/integ-tests-alpha'; const app = new cdk.App(); -const stack = new cdk.Stack(app, 'integ-ec2-capacity-provider'); +const stack = new cdk.Stack(app, 'integ-ec2-capacity-provider-managed-draining'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/aws-cdk-lib/LICENSE b/packages/aws-cdk-lib/LICENSE index 9b722c65c5481..dcf28b52a83af 100644 --- a/packages/aws-cdk-lib/LICENSE +++ b/packages/aws-cdk-lib/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/aws-cdk-lib/NOTICE b/packages/aws-cdk-lib/NOTICE index 07256e46441bf..f1dbff982512f 100644 --- a/packages/aws-cdk-lib/NOTICE +++ b/packages/aws-cdk-lib/NOTICE @@ -1,5 +1,5 @@ AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. ------------------------------------------------------------------------------- diff --git a/packages/aws-cdk-lib/aws-ecs/README.md b/packages/aws-cdk-lib/aws-ecs/README.md index d118910def3b8..6fca89a428acd 100644 --- a/packages/aws-cdk-lib/aws-ecs/README.md +++ b/packages/aws-cdk-lib/aws-ecs/README.md @@ -1253,7 +1253,7 @@ rather manage scaling behavior yourself set `enableManagedScaling` to `false`. Additionally [Managed Termination Protection](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-auto-scaling.html#managed-termination-protection) is enabled by default to prevent scale-in behavior from terminating instances that have non-daemon tasks -running on them. This is ideal for tasks that should be ran to completion. If your +running on them. This is ideal for tasks that can be run to completion. If your tasks are safe to interrupt then this protection can be disabled by setting `enableManagedTerminationProtection` to `false`. Managed Scaling must be enabled for Managed Termination Protection to work. @@ -1266,10 +1266,10 @@ Managed Termination Protection to work. > delete the Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-process-shutdown.html). > For other workarounds, see [this GitHub issue](https://github.com/aws/aws-cdk/issues/18179). -[Need to confirm with Doc team] -Additionally [Managed Draining](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-auto-scaling.html#managed-instance-draining) is enabled by default for new capacity providers to -gracefully terminate Amazon ECS instances. Setting `enableManagedDraining` to `true` will replace the instance-draining lifecycle hook -created during addAsgCapacityProvider. +Managed instance draining facilitates graceful termination of Amazon ECS instances. +This allows your service workloads to stop safely and be rescheduled to non-terminating instances. +Infrastructure maintenance and updates are preformed without disruptions to workloads. +To use managed instance draining, set enableManagedDraining to true. ```ts declare const vpc: ec2.Vpc; diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index f8b1e861cae46..c8f7bf65969ea 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -1168,7 +1168,10 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt readonly enableManagedTerminationProtection?: boolean; /** - * PLACEHOLDER FOR DOC + * Managed instance draining facilitates graceful termination of Amazon ECS instances. + * This allows your service workloads to stop safely and be rescheduled to non-terminating instances. + * Infrastructure maintenance and updates are preformed without disruptions to workloads. + * To use managed instance draining, set enableManagedDraining to true. * * @default null */ @@ -1243,7 +1246,7 @@ export class AsgCapacityProvider extends Construct { this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2; this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole; this.enableManagedTerminationProtection = props.enableManagedTerminationProtection ?? true; - this.enableManagedDraining = props.enableManagedDraining ?? undefined; + this.enableManagedDraining = props.enableManagedDraining; let managedDraining = undefined; if (this.enableManagedDraining != undefined) { From 177c45cff774ebb4593b36c29477a977e6492712 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Thu, 4 Jan 2024 17:06:03 -0800 Subject: [PATCH 6/6] change the documentated default to true --- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index c8f7bf65969ea..0143b90b84a98 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -1173,7 +1173,7 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt * Infrastructure maintenance and updates are preformed without disruptions to workloads. * To use managed instance draining, set enableManagedDraining to true. * - * @default null + * @default true */ readonly enableManagedDraining?: boolean;