From dcdd1f7a70cf5ed5f9b5dfb2d05ff602ec73c80e Mon Sep 17 00:00:00 2001 From: Ian Kerins Date: Tue, 16 Sep 2025 22:07:05 -0400 Subject: [PATCH] fix(aws-ecs): allow empty placementStrategies on EC2Service Same fix as #30382 but for `placementStrategies`. Apparently this was not done at that time because CloudFormation [previously did not have the appropriate semantics](https://github.com/aws/aws-cdk/pull/27572#issuecomment-1766287866) for setting PlacementStrategies to the empty array as it did for PlacementConstraints, but that is no longer the case. The CloudFormation docs [state](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-service.html#cfn-ecs-service-placementstrategies): > To remove this property from your service resource, specify an empty PlacementStrategy array. And indeed that works, with this CDK change applied. --- ...cdk-ecs-integration-test-stack.assets.json | 8 +- ...k-ecs-integration-test-stack.template.json | 22 ++++ .../cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 111 +++++++++++------- .../tree.json | 2 +- .../test/ec2/integ.placement-strategies.ts | 6 + .../aws-ecs/lib/ec2/ec2-service.ts | 13 +- .../aws-ecs/test/ec2/ec2-service.test.ts | 25 ++++ 9 files changed, 137 insertions(+), 54 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.assets.json index fad9e7067f6bf..d5d8afe9c133a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.assets.json @@ -1,16 +1,16 @@ { - "version": "45.0.0", + "version": "48.0.0", "files": { - "59dbe7102301a129565a9d0ffcc60b8a5063ca07ff546bcd6f384ffd9857b080": { + "77a00edf8971555571ead3c22cb486b09978436ef675e31e62d7e0eb82b75609": { "displayName": "aws-cdk-ecs-integration-test-stack Template", "source": { "path": "aws-cdk-ecs-integration-test-stack.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-03b9e879": { + "current_account-current_region-b9fed9a6": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "59dbe7102301a129565a9d0ffcc60b8a5063ca07ff546bcd6f384ffd9857b080.json", + "objectKey": "77a00edf8971555571ead3c22cb486b09978436ef675e31e62d7e0eb82b75609.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.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.template.json index dfdc07e1b61d7..a80e5d35538e7 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/aws-cdk-ecs-integration-test-stack.template.json @@ -968,6 +968,28 @@ "DependsOn": [ "TaskDefTaskRole1EDB4A67" ] + }, + "TestEmptyService1DB8D95A": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "EcsCluster97242B84" + }, + "DeploymentConfiguration": { + "MaximumPercent": 200, + "MinimumHealthyPercent": 50 + }, + "EnableECSManagedTags": false, + "LaunchType": "EC2", + "PlacementStrategies": [], + "SchedulingStrategy": "REPLICA", + "TaskDefinition": { + "Ref": "TaskDef54694570" + } + }, + "DependsOn": [ + "TaskDefTaskRole1EDB4A67" + ] } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/cdk.out index 3704a1b682acf..523a9aac37cbf 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"45.0.0"} \ No newline at end of file +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/integ.json index fd337ef8d2812..873de15e21be1 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/integ.json @@ -11,5 +11,5 @@ }, "synthContext": {}, "enableLookups": false, - "minimumCliVersion": "2.1023.0" + "minimumCliVersion": "2.1027.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/manifest.json index eaf3d2135d27e..6e82b19034ce5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "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}/59dbe7102301a129565a9d0ffcc60b8a5063ca07ff546bcd6f384ffd9857b080.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/77a00edf8971555571ead3c22cb486b09978436ef675e31e62d7e0eb82b75609.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -970,6 +970,26 @@ "data": "TestStackService5548C840" } ], + "/aws-cdk-ecs-integration-test-stack/Test_Empty": [ + { + "type": "aws:cdk:warning", + "data": "minHealthyPercent has not been configured so the default value of 50% is used. The number of running tasks will decrease below the desired count during deployments etc. See https://github.com/aws/aws-cdk/issues/31705 [ack: @aws-cdk/aws-ecs:minHealthyPercent]" + }, + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], + "/aws-cdk-ecs-integration-test-stack/Test_Empty/Service": [ + { + "type": "aws:cdk:logicalId", + "data": "TestEmptyService1DB8D95A" + } + ], "/aws-cdk-ecs-integration-test-stack/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -996,57 +1016,48 @@ "properties": { "module": "aws-cdk-lib", "flags": { - "@aws-cdk/core:enableStackNameDuplicates": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { "recommendedValue": true, - "explanation": "Allow multiple stacks with the same name" - }, - "aws-cdk:enableDiffNoFail": { - "recommendedValue": true, - "explanation": "Make `cdk diff` not fail when there are differences" + "explanation": "Pass signingProfileName to CfnSigningProfile" }, "@aws-cdk/core:newStyleStackSynthesis": { "recommendedValue": true, - "explanation": "Switch to new stack synthesis method which enables CI/CD" + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/core:stackRelativeExports": { "recommendedValue": true, - "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path" - }, - "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": { - "recommendedValue": true, - "explanation": "DockerImageAsset properly supports `.dockerignore` files by default" - }, - "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": { - "recommendedValue": true, - "explanation": "Fix the referencing of SecretsManager names from ARNs" - }, - "@aws-cdk/aws-kms:defaultKeyPolicies": { - "recommendedValue": true, - "explanation": "Tighten default KMS key policies" - }, - "@aws-cdk/aws-s3:grantWriteWithoutAcl": { - "recommendedValue": true, - "explanation": "Remove `PutObjectAcl` from Bucket.grantWrite" + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } }, - "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": { + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { "recommendedValue": true, - "explanation": "Do not specify a default DesiredCount for ECS services" + "explanation": "Disable implicit openListener when custom security groups are provided" }, "@aws-cdk/aws-rds:lowercaseDbIdentifier": { "recommendedValue": true, - "explanation": "Force lowercasing of RDS Cluster names in CDK" + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { "recommendedValue": true, - "explanation": "Allow adding/removing multiple UsagePlanKeys independently" - }, - "@aws-cdk/aws-efs:defaultEncryptionAtRest": { - "recommendedValue": true, - "explanation": "Enable this feature flag to have elastic file systems encrypted at rest by default." + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-lambda:recognizeVersionProps": { "recommendedValue": true, - "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-lambda:recognizeLayerVersion": { "userValue": true, @@ -1055,7 +1066,10 @@ }, "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { "recommendedValue": true, - "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default." + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/core:checkSecretUsage": { "userValue": true, @@ -1276,7 +1290,10 @@ }, "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { "recommendedValue": true, - "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy" + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-eks:nodegroupNameAttribute": { "userValue": true, @@ -1305,7 +1322,10 @@ }, "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { "recommendedValue": true, - "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model." + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/core:explicitStackTags": { "userValue": true, @@ -1369,7 +1389,10 @@ }, "@aws-cdk/core:aspectStabilization": { "recommendedValue": true, - "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis." + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { "userValue": true, @@ -1403,7 +1426,10 @@ }, "@aws-cdk/pipelines:reduceStageRoleTrustScope": { "recommendedValue": true, - "explanation": "Remove the root account principal from Stage addActions trust policy" + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-events:requireEventBusPolicySid": { "userValue": true, @@ -1426,7 +1452,10 @@ }, "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { "recommendedValue": true, - "explanation": "When enabled, scopes down the trust policy for the cross-account action role" + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } }, "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { "userValue": true, @@ -1461,5 +1490,5 @@ } } }, - "minimumCliVersion": "2.1023.0" + "minimumCliVersion": "2.1027.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/tree.json index 046f8ffec11a8..26cb6172263b5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-ecs-integration-test-stack":{"id":"aws-cdk-ecs-integration-test-stack","path":"aws-cdk-ecs-integration-test-stack","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VPC":{"id":"VPC","path":"aws-cdk-ecs-integration-test-stack/VPC","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.Vpc","version":"0.0.0","metadata":[{"restrictDefaultSecurityGroup":false}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/VPC/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPC","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC"}]}}},"PublicSubnet1":{"id":"PublicSubnet1","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PublicSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{},{"addNatGateway":["*"]}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"}}}},"EIP":{"id":"EIP","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/EIP","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnEIP","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/NATGateway","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnNatGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet1EIP6AD938E8","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"},"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}]}}}}},"PublicSubnet2":{"id":"PublicSubnet2","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PublicSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{},{"addNatGateway":["*"]}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"}}}},"EIP":{"id":"EIP","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/EIP","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnEIP","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/NATGateway","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnNatGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet2EIP4947BC00","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"},"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}]}}}}},"PrivateSubnet1":{"id":"PrivateSubnet1","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrivateSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"},"subnetId":{"Ref":"VPCPrivateSubnet1Subnet8BCA10E0"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet1NATGatewayE0556630"},"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"}}}}}},"PrivateSubnet2":{"id":"PrivateSubnet2","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrivateSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"},"subnetId":{"Ref":"VPCPrivateSubnet2SubnetCFCDAA7A"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet2NATGateway3C070193"},"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"}}}}}},"IGW":{"id":"IGW","path":"aws-cdk-ecs-integration-test-stack/VPC/IGW","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnInternetGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::InternetGateway","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC"}]}}},"VPCGW":{"id":"VPCGW","path":"aws-cdk-ecs-integration-test-stack/VPC/VPCGW","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::VPCGatewayAttachment","aws:cdk:cloudformation:props":{"internetGatewayId":{"Ref":"VPCIGWB7E252D3"},"vpcId":{"Ref":"VPCB9E5F0B4"}}}}}},"EcsCluster":{"id":"EcsCluster","path":"aws-cdk-ecs-integration-test-stack/EcsCluster","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Cluster","version":"0.0.0","metadata":[{"vpc":"*"},{"addCapacity":["*",{"instanceType":"*"}]},{"addAutoScalingGroup":["*",{"machineImageType":0}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnCluster","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::Cluster","aws:cdk:cloudformation:props":{}}},"DefaultAutoScalingGroup":{"id":"DefaultAutoScalingGroup","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.AutoScalingGroup","version":"0.0.0","metadata":[{"vpc":"*","machineImage":"*","updateType":"Replace","instanceType":"*"},{"addUserData":["*"]},{"addUserData":["*"]},{"addUserData":["*"]},{"addUserData":["*"]},{"addToRolePolicy":[{}]},{"addToRolePolicy":[{}]},{"addToRolePolicy":[{}]}]},"children":{"InstanceSecurityGroup":{"id":"InstanceSecurityGroup","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.SecurityGroup","version":"0.0.0","metadata":[{"vpc":"*","allowAllOutbound":true}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSecurityGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroup","aws:cdk:cloudformation:props":{"groupDescription":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup","securityGroupEgress":[{"cidrIp":"0.0.0.0/0","description":"Allow all outbound traffic by default","ipProtocol":"-1"}],"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}}}},"InstanceRole":{"id":"InstanceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"roleName":"*","assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportInstanceRole":{"id":"ImportInstanceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/ImportInstanceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"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":["EcsCluster97242B84","Arn"]}},{"Action":["ecs:Poll","ecs:StartTelemetrySession"],"Condition":{"ArnEquals":{"ecs:cluster":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}},"Effect":"Allow","Resource":"*"},{"Action":["ecr:GetAuthorizationToken","ecs:DiscoverPollEndpoint","logs:CreateLogStream","logs:PutLogEvents"],"Effect":"Allow","Resource":"*"}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupInstanceRoleDefaultPolicy04DC6C80","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupInstanceRole3C026863"}]}}}}}}},"InstanceProfile":{"id":"InstanceProfile","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceProfile","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnInstanceProfile","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::InstanceProfile","aws:cdk:cloudformation:props":{"roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupInstanceRole3C026863"}]}}},"ImportedInstanceProfile":{"id":"ImportedInstanceProfile","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/ImportedInstanceProfile","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"LaunchTemplate":{"id":"LaunchTemplate","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.LaunchTemplate","version":"0.0.0","metadata":[{"machineImage":"*","instanceType":"*","detailedMonitoring":false,"securityGroup":"*","userData":"*","associatePublicIpAddress":"*","spotOptions":"*","blockDevices":"*","instanceProfile":"*","keyPair":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnLaunchTemplate","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::LaunchTemplate","aws:cdk:cloudformation:props":{"launchTemplateData":{"iamInstanceProfile":{"arn":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupInstanceProfile2CE606B3","Arn"]}},"imageId":{"Ref":"SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter"},"instanceType":"t2.micro","monitoring":{"enabled":false},"securityGroupIds":[{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupInstanceSecurityGroup912E1231","GroupId"]}],"tagSpecifications":[{"resourceType":"instance","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]},{"resourceType":"volume","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]}],"userData":{"Fn::Base64":{"Fn::Join":["",["#!/bin/bash\necho ECS_CLUSTER=",{"Ref":"EcsCluster97242B84"}," >> /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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]}]}}}}},"ASG":{"id":"ASG","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/ASG","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.CfnAutoScalingGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::AutoScaling::AutoScalingGroup","aws:cdk:cloudformation:props":{"launchTemplate":{"launchTemplateId":{"Ref":"EcsClusterDefaultAutoScalingGroupLaunchTemplate3719972A"},"version":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupLaunchTemplate3719972A","LatestVersionNumber"]}},"maxSize":"1","minSize":"1","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup","propagateAtLaunch":true}],"vpcZoneIdentifier":[{"Ref":"VPCPrivateSubnet1Subnet8BCA10E0"},{"Ref":"VPCPrivateSubnet2SubnetCFCDAA7A"}]}}},"DrainECSHook":{"id":"DrainECSHook","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"children":{"Function":{"id":"Function","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"code":"*","handler":"*","runtime":"*","timeout":"*","environment":"*"},{"addEnvironment":["*","*"]}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"managedPolicies":[{"managedPolicyArn":"*"}]},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"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":"EcsClusterDefaultAutoScalingGroupASGC1A785DB"}]]}},{"Action":["ecs:DescribeContainerInstances","ecs:DescribeTasks","ecs:ListTasks","ecs:UpdateContainerInstancesState"],"Condition":{"ArnEquals":{"ecs:cluster":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}},"Effect":"Allow","Resource":"*"},{"Action":["ecs:ListContainerInstances","ecs:SubmitContainerStateChange","ecs:SubmitTaskStateChange"],"Effect":"Allow","Resource":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRoleDefaultPolicyA45BF396","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"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(f\"Got event without EC2InstanceId: { 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":"EcsCluster97242B84"}}},"handler":"index.lambda_handler","role":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA","Arn"]},"runtime":"python3.13","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}],"timeout":310}}},"AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572":{"id":"AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnPermission","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Permission","aws:cdk:cloudformation:props":{"action":"lambda:InvokeFunction","functionName":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E","Arn"]},"principal":"sns.amazonaws.com","sourceArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}}},"Topic":{"id":"Topic","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Topic","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.Subscription","version":"0.0.0","metadata":[{"topic":"*","endpoint":"*","protocol":"lambda","filterPolicy":"*","filterPolicyWithMessageBody":"*","region":"*","deadLetterQueue":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Topic/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.CfnSubscription","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SNS::Subscription","aws:cdk:cloudformation:props":{"endpoint":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E","Arn"]},"protocol":"lambda","topicArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}}}}}}}}},"LifecycleHookDrainHook":{"id":"LifecycleHookDrainHook","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.LifecycleHook","version":"0.0.0","metadata":[{"autoScalingGroup":"*","lifecycleTransition":"autoscaling:EC2_INSTANCE_TERMINATING","defaultResult":"CONTINUE","notificationTarget":"*","heartbeatTimeout":"*"}]},"children":{"Topic":{"id":"Topic","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Topic","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.Topic","version":"0.0.0","metadata":[{"masterKey":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Topic/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.CfnTopic","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SNS::Topic","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}}}},"Role":{"id":"Role","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportRole":{"id":"ImportRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/ImportRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"sns:Publish","Effect":"Allow","Resource":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleDefaultPolicy75002F88","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleA38EC83B"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.CfnLifecycleHook","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::AutoScaling::LifecycleHook","aws:cdk:cloudformation:props":{"autoScalingGroupName":{"Ref":"EcsClusterDefaultAutoScalingGroupASGC1A785DB"},"defaultResult":"CONTINUE","heartbeatTimeout":300,"lifecycleTransition":"autoscaling:EC2_INSTANCE_TERMINATING","notificationTargetArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"},"roleArn":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleA38EC83B","Arn"]}}}}}}}}}},"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":"aws-cdk-ecs-integration-test-stack/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":"aws-cdk-ecs-integration-test-stack/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","metadata":[]}},"TaskDef":{"id":"TaskDef","path":"aws-cdk-ecs-integration-test-stack/TaskDef","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Ec2TaskDefinition","version":"0.0.0","metadata":["*","*","*"]},"children":{"TaskRole":{"id":"TaskRole","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}}]},"children":{"ImportTaskRole":{"id":"ImportTaskRole","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole/ImportTaskRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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"}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/TaskDef/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnTaskDefinition","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::TaskDefinition","aws:cdk:cloudformation:props":{"containerDefinitions":[{"essential":true,"image":"amazon/amazon-ecs-sample","memory":256,"name":"web"}],"family":"awscdkecsintegrationteststackTaskDefF811D259","networkMode":"bridge","requiresCompatibilities":["EC2"],"taskRoleArn":{"Fn::GetAtt":["TaskDefTaskRole1EDB4A67","Arn"]}}}},"web":{"id":"web","path":"aws-cdk-ecs-integration-test-stack/TaskDef/web","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.ContainerDefinition","version":"0.0.0"}}}},"Test_Stack":{"id":"Test_Stack","path":"aws-cdk-ecs-integration-test-stack/Test_Stack","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Ec2Service","version":"0.0.0","metadata":["*","*"]},"children":{"Service":{"id":"Service","path":"aws-cdk-ecs-integration-test-stack/Test_Stack/Service","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnService","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::Service","aws:cdk:cloudformation:props":{"cluster":{"Ref":"EcsCluster97242B84"},"deploymentConfiguration":{"maximumPercent":200,"minimumHealthyPercent":50},"enableEcsManagedTags":false,"launchType":"EC2","placementStrategies":[{"type":"binpack","field":"CPU"},{"type":"binpack","field":"MEMORY"}],"schedulingStrategy":"REPLICA","taskDefinition":{"Ref":"TaskDef54694570"}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-ecs-integration-test-stack/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-ecs-integration-test-stack/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-ecs-integration-test-stack":{"id":"aws-cdk-ecs-integration-test-stack","path":"aws-cdk-ecs-integration-test-stack","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"VPC":{"id":"VPC","path":"aws-cdk-ecs-integration-test-stack/VPC","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.Vpc","version":"0.0.0","metadata":[{"restrictDefaultSecurityGroup":false}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/VPC/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPC","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC"}]}}},"PublicSubnet1":{"id":"PublicSubnet1","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PublicSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{},{"addNatGateway":["*"]}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"}}}},"EIP":{"id":"EIP","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/EIP","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnEIP","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1/NATGateway","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnNatGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet1EIP6AD938E8","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"},"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet1"}]}}}}},"PublicSubnet2":{"id":"PublicSubnet2","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PublicSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{},{"addNatGateway":["*"]}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"}}}},"EIP":{"id":"EIP","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/EIP","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnEIP","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2/NATGateway","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnNatGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet2EIP4947BC00","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"},"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PublicSubnet2"}]}}}}},"PrivateSubnet1":{"id":"PrivateSubnet1","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrivateSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"},"subnetId":{"Ref":"VPCPrivateSubnet1Subnet8BCA10E0"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet1/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet1NATGatewayE0556630"},"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"}}}}}},"PrivateSubnet2":{"id":"PrivateSubnet2","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrivateSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{}]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/Subnet","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/RouteTable","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/RouteTableAssociation","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"},"subnetId":{"Ref":"VPCPrivateSubnet2SubnetCFCDAA7A"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-ecs-integration-test-stack/VPC/PrivateSubnet2/DefaultRoute","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet2NATGateway3C070193"},"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"}}}}}},"IGW":{"id":"IGW","path":"aws-cdk-ecs-integration-test-stack/VPC/IGW","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnInternetGateway","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::InternetGateway","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/VPC"}]}}},"VPCGW":{"id":"VPCGW","path":"aws-cdk-ecs-integration-test-stack/VPC/VPCGW","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::VPCGatewayAttachment","aws:cdk:cloudformation:props":{"internetGatewayId":{"Ref":"VPCIGWB7E252D3"},"vpcId":{"Ref":"VPCB9E5F0B4"}}}}}},"EcsCluster":{"id":"EcsCluster","path":"aws-cdk-ecs-integration-test-stack/EcsCluster","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Cluster","version":"0.0.0","metadata":[{"vpc":"*"},{"addCapacity":["*",{"instanceType":"*"}]},{"addAutoScalingGroup":["*",{"machineImageType":0}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnCluster","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::Cluster","aws:cdk:cloudformation:props":{}}},"DefaultAutoScalingGroup":{"id":"DefaultAutoScalingGroup","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.AutoScalingGroup","version":"0.0.0","metadata":[{"vpc":"*","machineImage":"*","updateType":"Replace","instanceType":"*"},{"addUserData":["*"]},{"addUserData":["*"]},{"addUserData":["*"]},{"addUserData":["*"]},{"addToRolePolicy":[{}]},{"addToRolePolicy":[{}]},{"addToRolePolicy":[{}]}]},"children":{"InstanceSecurityGroup":{"id":"InstanceSecurityGroup","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.SecurityGroup","version":"0.0.0","metadata":[{"vpc":"*","allowAllOutbound":true}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSecurityGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroup","aws:cdk:cloudformation:props":{"groupDescription":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup","securityGroupEgress":[{"cidrIp":"0.0.0.0/0","description":"Allow all outbound traffic by default","ipProtocol":"-1"}],"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}}}},"InstanceRole":{"id":"InstanceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"roleName":"*","assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportInstanceRole":{"id":"ImportInstanceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/ImportInstanceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"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":["EcsCluster97242B84","Arn"]}},{"Action":["ecs:Poll","ecs:StartTelemetrySession"],"Condition":{"ArnEquals":{"ecs:cluster":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}},"Effect":"Allow","Resource":"*"},{"Action":["ecr:GetAuthorizationToken","ecs:DiscoverPollEndpoint","logs:CreateLogStream","logs:PutLogEvents"],"Effect":"Allow","Resource":"*"}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupInstanceRoleDefaultPolicy04DC6C80","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupInstanceRole3C026863"}]}}}}}}},"InstanceProfile":{"id":"InstanceProfile","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/InstanceProfile","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnInstanceProfile","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::InstanceProfile","aws:cdk:cloudformation:props":{"roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupInstanceRole3C026863"}]}}},"ImportedInstanceProfile":{"id":"ImportedInstanceProfile","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/ImportedInstanceProfile","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"LaunchTemplate":{"id":"LaunchTemplate","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.LaunchTemplate","version":"0.0.0","metadata":[{"machineImage":"*","instanceType":"*","detailedMonitoring":false,"securityGroup":"*","userData":"*","associatePublicIpAddress":"*","spotOptions":"*","blockDevices":"*","instanceProfile":"*","keyPair":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnLaunchTemplate","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::LaunchTemplate","aws:cdk:cloudformation:props":{"launchTemplateData":{"iamInstanceProfile":{"arn":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupInstanceProfile2CE606B3","Arn"]}},"imageId":{"Ref":"SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter"},"instanceType":"t2.micro","monitoring":{"enabled":false},"securityGroupIds":[{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupInstanceSecurityGroup912E1231","GroupId"]}],"tagSpecifications":[{"resourceType":"instance","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]},{"resourceType":"volume","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]}],"userData":{"Fn::Base64":{"Fn::Join":["",["#!/bin/bash\necho ECS_CLUSTER=",{"Ref":"EcsCluster97242B84"}," >> /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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LaunchTemplate"}]}]}}}}},"ASG":{"id":"ASG","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/ASG","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.CfnAutoScalingGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::AutoScaling::AutoScalingGroup","aws:cdk:cloudformation:props":{"launchTemplate":{"launchTemplateId":{"Ref":"EcsClusterDefaultAutoScalingGroupLaunchTemplate3719972A"},"version":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupLaunchTemplate3719972A","LatestVersionNumber"]}},"maxSize":"1","minSize":"1","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup","propagateAtLaunch":true}],"vpcZoneIdentifier":[{"Ref":"VPCPrivateSubnet1Subnet8BCA10E0"},{"Ref":"VPCPrivateSubnet2SubnetCFCDAA7A"}]}}},"DrainECSHook":{"id":"DrainECSHook","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"children":{"Function":{"id":"Function","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"code":"*","handler":"*","runtime":"*","timeout":"*","environment":"*"},{"addEnvironment":["*","*"]}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"managedPolicies":[{"managedPolicyArn":"*"}]},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"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":"EcsClusterDefaultAutoScalingGroupASGC1A785DB"}]]}},{"Action":["ecs:DescribeContainerInstances","ecs:DescribeTasks","ecs:ListTasks","ecs:UpdateContainerInstancesState"],"Condition":{"ArnEquals":{"ecs:cluster":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}},"Effect":"Allow","Resource":"*"},{"Action":["ecs:ListContainerInstances","ecs:SubmitContainerStateChange","ecs:SubmitTaskStateChange"],"Effect":"Allow","Resource":{"Fn::GetAtt":["EcsCluster97242B84","Arn"]}}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRoleDefaultPolicyA45BF396","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"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(f\"Got event without EC2InstanceId: { 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":"EcsCluster97242B84"}}},"handler":"index.lambda_handler","role":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA","Arn"]},"runtime":"python3.13","tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}],"timeout":310}}},"AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572":{"id":"AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/AllowInvoke:awscdkecsintegrationteststackEcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicD01B2572","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnPermission","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Permission","aws:cdk:cloudformation:props":{"action":"lambda:InvokeFunction","functionName":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E","Arn"]},"principal":"sns.amazonaws.com","sourceArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}}},"Topic":{"id":"Topic","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Topic","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.Subscription","version":"0.0.0","metadata":[{"topic":"*","endpoint":"*","protocol":"lambda","filterPolicy":"*","filterPolicyWithMessageBody":"*","region":"*","deadLetterQueue":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/DrainECSHook/Function/Topic/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.CfnSubscription","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SNS::Subscription","aws:cdk:cloudformation:props":{"endpoint":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E","Arn"]},"protocol":"lambda","topicArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}}}}}}}}},"LifecycleHookDrainHook":{"id":"LifecycleHookDrainHook","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.LifecycleHook","version":"0.0.0","metadata":[{"autoScalingGroup":"*","lifecycleTransition":"autoscaling:EC2_INSTANCE_TERMINATING","defaultResult":"CONTINUE","notificationTarget":"*","heartbeatTimeout":"*"}]},"children":{"Topic":{"id":"Topic","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Topic","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.Topic","version":"0.0.0","metadata":[{"masterKey":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Topic/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_sns.CfnTopic","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SNS::Topic","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}}}},"Role":{"id":"Role","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportRole":{"id":"ImportRole","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/ImportRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup"}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Role/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"sns:Publish","Effect":"Allow","Resource":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"}}],"Version":"2012-10-17"},"policyName":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleDefaultPolicy75002F88","roles":[{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleA38EC83B"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/EcsCluster/DefaultAutoScalingGroup/LifecycleHookDrainHook/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_autoscaling.CfnLifecycleHook","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::AutoScaling::LifecycleHook","aws:cdk:cloudformation:props":{"autoScalingGroupName":{"Ref":"EcsClusterDefaultAutoScalingGroupASGC1A785DB"},"defaultResult":"CONTINUE","heartbeatTimeout":300,"lifecycleTransition":"autoscaling:EC2_INSTANCE_TERMINATING","notificationTargetArn":{"Ref":"EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookTopicACD2D4A4"},"roleArn":{"Fn::GetAtt":["EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleA38EC83B","Arn"]}}}}}}}}}},"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":"aws-cdk-ecs-integration-test-stack/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":"aws-cdk-ecs-integration-test-stack/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","metadata":[]}},"TaskDef":{"id":"TaskDef","path":"aws-cdk-ecs-integration-test-stack/TaskDef","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Ec2TaskDefinition","version":"0.0.0","metadata":["*","*","*"]},"children":{"TaskRole":{"id":"TaskRole","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}}]},"children":{"ImportTaskRole":{"id":"ImportTaskRole","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole/ImportTaskRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/TaskDef/TaskRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"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"}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-ecs-integration-test-stack/TaskDef/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnTaskDefinition","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::TaskDefinition","aws:cdk:cloudformation:props":{"containerDefinitions":[{"essential":true,"image":"amazon/amazon-ecs-sample","memory":256,"name":"web"}],"family":"awscdkecsintegrationteststackTaskDefF811D259","networkMode":"bridge","requiresCompatibilities":["EC2"],"taskRoleArn":{"Fn::GetAtt":["TaskDefTaskRole1EDB4A67","Arn"]}}}},"web":{"id":"web","path":"aws-cdk-ecs-integration-test-stack/TaskDef/web","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.ContainerDefinition","version":"0.0.0"}}}},"Test_Stack":{"id":"Test_Stack","path":"aws-cdk-ecs-integration-test-stack/Test_Stack","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Ec2Service","version":"0.0.0","metadata":["*","*"]},"children":{"Service":{"id":"Service","path":"aws-cdk-ecs-integration-test-stack/Test_Stack/Service","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnService","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::Service","aws:cdk:cloudformation:props":{"cluster":{"Ref":"EcsCluster97242B84"},"deploymentConfiguration":{"maximumPercent":200,"minimumHealthyPercent":50},"enableEcsManagedTags":false,"launchType":"EC2","placementStrategies":[{"type":"binpack","field":"CPU"},{"type":"binpack","field":"MEMORY"}],"schedulingStrategy":"REPLICA","taskDefinition":{"Ref":"TaskDef54694570"}}}}}},"Test_Empty":{"id":"Test_Empty","path":"aws-cdk-ecs-integration-test-stack/Test_Empty","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.Ec2Service","version":"0.0.0","metadata":["*","*"]},"children":{"Service":{"id":"Service","path":"aws-cdk-ecs-integration-test-stack/Test_Empty/Service","constructInfo":{"fqn":"aws-cdk-lib.aws_ecs.CfnService","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECS::Service","aws:cdk:cloudformation:props":{"cluster":{"Ref":"EcsCluster97242B84"},"deploymentConfiguration":{"maximumPercent":200,"minimumHealthyPercent":50},"enableEcsManagedTags":false,"launchType":"EC2","placementStrategies":[],"schedulingStrategy":"REPLICA","taskDefinition":{"Ref":"TaskDef54694570"}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-ecs-integration-test-stack/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-ecs-integration-test-stack/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts index 67169c7651da4..a8c1c6367d0e6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts @@ -37,6 +37,12 @@ class EcsStack extends cdk.Stack { ecs.PlacementStrategy.packedByMemory(), ], }); + + new ecs.Ec2Service(this, 'Test_Empty', { + cluster, + taskDefinition, + placementStrategies: [], + }); } } diff --git a/packages/aws-cdk-lib/aws-ecs/lib/ec2/ec2-service.ts b/packages/aws-cdk-lib/aws-ecs/lib/ec2/ec2-service.ts index 414ab7cea1df0..84ca221f6352c 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/ec2/ec2-service.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/ec2/ec2-service.ts @@ -163,7 +163,7 @@ export class Ec2Service extends BaseService implements IEc2Service { } private constraints?: CfnService.PlacementConstraintProperty[]; - private readonly strategies: CfnService.PlacementStrategyProperty[]; + private strategies?: CfnService.PlacementStrategyProperty[]; private readonly daemon: boolean; private readonly availabilityZoneRebalancingEnabled: boolean; @@ -212,15 +212,13 @@ export class Ec2Service extends BaseService implements IEc2Service { cluster: props.cluster.clusterName, taskDefinition: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn, placementConstraints: Lazy.any({ produce: () => this.constraints }), - placementStrategies: Lazy.any({ produce: () => this.strategies }, { omitEmptyArray: true }), + placementStrategies: Lazy.any({ produce: () => this.strategies }), schedulingStrategy: props.daemon ? 'DAEMON' : 'REPLICA', availabilityZoneRebalancing: props.availabilityZoneRebalancing, }, props.taskDefinition); // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); - this.constraints = undefined; - this.strategies = []; this.daemon = props.daemon || false; this.availabilityZoneRebalancingEnabled = props.availabilityZoneRebalancing === AvailabilityZoneRebalancing.ENABLED; @@ -249,7 +247,9 @@ export class Ec2Service extends BaseService implements IEc2Service { if (props.placementConstraints) { this.addPlacementConstraints(...props.placementConstraints); } - this.addPlacementStrategies(...props.placementStrategies || []); + if (props.placementStrategies) { + this.addPlacementStrategies(...props.placementStrategies); + } this.node.addValidation({ validate: () => !this.taskDefinition.defaultContainer ? ['A TaskDefinition must have at least one essential container'] : [], @@ -272,13 +272,14 @@ export class Ec2Service extends BaseService implements IEc2Service { throw new ValidationError("Can't configure placement strategies when daemon=true", this); } - if (strategies.length > 0 && this.strategies.length === 0 && this.availabilityZoneRebalancingEnabled) { + if (strategies.length > 0 && !this.strategies && this.availabilityZoneRebalancingEnabled) { const [placement] = strategies[0].toJson(); if (placement.type !== 'spread' || placement.field !== BuiltInAttributes.AVAILABILITY_ZONE) { throw new ValidationError(`AvailabilityZoneBalancing.ENABLED requires that the first placement strategy, if any, be 'spread across "${BuiltInAttributes.AVAILABILITY_ZONE}"'`, this); } } + this.strategies = []; for (const strategy of strategies) { this.strategies.push(...strategy.toJson()); } diff --git a/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-service.test.ts b/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-service.test.ts index 82475731bbc02..b9ffc8a90fd95 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-service.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-service.test.ts @@ -2307,6 +2307,31 @@ describe('ec2 service', () => { }); }); + test('with empty [] placement strategies', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + addDefaultCapacityProvider(cluster, stack, vpc); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef'); + + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + placementStrategies: [], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + PlacementStrategies: Match.arrayEquals([]), + }); + }); + testDeprecated('with both propagateTags and propagateTaskTagsFrom defined', () => { // GIVEN const stack = new cdk.Stack();