From 3686f91b328ff946a60d793cd378e18b6ca32b2e Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Sun, 21 Jan 2024 12:34:02 +0100 Subject: [PATCH 01/31] feat(docdb): support snapshot removal policy --- ...-removal-policy-snapshot-stack.assets.json | 19 + ...emoval-policy-snapshot-stack.template.json | 583 +++++++++++ ...efaultTestDeployAssertF3753098.assets.json | 19 + ...aultTestDeployAssertF3753098.template.json | 36 + .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 287 +++++ .../tree.json | 980 ++++++++++++++++++ .../integ.cluster-removal-policy-snapshot.ts | 58 ++ packages/aws-cdk-lib/aws-docdb/lib/cluster.ts | 17 +- .../aws-docdb/test/cluster.test.ts | 42 + packages/aws-cdk-lib/core/lib/cfn-resource.ts | 1 + .../core/test/cfn-resource.test.ts | 1 + 13 files changed, 2052 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.assets.json new file mode 100644 index 0000000000000..16a7be4277e5e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "b904b14d6955261a0572cd8fee5c1051667909a92d6b5391973f3e04b4f57531": { + "source": { + "path": "aws-cdk-docdb-removal-policy-snapshot-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b904b14d6955261a0572cd8fee5c1051667909a92d6b5391973f3e04b4f57531.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json new file mode 100644 index 0000000000000..00446c1b294c2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json @@ -0,0 +1,583 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC" + ] + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet2EIP4947BC00": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2NATGateway3C070193": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet2EIP4947BC00", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ] + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + }, + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + } + } + }, + "VPCPrivateSubnet2SubnetCFCDAA7A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet2RouteTable0A19E10E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet2RouteTableAssociation0C73D413": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "VPCPrivateSubnet2DefaultRouteF4F5CFD2": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + }, + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "ParamsA8366201": { + "Type": "AWS::DocDB::DBClusterParameterGroup", + "Properties": { + "Description": "A nice parameter group", + "Family": "docdb3.6", + "Parameters": { + "audit_logs": "disabled", + "tls": "enabled", + "ttl_monitor": "enabled" + } + } + }, + "DbSecurity381C2C15": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "DatabaseSubnets56F17B9A": { + "Type": "AWS::DocDB::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "Subnets for Database database", + "SubnetIds": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ] + } + }, + "DatabaseSecurityGroup5C91FDCB": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "DocumentDB security group", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "DatabaseSecurityGroupfrom00000IndirectPortF24F2E03": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "CidrIp": "0.0.0.0/0", + "Description": "Open to the world", + "FromPort": { + "Fn::GetAtt": [ + "DatabaseB269D8BB", + "Port" + ] + }, + "GroupId": { + "Fn::GetAtt": [ + "DatabaseSecurityGroup5C91FDCB", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "ToPort": { + "Fn::GetAtt": [ + "DatabaseB269D8BB", + "Port" + ] + } + } + }, + "DatabaseB269D8BB": { + "Type": "AWS::DocDB::DBCluster", + "Properties": { + "DBClusterParameterGroupName": { + "Ref": "ParamsA8366201" + }, + "DBSubnetGroupName": { + "Ref": "DatabaseSubnets56F17B9A" + }, + "EngineVersion": "3.6.0", + "KmsKeyId": { + "Fn::GetAtt": [ + "DbSecurity381C2C15", + "Arn" + ] + }, + "MasterUserPassword": "7959866cacc02c2d243ecfe177464fe6", + "MasterUsername": "docdb", + "StorageEncrypted": true, + "VpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "DatabaseSecurityGroup5C91FDCB", + "GroupId" + ] + } + ] + }, + "UpdateReplacePolicy": "Snapshot", + "DeletionPolicy": "Snapshot" + }, + "DatabaseInstance1844F58FD": { + "Type": "AWS::DocDB::DBInstance", + "Properties": { + "DBClusterIdentifier": { + "Ref": "DatabaseB269D8BB" + }, + "DBInstanceClass": "db.r5.large", + "EnablePerformanceInsights": true + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC", + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets.json new file mode 100644 index 0000000000000..230756e4f1fa9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/cdk.out new file mode 100644 index 0000000000000..2313ab5436501 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/integ.json new file mode 100644 index 0000000000000..b1db63db0f8d2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "34.0.0", + "testCases": { + "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest": { + "stacks": [ + "aws-cdk-docdb-removal-policy-snapshot-stack" + ], + "assertionStack": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert", + "assertionStackName": "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/manifest.json new file mode 100644 index 0000000000000..0136687195d29 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/manifest.json @@ -0,0 +1,287 @@ +{ + "version": "34.0.0", + "artifacts": { + "aws-cdk-docdb-removal-policy-snapshot-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-docdb-removal-policy-snapshot-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-docdb-removal-policy-snapshot-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-docdb-removal-policy-snapshot-stack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b904b14d6955261a0572cd8fee5c1051667909a92d6b5391973f3e04b4f57531.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-docdb-removal-policy-snapshot-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-docdb-removal-policy-snapshot-stack.assets" + ], + "metadata": { + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1SubnetB4246D30" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableFEE4B781" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableAssociation0B0896DC" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1DefaultRoute91CEF279" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1EIP6AD938E8" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1NATGatewayE0556630" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2Subnet74179F39" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTable6F1A15F1" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTableAssociation5A808732" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2DefaultRouteB7481BBA" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2EIP4947BC00" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2NATGateway3C070193" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableBE8A6027" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableAssociation347902D1" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1DefaultRouteAE1D6490" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTable0A19E10E" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTableAssociation0C73D413" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2DefaultRouteF4F5CFD2" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Params/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ParamsA8366201" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/DbSecurity/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DbSecurity381C2C15" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Database/Subnets": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseSubnets56F17B9A" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Database/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseSecurityGroup5C91FDCB" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Database/SecurityGroup/from 0.0.0.0_0:{IndirectPort}": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseSecurityGroupfrom00000IndirectPortF24F2E03" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Database/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseB269D8BB" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/Database/Instance1": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseInstance1844F58FD" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-docdb-removal-policy-snapshot-stack" + }, + "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "awscdkdocdbremovalpolicysnapshotintegDefaultTestDeployAssertF3753098.assets" + ], + "metadata": { + "/aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/tree.json new file mode 100644 index 0000000000000..4d25c6c68a704 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/tree.json @@ -0,0 +1,980 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-docdb-removal-policy-snapshot-stack": { + "id": "aws-cdk-docdb-removal-policy-snapshot-stack", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack", + "children": { + "VPC": { + "id": "VPC", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1/NATGateway", + "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-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "subnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2/NATGateway", + "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-docdb-removal-policy-snapshot-stack/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + }, + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + }, + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "Params": { + "id": "Params", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Params", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Params/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DocDB::DBClusterParameterGroup", + "aws:cdk:cloudformation:props": { + "description": "A nice parameter group", + "family": "docdb3.6", + "parameters": { + "audit_logs": "disabled", + "tls": "enabled", + "ttl_monitor": "enabled" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.CfnDBClusterParameterGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.ClusterParameterGroup", + "version": "0.0.0" + } + }, + "DbSecurity": { + "id": "DbSecurity", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/DbSecurity", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/DbSecurity/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "0.0.0" + } + }, + "Database": { + "id": "Database", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database", + "children": { + "Subnets": { + "id": "Subnets", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/Subnets", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DocDB::DBSubnetGroup", + "aws:cdk:cloudformation:props": { + "dbSubnetGroupDescription": "Subnets for Database database", + "subnetIds": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.CfnDBSubnetGroup", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "DocumentDB security group", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "from 0.0.0.0_0:{IndirectPort}": { + "id": "from 0.0.0.0_0:{IndirectPort}", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/SecurityGroup/from 0.0.0.0_0:{IndirectPort}", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupIngress", + "aws:cdk:cloudformation:props": { + "cidrIp": "0.0.0.0/0", + "description": "Open to the world", + "fromPort": { + "Fn::GetAtt": [ + "DatabaseB269D8BB", + "Port" + ] + }, + "groupId": { + "Fn::GetAtt": [ + "DatabaseSecurityGroup5C91FDCB", + "GroupId" + ] + }, + "ipProtocol": "tcp", + "toPort": { + "Fn::GetAtt": [ + "DatabaseB269D8BB", + "Port" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroupIngress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DocDB::DBCluster", + "aws:cdk:cloudformation:props": { + "dbClusterParameterGroupName": { + "Ref": "ParamsA8366201" + }, + "dbSubnetGroupName": { + "Ref": "DatabaseSubnets56F17B9A" + }, + "engineVersion": "3.6.0", + "kmsKeyId": { + "Fn::GetAtt": [ + "DbSecurity381C2C15", + "Arn" + ] + }, + "masterUsername": "docdb", + "masterUserPassword": "7959866cacc02c2d243ecfe177464fe6", + "storageEncrypted": true, + "vpcSecurityGroupIds": [ + { + "Fn::GetAtt": [ + "DatabaseSecurityGroup5C91FDCB", + "GroupId" + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.CfnDBCluster", + "version": "0.0.0" + } + }, + "Instance1": { + "id": "Instance1", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/Database/Instance1", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DocDB::DBInstance", + "aws:cdk:cloudformation:props": { + "dbClusterIdentifier": { + "Ref": "DatabaseB269D8BB" + }, + "dbInstanceClass": "db.r5.large", + "enablePerformanceInsights": true + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.CfnDBInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_docdb.DatabaseCluster", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-docdb-removal-policy-snapshot-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-docdb-removal-policy-snapshot-integ": { + "id": "aws-cdk-docdb-removal-policy-snapshot-integ", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-docdb-removal-policy-snapshot-integ/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts new file mode 100644 index 0000000000000..fe3a386bcb727 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts @@ -0,0 +1,58 @@ +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as cdk from 'aws-cdk-lib'; +import * as constructs from 'constructs'; +import { DatabaseCluster, ClusterParameterGroup } from 'aws-cdk-lib/aws-docdb'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +/* + * Stack verification steps: + * * aws docdb describe-db-cluster-snapshots --db-cluster-identifier + */ + +class TestStack extends cdk.Stack { + constructor(scope: constructs.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, 'VPC', { maxAzs: 2, restrictDefaultSecurityGroup: false }); + + const params = new ClusterParameterGroup(this, 'Params', { + family: 'docdb3.6', + description: 'A nice parameter group', + parameters: { + audit_logs: 'disabled', + tls: 'enabled', + ttl_monitor: 'enabled', + }, + }); + + const kmsKey = new kms.Key(this, 'DbSecurity', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + + const cluster = new DatabaseCluster(this, 'Database', { + engineVersion: '3.6.0', + masterUser: { + username: 'docdb', + password: cdk.SecretValue.unsafePlainText('7959866cacc02c2d243ecfe177464fe6'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE), + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + vpc, + parameterGroup: params, + kmsKey, + removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + enablePerformanceInsights: true, + }); + + cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); + } +} + +const app = new cdk.App(); + +const stack = new TestStack(app, 'aws-cdk-docdb-removal-policy-snapshot-stack'); + +new IntegTest(app, 'aws-cdk-docdb-removal-policy-snapshot-integ', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts index b54f9c79a1033..c2c9232492530 100644 --- a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts @@ -421,14 +421,18 @@ export class DatabaseCluster extends DatabaseClusterBase { vpc: this.vpc, }); // HACK: Use an escape-hatch to apply a consistent removal policy to the - // security group so we don't get errors when trying to delete the stack - (securityGroup.node.defaultChild as CfnResource).applyRemovalPolicy(props.removalPolicy, { + // security group so we don't get errors when trying to delete the stack. + // AWS::EC2::SecurityGroup does not support snapshot removal policy + // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html + const securityGroupRemovalPolicy = !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? + props.removalPolicy : RemovalPolicy.DESTROY; + (securityGroup.node.defaultChild as CfnResource).applyRemovalPolicy(securityGroupRemovalPolicy, { applyToUpdateReplacePolicy: true, }); } this.securityGroupId = securityGroup.securityGroupId; - // Create the CloudwatchLogsConfiguratoin + // Create the CloudwatchLogsConfiguration const enableCloudwatchLogsExports: string[] = []; if (props.exportAuditLogsToCloudWatch) { enableCloudwatchLogsExports.push('audit'); @@ -504,6 +508,11 @@ export class DatabaseCluster extends DatabaseClusterBase { throw new Error('At least one instance is required'); } + // AWS::DocDB::DBInstance does not support SNAPSHOT removal policy + // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html + const instanceRemovalPolicy = !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? + props.removalPolicy : RemovalPolicy.DESTROY; + for (let i = 0; i < instanceCount; i++) { const instanceIndex = i + 1; @@ -519,7 +528,7 @@ export class DatabaseCluster extends DatabaseClusterBase { enablePerformanceInsights: props.enablePerformanceInsights, }); - instance.applyRemovalPolicy(props.removalPolicy, { + instance.applyRemovalPolicy(instanceRemovalPolicy, { applyToUpdateReplacePolicy: true, }); diff --git a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts index 7b1ff72a62984..fa8a3434f88a3 100644 --- a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts @@ -956,6 +956,48 @@ describe('DatabaseCluster', () => { VpcSecurityGroupIds: Match.arrayWith([stack.resolve(securityGroup.securityGroupId)]), }); }); + + test('can create a cluster with snapshot removal policy', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + instances: 1, + masterUser: { + username: 'admin', + password: cdk.SecretValue.unsafePlainText('tooshort'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::DocDB::DBCluster', { + Properties: { + DBSubnetGroupName: { Ref: 'DatabaseSubnets56F17B9A' }, + MasterUsername: 'admin', + MasterUserPassword: 'tooshort', + VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], + }, + DeletionPolicy: 'Snapshot', + UpdateReplacePolicy: 'Snapshot', + }); + + // Associated instance gets delete policy + Template.fromStack(stack).hasResource('AWS::DocDB::DBInstance', { + DeletionPolicy: 'Delete', + UpdateReplacePolicy: 'Delete', + }); + + // Associated security group gets delete policy + Template.fromStack(stack).hasResource('AWS::EC2::SecurityGroup', { + DeletionPolicy: 'Delete', + UpdateReplacePolicy: 'Delete', + }); + }); }); function testStack() { diff --git a/packages/aws-cdk-lib/core/lib/cfn-resource.ts b/packages/aws-cdk-lib/core/lib/cfn-resource.ts index a4dfd3066aaf4..587baac478638 100644 --- a/packages/aws-cdk-lib/core/lib/cfn-resource.ts +++ b/packages/aws-cdk-lib/core/lib/cfn-resource.ts @@ -141,6 +141,7 @@ export class CfnResource extends CfnRefElement { case RemovalPolicy.SNAPSHOT: // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html const snapshottableResourceTypes = [ + 'AWS::DocDB::DBCluster', 'AWS::EC2::Volume', 'AWS::ElastiCache::CacheCluster', 'AWS::ElastiCache::ReplicationGroup', diff --git a/packages/aws-cdk-lib/core/test/cfn-resource.test.ts b/packages/aws-cdk-lib/core/test/cfn-resource.test.ts index 78230863d3f51..4a8c4ab8912b3 100644 --- a/packages/aws-cdk-lib/core/test/cfn-resource.test.ts +++ b/packages/aws-cdk-lib/core/test/cfn-resource.test.ts @@ -49,6 +49,7 @@ describe('cfn resource', () => { describe('snapshot removal policy', () => { const supportedResources = [ + 'AWS::DocDB::DBCluster', 'AWS::EC2::Volume', 'AWS::ElastiCache::CacheCluster', 'AWS::ElastiCache::ReplicationGroup', From 15ce2b5ae2a2f5761b15c83820f0bb1aa1ae68f5 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Thu, 25 Jan 2024 07:29:45 +0100 Subject: [PATCH 02/31] update README --- packages/aws-cdk-lib/aws-docdb/README.md | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/aws-cdk-lib/aws-docdb/README.md b/packages/aws-cdk-lib/aws-docdb/README.md index 4b34af779b25d..7552f1435da3c 100644 --- a/packages/aws-cdk-lib/aws-docdb/README.md +++ b/packages/aws-cdk-lib/aws-docdb/README.md @@ -171,3 +171,30 @@ const cluster = new docdb.DatabaseCluster(this, 'Database', { enablePerformanceInsights: true, // Enable Performance Insights in all instances under this cluster }); ``` + +## Removal Policy + +This resource supports the snapshot removal policy. +To specify it use the `removalPolicy` property: + +```ts +declare const vpc: ec2.Vpc; + +const cluster = new docdb.DatabaseCluster(this, 'Database', { + masterUser: { + username: 'myuser', + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.MEMORY5, ec2.InstanceSize.LARGE), + vpcSubnets: { + subnetType: ec2.SubnetType.PUBLIC, + }, + vpc, + removalPolicy: cdk.RemovalPolicy.SNAPSHOT, +}); +``` + +**Note**: A `RemovalPolicy.DESTROY` removal policy will be applied to the +cluster's instances and security group as they don't support the snapshot +removal policy. + +> Visit [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) for more details. From d57f095521824eb042685ec6472364c62129f2af Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Sat, 27 Jan 2024 18:58:10 +0100 Subject: [PATCH 03/31] fixed README --- packages/aws-cdk-lib/aws-docdb/README.md | 2 +- packages/aws-cdk-lib/rosetta/aws_docdb/default.ts-fixture | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/aws-docdb/README.md b/packages/aws-cdk-lib/aws-docdb/README.md index 7552f1435da3c..68eb4ee187527 100644 --- a/packages/aws-cdk-lib/aws-docdb/README.md +++ b/packages/aws-cdk-lib/aws-docdb/README.md @@ -189,7 +189,7 @@ const cluster = new docdb.DatabaseCluster(this, 'Database', { subnetType: ec2.SubnetType.PUBLIC, }, vpc, - removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + removalPolicy: RemovalPolicy.SNAPSHOT, }); ``` diff --git a/packages/aws-cdk-lib/rosetta/aws_docdb/default.ts-fixture b/packages/aws-cdk-lib/rosetta/aws_docdb/default.ts-fixture index c006c67447724..2a72d93cceaeb 100644 --- a/packages/aws-cdk-lib/rosetta/aws_docdb/default.ts-fixture +++ b/packages/aws-cdk-lib/rosetta/aws_docdb/default.ts-fixture @@ -1,5 +1,5 @@ // Fixture with packages imported, but nothing else -import { Stack } from 'aws-cdk-lib'; +import { RemovalPolicy, Stack } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as docdb from 'aws-cdk-lib/aws-docdb'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; From 5d19137293bd134ee7ba34d2551b5f342a3bb533 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Sat, 24 Feb 2024 18:07:13 +0100 Subject: [PATCH 04/31] add instanceRemovalPolicy and securityGroupRemovalPolicy properties --- ...emoval-policy-snapshot-stack.template.json | 4 +- .../integ.cluster-removal-policy-snapshot.ts | 1 + packages/aws-cdk-lib/aws-docdb/README.md | 42 ++++++++- packages/aws-cdk-lib/aws-docdb/lib/cluster.ts | 55 ++++++++++-- .../aws-docdb/test/cluster.test.ts | 90 +++++++++++++++++++ 5 files changed, 181 insertions(+), 11 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json index 00446c1b294c2..042cd76401b0d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json @@ -542,8 +542,8 @@ "VPCPublicSubnet2DefaultRouteB7481BBA", "VPCPublicSubnet2RouteTableAssociation5A808732" ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts index fe3a386bcb727..c4a5fea0f4abb 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts @@ -42,6 +42,7 @@ class TestStack extends cdk.Stack { parameterGroup: params, kmsKey, removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + instanceRemovalPolicy: cdk.RemovalPolicy.RETAIN, // Remember to cleanup after running this test enablePerformanceInsights: true, }); diff --git a/packages/aws-cdk-lib/aws-docdb/README.md b/packages/aws-cdk-lib/aws-docdb/README.md index 68eb4ee187527..abff67dd579d1 100644 --- a/packages/aws-cdk-lib/aws-docdb/README.md +++ b/packages/aws-cdk-lib/aws-docdb/README.md @@ -194,7 +194,47 @@ const cluster = new docdb.DatabaseCluster(this, 'Database', { ``` **Note**: A `RemovalPolicy.DESTROY` removal policy will be applied to the -cluster's instances and security group as they don't support the snapshot +cluster's instances and security group by default as they don't support the snapshot removal policy. > Visit [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) for more details. + +To specify a custom removal policy for the cluster's instances, use the +`instanceRemovalPolicy` property: + +```ts +declare const vpc: ec2.Vpc; + +const cluster = new docdb.DatabaseCluster(this, 'Database', { + masterUser: { + username: 'myuser', + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.MEMORY5, ec2.InstanceSize.LARGE), + vpcSubnets: { + subnetType: ec2.SubnetType.PUBLIC, + }, + vpc, + removalPolicy: RemovalPolicy.SNAPSHOT, + instanceRemovalPolicy: RemovalPolicy.RETAIN, +}); +``` + +To specify a custom removal policy for the cluster's security group, use the +`securityGroupRemovalPolicy` property: + +```ts +declare const vpc: ec2.Vpc; + +const cluster = new docdb.DatabaseCluster(this, 'Database', { + masterUser: { + username: 'myuser', + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.MEMORY5, ec2.InstanceSize.LARGE), + vpcSubnets: { + subnetType: ec2.SubnetType.PUBLIC, + }, + vpc, + removalPolicy: RemovalPolicy.SNAPSHOT, + securityGroupRemovalPolicy: RemovalPolicy.RETAIN, +}); +``` diff --git a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts index c2c9232492530..74cf7f0aec8e2 100644 --- a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts @@ -135,6 +135,11 @@ export interface DatabaseClusterProps { * removal policy also applies to the implicit security group created for the * cluster if one is not supplied as a parameter. * + * When set to `SNAPSHOT`, the removal policy for the instances and the security group + * will default to `DESTROY` as those resources do not support the policy. + * + * Use the `instanceRemovalPolicy` and `securityGroupRemovalPolicy` to change the behavior. + * * @default - Retain cluster. */ readonly removalPolicy?: RemovalPolicy; @@ -190,6 +195,28 @@ export interface DatabaseClusterProps { * @default - false */ readonly enablePerformanceInsights?: boolean; + + /** + * The removal policy to apply to the cluster's instances. + * + * Cannot be set to `SNAPSHOT`. + * + * @default - `RemovalPolicy.DESTROY` when `removalPolicy` is set to `SNAPSHOT`, `removalPolicy` otherwise. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html + */ + readonly instanceRemovalPolicy?: RemovalPolicy; + + /** + * The removal policy to apply to the cluster's security group. + * + * Cannot be set to `SNAPSHOT`. + * + * @default - `RemovalPolicy.DESTROY` when `removalPolicy` is set to `SNAPSHOT`, `removalPolicy` otherwise. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html + */ + readonly securityGroupRemovalPolicy?: RemovalPolicy; } /** @@ -422,10 +449,7 @@ export class DatabaseCluster extends DatabaseClusterBase { }); // HACK: Use an escape-hatch to apply a consistent removal policy to the // security group so we don't get errors when trying to delete the stack. - // AWS::EC2::SecurityGroup does not support snapshot removal policy - // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html - const securityGroupRemovalPolicy = !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? - props.removalPolicy : RemovalPolicy.DESTROY; + const securityGroupRemovalPolicy = this.getSecurityGroupRemovalPolicy(props); (securityGroup.node.defaultChild as CfnResource).applyRemovalPolicy(securityGroupRemovalPolicy, { applyToUpdateReplacePolicy: true, }); @@ -508,10 +532,7 @@ export class DatabaseCluster extends DatabaseClusterBase { throw new Error('At least one instance is required'); } - // AWS::DocDB::DBInstance does not support SNAPSHOT removal policy - // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html - const instanceRemovalPolicy = !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? - props.removalPolicy : RemovalPolicy.DESTROY; + const instanceRemovalPolicy = this.getInstanceRemovalPolicy(props); for (let i = 0; i < instanceCount; i++) { const instanceIndex = i + 1; @@ -561,6 +582,24 @@ export class DatabaseCluster extends DatabaseClusterBase { } } + private getInstanceRemovalPolicy(props: DatabaseClusterProps) { + if (props.instanceRemovalPolicy === RemovalPolicy.SNAPSHOT) { + throw new Error('AWS::DocDB::DBInstance does not support the SNAPSHOT removal policy'); + } + if (props.instanceRemovalPolicy) return props.instanceRemovalPolicy; + return !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? + props.removalPolicy : RemovalPolicy.DESTROY; + } + + private getSecurityGroupRemovalPolicy(props: DatabaseClusterProps) { + if (props.securityGroupRemovalPolicy === RemovalPolicy.SNAPSHOT) { + throw new Error('AWS::EC2::SecurityGroup does not support the SNAPSHOT removal policy'); + } + if (props.securityGroupRemovalPolicy) return props.securityGroupRemovalPolicy; + return !props.removalPolicy || props.removalPolicy !== RemovalPolicy.SNAPSHOT ? + props.removalPolicy : RemovalPolicy.DESTROY; + } + /** * Adds the single user rotation of the master password to this cluster. * diff --git a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts index fa8a3434f88a3..9e2aabd7a9edb 100644 --- a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts @@ -998,6 +998,96 @@ describe('DatabaseCluster', () => { UpdateReplacePolicy: 'Delete', }); }); + + test('can specify instances removal policy', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + instances: 1, + masterUser: { + username: 'admin', + password: cdk.SecretValue.unsafePlainText('tooshort'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + instanceRemovalPolicy: cdk.RemovalPolicy.DESTROY, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::DocDB::DBInstance', { + DeletionPolicy: 'Delete', + UpdateReplacePolicy: 'Delete', + }); + }); + + test('can specify security group removal policy', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + instances: 1, + masterUser: { + username: 'admin', + password: cdk.SecretValue.unsafePlainText('tooshort'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + securityGroupRemovalPolicy: cdk.RemovalPolicy.DESTROY, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::EC2::SecurityGroup', { + DeletionPolicy: 'Delete', + UpdateReplacePolicy: 'Delete', + }); + }); + + test('instances removal policy cannot be set to snapshot', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + // THEN + expect(() => { + new DatabaseCluster(stack, 'Database', { + instances: 1, + masterUser: { + username: 'admin', + password: cdk.SecretValue.unsafePlainText('tooshort'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + instanceRemovalPolicy: cdk.RemovalPolicy.SNAPSHOT, + }); + }).toThrow(/AWS::DocDB::DBInstance does not support the SNAPSHOT removal policy/); + }); + + test('security group removal policy cannot be set to snapshot', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + // THEN + expect(() => { + new DatabaseCluster(stack, 'Database', { + instances: 1, + masterUser: { + username: 'admin', + password: cdk.SecretValue.unsafePlainText('tooshort'), + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + securityGroupRemovalPolicy: cdk.RemovalPolicy.SNAPSHOT, + }); + }).toThrow(/AWS::EC2::SecurityGroup does not support the SNAPSHOT removal policy/); + }); }); function testStack() { From cfd93b904431cab9e075b534ba801c255cc271c6 Mon Sep 17 00:00:00 2001 From: Douglas Naphas Date: Tue, 27 Feb 2024 10:52:39 -0500 Subject: [PATCH 05/31] chore(cognito): fix grammar in UserPool IDP docstrings (#29255) Closes gh-29254. ### Issue # (if applicable) Closes #29254. ### Reason for this change This fixes minor grammar issues in docs. ### Description of changes I made no functional code changes, only changes to docs via comments. I made no design decisions. ### Description of how you validated changes Doc changes only. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-lib/aws-cognito/lib/user-pool-idps/amazon.ts | 6 +++--- .../aws-cdk-lib/aws-cognito/lib/user-pool-idps/apple.ts | 2 +- .../aws-cdk-lib/aws-cognito/lib/user-pool-idps/facebook.ts | 6 +++--- .../aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts | 4 ++-- packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts | 2 +- packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/saml.ts | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/amazon.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/amazon.ts index d0bb5e432e9a3..0d166985995bf 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/amazon.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/amazon.ts @@ -8,12 +8,12 @@ import { CfnUserPoolIdentityProvider } from '../cognito.generated'; */ export interface UserPoolIdentityProviderAmazonProps extends UserPoolIdentityProviderProps { /** - * The client id recognized by 'Login with Amazon' APIs. + * The client id recognized by Login with Amazon APIs. * @see https://developer.amazon.com/docs/login-with-amazon/security-profile.html#client-identifier */ readonly clientId: string; /** - * The client secret to be accompanied with clientId for 'Login with Amazon' APIs to authenticate the client. + * The client secret to be accompanied with clientId for Login with Amazon APIs to authenticate the client. * @see https://developer.amazon.com/docs/login-with-amazon/security-profile.html#client-identifier */ readonly clientSecret: string; @@ -26,7 +26,7 @@ export interface UserPoolIdentityProviderAmazonProps extends UserPoolIdentityPro } /** - * Represents a identity provider that integrates with 'Login with Amazon' + * Represents an identity provider that integrates with Login with Amazon * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderAmazon extends UserPoolIdentityProviderBase { diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/apple.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/apple.ts index d4514d8865d48..fff4981a39131 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/apple.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/apple.ts @@ -33,7 +33,7 @@ export interface UserPoolIdentityProviderAppleProps extends UserPoolIdentityProv } /** - * Represents a identity provider that integrates with 'Apple' + * Represents an identity provider that integrates with Apple * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderApple extends UserPoolIdentityProviderBase { diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/facebook.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/facebook.ts index c19f1aeabfa04..9acdd68039bfe 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/facebook.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/facebook.ts @@ -12,12 +12,12 @@ export interface UserPoolIdentityProviderFacebookProps extends UserPoolIdentityP */ readonly clientId: string; /** - * The client secret to be accompanied with clientUd for Facebook to authenticate the client. + * The client secret to be accompanied with clientId for Facebook to authenticate the client. * @see https://developers.facebook.com/docs/facebook-login/security#appsecret */ readonly clientSecret: string; /** - * The list of facebook permissions to obtain for getting access to the Facebook profile. + * The list of Facebook permissions to obtain for getting access to the Facebook profile. * @see https://developers.facebook.com/docs/facebook-login/permissions * @default [ public_profile ] */ @@ -30,7 +30,7 @@ export interface UserPoolIdentityProviderFacebookProps extends UserPoolIdentityP } /** - * Represents a identity provider that integrates with 'Facebook Login' + * Represents an identity provider that integrates with Facebook Login * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderFacebook extends UserPoolIdentityProviderBase { diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts index c99b3c49cd6de..fe750c5db1fee 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/google.ts @@ -27,7 +27,7 @@ export interface UserPoolIdentityProviderGoogleProps extends UserPoolIdentityPro */ readonly clientSecretValue?: SecretValue; /** - * The list of google permissions to obtain for getting access to the google profile + * The list of Google permissions to obtain for getting access to the Google profile * @see https://developers.google.com/identity/sign-in/web/sign-in * @default [ profile ] */ @@ -35,7 +35,7 @@ export interface UserPoolIdentityProviderGoogleProps extends UserPoolIdentityPro } /** - * Represents a identity provider that integrates with 'Google' + * Represents an identity provider that integrates with Google * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderGoogle extends UserPoolIdentityProviderBase { diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts index b4eabc967908e..c17b48a799bdc 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts @@ -98,7 +98,7 @@ export enum OidcAttributeRequestMethod { } /** - * Represents a identity provider that integrates with OpenID Connect + * Represents an identity provider that integrates with OpenID Connect * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderOidc extends UserPoolIdentityProviderBase { diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/saml.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/saml.ts index 518cb67b62961..a4d5bedd1051c 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/saml.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/saml.ts @@ -78,7 +78,7 @@ export class UserPoolIdentityProviderSamlMetadata { } /** - * Represents a identity provider that integrates with SAML. + * Represents an identity provider that integrates with SAML. * @resource AWS::Cognito::UserPoolIdentityProvider */ export class UserPoolIdentityProviderSaml extends UserPoolIdentityProviderBase { From ccb07d0c4a4a5f2e2b220558c9efe9702e200888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:01:58 +0000 Subject: [PATCH 06/31] chore(deps): bump es5-ext from 0.10.62 to 0.10.63 (#29281) Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.62 to 0.10.63.
Release notes

Sourced from es5-ext's releases.

0.10.63 (2024-02-23)

Bug Fixes

  • Do not rely on problematic regex (3551cdd), addresses #201
  • Support ES2015+ function definitions in function#toStringTokens() (a52e957), addresses #021
  • Ensure postinstall script does not crash on Windows, fixes #181 (bf8ed79)

Maintenance Improvements

  • Simplify the manifest message (7855319)

Comparison since last release

Changelog

Sourced from es5-ext's changelog.

0.10.63 (2024-02-23)

Bug Fixes

  • Do not rely on problematic regex (3551cdd), addresses #201
  • Support ES2015+ function definitions in function#toStringTokens() (a52e957), addresses #021
  • Ensure postinstall script does not crash on Windows, fixes #181 (bf8ed79)

Maintenance Improvements

  • Simplify the manifest message (7855319)
Commits
  • de4e03c chore: Release v0.10.63
  • 3fd53b7 chore: Upgrade lint-staged to v13
  • bf8ed79 chore: Ensure postinstall script does not crash on Windows
  • 2cbbb07 chore: Bump dependencies
  • 22d0416 chore: Bump LICENSE year
  • a52e957 fix: Support ES2015+ function definitions in function#toStringTokens()
  • 3551cdd fix: Do not rely on problematic regex
  • 7855319 chore: Simplify the manifest message
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=es5-ext&package-manager=npm_and_yarn&previous-version=0.10.62&new-version=0.10.63)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/aws/aws-cdk/network/alerts).
--- yarn.lock | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index d967a4b0e99e6..ac354b9dba1a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7726,13 +7726,14 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: - version "0.10.62" - resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" - integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@^0.10.62, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.63" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.63.tgz#9c222a63b6a332ac80b1e373b426af723b895bd6" + integrity sha512-hUCZd2Byj/mNKjfP9jXrdVZ62B8KuA/VoK7X8nUh5qT+AxDmcbvZz041oDVZdbIN1qW6XY9VDNwzkvKnZvK2TQ== dependencies: es6-iterator "^2.0.3" es6-symbol "^3.1.3" + esniff "^2.0.1" next-tick "^1.1.0" es6-error@^4.0.1: @@ -8024,6 +8025,16 @@ eslint@^8: strip-ansi "^6.0.1" text-table "^0.2.0" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + espree@^7.3.0, espree@^7.3.1: version "7.3.1" resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" From 1f30b5d873b7a1b11733211fa9ef47792fa4c678 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Tue, 27 Feb 2024 13:11:24 -0500 Subject: [PATCH 07/31] chore(eks): improve the doc on updating clusters (#29283) ### Issue # (if applicable) As described in https://github.com/aws/aws-cdk/issues/29282 , when renaming the cluster, an additional temporary IAM policy will be required. I am proposing the doc update to clarify this with this PR. Closes #29282 #24174 ### Reason for this change To address this use case. ### Description of changes ### Description of how you validated changes ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-eks/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/aws-cdk-lib/aws-eks/README.md b/packages/aws-cdk-lib/aws-eks/README.md index 081743a3d0d75..f5d2c00c9aca3 100644 --- a/packages/aws-cdk-lib/aws-eks/README.md +++ b/packages/aws-cdk-lib/aws-eks/README.md @@ -15,6 +15,7 @@ In addition, the library also supports defining Kubernetes resource manifests wi - [Node Groups with IPv6 Support](#node-groups-with-ipv6-support) - [Spot Instances Support](#spot-instances-support) - [Launch Template Support](#launch-template-support) + - [Update clusters](#update-clusters) - [Fargate profiles](#fargate-profiles) - [Self-managed nodes](#self-managed-nodes) - [Spot Instances](#spot-instances) @@ -366,6 +367,29 @@ You may specify one `instanceType` in the launch template or multiple `instanceT Graviton 2 instance types are supported including `c6g`, `m6g`, `r6g` and `t4g`. Graviton 3 instance types are supported including `c7g`. +### Update clusters + +When you rename the cluster name and redeploy the stack, the cluster replacement will be triggered and +the existing one will be deleted after the new one is provisioned. As the cluster resource ARN has been changed, +the cluster resource handler would not be able to delete the old one as the resource ARN in the IAM policy +has been changed. As a workaround, you need to add a temporary policy to the cluster admin role for +successful replacement. Consider this example if you are renaming the cluster from `foo` to `bar`: + +```ts +const cluster = new eks.Cluster(this, 'cluster-to-rename', { + clusterName: 'foo', // rename this to 'bar' + version: eks.KubernetesVersion.V1_29, +}); + +// allow the cluster admin role to delete the cluster 'foo' +cluster.adminRole.addToPolicy(new iam.PolicyStatement({ + actions: ['eks:DeleteCluster'], + resources: [ + Stack.of(this).formatArn({ service: 'eks', resource: 'cluster', resourceName: 'foo' }), +] +})) +``` + ### Fargate profiles AWS Fargate is a technology that provides on-demand, right-sized compute From 19d75d6c0ca7355be8a2375a60f3a228e4758e23 Mon Sep 17 00:00:00 2001 From: kazuho cryer-shinozuka Date: Thu, 29 Feb 2024 00:25:00 +0900 Subject: [PATCH 08/31] feat(apigatewayv2-integrations): stepfunctions integration (#28982) ### Issue Closes #28904. ### Reason for this change It is not possible to create an integration between Step Functions and HTTP API. ### Description of changes You can create integration by `HttpStepFunctionsIntegration` class: ```ts declare const httpApi: apigwv2.HttpApi; declare const stateMachine: sfn.StateMachine; const integration = new HttpStepFunctionIntegration('StepFunctionIntegration', { stateMachine, }) httpApi.addRoutes({ path: '/jobs', methods: [apigwv2.HttpMethod.POST], integration, }); ``` ### Description of how you validated changes Added unit tests and integ test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../integ.stepfunctions.js.snapshot/cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 239 +++++ .../stepfunctions-integration.assets.json | 19 + .../stepfunctions-integration.template.json | 486 +++++++++ ...efaultTestDeployAssert09AC4C77.assets.json | 19 + ...aultTestDeployAssert09AC4C77.template.json | 36 + .../integ.stepfunctions.js.snapshot/tree.json | 999 ++++++++++++++++++ .../test/http/integ.stepfunctions.ts | 56 + .../aws-apigatewayv2-integrations/README.md | 52 + .../lib/http/index.ts | 1 + .../lib/http/stepfunctions.ts | 110 ++ .../test/http/stepfunctions.test.ts | 228 ++++ 13 files changed, 2258 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.ts create mode 100644 packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/stepfunctions.ts create mode 100644 packages/aws-cdk-lib/aws-apigatewayv2-integrations/test/http/stepfunctions.test.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/integ.json new file mode 100644 index 0000000000000..e16d5a28f77c1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "stepfunctions-integration-integ-test/DefaultTest": { + "stacks": [ + "stepfunctions-integration" + ], + "assertionStack": "stepfunctions-integration-integ-test/DefaultTest/DeployAssert", + "assertionStackName": "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/manifest.json new file mode 100644 index 0000000000000..9169101ee2313 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/manifest.json @@ -0,0 +1,239 @@ +{ + "version": "36.0.0", + "artifacts": { + "stepfunctions-integration.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "stepfunctions-integration.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "stepfunctions-integration": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "stepfunctions-integration.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/19e42465a3a7d7c94541f96a140ab7bdb71eb54da666c1b3c1bc9f3a03c310a2.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "stepfunctions-integration.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "stepfunctions-integration.assets" + ], + "metadata": { + "/stepfunctions-integration/RouteStateMachine/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RouteStateMachineRoleF32EE107" + } + ], + "/stepfunctions-integration/RouteStateMachine/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RouteStateMachineC11CAF3B" + } + ], + "/stepfunctions-integration/ExpressStateMachine/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ExpressStateMachineRole4C3738D2" + } + ], + "/stepfunctions-integration/ExpressStateMachine/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ExpressStateMachineE90FFF22" + } + ], + "/stepfunctions-integration/Api/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiF70053CD" + } + ], + "/stepfunctions-integration/Api/DefaultStage/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiDefaultStage189A7074" + } + ], + "/stepfunctions-integration/Api/POST--default/InvokeRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTdefaultInvokeRole9137E4F5" + } + ], + "/stepfunctions-integration/Api/POST--default/InvokeRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTdefaultInvokeRoleDefaultPolicy603C0AF3" + } + ], + "/stepfunctions-integration/Api/POST--default/Integration/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTdefaultIntegration15333EAA" + } + ], + "/stepfunctions-integration/Api/POST--default/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTdefault1EEA0D1D" + } + ], + "/stepfunctions-integration/Api/POST--start/InvokeRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartInvokeRoleA9D6BD6A" + } + ], + "/stepfunctions-integration/Api/POST--start/InvokeRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartInvokeRoleDefaultPolicy495BCE0C" + } + ], + "/stepfunctions-integration/Api/POST--start/Integration/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartIntegration373B2B85" + } + ], + "/stepfunctions-integration/Api/POST--start/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartB39FD25E" + } + ], + "/stepfunctions-integration/Api/POST--start-sync/InvokeRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartsyncInvokeRoleC429A7AB" + } + ], + "/stepfunctions-integration/Api/POST--start-sync/InvokeRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartsyncInvokeRoleDefaultPolicy244CA8B0" + } + ], + "/stepfunctions-integration/Api/POST--start-sync/Integration/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartsyncIntegrationB86BBC38" + } + ], + "/stepfunctions-integration/Api/POST--start-sync/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstartsync3659F9A0" + } + ], + "/stepfunctions-integration/Api/POST--stop/InvokeRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstopInvokeRoleB9DFDAA9" + } + ], + "/stepfunctions-integration/Api/POST--stop/InvokeRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstopInvokeRoleDefaultPolicy4B17C921" + } + ], + "/stepfunctions-integration/Api/POST--stop/Integration/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstopIntegrationDA24B606" + } + ], + "/stepfunctions-integration/Api/POST--stop/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiPOSTstopBDBE4015" + } + ], + "/stepfunctions-integration/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/stepfunctions-integration/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "stepfunctions-integration" + }, + "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets" + ], + "metadata": { + "/stepfunctions-integration-integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/stepfunctions-integration-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "stepfunctions-integration-integ-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.assets.json new file mode 100644 index 0000000000000..b778a7d47b763 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "19e42465a3a7d7c94541f96a140ab7bdb71eb54da666c1b3c1bc9f3a03c310a2": { + "source": { + "path": "stepfunctions-integration.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "19e42465a3a7d7c94541f96a140ab7bdb71eb54da666c1b3c1bc9f3a03c310a2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.template.json new file mode 100644 index 0000000000000..9e1cc70fa86b0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctions-integration.template.json @@ -0,0 +1,486 @@ +{ + "Resources": { + "RouteStateMachineRoleF32EE107": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "RouteStateMachineC11CAF3B": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "DefinitionString": "{\"StartAt\":\"Pass1\",\"States\":{\"Pass1\":{\"Type\":\"Pass\",\"End\":true}}}", + "RoleArn": { + "Fn::GetAtt": [ + "RouteStateMachineRoleF32EE107", + "Arn" + ] + } + }, + "DependsOn": [ + "RouteStateMachineRoleF32EE107" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ExpressStateMachineRole4C3738D2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ExpressStateMachineE90FFF22": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "DefinitionString": "{\"StartAt\":\"Pass2\",\"States\":{\"Pass2\":{\"Type\":\"Pass\",\"End\":true}}}", + "RoleArn": { + "Fn::GetAtt": [ + "ExpressStateMachineRole4C3738D2", + "Arn" + ] + }, + "StateMachineType": "EXPRESS" + }, + "DependsOn": [ + "ExpressStateMachineRole4C3738D2" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ApiF70053CD": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Name": "Api", + "ProtocolType": "HTTP" + } + }, + "ApiDefaultStage189A7074": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "AutoDeploy": true, + "StageName": "$default" + } + }, + "ApiPOSTdefaultInvokeRole9137E4F5": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ApiPOSTdefaultInvokeRoleDefaultPolicy603C0AF3": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "RouteStateMachineC11CAF3B" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ApiPOSTdefaultInvokeRoleDefaultPolicy603C0AF3", + "Roles": [ + { + "Ref": "ApiPOSTdefaultInvokeRole9137E4F5" + } + ] + } + }, + "ApiPOSTdefaultIntegration15333EAA": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "ConnectionType": "INTERNET", + "CredentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTdefaultInvokeRole9137E4F5", + "Arn" + ] + }, + "IntegrationSubtype": "StepFunctions-StartExecution", + "IntegrationType": "AWS_PROXY", + "PayloadFormatVersion": "1.0", + "RequestParameters": { + "StateMachineArn": { + "Ref": "RouteStateMachineC11CAF3B" + } + } + } + }, + "ApiPOSTdefault1EEA0D1D": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "AuthorizationType": "NONE", + "RouteKey": "POST /default", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTdefaultIntegration15333EAA" + } + ] + ] + } + } + }, + "ApiPOSTstartInvokeRoleA9D6BD6A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ApiPOSTstartInvokeRoleDefaultPolicy495BCE0C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "RouteStateMachineC11CAF3B" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ApiPOSTstartInvokeRoleDefaultPolicy495BCE0C", + "Roles": [ + { + "Ref": "ApiPOSTstartInvokeRoleA9D6BD6A" + } + ] + } + }, + "ApiPOSTstartIntegration373B2B85": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "ConnectionType": "INTERNET", + "CredentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstartInvokeRoleA9D6BD6A", + "Arn" + ] + }, + "IntegrationSubtype": "StepFunctions-StartExecution", + "IntegrationType": "AWS_PROXY", + "PayloadFormatVersion": "1.0", + "RequestParameters": { + "StateMachineArn": { + "Ref": "RouteStateMachineC11CAF3B" + } + } + } + }, + "ApiPOSTstartB39FD25E": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "AuthorizationType": "NONE", + "RouteKey": "POST /start", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstartIntegration373B2B85" + } + ] + ] + } + } + }, + "ApiPOSTstartsyncInvokeRoleC429A7AB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ApiPOSTstartsyncInvokeRoleDefaultPolicy244CA8B0": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StartSyncExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ExpressStateMachineE90FFF22" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ApiPOSTstartsyncInvokeRoleDefaultPolicy244CA8B0", + "Roles": [ + { + "Ref": "ApiPOSTstartsyncInvokeRoleC429A7AB" + } + ] + } + }, + "ApiPOSTstartsyncIntegrationB86BBC38": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "ConnectionType": "INTERNET", + "CredentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstartsyncInvokeRoleC429A7AB", + "Arn" + ] + }, + "IntegrationSubtype": "StepFunctions-StartSyncExecution", + "IntegrationType": "AWS_PROXY", + "PayloadFormatVersion": "1.0", + "RequestParameters": { + "StateMachineArn": { + "Ref": "ExpressStateMachineE90FFF22" + } + } + } + }, + "ApiPOSTstartsync3659F9A0": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "AuthorizationType": "NONE", + "RouteKey": "POST /start-sync", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstartsyncIntegrationB86BBC38" + } + ] + ] + } + } + }, + "ApiPOSTstopInvokeRoleB9DFDAA9": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ApiPOSTstopInvokeRoleDefaultPolicy4B17C921": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "states:StopExecution", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":states:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":execution:", + { + "Fn::GetAtt": [ + "RouteStateMachineC11CAF3B", + "Name" + ] + }, + ":*" + ] + ] + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ApiPOSTstopInvokeRoleDefaultPolicy4B17C921", + "Roles": [ + { + "Ref": "ApiPOSTstopInvokeRoleB9DFDAA9" + } + ] + } + }, + "ApiPOSTstopIntegrationDA24B606": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "ConnectionType": "INTERNET", + "CredentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstopInvokeRoleB9DFDAA9", + "Arn" + ] + }, + "IntegrationSubtype": "StepFunctions-StopExecution", + "IntegrationType": "AWS_PROXY", + "PayloadFormatVersion": "1.0", + "RequestParameters": { + "ExecutionArn": "$request.querystring.executionArn" + } + } + }, + "ApiPOSTstopBDBE4015": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "ApiF70053CD" + }, + "AuthorizationType": "NONE", + "RouteKey": "POST /stop", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstopIntegrationDA24B606" + } + ] + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets.json new file mode 100644 index 0000000000000..002ef777e5465 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/stepfunctionsintegrationintegtestDefaultTestDeployAssert09AC4C77.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/tree.json new file mode 100644 index 0000000000000..c8ede561fccac --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.js.snapshot/tree.json @@ -0,0 +1,999 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "stepfunctions-integration": { + "id": "stepfunctions-integration", + "path": "stepfunctions-integration", + "children": { + "Pass1": { + "id": "Pass1", + "path": "stepfunctions-integration/Pass1", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.Pass", + "version": "0.0.0" + } + }, + "RouteStateMachine": { + "id": "RouteStateMachine", + "path": "stepfunctions-integration/RouteStateMachine", + "children": { + "Role": { + "id": "Role", + "path": "stepfunctions-integration/RouteStateMachine/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "stepfunctions-integration/RouteStateMachine/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/RouteStateMachine/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/RouteStateMachine/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", + "aws:cdk:cloudformation:props": { + "definitionString": "{\"StartAt\":\"Pass1\",\"States\":{\"Pass1\":{\"Type\":\"Pass\",\"End\":true}}}", + "roleArn": { + "Fn::GetAtt": [ + "RouteStateMachineRoleF32EE107", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.CfnStateMachine", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.StateMachine", + "version": "0.0.0" + } + }, + "Pass2": { + "id": "Pass2", + "path": "stepfunctions-integration/Pass2", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.Pass", + "version": "0.0.0" + } + }, + "ExpressStateMachine": { + "id": "ExpressStateMachine", + "path": "stepfunctions-integration/ExpressStateMachine", + "children": { + "Role": { + "id": "Role", + "path": "stepfunctions-integration/ExpressStateMachine/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "stepfunctions-integration/ExpressStateMachine/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/ExpressStateMachine/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/ExpressStateMachine/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", + "aws:cdk:cloudformation:props": { + "definitionString": "{\"StartAt\":\"Pass2\",\"States\":{\"Pass2\":{\"Type\":\"Pass\",\"End\":true}}}", + "roleArn": { + "Fn::GetAtt": [ + "ExpressStateMachineRole4C3738D2", + "Arn" + ] + }, + "stateMachineType": "EXPRESS" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.CfnStateMachine", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.StateMachine", + "version": "0.0.0" + } + }, + "Api": { + "id": "Api", + "path": "stepfunctions-integration/Api", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Api", + "aws:cdk:cloudformation:props": { + "name": "Api", + "protocolType": "HTTP" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnApi", + "version": "0.0.0" + } + }, + "DefaultStage": { + "id": "DefaultStage", + "path": "stepfunctions-integration/Api/DefaultStage", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/DefaultStage/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Stage", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "autoDeploy": true, + "stageName": "$default" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnStage", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpStage", + "version": "0.0.0" + } + }, + "POST--default": { + "id": "POST--default", + "path": "stepfunctions-integration/Api/POST--default", + "children": { + "InvokeRole": { + "id": "InvokeRole", + "path": "stepfunctions-integration/Api/POST--default/InvokeRole", + "children": { + "ImportInvokeRole": { + "id": "ImportInvokeRole", + "path": "stepfunctions-integration/Api/POST--default/InvokeRole/ImportInvokeRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--default/InvokeRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stepfunctions-integration/Api/POST--default/InvokeRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--default/InvokeRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "RouteStateMachineC11CAF3B" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ApiPOSTdefaultInvokeRoleDefaultPolicy603C0AF3", + "roles": [ + { + "Ref": "ApiPOSTdefaultInvokeRole9137E4F5" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Integration": { + "id": "Integration", + "path": "stepfunctions-integration/Api/POST--default/Integration", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--default/Integration/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Integration", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "connectionType": "INTERNET", + "credentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTdefaultInvokeRole9137E4F5", + "Arn" + ] + }, + "integrationSubtype": "StepFunctions-StartExecution", + "integrationType": "AWS_PROXY", + "payloadFormatVersion": "1.0", + "requestParameters": { + "StateMachineArn": { + "Ref": "RouteStateMachineC11CAF3B" + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnIntegration", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpIntegration", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--default/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Route", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "authorizationType": "NONE", + "routeKey": "POST /default", + "target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTdefaultIntegration15333EAA" + } + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpRoute", + "version": "0.0.0" + } + }, + "POST--start": { + "id": "POST--start", + "path": "stepfunctions-integration/Api/POST--start", + "children": { + "InvokeRole": { + "id": "InvokeRole", + "path": "stepfunctions-integration/Api/POST--start/InvokeRole", + "children": { + "ImportInvokeRole": { + "id": "ImportInvokeRole", + "path": "stepfunctions-integration/Api/POST--start/InvokeRole/ImportInvokeRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start/InvokeRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stepfunctions-integration/Api/POST--start/InvokeRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start/InvokeRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "RouteStateMachineC11CAF3B" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ApiPOSTstartInvokeRoleDefaultPolicy495BCE0C", + "roles": [ + { + "Ref": "ApiPOSTstartInvokeRoleA9D6BD6A" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Integration": { + "id": "Integration", + "path": "stepfunctions-integration/Api/POST--start/Integration", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start/Integration/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Integration", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "connectionType": "INTERNET", + "credentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstartInvokeRoleA9D6BD6A", + "Arn" + ] + }, + "integrationSubtype": "StepFunctions-StartExecution", + "integrationType": "AWS_PROXY", + "payloadFormatVersion": "1.0", + "requestParameters": { + "StateMachineArn": { + "Ref": "RouteStateMachineC11CAF3B" + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnIntegration", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpIntegration", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Route", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "authorizationType": "NONE", + "routeKey": "POST /start", + "target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstartIntegration373B2B85" + } + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpRoute", + "version": "0.0.0" + } + }, + "POST--start-sync": { + "id": "POST--start-sync", + "path": "stepfunctions-integration/Api/POST--start-sync", + "children": { + "InvokeRole": { + "id": "InvokeRole", + "path": "stepfunctions-integration/Api/POST--start-sync/InvokeRole", + "children": { + "ImportInvokeRole": { + "id": "ImportInvokeRole", + "path": "stepfunctions-integration/Api/POST--start-sync/InvokeRole/ImportInvokeRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start-sync/InvokeRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stepfunctions-integration/Api/POST--start-sync/InvokeRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start-sync/InvokeRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "states:StartSyncExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ExpressStateMachineE90FFF22" + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ApiPOSTstartsyncInvokeRoleDefaultPolicy244CA8B0", + "roles": [ + { + "Ref": "ApiPOSTstartsyncInvokeRoleC429A7AB" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Integration": { + "id": "Integration", + "path": "stepfunctions-integration/Api/POST--start-sync/Integration", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start-sync/Integration/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Integration", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "connectionType": "INTERNET", + "credentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstartsyncInvokeRoleC429A7AB", + "Arn" + ] + }, + "integrationSubtype": "StepFunctions-StartSyncExecution", + "integrationType": "AWS_PROXY", + "payloadFormatVersion": "1.0", + "requestParameters": { + "StateMachineArn": { + "Ref": "ExpressStateMachineE90FFF22" + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnIntegration", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpIntegration", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--start-sync/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Route", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "authorizationType": "NONE", + "routeKey": "POST /start-sync", + "target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstartsyncIntegrationB86BBC38" + } + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpRoute", + "version": "0.0.0" + } + }, + "POST--stop": { + "id": "POST--stop", + "path": "stepfunctions-integration/Api/POST--stop", + "children": { + "InvokeRole": { + "id": "InvokeRole", + "path": "stepfunctions-integration/Api/POST--stop/InvokeRole", + "children": { + "ImportInvokeRole": { + "id": "ImportInvokeRole", + "path": "stepfunctions-integration/Api/POST--stop/InvokeRole/ImportInvokeRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--stop/InvokeRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "apigateway.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stepfunctions-integration/Api/POST--stop/InvokeRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--stop/InvokeRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "states:StopExecution", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":states:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":execution:", + { + "Fn::GetAtt": [ + "RouteStateMachineC11CAF3B", + "Name" + ] + }, + ":*" + ] + ] + }, + "Sid": "AllowStepFunctionsExecution" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ApiPOSTstopInvokeRoleDefaultPolicy4B17C921", + "roles": [ + { + "Ref": "ApiPOSTstopInvokeRoleB9DFDAA9" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Integration": { + "id": "Integration", + "path": "stepfunctions-integration/Api/POST--stop/Integration", + "children": { + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--stop/Integration/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Integration", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "connectionType": "INTERNET", + "credentialsArn": { + "Fn::GetAtt": [ + "ApiPOSTstopInvokeRoleB9DFDAA9", + "Arn" + ] + }, + "integrationSubtype": "StepFunctions-StopExecution", + "integrationType": "AWS_PROXY", + "payloadFormatVersion": "1.0", + "requestParameters": { + "ExecutionArn": "$request.querystring.executionArn" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnIntegration", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpIntegration", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stepfunctions-integration/Api/POST--stop/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGatewayV2::Route", + "aws:cdk:cloudformation:props": { + "apiId": { + "Ref": "ApiF70053CD" + }, + "authorizationType": "NONE", + "routeKey": "POST /stop", + "target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "ApiPOSTstopIntegrationDA24B606" + } + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_apigatewayv2.HttpApi", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "stepfunctions-integration/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "stepfunctions-integration/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "stepfunctions-integration-integ-test": { + "id": "stepfunctions-integration-integ-test", + "path": "stepfunctions-integration-integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "stepfunctions-integration-integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "stepfunctions-integration-integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "stepfunctions-integration-integ-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "stepfunctions-integration-integ-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "stepfunctions-integration-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.ts new file mode 100644 index 0000000000000..b2a816a21639b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-integrations/test/http/integ.stepfunctions.ts @@ -0,0 +1,56 @@ +import { HttpApi, HttpIntegrationSubtype, HttpMethod, ParameterMapping } from 'aws-cdk-lib/aws-apigatewayv2'; +import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; +import { App, Stack } from 'aws-cdk-lib'; +import { HttpStepFunctionsIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; +import * as integ from '@aws-cdk/integ-tests-alpha'; + +const app = new App(); +const stack = new Stack(app, 'stepfunctions-integration'); + +const stateMachine = new sfn.StateMachine(stack, 'RouteStateMachine', { + definition: new sfn.Pass(stack, 'Pass1'), +}); +const expressStateMachine = new sfn.StateMachine(stack, 'ExpressStateMachine', { + definition: new sfn.Pass(stack, 'Pass2'), + stateMachineType: sfn.StateMachineType.EXPRESS, +}); + +const httpApi = new HttpApi(stack, 'Api'); +httpApi.addRoutes({ + path: '/default', + methods: [HttpMethod.POST], + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + }), +}); +httpApi.addRoutes({ + path: '/start', + methods: [HttpMethod.POST], + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + subtype: HttpIntegrationSubtype.STEPFUNCTIONS_START_EXECUTION, + }), +}); +httpApi.addRoutes({ + path: '/start-sync', + methods: [HttpMethod.POST], + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine: expressStateMachine, + subtype: HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION, + }), +}); +httpApi.addRoutes({ + path: '/stop', + methods: [HttpMethod.POST], + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + subtype: HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION, + parameterMapping: new ParameterMapping() + .custom('ExecutionArn', '$request.querystring.executionArn'), + }), +}); + +new integ.IntegTest(app, 'stepfunctions-integration-integ-test', { + testCases: [stack], +}); +app.synth(); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md index ba8d08d880d55..82a9ea2cd6341 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md @@ -65,6 +65,58 @@ httpApi.addRoutes({ }); ``` +### StepFunctions Integration + +Step Functions integrations enable integrating an HTTP API route with AWS Step Functions. +This allows the HTTP API to start state machine executions synchronously or asynchronously, or to stop executions. + +When a client invokes the route configured with a Step Functions integration, the API Gateway service interacts with the specified state machine according to the integration subtype (e.g., starts a new execution, synchronously starts an execution, or stops an execution) and returns the response to the client. + +The following code configures a Step Functions integrations: + +```ts +import { HttpStepFunctionsIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; +import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; + +declare const stateMachine: sfn.StateMachine; +declare const httpApi: apigwv2.HttpApi; + +httpApi.addRoutes({ + path: '/start', + methods: [ apigwv2.HttpMethod.POST ], + integration: new HttpStepFunctionsIntegration('StartExecutionIntegration', { + stateMachine, + subtype: apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_START_EXECUTION, + }), +}); + +httpApi.addRoutes({ + path: '/start-sync', + methods: [ apigwv2.HttpMethod.POST ], + integration: new HttpStepFunctionsIntegration('StartSyncExecutionIntegration', { + stateMachine, + subtype: apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION, + }), +}); + +httpApi.addRoutes({ + path: '/stop', + methods: [ apigwv2.HttpMethod.POST ], + integration: new HttpStepFunctionsIntegration('StopExecutionIntegration', { + stateMachine, + subtype: apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION, + // For the `STOP_EXECUTION` subtype, it is necessary to specify the `executionArn`. + parameterMapping: new apigwv2.ParameterMapping() + .custom('ExecutionArn', '$request.querystring.executionArn'), + }), +}); +``` + +**Note**: + +- The `executionArn` parameter is required for the `STOP_EXECUTION` subtype. It is necessary to specify the `executionArn` in the `parameterMapping` property of the `HttpStepFunctionsIntegration` object. +- `START_SYNC_EXECUTION` subtype is only supported for EXPRESS type state machine. + ### Private Integration Private integrations enable integrating an HTTP API route with private resources in a VPC, such as Application Load Balancers or diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/index.ts b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/index.ts index 8e0598975f8cb..8162b443fc122 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/index.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/index.ts @@ -4,3 +4,4 @@ export * from './nlb'; export * from './service-discovery'; export * from './http-proxy'; export * from './lambda'; +export * from './stepfunctions'; \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/stepfunctions.ts b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/stepfunctions.ts new file mode 100644 index 0000000000000..4229bda171232 --- /dev/null +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/lib/http/stepfunctions.ts @@ -0,0 +1,110 @@ +import * as apigwv2 from '../../../aws-apigatewayv2'; +import * as iam from '../../../aws-iam'; +import * as sfn from '../../../aws-stepfunctions'; + +/** + * Properties to initialize `HttpStepFunctionsIntegration`. + */ +export interface HttpStepFunctionsIntegrationProps { + /** + * Specifies how to transform HTTP requests before sending them to the backend. + * + * When the subtype is either `START_EXECUTION` or `START_SYNC_EXECUTION`, + * it is necessary to specify the `StateMachineArn`. + * Conversely, when the subtype is `STOP_EXECUTION`, the `ExecutionArn` must be specified. + * + * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-parameter-mapping.html + * + * @default - specify only `StateMachineArn` + */ + readonly parameterMapping?: apigwv2.ParameterMapping; + + /** + * The subtype of the HTTP integration. + * + * Only subtypes starting with STEPFUNCTIONS_ can be specified. + * + * @default HttpIntegrationSubtype.STEPFUNCTIONS_START_EXECUTION + */ + readonly subtype?: apigwv2.HttpIntegrationSubtype; + + /** + * Statemachine that Integrates with API Gateway + */ + readonly stateMachine: sfn.StateMachine; +} + +/** + * The StepFunctions integration resource for HTTP API + */ +export class HttpStepFunctionsIntegration extends apigwv2.HttpRouteIntegration { + /** + * @param id id of the underlying integration construct + * @param props properties to configure the integration + */ + constructor( + id: string, + private readonly props: HttpStepFunctionsIntegrationProps, + ) { + super(id); + } + + public bind(options: apigwv2.HttpRouteIntegrationBindOptions): apigwv2.HttpRouteIntegrationConfig { + if (this.props.subtype && !this.props.subtype.startsWith('StepFunctions-')) { + throw new Error('Subtype must start with `STEPFUNCTIONS_`'); + } + if ( + this.props.subtype === apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION + && this.props.stateMachine.stateMachineType === sfn.StateMachineType.STANDARD + ) { + throw new Error('Cannot use subtype `STEPFUNCTIONS_START_SYNC_EXECUTION` with a standard type state machine'); + } + + const invokeRole = new iam.Role(options.scope, 'InvokeRole', { + assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'), + }); + + invokeRole.addToPolicy( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + sid: 'AllowStepFunctionsExecution', + actions: [this.determineActionBySubtype(this.props.subtype)], + resources: [this.determineResourceArn(options)], + }), + ); + + return { + payloadFormatVersion: apigwv2.PayloadFormatVersion.VERSION_1_0, + type: apigwv2.HttpIntegrationType.AWS_PROXY, + subtype: this.props.subtype ?? apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_START_EXECUTION, + credentials: apigwv2.IntegrationCredentials.fromRole(invokeRole), + connectionType: apigwv2.HttpConnectionType.INTERNET, + parameterMapping: this.props.parameterMapping ?? new apigwv2.ParameterMapping() + .custom('StateMachineArn', this.props.stateMachine.stateMachineArn), + }; + } + + private determineActionBySubtype(subtype?: apigwv2.HttpIntegrationSubtype): string { + switch (subtype) { + case apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION: + return 'states:StopExecution'; + case apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION: + return 'states:StartSyncExecution'; + default: + return 'states:StartExecution'; + } + } + + private determineResourceArn(options: apigwv2.HttpRouteIntegrationBindOptions): string { + switch (this.props.subtype) { + case apigwv2.HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION: + return options.route.stack.formatArn({ + service: 'states', + resource: `execution:${this.props.stateMachine.stateMachineName}:*`, + }); + // Both START_EXECUTION and START_SYNC_EXECUTION return the state machine arn + default: + return this.props.stateMachine.stateMachineArn; + } + } +} diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/test/http/stepfunctions.test.ts b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/test/http/stepfunctions.test.ts new file mode 100644 index 0000000000000..1ce6359a26398 --- /dev/null +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/test/http/stepfunctions.test.ts @@ -0,0 +1,228 @@ +import { Match, Template } from '../../../assertions'; +import { HttpApi, HttpIntegrationSubtype, HttpRoute, HttpRouteKey, ParameterMapping } from '../../../aws-apigatewayv2'; +import * as sfn from '../../../aws-stepfunctions'; +import { App, Stack } from '../../../core'; +import { HttpStepFunctionsIntegration } from '../../lib/http/stepfunctions'; + +describe('StepFunctionsIntegration', () => { + test('default', () => { + const app = new App(); + const stack = new Stack(app, 'stack'); + const api = new HttpApi(stack, 'HttpApi'); + const targetStateMachine = new sfn.StateMachine(stack, 'StateMachine', { + definition: new sfn.Pass(stack, 'Pass'), + }); + + new HttpRoute(stack, 'StepFunctionsRoute', { + httpApi: api, + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine: targetStateMachine, + }), + routeKey: HttpRouteKey.with('/tests'), + }); + + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: Match.arrayWith([ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'apigateway.amazonaws.com', + }, + }, + ]), + }, + }); + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'states:StartExecution', + Effect: 'Allow', + Resource: stack.resolve(targetStateMachine.stateMachineArn), + }, + ], + }, + Roles: [ + { + Ref: 'StepFunctionsRouteInvokeRole5E3B5519', + }, + ], + }); + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { + ConnectionType: 'INTERNET', + CredentialsArn: { + 'Fn::GetAtt': [ + 'StepFunctionsRouteInvokeRole5E3B5519', + 'Arn', + ], + }, + IntegrationType: 'AWS_PROXY', + IntegrationSubtype: 'StepFunctions-StartExecution', + PayloadFormatVersion: '1.0', + RequestParameters: { + StateMachineArn: stack.resolve(targetStateMachine.stateMachineArn), + }, + }); + }); + + test('with parameterMapping', () => { + const app = new App(); + const stack = new Stack(app, 'stack'); + const api = new HttpApi(stack, 'HttpApi'); + const targetStateMachine = new sfn.StateMachine(stack, 'StateMachine', { + definition: new sfn.Pass(stack, 'Pass'), + }); + + new HttpRoute(stack, 'StepFunctionsRoute', { + httpApi: api, + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine: targetStateMachine, + parameterMapping: new ParameterMapping() + .custom('Input', '$request.body') + .custom('StateMachineArn', targetStateMachine.stateMachineArn), + }), + routeKey: HttpRouteKey.with('/tests'), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { + ConnectionType: 'INTERNET', + CredentialsArn: { + 'Fn::GetAtt': [ + 'StepFunctionsRouteInvokeRole5E3B5519', + 'Arn', + ], + }, + IntegrationType: 'AWS_PROXY', + IntegrationSubtype: 'StepFunctions-StartExecution', + PayloadFormatVersion: '1.0', + RequestParameters: { + Input: '$request.body', + StateMachineArn: stack.resolve(targetStateMachine.stateMachineArn), + }, + }); + }); + + test.each([ + [HttpIntegrationSubtype.STEPFUNCTIONS_START_EXECUTION, 'states:StartExecution', undefined], + [HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION, 'states:StartSyncExecution', undefined], + [ + HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION, + 'states:StopExecution', + new ParameterMapping().custom('ExecutionArn', '$request.querystring.executionArn'), + ], + ])('with subtype %s', (subtype, action, parameterMapping) => { + const app = new App(); + const stack = new Stack(app, 'stack'); + const api = new HttpApi(stack, 'HttpApi'); + const stateMachine = new sfn.StateMachine(stack, 'StateMachine', { + definition: new sfn.Pass(stack, 'Pass'), + stateMachineType: sfn.StateMachineType.EXPRESS, + }); + + new HttpRoute(stack, 'StepFunctionsRoute', { + httpApi: api, + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + subtype, + parameterMapping, + }), + routeKey: HttpRouteKey.with('/tests'), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: action, + Effect: 'Allow', + Resource: subtype === HttpIntegrationSubtype.STEPFUNCTIONS_STOP_EXECUTION ? { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':states:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':execution:', + { 'Fn::GetAtt': [stack.resolve(stateMachine.stateMachineArn).Ref, 'Name'] }, + ':*', + ], + ], + } : stack.resolve(stateMachine.stateMachineArn), + }, + ], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { + ConnectionType: 'INTERNET', + CredentialsArn: { + 'Fn::GetAtt': [ + 'StepFunctionsRouteInvokeRole5E3B5519', + 'Arn', + ], + }, + IntegrationType: 'AWS_PROXY', + IntegrationSubtype: subtype, + PayloadFormatVersion: '1.0', + RequestParameters: { + ...(parameterMapping ? + parameterMapping.mappings : + { StateMachineArn: stack.resolve(stateMachine.stateMachineArn) } + ), + }, + }); + }); + + test('throw error when subtype does not start with STEPFUNCTIONS_', () => { + const app = new App(); + const stack = new Stack(app, 'stack'); + const api = new HttpApi(stack, 'HttpApi'); + const stateMachine = new sfn.StateMachine(stack, 'StateMachine', { + definition: new sfn.Pass(stack, 'Pass'), + }); + + expect(() => { + new HttpRoute(stack, 'StepFunctionsRoute', { + httpApi: api, + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + subtype: HttpIntegrationSubtype.SQS_DELETE_MESSAGE, + }), + routeKey: HttpRouteKey.with('/tests'), + }); + }).toThrow(/Subtype must start with `STEPFUNCTIONS_`/); + }); + + test('throw error when subtype is STEPFUNCTIONS_START_SYNC_EXECUTION with standard state machine', () => { + const app = new App(); + const stack = new Stack(app, 'stack'); + const api = new HttpApi(stack, 'HttpApi'); + const stateMachine = new sfn.StateMachine(stack, 'StateMachine', { + definition: new sfn.Pass(stack, 'Pass'), + stateMachineType: sfn.StateMachineType.STANDARD, + }); + + expect(() => { + new HttpRoute(stack, 'StepFunctionsRoute', { + httpApi: api, + integration: new HttpStepFunctionsIntegration('Integration', { + stateMachine, + subtype: HttpIntegrationSubtype.STEPFUNCTIONS_START_SYNC_EXECUTION, + }), + routeKey: HttpRouteKey.with('/tests'), + }); + }).toThrow(/Cannot use subtype `STEPFUNCTIONS_START_SYNC_EXECUTION` with a standard type state machine/); + }); +}); + From 7e8239b2b85d0becb3c7fdcf5a2f4afbaf84f8b4 Mon Sep 17 00:00:00 2001 From: kazuho cryer-shinozuka Date: Thu, 29 Feb 2024 01:02:01 +0900 Subject: [PATCH 09/31] feat(appsync): add the `grant` method to the imported `GraphqlApi` (#29086) ### Issue Closes #23031. ### Reason for this change The `grantXx` methods are implemented in the `GraphqlApi` class, but it could not be used with an imported graphql api. ### Description of changes Moved the implementation of the `grantXx` method from the `GraphqlApi` class to the `GraphqlApiBase` class." ### Description of how you validated changes I've added both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssertE072C285.assets.json | 19 + ...aultTestDeployAssertE072C285.template.json | 36 + .../aws-appsync-integ.assets.json | 19 + .../aws-appsync-integ.template.json | 116 +++ .../cdk.out | 1 + .../imported-stack.assets.json | 19 + .../imported-stack.template.json | 282 +++++++ .../integ.json | 12 + .../manifest.json | 228 ++++++ .../tree.json | 688 ++++++++++++++++++ .../test/integ.graphql-grant-imported-api.ts | 91 +++ packages/aws-cdk-lib/aws-appsync/README.md | 4 +- .../aws-appsync/lib/graphqlapi-base.ts | 151 +++- .../aws-cdk-lib/aws-appsync/lib/graphqlapi.ts | 113 +-- .../aws-appsync/test/appsync-grant.test.ts | 586 +++++++++++++++ 15 files changed, 2251 insertions(+), 114 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets.json new file mode 100644 index 0000000000000..132fc9ca01136 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.assets.json new file mode 100644 index 0000000000000..c4ce0ba3b127b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "eaa071d73fbf78d2b0887200d22f7bab11fc3b13290fd6d6d13fde6b1036c165": { + "source": { + "path": "aws-appsync-integ.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "eaa071d73fbf78d2b0887200d22f7bab11fc3b13290fd6d6d13fde6b1036c165.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.template.json new file mode 100644 index 0000000000000..ba09319e244a3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/aws-appsync-integ.template.json @@ -0,0 +1,116 @@ +{ + "Resources": { + "PoolD3F588B8": { + "Type": "AWS::Cognito::UserPool", + "Properties": { + "AccountRecoverySetting": { + "RecoveryMechanisms": [ + { + "Name": "verified_phone_number", + "Priority": 1 + }, + { + "Name": "verified_email", + "Priority": 2 + } + ] + }, + "AdminCreateUserConfig": { + "AllowAdminCreateUserOnly": true + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "UserPoolName": "myPool", + "VerificationMessageTemplate": { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ApiF70053CD": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AdditionalAuthenticationProviders": [ + { + "AuthenticationType": "AWS_IAM" + } + ], + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "Name": "Integ_Test_IAM", + "UserPoolConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "DefaultAction": "ALLOW", + "UserPoolId": { + "Ref": "PoolD3F588B8" + } + } + } + }, + "ApiSchema510EECD7": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "ApiF70053CD", + "ApiId" + ] + }, + "Definition": "type test @aws_iam {\n id: String!\n version: String!\n}\n\ntype Query {\n getTest(id: String!): test\n getTests: [ test! ]\n @aws_iam \n}\n\ninput TestInput {\n version: String!\n}\n\ntype Mutation {\n addTest(input: TestInput!): test\n @aws_iam\n}\n" + } + } + }, + "Outputs": { + "ExportsOutputFnGetAttApiF70053CDApiIdF185726B": { + "Value": { + "Fn::GetAtt": [ + "ApiF70053CD", + "ApiId" + ] + }, + "Export": { + "Name": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.assets.json new file mode 100644 index 0000000000000..5dc8598e31d89 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "33fc02df19070d9366b8e00d2471256ee84cacf09985e1a83461f75872733e2e": { + "source": { + "path": "imported-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "33fc02df19070d9366b8e00d2471256ee84cacf09985e1a83461f75872733e2e.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.template.json new file mode 100644 index 0000000000000..103c197099d13 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/imported-stack.template.json @@ -0,0 +1,282 @@ +{ + "Resources": { + "lambdaRoleC844FDB1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "lambdaRoleDefaultPolicyA63A8A92": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Query/fields/getPost" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "lambdaRoleDefaultPolicyA63A8A92", + "Roles": [ + { + "Ref": "lambdaRoleC844FDB1" + } + ] + } + }, + "mutatioLambdaRole7F96C419": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "mutatioLambdaRoleDefaultPolicyCB07404D": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Mutation/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "mutatioLambdaRoleDefaultPolicyCB07404D", + "Roles": [ + { + "Ref": "mutatioLambdaRole7F96C419" + } + ] + } + }, + "queryLambdaRole5A00034A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "queryLambdaRoleDefaultPolicyC3CBAE04": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Query/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "queryLambdaRoleDefaultPolicyC3CBAE04", + "Roles": [ + { + "Ref": "queryLambdaRole5A00034A" + } + ] + } + }, + "subscriptionLambdaRoleB3A245CA": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "subscriptionLambdaRoleDefaultPolicy11B257BC": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Subscription/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "subscriptionLambdaRoleDefaultPolicy11B257BC", + "Roles": [ + { + "Ref": "subscriptionLambdaRoleB3A245CA" + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/integ.json new file mode 100644 index 0000000000000..c958b67489e04 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "GraphqlGrantImportedApiInteg/DefaultTest": { + "stacks": [ + "imported-stack" + ], + "assertionStack": "GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert", + "assertionStackName": "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/manifest.json new file mode 100644 index 0000000000000..05fcf1f21e63a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/manifest.json @@ -0,0 +1,228 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-appsync-integ.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-appsync-integ.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-appsync-integ": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-appsync-integ.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/eaa071d73fbf78d2b0887200d22f7bab11fc3b13290fd6d6d13fde6b1036c165.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-appsync-integ.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-appsync-integ.assets" + ], + "metadata": { + "/aws-appsync-integ/Pool/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PoolD3F588B8" + } + ], + "/aws-appsync-integ/Api/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiF70053CD" + } + ], + "/aws-appsync-integ/Api/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiSchema510EECD7" + } + ], + "/aws-appsync-integ/Exports/Output{\"Fn::GetAtt\":[\"ApiF70053CD\",\"ApiId\"]}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + } + ], + "/aws-appsync-integ/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-appsync-integ/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-appsync-integ" + }, + "imported-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "imported-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "imported-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "imported-stack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/33fc02df19070d9366b8e00d2471256ee84cacf09985e1a83461f75872733e2e.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "imported-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-appsync-integ", + "imported-stack.assets" + ], + "metadata": { + "/imported-stack/lambdaRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "lambdaRoleC844FDB1" + } + ], + "/imported-stack/lambdaRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "lambdaRoleDefaultPolicyA63A8A92" + } + ], + "/imported-stack/mutatioLambdaRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "mutatioLambdaRole7F96C419" + } + ], + "/imported-stack/mutatioLambdaRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "mutatioLambdaRoleDefaultPolicyCB07404D" + } + ], + "/imported-stack/queryLambdaRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "queryLambdaRole5A00034A" + } + ], + "/imported-stack/queryLambdaRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "queryLambdaRoleDefaultPolicyC3CBAE04" + } + ], + "/imported-stack/subscriptionLambdaRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "subscriptionLambdaRoleB3A245CA" + } + ], + "/imported-stack/subscriptionLambdaRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "subscriptionLambdaRoleDefaultPolicy11B257BC" + } + ], + "/imported-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/imported-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "imported-stack" + }, + "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "GraphqlGrantImportedApiIntegDefaultTestDeployAssertE072C285.assets" + ], + "metadata": { + "/GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/tree.json new file mode 100644 index 0000000000000..fc4f63f478dc1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.js.snapshot/tree.json @@ -0,0 +1,688 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-appsync-integ": { + "id": "aws-appsync-integ", + "path": "aws-appsync-integ", + "children": { + "Pool": { + "id": "Pool", + "path": "aws-appsync-integ/Pool", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-appsync-integ/Pool/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Cognito::UserPool", + "aws:cdk:cloudformation:props": { + "accountRecoverySetting": { + "recoveryMechanisms": [ + { + "name": "verified_phone_number", + "priority": 1 + }, + { + "name": "verified_email", + "priority": 2 + } + ] + }, + "adminCreateUserConfig": { + "allowAdminCreateUserOnly": true + }, + "emailVerificationMessage": "The verification code to your new account is {####}", + "emailVerificationSubject": "Verify your new account", + "smsVerificationMessage": "The verification code to your new account is {####}", + "userPoolName": "myPool", + "verificationMessageTemplate": { + "defaultEmailOption": "CONFIRM_WITH_CODE", + "emailMessage": "The verification code to your new account is {####}", + "emailSubject": "Verify your new account", + "smsMessage": "The verification code to your new account is {####}" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cognito.CfnUserPool", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cognito.UserPool", + "version": "0.0.0" + } + }, + "Api": { + "id": "Api", + "path": "aws-appsync-integ/Api", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-appsync-integ/Api/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "additionalAuthenticationProviders": [ + { + "authenticationType": "AWS_IAM" + } + ], + "authenticationType": "AMAZON_COGNITO_USER_POOLS", + "name": "Integ_Test_IAM", + "userPoolConfig": { + "userPoolId": { + "Ref": "PoolD3F588B8" + }, + "awsRegion": { + "Ref": "AWS::Region" + }, + "defaultAction": "ALLOW" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "aws-appsync-integ/Api/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "ApiF70053CD", + "ApiId" + ] + }, + "definition": "type test @aws_iam {\n id: String!\n version: String!\n}\n\ntype Query {\n getTest(id: String!): test\n getTests: [ test! ]\n @aws_iam \n}\n\ninput TestInput {\n version: String!\n}\n\ntype Mutation {\n addTest(input: TestInput!): test\n @aws_iam\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "aws-appsync-integ/Api/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "ImportedApi": { + "id": "ImportedApi", + "path": "aws-appsync-integ/ImportedApi", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApiBase", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "aws-appsync-integ/Exports", + "children": { + "Output{\"Fn::GetAtt\":[\"ApiF70053CD\",\"ApiId\"]}": { + "id": "Output{\"Fn::GetAtt\":[\"ApiF70053CD\",\"ApiId\"]}", + "path": "aws-appsync-integ/Exports/Output{\"Fn::GetAtt\":[\"ApiF70053CD\",\"ApiId\"]}", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-appsync-integ/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-appsync-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "imported-stack": { + "id": "imported-stack", + "path": "imported-stack", + "children": { + "lambdaRole": { + "id": "lambdaRole", + "path": "imported-stack/lambdaRole", + "children": { + "ImportlambdaRole": { + "id": "ImportlambdaRole", + "path": "imported-stack/lambdaRole/ImportlambdaRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "imported-stack/lambdaRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "imported-stack/lambdaRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "imported-stack/lambdaRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Query/fields/getPost" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "lambdaRoleDefaultPolicyA63A8A92", + "roles": [ + { + "Ref": "lambdaRoleC844FDB1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "mutatioLambdaRole": { + "id": "mutatioLambdaRole", + "path": "imported-stack/mutatioLambdaRole", + "children": { + "ImportmutatioLambdaRole": { + "id": "ImportmutatioLambdaRole", + "path": "imported-stack/mutatioLambdaRole/ImportmutatioLambdaRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "imported-stack/mutatioLambdaRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "imported-stack/mutatioLambdaRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "imported-stack/mutatioLambdaRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Mutation/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "mutatioLambdaRoleDefaultPolicyCB07404D", + "roles": [ + { + "Ref": "mutatioLambdaRole7F96C419" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "queryLambdaRole": { + "id": "queryLambdaRole", + "path": "imported-stack/queryLambdaRole", + "children": { + "ImportqueryLambdaRole": { + "id": "ImportqueryLambdaRole", + "path": "imported-stack/queryLambdaRole/ImportqueryLambdaRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "imported-stack/queryLambdaRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "imported-stack/queryLambdaRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "imported-stack/queryLambdaRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Query/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "queryLambdaRoleDefaultPolicyC3CBAE04", + "roles": [ + { + "Ref": "queryLambdaRole5A00034A" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "subscriptionLambdaRole": { + "id": "subscriptionLambdaRole", + "path": "imported-stack/subscriptionLambdaRole", + "children": { + "ImportsubscriptionLambdaRole": { + "id": "ImportsubscriptionLambdaRole", + "path": "imported-stack/subscriptionLambdaRole/ImportsubscriptionLambdaRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "imported-stack/subscriptionLambdaRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "imported-stack/subscriptionLambdaRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "imported-stack/subscriptionLambdaRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":appsync:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":apis/", + { + "Fn::ImportValue": "aws-appsync-integ:ExportsOutputFnGetAttApiF70053CDApiIdF185726B" + }, + "/types/Subscription/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "subscriptionLambdaRoleDefaultPolicy11B257BC", + "roles": [ + { + "Ref": "subscriptionLambdaRoleB3A245CA" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "imported-stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "imported-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "GraphqlGrantImportedApiInteg": { + "id": "GraphqlGrantImportedApiInteg", + "path": "GraphqlGrantImportedApiInteg", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "GraphqlGrantImportedApiInteg/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "GraphqlGrantImportedApiInteg/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "GraphqlGrantImportedApiInteg/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.ts new file mode 100644 index 0000000000000..fab8a1ce93027 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.graphql-grant-imported-api.ts @@ -0,0 +1,91 @@ +import { join } from 'path'; +import { UserPool } from 'aws-cdk-lib/aws-cognito'; +import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { + AuthorizationType, + GraphqlApi, + UserPoolDefaultAction, + SchemaFile, + IamResource, +} from 'aws-cdk-lib/aws-appsync'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { ServicePrincipal, Role } from 'aws-cdk-lib/aws-iam'; + +class OriginalStack extends Stack { + + public readonly apiId: string; + + constructor(scope: App, id: string) { + super(scope, id); + + const userPool = new UserPool(this, 'Pool', { + userPoolName: 'myPool', + removalPolicy: RemovalPolicy.DESTROY, + }); + + const api = new GraphqlApi(this, 'Api', { + name: 'Integ_Test_IAM', + schema: SchemaFile.fromAsset(join(__dirname, 'integ.graphql-iam.graphql')), + authorizationConfig: { + defaultAuthorization: { + authorizationType: AuthorizationType.USER_POOL, + userPoolConfig: { + userPool, + defaultAction: UserPoolDefaultAction.ALLOW, + }, + }, + additionalAuthorizationModes: [ + { + authorizationType: AuthorizationType.IAM, + }, + ], + }, + }); + + this.apiId = api.apiId; + } +} + +interface ImportedStackProps extends StackProps { + apiId: string; +} + +class ImportedStack extends Stack { + constructor(scope: App, id: string, props: ImportedStackProps) { + super(scope, id); + + const importedApi = GraphqlApi.fromGraphqlApiAttributes(originalStack, 'ImportedApi', { + graphqlApiId: `${props.apiId}`, + }); + + const lambdaRole = new Role(this, 'lambdaRole', { + assumedBy: new ServicePrincipal('lambda.amazonaws.com'), + }); + importedApi.grant(lambdaRole, IamResource.custom('types/Query/fields/getPost'), 'appsync:GraphQL'); + + const mutationLambdaRole = new Role(this, 'mutatioLambdaRole', { + assumedBy: new ServicePrincipal('lambda.amazonaws.com'), + }); + importedApi.grantMutation(mutationLambdaRole); + + const queryLambdaRole = new Role(this, 'queryLambdaRole', { + assumedBy: new ServicePrincipal('lambda.amazonaws.com'), + }); + importedApi.grantQuery(queryLambdaRole); + + const subscriptionLambdaRole = new Role(this, 'subscriptionLambdaRole', { + assumedBy: new ServicePrincipal('lambda.amazonaws.com'), + }); + importedApi.grantSubscription(subscriptionLambdaRole); + } +} + +const app = new App(); +const originalStack = new OriginalStack(app, 'aws-appsync-integ'); +const importedStack = new ImportedStack(app, 'imported-stack', { + apiId: originalStack.apiId, +}); + +new IntegTest(app, 'GraphqlGrantImportedApiInteg', { + testCases: [importedStack], +}); diff --git a/packages/aws-cdk-lib/aws-appsync/README.md b/packages/aws-cdk-lib/aws-appsync/README.md index d24828f11ff80..119b139ff0721 100644 --- a/packages/aws-cdk-lib/aws-appsync/README.md +++ b/packages/aws-cdk-lib/aws-appsync/README.md @@ -632,7 +632,7 @@ Use the `grant` function for more granular authorization. const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -declare const api: appsync.GraphqlApi; +declare const api: appsync.IGraphqlApi; api.grant(role, appsync.IamResource.custom('types/Mutation/fields/updateExample'), 'appsync:GraphQL'); ``` @@ -658,7 +658,7 @@ These include: - grantSubscription (use to grant access to Subscription fields) ```ts -declare const api: appsync.GraphqlApi; +declare const api: appsync.IGraphqlApi; declare const role: iam.Role; // For generic types diff --git a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi-base.ts b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi-base.ts index f4acb601aa7bd..a75657f80a1a8 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi-base.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi-base.ts @@ -13,11 +13,12 @@ import { Resolver, ExtendedResolverProps } from './resolver'; import { ITable } from '../../aws-dynamodb'; import { IDomain as IElasticsearchDomain } from '../../aws-elasticsearch'; import { IEventBus } from '../../aws-events'; +import { Grant, IGrantable } from '../../aws-iam'; import { IFunction } from '../../aws-lambda'; import { IDomain as IOpenSearchDomain } from '../../aws-opensearchservice'; import { IServerlessCluster } from '../../aws-rds'; import { ISecret } from '../../aws-secretsmanager'; -import { CfnResource, IResource, Resource } from '../../core'; +import { ArnFormat, CfnResource, IResource, Resource, Stack } from '../../core'; /** * Optional configuration for data sources @@ -50,6 +51,67 @@ export interface HttpDataSourceOptions extends DataSourceOptions { readonly authorizationConfig?: AwsIamConfig; } +/** + * A class used to generate resource arns for AppSync + */ +export class IamResource { + /** + * Generate the resource names given custom arns + * + * @param arns The custom arns that need to be permissioned + * + * Example: custom('/types/Query/fields/getExample') + */ + public static custom(...arns: string[]): IamResource { + if (arns.length === 0) { + throw new Error('At least 1 custom ARN must be provided.'); + } + return new IamResource(arns); + } + + /** + * Generate the resource names given a type and fields + * + * @param type The type that needs to be allowed + * @param fields The fields that need to be allowed, if empty grant permissions to ALL fields + * + * Example: ofType('Query', 'GetExample') + */ + public static ofType(type: string, ...fields: string[]): IamResource { + const arns = fields.length ? fields.map((field) => `types/${type}/fields/${field}`) : [`types/${type}/*`]; + return new IamResource(arns); + } + + /** + * Generate the resource names that accepts all types: `*` + */ + public static all(): IamResource { + return new IamResource(['*']); + } + + private arns: string[]; + + private constructor(arns: string[]) { + this.arns = arns; + } + + /** + * Return the Resource ARN + * + * @param api The GraphQL API to give permissions + */ + public resourceArns(api: GraphqlApiBase): string[] { + return this.arns.map((arn) => + Stack.of(api).formatArn({ + service: 'appsync', + resource: `apis/${api.apiId}`, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + resourceName: `${arn}`, + }), + ); + } +} + /** * Interface for GraphQL */ @@ -161,6 +223,43 @@ export interface IGraphqlApi extends IResource { * @param construct the dependee */ addSchemaDependency(construct: CfnResource): boolean; + + /** + * Adds an IAM policy statement associated with this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param resources The set of resources to allow (i.e. ...:[region]:[accountId]:apis/GraphQLId/...) + * @param actions The actions that should be granted to the principal (i.e. appsync:graphql ) + */ + grant(grantee: IGrantable, resources: IamResource, ...actions: string[]): Grant; + + /** + * Adds an IAM policy statement for Mutation access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Mutations (leave blank for all) + */ + grantMutation(grantee: IGrantable, ...fields: string[]): Grant; + + /** + * Adds an IAM policy statement for Query access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Queries (leave blank for all) + */ + grantQuery(grantee: IGrantable, ...fields: string[]): Grant; + + /** + * Adds an IAM policy statement for Subscription access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Subscriptions (leave blank for all) + */ + grantSubscription(grantee: IGrantable, ...fields: string[]): Grant; } /** @@ -335,4 +434,54 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi { construct; return false; } + + /** + * Adds an IAM policy statement associated with this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param resources The set of resources to allow (i.e. ...:[region]:[accountId]:apis/GraphQLId/...) + * @param actions The actions that should be granted to the principal (i.e. appsync:graphql ) + */ + public grant(grantee: IGrantable, resources: IamResource, ...actions: string[]): Grant { + return Grant.addToPrincipal({ + grantee, + actions, + resourceArns: resources.resourceArns(this), + scope: this, + }); + } + + /** + * Adds an IAM policy statement for Mutation access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Mutations (leave blank for all) + */ + public grantMutation(grantee: IGrantable, ...fields: string[]): Grant { + return this.grant(grantee, IamResource.ofType('Mutation', ...fields), 'appsync:GraphQL'); + } + + /** + * Adds an IAM policy statement for Query access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Queries (leave blank for all) + */ + public grantQuery(grantee: IGrantable, ...fields: string[]): Grant { + return this.grant(grantee, IamResource.ofType('Query', ...fields), 'appsync:GraphQL'); + } + + /** + * Adds an IAM policy statement for Subscription access to this GraphQLApi to an IAM + * principal's policy. + * + * @param grantee The principal + * @param fields The fields to grant access to that are Subscriptions (leave blank for all) + */ + public grantSubscription(grantee: IGrantable, ...fields: string[]): Grant { + return this.grant(grantee, IamResource.ofType('Subscription', ...fields), 'appsync:GraphQL'); + } } diff --git a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts index 04b6ed99b793d..75420814843b7 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts @@ -5,10 +5,10 @@ import { ISchema, SchemaFile } from './schema'; import { MergeType, addSourceApiAutoMergePermission, addSourceGraphQLPermission } from './source-api-association'; import { ICertificate } from '../../aws-certificatemanager'; import { IUserPool } from '../../aws-cognito'; -import { ManagedPolicy, Role, IRole, ServicePrincipal, Grant, IGrantable } from '../../aws-iam'; +import { ManagedPolicy, Role, IRole, ServicePrincipal } from '../../aws-iam'; import { IFunction } from '../../aws-lambda'; import { ILogGroup, LogGroup, LogRetention, RetentionDays } from '../../aws-logs'; -import { ArnFormat, CfnResource, Duration, Expiration, FeatureFlags, IResolvable, Lazy, Stack, Token } from '../../core'; +import { CfnResource, Duration, Expiration, FeatureFlags, IResolvable, Lazy, Stack, Token } from '../../core'; import * as cxapi from '../../cx-api'; /** @@ -458,65 +458,6 @@ export interface GraphqlApiProps { readonly environmentVariables?: { [key: string]: string }; } -/** - * A class used to generate resource arns for AppSync - */ -export class IamResource { - /** - * Generate the resource names given custom arns - * - * @param arns The custom arns that need to be permissioned - * - * Example: custom('/types/Query/fields/getExample') - */ - public static custom(...arns: string[]): IamResource { - if (arns.length === 0) { - throw new Error('At least 1 custom ARN must be provided.'); - } - return new IamResource(arns); - } - - /** - * Generate the resource names given a type and fields - * - * @param type The type that needs to be allowed - * @param fields The fields that need to be allowed, if empty grant permissions to ALL fields - * - * Example: ofType('Query', 'GetExample') - */ - public static ofType(type: string, ...fields: string[]): IamResource { - const arns = fields.length ? fields.map((field) => `types/${type}/fields/${field}`) : [`types/${type}/*`]; - return new IamResource(arns); - } - - /** - * Generate the resource names that accepts all types: `*` - */ - public static all(): IamResource { - return new IamResource(['*']); - } - - private arns: string[]; - - private constructor(arns: string[]) { - this.arns = arns; - } - - /** - * Return the Resource ARN - * - * @param api The GraphQL API to give permissions - */ - public resourceArns(api: GraphqlApi): string[] { - return this.arns.map((arn) => Stack.of(api).formatArn({ - service: 'appsync', - resource: `apis/${api.apiId}`, - arnFormat: ArnFormat.SLASH_RESOURCE_NAME, - resourceName: `${arn}`, - })); - } -} - /** * Attributes for GraphQL imports */ @@ -785,56 +726,6 @@ export class GraphqlApi extends GraphqlApiBase { } } - /** - * Adds an IAM policy statement associated with this GraphQLApi to an IAM - * principal's policy. - * - * @param grantee The principal - * @param resources The set of resources to allow (i.e. ...:[region]:[accountId]:apis/GraphQLId/...) - * @param actions The actions that should be granted to the principal (i.e. appsync:graphql ) - */ - public grant(grantee: IGrantable, resources: IamResource, ...actions: string[]): Grant { - return Grant.addToPrincipal({ - grantee, - actions, - resourceArns: resources.resourceArns(this), - scope: this, - }); - } - - /** - * Adds an IAM policy statement for Mutation access to this GraphQLApi to an IAM - * principal's policy. - * - * @param grantee The principal - * @param fields The fields to grant access to that are Mutations (leave blank for all) - */ - public grantMutation(grantee: IGrantable, ...fields: string[]): Grant { - return this.grant(grantee, IamResource.ofType('Mutation', ...fields), 'appsync:GraphQL'); - } - - /** - * Adds an IAM policy statement for Query access to this GraphQLApi to an IAM - * principal's policy. - * - * @param grantee The principal - * @param fields The fields to grant access to that are Queries (leave blank for all) - */ - public grantQuery(grantee: IGrantable, ...fields: string[]): Grant { - return this.grant(grantee, IamResource.ofType('Query', ...fields), 'appsync:GraphQL'); - } - - /** - * Adds an IAM policy statement for Subscription access to this GraphQLApi to an IAM - * principal's policy. - * - * @param grantee The principal - * @param fields The fields to grant access to that are Subscriptions (leave blank for all) - */ - public grantSubscription(grantee: IGrantable, ...fields: string[]): Grant { - return this.grant(grantee, IamResource.ofType('Subscription', ...fields), 'appsync:GraphQL'); - } - private validateAuthorizationProps(modes: AuthorizationMode[]) { if (modes.filter((mode) => mode.authorizationType === AuthorizationType.LAMBDA).length > 1) { throw new Error('You can only have a single AWS Lambda function configured to authorize your API.'); diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-grant.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-grant.test.ts index e6ad4a1741238..0c89126a34a90 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/appsync-grant.test.ts +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-grant.test.ts @@ -578,4 +578,590 @@ describe('grantSubscription Permissions', () => { }, }); }); +}); + +describe('imported API', () => { + let importedApi: appsync.IGraphqlApi; + beforeEach(() => { + importedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(stack, 'imported', { + graphqlApiId: 'importedId', + }); + }); + + describe('grant Permissions', () => { + test('IamResource throws error when custom is called with no arguments', () => { + //THEN + expect(() => { + importedApi.grant(role, appsync.IamResource.custom(), 'appsync:GraphQL'); + }).toThrow('At least 1 custom ARN must be provided.'); + }); + + test('grant provides custom permissions when called with `custom` argument', () => { + // WHEN + importedApi.grant( + role, + appsync.IamResource.custom('types/Mutation/fields/addTest'), + 'appsync:GraphQL', + ); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/fields/addTest', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grant provides [type parameter]/* permissions when called with `type` argument', () => { + // WHEN + importedApi.grant(role, appsync.IamResource.ofType('Mutation'), 'appsync:GraphQL'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/*', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grant provides fields/[field param] permissions when called with `type` and `field` argument', () => { + // WHEN + importedApi.grant(role, appsync.IamResource.ofType('Mutation', 'addTest'), 'appsync:GraphQL'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/fields/addTest', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grant provides all permissions when called with IamResource.all()', () => { + // WHEN + importedApi.grant(role, appsync.IamResource.all(), 'appsync:GraphQL'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/*', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grant provides multiple permissions using one IamResource custom call', () => { + // WHEN + importedApi.grant(role, appsync.IamResource.custom('I', 'am', 'custom'), 'appsync:GraphQL'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/I', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/am', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/custom', + ], + ], + }, + ], + }, + ], + }, + }); + }); + + test('grant provides multiple permissions using one IamResource ofType call', () => { + // WHEN + importedApi.grant(role, appsync.IamResource.ofType('I', 'am', 'custom'), 'appsync:GraphQL'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/I/fields/am', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/I/fields/custom', + ], + ], + }, + ], + }, + ], + }, + }); + }); + }); + + describe('grantMutation Permissions', () => { + test('grantMutation provides Mutation/* permissions when called with no `fields` argument', () => { + // WHEN + importedApi.grantMutation(role); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/*', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantMutation provides fields/[field param] permissions when called with `fields` argument', () => { + // WHEN + importedApi.grantMutation(role, 'addTest'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/fields/addTest', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantMutation provides multiple permissions when called with `fields` argument', () => { + // WHEN + importedApi.grantMutation(role, 'addTest', 'removeTest'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/fields/addTest', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Mutation/fields/removeTest', + ], + ], + }, + ], + }, + ], + }, + }); + }); + }); + + describe('grantQuery Permissions', () => { + test('grantQuery provides Query/* permissions when called without the `fields` argument', () => { + // WHEN + importedApi.grantQuery(role); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Query/*', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantQuery provides fields/[field param] permissions when called with `fields` arugment', () => { + // WHEN + importedApi.grantQuery(role, 'getTest'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Query/fields/getTest', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantQuery provides multiple permissions when called with `fields` argument', () => { + // WHEN + importedApi.grantQuery(role, 'getTests', 'getTest'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Query/fields/getTests', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Query/fields/getTest', + ], + ], + }, + ], + }, + ], + }, + }); + }); + }); + + describe('grantSubscription Permissions', () => { + test('grantSubscription provides Subscription/* permissions when called without `fields` argument', () => { + // WHEN + importedApi.grantSubscription(role); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Subscription/*', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantSubscription provides fields/[field param] when called with `field` argument', () => { + importedApi.grantSubscription(role, 'subscribe'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Subscription/fields/subscribe', + ], + ], + }, + }, + ], + }, + }); + }); + + test('grantSubscription provides multiple permissions when called with `fields` argument', () => { + // WHEN + importedApi.grantSubscription(role, 'subscribe', 'custom'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:GraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Subscription/fields/subscribe', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':appsync:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':apis/importedId/types/Subscription/fields/custom', + ], + ], + }, + ], + }, + ], + }, + }); + }); + }); }); \ No newline at end of file From a7de7feb6a14658ec25f4cfda434d5e1d69157d2 Mon Sep 17 00:00:00 2001 From: "k.goto" <24818752+go-to-k@users.noreply.github.com> Date: Thu, 29 Feb 2024 01:32:59 +0900 Subject: [PATCH 10/31] fix(autoscaling): step scaling without adjustment type fails (#29158) ### Reason for this change Step Scaling without `adjustmentType` fails with CFn error `You must specify an AdjustmentType for policy type: StepScaling`. - Reproduction code ```ts const asg = new autoscaling.AutoScalingGroup(stack, 'ASG', { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), }); asg.scaleOnMetric('StepScaling', { metric: new cloudwatch.Metric({ namespace: 'AWS/EC2', metricName: 'CPUUtilization', dimensionsMap: { AutoScalingGroupName: asg.autoScalingGroupName } }), scalingSteps: [ { upper: 10, change: -1 }, { lower: 50, change: +1 }, { lower: 90, change: +2 }, ], evaluationPeriods: 10, datapointsToAlarm: 5, metricAggregationType: autoscaling.MetricAggregationType.MAXIMUM, // adjustmentType: autoscaling.AdjustmentType.CHANGE_IN_CAPACITY, }); ``` ### Description of changes According to [the CDK code](https://github.com/aws/aws-cdk/blob/v2.122.0/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts#L105-L115), `CHANGE_IN_CAPACITY` will be used if `adjustmentType` is not specified in the prop. But the variable is not passed into `StepScalingAction` construct (instead `props.adjustmentType` is passed as is). [The documentation](https://github.com/aws/aws-cdk/blob/v2.122.0/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts#L26) also says that the default value is `CHANGE_IN_CAPACITY`. So we should use `adjustmentType` instead of `props.adjustmentType`. ```ts const adjustmentType = props.adjustmentType || AdjustmentType.CHANGE_IN_CAPACITY; const changesAreAbsolute = adjustmentType === AdjustmentType.EXACT_CAPACITY; // ... // ... this.lowerAction = new StepScalingAction(this, 'LowerPolicy', { // adjustmentType: props.adjustmentType, adjustmentType, ``` **The fact that the error occurs if `props.adjustmentType` is not specified means that the user's successful existing stack always specifies `props.adjustmentType`. In other words, no change to the existing resource will occur due to this change, so there is no need for a feature flag.** ### Description of how you validated changes ~~Unit tests without integ tests, because this PR could cover this bug by unit tests.~~ Both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../autoscaling-step-scaling.assets.json | 4 +- .../autoscaling-step-scaling.template.json | 93 ++++++++++ .../manifest.json | 26 ++- .../tree.json | 175 ++++++++++++++++++ .../test/integ.asg-step-scaling.ts | 11 ++ .../lib/step-scaling-policy.ts | 4 +- .../aws-autoscaling/test/scaling.test.ts | 22 +++ 7 files changed, 330 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.assets.json index 82a1625220d4e..0e8e3a9ec8b31 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.assets.json @@ -1,7 +1,7 @@ { "version": "36.0.0", "files": { - "b6351ec1c05eef818c53fedccb18fb96ff55ee77e2049a05d2b5b15903984b19": { + "9275d003ca02cbf717d5af0130f852ba74ab89d57dbc60b2edf6737afc7f4757": { "source": { "path": "autoscaling-step-scaling.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b6351ec1c05eef818c53fedccb18fb96ff55ee77e2049a05d2b5b15903984b19.json", + "objectKey": "9275d003ca02cbf717d5af0130f852ba74ab89d57dbc60b2edf6737afc7f4757.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-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.template.json index d15d364a6c214..d0a582898d7c3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/autoscaling-step-scaling.template.json @@ -643,6 +643,99 @@ "Statistic": "Average", "Threshold": 50 } + }, + "ASGStepScalingWithDefaultAdjustmentTypeLowerPolicyA6C1EA33": { + "Type": "AWS::AutoScaling::ScalingPolicy", + "Properties": { + "AdjustmentType": "ChangeInCapacity", + "AutoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "MetricAggregationType": "Maximum", + "PolicyType": "StepScaling", + "StepAdjustments": [ + { + "MetricIntervalUpperBound": 0, + "ScalingAdjustment": -1 + } + ] + } + }, + "ASGStepScalingWithDefaultAdjustmentTypeLowerAlarmF9F52487": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "AlarmActions": [ + { + "Ref": "ASGStepScalingWithDefaultAdjustmentTypeLowerPolicyA6C1EA33" + } + ], + "AlarmDescription": "Lower threshold scaling alarm", + "ComparisonOperator": "LessThanOrEqualToThreshold", + "DatapointsToAlarm": 5, + "Dimensions": [ + { + "Name": "AutoScalingGroupName", + "Value": { + "Ref": "ASG46ED3070" + } + } + ], + "EvaluationPeriods": 10, + "MetricName": "DiskWriteOps", + "Namespace": "AWS/EC2", + "Period": 300, + "Statistic": "Average", + "Threshold": 100 + } + }, + "ASGStepScalingWithDefaultAdjustmentTypeUpperPolicy08CC2D99": { + "Type": "AWS::AutoScaling::ScalingPolicy", + "Properties": { + "AdjustmentType": "ChangeInCapacity", + "AutoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "MetricAggregationType": "Maximum", + "PolicyType": "StepScaling", + "StepAdjustments": [ + { + "MetricIntervalLowerBound": 0, + "MetricIntervalUpperBound": 200, + "ScalingAdjustment": 1 + }, + { + "MetricIntervalLowerBound": 200, + "ScalingAdjustment": 2 + } + ] + } + }, + "ASGStepScalingWithDefaultAdjustmentTypeUpperAlarm2379E17B": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "AlarmActions": [ + { + "Ref": "ASGStepScalingWithDefaultAdjustmentTypeUpperPolicy08CC2D99" + } + ], + "AlarmDescription": "Upper threshold scaling alarm", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "DatapointsToAlarm": 5, + "Dimensions": [ + { + "Name": "AutoScalingGroupName", + "Value": { + "Ref": "ASG46ED3070" + } + } + ], + "EvaluationPeriods": 10, + "MetricName": "DiskWriteOps", + "Namespace": "AWS/EC2", + "Period": 300, + "Statistic": "Average", + "Threshold": 300 + } } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/manifest.json index 877089e7ae7f2..c3907637c2628 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.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}/b6351ec1c05eef818c53fedccb18fb96ff55ee77e2049a05d2b5b15903984b19.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9275d003ca02cbf717d5af0130f852ba74ab89d57dbc60b2edf6737afc7f4757.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -226,6 +226,30 @@ "data": "ASGStepScalingUpperAlarmD989D805" } ], + "/autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGStepScalingWithDefaultAdjustmentTypeLowerPolicyA6C1EA33" + } + ], + "/autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerAlarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGStepScalingWithDefaultAdjustmentTypeLowerAlarmF9F52487" + } + ], + "/autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGStepScalingWithDefaultAdjustmentTypeUpperPolicy08CC2D99" + } + ], + "/autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperAlarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGStepScalingWithDefaultAdjustmentTypeUpperAlarm2379E17B" + } + ], "/autoscaling-step-scaling/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/tree.json index ddc20e3a7c9b3..b983ee1e8ae20 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.js.snapshot/tree.json @@ -1067,6 +1067,181 @@ "fqn": "constructs.Construct", "version": "10.3.0" } + }, + "StepScalingWithDefaultAdjustmentType": { + "id": "StepScalingWithDefaultAdjustmentType", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType", + "children": { + "LowerPolicy": { + "id": "LowerPolicy", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::ScalingPolicy", + "aws:cdk:cloudformation:props": { + "adjustmentType": "ChangeInCapacity", + "autoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "metricAggregationType": "Maximum", + "policyType": "StepScaling", + "stepAdjustments": [ + { + "metricIntervalUpperBound": 0, + "scalingAdjustment": -1 + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "LowerAlarm": { + "id": "LowerAlarm", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerAlarm", + "children": { + "Resource": { + "id": "Resource", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/LowerAlarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "alarmActions": [ + { + "Ref": "ASGStepScalingWithDefaultAdjustmentTypeLowerPolicyA6C1EA33" + } + ], + "alarmDescription": "Lower threshold scaling alarm", + "comparisonOperator": "LessThanOrEqualToThreshold", + "datapointsToAlarm": 5, + "dimensions": [ + { + "name": "AutoScalingGroupName", + "value": { + "Ref": "ASG46ED3070" + } + } + ], + "evaluationPeriods": 10, + "metricName": "DiskWriteOps", + "namespace": "AWS/EC2", + "period": 300, + "statistic": "Average", + "threshold": 100 + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "UpperPolicy": { + "id": "UpperPolicy", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::ScalingPolicy", + "aws:cdk:cloudformation:props": { + "adjustmentType": "ChangeInCapacity", + "autoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "metricAggregationType": "Maximum", + "policyType": "StepScaling", + "stepAdjustments": [ + { + "metricIntervalLowerBound": 0, + "metricIntervalUpperBound": 200, + "scalingAdjustment": 1 + }, + { + "metricIntervalLowerBound": 200, + "scalingAdjustment": 2 + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "UpperAlarm": { + "id": "UpperAlarm", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperAlarm", + "children": { + "Resource": { + "id": "Resource", + "path": "autoscaling-step-scaling/ASG/StepScalingWithDefaultAdjustmentType/UpperAlarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "alarmActions": [ + { + "Ref": "ASGStepScalingWithDefaultAdjustmentTypeUpperPolicy08CC2D99" + } + ], + "alarmDescription": "Upper threshold scaling alarm", + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "datapointsToAlarm": 5, + "dimensions": [ + { + "name": "AutoScalingGroupName", + "value": { + "Ref": "ASG46ED3070" + } + } + ], + "evaluationPeriods": 10, + "metricName": "DiskWriteOps", + "namespace": "AWS/EC2", + "period": 300, + "statistic": "Average", + "threshold": 300 + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.ts index c49ed5d312e98..081d85b8c6ec8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-autoscaling/test/integ.asg-step-scaling.ts @@ -30,6 +30,17 @@ asg.scaleOnMetric('StepScaling', { datapointsToAlarm: 5, metricAggregationType: autoscaling.MetricAggregationType.MAXIMUM, }); +asg.scaleOnMetric('StepScalingWithDefaultAdjustmentType', { + metric: new cloudwatch.Metric({ namespace: 'AWS/EC2', metricName: 'DiskWriteOps', dimensionsMap: { AutoScalingGroupName: asg.autoScalingGroupName } }), + scalingSteps: [ + { upper: 100, change: -1 }, + { lower: 300, change: +1 }, + { lower: 500, change: +2 }, + ], + evaluationPeriods: 10, + datapointsToAlarm: 5, + metricAggregationType: autoscaling.MetricAggregationType.MAXIMUM, +}); new integ.IntegTest(app, 'autoscaling-step-scaling-integ', { testCases: [stack], diff --git a/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts b/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts index eed4950e7e720..937c92c0b80b1 100644 --- a/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts +++ b/packages/aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts @@ -147,7 +147,7 @@ export class StepScalingPolicy extends Construct { const threshold = intervals[alarms.lowerAlarmIntervalIndex].upper; this.lowerAction = new StepScalingAction(this, 'LowerPolicy', { - adjustmentType: props.adjustmentType, + adjustmentType, cooldown: props.cooldown, estimatedInstanceWarmup: props.estimatedInstanceWarmup, metricAggregationType: props.metricAggregationType ?? aggregationTypeFromMetric(props.metric), @@ -179,7 +179,7 @@ export class StepScalingPolicy extends Construct { const threshold = intervals[alarms.upperAlarmIntervalIndex].lower; this.upperAction = new StepScalingAction(this, 'UpperPolicy', { - adjustmentType: props.adjustmentType, + adjustmentType, cooldown: props.cooldown, estimatedInstanceWarmup: props.estimatedInstanceWarmup, metricAggregationType: props.metricAggregationType ?? aggregationTypeFromMetric(props.metric), diff --git a/packages/aws-cdk-lib/aws-autoscaling/test/scaling.test.ts b/packages/aws-cdk-lib/aws-autoscaling/test/scaling.test.ts index dc4a564d75221..f8dd19b431812 100644 --- a/packages/aws-cdk-lib/aws-autoscaling/test/scaling.test.ts +++ b/packages/aws-cdk-lib/aws-autoscaling/test/scaling.test.ts @@ -294,6 +294,28 @@ test('step scaling from percentile metric', () => { }); }); +test('step scaling with adjustmentType by default', () => { + // GIVEN + const stack = new cdk.Stack(); + const fixture = new ASGFixture(stack, 'Fixture'); + + // WHEN + fixture.asg.scaleOnMetric('Tracking', { + metric: new cloudwatch.Metric({ namespace: 'Test', metricName: 'Metric', statistic: 'p99' }), + scalingSteps: [ + { upper: 0, change: -1 }, + { lower: 100, change: +1 }, + { lower: 500, change: +5 }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::ScalingPolicy', { + PolicyType: 'StepScaling', + AdjustmentType: 'ChangeInCapacity', + }); +}); + test('step scaling with evaluation period configured', () => { // GIVEN const stack = new cdk.Stack(); From 0f47c3d2737ad684ebdbe290076cb24acb94ce09 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:15:11 -0500 Subject: [PATCH 11/31] chore: move github actions to cdklabs (#29303) I have not tested any of the actions in the new source because all I have done are move the actions over to a different repository. I will monitor the actions for any failures and deal with them on the fly. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .github/workflows/close-stale-prs.yml | 2 +- .github/workflows/github-merit-badger.yml | 2 +- .github/workflows/issue-reprioritization.yml | 2 +- .github/workflows/pr-labeler.yml | 2 +- .github/workflows/pr-linter-exemption-labeler.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/close-stale-prs.yml b/.github/workflows/close-stale-prs.yml index cd601426deba9..5eb104b04a417 100644 --- a/.github/workflows/close-stale-prs.yml +++ b/.github/workflows/close-stale-prs.yml @@ -11,7 +11,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: rix0rrr/close-stale-prs@main + - uses: cdklabs/close-stale-prs@main with: # Required # Must be PROJEN_GITHUB_TOKEN because the default GHA GitHub token will not have permissions to diff --git a/.github/workflows/github-merit-badger.yml b/.github/workflows/github-merit-badger.yml index 0628aa33fb652..52fb16387ac6c 100644 --- a/.github/workflows/github-merit-badger.yml +++ b/.github/workflows/github-merit-badger.yml @@ -10,7 +10,7 @@ jobs: permissions: pull-requests: write steps: - - uses: aws-github-ops/github-merit-badger@main + - uses: cdklabs/github-merit-badger@main id: merit-badger with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/issue-reprioritization.yml b/.github/workflows/issue-reprioritization.yml index e8a68ec1276d1..8a3590c9ecc09 100644 --- a/.github/workflows/issue-reprioritization.yml +++ b/.github/workflows/issue-reprioritization.yml @@ -11,7 +11,7 @@ jobs: repository-projects: write runs-on: ubuntu-latest steps: - - uses: kaizencc/issue-reprioritization-manager@main + - uses: cdklabs/issue-reprioritization-manager@main id: reprioritization-manager with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 1ce06fd16fcf1..f0757ded212b9 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -24,7 +24,7 @@ jobs: permissions: pull-requests: write steps: - - uses: kaizencc/pr-triage-manager@main + - uses: cdklabs/pr-triage-manager@main with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-linter-exemption-labeler.yml b/.github/workflows/pr-linter-exemption-labeler.yml index 332a216a6811e..878d90d3f2ffc 100644 --- a/.github/workflows/pr-linter-exemption-labeler.yml +++ b/.github/workflows/pr-linter-exemption-labeler.yml @@ -12,6 +12,6 @@ jobs: if: ${{ (github.event.issue.pull_request) && (github.event.issue.state == 'open') }} runs-on: ubuntu-latest steps: - - uses: TheRealAmazonKendra/pr-linter-exemption-labeler@main + - uses: cdklabs/pr-linter-exemption-labeler@main with: github-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} \ No newline at end of file From 98b9bf28c95f87a3c2954bd73fc1a72c567d1e40 Mon Sep 17 00:00:00 2001 From: Michael Sambol Date: Wed, 28 Feb 2024 12:22:35 -0700 Subject: [PATCH 12/31] fix(ecs): `autoscalingGroup` attribute does not exist on `ImportedCluster` (#29244) This PR adds an `autoscalingGroup` attribute to `ImportedCluster`. This attribute is set using the `autoscalingGroup` property from `ClusterAttributes` in the constructor of `ImportedCluster`. Closes #29241. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssert8B67C7A2.assets.json | 19 + ...aultTestDeployAssert8B67C7A2.template.json | 36 + .../cdk.out | 1 + .../integ-ecs-imported-cluster.assets.json | 19 + .../integ-ecs-imported-cluster.template.json | 965 ++++++++++ .../integ.json | 12 + .../manifest.json | 359 ++++ .../tree.json | 1620 +++++++++++++++++ .../aws-ecs/test/integ.cluster-imported.ts | 39 + packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 6 + .../aws-cdk-lib/aws-ecs/test/cluster.test.ts | 20 + 11 files changed, 3096 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.assets.json new file mode 100644 index 0000000000000..8fe55b44f1cc2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.assets.json new file mode 100644 index 0000000000000..404971fd86604 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "e56132cf60edf65ae2879e26d8df65912906d3df363d16fc86d4a530d83a07df": { + "source": { + "path": "integ-ecs-imported-cluster.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "e56132cf60edf65ae2879e26d8df65912906d3df363d16fc86d4a530d83a07df.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.template.json new file mode 100644 index 0000000000000..a399b594069ab --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ-ecs-imported-cluster.template.json @@ -0,0 +1,965 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677" + ] + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTableAssociationDD5762D8" + ] + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ClusterEB0386A7": { + "Type": "AWS::ECS::Cluster" + }, + "Cluster3DA9CCBA": { + "Type": "AWS::ECS::ClusterCapacityProviderAssociations", + "Properties": { + "CapacityProviders": [ + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "Cluster": { + "Ref": "ClusterEB0386A7" + }, + "DefaultCapacityProviderStrategy": [] + } + }, + "ASGInstanceSecurityGroup0525485D": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ecs-imported-cluster/ASG/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ASGInstanceRoleE263A41B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "ASGInstanceRoleDefaultPolicy7636D8BF": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGInstanceRoleDefaultPolicy7636D8BF", + "Roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "ASGInstanceProfile0A2834D7": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "ASGLaunchTemplate0CA92847": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "IamInstanceProfile": { + "Arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t2.micro", + "Monitoring": { + "Enabled": false + }, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\necho ECS_CLUSTER=", + { + "Ref": "ClusterEB0386A7" + }, + " >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config" + ] + ] + } + } + }, + "TagSpecifications": [ + { + "ResourceType": "launch-template", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + } + ] + }, + "DependsOn": [ + "ASGInstanceRoleDefaultPolicy7636D8BF", + "ASGInstanceRoleE263A41B" + ] + }, + "ASG46ED3070": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "LaunchTemplate": { + "LaunchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "Version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "MaxSize": "1", + "MinSize": "0", + "Tags": [ + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "integ-ecs-imported-cluster/ASG" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + }, + "UpdatePolicy": { + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "ASGDrainECSHookFunctionServiceRoleC12963BB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "Roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "ASGDrainECSHookFunction5F24CF4D": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "Environment": { + "Variables": { + "CLUSTER": { + "Ref": "ClusterEB0386A7" + } + } + }, + "Handler": "index.lambda_handler", + "Role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "Runtime": "python3.9", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ], + "Timeout": 310 + }, + "DependsOn": [ + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "ASGDrainECSHookFunctionServiceRoleC12963BB" + ] + }, + "ASGDrainECSHookFunctionAllowInvokeintegecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12B2C7A898": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Principal": "sns.amazonaws.com", + "SourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGDrainECSHookFunctionTopicD6FC59F7": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGLifecycleHookDrainHookTopicA8AD4ACB": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleD640316C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "Roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "ASGLifecycleHookDrainHookFE4AFEBE": { + "Type": "AWS::AutoScaling::LifecycleHook", + "Properties": { + "AutoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "DefaultResult": "CONTINUE", + "HeartbeatTimeout": 300, + "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "NotificationTargetARN": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "RoleARN": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + }, + "DependsOn": [ + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "ASGLifecycleHookDrainHookRoleD640316C" + ] + }, + "EC2CapacityProvider5A2E35CD": { + "Type": "AWS::ECS::CapacityProvider", + "Properties": { + "AutoScalingGroupProvider": { + "AutoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "ManagedScaling": { + "Status": "ENABLED", + "TargetCapacity": 100 + }, + "ManagedTerminationProtection": "DISABLED" + } + } + } + }, + "Parameters": { + "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ.json new file mode 100644 index 0000000000000..7d4c33ddbdfc2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "ClusterImported/DefaultTest": { + "stacks": [ + "integ-ecs-imported-cluster" + ], + "assertionStack": "ClusterImported/DefaultTest/DeployAssert", + "assertionStackName": "ClusterImportedDefaultTestDeployAssert8B67C7A2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/manifest.json new file mode 100644 index 0000000000000..1a633d69895eb --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/manifest.json @@ -0,0 +1,359 @@ +{ + "version": "36.0.0", + "artifacts": { + "integ-ecs-imported-cluster.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-ecs-imported-cluster.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-ecs-imported-cluster": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-ecs-imported-cluster.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e56132cf60edf65ae2879e26d8df65912906d3df363d16fc86d4a530d83a07df.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-ecs-imported-cluster.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-ecs-imported-cluster.assets" + ], + "metadata": { + "/integ-ecs-imported-cluster/Vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpc8378EB38" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1Subnet5C2D37C4" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTable6C95E38E" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTableAssociation97140677" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1EIPD7E02669" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1NATGateway4D7517AA" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTable94F7E489" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTableAssociationDD5762D8" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2DefaultRoute97F91067" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2EIP3C605A87" + } + ], + "/integ-ecs-imported-cluster/Vpc/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2NATGateway9182C01D" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1Subnet536B997A" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableB2C5B500" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableAssociation70C59FA6" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1DefaultRouteBE02A9ED" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2Subnet3788AAA1" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableA678073B" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableAssociationA89CAD56" + } + ], + "/integ-ecs-imported-cluster/Vpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2DefaultRoute060D2087" + } + ], + "/integ-ecs-imported-cluster/Vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIGWD7BA715C" + } + ], + "/integ-ecs-imported-cluster/Vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcVPCGWBF912B6E" + } + ], + "/integ-ecs-imported-cluster/Cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ClusterEB0386A7" + } + ], + "/integ-ecs-imported-cluster/Cluster/Cluster": [ + { + "type": "aws:cdk:logicalId", + "data": "Cluster3DA9CCBA" + } + ], + "/integ-ecs-imported-cluster/ASG/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceSecurityGroup0525485D" + } + ], + "/integ-ecs-imported-cluster/ASG/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceRoleE263A41B" + } + ], + "/integ-ecs-imported-cluster/ASG/InstanceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceRoleDefaultPolicy7636D8BF" + } + ], + "/integ-ecs-imported-cluster/ASG/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceProfile0A2834D7" + } + ], + "/integ-ecs-imported-cluster/ASG/LaunchTemplate/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLaunchTemplate0CA92847" + } + ], + "/integ-ecs-imported-cluster/ASG/ASG": [ + { + "type": "aws:cdk:logicalId", + "data": "ASG46ED3070" + } + ], + "/integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ], + "/integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27" + } + ], + "/integ-ecs-imported-cluster/ASG/DrainECSHook/Function/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunction5F24CF4D" + } + ], + "/integ-ecs-imported-cluster/ASG/DrainECSHook/Function/AllowInvoke:integecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionAllowInvokeintegecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12B2C7A898" + } + ], + "/integ-ecs-imported-cluster/ASG/DrainECSHook/Function/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionTopicD6FC59F7" + } + ], + "/integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + ], + "/integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleD640316C" + } + ], + "/integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57" + } + ], + "/integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookFE4AFEBE" + } + ], + "/integ-ecs-imported-cluster/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/integ-ecs-imported-cluster/EC2CapacityProvider/EC2CapacityProvider": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2CapacityProvider5A2E35CD" + } + ], + "/integ-ecs-imported-cluster/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-ecs-imported-cluster/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-ecs-imported-cluster" + }, + "ClusterImportedDefaultTestDeployAssert8B67C7A2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ClusterImportedDefaultTestDeployAssert8B67C7A2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ClusterImportedDefaultTestDeployAssert8B67C7A2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ClusterImportedDefaultTestDeployAssert8B67C7A2.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ClusterImportedDefaultTestDeployAssert8B67C7A2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ClusterImportedDefaultTestDeployAssert8B67C7A2.assets" + ], + "metadata": { + "/ClusterImported/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ClusterImported/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ClusterImported/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/tree.json new file mode 100644 index 0000000000000..d252625617183 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.js.snapshot/tree.json @@ -0,0 +1,1620 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-ecs-imported-cluster": { + "id": "integ-ecs-imported-cluster", + "path": "integ-ecs-imported-cluster", + "children": { + "Vpc": { + "id": "Vpc", + "path": "integ-ecs-imported-cluster/Vpc", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/Vpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-ecs-imported-cluster/Vpc/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-imported-cluster/Vpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-ecs-imported-cluster/Vpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-ecs-imported-cluster/Vpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Cluster": { + "id": "Cluster", + "path": "integ-ecs-imported-cluster/Cluster", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/Cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Cluster": { + "id": "Cluster", + "path": "integ-ecs-imported-cluster/Cluster/Cluster", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::ClusterCapacityProviderAssociations", + "aws:cdk:cloudformation:props": { + "capacityProviders": [ + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "cluster": { + "Ref": "ClusterEB0386A7" + }, + "defaultCapacityProviderStrategy": [] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ecs-imported-cluster/ASG", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "integ-ecs-imported-cluster/ASG/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "integ-ecs-imported-cluster/ASG/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "integ-ecs-imported-cluster/ASG/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "integ-ecs-imported-cluster/ASG/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-imported-cluster/ASG/InstanceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/InstanceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGInstanceRoleDefaultPolicy7636D8BF", + "roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "integ-ecs-imported-cluster/ASG/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "ASGInstanceRoleE263A41B" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ImportedInstanceProfile": { + "id": "ImportedInstanceProfile", + "path": "integ-ecs-imported-cluster/ASG/ImportedInstanceProfile", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "LaunchTemplate": { + "id": "LaunchTemplate", + "path": "integ-ecs-imported-cluster/ASG/LaunchTemplate", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/LaunchTemplate/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::LaunchTemplate", + "aws:cdk:cloudformation:props": { + "launchTemplateData": { + "iamInstanceProfile": { + "arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t2.micro", + "monitoring": { + "enabled": false + }, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "tagSpecifications": [ + { + "resourceType": "instance", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + }, + { + "resourceType": "volume", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + } + ], + "userData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\necho ECS_CLUSTER=", + { + "Ref": "ClusterEB0386A7" + }, + " >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config" + ] + ] + } + } + }, + "tagSpecifications": [ + { + "resourceType": "launch-template", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG/LaunchTemplate" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ecs-imported-cluster/ASG/ASG", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::AutoScalingGroup", + "aws:cdk:cloudformation:props": { + "launchTemplate": { + "launchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "maxSize": "1", + "minSize": "0", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG", + "propagateAtLaunch": true + } + ], + "vpcZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DrainECSHook": { + "id": "DrainECSHook", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook", + "children": { + "Function": { + "id": "Function", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "environment": { + "variables": { + "CLUSTER": { + "Ref": "ClusterEB0386A7" + } + } + }, + "handler": "index.lambda_handler", + "role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "runtime": "python3.9", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ], + "timeout": 310 + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "AllowInvoke:integecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12": { + "id": "AllowInvoke:integecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/AllowInvoke:integecsimportedclusterASGLifecycleHookDrainHookTopic78A11E12", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "principal": "sns.amazonaws.com", + "sourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Topic": { + "id": "Topic", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/DrainECSHook/Function/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", + "aws:cdk:cloudformation:props": { + "endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "protocol": "lambda", + "topicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "LifecycleHookDrainHook": { + "id": "LifecycleHookDrainHook", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook", + "children": { + "Topic": { + "id": "Topic", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Role": { + "id": "Role", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/ImportRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-imported-cluster/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-imported-cluster/ASG/LifecycleHookDrainHook/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::LifecycleHook", + "aws:cdk:cloudformation:props": { + "autoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "defaultResult": "CONTINUE", + "heartbeatTimeout": 300, + "lifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "notificationTargetArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "roleArn": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ecs-imported-cluster/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ecs-imported-cluster/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ecs-imported-cluster/EC2CapacityProvider", + "children": { + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ecs-imported-cluster/EC2CapacityProvider/EC2CapacityProvider", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::CapacityProvider", + "aws:cdk:cloudformation:props": { + "autoScalingGroupProvider": { + "autoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "managedScaling": { + "status": "ENABLED", + "targetCapacity": 100 + }, + "managedTerminationProtection": "DISABLED" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ImportedCluster": { + "id": "ImportedCluster", + "path": "integ-ecs-imported-cluster/ImportedCluster", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-ecs-imported-cluster/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-ecs-imported-cluster/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ClusterImported": { + "id": "ClusterImported", + "path": "ClusterImported", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ClusterImported/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ClusterImported/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ClusterImported/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ClusterImported/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ClusterImported/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts new file mode 100644 index 0000000000000..9bb84fd52424f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts @@ -0,0 +1,39 @@ +import * as autoscaling from 'aws-cdk-lib/aws-autoscaling'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as integ from '@aws-cdk/integ-tests-alpha'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-ecs-imported-cluster'); + +const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); +const cluster = new ecs.Cluster(stack, 'Cluster', { + vpc, +}); + +const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'ASG', { + vpc, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.STANDARD), + minCapacity: 0, +}); + +const cp = new ecs.AsgCapacityProvider(stack, 'EC2CapacityProvider', { + autoScalingGroup, + enableManagedTerminationProtection: false, +}); + +cluster.addAsgCapacityProvider(cp); + +ecs.Cluster.fromClusterAttributes(stack, 'ImportedCluster', { + clusterName: cluster.clusterName, + vpc, + autoscalingGroup: autoScalingGroup, +}); + +new integ.IntegTest(app, 'ClusterImported', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index e65e62d4b2813..03a5f2c852242 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -858,6 +858,11 @@ class ImportedCluster extends Resource implements ICluster { */ public readonly hasEc2Capacity: boolean; + /** + * The autoscaling group added to the cluster if capacity is associated to the cluster + */ + public readonly autoscalingGroup?: autoscaling.IAutoScalingGroup; + /** * Cloudmap namespace created in the cluster */ @@ -878,6 +883,7 @@ class ImportedCluster extends Resource implements ICluster { this.hasEc2Capacity = props.hasEc2Capacity !== false; this._defaultCloudMapNamespace = props.defaultCloudMapNamespace; this._executeCommandConfiguration = props.executeCommandConfiguration; + this.autoscalingGroup = props.autoscalingGroup; this.clusterArn = props.clusterArn ?? Stack.of(this).formatArn({ service: 'ecs', diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index 3ba6f23a71c3c..091b8f8ad469d 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -1527,6 +1527,26 @@ describe('cluster', () => { expect(cluster.connections.securityGroups).toEqual([]); }); + test('Can import autoscaling groups', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const autoscalingGroup = new autoscaling.AutoScalingGroup(stack, 'asgal2', { + vpc, + instanceType: new ec2.InstanceType('bogus'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + + const cluster = ecs.Cluster.fromClusterAttributes(stack, 'Cluster', { + clusterName: 'cluster-name', + vpc, + autoscalingGroup, + }); + + // THEN + expect(cluster.autoscalingGroup).toEqual(autoscalingGroup); + }); + test('Metric', () => { // GIVEN const stack = new cdk.Stack(); From d30881882f0742362d171340d2f94be8b7707acc Mon Sep 17 00:00:00 2001 From: shikha372 Date: Wed, 28 Feb 2024 11:51:36 -0800 Subject: [PATCH 13/31] chore: add abstraction team to mergify and merit badger (#29273) ### Issue # (if applicable) NA ### Reason for this change adding abstraction team new members to mergify and merit badger ### Description of changes adding abstraction team new members to mergify and merit badger ### Description of how you validated changes NA ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .github/workflows/github-merit-badger.yml | 2 +- .mergify.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-merit-badger.yml b/.github/workflows/github-merit-badger.yml index 52fb16387ac6c..240ba4eb57b9b 100644 --- a/.github/workflows/github-merit-badger.yml +++ b/.github/workflows/github-merit-badger.yml @@ -17,4 +17,4 @@ jobs: badges: '[beginning-contributor,repeat-contributor,valued-contributor,admired-contributor,star-contributor,distinguished-contributor]' thresholds: '[0,3,6,13,25,50]' badge-type: 'achievement' - ignore-usernames: '[rix0rrr,MrArnoldPalmer,iliapolo,otaviomacedo,madeline-k,kaizencc,comcalvi,TheRealAmazonKendra,vinayak-kukreja,mrgrain,pahud,cgarvis,kellertk,HBobertz,sumupitchayan,SankyRed,udaypant,colifran,khushail,scanlonp,mikewrighton,moelasmar,paulhcsun,awsmjs,evgenyka,GavinZZ,aaythapa,xazhao,ConnorRobertson,ssenchenko,gracelu0,jfuss,SimonCMoore,aws-cdk-automation,dependabot[bot],mergify[bot]]' + ignore-usernames: '[rix0rrr,iliapolo,otaviomacedo,kaizencc,comcalvi,TheRealAmazonKendra,vinayak-kukreja,mrgrain,pahud,cgarvis,kellertk,HBobertz,sumupitchayan,SankyRed,udaypant,colifran,khushail,scanlonp,mikewrighton,moelasmar,paulhcsun,awsmjs,evgenyka,GavinZZ,aaythapa,xazhao,ConnorRobertson,ssenchenko,gracelu0,jfuss,SimonCMoore,shikha372,kirtishrinkhala,godwingrs22,aws-cdk-automation,dependabot[bot],mergify[bot]]' diff --git a/.mergify.yml b/.mergify.yml index f3e915f1c5edb..2960e8216acf2 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -11,7 +11,7 @@ pull_request_rules: label: add: [ contribution/core ] conditions: - - author~=^(rix0rrr|iliapolo|otaviomacedo|kaizencc|comcalvi|TheRealAmazonKendra|vinayak-kukreja|mrgrain|pahud|cgarvis|kellertk|HBobertz|sumupitchayan|SankyRed|udaypant|colifran|scanlonp|mikewrighton|moelasmar|paulhcsun|awsmjs|evgenyka|GavinZZ|aaythapa|xazhao|ConnorRobertson|ssenchenko|gracelu0|jfuss|SimonCMoore)$ + - author~=^(rix0rrr|iliapolo|otaviomacedo|kaizencc|comcalvi|TheRealAmazonKendra|vinayak-kukreja|mrgrain|pahud|cgarvis|kellertk|HBobertz|sumupitchayan|SankyRed|udaypant|colifran|scanlonp|mikewrighton|moelasmar|paulhcsun|awsmjs|evgenyka|GavinZZ|aaythapa|xazhao|ConnorRobertson|ssenchenko|gracelu0|jfuss|SimonCMoore|shikha372|kirtishrinkhala|godwingrs22)$ - -label~="contribution/core" - name: automatic merge actions: From 8d07b857aec64211054e409a098a841ac57d9e09 Mon Sep 17 00:00:00 2001 From: Sumu Pitchayan <35242245+sumupitchayan@users.noreply.github.com> Date: Thu, 29 Feb 2024 00:45:07 -0500 Subject: [PATCH 14/31] fix(cli-integ): use `Python_3_12` instead of `Python_3_7` lambda runtime (#29305) Fix for failing CLI integ canary ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../sam_cdk_integ_app/lib/nested-stack.js | 2 +- .../cdk-apps/sam_cdk_integ_app/lib/test-stack.js | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js b/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js index 91828413b270a..8620fb693e4bf 100644 --- a/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js +++ b/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js @@ -10,7 +10,7 @@ class NestedStack1 extends NestedStack { constructor(scope, id, props) { super(scope, id, props); new Function(this, 'FunctionPythonRuntime', { - runtime: Runtime.PYTHON_3_7, + runtime: Runtime.PYTHON_3_12, code: Code.fromAsset('./src/python/Function'), handler: 'app.lambda_handler', }); diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js b/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js index 9df6588f83bd3..3e9a071de8ff1 100644 --- a/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js +++ b/packages/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js @@ -29,19 +29,19 @@ class CDKSupportDemoRootStack extends Stack{ // Layers new PythonLayerVersion(this, 'PythonLayerVersion', { compatibleRuntimes: [ - Runtime.PYTHON_3_7, + Runtime.PYTHON_3_12, ], entry: './src/python/Layer', }); new LayerVersion(this, 'LayerVersion', { compatibleRuntimes: [ - Runtime.PYTHON_3_7, + Runtime.PYTHON_3_12, ], code: Code.fromAsset('./src/python/Layer'), }); new LayerVersion(this, 'BundledLayerVersionPythonRuntime', { compatibleRuntimes: [ - Runtime.PYTHON_3_7, + Runtime.PYTHON_3_12, ], code: Code.fromAsset('./src/python/Layer', { bundling: { @@ -50,7 +50,7 @@ class CDKSupportDemoRootStack extends Stack{ '-c', 'rm -rf /tmp/asset-input && mkdir /tmp/asset-input && cp * /tmp/asset-input && cd /tmp/asset-input && pip install -r requirements.txt -t . && mkdir /asset-output/python && cp -R /tmp/asset-input/* /asset-output/python', ], - image: Runtime.PYTHON_3_7.bundlingImage, + image: Runtime.PYTHON_3_12.bundlingImage, user: 'root', } }), @@ -61,17 +61,17 @@ class CDKSupportDemoRootStack extends Stack{ entry: './src/python/Function', index: 'app.py', handler: 'lambda_handler', - runtime: Runtime.PYTHON_3_7, + runtime: Runtime.PYTHON_3_12, functionName: 'pythonFunc', logRetention: RetentionDays.THREE_MONTHS, }); new Function(this, 'FunctionPythonRuntime', { - runtime: Runtime.PYTHON_3_7, + runtime: Runtime.PYTHON_3_12, code: Code.fromAsset('./src/python/Function'), handler: 'app.lambda_handler', }); new Function(this, 'BundledFunctionPythonRuntime', { - runtime: Runtime.PYTHON_3_7, + runtime: Runtime.PYTHON_3_12, code: Code.fromAsset('./src/python/Function/', { bundling: { command: [ @@ -79,7 +79,7 @@ class CDKSupportDemoRootStack extends Stack{ '-c', 'rm -rf /tmp/asset-input && mkdir /tmp/asset-input && cp * /tmp/asset-input && cd /tmp/asset-input && pip install -r requirements.txt -t . && cp -R /tmp/asset-input/* /asset-output', ], - image: Runtime.PYTHON_3_7.bundlingImage, + image: Runtime.PYTHON_3_12.bundlingImage, user: 'root', } }), From 8c926f4b36ca22faeab50c7840b5ffd8a4cb6884 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Thu, 29 Feb 2024 08:23:31 +0100 Subject: [PATCH 15/31] updated test cases --- ...emoval-policy-snapshot-stack.template.json | 4 +- .../integ.cluster-removal-policy-snapshot.ts | 1 - .../aws-docdb/test/cluster.test.ts | 38 ++++++++++++++++--- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json index 042cd76401b0d..00446c1b294c2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.js.snapshot/aws-cdk-docdb-removal-policy-snapshot-stack.template.json @@ -542,8 +542,8 @@ "VPCPublicSubnet2DefaultRouteB7481BBA", "VPCPublicSubnet2RouteTableAssociation5A808732" ], - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts index c4a5fea0f4abb..fe3a386bcb727 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-docdb/test/integ.cluster-removal-policy-snapshot.ts @@ -42,7 +42,6 @@ class TestStack extends cdk.Stack { parameterGroup: params, kmsKey, removalPolicy: cdk.RemovalPolicy.SNAPSHOT, - instanceRemovalPolicy: cdk.RemovalPolicy.RETAIN, // Remember to cleanup after running this test enablePerformanceInsights: true, }); diff --git a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts index 9e2aabd7a9edb..f28f335d5c0e2 100644 --- a/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-docdb/test/cluster.test.ts @@ -1013,13 +1013,26 @@ describe('DatabaseCluster', () => { }, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), vpc, - instanceRemovalPolicy: cdk.RemovalPolicy.DESTROY, + removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + instanceRemovalPolicy: cdk.RemovalPolicy.RETAIN, }); // THEN + Template.fromStack(stack).hasResource('AWS::DocDB::DBCluster', { + Properties: { + DBSubnetGroupName: { Ref: 'DatabaseSubnets56F17B9A' }, + MasterUsername: 'admin', + MasterUserPassword: 'tooshort', + VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], + }, + DeletionPolicy: 'Snapshot', + UpdateReplacePolicy: 'Snapshot', + }); + + // Associated instance gets specified policy Template.fromStack(stack).hasResource('AWS::DocDB::DBInstance', { - DeletionPolicy: 'Delete', - UpdateReplacePolicy: 'Delete', + DeletionPolicy: 'Retain', + UpdateReplacePolicy: 'Retain', }); }); @@ -1037,13 +1050,26 @@ describe('DatabaseCluster', () => { }, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), vpc, - securityGroupRemovalPolicy: cdk.RemovalPolicy.DESTROY, + removalPolicy: cdk.RemovalPolicy.SNAPSHOT, + securityGroupRemovalPolicy: cdk.RemovalPolicy.RETAIN, }); // THEN + Template.fromStack(stack).hasResource('AWS::DocDB::DBCluster', { + Properties: { + DBSubnetGroupName: { Ref: 'DatabaseSubnets56F17B9A' }, + MasterUsername: 'admin', + MasterUserPassword: 'tooshort', + VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], + }, + DeletionPolicy: 'Snapshot', + UpdateReplacePolicy: 'Snapshot', + }); + + // Associated security group gets specified policy Template.fromStack(stack).hasResource('AWS::EC2::SecurityGroup', { - DeletionPolicy: 'Delete', - UpdateReplacePolicy: 'Delete', + DeletionPolicy: 'Retain', + UpdateReplacePolicy: 'Retain', }); }); From 457afa9d01fca8c9b91648175d6aa3183611e504 Mon Sep 17 00:00:00 2001 From: paulhcsun <47882901+paulhcsun@users.noreply.github.com> Date: Thu, 29 Feb 2024 06:50:36 -0800 Subject: [PATCH 16/31] fix(cloudtrail): isOrganizationTrail attaches insufficient permissions to bucket (#29242) ### Issue https://github.com/aws/aws-cdk/issues/22267 (if applicable) Closes https://github.com/aws/aws-cdk/issues/22267. ### Reason for this change Setting the `isOrganizationTrail` property to `true` attaches insufficient permissions to the bucket thus failing to deploy the `Trail` with: ``` Invalid request provided: Incorrect S3 bucket policy is detected for bucket: ... ``` ### Description of changes This PR adds a new property `orgId` to `TrailProps` that will be used to attach the [missing permission](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html#org-trail-bucket-policy) ``` "Action": "s3:PutObject", "Resource": "arn:aws:s3:::myOrganizationBucket/AWSLogs/o-organizationID/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceArn": "arn:aws:cloudtrail:region:managementAccountID:trail/trailName" } ``` when `isOrganizationTrail: true`. ### Description of how you validated changes Validated locally that I can deploy when `Trail.isOrganizationTrail: true` with a valid `orgId` + added unit test case. I can't think of a way to test this with an integ test as it requires a valid `orgId` to deploy but any suggestions are welcome. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cloudtrail/lib/cloudtrail.ts | 24 ++++ .../aws-cloudtrail/test/cloudtrail.test.ts | 130 ++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts b/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts index 7e85a0821278a..301c32eaa22b3 100644 --- a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts +++ b/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts @@ -128,6 +128,14 @@ export interface TrailProps { */ readonly isOrganizationTrail?: boolean; + /** The orgId. + * + * Required when `isOrganizationTrail` is set to true to attach the necessary permissions. + * + * @default - No orgId + */ + readonly orgId?: string; + /** * A JSON string that contains the insight types you want to log on a trail. * @@ -262,6 +270,22 @@ export class Trail extends Resource { }, })); + if (props.isOrganizationTrail) { + this.s3bucket.addToResourcePolicy(new iam.PolicyStatement({ + resources: [this.s3bucket.arnForObjects( + `AWSLogs/${props.orgId}/*`, + )], + actions: ['s3:PutObject'], + principals: [cloudTrailPrincipal], + conditions: { + StringEquals: { + 's3:x-amz-acl': 'bucket-owner-full-control', + 'aws:SourceArn': `arn:${this.stack.partition}:cloudtrail:${this.s3bucket.stack.region}:${this.s3bucket.stack.account}:trail/${props.trailName}`, + }, + }, + })); + } + this.topic = props.snsTopic; if (this.topic) { this.topic.grantPublish(cloudTrailPrincipal); diff --git a/packages/aws-cdk-lib/aws-cloudtrail/test/cloudtrail.test.ts b/packages/aws-cdk-lib/aws-cloudtrail/test/cloudtrail.test.ts index 0950d68c185cc..55d762db6efe0 100644 --- a/packages/aws-cdk-lib/aws-cloudtrail/test/cloudtrail.test.ts +++ b/packages/aws-cdk-lib/aws-cloudtrail/test/cloudtrail.test.ts @@ -246,6 +246,136 @@ describe('cloudtrail', () => { }); }); + test('with orgId', () => { + // GIVEN + const stack = getTestStack(); + + // WHEN + new Trail(stack, 'Trail', { isOrganizationTrail: true, orgId: 'o-xxxxxxxxx', trailName: 'trailname123' }); + + Template.fromStack(stack).resourceCountIs('AWS::CloudTrail::Trail', 1); + Template.fromStack(stack).resourceCountIs('AWS::S3::Bucket', 1); + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + Bucket: { Ref: 'TrailS30071F172' }, + PolicyDocument: { + Statement: [ + { + Action: 's3:*', + Condition: { + Bool: { + 'aws:SecureTransport': 'false', + }, + }, + Effect: 'Deny', + Principal: { + AWS: '*', + }, + Resource: [ + { + 'Fn::GetAtt': [ + 'TrailS30071F172', + 'Arn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'TrailS30071F172', + 'Arn', + ], + }, + '/*', + ], + ], + }, + ], + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { + Service: 'cloudtrail.amazonaws.com', + }, + Resource: { + 'Fn::GetAtt': [ + 'TrailS30071F172', + 'Arn', + ], + }, + }, + { + Action: 's3:PutObject', + Condition: { + StringEquals: { + 's3:x-amz-acl': 'bucket-owner-full-control', + }, + }, + Effect: 'Allow', + Principal: { + Service: 'cloudtrail.amazonaws.com', + }, + Resource: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'TrailS30071F172', + 'Arn', + ], + }, + '/AWSLogs/123456789012/*', + ], + ], + }, + }, + { + Action: 's3:PutObject', + Condition: { + StringEquals: { + 's3:x-amz-acl': 'bucket-owner-full-control', + 'aws:SourceArn': { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':cloudtrail:us-east-1:123456789012:trail/trailname123', + ], + ], + }, + }, + }, + Effect: 'Allow', + Principal: { + Service: 'cloudtrail.amazonaws.com', + }, + Resource: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'TrailS30071F172', + 'Arn', + ], + }, + '/AWSLogs/o-xxxxxxxxx/*', + ], + ], + }, + }, + ], + Version: '2012-10-17', + }, + }); + }); + test('encryption keys', () => { const stack = new Stack(); const key = new kms.Key(stack, 'key'); From f803cf620df28df111aa370e0f69439a1d1f87ff Mon Sep 17 00:00:00 2001 From: Sumu Pitchayan <35242245+sumupitchayan@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:23:40 -0500 Subject: [PATCH 17/31] fix(cli-integ): add regression patch for cli integ fix (#29313) Follow up to #29305 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk-testing/cli-integ/.gitignore | 2 +- .../cli-regression-patches/v2.130.0/NOTES.md | 1 + .../sam_cdk_integ_app/lib/nested-stack.js | 19 +++ .../sam_cdk_integ_app/lib/test-stack.js | 134 ++++++++++++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/NOTES.md create mode 100644 packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js create mode 100644 packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js diff --git a/packages/@aws-cdk-testing/cli-integ/.gitignore b/packages/@aws-cdk-testing/cli-integ/.gitignore index eb8b474f4ca2a..27bbbe26ae338 100644 --- a/packages/@aws-cdk-testing/cli-integ/.gitignore +++ b/packages/@aws-cdk-testing/cli-integ/.gitignore @@ -17,4 +17,4 @@ nyc.config.js .DS_Store -junit.xml +junit.xml \ No newline at end of file diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/NOTES.md b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/NOTES.md new file mode 100644 index 0000000000000..d2b0b6c31ba17 --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/NOTES.md @@ -0,0 +1 @@ +This patch brings the [fix](https://github.com/aws/aws-cdk/pull/29305) into the regression suite. \ No newline at end of file diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js new file mode 100644 index 0000000000000..8620fb693e4bf --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js @@ -0,0 +1,19 @@ +if (process.env.PACKAGE_LAYOUT_VERSION === '1') { + var { NestedStack } = require('@aws-cdk/core'); + var { Function, Runtime, Code } = require('@aws-cdk/aws-lambda'); +} else { + var { NestedStack } = require('aws-cdk-lib'); + var { Function, Runtime, Code } = require('aws-cdk-lib/aws-lambda'); +} + +class NestedStack1 extends NestedStack { + constructor(scope, id, props) { + super(scope, id, props); + new Function(this, 'FunctionPythonRuntime', { + runtime: Runtime.PYTHON_3_12, + code: Code.fromAsset('./src/python/Function'), + handler: 'app.lambda_handler', + }); + } +} +exports.NestedStack1 = NestedStack1; diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js new file mode 100644 index 0000000000000..3e9a071de8ff1 --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js @@ -0,0 +1,134 @@ +var path = require('path'); +var { NestedStack1 } = require('./nested-stack'); +if (process.env.PACKAGE_LAYOUT_VERSION === '1') { + var { Stack } = require('@aws-cdk/core'); + var { Runtime, LayerVersion, Code, Function, DockerImageFunction, DockerImageCode } = require('@aws-cdk/aws-lambda'); + var { SpecRestApi, ApiDefinition } = require('@aws-cdk/aws-apigateway'); + var { NodejsFunction } = require('@aws-cdk/aws-lambda-nodejs'); + var { GoFunction } = require('@aws-cdk/aws-lambda-go'); + var { PythonFunction, PythonLayerVersion } = require('@aws-cdk/aws-lambda-python'); + var { Role, ServicePrincipal, PolicyStatement } = require('@aws-cdk/aws-iam'); + var { RetentionDays } = require('@aws-cdk/aws-logs'); +} else { + var { Stack } = require('aws-cdk-lib'); + var { Runtime, LayerVersion, Code, Function, DockerImageFunction, DockerImageCode } = require('aws-cdk-lib/aws-lambda'); + var { SpecRestApi, ApiDefinition } = require('aws-cdk-lib/aws-apigateway'); + var { NodejsFunction } = require('aws-cdk-lib/aws-lambda-nodejs'); + var { GoFunction } = require('@aws-cdk/aws-lambda-go-alpha'); + var { PythonFunction, PythonLayerVersion } = require('@aws-cdk/aws-lambda-python-alpha'); + var { Role, ServicePrincipal, PolicyStatement } = require('aws-cdk-lib/aws-iam'); + var { RetentionDays } = require('aws-cdk-lib/aws-logs'); +} + +const isRunningOnCodeBuild = !!process.env.CODEBUILD_BUILD_ID; + +class CDKSupportDemoRootStack extends Stack{ + constructor(scope, id, props) { + super(scope, id, props); + // Python Runtime + // Layers + new PythonLayerVersion(this, 'PythonLayerVersion', { + compatibleRuntimes: [ + Runtime.PYTHON_3_12, + ], + entry: './src/python/Layer', + }); + new LayerVersion(this, 'LayerVersion', { + compatibleRuntimes: [ + Runtime.PYTHON_3_12, + ], + code: Code.fromAsset('./src/python/Layer'), + }); + new LayerVersion(this, 'BundledLayerVersionPythonRuntime', { + compatibleRuntimes: [ + Runtime.PYTHON_3_12, + ], + code: Code.fromAsset('./src/python/Layer', { + bundling: { + command: [ + '/bin/sh', + '-c', + 'rm -rf /tmp/asset-input && mkdir /tmp/asset-input && cp * /tmp/asset-input && cd /tmp/asset-input && pip install -r requirements.txt -t . && mkdir /asset-output/python && cp -R /tmp/asset-input/* /asset-output/python', + ], + image: Runtime.PYTHON_3_12.bundlingImage, + user: 'root', + } + }), + }); + + // ZIP package type Functions + new PythonFunction(this, 'PythonFunction', { + entry: './src/python/Function', + index: 'app.py', + handler: 'lambda_handler', + runtime: Runtime.PYTHON_3_12, + functionName: 'pythonFunc', + logRetention: RetentionDays.THREE_MONTHS, + }); + new Function(this, 'FunctionPythonRuntime', { + runtime: Runtime.PYTHON_3_12, + code: Code.fromAsset('./src/python/Function'), + handler: 'app.lambda_handler', + }); + new Function(this, 'BundledFunctionPythonRuntime', { + runtime: Runtime.PYTHON_3_12, + code: Code.fromAsset('./src/python/Function/', { + bundling: { + command: [ + '/bin/sh', + '-c', + 'rm -rf /tmp/asset-input && mkdir /tmp/asset-input && cp * /tmp/asset-input && cd /tmp/asset-input && pip install -r requirements.txt -t . && cp -R /tmp/asset-input/* /asset-output', + ], + image: Runtime.PYTHON_3_12.bundlingImage, + user: 'root', + } + }), + handler: 'app.lambda_handler', + }); + + // NodeJs Runtime + new NodejsFunction(this, 'NodejsFunction', { + entry: path.join(__dirname, '../src/nodejs/NodeJsFunctionConstruct/app.ts'), + depsLockFilePath: path.join(__dirname, '../src/nodejs/NodeJsFunctionConstruct/package-lock.json'), + bundling: { + forceDockerBundling: true, + }, + handler: 'lambdaHandler', + }); + + // Go Runtime + new GoFunction(this, 'GoFunction', { + entry: './src/go/GoFunctionConstruct', + bundling: { + forcedDockerBundling: true, + // Only use Google proxy in the CI tests, as it is blocked on workstations + goProxies: isRunningOnCodeBuild ? [GoFunction.GOOGLE_GOPROXY, 'direct'] : undefined, + }, + }); + + // Image Package Type Functions + new DockerImageFunction(this, 'DockerImageFunction', { + code: DockerImageCode.fromImageAsset('./src/docker/DockerImageFunctionConstruct', { + file: 'Dockerfile', + }), + }); + + // Spec Rest Api + new SpecRestApi(this, 'SpecRestAPI', { + apiDefinition: ApiDefinition.fromAsset('./src/rest-api-definition.yaml'), + }); + // Role to be used as credentials for the Spec rest APi + // it is used inside the spec rest api definition file + new Role(this, 'SpecRestApiRole', { + assumedBy: new ServicePrincipal('apigateway.amazonaws.com'), + roleName: 'SpecRestApiRole', + }).addToPolicy(new PolicyStatement({ + actions: ['lambda:InvokeFunction'], + resources: ['*'], + })); + + // Nested Stack + new NestedStack1(this, 'NestedStack', {}); + } +} +exports.CDKSupportDemoRootStack = CDKSupportDemoRootStack; From 6fe97ea2841412e98678c53c514e67ce6af130bf Mon Sep 17 00:00:00 2001 From: Evan K <113387406+evzzk@users.noreply.github.com> Date: Thu, 29 Feb 2024 08:12:41 -1000 Subject: [PATCH 18/31] docs(events): mention property requirements when creating custom events (#29287) ### Issue # (if applicable) Closes #. ### Reason for this change When creating an EventPattern for a custom event, a few properties are required. Documentation currently isn't clear on which properties are required. This change links to AWS documentation that describes the required properties for custom events. ### Description of changes Added text stating that some optional properties are required for custom events and provided link to docs. ### Description of how you validated changes No validation ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-events/lib/event-pattern.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts b/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts index 93076c7b51726..c4f37bdffe055 100644 --- a/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts +++ b/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts @@ -262,6 +262,9 @@ export class Match implements IResolvable { * - Number matching is at the string representation level. For example, 300, * 300.0, and 3.0e2 are not considered equal. * + * For custom events, some optional properties are required. For more information, see + * [Minimum information needed for a valid custom event](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events-structure.html#eb-custom-event). + * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html */ export interface EventPattern { From 2f720a1d4cea7b23efdab7f0031eacc1914a9c54 Mon Sep 17 00:00:00 2001 From: Ben Fradet Date: Thu, 29 Feb 2024 21:00:34 +0100 Subject: [PATCH 19/31] chore(rds): add clusterArn property to DatabaseCluster (#29133) ### Issue # (if applicable) ### Reason for this change This is to bring parity with #10741, we need the cluster arn to enable data api manually waiting for #28574. ### Description of changes This adds a clusterArn property to IDatabaseCluster ### Description of how you validated changes The changes have been validated through a unit test ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-lib/aws-rds/lib/cluster-ref.ts | 5 +++ packages/aws-cdk-lib/aws-rds/lib/cluster.ts | 12 +++++++ .../aws-cdk-lib/aws-rds/test/cluster.test.ts | 32 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster-ref.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster-ref.ts index 796e05d978573..a55a0c4f52396 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster-ref.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster-ref.ts @@ -50,6 +50,11 @@ export interface IDatabaseCluster extends IResource, ec2.IConnectable, secretsma */ readonly engine?: IClusterEngine; + /** + * The ARN of the database cluster + */ + readonly clusterArn: string; + /** * Add a new db proxy to this cluster. */ diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index b0a062776c496..b5d531f2dc7d9 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -457,6 +457,18 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC */ public abstract readonly connections: ec2.Connections; + /** + * The ARN of the cluster + */ + public get clusterArn(): string { + return Stack.of(this).formatArn({ + service: 'rds', + resource: 'cluster', + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + resourceName: this.clusterIdentifier, + }); + } + /** * Add a new db proxy to this cluster. */ diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index 585cd870181a3..b368b79e6836c 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -4052,6 +4052,38 @@ describe('cluster', () => { ], }); }); + + test('clusterArn property', () => { + // GIVEN + const stack = testStack(); + const vpc = ec2.Vpc.fromLookup(stack, 'VPC', { isDefault: true }); + const cluster = new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.auroraPostgres({ version: AuroraPostgresEngineVersion.VER_14_3 }), + instanceProps: { vpc }, + }); + const exportName = 'DbCluterArn'; + + // WHEN + new cdk.CfnOutput(stack, exportName, { + exportName, + value: cluster.clusterArn, + }); + + // THEN + expect( + stack.resolve(cluster.clusterArn), + ).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':rds:us-test-1:12345:cluster:', + { Ref: 'DatabaseB269D8BB' }, + ], + ], + }); + }); }); test.each([ From fdacbe06ff55832f285bfb1adb37245b47aef771 Mon Sep 17 00:00:00 2001 From: Sumu Pitchayan <35242245+sumupitchayan@users.noreply.github.com> Date: Thu, 29 Feb 2024 16:07:29 -0500 Subject: [PATCH 20/31] fix(cli): add skip-tests.txt file for v2.130.0 (#29320) Follow-up to #29313 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../resources/cli-regression-patches/v2.130.0/skip-tests.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/skip-tests.txt diff --git a/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/skip-tests.txt b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/skip-tests.txt new file mode 100644 index 0000000000000..4271078bdc89c --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/resources/cli-regression-patches/v2.130.0/skip-tests.txt @@ -0,0 +1,5 @@ +# The fix for upgrading lambda runtimes from python 3.7 to 3.12 is not relased yet: https://github.com/aws/aws-cdk/pull/29305 +# Skipping the bootstrapping test as it is flakey; only doing so to get the 2.131.0 release out this week. + +sam can locally test the synthesized cdk application +switch on termination protection, switch is left alone on re-bootstrap \ No newline at end of file From 3cbad4a2164a41f5529e04aba4d15085c71b7849 Mon Sep 17 00:00:00 2001 From: kazuho cryer-shinozuka Date: Fri, 1 Mar 2024 08:27:47 +0900 Subject: [PATCH 21/31] feat(ec2): support for the credit configuration mode for burstable instances (#28728) In this PR, I have enabled the setting of the [credit configuration mode](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html#key-concepts) for EC2 instances and NAT instances in burstable performance instances. ```ts // for EC2 instance new Instance(stack, 'Instance', { vpc, machineImage: new AmazonLinuxImage(), instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), creditSpecification: CpuCredits.STANDARD, // added }); // for NAT instance const natInstanceProvider = NatProvider.instance({ instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), machineImage: new AmazonLinuxImage(), creditSpecification: CpuCredits.STANDARD, // added }); new Vpc(stack, 'VPC', { natGatewayProvider: natInstanceProvider, }); ``` Closes #19166. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../__entrypoint__.js | 147 +++ .../index.js | 1 + .../integ.instance-credit.js.snapshot/cdk.out | 1 + ...efaultTestDeployAssert5516EAF1.assets.json | 19 + ...aultTestDeployAssert5516EAF1.template.json | 36 + .../integ-ec2-instance-credit.assets.json | 32 + .../integ-ec2-instance-credit.template.json | 553 +++++++++++ .../integ.json | 12 + .../manifest.json | 257 +++++ .../tree.json | 843 +++++++++++++++++ .../aws-ec2/test/integ.instance-credit.ts | 36 + .../__entrypoint__.js | 147 +++ .../index.js | 1 + ...ws-cdk-vpc-nat-instance-credit.assets.json | 32 + ...-cdk-vpc-nat-instance-credit.template.json | 586 ++++++++++++ .../cdk.out | 1 + .../integ.json | 12 + ...efaultTestDeployAssert24D5C536.assets.json | 19 + ...aultTestDeployAssert24D5C536.template.json | 36 + .../manifest.json | 269 ++++++ .../tree.json | 892 ++++++++++++++++++ .../aws-ec2/test/integ.nat-instance-credit.ts | 27 + packages/aws-cdk-lib/aws-ec2/README.md | 30 + .../aws-cdk-lib/aws-ec2/lib/instance-types.ts | 7 + packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 15 + packages/aws-cdk-lib/aws-ec2/lib/nat.ts | 10 + .../aws-cdk-lib/aws-ec2/test/instance.test.ts | 30 + packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts | 29 + 28 files changed, 4080 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.ts create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js new file mode 100644 index 0000000000000..1e64dba70bdc0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js new file mode 100644 index 0000000000000..013bcaffd8fe5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js @@ -0,0 +1 @@ +"use strict";var I=Object.create;var t=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty;var G=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},n=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of P(e))!l.call(r,s)&&s!==o&&t(r,s,{get:()=>e[s],enumerable:!(i=y(e,s))||i.enumerable});return r};var R=(r,e,o)=>(o=r!=null?I(g(r)):{},n(e||!r||!r.__esModule?t(o,"default",{value:r,enumerable:!0}):o,r)),S=r=>n(t({},"__esModule",{value:!0}),r);var k={};G(k,{handler:()=>f});module.exports=S(k);var a=R(require("@aws-sdk/client-ec2")),u=new a.EC2({});function c(r,e){return{GroupId:r,IpPermissions:[{UserIdGroupPairs:[{GroupId:r,UserId:e}],IpProtocol:"-1"}]}}function d(r){return{GroupId:r,IpPermissions:[{IpRanges:[{CidrIp:"0.0.0.0/0"}],IpProtocol:"-1"}]}}async function f(r){let e=r.ResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.Account;switch(r.RequestType){case"Create":return p(e,o);case"Update":return h(r);case"Delete":return m(e,o)}}async function h(r){let e=r.OldResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.DefaultSecurityGroupId;e!==o&&(await m(e,r.ResourceProperties.Account),await p(o,r.ResourceProperties.Account))}async function p(r,e){try{await u.revokeSecurityGroupEgress(d(r))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}try{await u.revokeSecurityGroupIngress(c(r,e))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}}async function m(r,e){await u.authorizeSecurityGroupIngress(c(r,e)),await u.authorizeSecurityGroupEgress(d(r))}0&&(module.exports={handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json new file mode 100644 index 0000000000000..0d00b28b63a59 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "instancetestDefaultTestDeployAssert5516EAF1.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.assets.json new file mode 100644 index 0000000000000..0d4d06a1507ba --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.assets.json @@ -0,0 +1,32 @@ +{ + "version": "36.0.0", + "files": { + "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292": { + "source": { + "path": "asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "678e69656af4f2048e81e493072e381c3d08322474b0ffd99f40e79fde9cb119": { + "source": { + "path": "integ-ec2-instance-credit.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "678e69656af4f2048e81e493072e381c3d08322474b0ffd99f40e79fde9cb119.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.template.json new file mode 100644 index 0000000000000..5e0829bedae5c --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ-ec2-instance-credit.template.json @@ -0,0 +1,553 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCIsolatedSubnet1SubnetEBD00FC6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCIsolatedSubnet1RouteTableEB156210": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCIsolatedSubnet1RouteTableAssociationA2D18F7C": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCIsolatedSubnet1RouteTableEB156210" + }, + "SubnetId": { + "Ref": "VPCIsolatedSubnet1SubnetEBD00FC6" + } + } + }, + "VPCIsolatedSubnet2Subnet4B1C8CAA": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/IsolatedSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCIsolatedSubnet2RouteTable9B4F78DC": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC/IsolatedSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCIsolatedSubnet2RouteTableAssociation7BF8E0EB": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCIsolatedSubnet2RouteTable9B4F78DC" + }, + "SubnetId": { + "Ref": "VPCIsolatedSubnet2Subnet4B1C8CAA" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCRestrictDefaultSecurityGroupCustomResource59474679": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "VPCB9E5F0B4", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "VPCB9E5F0B4", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": "nodejs18.x", + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + }, + "IntegSg68DC2C7E": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ec2-instance-credit/IntegSg", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + }, + { + "CidrIpv6": "::/0", + "Description": "Allow all outbound ipv6 traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "InstanceInstanceRoleE9785DE5": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/Instance" + } + ] + } + }, + "InstanceInstanceProfileAB5AEF02": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "InstanceC1063A87": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CreditSpecification": { + "CPUCredits": "standard" + }, + "IamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.nano", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "IntegSg68DC2C7E", + "GroupId" + ] + } + ], + "SubnetId": { + "Ref": "VPCIsolatedSubnet1SubnetEBD00FC6" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance-credit/Instance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "DependsOn": [ + "InstanceInstanceRoleE9785DE5" + ] + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ.json new file mode 100644 index 0000000000000..8e6612fb2b3f5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "instance-test/DefaultTest": { + "stacks": [ + "integ-ec2-instance-credit" + ], + "assertionStack": "instance-test/DefaultTest/DeployAssert", + "assertionStackName": "instancetestDefaultTestDeployAssert5516EAF1" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/manifest.json new file mode 100644 index 0000000000000..d83d941bf565d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/manifest.json @@ -0,0 +1,257 @@ +{ + "version": "36.0.0", + "artifacts": { + "integ-ec2-instance-credit.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-ec2-instance-credit.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-ec2-instance-credit": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-ec2-instance-credit.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/678e69656af4f2048e81e493072e381c3d08322474b0ffd99f40e79fde9cb119.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-ec2-instance-credit.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-ec2-instance-credit.assets" + ], + "metadata": { + "/integ-ec2-instance-credit/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1SubnetB4246D30" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableFEE4B781" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableAssociation0B0896DC" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1DefaultRoute91CEF279" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2Subnet74179F39" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTable6F1A15F1" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTableAssociation5A808732" + } + ], + "/integ-ec2-instance-credit/VPC/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2DefaultRouteB7481BBA" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet1SubnetEBD00FC6" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet1RouteTableEB156210" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet1RouteTableAssociationA2D18F7C" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet2Subnet4B1C8CAA" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet2RouteTable9B4F78DC" + } + ], + "/integ-ec2-instance-credit/VPC/IsolatedSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIsolatedSubnet2RouteTableAssociation7BF8E0EB" + } + ], + "/integ-ec2-instance-credit/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/integ-ec2-instance-credit/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/integ-ec2-instance-credit/VPC/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCRestrictDefaultSecurityGroupCustomResource59474679" + } + ], + "/integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/integ-ec2-instance-credit/IntegSg/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegSg68DC2C7E" + } + ], + "/integ-ec2-instance-credit/Instance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceRoleE9785DE5" + } + ], + "/integ-ec2-instance-credit/Instance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceProfileAB5AEF02" + } + ], + "/integ-ec2-instance-credit/Instance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceC1063A87" + } + ], + "/integ-ec2-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/integ-ec2-instance-credit/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-ec2-instance-credit/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-ec2-instance-credit" + }, + "instancetestDefaultTestDeployAssert5516EAF1.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "instancetestDefaultTestDeployAssert5516EAF1.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "instancetestDefaultTestDeployAssert5516EAF1": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "instancetestDefaultTestDeployAssert5516EAF1.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "instancetestDefaultTestDeployAssert5516EAF1.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "instancetestDefaultTestDeployAssert5516EAF1.assets" + ], + "metadata": { + "/instance-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/instance-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "instance-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/tree.json new file mode 100644 index 0000000000000..32e884c1c3a91 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.js.snapshot/tree.json @@ -0,0 +1,843 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-ec2-instance-credit": { + "id": "integ-ec2-instance-credit", + "path": "integ-ec2-instance-credit", + "children": { + "VPC": { + "id": "VPC", + "path": "integ-ec2-instance-credit/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance-credit/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "subnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-instance-credit/VPC/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "IsolatedSubnet1": { + "id": "IsolatedSubnet1", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/IsolatedSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/IsolatedSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCIsolatedSubnet1RouteTableEB156210" + }, + "subnetId": { + "Ref": "VPCIsolatedSubnet1SubnetEBD00FC6" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IsolatedSubnet2": { + "id": "IsolatedSubnet2", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/IsolatedSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC/IsolatedSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance-credit/VPC/IsolatedSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCIsolatedSubnet2RouteTable9B4F78DC" + }, + "subnetId": { + "Ref": "VPCIsolatedSubnet2Subnet4B1C8CAA" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-ec2-instance-credit/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-ec2-instance-credit/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "integ-ec2-instance-credit/VPC/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "integ-ec2-instance-credit/VPC/RestrictDefaultSecurityGroupCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "integ-ec2-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "IntegSg": { + "id": "IntegSg", + "path": "integ-ec2-instance-credit/IntegSg", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance-credit/IntegSg/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "integ-ec2-instance-credit/IntegSg", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + }, + { + "ipProtocol": "-1", + "cidrIpv6": "::/0", + "description": "Allow all outbound ipv6 traffic by default" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Instance": { + "id": "Instance", + "path": "integ-ec2-instance-credit/Instance", + "children": { + "InstanceRole": { + "id": "InstanceRole", + "path": "integ-ec2-instance-credit/Instance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "integ-ec2-instance-credit/Instance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance-credit/Instance/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/Instance" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "integ-ec2-instance-credit/Instance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance-credit/Instance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "creditSpecification": { + "cpuCredits": "standard" + }, + "iamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.nano", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "IntegSg68DC2C7E", + "GroupId" + ] + } + ], + "subnetId": { + "Ref": "VPCIsolatedSubnet1SubnetEBD00FC6" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance-credit/Instance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Instance", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ec2-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ec2-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-ec2-instance-credit/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-ec2-instance-credit/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "instance-test": { + "id": "instance-test", + "path": "instance-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "instance-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "instance-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "instance-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "instance-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "instance-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.ts new file mode 100644 index 0000000000000..aa1e1f586f124 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-credit.ts @@ -0,0 +1,36 @@ +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; + +const app = new cdk.App(); + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const vpc = new ec2.Vpc(this, 'VPC', { + cidr: '10.0.0.0/16', + natGateways: 0, + maxAzs: 3, + }); + + const securityGroup = new ec2.SecurityGroup(this, 'IntegSg', { + vpc, + allowAllIpv6Outbound: true, + }); + + new ec2.Instance(this, 'Instance', { + vpc, + securityGroup, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), + machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), + creditSpecification: ec2.CpuCredits.STANDARD, + }); + } +} + +const testCase = new TestStack(app, 'integ-ec2-instance-credit'); + +new IntegTest(app, 'instance-test', { + testCases: [testCase], +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js new file mode 100644 index 0000000000000..1e64dba70bdc0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js new file mode 100644 index 0000000000000..013bcaffd8fe5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js @@ -0,0 +1 @@ +"use strict";var I=Object.create;var t=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty;var G=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},n=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of P(e))!l.call(r,s)&&s!==o&&t(r,s,{get:()=>e[s],enumerable:!(i=y(e,s))||i.enumerable});return r};var R=(r,e,o)=>(o=r!=null?I(g(r)):{},n(e||!r||!r.__esModule?t(o,"default",{value:r,enumerable:!0}):o,r)),S=r=>n(t({},"__esModule",{value:!0}),r);var k={};G(k,{handler:()=>f});module.exports=S(k);var a=R(require("@aws-sdk/client-ec2")),u=new a.EC2({});function c(r,e){return{GroupId:r,IpPermissions:[{UserIdGroupPairs:[{GroupId:r,UserId:e}],IpProtocol:"-1"}]}}function d(r){return{GroupId:r,IpPermissions:[{IpRanges:[{CidrIp:"0.0.0.0/0"}],IpProtocol:"-1"}]}}async function f(r){let e=r.ResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.Account;switch(r.RequestType){case"Create":return p(e,o);case"Update":return h(r);case"Delete":return m(e,o)}}async function h(r){let e=r.OldResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.DefaultSecurityGroupId;e!==o&&(await m(e,r.ResourceProperties.Account),await p(o,r.ResourceProperties.Account))}async function p(r,e){try{await u.revokeSecurityGroupEgress(d(r))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}try{await u.revokeSecurityGroupIngress(c(r,e))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}}async function m(r,e){await u.authorizeSecurityGroupIngress(c(r,e)),await u.authorizeSecurityGroupEgress(d(r))}0&&(module.exports={handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.assets.json new file mode 100644 index 0000000000000..c9ec4fa610889 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.assets.json @@ -0,0 +1,32 @@ +{ + "version": "36.0.0", + "files": { + "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292": { + "source": { + "path": "asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "51d7c84c8f1dc4fc57a1bf2e4ff039bb2c4332999eb3c62f4891975f6892d61b": { + "source": { + "path": "aws-cdk-vpc-nat-instance-credit.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "51d7c84c8f1dc4fc57a1bf2e4ff039bb2c4332999eb3c62f4891975f6892d61b.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.template.json new file mode 100644 index 0000000000000..ea7c7446bcee7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/aws-cdk-vpc-nat-instance-credit.template.json @@ -0,0 +1,586 @@ +{ + "Resources": { + "MyVpcF9F0CA6F": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "MyVpcPublicSubnet1SubnetF6608456": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet1RouteTableC46AB2F4": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + }, + "SubnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + } + } + }, + "MyVpcPublicSubnet1DefaultRoute95FDF9EB": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "RouteTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + }, + "DependsOn": [ + "MyVpcVPCGW488ACE0D" + ] + }, + "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "MyVpcNatRoleF1616EE9" + } + ] + } + }, + "MyVpcPublicSubnet1NatInstance8E94E5F7": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CreditSpecification": { + "CPUCredits": "standard" + }, + "IamInstanceProfile": { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.large", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "SourceDestCheck": false, + "SubnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "DependsOn": [ + "MyVpcNatRoleF1616EE9" + ] + }, + "MyVpcPublicSubnet2Subnet492B6BFB": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet2RouteTable1DF17386": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet2RouteTableAssociation227DE78D": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + }, + "SubnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + } + } + }, + "MyVpcPublicSubnet2DefaultRoute052936F6": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "RouteTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + } + }, + "DependsOn": [ + "MyVpcVPCGW488ACE0D" + ] + }, + "MyVpcPrivateSubnet1Subnet5057CF7E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTable8819E6E2": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + } + }, + "MyVpcPrivateSubnet1DefaultRouteA8CDE2FA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "InstanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + } + }, + "MyVpcPrivateSubnet2Subnet0040C983": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableCEDCEECE": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableAssociation86A610DA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + } + }, + "MyVpcPrivateSubnet2DefaultRoute9CE96294": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "InstanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + } + }, + "MyVpcIGW5C4A4F63": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "MyVpcVPCGW488ACE0D": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcNatSecurityGroupAA76397E": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security Group for NAT instances", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "from 0.0.0.0/0:ALL TRAFFIC", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcNatRoleF1616EE9": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": "nodejs18.x", + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integ.json new file mode 100644 index 0000000000000..c3070167c9f95 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integ-test/DefaultTest": { + "stacks": [ + "aws-cdk-vpc-nat-instance-credit" + ], + "assertionStack": "integ-test/DefaultTest/DeployAssert", + "assertionStackName": "integtestDefaultTestDeployAssert24D5C536" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json new file mode 100644 index 0000000000000..3555eb95abb24 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestDefaultTestDeployAssert24D5C536.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/manifest.json new file mode 100644 index 0000000000000..8ba0fbb01b689 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/manifest.json @@ -0,0 +1,269 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-vpc-nat-instance-credit.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-vpc-nat-instance-credit.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-vpc-nat-instance-credit": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-vpc-nat-instance-credit.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/51d7c84c8f1dc4fc57a1bf2e4ff039bb2c4332999eb3c62f4891975f6892d61b.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-vpc-nat-instance-credit.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-vpc-nat-instance-credit.assets" + ], + "metadata": { + "/aws-cdk-vpc-nat-instance-credit/MyVpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcF9F0CA6F" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1SubnetF6608456" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1DefaultRoute95FDF9EB" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1NatInstance8E94E5F7" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2Subnet492B6BFB" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTable1DF17386" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTableAssociation227DE78D" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2DefaultRoute052936F6" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1DefaultRouteA8CDE2FA" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2Subnet0040C983" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableAssociation86A610DA" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2DefaultRoute9CE96294" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcIGW5C4A4F63" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcVPCGW488ACE0D" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/NatSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcNatSecurityGroupAA76397E" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/NatRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcNatRoleF1616EE9" + } + ], + "/aws-cdk-vpc-nat-instance-credit/MyVpc/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62" + } + ], + "/aws-cdk-vpc-nat-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/aws-cdk-vpc-nat-instance-credit/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-vpc-nat-instance-credit/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-vpc-nat-instance-credit" + }, + "integtestDefaultTestDeployAssert24D5C536.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestDefaultTestDeployAssert24D5C536.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestDefaultTestDeployAssert24D5C536": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestDefaultTestDeployAssert24D5C536.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "metadata": { + "/integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/tree.json new file mode 100644 index 0000000000000..39127d4c5493a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.js.snapshot/tree.json @@ -0,0 +1,892 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-vpc-nat-instance-credit": { + "id": "aws-cdk-vpc-nat-instance-credit", + "path": "aws-cdk-vpc-nat-instance-credit", + "children": { + "MyVpc": { + "id": "MyVpc", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + }, + "subnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "routeTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "NatInstance": { + "id": "NatInstance", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance", + "children": { + "InstanceProfile": { + "id": "InstanceProfile", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "MyVpcNatRoleF1616EE9" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "creditSpecification": { + "cpuCredits": "standard" + }, + "iamInstanceProfile": { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.large", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "sourceDestCheck": false, + "subnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet1/NatInstance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Instance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + }, + "subnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "routeTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + }, + "subnetId": { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "instanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "routeTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + }, + "subnetId": { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "instanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "routeTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "NatSecurityGroup": { + "id": "NatSecurityGroup", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/NatSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/NatSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "Security Group for NAT instances", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "-1", + "description": "from 0.0.0.0/0:ALL TRAFFIC" + } + ], + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "NatRole": { + "id": "NatRole", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/NatRole", + "children": { + "ImportNatRole": { + "id": "ImportNatRole", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/NatRole/ImportNatRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/NatRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instance-credit/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-vpc-nat-instance-credit/MyVpc/RestrictDefaultSecurityGroupCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "aws-cdk-vpc-nat-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "aws-cdk-vpc-nat-instance-credit/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "aws-cdk-vpc-nat-instance-credit/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-vpc-nat-instance-credit/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-vpc-nat-instance-credit/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integ-test": { + "id": "integ-test", + "path": "integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.ts new file mode 100644 index 0000000000000..3d3364a90ed9d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instance-credit.ts @@ -0,0 +1,27 @@ +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +class NatInstanceStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const natInstanceProvider = ec2.NatProvider.instance({ + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.LARGE), + machineImage: new ec2.AmazonLinuxImage(), + creditSpecification: ec2.CpuCredits.STANDARD, + }); + + new ec2.Vpc(this, 'MyVpc', { + natGatewayProvider: natInstanceProvider, + natGateways: 1, + }); + } +} + +const app = new cdk.App(); +const testCase = new NatInstanceStack(app, 'aws-cdk-vpc-nat-instance-credit', {}); + +new IntegTest(app, 'integ-test', { + testCases: [testCase], +}); diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index b55688feeb403..fef870d937a84 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -1757,6 +1757,36 @@ Note to set `mapPublicIpOnLaunch` to true in the `subnetConfiguration`. Additionally, IPv6 support varies by instance type. Most instance types have IPv6 support with exception of m1-m3, c1, g2, and t1.micro. A full list can be found here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI. +### Credit configuration modes for burstable instances + +You can set the [credit configuration mode](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html) for burstable instances (T2, T3, T3a and T4g instance types): + +```ts +declare const vpc: ec2.Vpc; + +const instance = new ec2.Instance(this, 'Instance', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO), + machineImage: ec2.MachineImage.latestAmazonLinux2(), + vpc: vpc, + creditSpecification: ec2.CpuCredits.STANDARD, +}); +``` + +It is also possible to set the credit configuration mode for NAT instances. + +```ts +const natInstanceProvider = ec2.NatProvider.instance({ + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T4G, ec2.InstanceSize.LARGE), + machineImage: new ec2.AmazonLinuxImage(), + creditSpecification: ec2.CpuCredits.UNLIMITED, +}); +new ec2.Vpc(this, 'VPC', { + natGatewayProvider: natInstanceProvider, +}); +``` + +**Note**: `CpuCredits.UNLIMITED` mode is not supported for T3 instances that are launched on a Dedicated Host. + ## VPC Flow Logs VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (). diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts index 2cdf1b98c9bd9..bcf63f59a0260 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts @@ -1555,4 +1555,11 @@ export class InstanceType { return instanceClassId[1] === otherInstanceClassId[1]; } + /** + * Return whether this instance type is a burstable instance type + */ + public isBurstable(): boolean { + return this.instanceTypeIdentifier.startsWith('t3') || this.instanceTypeIdentifier.startsWith('t4g') || this.instanceTypeIdentifier.startsWith('t2'); + } + } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts index d0f064f85081d..44e617604eb8f 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts @@ -6,6 +6,7 @@ import { Connections, IConnectable } from './connections'; import { CfnInstance } from './ec2.generated'; import { InstanceType } from './instance-types'; import { IKeyPair } from './key-pair'; +import { CpuCredits } from './launch-template'; import { IMachineImage, OperatingSystemType } from './machine-image'; import { instanceBlockDeviceMappings } from './private/ebs-util'; import { ISecurityGroup, SecurityGroup } from './security-group'; @@ -295,6 +296,14 @@ export interface InstanceProps { * @default - public IP address is automatically assigned based on default behavior */ readonly associatePublicIpAddress?: boolean; + + /** + * Specifying the CPU credit type for burstable EC2 instance types (T2, T3, T3a, etc). + * The unlimited CPU credit option is not supported for T3 instances with a dedicated host. + * + * @default - T2 instances are standard, while T3, T4g, and T3a instances are unlimited. + */ + readonly creditSpecification?: CpuCredits; } /** @@ -370,6 +379,11 @@ export class Instance extends Resource implements IInstance { throw new Error('Cannot specify both of \'keyName\' and \'keyPair\'; prefer \'keyPair\''); } + // if credit specification is set, then the instance type must be burstable + if (props.creditSpecification && !props.instanceType.isBurstable()) { + throw new Error(`creditSpecification is supported only for T4g, T3a, T3, T2 instance type, got: ${props.instanceType.toString()}`); + } + if (props.securityGroup) { this.securityGroup = props.securityGroup; } else { @@ -459,6 +473,7 @@ export class Instance extends Resource implements IInstance { privateIpAddress: networkInterfaces ? undefined : props.privateIpAddress, propagateTagsToVolumeOnCreation: props.propagateTagsToVolumeOnCreation, monitoring: props.detailedMonitoring, + creditSpecification: props.creditSpecification ? { cpuCredits: props.creditSpecification } : undefined, }); this.instance.node.addDependency(this.role); diff --git a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts index ca0960c480a6b..48c2ac0de94f2 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts @@ -2,6 +2,7 @@ import { Connections, IConnectable } from './connections'; import { Instance } from './instance'; import { InstanceType } from './instance-types'; import { IKeyPair } from './key-pair'; +import { CpuCredits } from './launch-template'; import { IMachineImage, LookupMachineImage } from './machine-image'; import { Port } from './port'; import { ISecurityGroup, SecurityGroup } from './security-group'; @@ -218,6 +219,14 @@ export interface NatInstanceProps { * @default NatTrafficDirection.INBOUND_AND_OUTBOUND */ readonly defaultAllowedTraffic?: NatTrafficDirection; + + /** + * Specifying the CPU credit type for burstable EC2 instance types (T2, T3, T3a, etc). + * The unlimited CPU credit option is not supported for T3 instances with dedicated host (`host`) tenancy. + * + * @default - T2 instances are standard, while T3, T4g, and T3a instances are unlimited. + */ + readonly creditSpecification?: CpuCredits; } /** @@ -323,6 +332,7 @@ export class NatInstanceProvider extends NatProvider implements IConnectable { role, keyPair: this.props.keyPair, keyName: this.props.keyName, + creditSpecification: this.props.creditSpecification, }); // NAT instance routes all traffic, both ways this.gateways.add(sub.availabilityZone, natInstance); diff --git a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts index 43b7e4183182d..8ae81b63f7b1b 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts @@ -25,6 +25,7 @@ import { WindowsVersion, KeyPair, KeyPairType, + CpuCredits, } from '../lib'; let stack: Stack; @@ -613,6 +614,35 @@ describe('instance', () => { }); }); + test('burstable instance with explicit credit specification', () => { + // WHEN + new Instance(stack, 'Instance', { + vpc, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + creditSpecification: CpuCredits.STANDARD, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + InstanceType: 't3.large', + CreditSpecification: { + CPUCredits: 'standard', + }, + }); + }); + + test('throw if creditSpecification is defined for a non-burstable instance type', () => { + // THEN + expect(() => { + new Instance(stack, 'Instance', { + vpc, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.M5, InstanceSize.LARGE), + creditSpecification: CpuCredits.STANDARD, + }); + }).toThrow('creditSpecification is supported only for T4g, T3a, T3, T2 instance type, got: m5.large'); + }); }); test('add CloudFormation Init to instance', () => { diff --git a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts index f51385c31ba13..495c0d2ee4162 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts @@ -31,6 +31,10 @@ import { Ipv6Addresses, InterfaceVpcEndpointAwsService, IpProtocol, + AmazonLinuxImage, + CpuCredits, + InstanceClass, + InstanceSize, } from '../lib'; describe('vpc', () => { @@ -1659,6 +1663,31 @@ describe('vpc', () => { }); + test('burstable instance with explicit credit specification', () => { + // GIVEN + const stack = getTestStack(); + + // WHEN + const natInstanceProvider = NatProvider.instance({ + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + machineImage: new AmazonLinuxImage(), + creditSpecification: CpuCredits.STANDARD, + }); + new Vpc(stack, 'VPC', { + natGatewayProvider: natInstanceProvider, + // The 'natGateways' parameter now controls the number of NAT instances + natGateways: 1, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + InstanceType: 't3.large', + CreditSpecification: { + CPUCredits: 'standard', + }, + }); + }); + }); describe('Network ACL association', () => { From aca68ba1cb1768c5bfd09db7dd83d83295ff5b96 Mon Sep 17 00:00:00 2001 From: Michael Sambol Date: Thu, 29 Feb 2024 17:10:22 -0700 Subject: [PATCH 22/31] fix(ecs): stack name can result in noncompliant capacity provider name (#29235) Closes #29151. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 21 +++++++++++---- .../aws-cdk-lib/aws-ecs/test/cluster.test.ts | 27 ++++++++++++++++++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index 03a5f2c852242..95979e740f8b2 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -11,7 +11,7 @@ import * as kms from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cloudmap from '../../aws-servicediscovery'; -import { Duration, IResource, Resource, Stack, Aspects, ArnFormat, IAspect, Token } from '../../core'; +import { Duration, IResource, Resource, Stack, Aspects, ArnFormat, IAspect, Token, Names } from '../../core'; const CLUSTER_SYMBOL = Symbol.for('@aws-cdk/aws-ecs/lib/cluster.Cluster'); @@ -1168,6 +1168,8 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt * The name of the capacity provider. If a name is specified, * it cannot start with `aws`, `ecs`, or `fargate`. If no name is specified, * a default name in the CFNStackName-CFNResourceName-RandomString format is used. + * If the stack name starts with `aws`, `ecs`, or `fargate`, a unique resource name + * is generated that starts with `cp-`. * * @default CloudFormation-generated name */ @@ -1288,6 +1290,7 @@ export class AsgCapacityProvider extends Construct { constructor(scope: Construct, id: string, props: AsgCapacityProviderProps) { super(scope, id); + let capacityProviderName = props.capacityProviderName; this.autoScalingGroup = props.autoScalingGroup as autoscaling.AutoScalingGroup; this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2; this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole; @@ -1306,9 +1309,17 @@ export class AsgCapacityProvider extends Construct { this.autoScalingGroup.protectNewInstancesFromScaleIn(); } - if (props.capacityProviderName) { - if (!(/^(?!aws|ecs|fargate).+/gm.test(props.capacityProviderName))) { - throw new Error(`Invalid Capacity Provider Name: ${props.capacityProviderName}, If a name is specified, it cannot start with aws, ecs, or fargate.`); + const capacityProviderNameRegex = /^(?!aws|ecs|fargate).+/gm; + if (capacityProviderName) { + if (!(capacityProviderNameRegex.test(capacityProviderName))) { + throw new Error(`Invalid Capacity Provider Name: ${capacityProviderName}, If a name is specified, it cannot start with aws, ecs, or fargate.`); + } + } else { + if (!(capacityProviderNameRegex.test(Stack.of(this).stackName))) { + // name cannot start with 'aws|ecs|fargate', so append 'cp-' + // 255 is the max length, subtract 3 because of 'cp-' + // if the regex condition isn't met, CFN will name the capacity provider + capacityProviderName = 'cp-' + Names.uniqueResourceName(this, { maxLength: 252, allowedSpecialCharacters: '-_' }); } } @@ -1319,7 +1330,7 @@ export class AsgCapacityProvider extends Construct { } const capacityProvider = new CfnCapacityProvider(this, id, { - name: props.capacityProviderName, + name: capacityProviderName, autoScalingGroupProvider: { autoScalingGroupArn: this.autoScalingGroup.autoScalingGroupName, managedScaling: props.enableManagedScaling === false ? undefined : { diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index 091b8f8ad469d..260cd89b60c9c 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -2928,7 +2928,7 @@ test('can add ASG capacity via Capacity Provider by not specifying machineImageT }); -test('throws when ASG Capacity Provider with capacityProviderName starting with aws, ecs or faragte', () => { +test('throws when ASG Capacity Provider with capacityProviderName starting with aws, ecs or fargate', () => { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); @@ -2965,6 +2965,31 @@ test('throws when ASG Capacity Provider with capacityProviderName starting with }).toThrow(/Invalid Capacity Provider Name: ecscp, If a name is specified, it cannot start with aws, ecs, or fargate./); }); +test('throws when ASG Capacity Provider with no capacityProviderName but stack name starting with aws, ecs or fargate', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'ecscp'); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + const autoScalingGroupAl2 = new autoscaling.AutoScalingGroup(stack, 'asgal2', { + vpc, + instanceType: new ec2.InstanceType('bogus'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + + expect(() => { + // WHEN Capacity Provider when stack name starts with ecs. + const capacityProvider = new ecs.AsgCapacityProvider(stack, 'provideral2-2', { + autoScalingGroup: autoScalingGroupAl2, + enableManagedTerminationProtection: false, + }); + + cluster.addAsgCapacityProvider(capacityProvider); + + }).not.toThrow(); +}); + test('throws when InstanceWarmupPeriod is less than 0', () => { // GIVEN const app = new cdk.App(); From 92a31fa0dc25708662cfb814eb69a951a23c518e Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:05:25 -0800 Subject: [PATCH 23/31] chore: update Contributors File (#29324) Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action --- CONTRIBUTORS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 412a39716f666..efa22129c850b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -16,11 +16,11 @@ Shout out to our top contributors! - [NetaNir](https://github.com/NetaNir) - [comcalvi](https://github.com/comcalvi) - [robertd](https://github.com/robertd) -- [MrArnoldPalmer](https://github.com/MrArnoldPalmer) - [pahud](https://github.com/pahud) +- [MrArnoldPalmer](https://github.com/MrArnoldPalmer) - [TheRealAmazonKendra](https://github.com/TheRealAmazonKendra) -- [peterwoodworth](https://github.com/peterwoodworth) - [lpizzinidev](https://github.com/lpizzinidev) +- [peterwoodworth](https://github.com/peterwoodworth) - [go-to-k](https://github.com/go-to-k) - [colifran](https://github.com/colifran) - [nija-at](https://github.com/nija-at) @@ -29,4 +29,4 @@ Shout out to our top contributors! - [jumic](https://github.com/jumic) -_Last updated: Thu, 01 Feb 24 00:09:34 +0000_ \ No newline at end of file +_Last updated: Fri, 01 Mar 24 00:09:32 +0000_ \ No newline at end of file From 985c7e4d9da583cb43479db3258723ba93faca3c Mon Sep 17 00:00:00 2001 From: "k.goto" <24818752+go-to-k@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:34:22 +0900 Subject: [PATCH 24/31] fix(ec2): internet gateway is created even if public subnets are reserved (#28607) This PR fixes that Internet Gateway will be created even if (all) public subnets are reserved. The `reserved` option is for not actually creating subnet resources. So IGW should not be created if all public subnets are reserved, because there is no public subnets in the VPC. It would be appropriate to consider the `reserved` option since [we originally did not want to create an IGW if there was no public subnets](https://github.com/aws/aws-cdk/blob/v2.118.0/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts#L1493-L1497). Also, if this bug is not fixed, it will go to the [code where the NatGateway is created](https://github.com/aws/aws-cdk/blob/v2.118.0/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts#L1513-L1517) without public subnets. (This will be stopped with another error, but...) Closes #28593. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../__entrypoint__.js | 147 +++++++ .../index.js | 1 + ...ec2-vpc-reserved-public-subnet.assets.json | 32 ++ ...2-vpc-reserved-public-subnet.template.json | 283 +++++++++++++ .../cdk.out | 1 + .../integ.json | 12 + ...efaultTestDeployAssert469B3DFB.assets.json | 19 + ...aultTestDeployAssert469B3DFB.template.json | 36 ++ .../manifest.json | 167 ++++++++ .../tree.json | 384 ++++++++++++++++++ .../test/integ.reserved-public-subnet.ts | 34 ++ packages/aws-cdk-lib/aws-ec2/lib/vpc.ts | 4 +- packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts | 69 ++++ 13 files changed, 1187 insertions(+), 2 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js new file mode 100644 index 0000000000000..1e64dba70bdc0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js new file mode 100644 index 0000000000000..013bcaffd8fe5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js @@ -0,0 +1 @@ +"use strict";var I=Object.create;var t=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty;var G=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},n=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of P(e))!l.call(r,s)&&s!==o&&t(r,s,{get:()=>e[s],enumerable:!(i=y(e,s))||i.enumerable});return r};var R=(r,e,o)=>(o=r!=null?I(g(r)):{},n(e||!r||!r.__esModule?t(o,"default",{value:r,enumerable:!0}):o,r)),S=r=>n(t({},"__esModule",{value:!0}),r);var k={};G(k,{handler:()=>f});module.exports=S(k);var a=R(require("@aws-sdk/client-ec2")),u=new a.EC2({});function c(r,e){return{GroupId:r,IpPermissions:[{UserIdGroupPairs:[{GroupId:r,UserId:e}],IpProtocol:"-1"}]}}function d(r){return{GroupId:r,IpPermissions:[{IpRanges:[{CidrIp:"0.0.0.0/0"}],IpProtocol:"-1"}]}}async function f(r){let e=r.ResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.Account;switch(r.RequestType){case"Create":return p(e,o);case"Update":return h(r);case"Delete":return m(e,o)}}async function h(r){let e=r.OldResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.DefaultSecurityGroupId;e!==o&&(await m(e,r.ResourceProperties.Account),await p(o,r.ResourceProperties.Account))}async function p(r,e){try{await u.revokeSecurityGroupEgress(d(r))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}try{await u.revokeSecurityGroupIngress(c(r,e))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}}async function m(r,e){await u.authorizeSecurityGroupIngress(c(r,e)),await u.authorizeSecurityGroupEgress(d(r))}0&&(module.exports={handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.assets.json new file mode 100644 index 0000000000000..77cb569c86e0a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.assets.json @@ -0,0 +1,32 @@ +{ + "version": "36.0.0", + "files": { + "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292": { + "source": { + "path": "asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "0be9f67311ac931a5c3e369f73311505432ebd374b19daf1705e3e1fb03a16ff": { + "source": { + "path": "aws-cdk-ec2-vpc-reserved-public-subnet.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "0be9f67311ac931a5c3e369f73311505432ebd374b19daf1705e3e1fb03a16ff.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.template.json new file mode 100644 index 0000000000000..e74e53d3933b8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/aws-cdk-ec2-vpc-reserved-public-subnet.template.json @@ -0,0 +1,283 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC" + } + ] + } + }, + "VPCisolatedSubnet1Subnet84AF7038": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCisolatedSubnet1RouteTable2BB88525": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCisolatedSubnet1RouteTableAssociation2886DD39": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCisolatedSubnet1RouteTable2BB88525" + }, + "SubnetId": { + "Ref": "VPCisolatedSubnet1Subnet84AF7038" + } + } + }, + "VPCisolatedSubnet2Subnet8AE9E765": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCisolatedSubnet2RouteTable1EDFC77F": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCisolatedSubnet2RouteTableAssociation8A6ECC3C": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCisolatedSubnet2RouteTable1EDFC77F" + }, + "SubnetId": { + "Ref": "VPCisolatedSubnet2Subnet8AE9E765" + } + } + }, + "VPCRestrictDefaultSecurityGroupCustomResource59474679": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "VPCB9E5F0B4", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "VPCB9E5F0B4", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": "nodejs18.x", + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integ.json new file mode 100644 index 0000000000000..84120ab9a63c5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest": { + "stacks": [ + "aws-cdk-ec2-vpc-reserved-public-subnet" + ], + "assertionStack": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert", + "assertionStackName": "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets.json new file mode 100644 index 0000000000000..16573eec0e366 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/manifest.json new file mode 100644 index 0000000000000..c5651b719cec8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/manifest.json @@ -0,0 +1,167 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-ec2-vpc-reserved-public-subnet.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-ec2-vpc-reserved-public-subnet.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-ec2-vpc-reserved-public-subnet": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-ec2-vpc-reserved-public-subnet.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0be9f67311ac931a5c3e369f73311505432ebd374b19daf1705e3e1fb03a16ff.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-ec2-vpc-reserved-public-subnet.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-ec2-vpc-reserved-public-subnet.assets" + ], + "metadata": { + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet1Subnet84AF7038" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet1RouteTable2BB88525" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet1RouteTableAssociation2886DD39" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet2Subnet8AE9E765" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet2RouteTable1EDFC77F" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCisolatedSubnet2RouteTableAssociation8A6ECC3C" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/VPC/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCRestrictDefaultSecurityGroupCustomResource59474679" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-ec2-vpc-reserved-public-subnet/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-ec2-vpc-reserved-public-subnet" + }, + "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integawscdkec2vpcreservedpublicsubnetDefaultTestDeployAssert469B3DFB.assets" + ], + "metadata": { + "/integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/tree.json new file mode 100644 index 0000000000000..0d64e87404607 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.js.snapshot/tree.json @@ -0,0 +1,384 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-ec2-vpc-reserved-public-subnet": { + "id": "aws-cdk-ec2-vpc-reserved-public-subnet", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet", + "children": { + "VPC": { + "id": "VPC", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "isolatedSubnet1": { + "id": "isolatedSubnet1", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCisolatedSubnet1RouteTable2BB88525" + }, + "subnetId": { + "Ref": "VPCisolatedSubnet1Subnet84AF7038" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "isolatedSubnet2": { + "id": "isolatedSubnet2", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/isolatedSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCisolatedSubnet2RouteTable1EDFC77F" + }, + "subnetId": { + "Ref": "VPCisolatedSubnet2Subnet8AE9E765" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/VPC/RestrictDefaultSecurityGroupCustomResource/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Role": { + "id": "Role", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Handler": { + "id": "Handler", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-ec2-vpc-reserved-public-subnet/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "integ-aws-cdk-ec2-vpc-reserved-public-subnet": { + "id": "integ-aws-cdk-ec2-vpc-reserved-public-subnet", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-aws-cdk-ec2-vpc-reserved-public-subnet/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.ts new file mode 100644 index 0000000000000..8e2085d756de6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.reserved-public-subnet.ts @@ -0,0 +1,34 @@ +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; + +const app = new cdk.App(); + +class VpcReservedPublicSubnetStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new ec2.Vpc(this, 'VPC', { + ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), + subnetConfiguration: [ + { + name: 'public', + subnetType: ec2.SubnetType.PUBLIC, + reserved: true, + }, + { + name: 'isolated', + subnetType: ec2.SubnetType.PRIVATE_ISOLATED, + }, + ], + natGateways: 0, + }); + } +} +const stack = new VpcReservedPublicSubnetStack(app, 'aws-cdk-ec2-vpc-reserved-public-subnet'); + +new IntegTest(app, 'integ-aws-cdk-ec2-vpc-reserved-public-subnet', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts index c49176d91bdf0..f466af74ce9d0 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts @@ -1607,7 +1607,7 @@ export class Vpc extends VpcBase { const createInternetGateway = props.createInternetGateway ?? true; const allowOutbound = this.subnetConfiguration.filter( - subnet => (subnet.subnetType !== SubnetType.PRIVATE_ISOLATED && subnet.subnetType !== SubnetType.ISOLATED)).length > 0; + subnet => (subnet.subnetType !== SubnetType.PRIVATE_ISOLATED && subnet.subnetType !== SubnetType.ISOLATED && !subnet.reserved)).length > 0; // Create an Internet Gateway and attach it if necessary if (allowOutbound && createInternetGateway) { @@ -2661,7 +2661,7 @@ class ImportedSubnet extends Resource implements ISubnet, IPublicSubnet, IPrivat function determineNatGatewayCount(requestedCount: number | undefined, subnetConfig: SubnetConfiguration[], azCount: number) { const hasPrivateSubnets = subnetConfig.some(c => (c.subnetType === SubnetType.PRIVATE_WITH_EGRESS || c.subnetType === SubnetType.PRIVATE || c.subnetType === SubnetType.PRIVATE_WITH_NAT) && !c.reserved); - const hasPublicSubnets = subnetConfig.some(c => c.subnetType === SubnetType.PUBLIC); + const hasPublicSubnets = subnetConfig.some(c => c.subnetType === SubnetType.PUBLIC && !c.reserved); const hasCustomEgress = subnetConfig.some(c => c.subnetType === SubnetType.PRIVATE_WITH_EGRESS); const count = requestedCount !== undefined ? Math.min(requestedCount, azCount) : (hasPrivateSubnets ? azCount : 0); diff --git a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts index 495c0d2ee4162..52bad89bb72dc 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts @@ -385,6 +385,75 @@ describe('vpc', () => { }); + test('with only reserved subnets as public subnets, should not create the internet gateway', () => { + const stack = getTestStack(); + const vpc = new Vpc(stack, 'TheVPC', { + subnetConfiguration: [ + { + subnetType: SubnetType.PRIVATE_ISOLATED, + name: 'isolated', + }, + { + subnetType: SubnetType.PUBLIC, + name: 'public', + reserved: true, + }, + ], + }); + Template.fromStack(stack).resourceCountIs('AWS::EC2::InternetGateway', 0); + Template.fromStack(stack).resourceCountIs('AWS::EC2::VPCGatewayAttachment', 0); + }); + + test('with only reserved subnets as private subnets with egress, should not create the internet gateway', () => { + const stack = getTestStack(); + const vpc = new Vpc(stack, 'TheVPC', { + subnetConfiguration: [ + { + subnetType: SubnetType.PRIVATE_ISOLATED, + name: 'isolated', + }, + { + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + name: 'egress', + reserved: true, + }, + ], + }); + Template.fromStack(stack).resourceCountIs('AWS::EC2::InternetGateway', 0); + Template.fromStack(stack).resourceCountIs('AWS::EC2::VPCGatewayAttachment', 0); + }); + + test('with no public subnets and natGateways > 0, should throw an error', () => { + const stack = getTestStack(); + expect(() => new Vpc(stack, 'TheVPC', { + subnetConfiguration: [ + { + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + name: 'egress', + }, + ], + natGateways: 1, + })).toThrow(/If you configure PRIVATE subnets in 'subnetConfiguration', you must also configure PUBLIC subnets to put the NAT gateways into \(got \[{"subnetType":"Private","name":"egress"}\]./); + }); + + test('with only reserved subnets as public subnets and natGateways > 0, should throw an error', () => { + const stack = getTestStack(); + expect(() => new Vpc(stack, 'TheVPC', { + subnetConfiguration: [ + { + subnetType: SubnetType.PUBLIC, + name: 'public', + reserved: true, + }, + { + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + name: 'egress', + }, + ], + natGateways: 1, + })).toThrow(/If you configure PRIVATE subnets in 'subnetConfiguration', you must also configure PUBLIC subnets to put the NAT gateways into \(got \[{"subnetType":"Public","name":"public","reserved":true},{"subnetType":"Private","name":"egress"}\]./); + }); + test('with subnets and reserved subnets defined, VPC subnet count should not contain reserved subnets ', () => { const stack = getTestStack(); new Vpc(stack, 'TheVPC', { From 63390e1bdd9f515eb1b9afcaf106985eb83fdc05 Mon Sep 17 00:00:00 2001 From: Michael Sambol Date: Thu, 29 Feb 2024 19:08:23 -0700 Subject: [PATCH 25/31] feat(applicationautoscaling): add missing PredefinedMetricType enum values (#29066) There are three `PredefinedMetricType` values missing from the enum: * SageMakerVariantProvisionedConcurrencyUtilization * SageMakerInferenceComponentInvocationsPerCopy * ElastiCacheDatabaseCapacityUsageCountedForEvictPercentage https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html Closes #29065. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-applicationautoscaling/README.md | 17 +++++++++++++++ .../lib/target-tracking-scaling-policy.ts | 21 ++++++++++++++++--- .../test/target-tracking.test.ts | 20 ++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/README.md b/packages/aws-cdk-lib/aws-applicationautoscaling/README.md index b52ef8ad4b1d7..ada0679a43080 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/README.md +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/README.md @@ -247,3 +247,20 @@ shardsScalableTarget.scaleToTrackMetric('ElastiCacheRedisShardsCPUUtilization', predefinedMetric: appscaling.PredefinedMetric.ELASTICACHE_PRIMARY_ENGINE_CPU_UTILIZATION, }); ``` + +### SageMaker variant provisioned concurrency utilization with target value + +```ts +const target = new appscaling.ScalableTarget(this, 'SageMakerVariantScalableTarget', { + serviceNamespace: appscaling.ServiceNamespace.SAGEMAKER, + scalableDimension: 'sagemaker:variant:DesiredProvisionedConcurrency', + minCapacity: 2, + maxCapacity: 10, + resourceId: 'endpoint/MyEndpoint/variant/MyVariant', +}); + +target.scaleToTrackMetric('SageMakerVariantProvisionedConcurrencyUtilization', { + targetValue: 0.9, + predefinedMetric: appscaling.PredefinedMetric.SAGEMAKER_VARIANT_PROVISIONED_CONCURRENCY_UTILIZATION, +}); +``` diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts b/packages/aws-cdk-lib/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts index 097a0d5df6bff..7277fc164e1ea 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts @@ -254,6 +254,16 @@ export enum PredefinedMetric { * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html */ SAGEMAKER_VARIANT_INVOCATIONS_PER_INSTANCE = 'SageMakerVariantInvocationsPerInstance', + /** + * SAGEMAKER_VARIANT_PROVISIONED_CONCURRENCY_UTILIZATION + * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html + */ + SAGEMAKER_VARIANT_PROVISIONED_CONCURRENCY_UTILIZATION = 'SageMakerVariantProvisionedConcurrencyUtilization', + /** + * SAGEMAKER_INFERENCE_COMPONENT_INVOCATIONS_PER_COPY + * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html + */ + SAGEMAKER_INFERENCE_COMPONENT_INVOCATIONS_PER_COPY = 'SageMakerInferenceComponentInvocationsPerCopy', /** * ECS_SERVICE_AVERAGE_CPU_UTILIZATION * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html @@ -275,18 +285,23 @@ export enum PredefinedMetric { */ KAFKA_BROKER_STORAGE_UTILIZATION = 'KafkaBrokerStorageUtilization', /** - * ELASTIC_CACHE_PRIMARY_ENGINE_CPU_UTILIZATION + * ELASTICACHE_PRIMARY_ENGINE_CPU_UTILIZATION * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html */ ELASTICACHE_PRIMARY_ENGINE_CPU_UTILIZATION = 'ElastiCachePrimaryEngineCPUUtilization', /** - * ELASTIC_CACHE_REPLICA_ENGINE_CPU_UTILIZATION + * ELASTICACHE_REPLICA_ENGINE_CPU_UTILIZATION * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html */ ELASTICACHE_REPLICA_ENGINE_CPU_UTILIZATION = 'ElastiCacheReplicaEngineCPUUtilization', /** - * ELASTIC_CACHE_REPLICA_ENGINE_CPU_UTILIZATION + * ELASTICACHE_DATABASE_MEMORY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html */ ELASTICACHE_DATABASE_MEMORY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE = 'ElastiCacheDatabaseMemoryUsageCountedForEvictPercentage', + /** + * ELASTICACHE_DATABASE_CAPACITY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE + * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html + */ + ELASTICACHE_DATABASE_CAPACITY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE = 'ElastiCacheDatabaseCapacityUsageCountedForEvictPercentage', } diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/test/target-tracking.test.ts b/packages/aws-cdk-lib/aws-applicationautoscaling/test/target-tracking.test.ts index ca117a8406a2f..df3c2c098d841 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/test/target-tracking.test.ts +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/test/target-tracking.test.ts @@ -71,6 +71,26 @@ describe('target tracking', () => { }); }); + test('test setup target tracking on predefined metric for SAGEMAKER_VARIANT_PROVISIONED_CONCURRENCY_UTILIZATION', () => { + // GIVEN + const stack = new cdk.Stack(); + const target = createScalableTarget(stack); + + // WHEN + target.scaleToTrackMetric('Tracking', { + predefinedMetric: appscaling.PredefinedMetric.SAGEMAKER_VARIANT_PROVISIONED_CONCURRENCY_UTILIZATION, + targetValue: 0.5, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { + TargetTrackingScalingPolicyConfiguration: { + PredefinedMetricSpecification: { PredefinedMetricType: 'SageMakerVariantProvisionedConcurrencyUtilization' }, + TargetValue: 0.5, + }, + }); + }); + test('test setup target tracking on custom metric', () => { // GIVEN const stack = new cdk.Stack(); From 0d6ef63e04ed0301e40684594266e83b50dce186 Mon Sep 17 00:00:00 2001 From: Rico Hermans Date: Fri, 1 Mar 2024 15:35:48 +0100 Subject: [PATCH 26/31] chore: add some debugging to regression test skipping (#29332) The regression test skipping mechanism doesn't seem to be working. Investigate what's going on by adding print logging. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk-testing/cli-integ/bin/apply-patches | 9 ++++++--- packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts | 11 +++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk-testing/cli-integ/bin/apply-patches b/packages/@aws-cdk-testing/cli-integ/bin/apply-patches index b27d0c93dc9e7..30229625387a9 100755 --- a/packages/@aws-cdk-testing/cli-integ/bin/apply-patches +++ b/packages/@aws-cdk-testing/cli-integ/bin/apply-patches @@ -14,6 +14,9 @@ fi candidate_dir="${scriptdir}/../resources/cli-regression-patches/v${version}" -if [[ -f "$candidate_dir" ]]; then - cp -R "${candidate_dir}/"* "$2" -fi \ No newline at end of file +if [[ -d "$candidate_dir" ]]; then + echo "Found patch directory: ${candidate_dir}" + cp -vR "${candidate_dir}/"* "$2" +else + echo "No patch directory named: ${candidate_dir}" +fi diff --git a/packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts b/packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts index 5ad6596cf1b77..b4655461b5f57 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts @@ -2,7 +2,14 @@ import * as fs from 'fs'; import * as path from 'path'; import { MemoryStream } from './corking'; -const SKIP_TESTS = fs.readFileSync(path.join(__dirname, '..', 'skip-tests.txt'), { encoding: 'utf-8' }).split('\n'); +const SKIP_TESTS = fs.readFileSync(path.join(__dirname, '..', 'skip-tests.txt'), { encoding: 'utf-8' }) + .split('\n') + .map(x => x.trim()) + .filter(x => x && !x.startsWith('#')); + +if (SKIP_TESTS) { + process.stderr.write(`ℹ️ Skipping tests: ${JSON.stringify(SKIP_TESTS)}\n`); +} export interface TestContext { readonly randomString: string; @@ -11,7 +18,7 @@ export interface TestContext { }; if (process.env.JEST_TEST_CONCURRENT === 'true') { - process.stderr.write('ℹ️ JEST_TEST_CONCURRENT is true: tests will run concurrently and filters have no effect!'); + process.stderr.write('ℹ️ JEST_TEST_CONCURRENT is true: tests will run concurrently and filters have no effect!\n0'); } /** From 6a2747cf7ae88e7ba3c17c23b1af420104c476cb Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 1 Mar 2024 12:29:52 -0500 Subject: [PATCH 27/31] chore(eks): support Amazon Linux 2023 (#29335) ### Issue # (if applicable) Closes https://github.com/aws/aws-cdk/issues/29334 ### Reason for this change To support Amazon Linux 2023 nodegroup. ### Description of changes Allow the AmiType to select Amazon Linux 2023 for both x86_64 and ARM_64. ### Description of how you validated changes ```ts const mastersRole = new iam.Role(this, 'AdminRole', { assumedBy: new iam.AccountRootPrincipal(), }); const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true }); const cluster = new eks.Cluster(this, 'Cluster', { vpc, mastersRole, kubectlLayer: new KubectlV29Layer(this, 'KubectlLayer'), version: eks.KubernetesVersion.V1_29, defaultCapacity: 0, }); cluster.addNodegroupCapacity('NG-X86', { amiType: eks.NodegroupAmiType.AL2023_X86_64_STANDARD, desiredSize: 1, }); cluster.addNodegroupCapacity('NG-ARM', { amiType: eks.NodegroupAmiType.AL2023_ARM_64_STANDARD, desiredSize: 1, }); ``` ```sh $ /tmp/kubectl get no NAME STATUS ROLES AGE VERSION ip-172-31-1-222.ec2.internal Ready 4m53s v1.29.0-eks-5e0fdde ip-172-31-2-242.ec2.internal Ready 4m46s v1.29.0-eks-5e0fdde ``` ``` $ /tmp/kubectl get nodes ip-172-31-1-222.ec2.internal -o jsonpath="{ .status.nodeInfo}" | jq -r . { "architecture": "amd64", "bootID": "f65b39c5-f1c6-4b75-8f62-8424c29302ca", "containerRuntimeVersion": "containerd://1.7.11", "kernelVersion": "6.1.77-99.164.amzn2023.x86_64", "kubeProxyVersion": "v1.29.0-eks-5e0fdde", "kubeletVersion": "v1.29.0-eks-5e0fdde", "machineID": "ec23037a57eb6be59d03137fbe1c2625", "operatingSystem": "linux", "osImage": "Amazon Linux 2023", "systemUUID": "ec23037a-57eb-6be5-9d03-137fbe1c2625" } $ /tmp/kubectl get nodes ip-172-31-2-242.ec2.internal -o jsonpath="{ .status.nodeInfo}" | jq -r . { "architecture": "arm64", "bootID": "a2d15e6f-c48c-474b-aad5-510712c41153", "containerRuntimeVersion": "containerd://1.7.11", "kernelVersion": "6.1.77-99.164.amzn2023.aarch64", "kubeProxyVersion": "v1.29.0-eks-5e0fdde", "kubeletVersion": "v1.29.0-eks-5e0fdde", "machineID": "ec2b26d85fe443884398704c3b82887b", "operatingSystem": "linux", "osImage": "Amazon Linux 2023", "systemUUID": "ec2b26d8-5fe4-4388-4398-704c3b82887b" } ``` ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts b/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts index 9aee08d143e68..4e3d4c7751d8a 100644 --- a/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts +++ b/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts @@ -70,6 +70,14 @@ export enum NodegroupAmiType { * Windows Full 2022 (x86-64) */ WINDOWS_FULL_2022_X86_64 = 'WINDOWS_FULL_2022_x86_64', + /** + * Amazon Linux 2023 (x86-64) + */ + AL2023_X86_64_STANDARD = 'AL2023_x86_64_STANDARD', + /** + * Amazon Linux 2023 (ARM-64) + */ + AL2023_ARM_64_STANDARD = 'AL2023_ARM_64_STANDARD', } /** From 9156b133f7bb4db12b85954ca62a596b1c41366b Mon Sep 17 00:00:00 2001 From: daixi98 <92189099+daixi98@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:30:23 -0800 Subject: [PATCH 28/31] feat(ecs-patterns): allow custom ephemeral storage for ECS Fargate services (#29275) ### Issue # (if applicable) Closes #18105. ### Reason for this change In April 2021, Fargate added support for [requesting additional ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14). Support for this feature has [been added](https://github.com/aws/aws-cdk/commit/f1bf935c47006096b33fb7bf0c847ffab9230870#diff-dcfbc499b4d3c10afcd4e63ad0e4ecc54df2464e45af67f1fdae69d3fa2d43a0) to the aws-ecs package, but is still not supported by the aws-ecs-patterns package. ### Description of changes This code change adds an optional field `ephemeralStorageGiB` in `packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts`, after other fields like `cpu` and `memoryLimitMiB`. ### Description of how you validated changes Added unit tests and new integration tests. Created a simple CDK application with the new constructs, and verified that it synthesized and deployed correctly. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssertD8C2EA6F.assets.json | 19 + ...aultTestDeployAssertD8C2EA6F.template.json | 36 + ...tterns-alb-with-custom-storage.assets.json | 19 + ...erns-alb-with-custom-storage.template.json | 797 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 341 +++++ .../tree.json | 1353 +++++++++++++++++ ...nteg.alb-fargate-service-custom-storage.ts | 30 + .../aws-cdk-lib/aws-ecs-patterns/README.md | 29 + .../lib/base/fargate-service-base.ts | 11 + ...plication-load-balanced-fargate-service.ts | 1 + ...-multiple-target-groups-fargate-service.ts | 1 + .../network-load-balanced-fargate-service.ts | 1 + ...-multiple-target-groups-fargate-service.ts | 1 + .../queue-processing-fargate-service.ts | 1 + .../lib/fargate/scheduled-fargate-task.ts | 4 + .../load-balanced-fargate-service-v2.test.ts | 8 + .../queue-processing-fargate-service.test.ts | 4 + .../fargate/scheduled-fargate-task.test.ts | 4 + 20 files changed, 2673 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets.json new file mode 100644 index 0000000000000..36288598dbe40 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.assets.json new file mode 100644 index 0000000000000..d33c5f89ba261 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "4aeda6cd27be6d2d51086f4b349b34a0c0384a09e5ba307373053e07a1e7c01b": { + "source": { + "path": "aws-ecs-patterns-alb-with-custom-storage.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4aeda6cd27be6d2d51086f4b349b34a0c0384a09e5ba307373053e07a1e7c01b.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.template.json new file mode 100644 index 0000000000000..08ec2270724b4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/aws-ecs-patterns-alb-with-custom-storage.template.json @@ -0,0 +1,797 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC" + ] + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet2EIP4947BC00": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2NATGateway3C070193": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet2EIP4947BC00", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ] + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + }, + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + } + } + }, + "VPCPrivateSubnet2SubnetCFCDAA7A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet2RouteTable0A19E10E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "VPCPrivateSubnet2RouteTableAssociation0C73D413": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "VPCPrivateSubnet2DefaultRouteF4F5CFD2": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + }, + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-patterns-alb-with-custom-storage/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "ALBServiceWithCustomStorageLB2944BA62": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ], + "Type": "application" + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC", + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ] + }, + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLB0BB3EC80", + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "ALBServiceWithCustomStorageLBSecurityGrouptoawsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD71280CAF68E39": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + }, + "FromPort": 80, + "GroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "ToPort": 80 + } + }, + "ALBServiceWithCustomStorageLBPublicListener89E8575A": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "ALBServiceWithCustomStorageLB2944BA62" + }, + "Port": 80, + "Protocol": "HTTP" + } + }, + "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 80, + "Protocol": "HTTP", + "TargetGroupAttributes": [ + { + "Key": "stickiness.enabled", + "Value": "false" + } + ], + "TargetType": "ip", + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ALBServiceWithCustomStorageTaskDef874CA24B": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Essential": true, + "HealthCheck": { + "Command": [ + "CMD-SHELL", + "curl -f http://localhost/ || exit 1" + ], + "Interval": 10, + "Retries": 10, + "Timeout": 5 + }, + "Image": "amazon/amazon-ecs-sample", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241" + }, + "awslogs-stream-prefix": "ALBServiceWithCustomStorage", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "Name": "web", + "PortMappings": [ + { + "ContainerPort": 80, + "Protocol": "tcp" + } + ] + } + ], + "Cpu": "256", + "EphemeralStorage": { + "SizeInGiB": 35 + }, + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37", + "Arn" + ] + }, + "Family": "awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageTaskDefC0C6519F", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36", + "Arn" + ] + } + } + }, + "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241": { + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ALBServiceWithCustomStorageTaskDefExecutionRoleDefaultPolicy39D49813": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ALBServiceWithCustomStorageTaskDefExecutionRoleDefaultPolicy39D49813", + "Roles": [ + { + "Ref": "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37" + } + ] + } + }, + "ALBServiceWithCustomStorageServiceBC418171": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" + }, + "DeploymentConfiguration": { + "Alarms": { + "AlarmNames": [], + "Enable": false, + "Rollback": false + }, + "MaximumPercent": 200, + "MinimumHealthyPercent": 50 + }, + "EnableECSManagedTags": false, + "HealthCheckGracePeriodSeconds": 60, + "LaunchType": "FARGATE", + "LoadBalancers": [ + { + "ContainerName": "web", + "ContainerPort": 80, + "TargetGroupArn": { + "Ref": "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E" + } + } + ], + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "ENABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ] + } + }, + "TaskDefinition": { + "Ref": "ALBServiceWithCustomStorageTaskDef874CA24B" + } + }, + "DependsOn": [ + "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E", + "ALBServiceWithCustomStorageLBPublicListener89E8575A", + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36" + ] + }, + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + }, + "DependsOn": [ + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36" + ] + }, + "ALBServiceWithCustomStorageServiceSecurityGroupfromawsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D808B830EAA": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "Description": "Load balancer to target", + "FromPort": 80, + "GroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + }, + "ToPort": 80 + }, + "DependsOn": [ + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36" + ] + }, + "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3": { + "Type": "AWS::ECS::Cluster" + } + }, + "Outputs": { + "ALBServiceWithCustomStorageLoadBalancerDNS5A824F2E": { + "Value": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLB2944BA62", + "DNSName" + ] + } + }, + "ALBServiceWithCustomStorageServiceURL30743F97": { + "Value": { + "Fn::Join": [ + "", + [ + "http://", + { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLB2944BA62", + "DNSName" + ] + } + ] + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/integ.json new file mode 100644 index 0000000000000..51ff298ac9572 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest": { + "stacks": [ + "aws-ecs-patterns-alb-with-custom-storage" + ], + "assertionStack": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert", + "assertionStackName": "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/manifest.json new file mode 100644 index 0000000000000..ffbaa238de8c6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/manifest.json @@ -0,0 +1,341 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-ecs-patterns-alb-with-custom-storage.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-ecs-patterns-alb-with-custom-storage.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-ecs-patterns-alb-with-custom-storage": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-ecs-patterns-alb-with-custom-storage.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4aeda6cd27be6d2d51086f4b349b34a0c0384a09e5ba307373053e07a1e7c01b.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-ecs-patterns-alb-with-custom-storage.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-ecs-patterns-alb-with-custom-storage.assets" + ], + "metadata": { + "/aws-ecs-patterns-alb-with-custom-storage/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1SubnetB4246D30" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableFEE4B781" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableAssociation0B0896DC" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1DefaultRoute91CEF279" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1EIP6AD938E8" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1NATGatewayE0556630" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2Subnet74179F39" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTable6F1A15F1" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTableAssociation5A808732" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2DefaultRouteB7481BBA" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2EIP4947BC00" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2NATGateway3C070193" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableBE8A6027" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableAssociation347902D1" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1DefaultRouteAE1D6490" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTable0A19E10E" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTableAssociation0C73D413" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2DefaultRouteF4F5CFD2" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLB2944BA62" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/SecurityGroup/to awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD712:80": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLBSecurityGrouptoawsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD71280CAF68E39" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLBPublicListener89E8575A" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener/ECSGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LoadBalancerDNS": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageLoadBalancerDNS5A824F2E" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/ServiceURL": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageServiceURL30743F97" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/TaskRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageTaskDef874CA24B" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/web/LogGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageTaskDefExecutionRoleDefaultPolicy39D49813" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/Service": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageServiceBC418171" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup/from awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D:80": [ + { + "type": "aws:cdk:logicalId", + "data": "ALBServiceWithCustomStorageServiceSecurityGroupfromawsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D808B830EAA" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/EcsDefaultClusterMnL3mNNYNVPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-ecs-patterns-alb-with-custom-storage/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-ecs-patterns-alb-with-custom-storage" + }, + "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ApplicationLoadBalancedFargateServiceCustomStorageTestDefaultTestDeployAssertD8C2EA6F.assets" + ], + "metadata": { + "/ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/tree.json new file mode 100644 index 0000000000000..2dc5c38f4f7c6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.js.snapshot/tree.json @@ -0,0 +1,1353 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-ecs-patterns-alb-with-custom-storage": { + "id": "aws-ecs-patterns-alb-with-custom-storage", + "path": "aws-ecs-patterns-alb-with-custom-storage", + "children": { + "VPC": { + "id": "VPC", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1/NATGateway", + "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-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "subnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2/NATGateway", + "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-ecs-patterns-alb-with-custom-storage/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + }, + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + }, + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-patterns-alb-with-custom-storage/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-ecs-patterns-alb-with-custom-storage/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + }, + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "ALBServiceWithCustomStorage": { + "id": "ALBServiceWithCustomStorage", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage", + "children": { + "LB": { + "id": "LB", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "aws:cdk:cloudformation:props": { + "loadBalancerAttributes": [ + { + "key": "deletion_protection.enabled", + "value": "false" + } + ], + "scheme": "internet-facing", + "securityGroups": [ + { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ], + "type": "application" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "Automatically created Security Group for ELB awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLB0BB3EC80", + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "tcp", + "fromPort": 80, + "toPort": 80, + "description": "Allow from anyone on port 80" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "to awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD712:80": { + "id": "to awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD712:80", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/SecurityGroup/to awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageServiceSecurityGroup5EBDD712:80", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupEgress", + "aws:cdk:cloudformation:props": { + "description": "Load balancer to target", + "destinationSecurityGroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + }, + "fromPort": 80, + "groupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + }, + "ipProtocol": "tcp", + "toPort": 80 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroupEgress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "PublicListener": { + "id": "PublicListener", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "defaultActions": [ + { + "type": "forward", + "targetGroupArn": { + "Ref": "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E" + } + } + ], + "loadBalancerArn": { + "Ref": "ALBServiceWithCustomStorageLB2944BA62" + }, + "port": 80, + "protocol": "HTTP" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnListener", + "version": "0.0.0" + } + }, + "ECSGroup": { + "id": "ECSGroup", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener/ECSGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LB/PublicListener/ECSGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "port": 80, + "protocol": "HTTP", + "targetGroupAttributes": [ + { + "key": "stickiness.enabled", + "value": "false" + } + ], + "targetType": "ip", + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnTargetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationTargetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationListener", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer", + "version": "0.0.0" + } + }, + "LoadBalancerDNS": { + "id": "LoadBalancerDNS", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/LoadBalancerDNS", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "0.0.0" + } + }, + "ServiceURL": { + "id": "ServiceURL", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/ServiceURL", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "0.0.0" + } + }, + "TaskDef": { + "id": "TaskDef", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef", + "children": { + "TaskRole": { + "id": "TaskRole", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/TaskRole", + "children": { + "ImportTaskRole": { + "id": "ImportTaskRole", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/TaskRole/ImportTaskRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/TaskRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::TaskDefinition", + "aws:cdk:cloudformation:props": { + "containerDefinitions": [ + { + "essential": true, + "image": "amazon/amazon-ecs-sample", + "name": "web", + "portMappings": [ + { + "containerPort": 80, + "protocol": "tcp" + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": { + "Ref": "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241" + }, + "awslogs-stream-prefix": "ALBServiceWithCustomStorage", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "healthCheck": { + "command": [ + "CMD-SHELL", + "curl -f http://localhost/ || exit 1" + ], + "interval": 10, + "retries": 10, + "timeout": 5 + } + } + ], + "cpu": "256", + "ephemeralStorage": { + "sizeInGiB": 35 + }, + "executionRoleArn": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37", + "Arn" + ] + }, + "family": "awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageTaskDefC0C6519F", + "memory": "512", + "networkMode": "awsvpc", + "requiresCompatibilities": [ + "FARGATE" + ], + "taskRoleArn": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefTaskRoleDB8D0B36", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnTaskDefinition", + "version": "0.0.0" + } + }, + "web": { + "id": "web", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/web", + "children": { + "LogGroup": { + "id": "LogGroup", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/web/LogGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/web/LogGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Logs::LogGroup", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_logs.CfnLogGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_logs.LogGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.ContainerDefinition", + "version": "0.0.0" + } + }, + "ExecutionRole": { + "id": "ExecutionRole", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole", + "children": { + "ImportExecutionRole": { + "id": "ImportExecutionRole", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/ImportExecutionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/TaskDef/ExecutionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageTaskDefwebLogGroup99D5D241", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ALBServiceWithCustomStorageTaskDefExecutionRoleDefaultPolicy39D49813", + "roles": [ + { + "Ref": "ALBServiceWithCustomStorageTaskDefExecutionRole4C674E37" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.FargateTaskDefinition", + "version": "0.0.0" + } + }, + "Service": { + "id": "Service", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service", + "children": { + "Service": { + "id": "Service", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/Service", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Service", + "aws:cdk:cloudformation:props": { + "cluster": { + "Ref": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" + }, + "deploymentConfiguration": { + "maximumPercent": 200, + "minimumHealthyPercent": 50, + "alarms": { + "alarmNames": [], + "enable": false, + "rollback": false + } + }, + "enableEcsManagedTags": false, + "healthCheckGracePeriodSeconds": 60, + "launchType": "FARGATE", + "loadBalancers": [ + { + "targetGroupArn": { + "Ref": "ALBServiceWithCustomStorageLBPublicListenerECSGroup9AD0558E" + }, + "containerName": "web", + "containerPort": 80 + } + ], + "networkConfiguration": { + "awsvpcConfiguration": { + "assignPublicIp": "ENABLED", + "subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ], + "securityGroups": [ + { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + } + ] + } + }, + "taskDefinition": { + "Ref": "ALBServiceWithCustomStorageTaskDef874CA24B" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnService", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "from awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D:80": { + "id": "from awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D:80", + "path": "aws-ecs-patterns-alb-with-custom-storage/ALBServiceWithCustomStorage/Service/SecurityGroup/from awsecspatternsalbwithcustomstorageALBServiceWithCustomStorageLBSecurityGroup415BB80D:80", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupIngress", + "aws:cdk:cloudformation:props": { + "description": "Load balancer to target", + "fromPort": 80, + "groupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageServiceSecurityGroupC2DED8D1", + "GroupId" + ] + }, + "ipProtocol": "tcp", + "sourceSecurityGroupId": { + "Fn::GetAtt": [ + "ALBServiceWithCustomStorageLBSecurityGroup5CCF3B01", + "GroupId" + ] + }, + "toPort": 80 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroupIngress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.FargateService", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService", + "version": "0.0.0" + } + }, + "EcsDefaultClusterMnL3mNNYNVPC": { + "id": "EcsDefaultClusterMnL3mNNYNVPC", + "path": "aws-ecs-patterns-alb-with-custom-storage/EcsDefaultClusterMnL3mNNYNVPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-patterns-alb-with-custom-storage/EcsDefaultClusterMnL3mNNYNVPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCluster", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Cluster", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-ecs-patterns-alb-with-custom-storage/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-ecs-patterns-alb-with-custom-storage/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "ApplicationLoadBalancedFargateServiceCustomStorageTest": { + "id": "ApplicationLoadBalancedFargateServiceCustomStorageTest", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ApplicationLoadBalancedFargateServiceCustomStorageTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.ts new file mode 100644 index 0000000000000..a97061e81b9a7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-custom-storage.ts @@ -0,0 +1,30 @@ +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { App, Stack, Duration } from 'aws-cdk-lib'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns'; +import { ContainerImage } from 'aws-cdk-lib/aws-ecs'; + +const app = new App(); +const stack = new Stack(app, 'aws-ecs-patterns-alb-with-custom-storage'); +const vpc = new ec2.Vpc(stack, 'VPC', { restrictDefaultSecurityGroup: false }); + +new ApplicationLoadBalancedFargateService(stack, 'ALBServiceWithCustomStorage', { + vpc, + memoryLimitMiB: 512, + ephemeralStorageGiB: 35, + taskImageOptions: { + image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, + assignPublicIp: true, + healthCheck: { + command: ['CMD-SHELL', 'curl -f http://localhost/ || exit 1'], + interval: Duration.seconds(10), + retries: 10, + }, +}); + +new integ.IntegTest(app, 'ApplicationLoadBalancedFargateServiceCustomStorageTest', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/README.md b/packages/aws-cdk-lib/aws-ecs-patterns/README.md index ab4991275a62e..77f62440f5efa 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/README.md +++ b/packages/aws-cdk-lib/aws-ecs-patterns/README.md @@ -1093,4 +1093,33 @@ const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'Schedul }, ], }); +``` + +### Use custom ephemeral storage for ECS Fargate tasks + +You can pass a custom ephemeral storage (21GiB - 200GiB) to ECS Fargate tasks on Fargate Platform Version 1.4.0 or later. + +```ts +const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); +const cluster = new ecs.Cluster(this, 'FargateCluster', { vpc }); + +const applicationLoadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'ALBFargateServiceWithCustomEphemeralStorage', { + cluster, + memoryLimitMiB: 1024, + cpu: 512, + ephemeralStorageGiB: 21, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, +}); + +const networkLoadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'NLBFargateServiceWithCustomEphemeralStorage', { + cluster, + memoryLimitMiB: 1024, + cpu: 512, + ephemeralStorageGiB: 200, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, +}); ``` \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts index 823640674fd59..d8df18c5501db 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts @@ -61,6 +61,17 @@ export interface FargateServiceBaseProps { */ readonly memoryLimitMiB?: number; + /** + * The amount (in GiB) of ephemeral storage to be allocated to the task. + * + * The minimum supported value is `21` GiB and the maximum supported value is `200` GiB. + * + * Only supported in Fargate platform version 1.4.0 or later. + * + * @default Undefined, in which case, the task will receive 20GiB ephemeral storage. + */ + readonly ephemeralStorageGiB?: number; + /** * The platform version on which to run your service. * diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts index 5c101ee7dd964..4bc76a56b73dc 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.ts @@ -74,6 +74,7 @@ export class ApplicationLoadBalancedFargateService extends ApplicationLoadBalanc this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', { memoryLimitMiB: props.memoryLimitMiB, cpu: props.cpu, + ephemeralStorageGiB: props.ephemeralStorageGiB, executionRole: taskImageOptions.executionRole, taskRole: taskImageOptions.taskRole, family: taskImageOptions.family, diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-multiple-target-groups-fargate-service.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-multiple-target-groups-fargate-service.ts index df9ed2cfd79e3..aca6f639ae0ac 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-multiple-target-groups-fargate-service.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-multiple-target-groups-fargate-service.ts @@ -65,6 +65,7 @@ export class ApplicationMultipleTargetGroupsFargateService extends ApplicationMu this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', { memoryLimitMiB: props.memoryLimitMiB, cpu: props.cpu, + ephemeralStorageGiB: props.ephemeralStorageGiB, executionRole: taskImageOptions.executionRole, taskRole: taskImageOptions.taskRole, family: taskImageOptions.family, diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts index a7c2c01f6d9f7..993a17a92aed2 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-load-balanced-fargate-service.ts @@ -59,6 +59,7 @@ export class NetworkLoadBalancedFargateService extends NetworkLoadBalancedServic this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', { memoryLimitMiB: props.memoryLimitMiB, cpu: props.cpu, + ephemeralStorageGiB: props.ephemeralStorageGiB, executionRole: taskImageOptions.executionRole, taskRole: taskImageOptions.taskRole, family: taskImageOptions.family, diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-multiple-target-groups-fargate-service.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-multiple-target-groups-fargate-service.ts index 21d97d8e9d5cb..9c6cc3c66649f 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-multiple-target-groups-fargate-service.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/network-multiple-target-groups-fargate-service.ts @@ -65,6 +65,7 @@ export class NetworkMultipleTargetGroupsFargateService extends NetworkMultipleTa this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', { memoryLimitMiB: props.memoryLimitMiB, cpu: props.cpu, + ephemeralStorageGiB: props.ephemeralStorageGiB, executionRole: taskImageOptions.executionRole, taskRole: taskImageOptions.taskRole, family: taskImageOptions.family, diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts index f2f26d5e8669d..77d28ea2821d0 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/queue-processing-fargate-service.ts @@ -77,6 +77,7 @@ export class QueueProcessingFargateService extends QueueProcessingServiceBase { this.taskDefinition = new FargateTaskDefinition(this, 'QueueProcessingTaskDef', { memoryLimitMiB: props.memoryLimitMiB || 512, cpu: props.cpu || 256, + ephemeralStorageGiB: props.ephemeralStorageGiB, family: props.family, runtimePlatform: props.runtimePlatform, }); diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/scheduled-fargate-task.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/scheduled-fargate-task.ts index c7725538ca7e2..bfd63a8fa2fc9 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/scheduled-fargate-task.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/fargate/scheduled-fargate-task.ts @@ -76,6 +76,7 @@ export class ScheduledFargateTask extends ScheduledTaskBase { this.taskDefinition = new FargateTaskDefinition(this, 'ScheduledTaskDef', { memoryLimitMiB: taskImageOptions.memoryLimitMiB || 512, cpu: taskImageOptions.cpu || 256, + ephemeralStorageGiB: taskImageOptions.ephemeralStorageGiB, }); this.taskDefinition.addContainer('ScheduledContainer', { image: taskImageOptions.image, @@ -97,6 +98,9 @@ export class ScheduledFargateTask extends ScheduledTaskBase { if (props.memoryLimitMiB) { Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs-patterns:propertyIgnored', 'Property \'memoryLimitMiB\' is ignored, use \'scheduledFargateTaskImageOptions.memoryLimitMiB\' instead.'); } + if (props.ephemeralStorageGiB) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs-patterns:propertyIgnored', 'Property \'ephemeralStorageGiB\' is ignored, use \'scheduledFargateTaskImageOptions.ephemeralStorageGiB\' instead.'); + } if (props.runtimePlatform) { Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs-patterns:propertyIgnored', 'Property \'runtimePlatform\' is ignored.'); } diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/load-balanced-fargate-service-v2.test.ts b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/load-balanced-fargate-service-v2.test.ts index 53c34c69b5dde..b7417f4ce962f 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/load-balanced-fargate-service-v2.test.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/load-balanced-fargate-service-v2.test.ts @@ -225,6 +225,7 @@ describe('Application Load Balancer', () => { cpu: 256, assignPublicIp: true, memoryLimitMiB: 512, + ephemeralStorageGiB: 50, desiredCount: 3, enableECSManagedTags: true, enableExecuteCommand: true, @@ -349,6 +350,9 @@ describe('Application Load Balancer', () => { }, ], Cpu: '256', + EphemeralStorage: { + SizeInGiB: 50, + }, ExecutionRoleArn: { 'Fn::GetAtt': [ 'ExecutionRole605A040B', @@ -847,6 +851,7 @@ describe('Network Load Balancer', () => { cpu: 256, assignPublicIp: true, memoryLimitMiB: 512, + ephemeralStorageGiB: 80, desiredCount: 3, enableECSManagedTags: true, enableExecuteCommand: true, @@ -955,6 +960,9 @@ describe('Network Load Balancer', () => { }, ], Cpu: '256', + EphemeralStorage: { + SizeInGiB: 80, + }, ExecutionRoleArn: { 'Fn::GetAtt': [ 'ExecutionRole605A040B', diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/queue-processing-fargate-service.test.ts b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/queue-processing-fargate-service.test.ts index f69c898ba7c1a..b4290f9c15f54 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/queue-processing-fargate-service.test.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/queue-processing-fargate-service.test.ts @@ -497,6 +497,7 @@ testDeprecated('test Fargate queue worker service construct - with optional prop new ecsPatterns.QueueProcessingFargateService(stack, 'Service', { cluster, memoryLimitMiB: 512, + ephemeralStorageGiB: 100, image: ecs.ContainerImage.fromRegistry('test'), command: ['-c', '4', 'amazon.com'], enableLogging: false, @@ -565,6 +566,9 @@ testDeprecated('test Fargate queue worker service construct - with optional prop }), ], Family: 'fargate-task-family', + EphemeralStorage: { + SizeInGiB: 100, + }, }); }); diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/scheduled-fargate-task.test.ts b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/scheduled-fargate-task.test.ts index 8b318fd8b1167..3e98cac7e023e 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/scheduled-fargate-task.test.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/test/fargate/scheduled-fargate-task.test.ts @@ -92,6 +92,7 @@ test('Can create a scheduled Fargate Task - with optional props', () => { image: ecs.ContainerImage.fromRegistry('henk'), memoryLimitMiB: 512, cpu: 2, + ephemeralStorageGiB: 100, environment: { TRIGGER: 'CloudWatch Events' }, }, desiredTaskCount: 2, @@ -162,6 +163,9 @@ test('Can create a scheduled Fargate Task - with optional props', () => { Name: 'ScheduledContainer', }, ], + EphemeralStorage: { + SizeInGiB: 100, + }, }); }); From aa8484a154baea87f223c4b22135f3a845b836b3 Mon Sep 17 00:00:00 2001 From: yoshi Date: Sat, 2 Mar 2024 04:29:00 +0900 Subject: [PATCH 29/31] fix(sqs): `redrivePermission` is set to `byQueue` no matter what value is specified (#29130) ### Issue #29129 Closes #29129. ### Reason for this change When `redriveAllowPolicy.redrivePermission` is specified, any value will be output to template as `byQueue` ### Description of changes 1. Fix the evaluation order by enclosing the ternary operators in parentheses ```typescript ?? (props.redriveAllowPolicy.sourceQueues ? RedrivePermission.BY_QUEUE : RedrivePermission.ALLOW_ALL), ``` 2. Added a test case in `packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts` when redrivePermission is specified other than `BY_QUEUE`. 3. Added an integ test case in `packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts` ### Description of how you validated changes Added a test case in `packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts` when redrivePermission is specified other than `BY_QUEUE`. Added an integ test case in `packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts` And ran the test case. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-sqs.template.json | 10 +++++++ .../test/integ.sqs-source-queue-permission.ts | 12 +++++++-- packages/aws-cdk-lib/aws-sqs/lib/queue.ts | 2 +- packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts | 27 +++++++++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.js.snapshot/aws-cdk-sqs.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.js.snapshot/aws-cdk-sqs.template.json index a116bcb48f618..a17bfbfefa270 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.js.snapshot/aws-cdk-sqs.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.js.snapshot/aws-cdk-sqs.template.json @@ -2,11 +2,21 @@ "Resources": { "SourceQueue1F4BBA4BB": { "Type": "AWS::SQS::Queue", + "Properties": { + "RedriveAllowPolicy": { + "redrivePermission": "allowAll" + } + }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, "SourceQueue22481CB5A": { "Type": "AWS::SQS::Queue", + "Properties": { + "RedriveAllowPolicy": { + "redrivePermission": "denyAll" + } + }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts index e6079ba21f67e..3ff61390fd95d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-sqs/test/integ.sqs-source-queue-permission.ts @@ -7,8 +7,16 @@ const app = new App(); const stack = new Stack(app, 'aws-cdk-sqs'); -const sourceQueue1 = new Queue(stack, 'SourceQueue1'); -const sourceQueue2 = new Queue(stack, 'SourceQueue2'); +const sourceQueue1 = new Queue(stack, 'SourceQueue1', { + redriveAllowPolicy: { + redrivePermission: RedrivePermission.ALLOW_ALL, + }, +}); +const sourceQueue2 = new Queue(stack, 'SourceQueue2', { + redriveAllowPolicy: { + redrivePermission: RedrivePermission.DENY_ALL, + }, +}); new Queue(stack, 'DeadLetterQueue', { redriveAllowPolicy: { diff --git a/packages/aws-cdk-lib/aws-sqs/lib/queue.ts b/packages/aws-cdk-lib/aws-sqs/lib/queue.ts index c8a9c758978a9..f425536f89937 100644 --- a/packages/aws-cdk-lib/aws-sqs/lib/queue.ts +++ b/packages/aws-cdk-lib/aws-sqs/lib/queue.ts @@ -411,7 +411,7 @@ export class Queue extends QueueBase { redrivePermission: props.redriveAllowPolicy.redrivePermission // When `sourceQueues` is provided in `redriveAllowPolicy`, `redrivePermission` defaults to allow specified queues (`BY_QUEUE`); // otherwise, it defaults to allow all queues (`ALLOW_ALL`). - ?? props.redriveAllowPolicy.sourceQueues ? RedrivePermission.BY_QUEUE : RedrivePermission.ALLOW_ALL, + ?? (props.redriveAllowPolicy.sourceQueues ? RedrivePermission.BY_QUEUE : RedrivePermission.ALLOW_ALL), sourceQueueArns: props.redriveAllowPolicy.sourceQueues?.map(q => q.queueArn), } : undefined; diff --git a/packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts b/packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts index 956c8a77cdd7a..0ae7bc2919ef5 100644 --- a/packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts +++ b/packages/aws-cdk-lib/aws-sqs/test/sqs.test.ts @@ -753,6 +753,33 @@ describe('redriveAllowPolicy', () => { }); }); + test.each([ + [sqs.RedrivePermission.ALLOW_ALL, 'allowAll'], + [sqs.RedrivePermission.DENY_ALL, 'denyAll'], + ])('redrive permission can be set to %s', (permission, expected) => { + const stack = new Stack(); + new sqs.Queue(stack, 'Queue', { + redriveAllowPolicy: { + redrivePermission: permission, + }, + }); + + Template.fromStack(stack).templateMatches({ + 'Resources': { + 'Queue4A7E3555': { + 'Type': 'AWS::SQS::Queue', + 'Properties': { + 'RedriveAllowPolicy': { + 'redrivePermission': expected, + }, + }, + 'UpdateReplacePolicy': 'Delete', + 'DeletionPolicy': 'Delete', + }, + }, + }); + }); + test('explicit specification of dead letter source queues', () => { const stack = new Stack(); const sourceQueue1 = new sqs.Queue(stack, 'SourceQueue1'); From 7205143d563449ab211406da04d99bbbcdc7c8cc Mon Sep 17 00:00:00 2001 From: Michael Sambol Date: Fri, 1 Mar 2024 13:19:51 -0700 Subject: [PATCH 30/31] fix(batch): windows does not support readonlyRootFilesystem (#29145) Here's from the k8s docs: ``` securityContext.readOnlyRootFilesystem - not possible on Windows; write access is required for registry & system processes to run inside the container ``` Closes #29140. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../manifest.json | 25 +- .../stack.assets.json | 4 +- .../stack.template.json | 100 ++++ .../tree.json | 504 ++++++++++++------ .../test/integ.ecs-job-definition.ts | 12 + .../aws-batch/lib/ecs-container-definition.ts | 14 +- .../test/ecs-container-definition.test.ts | 29 +- .../aws-ecs/lib/runtime-platform.ts | 9 +- 8 files changed, 525 insertions(+), 172 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/manifest.json index d4e5db68eb0de..4b40b7a3b001e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.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}/80ca79d29007dc0a645c6568c47e0730a748e22b27eaba47a7336b97d459edcc.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9b59badf02feb83b2f2747da9bbab479669d1efa47acadf76785d017660f7d03.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -247,10 +247,7 @@ "/stack/ECSFargateJobDefn/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ECSFargateJobDefn327BE725", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "ECSFargateJobDefn327BE725" } ], "/stack/EcsDockerContainer/ExecutionRole/Resource": [ @@ -271,6 +268,24 @@ "data": "ECSDockerJobDefnF388CFCF" } ], + "/stack/WindowsFargateContainer/ExecutionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WindowsFargateContainerExecutionRoleAE15A6C1" + } + ], + "/stack/WindowsFargateContainer/ExecutionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WindowsFargateContainerExecutionRoleDefaultPolicyA16F3283" + } + ], + "/stack/WindowsJobDefinitio/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "WindowsJobDefinitio0652E08A" + } + ], "/stack/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.assets.json index be9330c4ed096..5af4252f1a2d2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.assets.json @@ -1,7 +1,7 @@ { "version": "36.0.0", "files": { - "80ca79d29007dc0a645c6568c47e0730a748e22b27eaba47a7336b97d459edcc": { + "9b59badf02feb83b2f2747da9bbab479669d1efa47acadf76785d017660f7d03": { "source": { "path": "stack.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "80ca79d29007dc0a645c6568c47e0730a748e22b27eaba47a7336b97d459edcc.json", + "objectKey": "9b59badf02feb83b2f2747da9bbab479669d1efa47acadf76785d017660f7d03.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-batch/test/integ.ecs-job-definition.js.snapshot/stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.template.json index 07857e0e45000..4f3da7e9b5dcc 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/stack.template.json @@ -997,6 +997,106 @@ "Timeout": {}, "Type": "container" } + }, + "WindowsFargateContainerExecutionRoleAE15A6C1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "WindowsFargateContainerExecutionRoleDefaultPolicyA16F3283": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/batch/job:*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "WindowsFargateContainerExecutionRoleDefaultPolicyA16F3283", + "Roles": [ + { + "Ref": "WindowsFargateContainerExecutionRoleAE15A6C1" + } + ] + } + }, + "WindowsJobDefinitio0652E08A": { + "Type": "AWS::Batch::JobDefinition", + "Properties": { + "ContainerProperties": { + "Environment": [], + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "WindowsFargateContainerExecutionRoleAE15A6C1", + "Arn" + ] + }, + "FargatePlatformConfiguration": {}, + "Image": "mcr.microsoft.com/dotnet/framework/runtime:4.7.2", + "NetworkConfiguration": { + "AssignPublicIp": "DISABLED" + }, + "ResourceRequirements": [ + { + "Type": "MEMORY", + "Value": "8192" + }, + { + "Type": "VCPU", + "Value": "2" + } + ], + "RuntimePlatform": { + "CpuArchitecture": "X86_64", + "OperatingSystemFamily": "WINDOWS_SERVER_2019_FULL" + } + }, + "JobDefinitionName": "windows-job-definition", + "PlatformCapabilities": [ + "FARGATE" + ], + "RetryStrategy": {}, + "Timeout": {}, + "Type": "container" + } } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/tree.json index a6452a3856934..6d0429bfdff10 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.js.snapshot/tree.json @@ -31,8 +31,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "PublicSubnet1": { @@ -75,16 +75,16 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Acl": { "id": "Acl", "path": "stack/vpc/PublicSubnet1/Acl", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTable": { @@ -105,8 +105,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTableAssociation": { @@ -124,8 +124,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultRoute": { @@ -144,8 +144,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EIP": { @@ -164,8 +164,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "NATGateway": { @@ -192,14 +192,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "PublicSubnet2": { @@ -242,16 +242,16 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Acl": { "id": "Acl", "path": "stack/vpc/PublicSubnet2/Acl", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTable": { @@ -272,8 +272,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTableAssociation": { @@ -291,8 +291,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultRoute": { @@ -311,8 +311,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EIP": { @@ -331,8 +331,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "NATGateway": { @@ -359,14 +359,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "PrivateSubnet1": { @@ -409,16 +409,16 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Acl": { "id": "Acl", "path": "stack/vpc/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTable": { @@ -439,8 +439,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTableAssociation": { @@ -458,8 +458,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultRoute": { @@ -478,14 +478,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "PrivateSubnet2": { @@ -528,16 +528,16 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Acl": { "id": "Acl", "path": "stack/vpc/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTable": { @@ -558,8 +558,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "RouteTableAssociation": { @@ -577,8 +577,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultRoute": { @@ -597,14 +597,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "IGW": { @@ -622,8 +622,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "VPCGW": { @@ -641,14 +641,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.Vpc", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "myFileSystem": { @@ -691,8 +691,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_efs.CfnFileSystem", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EfsSecurityGroup": { @@ -725,14 +725,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EfsMountTarget-PrivateSubnet1": { @@ -758,8 +758,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_efs.CfnMountTarget", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EfsMountTarget-PrivateSubnet2": { @@ -785,14 +785,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_efs.CfnMountTarget", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_efs.FileSystem", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "mySecret": { @@ -809,14 +809,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.Secret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "anotherSecret": { @@ -833,14 +833,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.CfnSecret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_secretsmanager.Secret", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "ssm": { @@ -858,14 +858,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ssm.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ssm.StringParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "myContainer": { @@ -880,8 +880,8 @@ "id": "ImportExecutionRole", "path": "stack/myContainer/ExecutionRole/ImportExecutionRole", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Resource": { @@ -905,8 +905,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultPolicy": { @@ -1007,34 +1007,34 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "batchDefaultLogGroup": { "id": "batchDefaultLogGroup", "path": "stack/myContainer/batchDefaultLogGroup", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsEc2ContainerDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "ECSJobDefn": { @@ -1167,14 +1167,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.CfnJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "myFargateContainer": { @@ -1189,8 +1189,8 @@ "id": "ImportExecutionRole", "path": "stack/myFargateContainer/ExecutionRole/ImportExecutionRole", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Resource": { @@ -1214,8 +1214,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultPolicy": { @@ -1269,34 +1269,34 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "batchDefaultLogGroup": { "id": "batchDefaultLogGroup", "path": "stack/myFargateContainer/batchDefaultLogGroup", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsFargateContainerDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "ECSFargateJobDefn": { @@ -1378,14 +1378,14 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.CfnJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "dockerImageAsset": { @@ -1396,22 +1396,22 @@ "id": "Staging", "path": "stack/dockerImageAsset/Staging", "constructInfo": { - "fqn": "aws-cdk-lib.AssetStaging", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Repository": { "id": "Repository", "path": "stack/dockerImageAsset/Repository", "constructInfo": { - "fqn": "aws-cdk-lib.aws_ecr.RepositoryBase", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ecr_assets.DockerImageAsset", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "EcsDockerContainer": { @@ -1426,8 +1426,8 @@ "id": "ImportExecutionRole", "path": "stack/EcsDockerContainer/ExecutionRole/ImportExecutionRole", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "Resource": { @@ -1451,8 +1451,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "DefaultPolicy": { @@ -1542,34 +1542,34 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Policy", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "batchDefaultLogGroup": { "id": "batchDefaultLogGroup", "path": "stack/EcsDockerContainer/batchDefaultLogGroup", "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsEc2ContainerDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "ECSDockerJobDefn": { @@ -1614,36 +1614,216 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.CfnJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_batch.EcsJobDefinition", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "WindowsFargateContainer": { + "id": "WindowsFargateContainer", + "path": "stack/WindowsFargateContainer", + "children": { + "ExecutionRole": { + "id": "ExecutionRole", + "path": "stack/WindowsFargateContainer/ExecutionRole", + "children": { + "ImportExecutionRole": { + "id": "ImportExecutionRole", + "path": "stack/WindowsFargateContainer/ExecutionRole/ImportExecutionRole", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stack/WindowsFargateContainer/ExecutionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stack/WindowsFargateContainer/ExecutionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/WindowsFargateContainer/ExecutionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/batch/job:*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "WindowsFargateContainerExecutionRoleDefaultPolicyA16F3283", + "roles": [ + { + "Ref": "WindowsFargateContainerExecutionRoleAE15A6C1" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "batchDefaultLogGroup": { + "id": "batchDefaultLogGroup", + "path": "stack/WindowsFargateContainer/batchDefaultLogGroup", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "WindowsJobDefinitio": { + "id": "WindowsJobDefinitio", + "path": "stack/WindowsJobDefinitio", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/WindowsJobDefinitio/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Batch::JobDefinition", + "aws:cdk:cloudformation:props": { + "containerProperties": { + "image": "mcr.microsoft.com/dotnet/framework/runtime:4.7.2", + "environment": [], + "executionRoleArn": { + "Fn::GetAtt": [ + "WindowsFargateContainerExecutionRoleAE15A6C1", + "Arn" + ] + }, + "resourceRequirements": [ + { + "type": "MEMORY", + "value": "8192" + }, + { + "type": "VCPU", + "value": "2" + } + ], + "fargatePlatformConfiguration": {}, + "networkConfiguration": { + "assignPublicIp": "DISABLED" + }, + "runtimePlatform": { + "cpuArchitecture": "X86_64", + "operatingSystemFamily": "WINDOWS_SERVER_2019_FULL" + } + }, + "jobDefinitionName": "windows-job-definition", + "platformCapabilities": [ + "FARGATE" + ], + "retryStrategy": {}, + "timeout": {}, + "type": "container" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "stack/BootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "stack/CheckBootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "BatchEcsJobDefinitionTest": { @@ -1670,22 +1850,22 @@ "id": "BootstrapVersion", "path": "BatchEcsJobDefinitionTest/DefaultTest/DeployAssert/BootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "BatchEcsJobDefinitionTest/DefaultTest/DeployAssert/CheckBootstrapVersion", "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } }, @@ -1710,8 +1890,8 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.3.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.ts index ec2ac7fdeaec8..42bd10cb5ebfc 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-batch/test/integ.ecs-job-definition.ts @@ -92,6 +92,18 @@ new batch.EcsJobDefinition(stack, 'ECSDockerJobDefn', { }), }); +// can successfully launch a Windows container +new batch.EcsJobDefinition(stack, 'WindowsJobDefinitio', { + jobDefinitionName: 'windows-job-definition', + container: new batch.EcsFargateContainerDefinition(stack, 'WindowsFargateContainer', { + image: ecs.ContainerImage.fromRegistry('mcr.microsoft.com/dotnet/framework/runtime:4.7.2'), + memory: Size.gibibytes(8), + cpu: 2, + fargateCpuArchitecture: ecs.CpuArchitecture.X86_64, + fargateOperatingSystemFamily: ecs.OperatingSystemFamily.WINDOWS_SERVER_2019_FULL, + }), +}); + new integ.IntegTest(app, 'BatchEcsJobDefinitionTest', { testCases: [stack], }); diff --git a/packages/aws-cdk-lib/aws-batch/lib/ecs-container-definition.ts b/packages/aws-cdk-lib/aws-batch/lib/ecs-container-definition.ts index 8d5369d7c88d9..2253cb7d4868c 100644 --- a/packages/aws-cdk-lib/aws-batch/lib/ecs-container-definition.ts +++ b/packages/aws-cdk-lib/aws-batch/lib/ecs-container-definition.ts @@ -1057,6 +1057,11 @@ export class EcsFargateContainerDefinition extends EcsContainerDefinitionBase im this.fargateCpuArchitecture = props.fargateCpuArchitecture; this.fargateOperatingSystemFamily = props.fargateOperatingSystemFamily; + if (this.fargateOperatingSystemFamily?.isWindows() && this.readonlyRootFilesystem) { + // see https://kubernetes.io/docs/concepts/windows/intro/ + throw new Error('Readonly root filesystem is not possible on Windows; write access is required for registry & system processes to run inside the container'); + } + // validates ephemeralStorageSize is within limits if (props.ephemeralStorageSize) { if (props.ephemeralStorageSize.toGibibytes() > 200) { @@ -1071,7 +1076,7 @@ export class EcsFargateContainerDefinition extends EcsContainerDefinitionBase im * @internal */ public _renderContainerDefinition(): CfnJobDefinition.ContainerPropertiesProperty { - return { + let containerDef = { ...super._renderContainerDefinition(), ephemeralStorage: this.ephemeralStorageSize? { sizeInGiB: this.ephemeralStorageSize?.toGibibytes(), @@ -1087,6 +1092,13 @@ export class EcsFargateContainerDefinition extends EcsContainerDefinitionBase im operatingSystemFamily: this.fargateOperatingSystemFamily?._operatingSystemFamily, }, }; + + // readonlyRootFilesystem isn't applicable to Windows, see https://kubernetes.io/docs/concepts/windows/intro/ + if (this.fargateOperatingSystemFamily?.isWindows()) { + containerDef.readonlyRootFilesystem = undefined; + } + + return containerDef; }; } diff --git a/packages/aws-cdk-lib/aws-batch/test/ecs-container-definition.test.ts b/packages/aws-cdk-lib/aws-batch/test/ecs-container-definition.test.ts index 038ba05965020..c771cd19a3d90 100644 --- a/packages/aws-cdk-lib/aws-batch/test/ecs-container-definition.test.ts +++ b/packages/aws-cdk-lib/aws-batch/test/ecs-container-definition.test.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import { capitalizePropertyNames } from './utils'; import { Size, Stack } from '../..'; import * as cdk from '../..'; -import { Template } from '../../assertions'; +import { Match, Template } from '../../assertions'; import { Vpc } from '../../aws-ec2'; import * as ecr from '../../aws-ecr'; import { DockerImageAsset } from '../../aws-ecr-assets'; @@ -1067,4 +1067,31 @@ describe('Fargate containers', () => { }), })).toThrow("ECS Fargate container 'EcsFargateContainer2' specifies 'ephemeralStorageSize' at 201 > 200 GB"); }); + + test('readonlyRootFilesystem can\'t be true with Windows family', () => { + expect(() => new EcsJobDefinition(stack, 'ECSJobDefn', { + container: new EcsFargateContainerDefinition(stack, 'EcsFargateContainer', { + ...defaultContainerProps, + readonlyRootFilesystem: true, + fargateOperatingSystemFamily: ecs.OperatingSystemFamily.WINDOWS_SERVER_2004_CORE, + }), + })).toThrow('Readonly root filesystem is not possible on Windows; write access is required for registry & system processes to run inside the container'); + }); + + test('readonlyRootFilesystem is undefined with Windows family', () => { + // WHEN + new EcsJobDefinition(stack, 'ECSJobDefn', { + container: new EcsFargateContainerDefinition(stack, 'EcsFargateContainer', { + ...defaultContainerProps, + fargateOperatingSystemFamily: ecs.OperatingSystemFamily.WINDOWS_SERVER_2004_CORE, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', { + ContainerProperties: { + ReadonlyRootFilesystem: Match.absent(), + }, + }); + }); }); diff --git a/packages/aws-cdk-lib/aws-ecs/lib/runtime-platform.ts b/packages/aws-cdk-lib/aws-ecs/lib/runtime-platform.ts index 37d760c62e657..250e64a1f9ca4 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/runtime-platform.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/runtime-platform.ts @@ -88,6 +88,13 @@ export class OperatingSystemFamily { * @param _operatingSystemFamily The operating system family. */ private constructor(public readonly _operatingSystemFamily: string) { } + + /** + * Returns true if the operating system family is Windows + */ + public isWindows(): boolean { + return this._operatingSystemFamily?.toLowerCase().startsWith('windows') ? true : false; + } } /** @@ -107,4 +114,4 @@ export interface RuntimePlatform { * @default - Undefined. */ readonly operatingSystemFamily?: OperatingSystemFamily; -} \ No newline at end of file +} From ebe2adff61c5cefcd4576bbc22c3b5d27b390d92 Mon Sep 17 00:00:00 2001 From: Ruvim Radchishin <39605354+ruvimrd@users.noreply.github.com> Date: Fri, 1 Mar 2024 13:49:40 -0800 Subject: [PATCH 31/31] fix(cloudwatch): allow up to 30 dimensions for metric (#29341) ### Issue # (if applicable) Closes #29322. ### Reason for this change [AWS::CloudWatch::Alarm](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html) allows up to 30 dimension items, while the L2 [construct](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Metric.html#dimensions) for Metric allows up to 10. ### Description of changes Increased hard limit from 10 -> 30 ### Description of how you validated changes Updated unit test, added new integration test ### Checklist - [X] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...k-cloudwatch-metric-dimensions.assets.json | 19 ++ ...cloudwatch-metric-dimensions.template.json | 105 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 ++ .../manifest.json | 119 +++++++++++ ...efaultTestDeployAssert1196DF0F.assets.json | 19 ++ ...aultTestDeployAssert1196DF0F.template.json | 36 ++++ .../tree.json | 191 ++++++++++++++++++ .../test/integ.metric-with-dimensions.ts | 39 ++++ .../aws-cdk-lib/aws-cloudwatch/lib/metric.ts | 4 +- .../aws-cloudwatch/test/metrics.test.ts | 48 ++++- 11 files changed, 587 insertions(+), 6 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.assets.json new file mode 100644 index 0000000000000..16284e1e5e694 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "5b7b9376300e8d5da09834e7dfc97bf825e9354f770b53e1bc3e3d0a9de8f10c": { + "source": { + "path": "aws-cdk-cloudwatch-metric-dimensions.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5b7b9376300e8d5da09834e7dfc97bf825e9354f770b53e1bc3e3d0a9de8f10c.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.template.json new file mode 100644 index 0000000000000..54d0bd59f3349 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/aws-cdk-cloudwatch-metric-dimensions.template.json @@ -0,0 +1,105 @@ +{ + "Resources": { + "queue": { + "Type": "AWS::SQS::Queue" + }, + "Alarm7103F465": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "DatapointsToAlarm": 2, + "Dimensions": [ + { + "Name": "BlankD1", + "Value": "value1" + }, + { + "Name": "BlankD10", + "Value": "value10" + }, + { + "Name": "BlankD2", + "Value": "value2" + }, + { + "Name": "BlankD3", + "Value": "value3" + }, + { + "Name": "BlankD4", + "Value": "value4" + }, + { + "Name": "BlankD5", + "Value": "value5" + }, + { + "Name": "BlankD6", + "Value": "value6" + }, + { + "Name": "BlankD7", + "Value": "value7" + }, + { + "Name": "BlankD8", + "Value": "value8" + }, + { + "Name": "BlankD9", + "Value": "value9" + }, + { + "Name": "QueueName", + "Value": { + "Fn::GetAtt": [ + "queue", + "QueueName" + ] + } + } + ], + "EvaluationPeriods": 3, + "MetricName": "ApproximateNumberOfMessagesVisible", + "Namespace": "AWS/SQS", + "Period": 300, + "Statistic": "Average", + "Threshold": 100 + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/integ.json new file mode 100644 index 0000000000000..b3f4a8a62b0cf --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "metric-with-dimensions-test/DefaultTest": { + "stacks": [ + "aws-cdk-cloudwatch-metric-dimensions" + ], + "assertionStack": "metric-with-dimensions-test/DefaultTest/DeployAssert", + "assertionStackName": "metricwithdimensionstestDefaultTestDeployAssert1196DF0F" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/manifest.json new file mode 100644 index 0000000000000..31a9dc49d6c44 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/manifest.json @@ -0,0 +1,119 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-cloudwatch-metric-dimensions.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-cloudwatch-metric-dimensions.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-cloudwatch-metric-dimensions": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-cloudwatch-metric-dimensions.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5b7b9376300e8d5da09834e7dfc97bf825e9354f770b53e1bc3e3d0a9de8f10c.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-cloudwatch-metric-dimensions.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-cloudwatch-metric-dimensions.assets" + ], + "metadata": { + "/aws-cdk-cloudwatch-metric-dimensions/queue": [ + { + "type": "aws:cdk:logicalId", + "data": "queue" + } + ], + "/aws-cdk-cloudwatch-metric-dimensions/Alarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Alarm7103F465" + } + ], + "/aws-cdk-cloudwatch-metric-dimensions/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-cloudwatch-metric-dimensions/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-cloudwatch-metric-dimensions" + }, + "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "metricwithdimensionstestDefaultTestDeployAssert1196DF0F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets" + ], + "metadata": { + "/metric-with-dimensions-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/metric-with-dimensions-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "metric-with-dimensions-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets.json new file mode 100644 index 0000000000000..c673635d60504 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/metricwithdimensionstestDefaultTestDeployAssert1196DF0F.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/tree.json new file mode 100644 index 0000000000000..f48626e919d06 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.js.snapshot/tree.json @@ -0,0 +1,191 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-cloudwatch-metric-dimensions": { + "id": "aws-cdk-cloudwatch-metric-dimensions", + "path": "aws-cdk-cloudwatch-metric-dimensions", + "children": { + "queue": { + "id": "queue", + "path": "aws-cdk-cloudwatch-metric-dimensions/queue", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Alarm": { + "id": "Alarm", + "path": "aws-cdk-cloudwatch-metric-dimensions/Alarm", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-cloudwatch-metric-dimensions/Alarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", + "aws:cdk:cloudformation:props": { + "comparisonOperator": "GreaterThanOrEqualToThreshold", + "datapointsToAlarm": 2, + "dimensions": [ + { + "name": "BlankD1", + "value": "value1" + }, + { + "name": "BlankD10", + "value": "value10" + }, + { + "name": "BlankD2", + "value": "value2" + }, + { + "name": "BlankD3", + "value": "value3" + }, + { + "name": "BlankD4", + "value": "value4" + }, + { + "name": "BlankD5", + "value": "value5" + }, + { + "name": "BlankD6", + "value": "value6" + }, + { + "name": "BlankD7", + "value": "value7" + }, + { + "name": "BlankD8", + "value": "value8" + }, + { + "name": "BlankD9", + "value": "value9" + }, + { + "name": "QueueName", + "value": { + "Fn::GetAtt": [ + "queue", + "QueueName" + ] + } + } + ], + "evaluationPeriods": 3, + "metricName": "ApproximateNumberOfMessagesVisible", + "namespace": "AWS/SQS", + "period": 300, + "statistic": "Average", + "threshold": 100 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.Alarm", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-cloudwatch-metric-dimensions/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-cloudwatch-metric-dimensions/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "metric-with-dimensions-test": { + "id": "metric-with-dimensions-test", + "path": "metric-with-dimensions-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "metric-with-dimensions-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "metric-with-dimensions-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "metric-with-dimensions-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "metric-with-dimensions-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "metric-with-dimensions-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.ts new file mode 100644 index 0000000000000..204d876e989b7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.metric-with-dimensions.ts @@ -0,0 +1,39 @@ +// Creates an Alarm with a Metric that contains 11 dimensions +// 1 valid dimension used, with 10 blank ones since it's hard to find a resource with more than 5 dimensions that is feasable to run tests with +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-cloudwatch-metric-dimensions'); + +const queue = new cdk.CfnResource(stack, 'queue', { type: 'AWS::SQS::Queue' }); + +const numberOfMessagesVisibleMetric = new cloudwatch.Metric({ + namespace: 'AWS/SQS', + metricName: 'ApproximateNumberOfMessagesVisible', + dimensionsMap: { + QueueName: queue.getAtt('QueueName').toString(), + BlankD1: 'value1', + BlankD2: 'value2', + BlankD3: 'value3', + BlankD4: 'value4', + BlankD5: 'value5', + BlankD6: 'value6', + BlankD7: 'value7', + BlankD8: 'value8', + BlankD9: 'value9', + BlankD10: 'value10', + }, +}); + +numberOfMessagesVisibleMetric.createAlarm(stack, 'Alarm', { + threshold: 100, + evaluationPeriods: 3, + datapointsToAlarm: 2, +}); + +new IntegTest(app, 'metric-with-dimensions-test', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-cloudwatch/lib/metric.ts b/packages/aws-cdk-lib/aws-cloudwatch/lib/metric.ts index 99f7a27bc138c..8b6c05bc45122 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/lib/metric.ts +++ b/packages/aws-cdk-lib/aws-cloudwatch/lib/metric.ts @@ -509,8 +509,8 @@ export class Metric implements IMetric { } var dimsArray = Object.keys(dims); - if (dimsArray?.length > 10) { - throw new Error(`The maximum number of dimensions is 10, received ${dimsArray.length}`); + if (dimsArray?.length > 30) { + throw new Error(`The maximum number of dimensions is 30, received ${dimsArray.length}`); } dimsArray.map(key => { diff --git a/packages/aws-cdk-lib/aws-cloudwatch/test/metrics.test.ts b/packages/aws-cdk-lib/aws-cloudwatch/test/metrics.test.ts index ac0d0186ea014..42f3bd14a1fbb 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/test/metrics.test.ts +++ b/packages/aws-cdk-lib/aws-cloudwatch/test/metrics.test.ts @@ -112,7 +112,7 @@ describe('Metrics', () => { }); - testDeprecated('throws error when there are more than 10 dimensions', () => { + testDeprecated('throws error when there are more than 30 dimensions', () => { expect(() => { new Metric({ namespace: 'Test', @@ -130,13 +130,33 @@ describe('Metrics', () => { dimensionI: 'value9', dimensionJ: 'value10', dimensionK: 'value11', + dimensionL: 'value12', + dimensionM: 'value13', + dimensionN: 'value14', + dimensionO: 'value15', + dimensionP: 'value16', + dimensionQ: 'value17', + dimensionR: 'value18', + dimensionS: 'value19', + dimensionT: 'value20', + dimensionU: 'value21', + dimensionV: 'value22', + dimensionW: 'value23', + dimensionX: 'value24', + dimensionY: 'value25', + dimensionZ: 'value26', + dimensionAA: 'value27', + dimensionAB: 'value28', + dimensionAC: 'value29', + dimensionAD: 'value30', + dimensionAE: 'value31', }, } ); - }).toThrow(/The maximum number of dimensions is 10, received 11/); + }).toThrow(/The maximum number of dimensions is 30, received 31/); }); - test('throws error when there are more than 10 dimensions in dimensionsMap', () => { + test('throws error when there are more than 30 dimensions in dimensionsMap', () => { expect(() => { new Metric({ namespace: 'Test', @@ -154,9 +174,29 @@ describe('Metrics', () => { dimensionI: 'value9', dimensionJ: 'value10', dimensionK: 'value11', + dimensionL: 'value12', + dimensionM: 'value13', + dimensionN: 'value14', + dimensionO: 'value15', + dimensionP: 'value16', + dimensionQ: 'value17', + dimensionR: 'value18', + dimensionS: 'value19', + dimensionT: 'value20', + dimensionU: 'value21', + dimensionV: 'value22', + dimensionW: 'value23', + dimensionX: 'value24', + dimensionY: 'value25', + dimensionZ: 'value26', + dimensionAA: 'value27', + dimensionAB: 'value28', + dimensionAC: 'value29', + dimensionAD: 'value30', + dimensionAE: 'value31', }, } ); - }).toThrow(/The maximum number of dimensions is 10, received 11/); + }).toThrow(/The maximum number of dimensions is 30, received 31/); });