From ae7d1814900fc10ab489bc7a4cfe8ccd1694e8f8 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 7 Aug 2024 02:35:35 +0300 Subject: [PATCH 01/12] feat(region-info): update Metadata regions (#31044) Update the list of regions where the CDK deploys the `AWS::CDK::Metadata` resource. --- packages/aws-cdk-lib/region-info/build-tools/metadata.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts index c97ef832bf8ad..eb74c7396da1d 100644 --- a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts +++ b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts @@ -12,6 +12,7 @@ export const AWS_CDK_METADATA = new Set([ 'ap-east-1', 'ap-northeast-1', 'ap-northeast-2', + 'ap-northeast-3', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', From 71f07e4511206f66d3c31216d11b8b56534ac626 Mon Sep 17 00:00:00 2001 From: Ali Servet Donmez Date: Wed, 7 Aug 2024 02:32:35 +0200 Subject: [PATCH 02/12] docs(opensearchservice): fix broken Markdown due to an invisible char (#31007) ### Issue # (if applicable) Closes #. ### Reason for this change For some invisible char in the Markdown, it wasn't rendered correctly. ### Description of changes I am unsure what was there, but replacing the "space" between `##` and `Enable` with a regular space (i.e., ' ') fixed it. ### Description of how you validated changes After this change, using the Markdown preview feature in my editor, as well as regular Markdown syntax highlighting, worked as expected. ### 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-opensearchservice/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-opensearchservice/README.md b/packages/aws-cdk-lib/aws-opensearchservice/README.md index e24f2df325e25..dcff581a78857 100644 --- a/packages/aws-cdk-lib/aws-opensearchservice/README.md +++ b/packages/aws-cdk-lib/aws-opensearchservice/README.md @@ -464,7 +464,7 @@ const domain = new Domain(this, 'Domain', { }); ``` -## Enable support for Multi-AZ with Standby deployment +## Enable support for Multi-AZ with Standby deployment The domain can be configured to use [multi-AZ with standby](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/managedomains-multiaz.html#managedomains-za-standby). From 6ec69b9184417c7fb5d4df808b57ae59c546753c Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 7 Aug 2024 04:13:24 +0300 Subject: [PATCH 03/12] feat(region-info): update Metadata regions (#31046) Update the list of regions where the CDK deploys the `AWS::CDK::Metadata` resource. --- packages/aws-cdk-lib/region-info/build-tools/metadata.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts index eb74c7396da1d..0ef7b18fb82a2 100644 --- a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts +++ b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts @@ -14,14 +14,19 @@ export const AWS_CDK_METADATA = new Set([ 'ap-northeast-2', 'ap-northeast-3', 'ap-south-1', + 'ap-south-2', 'ap-southeast-1', 'ap-southeast-2', + 'ap-southeast-3', + 'ap-southeast-4', 'ca-central-1', 'cn-north-1', 'cn-northwest-1', 'eu-central-1', + 'eu-central-2', 'eu-north-1', 'eu-south-1', + 'eu-south-2', 'eu-west-1', 'eu-west-2', 'eu-west-3', From 9025635e7401388a4192d34b9fbe2ae28d849587 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 7 Aug 2024 06:16:08 +0300 Subject: [PATCH 04/12] feat(region-info): update Metadata regions (#31047) Update the list of regions where the CDK deploys the `AWS::CDK::Metadata` resource. --- packages/aws-cdk-lib/region-info/build-tools/metadata.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts index 0ef7b18fb82a2..58a7436ec118b 100644 --- a/packages/aws-cdk-lib/region-info/build-tools/metadata.ts +++ b/packages/aws-cdk-lib/region-info/build-tools/metadata.ts @@ -20,6 +20,7 @@ export const AWS_CDK_METADATA = new Set([ 'ap-southeast-3', 'ap-southeast-4', 'ca-central-1', + 'ca-west-1', 'cn-north-1', 'cn-northwest-1', 'eu-central-1', From e17fdd76959e8aafd07cfa1db34325f1c24b3acf Mon Sep 17 00:00:00 2001 From: shikha372 Date: Wed, 7 Aug 2024 08:21:02 -0700 Subject: [PATCH 05/12] feat(vpc): support custom route and subnet (#30538) ### Issue # (if applicable) Closes [RFC#507](https://github.com/aws/aws-cdk-rfcs/blob/57fd92a7f20e242b96885264c12567493f5e867f/text/0507-subnets.md). Issue#[5927](https://github.com/aws/aws-cdk/issues/5927) Tracking Ticket https://github.com/aws/aws-cdk/issues/30762 ### Reason for this change This PR implements below RFC for Full Control VPC configuration Implementing RFC [Full Control VPC](https://github.com/aws/aws-cdk-rfcs/blob/57fd92a7f20e242b96885264c12567493f5e867f/text/0507-subnets.md) ### Description of changes Experimental API for VPC Lifecycle Doc: https://github.com/cdklabs/team-internal/blob/main/docs/construct-library-lifecycle.md - Introduced a new alpha module for VPCV2 - Both new class VPCV2 and SubnetV2 implement IVPC and ISubnet for compatibility with other constructs - Introduced a new IPAM class to support IP address alllocation through IPAM pool. - Validations of IP ranges assigned to subnet. - L2 class(Route) to define custom routes under the subnet - L2s for gateways like Egress only IGW and NATGW. ### Next Steps: Iterate on the API with the feedback from community and team to make it ergonomic. Close on the features listed in [tracking ticket](https://github.com/aws/aws-cdk/issues/30762) Will follow the exit criteria for this experimental API as outlined in below doc: https://github.com/cdklabs/team-internal/blob/main/docs/construct-library-lifecycle.md ### Description of how you validated changes Added unit tests with current coverage ~70% Added integration tests for subnet, vpc and routing features. ### 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/aws-ec2-alpha/.eslintrc.js | 4 + packages/@aws-cdk/aws-ec2-alpha/.gitignore | 23 + packages/@aws-cdk/aws-ec2-alpha/.npmignore | 28 + packages/@aws-cdk/aws-ec2-alpha/LICENSE | 201 ++ packages/@aws-cdk/aws-ec2-alpha/NOTICE | 2 + packages/@aws-cdk/aws-ec2-alpha/README.md | 199 ++ packages/@aws-cdk/aws-ec2-alpha/awslint.json | 7 + .../@aws-cdk/aws-ec2-alpha/jest.config.js | 10 + packages/@aws-cdk/aws-ec2-alpha/lib/index.ts | 10 + packages/@aws-cdk/aws-ec2-alpha/lib/ipam.ts | 542 ++++ packages/@aws-cdk/aws-ec2-alpha/lib/route.ts | 587 ++++ .../@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts | 416 +++ packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 382 +++ .../@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts | 368 +++ packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts | 487 +++ packages/@aws-cdk/aws-ec2-alpha/package.json | 107 + .../aws-cdk-routev2-alpha.assets.json | 19 + .../aws-cdk-routev2-alpha.template.json | 115 + ...routev2-dynamodbendpoint-alpha.assets.json | 19 + ...utev2-dynamodbendpoint-alpha.template.json | 147 + ...dk-routev2-egressonlyigw-alpha.assets.json | 19 + ...-routev2-egressonlyigw-alpha.template.json | 134 + .../aws-cdk-routev2-igw-alpha.assets.json | 19 + .../aws-cdk-routev2-igw-alpha.template.json | 154 + ...ws-cdk-routev2-networkif-alpha.assets.json | 19 + ...-cdk-routev2-networkif-alpha.template.json | 115 + ...cdk-routev2-privatenatgw-alpha.assets.json | 19 + ...k-routev2-privatenatgw-alpha.template.json | 152 + ...-cdk-routev2-publicnatgw-alpha.assets.json | 19 + ...dk-routev2-publicnatgw-alpha.template.json | 204 ++ ...routev2-virtualprivategw-alpha.assets.json | 19 + ...utev2-virtualprivategw-alpha.template.json | 157 + ...outev2-vpcpeerconnection-alpha.assets.json | 19 + ...tev2-vpcpeerconnection-alpha.template.json | 115 + .../test/integ.route-v2.js.snapshot/cdk.out | 1 + .../integ.route-v2.js.snapshot/integ.json | 12 + ...efaultTestDeployAssertA16689B0.assets.json | 19 + ...aultTestDeployAssertA16689B0.template.json | 36 + ...efaultTestDeployAssert46FEDE40.assets.json | 19 + ...aultTestDeployAssert46FEDE40.template.json | 36 + ...efaultTestDeployAssert04E3783E.assets.json | 19 + ...aultTestDeployAssert04E3783E.template.json | 36 + ...efaultTestDeployAssertF3FA2F74.assets.json | 19 + ...aultTestDeployAssertF3FA2F74.template.json | 36 + ...efaultTestDeployAssert4B12233C.assets.json | 19 + ...aultTestDeployAssert4B12233C.template.json | 36 + ...efaultTestDeployAssertC0DDB875.assets.json | 19 + ...aultTestDeployAssertC0DDB875.template.json | 36 + ...efaultTestDeployAssert90B004F4.assets.json | 19 + ...aultTestDeployAssert90B004F4.template.json | 36 + ...efaultTestDeployAssert4C509DCE.assets.json | 19 + ...aultTestDeployAssert4C509DCE.template.json | 36 + ...efaultTestDeployAssert77221752.assets.json | 19 + ...aultTestDeployAssert77221752.template.json | 36 + .../integ.route-v2.js.snapshot/manifest.json | 1265 ++++++++ .../test/integ.route-v2.js.snapshot/tree.json | 2607 +++++++++++++++++ .../aws-ec2-alpha/test/integ.route-v2.ts | 160 + .../aws-cdk-vpcv2-alpha-new.assets.json | 19 + .../aws-cdk-vpcv2-alpha-new.template.json | 279 ++ .../test/integ.subnet-v2.js.snapshot/cdk.out | 1 + .../integ.subnet-v2.js.snapshot/integ.json | 12 + ...efaultTestDeployAssertCF40BD53.assets.json | 19 + ...aultTestDeployAssertCF40BD53.template.json | 36 + .../integ.subnet-v2.js.snapshot/manifest.json | 212 ++ .../integ.subnet-v2.js.snapshot/tree.json | 552 ++++ .../aws-ec2-alpha/test/integ.subnet-v2.ts | 80 + .../aws-cdk-vpcv2-alpha.assets.json | 19 + .../aws-cdk-vpcv2-alpha.template.json | 329 +++ .../integ.vpc-v2-alpha.js.snapshot/cdk.out | 1 + .../integ.vpc-v2-alpha.js.snapshot/integ.json | 12 + ...efaultTestDeployAssertCF40BD53.assets.json | 19 + ...aultTestDeployAssertCF40BD53.template.json | 36 + .../manifest.json | 272 ++ .../integ.vpc-v2-alpha.js.snapshot/tree.json | 608 ++++ .../aws-ec2-alpha/test/integ.vpc-v2-alpha.ts | 108 + .../@aws-cdk/aws-ec2-alpha/test/ipam.test.ts | 150 + .../@aws-cdk/aws-ec2-alpha/test/route.test.ts | 674 +++++ .../aws-ec2-alpha/test/subnet-v2.test.ts | 303 ++ packages/@aws-cdk/aws-ec2-alpha/test/util.ts | 27 + .../aws-ec2-alpha/test/vpc-v2.test.ts | 260 ++ .../cli-lib-alpha/THIRD_PARTY_LICENSES | 2 +- packages/@aws-cdk/cx-api/FEATURE_FLAGS.md | 2 +- yarn.lock | 2 +- 83 files changed, 13408 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/.eslintrc.js create mode 100644 packages/@aws-cdk/aws-ec2-alpha/.gitignore create mode 100644 packages/@aws-cdk/aws-ec2-alpha/.npmignore create mode 100644 packages/@aws-cdk/aws-ec2-alpha/LICENSE create mode 100644 packages/@aws-cdk/aws-ec2-alpha/NOTICE create mode 100644 packages/@aws-cdk/aws-ec2-alpha/README.md create mode 100644 packages/@aws-cdk/aws-ec2-alpha/awslint.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/jest.config.js create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/index.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/ipam.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/route.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/util.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/package.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/ipam.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/route.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/util.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/.eslintrc.js b/packages/@aws-cdk/aws-ec2-alpha/.eslintrc.js new file mode 100644 index 0000000000000..73d2505a85a7f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/.eslintrc.js @@ -0,0 +1,4 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +baseConfig.rules['import/order'] = 'off'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-ec2-alpha/.gitignore b/packages/@aws-cdk/aws-ec2-alpha/.gitignore new file mode 100644 index 0000000000000..3e895fc51317c --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/.gitignore @@ -0,0 +1,23 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml +!**/*.snapshot/**/asset.*/*.js +!**/*.snapshot/**/asset.*/*.d.ts + +!**/*.snapshot/**/asset.*/** diff --git a/packages/@aws-cdk/aws-ec2-alpha/.npmignore b/packages/@aws-cdk/aws-ec2-alpha/.npmignore new file mode 100644 index 0000000000000..b94897de6fcce --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/.npmignore @@ -0,0 +1,28 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +!*.lit.ts +**/*.snapshot diff --git a/packages/@aws-cdk/aws-ec2-alpha/LICENSE b/packages/@aws-cdk/aws-ec2-alpha/LICENSE new file mode 100644 index 0000000000000..dcf28b52a83af --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-ec2-alpha/NOTICE b/packages/@aws-cdk/aws-ec2-alpha/NOTICE new file mode 100644 index 0000000000000..c0b1f046c881a --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md new file mode 100644 index 0000000000000..0de7e39d27d35 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -0,0 +1,199 @@ +# Amazon VpcV2 Construct Library + + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. They are subject to non-backward compatible changes or removal in any future version. These are not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package. + +--- + + + +## VpcV2 + +`VpcV2` is a re-write of the [`ec2.Vpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html) construct. This new construct enables higher level of customization +on the VPC being created. `VpcV2` implements the existing [`IVpc`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IVpc.html), therefore, +`VpcV2` is compatible with other constructs that accepts `IVpc` (e.g. [`ApplicationLoadBalancer`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer.html#construct-props)). + +To create a VPC with both IPv4 and IPv6 support: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; + +const stack = new cdk.Stack(app, 'aws-cdk-vpcv2'); +new vpc_v2.VpcV2(stack, 'Vpc', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.0.0.0/24'), + secondaryAddressBlocks: [ + vpc_v2.IpAddresses.amazonProvidedIpv6({cidrBlockName: 'AmazonProvidedIpv6'}), + ], +}); +``` + +`VpcV2` does not automatically create subnets or allocate IP addresses, which is different from the `Vpc` construct. + +Importing existing VPC in an account into CDK as a `VpcV2` is not yet supported. + +## SubnetV2 + +`SubnetV2` is a re-write of the [`ec2.Subnet`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Subnet.html) construct. +This new construct can be used to add subnets to a `VpcV2` instance: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; + +const stack = new cdk.Stack(app, 'aws-cdk-vpcv2'); +const vpc = new vpc_v2.VpcV2(stack, 'Vpc', { + secondaryAddressBlocks: [ + vpc_v2.IpAddresses.amazonProvidedIpv6({ cidrBlockName: 'AmazonProvidedIp'}), + ], +}); +const vpcFirstIpV6Cidr = Fn.select(0, vpc.ipv6CidrBlocks); +const subCidrs = Fn.cidr(vpcFirstIpV6Cidr, 3, 32); +new vpc_v2.SubnetV2(stack, 'subnetA', { + vpc, + availabilityZone: 'us-east-1a', + cidrBlock: new vpc_v2.IpCidr('10.0.0.0/24'), + ipv6CidrBlock: new vpc_v2.IpCidr(Fn.select(0, subCidrs)), + subnetType: ec2.SubnetType.PRIVATE_ISOLATED, +}) +``` + +Same as `VpcV2`, importing existing subnets is not yet supported. + +## IP Addresses Management + +By default `VpcV2` uses `10.0.0.0/16` as the primary CIDR if none is defined. +Additional CIDRs can be adding to the VPC via the `secondaryAddressBlocks` prop. +The following example illustrates the different options of defining the address blocks: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; + +const stack = new cdk.Stack(app, 'aws-cdk-vpcv2'); +const ipam = new Ipam(stack, 'Ipam', { + operatingRegion: ['us-west-1'] +}); +const ipamPublicPool = ipam.publicScope.addPool('PublicPoolA', { + addressFamily: vpc_v2.AddressFamily.IP_V6, + awsService: 'ec2', + locale: 'us-west-1', + publicIpSource: vpc_v2.IpamPoolPublicIpSource.AMAZON, +}); +ipamPublicPool.provisionCidr('PublicPoolACidrA', { netmaskLength: 52 } ); + +const ipamPrivatePool = ipam.privateScope.addPool('PrivatePoolA', { + addressFamily: vpc_v2.AddressFamily.IP_V4, +}); +ipamPrivatePool.provisionCidr('PrivatePoolACidrA', { netmaskLength: 8 } ); + +new vpc_v2.VpcV2(stack, 'Vpc', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.0.0.0/24'), + secondaryAddressBlocks: [ + vpc_v2.IpAddresses.amazonProvidedIpv6({ cidrBlockName: 'AmazonIpv6' }), + vpc_v2.IpAddresses.ipv6Ipam({ + ipv6IpamPool: ipamPublicPool, + ipv6NetmaskLength: 52, + cidrBlockName: 'ipv6Ipam', + }), + vpc_v2.IpAddresses.ipv4Ipam({ + ipv6IpamPool: ipamPrivatePool, + ipv6NetmaskLength: 8, + cidrBlockName: 'ipv4Ipam', + }), + ], +}); +``` + +Since `VpcV2` does not create subnets automatically, users have full control over IP addresses allocation across subnets. + + +## Routing + +`RouteTable` is a new construct that allows for route tables to be customized in a variety of ways. For instance, the following example shows how a custom route table can be created and appended to a subnet: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; + +const myVpc = new vpc_v2.VpcV2(stack, 'Vpc', {...}); +const routeTable = new vpc_v2.RouteTable(stack, 'RouteTable', { + vpc: myVpc, +}); +const subnet = new vpc_v2.SubnetV2(stack, 'Subnet', { + vpc, + routeTable, + ..., +}); +``` + +`Route`s can be created to link subnets to various different AWS services via gateways and endpoints. Each unique route target has its own dedicated construct that can be routed to a given subnet via the `Route` construct. An example using the `InternetGateway` construct can be seen below: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; + +const myVpc = new vpc_v2.VpcV2(stack, 'Vpc', {...}); +const routeTable = new vpc_v2.RouteTable(stack, 'RouteTable', { + vpc: vpc.myVpc, +}); +const subnet = new vpc_v2.SubnetV2(stack, 'Subnet', {...}); + +const igw = new vpc_v2.InternetGateway(stack, 'IGW', { + vpcId: vpc.myVpc, +}); +new vpc_v2.Route(stack, 'IgwRoute', { + routeTable, + destination: vpc_v2.IpAddresses.ipv4('0.0.0.0/0'), + target: igw, +}); +``` + +Other route targets may require a deeper set of parameters to set up properly. For instance, the example below illustrates how to set up a `NatGateway`: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; + +const myVpc = new vpc_v2.VpcV2(stack, 'Vpc', {...}); +const routeTable = new vpc_v2.RouteTable(stack, 'RouteTable', { + vpcId: vpc.myVpc, +}); +const subnet = new vpc_v2.SubnetV2(stack, 'Subnet', {...}); + +const natgw = new vpc_v2.NatGateway(stack, 'NatGW', { + subnet: subnet, + vpcId: vpc.myVpc, + connectivityType: 'private', + privateIpAddress: '10.0.0.42', +}); +new vpc_v2.Route(stack, 'NatGwRoute', { + routeTable, + destination: vpc_v2.IpAddresses.ipv4('0.0.0.0/0'), + target: natgw, +}); +``` + +It is also possible to set up endpoints connecting other AWS services. For instance, the example below illustrates the linking of a Dynamo DB endpoint via the existing `ec2.GatewayVpcEndpoint` construct as a route target: + +```ts +import * as vpc_v2 from '@aws-cdk/aws-ec2-alpha'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; + +const myVpc = new vpc_v2.VpcV2(stack, 'Vpc', {...}); +const routeTable = new vpc_v2.RouteTable(stack, 'RouteTable', { + vpcId: vpc.myVpc, +}); +const subnet = new vpc_v2.SubnetV2(stack, 'Subnet', {...}); + +const dynamoEndpoint = new GatewayVpcEndpoint(stack, 'DynamoEndpoint', { + service: ec2.GatewayVpcEndpointAwsService.DYNAMODB, + vpc: vpc, + subnets: [subnet], +}); +new vpc_v2.Route(stack, 'DynamoDBRoute', { + routeTable, + destination: vpc_v2.IpAddresses.ipv4('0.0.0.0/0'), + target: dynamoEndpoint, +}); +``` diff --git a/packages/@aws-cdk/aws-ec2-alpha/awslint.json b/packages/@aws-cdk/aws-ec2-alpha/awslint.json new file mode 100644 index 0000000000000..35de7712d8ef5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/awslint.json @@ -0,0 +1,7 @@ +{ + "exclude": [ + "from-method:@aws-cdk/aws-ec2-alpha.VpcV2", + "attribute-tag:@aws-cdk/aws-ec2-alpha.RouteTable.routeTableId", + "from-method:@aws-cdk/aws-ec2-alpha.SubnetV2" + ] +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/jest.config.js b/packages/@aws-cdk/aws-ec2-alpha/jest.config.js new file mode 100644 index 0000000000000..4995208baf512 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/jest.config.js @@ -0,0 +1,10 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = { + ...baseConfig, + coverageThreshold: { + global: { + statements: 75, + branches: 63, + }, + }, +};; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts new file mode 100644 index 0000000000000..26f148f30b2aa --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts @@ -0,0 +1,10 @@ +// The index.ts files contains a list of files we want to +// include as part of the public API of this module. +// In general, all files including L2 classes will be listed here, +// while all files including only utility functions will be omitted from here. + +export * from './vpc-v2'; +export * from './ipam'; +export * from './vpc-v2-base'; +export * from './subnet-v2'; +export * from './route'; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/ipam.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/ipam.ts new file mode 100644 index 0000000000000..0d420603fee9d --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/ipam.ts @@ -0,0 +1,542 @@ +import { CfnIPAM, CfnIPAMPool, CfnIPAMPoolCidr, CfnIPAMScope } from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; +import { Lazy, Names, Resource, Stack } from 'aws-cdk-lib'; + +/** + * Represents the address family for IP addresses in an IPAM pool. + * IP_V4 - Represents the IPv4 address family. + * IP_V6 - Represents the IPv6 address family. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html#cfn-ec2-ipampool-addressfamily + */ +export enum AddressFamily { + /** + * Represents the IPv4 address family. + * Allowed under public and private pool. + */ + IP_V4 = 'ipv4', + + /** + * Represents the IPv6 address family. + * Only allowed under public pool. + */ + IP_V6 = 'ipv6', +} + +/** + * The IP address source for pools in the public scope. + * Only used for provisioning IP address CIDRs to pools in the public scope. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html#cfn-ec2-ipampool-publicipsource + */ +export enum IpamPoolPublicIpSource { + /** + * BYOIP Ipv6 to be registered under IPAM + */ + BYOIP = 'byoip', + + /** + * Amazon Provided Ipv6 range + */ + AMAZON = 'amazon', +} + +/** + * Limits which service in AWS that the pool can be used in + */ +export enum AwsServiceName { + /** + * Allows users to use space for Elastic IP addresses and VPCs + */ + EC2 = 'ec2', +} + +/** + * Options to create a new Ipam in the account + */ +export interface IpamProps{ + + /** + * The operating Regions for an IPAM. + * Operating Regions are AWS Regions where the IPAM is allowed to manage IP address CIDRs + * For more information about operating Regions, see [Create an IPAM](https://docs.aws.amazon.com//vpc/latest/ipam/create-ipam.html) in the *Amazon VPC IPAM User Guide* . + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipam.html#cfn-ec2-ipam-operatingregions + * @default Stack.region if defined else [] + */ + readonly operatingRegion?: string[]; + + /** + * Name of IPAM that can be used for tagging resource + * @default none + */ + readonly ipamName?: string; +} + +/** + * Refers to two possible scope types under IPAM + */ +export enum IpamScopeType { + /** + * Default scopes created by IPAM + */ + DEFAULT = 'default', + + /** + * Custom scope created using method + */ + CUSTOM = 'custom', +} + +/** + * Options for configuring an IPAM pool. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html + */ +export interface PoolOptions{ + + /** + * addressFamily - The address family of the pool (ipv4 or ipv6). + */ + readonly addressFamily: AddressFamily; + + /** + * Information about the CIDRs provisioned to the pool. + * @default - No CIDRs are provisioned + */ + readonly ipv4ProvisionedCidrs?: string[]; + + /** + * The locale (AWS Region) of the pool. Should be one of the IPAM operating region. + * Only resources in the same Region as the locale of the pool can get IP address allocations from the pool. + * You can only allocate a CIDR for a VPC, for example, from an IPAM pool that shares a locale with the VPC’s Region. + * Note that once you choose a Locale for a pool, you cannot modify it. If you choose an AWS Region for locale that has not been configured as an operating Region for the IPAM, you'll get an error. + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html#cfn-ec2-ipampool-locale + * @default - Current operating region + */ + readonly locale?: string; + + /** + * The IP address source for pools in the public scope. + * Only used for IPv6 address + * Only allowed values to this are 'byoip' or 'amazon' + * @default amazon + */ + readonly publicIpSource?: IpamPoolPublicIpSource; + + /** + * Limits which service in AWS that the pool can be used in. + * + * "ec2", for example, allows users to use space for Elastic IP addresses and VPCs. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html#cfn-ec2-ipampool-awsservice + * + * @default - No service + */ + readonly awsService?: AwsServiceName; +} + +/** + * Properties for creating an IPAM pool. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html + */ +interface IpamPoolProps extends PoolOptions { + /** + * Scope id where pool needs to be created + */ + readonly ipamScopeId: string; + + /** + * IPAM resource name + * @default autogenerated by CDK + */ + readonly ipamPoolName?: string; +} + +/** + * Options to provision CIDRs to an IPAM pool. + * Used to create a new IpamPoolCidr + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampoolcidr.html + */ +export interface IpamPoolCidrProvisioningOptions { + /** + * Ipv6 Netmask length for the CIDR + * @default none + */ + readonly netmaskLength?: number; + + /** + * Ipv6 CIDR block for the IPAM pool + * @default none + */ + readonly cidr?: string; +} + +/** + * Definition used to add or create a new IPAM pool + */ +export interface IIpamPool{ + /** + * Pool ID to be passed to the VPC construct + * @attribute IpamPoolId + */ + readonly ipamPoolId: string; + + /** + * Pool CIDR for IPv6 to be provisioned with Public IP source set to 'Amazon' + */ + readonly ipamCidrs: CfnIPAMPoolCidr[]; + + /** + * Function to associate a IPv6 address with IPAM pool + */ + provisionCidr(id: string, options: IpamPoolCidrProvisioningOptions): CfnIPAMPoolCidr; + +} + +/** + * IPAM scope is the highest-level container within IPAM. An IPAM contains two default scopes. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html + */ +interface IpamScopeProps extends IpamScopeOptions{ + /** + * IPAM id to which scope needs to be added + */ + readonly ipamId: string; + + /** + * Operating regions for the Ipam + * Required in order to validate the locale being set on pool + */ + readonly ipamOperatingRegions: string[]; + + /** + * Custom ipam scope id to add a pool in order to support default scopes + * @default none + */ + readonly ipamScopeId?: string; + +} + +/** + * Being used in IPAM class to add pools to default scope created by IPAM. + */ +export interface IpamScopeOptions { + + /** + * IPAM scope name that will be used for tagging + * @default none + */ + readonly ipamScopeName?: string; +} + +/** + * Options for configuring an IP Address Manager (IPAM). + * + * For more information, see the {@link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipam.html}. + */ +export interface IpamOptions { + + /** + * CIDR Mask for Vpc + * Only required when using AWS Ipam + * + * @default - None + */ + readonly netmaskLength?: number; + + /** + * Ipv4 or an Ipv6 IPAM pool + * Only required when using AWS Ipam + * + * @default - None + */ + readonly ipamPool?: IIpamPool; + + /** + * Required to set Secondary cidr block resource name + * in order to generate unique logical id for the resource. + */ + readonly cidrBlockName: string; +} + +/** + * Interface for IpamScope Class + */ +export interface IIpamScopeBase{ + + /** + * Reference to the current scope of stack to be passed in order to create + * a new IPAM pool + */ + readonly scope: Construct; + + /** + * Default Scope ids created by the IPAM or a new Resource id + */ + readonly scopeId: string; + + /** + * Defines scope type can be either default or custom + */ + readonly scopeType?: IpamScopeType; + + /** + * Function to add a new pool to an IPAM scope + */ + addPool(id: string, options: PoolOptions): IIpamPool; + +} + +/** + * Creates new IPAM Pool + * Pools enable you to organize your IP addresses according to your routing and security needs + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipampool.html + * @resource AWS::EC2::IPAMPool + * @internal + */ +class IpamPool extends Resource implements IIpamPool { + + /** + * Pool ID to be passed to the VPC construct + * @attribute IpamPoolId + */ + public readonly ipamPoolId: string; + + /** + * Pool CIDR for IPv6 to be provisioned with Public IP source set to 'Amazon' + */ + public readonly ipamCidrs: CfnIPAMPoolCidr[] = [] + + /** + * Reference to ipamPool resource created in this class + */ + private readonly _ipamPool: CfnIPAMPool; + + constructor(scope: Construct, id: string, props: IpamPoolProps) { + super(scope, id, { + physicalName: props.ipamPoolName ?? Lazy.string({ + produce: () => Names.uniqueResourceName(this, { maxLength: 128, allowedSpecialCharacters: '_' }), + }), + }); + + if (props.addressFamily === AddressFamily.IP_V6 && !props.awsService) { + throw new Error('awsService is required when addressFamily is set to ipv6'); + } + + this._ipamPool = new CfnIPAMPool(this, id, { + addressFamily: props.addressFamily, + provisionedCidrs: props.ipv4ProvisionedCidrs?.map(cidr => ({ cidr })), + locale: props.locale, + ipamScopeId: props.ipamScopeId, + publicIpSource: props.publicIpSource, + awsService: props.awsService, + }); + this.ipamPoolId = this._ipamPool.attrIpamPoolId; + this.node.defaultChild = this._ipamPool; + } + + /** + * A CIDR provisioned to an IPAM pool. + * @param id Name of Resource + * @param options Either a CIDR or netmask length must be provided + * @returns AWS::EC2::IPAMPoolCidr + */ + public provisionCidr(id: string, options: IpamPoolCidrProvisioningOptions): CfnIPAMPoolCidr { + const cidr = new CfnIPAMPoolCidr(this, id, { + ...options, + ipamPoolId: this.ipamPoolId, + }); + this.ipamCidrs.push(cidr); + return cidr; + } +} + +/** + * Creates custom Ipam Scope, custom IPAM scopes can only be private + * (can be used for adding custom scopes to an existing IPAM) + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html + * @resource AWS::EC2::IPAMScope + */ +class IpamScope extends Resource implements IIpamScopeBase { + + /** + * Stores the reference to newly created Resource + */ + private readonly _ipamScope: CfnIPAMScope; + + /** + * ID for Resource IpamScope + * @attribute IpamScopeId + */ + public readonly scopeId: string; + + /** + * Properties to configure ipam scope + */ + private readonly props: IpamScopeProps; + + /** + * Reference to stack scope to be passed through addPool method inorder to create a new IpamPool + */ + public readonly scope: Construct; + + /** + * Defines scope type can be either default or custom + */ + public readonly scopeType: IpamScopeType; + + constructor(scope: Construct, id: string, props: IpamScopeProps) { + super(scope, id); + this._ipamScope = new CfnIPAMScope(scope, 'IpamScope', { + ipamId: props.ipamId, + }); + this.scopeId = this._ipamScope.attrIpamScopeId; + this.scopeType = IpamScopeType.CUSTOM; + this.scope = scope; + this.props = props; + } + + /** + * Adds a pool to the IPAM scope. + * @external + */ + addPool(id: string, options: PoolOptions): IIpamPool { + return createIpamPool(this.scope, id, this.props, options, this.scopeId); + } + +} + +/** + * Base class for IPAM default scopes. + */ +class IpamScopeBase implements IIpamScopeBase { + constructor( + readonly scope: Construct, + readonly scopeId: string, + private readonly props: IpamScopeProps, + readonly scopeType?: IpamScopeType, + ) { + this.scopeType = IpamScopeType.DEFAULT; + } + + /** + * Adds a pool to the IPAM scope. + * @external + */ + addPool(id: string, options: PoolOptions): IIpamPool { + return createIpamPool(this.scope, id, this.props, options, this.scopeId); + } +} + +/** + * Creates new IPAM with default public and private scope + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html + * @resource AWS::EC2::IPAM + */ +export class Ipam extends Resource { + /** + * Provides access to default public IPAM scope through add pool method. + * Usage: To add an Ipam Pool to a default public scope + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html + */ + public readonly publicScope: IIpamScopeBase; + + /** + * Provides access to default private IPAM scope through add pool method. + * Usage: To add an Ipam Pool to a default private scope + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html + * */ + public readonly privateScope: IIpamScopeBase; + + // Resource IPAM + private readonly _ipam: CfnIPAM; + /** + * Access to Ipam resource id that can be used later to add a custom private scope to this IPAM + * @attribute IpamId + */ + public readonly ipamId: string; + + /** + * List of operating regions for IPAM + */ + public readonly operatingRegions: string[]; + + /** + * List of scopes created under this IPAM + */ + public readonly scopes: IIpamScopeBase[] = []; + + constructor(scope: Construct, id: string, props?: IpamProps) { + super(scope, id); + + if (!props?.operatingRegion && !Stack.of(this).region) { + throw new Error('Please provide at least one operating region'); + } + + this.operatingRegions = props?.operatingRegion ?? [Stack.of(this).region]; + + this._ipam = new CfnIPAM(this, 'Ipam', { + operatingRegions: this.operatingRegions ? this.operatingRegions.map(region => ({ regionName: region })) : [], + }); + this.node.defaultChild = this._ipam; + + this.ipamId = this._ipam.attrIpamId; + this.publicScope = new IpamScopeBase(this, 'DefaultPublicScope', { + ipamOperatingRegions: this.operatingRegions, + ipamId: this._ipam.attrIpamId, + ipamScopeId: this._ipam.attrPublicDefaultScopeId, + }); + this.privateScope = new IpamScopeBase(this, 'DefaultPrivateScope', { + ipamOperatingRegions: this.operatingRegions, + ipamId: this._ipam.attrIpamId, + ipamScopeId: this._ipam.attrPrivateDefaultScopeId, + }); + + this.scopes.push(this.publicScope, this.privateScope); + + } + + /** + * Function to add custom scope to an existing IPAM + * Custom scopes can only be private + */ + public addScope(scope: Construct, id: string, options: IpamScopeOptions): IIpamScopeBase { + const ipamScope = new IpamScope(scope, id, { + ...options, + ipamId: this.ipamId, + ipamOperatingRegions: this.operatingRegions, + }); + this.scopes.push(ipamScope); + return ipamScope; + } +} + +/** + * Function to create IpamPool under scope + * @internal + */ +function createIpamPool( + scope: Construct, + id: string, + scopeOptions: IpamScopeProps, + poolOptions: PoolOptions, + scopeId: string, +): IpamPool { + const isLocaleInOperatingRegions = scopeOptions.ipamOperatingRegions + ? scopeOptions.ipamOperatingRegions.map(region => ({ regionName: region })) + .some(region => region.regionName === poolOptions.locale) + : false; + + if (!isLocaleInOperatingRegions) { + throw new Error(`The provided locale '${poolOptions.locale}' is not in the operating regions.`); + } + + return new IpamPool(scope, id, { + ipamPoolName: id, + addressFamily: poolOptions.addressFamily, + ipv4ProvisionedCidrs: poolOptions.ipv4ProvisionedCidrs, + ipamScopeId: scopeId, + locale: poolOptions.locale, + publicIpSource: poolOptions.publicIpSource, + awsService: poolOptions.awsService, + }); +} + diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/route.ts new file mode 100644 index 0000000000000..3a6a0ea5cd717 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/route.ts @@ -0,0 +1,587 @@ +import { CfnEIP, CfnEgressOnlyInternetGateway, CfnInternetGateway, CfnNatGateway, CfnRoute, CfnRouteTable, CfnVPCGatewayAttachment, CfnVPNGateway, GatewayVpcEndpoint, IRouteTable, ISubnet, IVpcEndpoint, RouterType, VpnConnectionType } from 'aws-cdk-lib/aws-ec2'; +import { Construct, IDependable } from 'constructs'; +import { Duration, Resource } from 'aws-cdk-lib/core'; +import { IVpcV2 } from './vpc-v2-base'; + +/** + * Indicates whether the NAT gateway supports public or private connectivity. + * The default is public connectivity. + * See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html#cfn-ec2-natgateway-connectivitytype + */ +export enum NatConnectivityType { + /** + * Sets Connectivity type to PUBLIC + */ + PUBLIC = 'public', + /** + * Sets Connectivity type to PRIVATE + */ + PRIVATE = 'private', +} + +/** + * Interface to define a routing target, such as an + * egress-only internet gateway or VPC endpoint. + */ +export interface IRouteTarget { + /** + * The type of router used in the route. + */ + readonly routerType: RouterType; + + /** + * The ID of the route target. + */ + readonly routerTargetId: string; +} + +/** + * Properties to define an egress-only internet gateway. + */ +export interface EgressOnlyInternetGatewayProps { + /** + * The ID of the VPC for which to create the egress-only internet gateway. + */ + readonly vpc: IVpcV2; + + /** + * The resource name of the egress-only internet gateway. + * @default none + */ + readonly egressOnlyInternetGatewayName?: string; +} + +/** + * Properties to define an internet gateway. + */ +export interface InternetGatewayProps { + /** + * The ID of the VPC for which to create the internet gateway. + */ + readonly vpc: IVpcV2; + + /** + * The resource name of the internet gateway. + * @default none + */ + readonly internetGatewayName?: string; + +} + +/** + * Properties to define a VPN gateway. + */ +export interface VPNGatewayProps { + /** + * The type of VPN connection the virtual private gateway supports. + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngateway.html#cfn-ec2-vpngateway-type + */ + readonly type: VpnConnectionType; + + /** + * The ID of the VPC for which to create the VPN gateway. + */ + readonly vpc: IVpcV2; + + /** + * The private Autonomous System Number (ASN) for the Amazon side of a BGP session. + * @default none + */ + readonly amazonSideAsn?: number; + + /** + * The resource name of the VPN gateway. + * @default none + */ + readonly vpnGatewayName?: string; +} + +/** + * Properties to define a NAT gateway. + */ +export interface NatGatewayProps { + /** + * The subnet in which the NAT gateway is located. + */ + readonly subnet: ISubnet; + + /** + * The ID of the VPC in which the NAT gateway is located. + * @default none + */ + readonly vpc?: IVpcV2; + + /** + * AllocationID of Elastic IP address that's associated with the NAT gateway. This property is required for a public NAT + * gateway and cannot be specified with a private NAT gateway. + * @default attr.allocationID of a new Elastic IP created by default + * //TODO: ADD L2 for elastic ip + */ + readonly allocationId?: string; + + /** + * Indicates whether the NAT gateway supports public or private connectivity. + * @default public + */ + readonly connectivityType?: NatConnectivityType; + + /** + * The maximum amount of time to wait before forcibly releasing the + * IP addresses if connections are still in progress. + * @default 350 seconds + */ + readonly maxDrainDuration?: Duration; + + /** + * The private IPv4 address to assign to the NAT gateway. If you don't provide an + * address, a private IPv4 address will be automatically assigned. + * @default none + */ + readonly privateIpAddress?: string; + + /** + * Secondary EIP allocation IDs. + * @default none + * @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-creating + */ + readonly secondaryAllocationIds?: string[]; + + /** + * The number of secondary private IPv4 addresses you + * want to assign to the NAT gateway. + * + * `SecondaryPrivateIpAddressCount` and `SecondaryPrivateIpAddresses` cannot be + * set at the same time. + * + * @default none + * @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-creating + */ + readonly secondaryPrivateIpAddressCount?: number; + + /** + * Secondary private IPv4 addresses. + * + * `SecondaryPrivateIpAddressCount` and `SecondaryPrivateIpAddresses` cannot be + * set at the same time. + * + * @default none + * @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-creating + */ + readonly secondaryPrivateIpAddresses?: string[]; + + /** + * The resource name of the NAT gateway. + * @default none + */ + readonly natGatewayName?: string; + +} + +/** + * Creates an egress-only internet gateway + * @resource AWS::EC2::EgressOnlyInternetGateway + */ +export class EgressOnlyInternetGateway extends Resource implements IRouteTarget { + /** + * The type of router used in the route. + */ + readonly routerType: RouterType; + + /** + * The ID of the route target. + */ + readonly routerTargetId: string; + + /** + * The egress-only internet gateway CFN resource. + */ + public readonly resource: CfnEgressOnlyInternetGateway; + + constructor(scope: Construct, id: string, props: EgressOnlyInternetGatewayProps) { + super(scope, id); + + this.routerType = RouterType.EGRESS_ONLY_INTERNET_GATEWAY; + + this.resource = new CfnEgressOnlyInternetGateway(this, 'EIGW', { + vpcId: props.vpc.vpcId, + }); + this.node.defaultChild = this.resource; + + this.routerTargetId = this.resource.attrId; + } +} + +/** + * Creates an internet gateway + * @resource AWS::EC2::InternetGateway + */ +export class InternetGateway extends Resource implements IRouteTarget { + /** + * The type of router used in the route. + */ + readonly routerType: RouterType; + + /** + * The ID of the route target. + */ + readonly routerTargetId: string; + + /** + * The ID of the VPC for which to create the internet gateway. + */ + public readonly vpcId: string; + + /** + * The internet gateway CFN resource. + */ + public readonly resource: CfnInternetGateway; + + constructor(scope: Construct, id: string, props: InternetGatewayProps) { + super(scope, id); + + this.routerType = RouterType.GATEWAY; + + this.resource = new CfnInternetGateway(this, 'IGW', {}); + this.node.defaultChild = this.resource; + + this.routerTargetId = this.resource.attrInternetGatewayId; + this.vpcId = props.vpc.vpcId; + } +} + +/** + * Creates a virtual private gateway + * @resource AWS::EC2::VPNGateway + */ +export class VPNGateway extends Resource implements IRouteTarget { + /** + * The type of router used in the route. + */ + readonly routerType: RouterType; + + /** + * The ID of the route target. + */ + readonly routerTargetId: string; + + /** + * The ID of the VPC for which to create the VPN gateway. + */ + public readonly vpcId: string; + + /** + * The VPN gateway CFN resource. + */ + public readonly resource: CfnVPNGateway; + + constructor(scope: Construct, id: string, props: VPNGatewayProps) { + super(scope, id); + + this.routerType = RouterType.GATEWAY; + + this.resource = new CfnVPNGateway(this, 'IGW', { + type: props.type, + amazonSideAsn: props.amazonSideAsn, + }); + this.node.defaultChild = this.resource; + + this.routerTargetId = this.resource.attrVpnGatewayId; + this.vpcId = props.vpc.vpcId; + } +} + +/** + * Creates a network address translation (NAT) gateway + * @resource AWS::EC2::NatGateway + */ +export class NatGateway extends Resource implements IRouteTarget { + /** + * The type of router used in the route. + */ + readonly routerType: RouterType; + + /** + * The ID of the route target. + */ + readonly routerTargetId: string; + + /** + * Indicates whether the NAT gateway supports public or private connectivity. + * @default public + */ + public readonly connectivityType?: string; + + /** + * The maximum amount of time to wait before forcibly releasing the + * IP addresses if connections are still in progress. + * @default 350 seconds + */ + public readonly maxDrainDuration?: Duration; + + /** + * The NAT gateway CFN resource. + */ + public readonly resource: CfnNatGateway; + + constructor(scope: Construct, id: string, props: NatGatewayProps) { + super(scope, id); + + this.routerType = RouterType.NAT_GATEWAY; + + this.connectivityType = props.connectivityType || NatConnectivityType.PUBLIC; + this.maxDrainDuration = props.maxDrainDuration || Duration.seconds(350); + + // If user does not provide EIP, generate one for them + var aId: string | undefined; + if (this.connectivityType == 'public') { + if (!props.allocationId) { + let eip = new CfnEIP(this, 'EIP', { + domain: props.vpc?.vpcId, + }); + aId = eip.attrAllocationId; + } else { + aId = props.allocationId; + } + } + + this.resource = new CfnNatGateway(this, 'NATGateway', { + subnetId: props.subnet.subnetId, + allocationId: aId, + maxDrainDurationSeconds: props.maxDrainDuration?.toSeconds(), + secondaryAllocationIds: props.secondaryAllocationIds, + ...props, + }); + + this.routerTargetId = this.resource.attrNatGatewayId; + this.node.defaultChild = this.resource; + this.node.addDependency(props.subnet.internetConnectivityEstablished); + } +} + +/** + * The type of endpoint or gateway being targeted by the route. + */ +export interface RouteTargetProps { + /** + * The gateway route target. This is used for targets such as + * egress-only internet gateway or VPC peering connection. + * @default none + */ + readonly gateway?: IRouteTarget; + + /** + * The endpoint route target. This is used for targets such as + * VPC endpoints. + * @default none + */ + readonly endpoint?: IVpcEndpoint; +} + +/** + * The gateway or endpoint targeted by the route. + */ +export class RouteTargetType { + /** + * The gateway route target. This is used for targets such as + * egress-only internet gateway or VPC peering connection. + * @default none + */ + readonly gateway?: IRouteTarget; + + /** + * The endpoint route target. This is used for targets such as + * VPC endpoints. + * @default none + */ + readonly endpoint?: IVpcEndpoint; + + constructor(props: RouteTargetProps) { + if (props.gateway && props.endpoint) { + throw new Error('Cannot specify both gateway and endpoint'); + } else { + this.gateway = props.gateway; + this.endpoint = props.endpoint; + } + } +} + +/** + * Interface to define a route. + */ +export interface IRouteV2 { + /** + * The ID of the route table for the route. + * @attribute routeTable + */ + readonly routeTable: IRouteTable; + + /** + * The IPv4 or IPv6 CIDR block used for the destination match. + * + * Routing decisions are based on the most specific match. + * TODO: Look for strong IP type implementation here. + */ + readonly destination: string; + + /** + * The gateway or endpoint targeted by the route. + */ + readonly target: RouteTargetType; +} + +/** + * Properties to define a route. + */ +export interface RouteProps { + /** + * The ID of the route table for the route. + * @attribute routeTable + */ + readonly routeTable: IRouteTable; + + /** + * The IPv4 or IPv6 CIDR block used for the destination match. + * + * Routing decisions are based on the most specific match. + */ + readonly destination: string; + + /** + * The gateway or endpoint targeted by the route. + */ + readonly target: RouteTargetType; + + /** + * The resource name of the route. + * @default none + */ + readonly routeName?: string; +} + +/** + * Creates a new route with added functionality. + * @resource AWS::EC2::Route + */ +export class Route extends Resource implements IRouteV2 { + /** + * The IPv4 or IPv6 CIDR block used for the destination match. + * + * Routing decisions are based on the most specific match. + */ + public readonly destination: string; + + /** + * The gateway or endpoint targeted by the route. + */ + public readonly target: RouteTargetType; + + /** + * The route table for the route. + * @attribute routeTable + */ + public readonly routeTable: IRouteTable; + + /** + * The type of router the route is targetting + */ + public readonly targetRouterType: RouterType + + /** + * The route CFN resource. + */ + public readonly resource?: CfnRoute; + + constructor(scope: Construct, id: string, props: RouteProps) { + super(scope, id); + + this.destination = props.destination; + this.target = props.target; + this.routeTable = props.routeTable; + + this.targetRouterType = this.target.gateway ? this.target.gateway.routerType : RouterType.VPC_ENDPOINT; + + // Gateway generates route automatically via its RouteTable, thus we don't need to generate the resource for it + if (!(this.target.endpoint instanceof GatewayVpcEndpoint)) { + this.resource = new CfnRoute(this, 'Route', { + routeTableId: this.routeTable.routeTableId, + destinationCidrBlock: this.destination, + destinationIpv6CidrBlock: this.destination, + [routerTypeToPropName(this.targetRouterType)]: this.target.gateway ? this.target.gateway.routerTargetId : + this.target.endpoint ? this.target.endpoint.vpcEndpointId : null, + }); + } + this.node.defaultChild = this.resource; + + if (this.targetRouterType == RouterType.GATEWAY) { + if (this.target.gateway instanceof InternetGateway) { + new CfnVPCGatewayAttachment(this, 'GWAttachment', { + vpcId: this.target.gateway.vpcId, + internetGatewayId: this.target.gateway.routerTargetId, + }); + } else if (this.target.gateway instanceof VPNGateway) { + new CfnVPCGatewayAttachment(this, 'GWAttachment', { + vpcId: this.target.gateway.vpcId, + vpnGatewayId: this.target.gateway.routerTargetId, + }); + } + } + } +} + +/** + * Properties to define a route table. + */ +export interface RouteTableProps { + /** + * The ID of the VPC. + */ + readonly vpc: IVpcV2; + + /** + * The resource name of the route table. + * @default none + */ + readonly routeTableName?: string; +} + +/** + * Creates a route table for the specified VPC + * @resource AWS::EC2::RouteTable + */ +export class RouteTable extends Resource implements IRouteTable, IDependable { + /** + * The ID of the route table. + */ + public readonly routeTableId: string; + + /** + * The route table CFN resource. + */ + public readonly resource: CfnRouteTable; + + constructor(scope: Construct, id: string, props: RouteTableProps) { + super(scope, id); + + this.resource = new CfnRouteTable(this, 'RouteTable', { + vpcId: props.vpc.vpcId, + }); + this.node.defaultChild = this.resource; + + this.routeTableId = this.resource.attrRouteTableId; + } +} + +function routerTypeToPropName(routerType: RouterType) { + return ({ + [RouterType.CARRIER_GATEWAY]: 'carrierGatewayId', + [RouterType.EGRESS_ONLY_INTERNET_GATEWAY]: 'egressOnlyInternetGatewayId', + [RouterType.GATEWAY]: 'gatewayId', + [RouterType.INSTANCE]: 'instanceId', + [RouterType.LOCAL_GATEWAY]: 'localGatewayId', + [RouterType.NAT_GATEWAY]: 'natGatewayId', + [RouterType.NETWORK_INTERFACE]: 'networkInterfaceId', + [RouterType.TRANSIT_GATEWAY]: 'transitGatewayId', + [RouterType.VPC_PEERING_CONNECTION]: 'vpcPeeringConnectionId', + [RouterType.VPC_ENDPOINT]: 'vpcEndpointId', + })[routerType]; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts new file mode 100644 index 0000000000000..a71277d441cbc --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts @@ -0,0 +1,416 @@ +import { Resource, Names, Lazy } from 'aws-cdk-lib'; +import { CfnRouteTable, CfnSubnet, CfnSubnetRouteTableAssociation, INetworkAcl, IRouteTable, ISubnet, NetworkAcl, SubnetNetworkAclAssociation, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { Construct, DependencyGroup, IDependable } from 'constructs'; +import { IVpcV2 } from './vpc-v2-base'; +import { CidrBlock, CidrBlockIpv6 } from './util'; + +/** + * Interface to define subnet CIDR + */ +interface ICidr { + readonly cidr: string; +} + +/** + * IPv4 or IPv6 CIDR range for the subnet + */ +export class IpCidr implements ICidr { + + /** + * IPv6 CIDR range for the subnet + * Allowed only if IPv6 is enabled on VPc + */ + public readonly cidr: string; + constructor(props: string ) { + this.cidr = props; + } +} + +/** + * Properties to define subnet for VPC. + */ +export interface SubnetV2Props { +/** + * VPC Prop + */ + readonly vpc: IVpcV2; + + /** + * ipv4 cidr to assign to this subnet. + * See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html#cfn-ec2-subnet-cidrblock + */ + readonly ipv4CidrBlock: IpCidr; + + /** + * Ipv6 CIDR Range for subnet + * @default No Ipv6 address + */ + readonly ipv6CidrBlock?: IpCidr; + + /** + * Custom AZ for the subnet + */ + readonly availabilityZone: string; + + /** + * Custom Route for subnet + * @default Default route table + */ + readonly routeTable?: IRouteTable; + + /** + * The type of Subnet to configure. + * + * The Subnet type will control the ability to route and connect to the + * Internet. + * + * TODO: Add validation check `subnetType` when adding resources (e.g. cannot add NatGateway to private) + */ + readonly subnetType: SubnetType; + + /** + * Subnet name + * @default none + */ + readonly subnetName?: string; + + /** + * Indicates whether a network interface created in this subnet receives an IPv6 address. + * + * If you specify AssignIpv6AddressOnCreation, you must also specify Ipv6CidrBlock. + * + * @default false + */ + readonly assignIpv6AddressOnCreation?: boolean; + +} + +/** + * Interface with additional properties for SubnetV2 + */ +export interface ISubnetV2 extends ISubnet { + + /** + * The IPv6 CIDR block for this subnet + */ + readonly ipv6CidrBlock?: string; + +} + +/** + * The SubnetV2 class represents a subnet within a VPC (Virtual Private Cloud) in AWS. + * It extends the Resource class and implements the ISubnet interface. + * + * Instances of this class can be used to create and manage subnets within a VpcV2 instance. + * Subnets can be configured with specific IP address ranges (IPv4 and IPv6), availability zones, + * and subnet types (e.g., public, private, isolated). + * + * @resource AWS::EC2::Subnet + * + */ +export class SubnetV2 extends Resource implements ISubnetV2 { + + /** + * The Availability Zone the subnet is located in + */ + public readonly availabilityZone: string; + + /** + * The subnetId for this particular subnet + * @attribute + */ + public readonly subnetId: string; + + /** + * Dependencies for internet connectivity + * This Property exposes the RouteTable-Subnet association so that other resources can depend on it. + */ + public readonly internetConnectivityEstablished: IDependable; + + /** + * The variable name `internetConnectivityEstablished` does not reflect what it actually is. + * The naming is enforced by ISubnet. We need to keep it to maintain compatibility. + * It exposes the RouteTable-Subnet association so that other resources can depend on it. + * E.g. Resources in a subnet, when being deleted, may need the RouteTable to exist in order to delete properly + */ + private readonly _internetConnectivityEstablished = new DependencyGroup(); + + /** + * The IPv4 CIDR block for this subnet + */ + public readonly ipv4CidrBlock: string; + + /** + * The IPv6 CIDR Block for this subnet + */ + public readonly ipv6CidrBlock?: string; + + /** + * The route table for this subnet + */ + public readonly routeTable: IRouteTable; + + /** + * The type of subnet (public or private) that this subnet represents. + * @attribute SubnetType + */ + public readonly subnetType: SubnetType; + + private _networkAcl: INetworkAcl; + + /** + * Constructs a new SubnetV2 instance. + * @param scope The parent Construct that this resource will be part of. + * @param id The unique identifier for this resource. + * @param props The configuration properties for the subnet. + */ + constructor(scope: Construct, id: string, props: SubnetV2Props) { + super(scope, id, { + physicalName: props.subnetName ?? Lazy.string({ + produce: () => Names.uniqueResourceName(this, { maxLength: 128, allowedSpecialCharacters: '_' }), + }), + }); + + const ipv4CidrBlock = props.ipv4CidrBlock.cidr; + const ipv6CidrBlock = props.ipv6CidrBlock?.cidr; + + if (!checkCidrRanges(props.vpc, props.ipv4CidrBlock.cidr)) { + throw new Error('CIDR block should be within the range of VPC'); + }; + + let overlap: boolean = false; + let overlapIpv6: boolean = false; + + overlap = validateOverlappingCidrRanges(props.vpc, props.ipv4CidrBlock.cidr); + + //check whether VPC supports ipv6 + if (props.ipv6CidrBlock?.cidr) { + validateSupportIpv6(props.vpc); + overlapIpv6 = validateOverlappingCidrRangesipv6(props.vpc, props.ipv6CidrBlock?.cidr); + } + + if (overlap || overlapIpv6) { + throw new Error('CIDR block should not overlap with existing subnet blocks'); + } + + if (props.assignIpv6AddressOnCreation && !props.ipv6CidrBlock) { + throw new Error('IPv6 CIDR block is required when assigning IPv6 address on creation'); + } + + const subnet = new CfnSubnet(this, 'Subnet', { + vpcId: props.vpc.vpcId, + cidrBlock: ipv4CidrBlock, + ipv6CidrBlock: ipv6CidrBlock, + availabilityZone: props.availabilityZone, + assignIpv6AddressOnCreation: props.assignIpv6AddressOnCreation ?? false, + }); + + this.node.defaultChild = subnet; + this.ipv4CidrBlock = props.ipv4CidrBlock.cidr; + this.ipv6CidrBlock = props.ipv6CidrBlock?.cidr; + this.subnetId = subnet.ref; + this.availabilityZone = props.availabilityZone; + + this._networkAcl = NetworkAcl.fromNetworkAclId(this, 'Acl', subnet.attrNetworkAclAssociationId); + + if (props.routeTable) { + this.routeTable = props.routeTable; + } else { + const defaultTable = new CfnRouteTable(this, 'RouteTable', { + vpcId: props.vpc.vpcId, + }); + this.routeTable = { routeTableId: defaultTable.ref }; + } + + const routeAssoc = new CfnSubnetRouteTableAssociation(this, 'RouteTableAssociation', { + subnetId: this.subnetId, + routeTableId: this.routeTable.routeTableId, + }); + this._internetConnectivityEstablished.add(routeAssoc); + this.internetConnectivityEstablished = this._internetConnectivityEstablished; + + this.subnetType = props.subnetType; + storeSubnetToVpcByType(props.vpc, this, props.subnetType); + } + + /** + * Associate a Network ACL with this subnet + * + * @param id The unique identifier for this association. + * @param networkAcl The Network ACL to associate with this subnet. + * This allows controlling inbound and outbound traffic for instances in this subnet. + */ + public associateNetworkAcl(id: string, networkAcl: INetworkAcl) { + this._networkAcl = networkAcl; + + const scope = networkAcl instanceof Construct ? networkAcl : this; + const other = networkAcl instanceof Construct ? this : networkAcl; + new SubnetNetworkAclAssociation(scope, id + Names.nodeUniqueId(other.node), { + networkAcl, + subnet: this, + }); + } + /** + * Returns the Network ACL associated with this subnet. + */ + + public get networkAcl(): INetworkAcl { + return this._networkAcl; + } +} + +const subnetTypeMap = { + [SubnetType.PRIVATE_ISOLATED]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.isolatedSubnets.push(subnet), + [SubnetType.PUBLIC]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.publicSubnets.push(subnet), + [SubnetType.PRIVATE_WITH_EGRESS]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.privateSubnets.push(subnet), + [SubnetType.ISOLATED]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.isolatedSubnets.push(subnet), + [SubnetType.PRIVATE]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.privateSubnets.push(subnet), + [SubnetType.PRIVATE_WITH_NAT]: (vpc: IVpcV2, subnet: SubnetV2) => vpc.privateSubnets.push(subnet), +}; + +/** + * Stores the provided subnet in the VPC's collection of subnets based on the specified subnet type. + * + * @param vpc The VPC instance to which the subnet belongs. + * @param subnet The subnet instance to be stored. + * @param type The type of the subnet (e.g., public, private, isolated). + * @internal + */ +function storeSubnetToVpcByType(vpc: IVpcV2, subnet: SubnetV2, type: SubnetType) { + const findFunctionType = subnetTypeMap[type]; + if (findFunctionType) { + findFunctionType(vpc, subnet); + } else { + throw new Error(`Unsupported subnet type: ${type}`); + } + + /** + * Need to set explicit dependency as during stack deletion, + * the cidr blocks may get deleted first and will fail as the subnets are still using the cidr blocks + */ + for (const cidr of vpc.secondaryCidrBlock) { + subnet.node.addDependency(cidr); + } +} + +/** + * Validates whether the provided VPC supports IPv6 addresses. + * + * @param vpc The VPC instance to be validated. + * @throws Error if the VPC does not support IPv6 addresses. + * @returns True if the VPC supports IPv6 addresses, false otherwise. + * @internal + */ +function validateSupportIpv6(vpc: IVpcV2) { + if (vpc.secondaryCidrBlock.some((secondaryAddress) => secondaryAddress.amazonProvidedIpv6CidrBlock === true || + secondaryAddress.ipv6IpamPoolId != undefined)) { + return true; + } else { + throw new Error('To use IPv6, the VPC must enable IPv6 support.'); + } +} + +/** + * Checks if the provided CIDR range falls within the IP address ranges of the given VPC. + * + * @param vpc The VPC instance to check against. + * @param cidrRange The CIDR range to be checked. + * @returns True if the CIDR range falls within the VPC's IP address ranges, false otherwise. + * @internal + */ +function checkCidrRanges(vpc: IVpcV2, cidrRange: string) { + + const vpcCidrBlock = [vpc.ipv4CidrBlock]; + + for (const ipAddress of vpc.secondaryCidrBlock) { + if (ipAddress.cidrBlock) { + vpcCidrBlock.push(ipAddress.cidrBlock); + } + } + const cidrs = vpcCidrBlock.map(cidr => new CidrBlock(cidr)); + + const subnetCidrBlock = new CidrBlock(cidrRange); + + return cidrs.some(c => c.containsCidr(subnetCidrBlock)); + +} + +/** + * Validates if the provided IPv4 CIDR block overlaps with existing subnet CIDR blocks within the given VPC. + * + * @param vpc The VPC instance to check against. + * @param ipv4CidrBlock The IPv4 CIDR block to be validated. + * @returns True if the IPv4 CIDR block overlaps with existing subnet CIDR blocks, false otherwise. + * @internal + */ + +function validateOverlappingCidrRanges(vpc: IVpcV2, ipv4CidrBlock: string): boolean { + + let allSubnets: ISubnetV2[]; + try { + allSubnets = vpc.selectSubnets().subnets; + } catch (e) { + 'No subnets in VPC'; + return false; + } + + const ipMap: [string, string][] = new Array(); + + const inputRange = new CidrBlock(ipv4CidrBlock); + + const inputIpMap: [string, string] = [inputRange.minIp(), inputRange.maxIp()]; + + for (const subnet of allSubnets) { + const cidrBlock = new CidrBlock(subnet.ipv4CidrBlock); + ipMap.push([cidrBlock.minIp(), cidrBlock.maxIp()]); + } + + for (const range of ipMap) { + if (inputRange.rangesOverlap(range, inputIpMap)) { + return true; + } + } + + return false; +} + +/** + * Validates if the provided IPv6 CIDR block overlaps with existing subnet CIDR blocks within the given VPC. + * + * @param vpc The VPC instance to check against. + * @param ipv6CidrBlock The IPv6 CIDR block to be validated. + * @returns True if the IPv6 CIDR block overlaps with existing subnet CIDR blocks, false otherwise. + * @throws Error if no subnets are found in the VPC. + * @internal + */ +function validateOverlappingCidrRangesipv6(vpc: IVpcV2, ipv6CidrBlock: string): boolean { + + let allSubnets: ISubnetV2[]; + try { + allSubnets = vpc.selectSubnets().subnets; + } catch (e) { + 'No subnets in VPC'; + return false; + } + + const ipv6Map: string[]= []; + + const inputRange = new CidrBlockIpv6(ipv6CidrBlock); + + let result : boolean = false; + + for (const subnet of allSubnets) { + if (subnet.ipv6CidrBlock) { + const cidrBlock = new CidrBlockIpv6(subnet.ipv6CidrBlock); + ipv6Map.push(cidrBlock.cidr); + } + } + + for (const range of ipv6Map) { + if (inputRange.rangesOverlap(range, inputRange.cidr)) { + result = true; + } + } + + return result; +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts new file mode 100644 index 0000000000000..ed8ae62342ded --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -0,0 +1,382 @@ +/*eslint no-bitwise: ["error", { "allow": ["~", "|", "<<", "&"] }] */ + +import { ISubnet } from 'aws-cdk-lib/aws-ec2'; + +/** + * Return a subnet name from its construct ID + * + * All subnet names look like NAME <> "Subnet" <> INDEX + */ +export function subnetGroupNameFromConstructId(subnet: ISubnet) { + return subnet.node.id.replace(/Subnet\d+$/, ''); +} + +/** + * Make the subnet construct ID from a name and number + */ +export function subnetId(name: string, i: number) { + return `${name}Subnet${i + 1}`; +} + +/** + * Return the union of table IDs from all selected subnets + */ +export function allRouteTableIds(subnets: ISubnet[]): string[] { + const ret = new Set(); + for (const subnet of subnets) { + if (subnet.routeTable && subnet.routeTable.routeTableId) { + ret.add(subnet.routeTable.routeTableId); + } + } + return Array.from(ret); +} + +export function flatten(xs: A[][]): A[] { + return Array.prototype.concat.apply([], xs); +} + +/** + * NetworkUtils contains helpers to work with network constructs (subnets/ranges) + */ +export class NetworkUtils { + + /** + * Validates an IPv4 address string. + * + * @param ipAddress The IPv4 address string to be validated. + * @returns True if the string is a valid IPv4 address, false otherwise. + * Validates an IPv4 string + * + * returns true of the string contains 4 numbers between 0-255 delimited by + * a `.` character + */ + public static validIp(ipAddress: string): boolean { + const octets = ipAddress.split('.'); + if (octets.length !== 4) { + return false; + } + return octets.map((octet: string) => parseInt(octet, 10)). + every((octet: number) => octet >= 0 && octet <= 255); + } + + /** + * Converts a string representation of an IPv4 address to its corresponding numerical value. + * + * Uses the formula: + * (first octet * 256³) + (second octet * 256²) + (third octet * 256) + + * (fourth octet) + * + * @param ipAddress the IP address (e.g. 174.66.173.168) + * @returns the integer value of the IP address (e.g 2923605416) + */ + public static ipToNum(ipAddress: string): number { + if (!this.validIp(ipAddress)) { + throw new Error(`${ipAddress} is not valid`); + } + + return ipAddress + .split('.') + .reduce( + (p: number, c: string, i: number) => p + parseInt(c, 10) * 256 ** (3 - i), + 0, + ); + } + + /** + * Takes number and converts it to IPv4 address string + * + * Takes a number (e.g 2923605416) and converts it to an IPv4 address string + * currently only supports IPv4 + * + * @param ipNum integer value of the IP address (e.g 2923605416) + * @returns IPv4 address (e.g. 174.66.173.168) + */ + public static numToIp(ipNum: number): string { + // this all because bitwise math is signed + let remaining = ipNum; + const address = new Array(); + for (let i = 0; i < 4; i++) { + if (remaining !== 0) { + address.push(Math.floor(remaining / 256 ** (3 - i))); + remaining = remaining % 256 ** (3 - i); + } else { + address.push(0); + } + } + const ipAddress: string = address.join('.'); + if ( !this.validIp(ipAddress) ) { + throw new Error(`${ipAddress} is not a valid IP Address`); + } + return ipAddress; + } +} + +/** + * Exported class from VPC to support subnet filtering + * and CIDR validation + */ +export class CidrBlock { + + /** + * Calculates the netmask for a given CIDR mask + * + * The netmask is a 32-bit binary value used to separate the network portion from the host portion of an IPv4 address. + * It is calculated based on the CIDR prefix length (the number of bits used to represent the network portion). + * + * For example: + * CidrBlock.calculateNetmask(24) returns '255.255.255.0' + * + * @param mask The CIDR prefix length (between 0 and 32) for which to calculate the netmask. + // Calculate the netmask by performing a bitwise NOT on the result of (2^32 - 2^(32 - mask)) + * @returns The netmask string in IPv4 address format. + */ + public static calculateNetmask(mask: number): string { + return NetworkUtils.numToIp(2 ** 32 - 2 ** (32 - mask)); + } + + /** + * Calculates the number IP addresses in a CIDR Mask + * + * For example: + * CidrBlock.calculateNetsize(16) returns 65536 + * + * @param mask The CIDR prefix length (between 0 and 32) for which to calculate the network size. + * CidrBlock.calculateNetsize(24) returns 256 + */ + public static calculateNetsize(mask: number): number { + return 2 ** (32 - mask); + } + + /** + * IP address in the CIDR block. + */ + public readonly cidr: string; + + /* + * The CIDR mask e.g. for CIDR '10.0.0.0/21' returns 21 + */ + public readonly mask: number; + + /* + * The total number of IP addresses in the CIDR + */ + public readonly networkSize: number; + + /* + * The network address provided in CIDR creation offset by the Netsize -1 + */ + private readonly networkAddress: number; + + /* + * Parses either CIDR notation String or two numbers representing the IP + * space + * + * cidr expects a string '10.0.0.0/16' + * ipAddress expects a number + * mask expects a number + * + * If the given `cidr` or `ipAddress` is not the beginning of the block, + * then the next available block will be returned. For example, if + * `10.0.3.1/28` is given the returned block will represent `10.0.3.16/28`. + */ + constructor(cidr: string) + constructor(ipAddress: number, mask: number) + constructor(ipAddressOrCidr: string | number, mask?: number) { + if (typeof ipAddressOrCidr === 'string') { + this.mask = parseInt(ipAddressOrCidr.split('/')[1], 10); + this.networkAddress = NetworkUtils.ipToNum(ipAddressOrCidr.split('/')[0]) + + CidrBlock.calculateNetsize(this.mask) - 1; + } else { + if (typeof mask === 'number') { + this.mask = mask; + } else { + // this should be impossible + this.mask = 16; + } + this.networkAddress = ipAddressOrCidr + CidrBlock.calculateNetsize(this.mask) - 1; + this.networkSize = 2 ** (32 - this.mask); + } + this.networkSize = 2 ** (32 - this.mask); + this.cidr = `${this.minIp()}/${this.mask}`; + } + + /* + * The maximum IP in the CIDR Block e.g. '10.0.8.255' + */ + public maxIp(): string { + // min + (2^(32-mask)) - 1 [zero needs to count] + return NetworkUtils.numToIp(this.maxAddress()); + } + + /* + * Checks if this CIDR block fully contains the provided CIDR block. + * + * @param other The CIDR block to check for containment. + * @returns True if this CIDR block fully contains the provided CIDR block, false otherwise. + * + * The minimum IP in the CIDR Block e.g. '10.0.0.0' + */ + public minIp(): string { + return NetworkUtils.numToIp(this.minAddress()); + } + + /* + * Returns the number representation for the minimum IPv4 address + */ + public minAddress(): number { + const div = this.networkAddress % this.networkSize; + return this.networkAddress - div; + } + + /* + * Returns the number representation for the maximum IPv4 address + */ + public maxAddress(): number { + /** + * The maximum IP address in the CIDR block is calculated as the minimum address + (2^(32-mask)) - 1. + * This is because the minimum address represents the network address, and the maximum address is the broadcast address. + */ + // min + (2^(32-mask)) - 1 [zero needs to count] + return this.minAddress() + this.networkSize - 1; + } + + /* + * Returns the next consecutive CIDR block of the same mask size following this CIDR block. + * + * For example, if this CIDR block is '10.0.0.0/24', the next block would be '10.0.1.0/24'. + * + * Returns the next CIDR Block of the same mask size + */ + public nextBlock(): CidrBlock { + return new CidrBlock(this.maxAddress() + 1, this.mask); + } + + /* + * Returns true if this CidrBlock fully contains the provided CidrBlock + */ + public containsCidr(other: CidrBlock): boolean { + return (this.maxAddress() >= other.maxAddress()) && + (this.minAddress() <= other.minAddress()); + } + + /** + * Checks if two IP address ranges overlap. + * + * @param range1 The first IP address range represented as an array [start, end]. + * @param range2 The second IP address range represented as an array [start, end]. + * @returns True if the two IP address ranges overlap, false otherwise. + * + * Note: This method assumes that the start and end addresses are valid IPv4 addresses. + */ + public rangesOverlap(range1: [string, string], range2: [string, string]): boolean { + const [start1, end1] = range1; + const [start2, end2] = range2; + + // Check if ranges overlap + return start1 <= end2 && start2 <= end1; + } + +} + +/** + * Class with helper functions to support + * Subnet Ipv6 Address Validation + * + * This class provides methods for working with IPv6 CIDR blocks, including calculating the minimum and maximum + * IP addresses in a CIDR block, and checking if two CIDR blocks overlap. + */ +export class CidrBlockIpv6 { + + /** + * Ipv6 CIDR range + */ + public cidr: string; + /** + * The CIDR prefix length (number of bits used for the network portion of the address). + */ + public cidrPrefix: number; + private ipParts: bigint[]; + private networkBits: number; + private networkPart: bigint[]; + + constructor(cidr: string) { + this.cidr = cidr; + const [ipAddress, prefix] = cidr.split('/'); + this.cidrPrefix = parseInt(prefix, 10); + this.ipParts = this.parseBigIntParts(ipAddress); + this.networkBits = this.cidrPrefix; + this.networkPart = this.ipParts.slice(0, Math.ceil(this.networkBits / 16)); + } + + private parseBigIntParts(ipAddress: string): bigint[] { + return ipAddress.split(':').map((part) => BigInt(`0x${part.padStart(4, '0')}` || '0')); + } + + /** + * @returns Minimum IPv6 address for a provided CIDR + */ + public minIp(): string { + const startIP = [...this.networkPart]; + for (let i = this.networkPart.length; i < 8; i++) { + startIP.push(BigInt(0)); + } + return startIP.map(this.formatIPv6Part).join(':'); + } + + /** + * @returns Maximum IPv6 address for a provided CIDR + */ + public maxIp(): string { + const endIP = [...this.networkPart]; + const hostPart = Array(8 - this.networkPart.length).fill(BigInt(0xffff)); + endIP.push(...hostPart); + + return endIP.map(this.formatIPv6Part).join(':'); + } + + private formatIPv6Part = (part: bigint) => part.toString(16).padStart(4, '0'); + + /** + * + * @param range1 Ipv6 CIDR range to compare + * @param range2 Ipv6 CIDR range to compare + * @returns true if two ranges overlap, false otherwise + */ + public rangesOverlap(range1: string, range2: string): boolean { + const [start1, end1] = this.getIPv6Range(range1); + const [start2, end2] = this.getIPv6Range(range2); + + return (start1 <= end2) && (start2 <= end1); + } + + /** + * + * @param cidr + * @returns Range in the from of big int number [start, end] + */ + private getIPv6Range(cidr: string): [bigint, bigint] { + const [ipv6Address, prefixLength] = cidr.split('/'); + const ipv6Number = this.ipv6ToNumber(ipv6Address); + const mask = (BigInt(1) << BigInt(128 - Number(prefixLength))) - BigInt(1); + const networkPrefix = ipv6Number & ~mask; + const start = networkPrefix; + const end = networkPrefix | mask; + + return [start, end]; + } + + /** + * @param ipv6Address + * @returns Converts given ipv6 address range to big int number + */ + private ipv6ToNumber(ipv6Address: string): bigint { + const blocks = this.parseBigIntParts(ipv6Address); + let ipv6Number = BigInt(0); + for (const block of blocks) { + /* tslint:disable:no-bitwise */ + ipv6Number = (ipv6Number << BigInt(16)) + block; + } + return ipv6Number; + } +} + diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts new file mode 100644 index 0000000000000..1be8c35744356 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts @@ -0,0 +1,368 @@ +import { Resource, Annotations } from 'aws-cdk-lib'; +import { IVpc, ISubnet, SubnetSelection, SelectedSubnets, EnableVpnGatewayOptions, VpnGateway, VpnConnectionType, CfnVPCGatewayAttachment, CfnVPNGatewayRoutePropagation, VpnConnectionOptions, VpnConnection, ClientVpnEndpointOptions, ClientVpnEndpoint, InterfaceVpcEndpointOptions, InterfaceVpcEndpoint, GatewayVpcEndpointOptions, GatewayVpcEndpoint, FlowLogOptions, FlowLog, FlowLogResourceType, SubnetType, SubnetFilter, CfnVPCCidrBlock } from 'aws-cdk-lib/aws-ec2'; +import { allRouteTableIds, flatten, subnetGroupNameFromConstructId } from './util'; +import { IDependable, Dependable, IConstruct } from 'constructs'; + +/** + * Placeholder to see what extra props we might need, + * will be added to original IVPC + */ +export interface IVpcV2 extends IVpc { + /** + * The secondary CIDR blocks associated with the VPC. + * + * For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-resize}. + */ + readonly secondaryCidrBlock: CfnVPCCidrBlock[]; + + /** + * The primary IPv4 CIDR block associated with the VPC. + * Needed in order to validate the vpc range of subnet + * current prop vpcCidrBlock refers to the token value + * For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4}. + */ + readonly ipv4CidrBlock: string; + +} + +/** + * Base class for creating a VPC (Virtual Private Cloud) in AWS. + * + * For more information, see the {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html|AWS CDK Documentation on VPCs}. + */ +export abstract class VpcV2Base extends Resource implements IVpcV2 { + + /** + * Identifier for this VPC + */ + public abstract readonly vpcId: string; + + /** + * Arn of this VPC + */ + public abstract readonly vpcArn: string; + + /** + * CIDR range for this VPC + */ + public abstract readonly vpcCidrBlock: string; + + /** + * List of public subnets in this VPC + */ + public readonly publicSubnets: ISubnet[] = []; + + /** + * List of private subnets in this VPC + */ + public readonly privateSubnets: ISubnet[] = []; + + /** + * List of isolated subnets in this VPC + */ + public abstract readonly isolatedSubnets: ISubnet[]; + + /** + * AZs for this VPC + */ + public readonly availabilityZones: string[] = []; + + /** + * Dependable that can be depended upon to force internet connectivity established on the VPC + */ + public abstract readonly internetConnectivityEstablished: IDependable; + + /** + * Secondary IPs for the VPC, can be multiple Ipv4 or Ipv6 + * Ipv4 should be within RFC#1918 range + */ + public abstract readonly secondaryCidrBlock: CfnVPCCidrBlock[]; + + /** + * The primary IPv4 CIDR block associated with the VPC. + * Needed in order to validate the vpc range of subnet + * current prop vpcCidrBlock refers to the token value + * For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4}. + */ + public abstract readonly ipv4CidrBlock: string; + + /** + * If this is set to true, don't error out on trying to select subnets + */ + protected incompleteSubnetDefinition: boolean = false; + + /** + * Mutable private field for the vpnGatewayId + * + * @internal + */ + protected _vpnGatewayId?: string; + + /** + * Return information on the subnets appropriate for the given selection strategy + * + * Requires that at least one subnet is matched, throws a descriptive + * error message otherwise. + */ + public selectSubnets(selection: SubnetSelection = {}): SelectedSubnets { + const subnets = this.selectSubnetObjects(selection); + const pubs = new Set(this.publicSubnets); + + return { + subnetIds: subnets.map(s => s.subnetId), + get availabilityZones(): string[] { return subnets.map(s => s.availabilityZone); }, + internetConnectivityEstablished: tap(new CompositeDependable(), d => subnets.forEach(s => d.add(s.internetConnectivityEstablished))), + subnets, + hasPublic: subnets.some(s => pubs.has(s)), + isPendingLookup: this.incompleteSubnetDefinition, + }; + } + + /** + * Adds a VPN Gateway to this VPC + */ + public enableVpnGateway(options: EnableVpnGatewayOptions): void { + if (this.vpnGatewayId) { + throw new Error('The VPN Gateway has already been enabled.'); + } + + const vpnGateway = new VpnGateway(this, 'VpnGateway', { + amazonSideAsn: options.amazonSideAsn, + type: VpnConnectionType.IPSEC_1, + }); + + this._vpnGatewayId = vpnGateway.gatewayId; + + const attachment = new CfnVPCGatewayAttachment(this, 'VPCVPNGW', { + vpcId: this.vpcId, + vpnGatewayId: this._vpnGatewayId, + }); + + // Propagate routes on route tables associated with the right subnets + const vpnRoutePropagation = options.vpnRoutePropagation ?? [{}]; + const routeTableIds = allRouteTableIds(flatten(vpnRoutePropagation.map(s => this.selectSubnets(s).subnets))); + + if (routeTableIds.length === 0) { + Annotations.of(this).addError(`enableVpnGateway: no subnets matching selection: '${JSON.stringify(vpnRoutePropagation)}'. Select other subnets to add routes to.`); + } + + const routePropagation = new CfnVPNGatewayRoutePropagation(this, 'RoutePropagation', { + routeTableIds, + vpnGatewayId: this._vpnGatewayId, + }); + // The AWS::EC2::VPNGatewayRoutePropagation resource cannot use the VPN gateway + // until it has successfully attached to the VPC. + // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html + routePropagation.node.addDependency(attachment); + } + + /** + * Adds a new VPN connection to this VPC + */ + public addVpnConnection(id: string, options: VpnConnectionOptions): VpnConnection { + return new VpnConnection(this, id, { + vpc: this, + ...options, + }); + } + + /** + * Adds a new client VPN endpoint to this VPC + */ + public addClientVpnEndpoint(id: string, options: ClientVpnEndpointOptions): ClientVpnEndpoint { + return new ClientVpnEndpoint(this, id, { + ...options, + vpc: this, + }); + } + + /** + * Adds a new interface endpoint to this VPC + */ + public addInterfaceEndpoint(id: string, options: InterfaceVpcEndpointOptions): InterfaceVpcEndpoint { + return new InterfaceVpcEndpoint(this, id, { + vpc: this, + ...options, + }); + } + + /** + * Adds a new gateway endpoint to this VPC + */ + public addGatewayEndpoint(id: string, options: GatewayVpcEndpointOptions): GatewayVpcEndpoint { + return new GatewayVpcEndpoint(this, id, { + vpc: this, + ...options, + }); + } + + /** + * Adds a new flow log to this VPC + */ + public addFlowLog(id: string, options?: FlowLogOptions): FlowLog { + return new FlowLog(this, id, { + resourceType: FlowLogResourceType.fromVpc(this), + ...options, + }); + } + + /** + * Returns the id of the VPN Gateway (if enabled) + */ + public get vpnGatewayId(): string | undefined { + return this._vpnGatewayId; + } + + /** + * Return the subnets appropriate for the placement strategy + */ + protected selectSubnetObjects(selection: SubnetSelection = {}): ISubnet[] { + selection = this.reifySelectionDefaults(selection); + + if (selection.subnets !== undefined) { + return selection.subnets; + } + + let subnets; + + if (selection.subnetGroupName !== undefined) { // Select by name + subnets = this.selectSubnetObjectsByName(selection.subnetGroupName); + + } else { // Or specify by type + const type = selection.subnetType || SubnetType.PRIVATE_WITH_EGRESS; + subnets = this.selectSubnetObjectsByType(type); + } + + // Apply all the filters + subnets = this.applySubnetFilters(subnets, selection.subnetFilters ?? []); + + return subnets; + } + + private applySubnetFilters(subnets: ISubnet[], filters: SubnetFilter[]): ISubnet[] { + let filtered = subnets; + // Apply each filter in sequence + for (const filter of filters) { + filtered = filter.selectSubnets(filtered); + } + return filtered; + } + + private selectSubnetObjectsByName(groupName: string) { + const allSubnets = [...this.publicSubnets, ...this.privateSubnets, ...this.isolatedSubnets]; + const subnets = allSubnets.filter(s => subnetGroupNameFromConstructId(s) === groupName); + + if (subnets.length === 0 && !this.incompleteSubnetDefinition) { + const names = Array.from(new Set(allSubnets.map(subnetGroupNameFromConstructId))); + throw new Error(`There are no subnet groups with name '${groupName}' in this VPC. Available names: ${names}`); + } + + return subnets; + } + + private selectSubnetObjectsByType(subnetType: SubnetType) { + const allSubnets = { + [SubnetType.PRIVATE_ISOLATED]: this.isolatedSubnets, + [SubnetType.ISOLATED]: this.isolatedSubnets, + [SubnetType.PRIVATE_WITH_NAT]: this.privateSubnets, + [SubnetType.PRIVATE_WITH_EGRESS]: this.privateSubnets, + [SubnetType.PRIVATE]: this.privateSubnets, + [SubnetType.PUBLIC]: this.publicSubnets, + }; + + const subnets = allSubnets[subnetType]; + + // Force merge conflict here with https://github.com/aws/aws-cdk/pull/4089 + // see ImportedVpc + + if (subnets.length === 0 && !this.incompleteSubnetDefinition) { + const availableTypes = Object.entries(allSubnets).filter(([_, subs]) => subs.length > 0).map(([typeName, _]) => typeName); + throw new Error(`There are no '${subnetType}' subnet groups in this VPC. Available types: ${availableTypes}`); + } + + return subnets; + } + + /** + * Validate the fields in a SubnetSelection object, and reify defaults if necessary + * + * In case of default selection, select the first type of PRIVATE, ISOLATED, + * PUBLIC (in that order) that has any subnets. + */ + private reifySelectionDefaults(placement: SubnetSelection): SubnetSelection { + + // TODO: throw error as new VpcV2 cannot support subnetName or subnetGroupName anymore + if (placement.subnetName !== undefined) { + if (placement.subnetGroupName !== undefined) { + throw new Error('Please use only \'subnetGroupName\' (\'subnetName\' is deprecated and has the same behavior)'); + } else { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:subnetNameDeprecated', 'Usage of \'subnetName\' in SubnetSelection is deprecated, use \'subnetGroupName\' instead'); + } + placement = { ...placement, subnetGroupName: placement.subnetName }; + } + + const exclusiveSelections: Array = ['subnets', 'subnetType', 'subnetGroupName']; + const providedSelections = exclusiveSelections.filter(key => placement[key] !== undefined); + if (providedSelections.length > 1) { + throw new Error(`Only one of '${providedSelections}' can be supplied to subnet selection.`); + } + + if (placement.subnetType === undefined && placement.subnetGroupName === undefined && placement.subnets === undefined) { + // Return default subnet type based on subnets that actually exist + let subnetType = this.privateSubnets.length + ? SubnetType.PRIVATE_WITH_EGRESS : this.isolatedSubnets.length ? SubnetType.PRIVATE_ISOLATED : SubnetType.PUBLIC; + placement = { ...placement, subnetType: subnetType }; + } + + // Establish which subnet filters are going to be used + let subnetFilters = placement.subnetFilters ?? []; + + // Backwards compatibility with existing `availabilityZones` and `onePerAz` functionality + if (placement.availabilityZones !== undefined) { // Filter by AZs, if specified + subnetFilters.push(SubnetFilter.availabilityZones(placement.availabilityZones)); + } + if (!!placement.onePerAz) { // Ensure one per AZ if specified + subnetFilters.push(SubnetFilter.onePerAz()); + } + + // Overwrite the provided placement filters and remove the availabilityZones and onePerAz properties + placement = { ...placement, subnetFilters: subnetFilters, availabilityZones: undefined, onePerAz: undefined }; + const { availabilityZones, onePerAz, ...rest } = placement; + + return rest; + } + +} + +class CompositeDependable implements IDependable { + private readonly dependables = new Array(); + + constructor() { + const self = this; + Dependable.implement(this, { + get dependencyRoots() { + const ret = new Array(); + for (const dep of self.dependables) { + ret.push(...Dependable.of(dep).dependencyRoots); + } + return ret; + }, + }); + } + + /** + * Add a construct to the dependency roots + */ + public add(dep: IDependable) { + this.dependables.push(dep); + } +} + +/** +* Invoke a function on a value (for its side effect) and return the value +*/ +function tap(x: T, fn: (x: T) => void): T { + fn(x); + return x; + +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts new file mode 100644 index 0000000000000..76fc7c654921b --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts @@ -0,0 +1,487 @@ +import { CfnVPC, CfnVPCCidrBlock, DefaultInstanceTenancy, ISubnet } from 'aws-cdk-lib/aws-ec2'; +import { Arn, CfnResource, Lazy, Names } from 'aws-cdk-lib/core'; +import { Construct, DependencyGroup, IDependable } from 'constructs'; +import { IpamOptions, IIpamPool } from './ipam'; +import { VpcV2Base } from './vpc-v2-base'; + +/** + * Additional props needed for secondary Address + */ +export interface SecondaryAddressProps { + /** + * Required to set Secondary cidr block resource name + * in order to generate unique logical id for the resource. + */ + readonly cidrBlockName: string; +} + +/** + * IpAddress options to define VPC V2 + */ +export class IpAddresses { + + /** + * An IPv4 CIDR Range + */ + public static ipv4(ipv4Cidr: string, props?: SecondaryAddressProps): IIpAddresses { + return new ipv4CidrAllocation(ipv4Cidr, props); + } + + /** + * An Ipv4 Ipam Pool + */ + public static ipv4Ipam(ipv4IpamOptions: IpamOptions): IIpAddresses { + return new IpamIpv4(ipv4IpamOptions); + } + + /** + * An Ipv6 Ipam Pool + */ + public static ipv6Ipam(ipv6IpamOptions: IpamOptions): IIpAddresses { + return new IpamIpv6(ipv6IpamOptions); + } + + /** + * Amazon Provided Ipv6 range + */ + public static amazonProvidedIpv6(props: SecondaryAddressProps) : IIpAddresses { + return new AmazonProvided(props); + } +} + +/** + * Consolidated return parameters to pass to VPC construct + */ +export interface VpcCidrOptions { + + /** + * IPv4 CIDR Block + * @default - '10.0.0.0/16' + */ + readonly ipv4CidrBlock?: string; + + /** + * CIDR Mask for Vpc + * + * @default - Only required when using IPAM Ipv4 + */ + readonly ipv4NetmaskLength?: number; + + /** + * Ipv4 IPAM Pool + * + * @default - Only required when using IPAM Ipv4 + */ + readonly ipv4IpamPool?: IIpamPool; + + /** + * Implementing Ipv6 + * @default - No ipv6 address + */ + readonly ipv6CidrBlock?: string; + + /** + * CIDR Mask for Vpc + * + * @default - Only required when using AWS Ipam + */ + readonly ipv6NetmaskLength?: number; + + /** + * Ipv6 IPAM pool id for VPC range, can only be defined + * under public scope + * + * @default - no pool id + */ + readonly ipv6IpamPool?: IIpamPool; + + /** + * Use amazon provided IP range + * @default false + */ + readonly amazonProvided?: boolean; + + /** + * Dependency to associate Ipv6 CIDR block + * @default - No dependency + */ + readonly dependencies?: CfnResource[]; + + /** + * Required to set Secondary cidr block resource name + * in order to generate unique logical id for the resource. + * @default : no name for primary addresses + */ + readonly cidrBlockName?: string; +} + +/** + * Implements ip address allocation according to the IPAdress type + */ +export interface IIpAddresses { + + /** + * Method to define the implementation logic of + * IP address allocation + */ + allocateVpcCidr() : VpcCidrOptions; + +} + +/** + * Properties to define VPC + * [disable-awslint:from-method] + */ +export interface VpcV2Props { + + /** A must IPv4 CIDR block for the VPC + * https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html + * @default - Ipv4 CIDR Block ('10.0.0.0/16') + */ + readonly primaryAddressBlock?: IIpAddresses; + + /** + * The secondary CIDR blocks associated with the VPC. + * Can be IPv4 or IPv6, two IPv4 ranges must follow RFC#1918 convention + * For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-resize}. + * @default - No secondary IP address + */ + readonly secondaryAddressBlocks?: IIpAddresses[]; + + /** + * Indicates whether the instances launched in the VPC get DNS hostnames + * @default true + */ + readonly enableDnsHostnames?: boolean; + + /** + * Indicates whether the DNS resolution is supported for the VPC. + * @default true + */ + readonly enableDnsSupport?: boolean; + + /** + * The default tenancy of instances launched into the VPC. + * + * By setting this to dedicated tenancy, instances will be launched on + * hardware dedicated to a single AWS customer, unless specifically specified + * at instance launch time. Please note, not all instance types are usable + * with Dedicated tenancy. + * + * @default DefaultInstanceTenancy.Default (shared) tenancy + */ + readonly defaultInstanceTenancy?: DefaultInstanceTenancy; + + /** + * Physical name for the VPC + * @default: autogenerated by CDK + */ + readonly vpcName?: string; +} + +/** + * This class provides a foundation for creating and configuring a VPC with advanced features such as IPAM (IP Address Management) and IPv6 support. + * + * For more information, see the {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html|AWS CDK Documentation on VPCs}. + * + * @resource AWS::EC2::VPC + */ +export class VpcV2 extends VpcV2Base { + + /** + * Identifier for this VPC + */ + public readonly vpcId: string; + + /** + * @attribute + */ + public readonly vpcArn: string; + + /** + * @attribute + */ + public readonly vpcCidrBlock: string; + /** + * The IPv6 CIDR blocks for the VPC. + * + * See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html#aws-resource-ec2-vpc-return-values + */ + public readonly ipv6CidrBlocks: string[]; + + /** + * The provider of ipv4 addresses + */ + public readonly ipAddresses: IIpAddresses; + + /** + * The AWS CloudFormation resource representing the VPC. + */ + public readonly resource: CfnVPC; + + /** + * Indicates if instances launched in this VPC will have public DNS hostnames. + */ + public readonly dnsHostnamesEnabled: boolean; + + /** + * Indicates if DNS support is enabled for this VPC. + */ + public readonly dnsSupportEnabled: boolean; + + /** + * Isolated Subnets that are part of this VPC. + */ + public readonly isolatedSubnets: ISubnet[]; + + /** + * Public Subnets that are part of this VPC. + */ + public readonly publicSubnets: ISubnet[]; + + /** + * Pbulic Subnets that are part of this VPC. + */ + public readonly privateSubnets: ISubnet[]; + + /** + * To define dependency on internet connectivity + */ + public readonly internetConnectivityEstablished: IDependable; + + /** + * To define dependency on internet connectivity + */ + private readonly _internetConnectivityEstablished = new DependencyGroup(); + + /** + * reference to all secondary blocks attached + */ + public readonly secondaryCidrBlock = new Array; + + /** + * For validation to define IPv6 subnets, set to true in case of + * Amazon Provided IPv6 cidr range + * IPv6 addresses can be attached to the subnets + * @default false + */ + public readonly useIpv6: boolean = false; + + public readonly ipv4CidrBlock: string = ''; + + constructor(scope: Construct, id: string, props: VpcV2Props = {}) { + super(scope, id, { + physicalName: props.vpcName ?? Lazy.string({ + produce: () => Names.uniqueResourceName(this, { maxLength: 128, allowedSpecialCharacters: '_' }), + }), + }); + + this.ipAddresses = props.primaryAddressBlock ?? IpAddresses.ipv4('10.0.0.0/16'); + const vpcOptions = this.ipAddresses.allocateVpcCidr(); + + this.dnsHostnamesEnabled = props.enableDnsHostnames == null ? true : props.enableDnsHostnames; + this.dnsSupportEnabled = props.enableDnsSupport == null ? true : props.enableDnsSupport; + const instanceTenancy = props.defaultInstanceTenancy || 'default'; + this.resource = new CfnVPC(this, 'Resource', { + cidrBlock: vpcOptions.ipv4CidrBlock, //for Ipv4 addresses CIDR block + enableDnsHostnames: this.dnsHostnamesEnabled, + enableDnsSupport: this.dnsSupportEnabled, + ipv4IpamPoolId: vpcOptions.ipv4IpamPool?.ipamPoolId, // for Ipv4 ipam option + ipv4NetmaskLength: vpcOptions.ipv4NetmaskLength, // for Ipv4 ipam option + instanceTenancy: instanceTenancy, + }); + + this.node.defaultChild = this.resource; + this.vpcCidrBlock = this.resource.attrCidrBlock; + if (vpcOptions.ipv4CidrBlock) { + this.ipv4CidrBlock = vpcOptions.ipv4CidrBlock; + } + this.ipv6CidrBlocks = this.resource.attrIpv6CidrBlocks; + this.vpcId = this.resource.attrVpcId; + this.vpcArn = Arn.format({ + service: 'ec2', + resource: 'vpc', + resourceName: this.vpcId, + }, this.stack); + + if (props.secondaryAddressBlocks) { + const secondaryAddressBlocks: IIpAddresses[] = props.secondaryAddressBlocks; + + for (const secondaryAddressBlock of secondaryAddressBlocks) { + + const secondaryVpcOptions: VpcCidrOptions = secondaryAddressBlock.allocateVpcCidr(); + if (!secondaryVpcOptions.cidrBlockName) { + throw new Error('Cidr Block Name is required to create secondary IP address'); + } + + if (secondaryVpcOptions.amazonProvided || secondaryVpcOptions.ipv6IpamPool) { + this.useIpv6 = true; + } + //validate CIDR ranges per RFC 1918 + if (secondaryVpcOptions.ipv4CidrBlock!) { + const ret = validateIpv4address(secondaryVpcOptions.ipv4CidrBlock, this.resource.cidrBlock); + if (ret === false) { + throw new Error('CIDR block should be in the same RFC 1918 range in the VPC'); + } + } + const cfnVpcCidrBlock = new CfnVPCCidrBlock(this, secondaryVpcOptions.cidrBlockName, { + vpcId: this.vpcId, + cidrBlock: secondaryVpcOptions.ipv4CidrBlock, + ipv4IpamPoolId: secondaryVpcOptions.ipv4IpamPool?.ipamPoolId, + ipv4NetmaskLength: secondaryVpcOptions.ipv4NetmaskLength, + ipv6NetmaskLength: secondaryVpcOptions.ipv6NetmaskLength, + ipv6IpamPoolId: secondaryVpcOptions.ipv6IpamPool?.ipamPoolId, + amazonProvidedIpv6CidrBlock: secondaryVpcOptions.amazonProvided, + }); + if (secondaryVpcOptions.dependencies) { + for (const dep of secondaryVpcOptions.dependencies) { + cfnVpcCidrBlock.addDependency(dep); + } + } + //Create secondary blocks for Ipv4 and Ipv6 + this.secondaryCidrBlock.push(cfnVpcCidrBlock); + } + } + + /** + * Empty array for isolated subnets + */ + this.isolatedSubnets = new Array; + + /** + * Empty array for public subnets + */ + this.publicSubnets = new Array; + + /** + * Empty array for private subnets + */ + this.privateSubnets = new Array; + + /** + * Dependable that can be depended upon to force internet connectivity established on the VPC + * Add igw to this if its a public subnet + */ + this.internetConnectivityEstablished = this._internetConnectivityEstablished; + } +} +/** + * Supports assigning IPv4 address to VPC + */ +class ipv4CidrAllocation implements IIpAddresses { + + constructor(private readonly cidrBlock: string, private readonly props?: { cidrBlockName: string}) { + } + + /** + * @returns CIDR block provided by the user to set IPv4 + */ + allocateVpcCidr(): VpcCidrOptions { + return { + ipv4CidrBlock: this.cidrBlock, + cidrBlockName: this.props?.cidrBlockName, + }; + } +} + +/** + * Supports Amazon Provided Ipv6 ranges + */ +class AmazonProvided implements IIpAddresses { + /** + * Represents an Amazon-provided IPv6 CIDR range for a VPC. + * + * This class implements the IIpAddresses interface and is used to allocate an Amazon-provided + * IPv6 CIDR range for a VPC. When an instance of this class is used to allocate the VPC CIDR, + * Amazon will automatically assign an IPv6 CIDR range from its pool of available addresses. + */ + + constructor(private readonly props: { cidrBlockName: string}) {}; + + allocateVpcCidr(): VpcCidrOptions { + return { + amazonProvided: true, + cidrBlockName: this.props.cidrBlockName, + }; + } + +} + +/** + * Represents an IPv4 address range managed by AWS IP Address Manager (IPAM). + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipam.html + */ +class IpamIpv6 implements IIpAddresses { + + constructor(private readonly props: IpamOptions) { + } + + allocateVpcCidr(): VpcCidrOptions { + return { + ipv6NetmaskLength: this.props.netmaskLength, + ipv6IpamPool: this.props.ipamPool, + dependencies: this.props.ipamPool?.ipamCidrs.map(c => c as CfnResource), + cidrBlockName: this.props.cidrBlockName, + }; + } +} + +/** + * Represents an IPv4 address range managed by AWS IP Address Manager (IPAM). + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipam.html + */ +class IpamIpv4 implements IIpAddresses { + + constructor(private readonly props: IpamOptions) { + } + allocateVpcCidr(): VpcCidrOptions { + + return { + ipv4NetmaskLength: this.props.netmaskLength, + ipv4IpamPool: this.props.ipamPool, + cidrBlockName: this.props?.cidrBlockName, + }; + } +} + +//@internal First two Octet to verify RFC 1918 +interface IPaddressConfig { + octet1: number; + octet2: number; +} + +/** + * Validates whether a secondary IPv4 address is within the same private IP address range as the primary IPv4 address. + * + * @param cidr1 The secondary IPv4 CIDR block to be validated. + * @param cidr2 The primary IPv4 CIDR block to validate against. + * @returns True if the secondary IPv4 CIDR block is within the same private IP address range as the primary IPv4 CIDR block, false otherwise. + * @internal + * The private IP address ranges are defined by RFC 1918 as 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16. + */ +function validateIpv4address(cidr1?: string, cidr2?: string): boolean { + if (!cidr1 || !cidr2) { + return false; // Handle cases where CIDR ranges are not provided + } + + const octetsCidr1: number[] = cidr1.split('.').map(octet => parseInt(octet, 10)); + const octetsCidr2: number[] = cidr2.split('.').map(octet => parseInt(octet, 10)); + + if (octetsCidr1.length !== 4 || octetsCidr2.length !== 4) { + return false; // Handle invalid CIDR ranges + } + + const ip1: IPaddressConfig = { + octet1: octetsCidr1[0], + octet2: octetsCidr1[1], + }; + + const ip2: IPaddressConfig = { + octet1: octetsCidr2[0], + octet2: octetsCidr2[1], + }; + + return (ip1.octet1 === 10 && ip2.octet1 === 10) || + (ip1.octet1 === 192 && ip1.octet2 === 168 && ip2.octet1 === 192 && ip2.octet2 === 168) || + (ip1.octet1 === 172 && ip1.octet2 === 16 && ip2.octet1 === 172 && ip2.octet2 === 16); // CIDR ranges belong to same private IP address ranges +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/package.json b/packages/@aws-cdk/aws-ec2-alpha/package.json new file mode 100644 index 0000000000000..be679d1fa77c6 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/package.json @@ -0,0 +1,107 @@ +{ + "name": "@aws-cdk/aws-ec2-alpha", + "private": true, + "version": "0.0.0", + "description": "The CDK construct library for VPC V2", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.ec2.alpha", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "ec2-alpha" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.ec2.Alpha", + "packageId": "Amazon.CDK.AWS.ec2.Alpha", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-ec2-alpha", + "module": "aws_cdk.aws_ec2_alpha", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ] + }, + "go": { + "moduleName": "github.com/aws/aws-cdk-go", + "packageName": "awsec2alpha" + } + }, + "projectReferences": true, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-ec2-alpha" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "integ-runner --language javascript", + "pkglint": "pkglint -f", + "awslint": "cdk-awslint", + "package": "cdk-package", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "keywords": [ + "aws", + "cdk", + "example", + "construct", + "library" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests-alpha": "^0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^29.5.12", + "aws-cdk-lib": "0.0.0", + "jest": "^29.7.0" + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + "aws-cdk-lib": "^0.0.0", + "constructs": "^10.0.0" + }, + "separate-module": false, + "engines": { + "node": ">= 14.15.0" + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + } +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.assets.json new file mode 100644 index 0000000000000..f61a2717f93a6 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "b3d06cef480a17aaf78379d18a13893141f2d689a23bcbbcf34b284e77752b0f": { + "source": { + "path": "aws-cdk-routev2-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b3d06cef480a17aaf78379d18a13893141f2d689a23bcbbcf34b284e77752b0f.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.template.json new file mode 100644 index 0000000000000..140f9ebf102e0 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-alpha.template.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "defaultC974F9E3": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "defaultAmazonIpv6C7A4D665": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + } + }, + "defaultSubnetDFB3A3B6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "defaultC974F9E3", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + }, + "DependsOn": [ + "defaultAmazonIpv6C7A4D665" + ] + }, + "defaultSubnetRouteTableAssociationF1D85D29": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "defaultSubnetDFB3A3B6" + } + }, + "DependsOn": [ + "defaultAmazonIpv6C7A4D665" + ] + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.assets.json new file mode 100644 index 0000000000000..b9734dc366438 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "7711ae87a96bcf4e738e5904b6071f21ac59ee14247c420b0bf33d20a87348a3": { + "source": { + "path": "aws-cdk-routev2-dynamodbendpoint-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "7711ae87a96bcf4e738e5904b6071f21ac59ee14247c420b0bf33d20a87348a3.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.template.json new file mode 100644 index 0000000000000..1fc8a4ff1bbe3 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-dynamodbendpoint-alpha.template.json @@ -0,0 +1,147 @@ +{ + "Resources": { + "dynamodbC0A56799": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "dynamodbAmazonIpv6698EF571": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "dynamodbSubnet81957A26": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + }, + "DependsOn": [ + "dynamodbAmazonIpv6698EF571" + ] + }, + "dynamodbSubnetRouteTableAssociationC38B30F3": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "dynamodbSubnet81957A26" + } + }, + "DependsOn": [ + "dynamodbAmazonIpv6698EF571" + ] + }, + "testDynamoEndpoint03D5BDE5": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "RouteTableIds": [ + { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + ], + "ServiceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".dynamodb" + ] + ] + }, + "VpcEndpointType": "Gateway", + "VpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.assets.json new file mode 100644 index 0000000000000..b27c0c57931d5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "6cd56bb964ed1f90f0206d705f085aef381173834b50d5ba372fa2185156d51d": { + "source": { + "path": "aws-cdk-routev2-egressonlyigw-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6cd56bb964ed1f90f0206d705f085aef381173834b50d5ba372fa2185156d51d.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.template.json new file mode 100644 index 0000000000000..1c4d9adad8e08 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-egressonlyigw-alpha.template.json @@ -0,0 +1,134 @@ +{ + "Resources": { + "eigwC0F094EF": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "eigwAmazonIpv69E78211F": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "eigwSubnetCC28B9F9": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "VpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + }, + "DependsOn": [ + "eigwAmazonIpv69E78211F" + ] + }, + "eigwSubnetRouteTableAssociation887F4A97": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "eigwSubnetCC28B9F9" + } + }, + "DependsOn": [ + "eigwAmazonIpv69E78211F" + ] + }, + "testEOIGWEIGW54CCAD37": { + "Type": "AWS::EC2::EgressOnlyInternetGateway", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "testEIGWRouteEB4FE8D5": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "DestinationIpv6CidrBlock": "0.0.0.0/0", + "EgressOnlyInternetGatewayId": { + "Fn::GetAtt": [ + "testEOIGWEIGW54CCAD37", + "Id" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.assets.json new file mode 100644 index 0000000000000..677f15417b1ed --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "44c69eec973961e184209d04e6e45c230320a2f7a110f0275431dc0587273038": { + "source": { + "path": "aws-cdk-routev2-igw-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "44c69eec973961e184209d04e6e45c230320a2f7a110f0275431dc0587273038.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.template.json new file mode 100644 index 0000000000000..1ddb6c3cc40d9 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-igw-alpha.template.json @@ -0,0 +1,154 @@ +{ + "Resources": { + "igw127F1970": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "igwAmazonIpv64026617C": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "igwSubnetF238E402": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "igw127F1970", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + }, + "DependsOn": [ + "igwAmazonIpv64026617C" + ] + }, + "igwSubnetRouteTableAssociationA48C27F3": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "igwSubnetF238E402" + } + }, + "DependsOn": [ + "igwAmazonIpv64026617C" + ] + }, + "testIGW8D947AF2": { + "Type": "AWS::EC2::InternetGateway" + }, + "testIGWRoute7696715B": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "DestinationIpv6CidrBlock": "0.0.0.0/0", + "GatewayId": { + "Fn::GetAtt": [ + "testIGW8D947AF2", + "InternetGatewayId" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "testIGWRouteGWAttachmentB0836D42": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Fn::GetAtt": [ + "testIGW8D947AF2", + "InternetGatewayId" + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.assets.json new file mode 100644 index 0000000000000..733952daae63f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "087e3b456bae228983dc7a31eea1570bfeccfd6b4f163b7e10a2af07dc31291f": { + "source": { + "path": "aws-cdk-routev2-networkif-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "087e3b456bae228983dc7a31eea1570bfeccfd6b4f163b7e10a2af07dc31291f.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.template.json new file mode 100644 index 0000000000000..d796497fc5388 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-networkif-alpha.template.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "nif44200315": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "nifAmazonIpv6CF4BF46B": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + } + }, + "nifSubnetAEB60456": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "nif44200315", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + }, + "DependsOn": [ + "nifAmazonIpv6CF4BF46B" + ] + }, + "nifSubnetRouteTableAssociationE4036B9F": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "nifSubnetAEB60456" + } + }, + "DependsOn": [ + "nifAmazonIpv6CF4BF46B" + ] + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.assets.json new file mode 100644 index 0000000000000..591ec9e8d3066 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "89c945d2b4cb2aa79cca0e52ea8fa68849a586495b0a27b7de229ae44b3c5239": { + "source": { + "path": "aws-cdk-routev2-privatenatgw-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "89c945d2b4cb2aa79cca0e52ea8fa68849a586495b0a27b7de229ae44b3c5239.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.template.json new file mode 100644 index 0000000000000..f2ed7e0d44c03 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-privatenatgw-alpha.template.json @@ -0,0 +1,152 @@ +{ + "Resources": { + "natgwpriv081A7D93": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "natgwprivAmazonIpv6915E8E4F": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + } + }, + "natgwprivSubnetE547C5A0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + }, + "DependsOn": [ + "natgwprivAmazonIpv6915E8E4F" + ] + }, + "natgwprivSubnetRouteTableAssociation9E115869": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "natgwprivSubnetE547C5A0" + } + }, + "DependsOn": [ + "natgwprivAmazonIpv6915E8E4F" + ] + }, + "testNATgwNATGateway1533420D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "ConnectivityType": "private", + "PrivateIpAddress": "10.0.0.42", + "SecondaryPrivateIpAddresses": [ + "10.0.0.43", + "10.0.0.44", + "10.0.0.45" + ], + "SubnetId": { + "Ref": "natgwprivSubnetE547C5A0" + } + }, + "DependsOn": [ + "natgwprivSubnetRouteTableAssociation9E115869" + ] + }, + "testNATGWRoute7A26EC80": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "DestinationIpv6CidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Fn::GetAtt": [ + "testNATgwNATGateway1533420D", + "NatGatewayId" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.assets.json new file mode 100644 index 0000000000000..29398ffe76faa --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "6592172436ea6af85dd73663ffd81cc1342c29574aa00f4dacf5179cf3054441": { + "source": { + "path": "aws-cdk-routev2-publicnatgw-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6592172436ea6af85dd73663ffd81cc1342c29574aa00f4dacf5179cf3054441.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.template.json new file mode 100644 index 0000000000000..5f80cf56a0aa5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-publicnatgw-alpha.template.json @@ -0,0 +1,204 @@ +{ + "Resources": { + "natgwpub2FB85986": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "natgwpubAmazonIpv625B947F8": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "natgwpubSubnet79D316E5": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + }, + "DependsOn": [ + "natgwpubAmazonIpv625B947F8" + ] + }, + "natgwpubSubnetRouteTableAssociation019CE26A": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "natgwpubSubnet79D316E5" + } + }, + "DependsOn": [ + "natgwpubAmazonIpv625B947F8" + ] + }, + "testNATgwIGW6AC97E9A": { + "Type": "AWS::EC2::InternetGateway" + }, + "testnatgwigwRouteE8D2BF39": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "242.0.0.0/32", + "DestinationIpv6CidrBlock": "242.0.0.0/32", + "GatewayId": { + "Fn::GetAtt": [ + "testNATgwIGW6AC97E9A", + "InternetGatewayId" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "testnatgwigwRouteGWAttachmentB8E1033C": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Fn::GetAtt": [ + "testNATgwIGW6AC97E9A", + "InternetGatewayId" + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "testNATgwEIP1C260FAD": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + }, + "DependsOn": [ + "natgwpubSubnetRouteTableAssociation019CE26A" + ] + }, + "testNATgwNATGateway1533420D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "testNATgwEIP1C260FAD", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "natgwpubSubnet79D316E5" + } + }, + "DependsOn": [ + "natgwpubSubnetRouteTableAssociation019CE26A" + ] + }, + "testNATGWRoute7A26EC80": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "DestinationIpv6CidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Fn::GetAtt": [ + "testNATgwNATGateway1533420D", + "NatGatewayId" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.assets.json new file mode 100644 index 0000000000000..601d17d534bb8 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "2318541485e9424ef1bba0f0bb0e0e91e2759dc53597436fb250a8605e5e0107": { + "source": { + "path": "aws-cdk-routev2-virtualprivategw-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "2318541485e9424ef1bba0f0bb0e0e91e2759dc53597436fb250a8605e5e0107.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.template.json new file mode 100644 index 0000000000000..f96743310fabe --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-virtualprivategw-alpha.template.json @@ -0,0 +1,157 @@ +{ + "Resources": { + "vpgw2AB64B6B": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "vpgwAmazonIpv6C872FF1E": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + } + }, + "vpgwSubnet5E7F36AD": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + }, + "DependsOn": [ + "vpgwAmazonIpv6C872FF1E" + ] + }, + "vpgwSubnetRouteTableAssociation49921F90": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "vpgwSubnet5E7F36AD" + } + }, + "DependsOn": [ + "vpgwAmazonIpv6C872FF1E" + ] + }, + "testVPGWIGW816C7C4F": { + "Type": "AWS::EC2::VPNGateway", + "Properties": { + "Type": "ipsec.1" + } + }, + "testVPGWRouteA169B1AA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "DestinationIpv6CidrBlock": "0.0.0.0/0", + "GatewayId": { + "Fn::GetAtt": [ + "testVPGWIGW816C7C4F", + "VPNGatewayId" + ] + }, + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "testVPGWRouteGWAttachment01E74575": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + }, + "VpnGatewayId": { + "Fn::GetAtt": [ + "testVPGWIGW816C7C4F", + "VPNGatewayId" + ] + } + } + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.assets.json new file mode 100644 index 0000000000000..fa96e660e9d19 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "7b04eb9c84a61a91a957fceb96a85b38336f8b5999d1c0b5b972cd191926c473": { + "source": { + "path": "aws-cdk-routev2-vpcpeerconnection-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "7b04eb9c84a61a91a957fceb96a85b38336f8b5999d1c0b5b972cd191926c473.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.template.json new file mode 100644 index 0000000000000..804f7b179ac91 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/aws-cdk-routev2-vpcpeerconnection-alpha.template.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "vpcpc6CAE1A04": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "vpcpcAmazonIpv66504EEB2": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + } + }, + "TestRoottableRouteTableFA28AA38": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + } + }, + "vpcpcSubnet1DD6CE35": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "CidrBlock": "10.0.0.0/24", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "Ipv6CidrBlocks" + ] + } + ] + }, + "VpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + }, + "DependsOn": [ + "vpcpcAmazonIpv66504EEB2" + ] + }, + "vpcpcSubnetRouteTableAssociation8531BF5C": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "vpcpcSubnet1DD6CE35" + } + }, + "DependsOn": [ + "vpcpcAmazonIpv66504EEB2" + ] + } + }, + "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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integ.json new file mode 100644 index 0000000000000..4ba304a14b0f1 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integtest-model-8/DefaultTest": { + "stacks": [ + "aws-cdk-routev2-dynamodbendpoint-alpha" + ], + "assertionStack": "integtest-model-8/DefaultTest/DeployAssert", + "assertionStackName": "integtestmodel8DefaultTestDeployAssert77221752" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.assets.json new file mode 100644 index 0000000000000..db0c4fcd06799 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel0DefaultTestDeployAssertA16689B0.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel0DefaultTestDeployAssertA16689B0.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.assets.json new file mode 100644 index 0000000000000..494dbc93fd34d --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel1DefaultTestDeployAssert46FEDE40.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel1DefaultTestDeployAssert46FEDE40.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.assets.json new file mode 100644 index 0000000000000..063e77bfac0d8 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel2DefaultTestDeployAssert04E3783E.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel2DefaultTestDeployAssert04E3783E.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.assets.json new file mode 100644 index 0000000000000..3b7039646f51f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel3DefaultTestDeployAssertF3FA2F74.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel3DefaultTestDeployAssertF3FA2F74.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.assets.json new file mode 100644 index 0000000000000..a760a50f08dc1 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel4DefaultTestDeployAssert4B12233C.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel4DefaultTestDeployAssert4B12233C.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.assets.json new file mode 100644 index 0000000000000..34f6c443f8be6 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel5DefaultTestDeployAssertC0DDB875.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel5DefaultTestDeployAssertC0DDB875.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.assets.json new file mode 100644 index 0000000000000..933d02b8072da --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel6DefaultTestDeployAssert90B004F4.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel6DefaultTestDeployAssert90B004F4.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.assets.json new file mode 100644 index 0000000000000..57cecd7995331 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel7DefaultTestDeployAssert4C509DCE.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel7DefaultTestDeployAssert4C509DCE.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.assets.json new file mode 100644 index 0000000000000..c9d2f2fc69193 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodel8DefaultTestDeployAssert77221752.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/integtestmodel8DefaultTestDeployAssert77221752.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/aws-ec2-alpha/test/integ.route-v2.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/manifest.json new file mode 100644 index 0000000000000..2dec0815f28b0 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/manifest.json @@ -0,0 +1,1265 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-routev2-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-alpha.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}/b3d06cef480a17aaf78379d18a13893141f2d689a23bcbbcf34b284e77752b0f.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-alpha.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" + }, + "stackName": "DefaultVpcDeploy" + }, + "dependencies": [ + "aws-cdk-routev2-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-alpha/default/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "defaultC974F9E3" + } + ], + "/aws-cdk-routev2-alpha/default/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "defaultAmazonIpv6C7A4D665" + } + ], + "/aws-cdk-routev2-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-alpha/defaultSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "defaultSubnetDFB3A3B6" + } + ], + "/aws-cdk-routev2-alpha/defaultSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "defaultSubnetRouteTableAssociationF1D85D29" + } + ], + "/aws-cdk-routev2-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-alpha" + }, + "aws-cdk-routev2-egressonlyigw-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-egressonlyigw-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-egressonlyigw-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-egressonlyigw-alpha.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}/6cd56bb964ed1f90f0206d705f085aef381173834b50d5ba372fa2185156d51d.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-egressonlyigw-alpha.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" + }, + "stackName": "EgressOnlyIgwVpc" + }, + "dependencies": [ + "aws-cdk-routev2-egressonlyigw-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-egressonlyigw-alpha/eigw/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "eigwC0F094EF" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/eigw/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "eigwAmazonIpv69E78211F" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "eigwSubnetCC28B9F9" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "eigwSubnetRouteTableAssociation887F4A97" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/testEOIGW/EIGW": [ + { + "type": "aws:cdk:logicalId", + "data": "testEOIGWEIGW54CCAD37" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/testEIGWRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testEIGWRouteEB4FE8D5" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-egressonlyigw-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-egressonlyigw-alpha" + }, + "aws-cdk-routev2-igw-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-igw-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-igw-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-igw-alpha.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}/44c69eec973961e184209d04e6e45c230320a2f7a110f0275431dc0587273038.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-igw-alpha.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" + }, + "stackName": "InternetGatewayVpc" + }, + "dependencies": [ + "aws-cdk-routev2-igw-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-igw-alpha/igw/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "igw127F1970" + } + ], + "/aws-cdk-routev2-igw-alpha/igw/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "igwAmazonIpv64026617C" + } + ], + "/aws-cdk-routev2-igw-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-igw-alpha/igwSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "igwSubnetF238E402" + } + ], + "/aws-cdk-routev2-igw-alpha/igwSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "igwSubnetRouteTableAssociationA48C27F3" + } + ], + "/aws-cdk-routev2-igw-alpha/testIGW/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "testIGW8D947AF2" + } + ], + "/aws-cdk-routev2-igw-alpha/testIGWRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testIGWRoute7696715B" + } + ], + "/aws-cdk-routev2-igw-alpha/testIGWRoute/GWAttachment": [ + { + "type": "aws:cdk:logicalId", + "data": "testIGWRouteGWAttachmentB0836D42" + } + ], + "/aws-cdk-routev2-igw-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-igw-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-igw-alpha" + }, + "aws-cdk-routev2-virtualprivategw-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-virtualprivategw-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-virtualprivategw-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-virtualprivategw-alpha.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}/2318541485e9424ef1bba0f0bb0e0e91e2759dc53597436fb250a8605e5e0107.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-virtualprivategw-alpha.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" + }, + "stackName": "VirtualPrivateGwVpc" + }, + "dependencies": [ + "aws-cdk-routev2-virtualprivategw-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-virtualprivategw-alpha/vpgw/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "vpgw2AB64B6B" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/vpgw/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "vpgwAmazonIpv6C872FF1E" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "vpgwSubnet5E7F36AD" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "vpgwSubnetRouteTableAssociation49921F90" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/testVPGW/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "testVPGWIGW816C7C4F" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/testVPGWRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testVPGWRouteA169B1AA" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/testVPGWRoute/GWAttachment": [ + { + "type": "aws:cdk:logicalId", + "data": "testVPGWRouteGWAttachment01E74575" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-virtualprivategw-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-virtualprivategw-alpha" + }, + "aws-cdk-routev2-publicnatgw-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-publicnatgw-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-publicnatgw-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-publicnatgw-alpha.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}/6592172436ea6af85dd73663ffd81cc1342c29574aa00f4dacf5179cf3054441.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-publicnatgw-alpha.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" + }, + "stackName": "NatGwPubVpc" + }, + "dependencies": [ + "aws-cdk-routev2-publicnatgw-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-publicnatgw-alpha/natgw_pub/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwpub2FB85986" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/natgw_pub/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwpubAmazonIpv625B947F8" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwpubSubnet79D316E5" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwpubSubnetRouteTableAssociation019CE26A" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testNATgwIGW/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATgwIGW6AC97E9A" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testnatgwigwRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testnatgwigwRouteE8D2BF39" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testnatgwigwRoute/GWAttachment": [ + { + "type": "aws:cdk:logicalId", + "data": "testnatgwigwRouteGWAttachmentB8E1033C" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testNATgw/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATgwEIP1C260FAD" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testNATgw/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATgwNATGateway1533420D" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/testNATGWRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATGWRoute7A26EC80" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-publicnatgw-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-publicnatgw-alpha" + }, + "aws-cdk-routev2-privatenatgw-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-privatenatgw-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-privatenatgw-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-privatenatgw-alpha.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}/89c945d2b4cb2aa79cca0e52ea8fa68849a586495b0a27b7de229ae44b3c5239.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-privatenatgw-alpha.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" + }, + "stackName": "NatGwPrivVpc" + }, + "dependencies": [ + "aws-cdk-routev2-privatenatgw-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-privatenatgw-alpha/natgw_priv/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwpriv081A7D93" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/natgw_priv/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwprivAmazonIpv6915E8E4F" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwprivSubnetE547C5A0" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "natgwprivSubnetRouteTableAssociation9E115869" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/testNATgw/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATgwNATGateway1533420D" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/testNATGWRoute/Route": [ + { + "type": "aws:cdk:logicalId", + "data": "testNATGWRoute7A26EC80" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-privatenatgw-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-privatenatgw-alpha" + }, + "aws-cdk-routev2-networkif-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-networkif-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-networkif-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-networkif-alpha.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}/087e3b456bae228983dc7a31eea1570bfeccfd6b4f163b7e10a2af07dc31291f.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-networkif-alpha.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" + }, + "stackName": "NetworkInterfaceVpc" + }, + "dependencies": [ + "aws-cdk-routev2-networkif-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-networkif-alpha/nif/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "nif44200315" + } + ], + "/aws-cdk-routev2-networkif-alpha/nif/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "nifAmazonIpv6CF4BF46B" + } + ], + "/aws-cdk-routev2-networkif-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-networkif-alpha/nifSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "nifSubnetAEB60456" + } + ], + "/aws-cdk-routev2-networkif-alpha/nifSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "nifSubnetRouteTableAssociationE4036B9F" + } + ], + "/aws-cdk-routev2-networkif-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-networkif-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-networkif-alpha" + }, + "aws-cdk-routev2-vpcpeerconnection-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-vpcpeerconnection-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-vpcpeerconnection-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-vpcpeerconnection-alpha.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}/7b04eb9c84a61a91a957fceb96a85b38336f8b5999d1c0b5b972cd191926c473.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-vpcpeerconnection-alpha.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" + }, + "stackName": "VpcPeerConnection" + }, + "dependencies": [ + "aws-cdk-routev2-vpcpeerconnection-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-vpcpeerconnection-alpha/vpcpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcpc6CAE1A04" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/vpcpc/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcpcAmazonIpv66504EEB2" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcpcSubnet1DD6CE35" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcpcSubnetRouteTableAssociation8531BF5C" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-vpcpeerconnection-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-routev2-vpcpeerconnection-alpha" + }, + "aws-cdk-routev2-dynamodbendpoint-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-routev2-dynamodbendpoint-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-routev2-dynamodbendpoint-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-routev2-dynamodbendpoint-alpha.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}/7711ae87a96bcf4e738e5904b6071f21ac59ee14247c420b0bf33d20a87348a3.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-routev2-dynamodbendpoint-alpha.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" + }, + "stackName": "DynamodbEndpointVpc" + }, + "dependencies": [ + "aws-cdk-routev2-dynamodbendpoint-alpha.assets" + ], + "metadata": { + "/aws-cdk-routev2-dynamodbendpoint-alpha/dynamodb/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "dynamodbC0A56799" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/dynamodb/AmazonIpv6": [ + { + "type": "aws:cdk:logicalId", + "data": "dynamodbAmazonIpv6698EF571" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/TestRoottable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TestRoottableRouteTableFA28AA38" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "dynamodbSubnet81957A26" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "dynamodbSubnetRouteTableAssociationC38B30F3" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/testDynamoEndpoint/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "testDynamoEndpoint03D5BDE5" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-routev2-dynamodbendpoint-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ], + "dynamodbSecondaryIp4EEF58BFBEFB": [ + { + "type": "aws:cdk:logicalId", + "data": "dynamodbSecondaryIp4EEF58BFBEFB", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ] + }, + "displayName": "aws-cdk-routev2-dynamodbendpoint-alpha" + }, + "integtestmodel0DefaultTestDeployAssertA16689B0.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel0DefaultTestDeployAssertA16689B0.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel0DefaultTestDeployAssertA16689B0": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel0DefaultTestDeployAssertA16689B0.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": [ + "integtestmodel0DefaultTestDeployAssertA16689B0.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": [ + "integtestmodel0DefaultTestDeployAssertA16689B0.assets" + ], + "metadata": { + "/integtest-model-0/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-0/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-0/DefaultTest/DeployAssert" + }, + "integtestmodel1DefaultTestDeployAssert46FEDE40.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel1DefaultTestDeployAssert46FEDE40.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel1DefaultTestDeployAssert46FEDE40": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel1DefaultTestDeployAssert46FEDE40.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": [ + "integtestmodel1DefaultTestDeployAssert46FEDE40.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": [ + "integtestmodel1DefaultTestDeployAssert46FEDE40.assets" + ], + "metadata": { + "/integtest-model-1/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-1/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-1/DefaultTest/DeployAssert" + }, + "integtestmodel2DefaultTestDeployAssert04E3783E.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel2DefaultTestDeployAssert04E3783E.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel2DefaultTestDeployAssert04E3783E": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel2DefaultTestDeployAssert04E3783E.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": [ + "integtestmodel2DefaultTestDeployAssert04E3783E.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": [ + "integtestmodel2DefaultTestDeployAssert04E3783E.assets" + ], + "metadata": { + "/integtest-model-2/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-2/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-2/DefaultTest/DeployAssert" + }, + "integtestmodel3DefaultTestDeployAssertF3FA2F74.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel3DefaultTestDeployAssertF3FA2F74.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel3DefaultTestDeployAssertF3FA2F74": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel3DefaultTestDeployAssertF3FA2F74.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": [ + "integtestmodel3DefaultTestDeployAssertF3FA2F74.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": [ + "integtestmodel3DefaultTestDeployAssertF3FA2F74.assets" + ], + "metadata": { + "/integtest-model-3/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-3/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-3/DefaultTest/DeployAssert" + }, + "integtestmodel4DefaultTestDeployAssert4B12233C.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel4DefaultTestDeployAssert4B12233C.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel4DefaultTestDeployAssert4B12233C": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel4DefaultTestDeployAssert4B12233C.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": [ + "integtestmodel4DefaultTestDeployAssert4B12233C.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": [ + "integtestmodel4DefaultTestDeployAssert4B12233C.assets" + ], + "metadata": { + "/integtest-model-4/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-4/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-4/DefaultTest/DeployAssert" + }, + "integtestmodel5DefaultTestDeployAssertC0DDB875.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel5DefaultTestDeployAssertC0DDB875.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel5DefaultTestDeployAssertC0DDB875": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel5DefaultTestDeployAssertC0DDB875.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": [ + "integtestmodel5DefaultTestDeployAssertC0DDB875.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": [ + "integtestmodel5DefaultTestDeployAssertC0DDB875.assets" + ], + "metadata": { + "/integtest-model-5/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-5/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-5/DefaultTest/DeployAssert" + }, + "integtestmodel6DefaultTestDeployAssert90B004F4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel6DefaultTestDeployAssert90B004F4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel6DefaultTestDeployAssert90B004F4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel6DefaultTestDeployAssert90B004F4.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": [ + "integtestmodel6DefaultTestDeployAssert90B004F4.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": [ + "integtestmodel6DefaultTestDeployAssert90B004F4.assets" + ], + "metadata": { + "/integtest-model-6/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-6/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-6/DefaultTest/DeployAssert" + }, + "integtestmodel7DefaultTestDeployAssert4C509DCE.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel7DefaultTestDeployAssert4C509DCE.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel7DefaultTestDeployAssert4C509DCE": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel7DefaultTestDeployAssert4C509DCE.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": [ + "integtestmodel7DefaultTestDeployAssert4C509DCE.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": [ + "integtestmodel7DefaultTestDeployAssert4C509DCE.assets" + ], + "metadata": { + "/integtest-model-7/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-7/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-7/DefaultTest/DeployAssert" + }, + "integtestmodel8DefaultTestDeployAssert77221752.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodel8DefaultTestDeployAssert77221752.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodel8DefaultTestDeployAssert77221752": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodel8DefaultTestDeployAssert77221752.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": [ + "integtestmodel8DefaultTestDeployAssert77221752.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": [ + "integtestmodel8DefaultTestDeployAssert77221752.assets" + ], + "metadata": { + "/integtest-model-8/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model-8/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model-8/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/tree.json new file mode 100644 index 0000000000000..7adf7f1621505 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.js.snapshot/tree.json @@ -0,0 +1,2607 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-routev2-alpha": { + "id": "aws-cdk-routev2-alpha", + "path": "aws-cdk-routev2-alpha", + "children": { + "default": { + "id": "default", + "path": "aws-cdk-routev2-alpha/default", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-alpha/default/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-alpha/default/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "defaultSubnet": { + "id": "defaultSubnet", + "path": "aws-cdk-routev2-alpha/defaultSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-alpha/defaultSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "defaultC974F9E3", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "defaultC974F9E3", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-alpha/defaultSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-alpha/defaultSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "defaultSubnetDFB3A3B6" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-egressonlyigw-alpha": { + "id": "aws-cdk-routev2-egressonlyigw-alpha", + "path": "aws-cdk-routev2-egressonlyigw-alpha", + "children": { + "eigw": { + "id": "eigw", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigw", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigw/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigw/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-egressonlyigw-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-egressonlyigw-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "eigwSubnet": { + "id": "eigwSubnet", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "vpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-egressonlyigw-alpha/eigwSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "eigwSubnetCC28B9F9" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testEOIGW": { + "id": "testEOIGW", + "path": "aws-cdk-routev2-egressonlyigw-alpha/testEOIGW", + "children": { + "EIGW": { + "id": "EIGW", + "path": "aws-cdk-routev2-egressonlyigw-alpha/testEOIGW/EIGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EgressOnlyInternetGateway", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "eigwC0F094EF", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEgressOnlyInternetGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.EgressOnlyInternetGateway", + "version": "0.0.0" + } + }, + "testEIGWRoute": { + "id": "testEIGWRoute", + "path": "aws-cdk-routev2-egressonlyigw-alpha/testEIGWRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-egressonlyigw-alpha/testEIGWRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "destinationIpv6CidrBlock": "0.0.0.0/0", + "egressOnlyInternetGatewayId": { + "Fn::GetAtt": [ + "testEOIGWEIGW54CCAD37", + "Id" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-egressonlyigw-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-egressonlyigw-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-igw-alpha": { + "id": "aws-cdk-routev2-igw-alpha", + "path": "aws-cdk-routev2-igw-alpha", + "children": { + "igw": { + "id": "igw", + "path": "aws-cdk-routev2-igw-alpha/igw", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-igw-alpha/igw/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-igw-alpha/igw/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-igw-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-igw-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "igwSubnet": { + "id": "igwSubnet", + "path": "aws-cdk-routev2-igw-alpha/igwSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-igw-alpha/igwSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "igw127F1970", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-igw-alpha/igwSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-igw-alpha/igwSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "igwSubnetF238E402" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testIGW": { + "id": "testIGW", + "path": "aws-cdk-routev2-igw-alpha/testIGW", + "children": { + "IGW": { + "id": "IGW", + "path": "aws-cdk-routev2-igw-alpha/testIGW/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.InternetGateway", + "version": "0.0.0" + } + }, + "testIGWRoute": { + "id": "testIGWRoute", + "path": "aws-cdk-routev2-igw-alpha/testIGWRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-igw-alpha/testIGWRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "destinationIpv6CidrBlock": "0.0.0.0/0", + "gatewayId": { + "Fn::GetAtt": [ + "testIGW8D947AF2", + "InternetGatewayId" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "GWAttachment": { + "id": "GWAttachment", + "path": "aws-cdk-routev2-igw-alpha/testIGWRoute/GWAttachment", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Fn::GetAtt": [ + "testIGW8D947AF2", + "InternetGatewayId" + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "igw127F1970", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-igw-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-igw-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-virtualprivategw-alpha": { + "id": "aws-cdk-routev2-virtualprivategw-alpha", + "path": "aws-cdk-routev2-virtualprivategw-alpha", + "children": { + "vpgw": { + "id": "vpgw", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgw", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgw/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgw/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-virtualprivategw-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-virtualprivategw-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "vpgwSubnet": { + "id": "vpgwSubnet", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-virtualprivategw-alpha/vpgwSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "vpgwSubnet5E7F36AD" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testVPGW": { + "id": "testVPGW", + "path": "aws-cdk-routev2-virtualprivategw-alpha/testVPGW", + "children": { + "IGW": { + "id": "IGW", + "path": "aws-cdk-routev2-virtualprivategw-alpha/testVPGW/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPNGateway", + "aws:cdk:cloudformation:props": { + "type": "ipsec.1" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPNGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VPNGateway", + "version": "0.0.0" + } + }, + "testVPGWRoute": { + "id": "testVPGWRoute", + "path": "aws-cdk-routev2-virtualprivategw-alpha/testVPGWRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-virtualprivategw-alpha/testVPGWRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "destinationIpv6CidrBlock": "0.0.0.0/0", + "gatewayId": { + "Fn::GetAtt": [ + "testVPGWIGW816C7C4F", + "VPNGatewayId" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "GWAttachment": { + "id": "GWAttachment", + "path": "aws-cdk-routev2-virtualprivategw-alpha/testVPGWRoute/GWAttachment", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "vpgw2AB64B6B", + "VpcId" + ] + }, + "vpnGatewayId": { + "Fn::GetAtt": [ + "testVPGWIGW816C7C4F", + "VPNGatewayId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-virtualprivategw-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-virtualprivategw-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-publicnatgw-alpha": { + "id": "aws-cdk-routev2-publicnatgw-alpha", + "path": "aws-cdk-routev2-publicnatgw-alpha", + "children": { + "natgw_pub": { + "id": "natgw_pub", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pub", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pub/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pub/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-publicnatgw-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-publicnatgw-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "natgw_pubSubnet": { + "id": "natgw_pubSubnet", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-publicnatgw-alpha/natgw_pubSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "natgwpubSubnet79D316E5" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testNATgwIGW": { + "id": "testNATgwIGW", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATgwIGW", + "children": { + "IGW": { + "id": "IGW", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATgwIGW/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.InternetGateway", + "version": "0.0.0" + } + }, + "testnatgwigwRoute": { + "id": "testnatgwigwRoute", + "path": "aws-cdk-routev2-publicnatgw-alpha/testnatgwigwRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-publicnatgw-alpha/testnatgwigwRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "242.0.0.0/32", + "destinationIpv6CidrBlock": "242.0.0.0/32", + "gatewayId": { + "Fn::GetAtt": [ + "testNATgwIGW6AC97E9A", + "InternetGatewayId" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "GWAttachment": { + "id": "GWAttachment", + "path": "aws-cdk-routev2-publicnatgw-alpha/testnatgwigwRoute/GWAttachment", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Fn::GetAtt": [ + "testNATgwIGW6AC97E9A", + "InternetGatewayId" + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "testNATgw": { + "id": "testNATgw", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATgw", + "children": { + "EIP": { + "id": "EIP", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATgw/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": { + "Fn::GetAtt": [ + "natgwpub2FB85986", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATgw/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "testNATgwEIP1C260FAD", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "natgwpubSubnet79D316E5" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.NatGateway", + "version": "0.0.0" + } + }, + "testNATGWRoute": { + "id": "testNATGWRoute", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATGWRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-publicnatgw-alpha/testNATGWRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "destinationIpv6CidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Fn::GetAtt": [ + "testNATgwNATGateway1533420D", + "NatGatewayId" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-publicnatgw-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-publicnatgw-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-privatenatgw-alpha": { + "id": "aws-cdk-routev2-privatenatgw-alpha", + "path": "aws-cdk-routev2-privatenatgw-alpha", + "children": { + "natgw_priv": { + "id": "natgw_priv", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_priv", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_priv/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_priv/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-privatenatgw-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-privatenatgw-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "natgw_privSubnet": { + "id": "natgw_privSubnet", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "natgwpriv081A7D93", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-privatenatgw-alpha/natgw_privSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "natgwprivSubnetE547C5A0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testNATgw": { + "id": "testNATgw", + "path": "aws-cdk-routev2-privatenatgw-alpha/testNATgw", + "children": { + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-routev2-privatenatgw-alpha/testNATgw/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "connectivityType": "private", + "privateIpAddress": "10.0.0.42", + "secondaryPrivateIpAddresses": [ + "10.0.0.43", + "10.0.0.44", + "10.0.0.45" + ], + "subnetId": { + "Ref": "natgwprivSubnetE547C5A0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.NatGateway", + "version": "0.0.0" + } + }, + "testNATGWRoute": { + "id": "testNATGWRoute", + "path": "aws-cdk-routev2-privatenatgw-alpha/testNATGWRoute", + "children": { + "Route": { + "id": "Route", + "path": "aws-cdk-routev2-privatenatgw-alpha/testNATGWRoute/Route", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "destinationIpv6CidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Fn::GetAtt": [ + "testNATgwNATGateway1533420D", + "NatGatewayId" + ] + }, + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-privatenatgw-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-privatenatgw-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-networkif-alpha": { + "id": "aws-cdk-routev2-networkif-alpha", + "path": "aws-cdk-routev2-networkif-alpha", + "children": { + "nif": { + "id": "nif", + "path": "aws-cdk-routev2-networkif-alpha/nif", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-networkif-alpha/nif/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-networkif-alpha/nif/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-networkif-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-networkif-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "nifSubnet": { + "id": "nifSubnet", + "path": "aws-cdk-routev2-networkif-alpha/nifSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-networkif-alpha/nifSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "nif44200315", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "nif44200315", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-networkif-alpha/nifSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-networkif-alpha/nifSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "nifSubnetAEB60456" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-networkif-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-networkif-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-vpcpeerconnection-alpha": { + "id": "aws-cdk-routev2-vpcpeerconnection-alpha", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha", + "children": { + "vpcpc": { + "id": "vpcpc", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpc", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpc/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpc/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "vpcpcSubnet": { + "id": "vpcpcSubnet", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "vpcpc6CAE1A04", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/vpcpcSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "vpcpcSubnet1DD6CE35" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-vpcpeerconnection-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-routev2-dynamodbendpoint-alpha": { + "id": "aws-cdk-routev2-dynamodbendpoint-alpha", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha", + "children": { + "dynamodb": { + "id": "dynamodb", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodb", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodb/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "AmazonIpv6": { + "id": "AmazonIpv6", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodb/AmazonIpv6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "TestRoottable": { + "id": "TestRoottable", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/TestRoottable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/TestRoottable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "dynamodbSubnet": { + "id": "dynamodbSubnet", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-1a", + "cidrBlock": "10.0.0.0/24", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "Ipv6CidrBlocks" + ] + } + ] + }, + "vpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/dynamodbSubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "dynamodbSubnet81957A26" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testDynamoEndpoint": { + "id": "testDynamoEndpoint", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/testDynamoEndpoint", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/testDynamoEndpoint/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCEndpoint", + "aws:cdk:cloudformation:props": { + "routeTableIds": [ + { + "Fn::GetAtt": [ + "TestRoottableRouteTableFA28AA38", + "RouteTableId" + ] + } + ], + "serviceName": { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".dynamodb" + ] + ] + }, + "vpcEndpointType": "Gateway", + "vpcId": { + "Fn::GetAtt": [ + "dynamodbC0A56799", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCEndpoint", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.GatewayVpcEndpoint", + "version": "0.0.0" + } + }, + "testDynamoRoute": { + "id": "testDynamoRoute", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/testDynamoRoute", + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Route", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-routev2-dynamodbendpoint-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integtest-model-0": { + "id": "integtest-model-0", + "path": "integtest-model-0", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-0/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-0/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-0/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-0/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-0/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" + } + }, + "integtest-model-1": { + "id": "integtest-model-1", + "path": "integtest-model-1", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-1/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-1/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-1/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-1/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-1/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" + } + }, + "integtest-model-2": { + "id": "integtest-model-2", + "path": "integtest-model-2", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-2/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-2/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-2/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-2/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-2/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" + } + }, + "integtest-model-3": { + "id": "integtest-model-3", + "path": "integtest-model-3", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-3/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-3/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-3/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-3/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-3/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" + } + }, + "integtest-model-4": { + "id": "integtest-model-4", + "path": "integtest-model-4", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-4/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-4/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-4/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-4/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-4/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" + } + }, + "integtest-model-5": { + "id": "integtest-model-5", + "path": "integtest-model-5", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-5/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-5/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-5/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-5/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-5/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" + } + }, + "integtest-model-6": { + "id": "integtest-model-6", + "path": "integtest-model-6", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-6/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-6/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-6/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-6/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-6/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" + } + }, + "integtest-model-7": { + "id": "integtest-model-7", + "path": "integtest-model-7", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-7/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-7/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-7/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-7/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-7/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" + } + }, + "integtest-model-8": { + "id": "integtest-model-8", + "path": "integtest-model-8", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model-8/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model-8/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model-8/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model-8/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model-8/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/aws-ec2-alpha/test/integ.route-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.ts new file mode 100644 index 0000000000000..579800e7dfcb3 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.route-v2.ts @@ -0,0 +1,160 @@ +// /* +// * Our integration tests act as snapshot tests to make sure the rendered template is stable. +// * If any changes to the result are required, +// * you need to perform an actual CloudFormation deployment of this application, +// * and, if it is successful, a new snapshot will be written out. +// * +// * For more information on CDK integ tests, +// * see the main CONTRIBUTING.md file. +// */ + +import * as vpc_v2 from '../lib/vpc-v2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { IpCidr, SubnetV2 } from '../lib/subnet-v2'; +// import { CarrierGateway, TransitGateway } from '../lib/route'; +import { EgressOnlyInternetGateway, InternetGateway, NatConnectivityType, NatGateway, Route, RouteTable, VPNGateway } from '../lib/route'; +import { GatewayVpcEndpoint, GatewayVpcEndpointAwsService, SubnetType, VpnConnectionType } from 'aws-cdk-lib/aws-ec2'; +import { Fn } from 'aws-cdk-lib'; +//import { log } from 'console'; + +// as in unit tests, we use a qualified import, +// not bring in individual classes +//import * as er from '../lib'; + +const app = new cdk.App(); + +const stacks: {[id: string] : cdk.Stack} = { + default: new cdk.Stack(app, 'aws-cdk-routev2-alpha', { stackName: 'DefaultVpcDeploy' }), + // 'cgw': new cdk.Stack(app, 'aws-cdk-routev2-carriergw-alpha', {stackName: 'CarrierGatewayVpc'}), + eigw: new cdk.Stack(app, 'aws-cdk-routev2-egressonlyigw-alpha', { stackName: 'EgressOnlyIgwVpc' }), + igw: new cdk.Stack(app, 'aws-cdk-routev2-igw-alpha', { stackName: 'InternetGatewayVpc' }), + vpgw: new cdk.Stack(app, 'aws-cdk-routev2-virtualprivategw-alpha', { stackName: 'VirtualPrivateGwVpc' }), + natgw_pub: new cdk.Stack(app, 'aws-cdk-routev2-publicnatgw-alpha', { stackName: 'NatGwPubVpc' }), + natgw_priv: new cdk.Stack(app, 'aws-cdk-routev2-privatenatgw-alpha', { stackName: 'NatGwPrivVpc' }), + nif: new cdk.Stack(app, 'aws-cdk-routev2-networkif-alpha', { stackName: 'NetworkInterfaceVpc' }), + // 'tgw': new cdk.Stack(app, 'aws-cdk-routev2-transitgw-alpha', {stackName: 'TransitGwVpc'}), + vpcpc: new cdk.Stack(app, 'aws-cdk-routev2-vpcpeerconnection-alpha', { stackName: 'VpcPeerConnection' }), + dynamodb: new cdk.Stack(app, 'aws-cdk-routev2-dynamodbendpoint-alpha', { stackName: 'DynamodbEndpointVpc' }), +}; + +var vpcs: {[id: string] : vpc_v2.VpcV2} = {}; +var subnets: {[id: string]: SubnetV2} = {}; +var routeTables: {[id: string]: RouteTable} = {}; + +for (const stackName in stacks) { + const vpc = new vpc_v2.VpcV2(stacks[stackName], stackName, { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6({ + cidrBlockName: 'AmazonIpv6', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }); + vpcs[stackName] = vpc; + const routeTable = new RouteTable(stacks[stackName], 'TestRoottable', { + vpc: vpcs[stackName], + }); + routeTables[stackName] = routeTable; + if (stackName == 'eigw') { + const subnet = new SubnetV2(stacks[stackName], stackName + 'Subnet', { + vpc: vpc, + availabilityZone: 'us-west-1a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + routeTable: routeTables[stackName], + }); + subnets[stackName] = subnet; + } else { + // use empty ipv6 that doesn't overlap + const subnet = new SubnetV2(stacks[stackName], stackName + 'Subnet', { + vpc: vpc, + availabilityZone: 'us-west-1a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + ipv6CidrBlock: new IpCidr(Fn.select(0, vpc.ipv6CidrBlocks)), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + routeTable: routeTables[stackName], + }); + subnets[stackName] = subnet; + } +} + +const eigw = new EgressOnlyInternetGateway(stacks.eigw, 'testEOIGW', { + vpc: vpcs.eigw, +}); +new Route(stacks.eigw, 'testEIGWRoute', { + routeTable: routeTables.eigw, + destination: '0.0.0.0/0', + target: { gateway: eigw }, +}); + +const igw = new InternetGateway(stacks.igw, 'testIGW', { + vpc: vpcs.igw, +}); +new Route(stacks.igw, 'testIGWRoute', { + routeTable: routeTables.igw, + destination: '0.0.0.0/0', + target: { gateway: igw }, +}); + +const vpgw = new VPNGateway(stacks.vpgw, 'testVPGW', { + type: VpnConnectionType.IPSEC_1, + vpc: vpcs.vpgw, +}); +new Route(stacks.vpgw, 'testVPGWRoute', { + routeTable: routeTables.vpgw, + destination: '0.0.0.0/0', + target: { gateway: vpgw }, +}); + +const natGwIgw = new InternetGateway(stacks.natgw_pub, 'testNATgwIGW', { + vpc: vpcs.natgw_pub, +}); +new Route(stacks.natgw_pub, 'testnatgwigwRoute', { + routeTable: routeTables.natgw_pub, + destination: '242.0.0.0/32', + target: { gateway: natGwIgw }, +}); +const natGwPub = new NatGateway(stacks.natgw_pub, 'testNATgw', { + subnet: subnets.natgw_pub, + vpc: vpcs.natgw_pub, +}); +new Route(stacks.natgw_pub, 'testNATGWRoute', { + routeTable: routeTables.natgw_pub, + destination: '0.0.0.0/0', + target: { gateway: natGwPub }, +}); + +const natGwPriv = new NatGateway(stacks.natgw_priv, 'testNATgw', { + subnet: subnets.natgw_priv, + vpc: vpcs.natgw_priv, + connectivityType: NatConnectivityType.PRIVATE, + privateIpAddress: '10.0.0.42', + secondaryPrivateIpAddresses: [ + '10.0.0.43', '10.0.0.44', '10.0.0.45', + ], +}); +new Route(stacks.natgw_priv, 'testNATGWRoute', { + routeTable: routeTables.natgw_priv, + destination: '0.0.0.0/0', + target: { gateway: natGwPriv }, +}); + +const dynamoEndpoint = new GatewayVpcEndpoint(stacks.dynamodb, 'testDynamoEndpoint', { + service: GatewayVpcEndpointAwsService.DYNAMODB, + vpc: vpcs.dynamodb, + subnets: [subnets.dynamodb], +}); +new Route(stacks.dynamodb, 'testDynamoRoute', { + routeTable: routeTables.dynamodb, + destination: '0.0.0.0/0', + target: { endpoint: dynamoEndpoint }, +}); + +var i = 0; +for (const stackName in stacks) { + new IntegTest(app, 'integtest-model-' + i, { + testCases: [stacks[stackName]], + }); + i++; +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.assets.json new file mode 100644 index 0000000000000..21b01be95b3c6 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "ccdbd85132bedf38aeb99e5b0c700f48494d3b7c344a96232f29b48a5279b6ef": { + "source": { + "path": "aws-cdk-vpcv2-alpha-new.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "ccdbd85132bedf38aeb99e5b0c700f48494d3b7c344a96232f29b48a5279b6ef.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/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.template.json new file mode 100644 index 0000000000000..575219310d27f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/aws-cdk-vpcv2-alpha-new.template.json @@ -0,0 +1,279 @@ +{ + "Resources": { + "Ipam50346F82": { + "Type": "AWS::EC2::IPAM", + "Properties": { + "OperatingRegions": [ + { + "RegionName": "eu-west-2" + } + ] + } + }, + "IpamPublicPool050D6AA6C": { + "Type": "AWS::EC2::IPAMPool", + "Properties": { + "AddressFamily": "ipv6", + "AwsService": "ec2", + "IpamScopeId": "DefaultPublicScope", + "Locale": "eu-west-2", + "PublicIpSource": "amazon" + } + }, + "IpamPublicPool0PublicPool0CidrAC7F711E": { + "Type": "AWS::EC2::IPAMPoolCidr", + "Properties": { + "IpamPoolId": { + "Fn::GetAtt": [ + "IpamPublicPool050D6AA6C", + "IpamPoolId" + ] + }, + "NetmaskLength": 52 + } + }, + "VPCTestFB735C86": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "VPCTestIpv6IpamCidrD5C271DD": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "Ipv6IpamPoolId": { + "Fn::GetAtt": [ + "IpamPublicPool050D6AA6C", + "IpamPoolId" + ] + }, + "Ipv6NetmaskLength": 56, + "VpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + }, + "DependsOn": [ + "IpamPublicPool0PublicPool0CidrAC7F711E" + ] + }, + "VPCTestVpnGateway51EEED38": { + "Type": "AWS::EC2::VPNGateway", + "Properties": { + "Type": "ipsec.1" + } + }, + "VPCTestVPCVPNGW0A869280": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + }, + "VpnGatewayId": { + "Ref": "VPCTestVpnGateway51EEED38" + } + } + }, + "VPCTestRoutePropagationFEA3011A": { + "Type": "AWS::EC2::VPNGatewayRoutePropagation", + "Properties": { + "RouteTableIds": [ + { + "Ref": "testsbubnetRouteTableF40F025B" + } + ], + "VpnGatewayId": { + "Ref": "VPCTestVpnGateway51EEED38" + } + }, + "DependsOn": [ + "VPCTestVPCVPNGW0A869280" + ] + }, + "testsbubnetSubnet77337845": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-2a", + "CidrBlock": "10.0.0.0/24", + "VpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCTestIpv6IpamCidrD5C271DD" + ] + }, + "testsbubnetRouteTableF40F025B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCTestIpv6IpamCidrD5C271DD" + ] + }, + "testsbubnetRouteTableAssociationD6D083FA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "testsbubnetRouteTableF40F025B" + }, + "SubnetId": { + "Ref": "testsbubnetSubnet77337845" + } + }, + "DependsOn": [ + "VPCTestIpv6IpamCidrD5C271DD" + ] + }, + "InstanceInstanceSecurityGroupF0E2D5BE": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-vpcv2-alpha-new/Instance/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpcv2-alpha-new/Instance" + } + ], + "VpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + } + }, + "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": "aws-cdk-vpcv2-alpha-new/Instance" + } + ] + } + }, + "InstanceInstanceProfileAB5AEF02": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "InstanceC1063A87": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": "eu-west-2a", + "IamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.micro", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "InstanceInstanceSecurityGroupF0E2D5BE", + "GroupId" + ] + } + ], + "SubnetId": { + "Ref": "testsbubnetSubnet77337845" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpcv2-alpha-new/Instance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "DependsOn": [ + "InstanceInstanceRoleE9785DE5" + ] + } + }, + "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/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integ.json new file mode 100644 index 0000000000000..321da99978a8c --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integtest-model/DefaultTest": { + "stacks": [ + "aws-cdk-vpcv2-alpha-new" + ], + "assertionStack": "integtest-model/DefaultTest/DeployAssert", + "assertionStackName": "integtestmodelDefaultTestDeployAssertCF40BD53" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json new file mode 100644 index 0000000000000..3dba4ef9b8bab --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/manifest.json new file mode 100644 index 0000000000000..5979efcf9a0da --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/manifest.json @@ -0,0 +1,212 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-vpcv2-alpha-new.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-vpcv2-alpha-new.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-vpcv2-alpha-new": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-vpcv2-alpha-new.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}/ccdbd85132bedf38aeb99e5b0c700f48494d3b7c344a96232f29b48a5279b6ef.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-vpcv2-alpha-new.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-vpcv2-alpha-new.assets" + ], + "metadata": { + "/aws-cdk-vpcv2-alpha-new/Ipam/Ipam": [ + { + "type": "aws:cdk:logicalId", + "data": "Ipam50346F82" + } + ], + "/aws-cdk-vpcv2-alpha-new/Ipam/PublicPool0/PublicPool0": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamPublicPool050D6AA6C" + } + ], + "/aws-cdk-vpcv2-alpha-new/Ipam/PublicPool0/PublicPool0Cidr": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamPublicPool0PublicPool0CidrAC7F711E" + } + ], + "/aws-cdk-vpcv2-alpha-new/VPCTest/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestFB735C86" + } + ], + "/aws-cdk-vpcv2-alpha-new/VPCTest/Ipv6IpamCidr": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestIpv6IpamCidrD5C271DD" + } + ], + "/aws-cdk-vpcv2-alpha-new/VPCTest/VpnGateway/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestVpnGateway51EEED38" + } + ], + "/aws-cdk-vpcv2-alpha-new/VPCTest/VPCVPNGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestVPCVPNGW0A869280" + } + ], + "/aws-cdk-vpcv2-alpha-new/VPCTest/RoutePropagation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestRoutePropagationFEA3011A" + } + ], + "/aws-cdk-vpcv2-alpha-new/testsbubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetSubnet77337845" + } + ], + "/aws-cdk-vpcv2-alpha-new/testsbubnet/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetRouteTableF40F025B" + } + ], + "/aws-cdk-vpcv2-alpha-new/testsbubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetRouteTableAssociationD6D083FA" + } + ], + "/aws-cdk-vpcv2-alpha-new/Instance/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceSecurityGroupF0E2D5BE" + } + ], + "/aws-cdk-vpcv2-alpha-new/Instance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceRoleE9785DE5" + } + ], + "/aws-cdk-vpcv2-alpha-new/Instance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceProfileAB5AEF02" + } + ], + "/aws-cdk-vpcv2-alpha-new/Instance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceC1063A87" + } + ], + "/aws-cdk-vpcv2-alpha-new/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-vpcv2-alpha-new/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-vpcv2-alpha-new/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ], + "VPCTestSecondaryIp48408C993194": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCTestSecondaryIp48408C993194", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ] + }, + "displayName": "aws-cdk-vpcv2-alpha-new" + }, + "integtestmodelDefaultTestDeployAssertCF40BD53.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodelDefaultTestDeployAssertCF40BD53.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodelDefaultTestDeployAssertCF40BD53": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.assets" + ], + "metadata": { + "/integtest-model/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/tree.json new file mode 100644 index 0000000000000..c1ff499051b89 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.js.snapshot/tree.json @@ -0,0 +1,552 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-vpcv2-alpha-new": { + "id": "aws-cdk-vpcv2-alpha-new", + "path": "aws-cdk-vpcv2-alpha-new", + "children": { + "Ipam": { + "id": "Ipam", + "path": "aws-cdk-vpcv2-alpha-new/Ipam", + "children": { + "Ipam": { + "id": "Ipam", + "path": "aws-cdk-vpcv2-alpha-new/Ipam/Ipam", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAM", + "aws:cdk:cloudformation:props": { + "operatingRegions": [ + { + "regionName": "eu-west-2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAM", + "version": "0.0.0" + } + }, + "PublicPool0": { + "id": "PublicPool0", + "path": "aws-cdk-vpcv2-alpha-new/Ipam/PublicPool0", + "children": { + "PublicPool0": { + "id": "PublicPool0", + "path": "aws-cdk-vpcv2-alpha-new/Ipam/PublicPool0/PublicPool0", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAMPool", + "aws:cdk:cloudformation:props": { + "addressFamily": "ipv6", + "awsService": "ec2", + "ipamScopeId": "DefaultPublicScope", + "locale": "eu-west-2", + "publicIpSource": "amazon" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAMPool", + "version": "0.0.0" + } + }, + "PublicPool0Cidr": { + "id": "PublicPool0Cidr", + "path": "aws-cdk-vpcv2-alpha-new/Ipam/PublicPool0/PublicPool0Cidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAMPoolCidr", + "aws:cdk:cloudformation:props": { + "ipamPoolId": { + "Fn::GetAtt": [ + "IpamPublicPool050D6AA6C", + "IpamPoolId" + ] + }, + "netmaskLength": 52 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAMPoolCidr", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Ipam", + "version": "0.0.0" + } + }, + "VPCTest": { + "id": "VPCTest", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "Ipv6IpamCidr": { + "id": "Ipv6IpamCidr", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/Ipv6IpamCidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "ipv6IpamPoolId": { + "Fn::GetAtt": [ + "IpamPublicPool050D6AA6C", + "IpamPoolId" + ] + }, + "ipv6NetmaskLength": 56, + "vpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + }, + "VpnGateway": { + "id": "VpnGateway", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/VpnGateway", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/VpnGateway/Default", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPNGateway", + "aws:cdk:cloudformation:props": { + "type": "ipsec.1" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPNGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.VpnGateway", + "version": "0.0.0" + } + }, + "VPCVPNGW": { + "id": "VPCVPNGW", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/VPCVPNGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + }, + "vpnGatewayId": { + "Ref": "VPCTestVpnGateway51EEED38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "RoutePropagation": { + "id": "RoutePropagation", + "path": "aws-cdk-vpcv2-alpha-new/VPCTest/RoutePropagation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPNGatewayRoutePropagation", + "aws:cdk:cloudformation:props": { + "routeTableIds": [ + { + "Ref": "testsbubnetRouteTableF40F025B" + } + ], + "vpnGatewayId": { + "Ref": "VPCTestVpnGateway51EEED38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPNGatewayRoutePropagation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "testsbubnet": { + "id": "testsbubnet", + "path": "aws-cdk-vpcv2-alpha-new/testsbubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpcv2-alpha-new/testsbubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "eu-west-2a", + "cidrBlock": "10.0.0.0/24", + "vpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpcv2-alpha-new/testsbubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpcv2-alpha-new/testsbubnet/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpcv2-alpha-new/testsbubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "testsbubnetRouteTableF40F025B" + }, + "subnetId": { + "Ref": "testsbubnetSubnet77337845" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "Instance": { + "id": "Instance", + "path": "aws-cdk-vpcv2-alpha-new/Instance", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "aws-cdk-vpcv2-alpha-new/Instance/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpcv2-alpha-new/Instance/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-cdk-vpcv2-alpha-new/Instance/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpcv2-alpha-new/Instance" + } + ], + "vpcId": { + "Fn::GetAtt": [ + "VPCTestFB735C86", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "aws-cdk-vpcv2-alpha-new/Instance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-vpcv2-alpha-new/Instance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpcv2-alpha-new/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": "aws-cdk-vpcv2-alpha-new/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": "aws-cdk-vpcv2-alpha-new/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": "aws-cdk-vpcv2-alpha-new/Instance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": "eu-west-2a", + "iamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.micro", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "InstanceInstanceSecurityGroupF0E2D5BE", + "GroupId" + ] + } + ], + "subnetId": { + "Ref": "testsbubnetSubnet77337845" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpcv2-alpha-new/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--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-vpcv2-alpha-new/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-vpcv2-alpha-new/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" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-vpcv2-alpha-new/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-vpcv2-alpha-new/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integtest-model": { + "id": "integtest-model", + "path": "integtest-model", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model/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/aws-ec2-alpha/test/integ.subnet-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.ts new file mode 100644 index 0000000000000..d30e47b2d9129 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.subnet-v2.ts @@ -0,0 +1,80 @@ +/* + * Our integration tests act as snapshot tests to make sure the rendered template is stable. + * If any changes to the result are required, + * you need to perform an actual CloudFormation deployment of this application, + * and, if it is successful, a new snapshot will be written out. + * + * For more information on CDK integ tests, + * see the main CONTRIBUTING.md file. + */ + +import * as vpc_v2 from '../lib/vpc-v2'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { AddressFamily, AwsServiceName, IpCidr, Ipam, IpamPoolPublicIpSource, SubnetV2 } from '../lib'; +//import { Ipv6Cidr } from '../lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-vpcv2-alpha-new'); + +const ipam = new Ipam(stack, 'Ipam', { + operatingRegion: ['eu-west-2'], //set to the region stack is being deployed to +}); + +/** + * Integ test for VPC with IPAM pool to be run with --no-clean + */ +const pool2 = ipam.publicScope.addPool('PublicPool0', { + addressFamily: AddressFamily.IP_V6, + awsService: AwsServiceName.EC2, + locale: 'eu-west-2', //set to the region stack is being deployed to + publicIpSource: IpamPoolPublicIpSource.AMAZON, +}); + +pool2.provisionCidr('PublicPool0Cidr', { netmaskLength: 52 } ); + +const vpc = new vpc_v2.VpcV2(stack, 'VPCTest', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.ipv6Ipam({ + ipamPool: pool2, + netmaskLength: 56, + cidrBlockName: 'Ipv6IpamCidr', + })], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +/** + * Since source for IPAM IPv6 is set to amazonProvided, + * can assign IPv6 address only after the allocation + * uncomment ipv6CidrBlock and provide valid IPv6 range + */ +new SubnetV2(stack, 'testsbubnet', { + vpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + //defined on the basis of allocation done in IPAM console + //ipv6CidrBlock: new Ipv6Cidr('2a05:d02c:25:4000::/60'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +vpc.enableVpnGateway({ + vpnRoutePropagation: [{ + subnetType: SubnetType.PRIVATE_ISOLATED, // optional, defaults to "PUBLIC" + }], + type: 'ipsec.1', +}); + +new ec2.Instance(stack, 'Instance', { + vpc, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO), + machineImage: new ec2.AmazonLinuxImage(), +}); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.assets.json new file mode 100644 index 0000000000000..073423dd71829 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "6af0c32b7b4dcf4566eda1afa97ddb6dc00a4597f5633e0d826df8642bc069f4": { + "source": { + "path": "aws-cdk-vpcv2-alpha.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6af0c32b7b4dcf4566eda1afa97ddb6dc00a4597f5633e0d826df8642bc069f4.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/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.template.json new file mode 100644 index 0000000000000..e1962661d5118 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/aws-cdk-vpcv2-alpha.template.json @@ -0,0 +1,329 @@ +{ + "Resources": { + "IpamTestIpam6C9298EF": { + "Type": "AWS::EC2::IPAM", + "Properties": { + "OperatingRegions": [ + { + "RegionName": "eu-central-1" + } + ] + } + }, + "IpamTestPrivatePool039C763DC": { + "Type": "AWS::EC2::IPAMPool", + "Properties": { + "AddressFamily": "ipv4", + "IpamScopeId": "DefaultPrivateScope", + "Locale": "eu-central-1", + "ProvisionedCidrs": [ + { + "Cidr": "10.2.0.0/16" + } + ] + } + }, + "IpamTestPublicPool0C44B7C49": { + "Type": "AWS::EC2::IPAMPool", + "Properties": { + "AddressFamily": "ipv6", + "AwsService": "ec2", + "IpamScopeId": "DefaultPublicScope", + "Locale": "eu-central-1", + "PublicIpSource": "amazon" + } + }, + "IpamTestPublicPool0PublicPool0CidrC57CE00C": { + "Type": "AWS::EC2::IPAMPoolCidr", + "Properties": { + "IpamPoolId": { + "Fn::GetAtt": [ + "IpamTestPublicPool0C44B7C49", + "IpamPoolId" + ] + }, + "NetmaskLength": 52 + } + }, + "VPCintegtest1EBA1CB75": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "VPCintegtest1ipv4IpamCidr8105B4E4": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "Ipv4IpamPoolId": { + "Fn::GetAtt": [ + "IpamTestPrivatePool039C763DC", + "IpamPoolId" + ] + }, + "Ipv4NetmaskLength": 20, + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "VPCintegtest1AmazonProvidedE0445E5C": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "Vpcintegtest20DAD8F9D": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.1.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default" + } + }, + "Vpcintegtest2Ipv6IpamCidrFF84EC2B": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "Ipv6IpamPoolId": { + "Fn::GetAtt": [ + "IpamTestPublicPool0C44B7C49", + "IpamPoolId" + ] + }, + "Ipv6NetmaskLength": 60, + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "IpamTestPublicPool0PublicPool0CidrC57CE00C" + ] + }, + "Vpcintegtest2SecondaryAddress2A96C0AF8": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "CidrBlock": "10.2.0.0/16", + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "Vpcintegtest2SecondaryAddress36FC60BBC": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "CidrBlock": "10.3.0.0/16", + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "testsbubnetSubnet77337845": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1a", + "CidrBlock": "10.1.0.0/24", + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "testsbubnetRouteTableF40F025B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "testsbubnetRouteTableAssociationD6D083FA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "testsbubnetRouteTableF40F025B" + }, + "SubnetId": { + "Ref": "testsbubnetSubnet77337845" + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "testsubnetSubnetDD417829": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1b", + "CidrBlock": "10.2.0.0/24", + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "testsubnetRouteTable55223C61": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "testsubnetRouteTableAssociationC106676D": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "testsubnetRouteTable55223C61" + }, + "SubnetId": { + "Ref": "testsubnetSubnetDD417829" + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "validateIpv6Subnet07BD40AE": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1b", + "CidrBlock": "10.3.0.0/24", + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "validateIpv6RouteTable10861B00": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + }, + "validateIpv6RouteTableAssociationD6330457": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "validateIpv6RouteTable10861B00" + }, + "SubnetId": { + "Ref": "validateIpv6Subnet07BD40AE" + } + }, + "DependsOn": [ + "Vpcintegtest2Ipv6IpamCidrFF84EC2B", + "Vpcintegtest2SecondaryAddress2A96C0AF8", + "Vpcintegtest2SecondaryAddress36FC60BBC" + ] + } + }, + "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/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integ.json new file mode 100644 index 0000000000000..c583ba29c25f7 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integtest-model/DefaultTest": { + "stacks": [ + "aws-cdk-vpcv2-alpha" + ], + "assertionStack": "integtest-model/DefaultTest/DeployAssert", + "assertionStackName": "integtestmodelDefaultTestDeployAssertCF40BD53" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json new file mode 100644 index 0000000000000..3dba4ef9b8bab --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/manifest.json new file mode 100644 index 0000000000000..bd084b1280480 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/manifest.json @@ -0,0 +1,272 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-vpcv2-alpha.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-vpcv2-alpha.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-vpcv2-alpha": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-vpcv2-alpha.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}/6af0c32b7b4dcf4566eda1afa97ddb6dc00a4597f5633e0d826df8642bc069f4.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-vpcv2-alpha.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-vpcv2-alpha.assets" + ], + "metadata": { + "/aws-cdk-vpcv2-alpha/IpamTest/Ipam": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamTestIpam6C9298EF" + } + ], + "/aws-cdk-vpcv2-alpha/IpamTest/PrivatePool0/PrivatePool0": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamTestPrivatePool039C763DC" + } + ], + "/aws-cdk-vpcv2-alpha/IpamTest/PublicPool0/PublicPool0": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamTestPublicPool0C44B7C49" + } + ], + "/aws-cdk-vpcv2-alpha/IpamTest/PublicPool0/PublicPool0Cidr": [ + { + "type": "aws:cdk:logicalId", + "data": "IpamTestPublicPool0PublicPool0CidrC57CE00C" + } + ], + "/aws-cdk-vpcv2-alpha/VPC-integ-test-1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1EBA1CB75" + } + ], + "/aws-cdk-vpcv2-alpha/VPC-integ-test-1/ipv4IpamCidr": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1ipv4IpamCidr8105B4E4" + } + ], + "/aws-cdk-vpcv2-alpha/VPC-integ-test-1/AmazonProvided": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1AmazonProvidedE0445E5C" + } + ], + "/aws-cdk-vpcv2-alpha/Vpc-integ-test-2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest20DAD8F9D" + } + ], + "/aws-cdk-vpcv2-alpha/Vpc-integ-test-2/Ipv6IpamCidr": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2Ipv6IpamCidrFF84EC2B" + } + ], + "/aws-cdk-vpcv2-alpha/Vpc-integ-test-2/SecondaryAddress2": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2SecondaryAddress2A96C0AF8" + } + ], + "/aws-cdk-vpcv2-alpha/Vpc-integ-test-2/SecondaryAddress3": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2SecondaryAddress36FC60BBC" + } + ], + "/aws-cdk-vpcv2-alpha/testsbubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetSubnet77337845" + } + ], + "/aws-cdk-vpcv2-alpha/testsbubnet/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetRouteTableF40F025B" + } + ], + "/aws-cdk-vpcv2-alpha/testsbubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "testsbubnetRouteTableAssociationD6D083FA" + } + ], + "/aws-cdk-vpcv2-alpha/testsubnet/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "testsubnetSubnetDD417829" + } + ], + "/aws-cdk-vpcv2-alpha/testsubnet/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "testsubnetRouteTable55223C61" + } + ], + "/aws-cdk-vpcv2-alpha/testsubnet/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "testsubnetRouteTableAssociationC106676D" + } + ], + "/aws-cdk-vpcv2-alpha/validateIpv6/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "validateIpv6Subnet07BD40AE" + } + ], + "/aws-cdk-vpcv2-alpha/validateIpv6/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "validateIpv6RouteTable10861B00" + } + ], + "/aws-cdk-vpcv2-alpha/validateIpv6/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "validateIpv6RouteTableAssociationD6330457" + } + ], + "/aws-cdk-vpcv2-alpha/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-vpcv2-alpha/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ], + "VPCintegtest1SecondaryIp684795D0A306": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1SecondaryIp684795D0A306", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "VPCintegtest1SecondaryIp757851A2E166": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1SecondaryIp757851A2E166", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "Vpcintegtest2SecondaryIp4840275314DC": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2SecondaryIp4840275314DC", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "Vpcintegtest2SecondaryIp58F23280A479": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2SecondaryIp58F23280A479", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "Vpcintegtest2SecondaryIpD363CCF2FF57": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcintegtest2SecondaryIpD363CCF2FF57", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ] + }, + "displayName": "aws-cdk-vpcv2-alpha" + }, + "integtestmodelDefaultTestDeployAssertCF40BD53.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodelDefaultTestDeployAssertCF40BD53.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodelDefaultTestDeployAssertCF40BD53": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.assets" + ], + "metadata": { + "/integtest-model/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/tree.json new file mode 100644 index 0000000000000..d8432677382f0 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.js.snapshot/tree.json @@ -0,0 +1,608 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-vpcv2-alpha": { + "id": "aws-cdk-vpcv2-alpha", + "path": "aws-cdk-vpcv2-alpha", + "children": { + "IpamTest": { + "id": "IpamTest", + "path": "aws-cdk-vpcv2-alpha/IpamTest", + "children": { + "Ipam": { + "id": "Ipam", + "path": "aws-cdk-vpcv2-alpha/IpamTest/Ipam", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAM", + "aws:cdk:cloudformation:props": { + "operatingRegions": [ + { + "regionName": "eu-central-1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAM", + "version": "0.0.0" + } + }, + "PrivatePool0": { + "id": "PrivatePool0", + "path": "aws-cdk-vpcv2-alpha/IpamTest/PrivatePool0", + "children": { + "PrivatePool0": { + "id": "PrivatePool0", + "path": "aws-cdk-vpcv2-alpha/IpamTest/PrivatePool0/PrivatePool0", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAMPool", + "aws:cdk:cloudformation:props": { + "addressFamily": "ipv4", + "ipamScopeId": "DefaultPrivateScope", + "locale": "eu-central-1", + "provisionedCidrs": [ + { + "cidr": "10.2.0.0/16" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAMPool", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "PublicPool0": { + "id": "PublicPool0", + "path": "aws-cdk-vpcv2-alpha/IpamTest/PublicPool0", + "children": { + "PublicPool0": { + "id": "PublicPool0", + "path": "aws-cdk-vpcv2-alpha/IpamTest/PublicPool0/PublicPool0", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAMPool", + "aws:cdk:cloudformation:props": { + "addressFamily": "ipv6", + "awsService": "ec2", + "ipamScopeId": "DefaultPublicScope", + "locale": "eu-central-1", + "publicIpSource": "amazon" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAMPool", + "version": "0.0.0" + } + }, + "PublicPool0Cidr": { + "id": "PublicPool0Cidr", + "path": "aws-cdk-vpcv2-alpha/IpamTest/PublicPool0/PublicPool0Cidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::IPAMPoolCidr", + "aws:cdk:cloudformation:props": { + "ipamPoolId": { + "Fn::GetAtt": [ + "IpamTestPublicPool0C44B7C49", + "IpamPoolId" + ] + }, + "netmaskLength": 52 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnIPAMPoolCidr", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.Ipam", + "version": "0.0.0" + } + }, + "VPC-integ-test-1": { + "id": "VPC-integ-test-1", + "path": "aws-cdk-vpcv2-alpha/VPC-integ-test-1", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpcv2-alpha/VPC-integ-test-1/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" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "ipv4IpamCidr": { + "id": "ipv4IpamCidr", + "path": "aws-cdk-vpcv2-alpha/VPC-integ-test-1/ipv4IpamCidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "ipv4IpamPoolId": { + "Fn::GetAtt": [ + "IpamTestPrivatePool039C763DC", + "IpamPoolId" + ] + }, + "ipv4NetmaskLength": 20, + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + }, + "AmazonProvided": { + "id": "AmazonProvided", + "path": "aws-cdk-vpcv2-alpha/VPC-integ-test-1/AmazonProvided", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "Vpc-integ-test-2": { + "id": "Vpc-integ-test-2", + "path": "aws-cdk-vpcv2-alpha/Vpc-integ-test-2", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpcv2-alpha/Vpc-integ-test-2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.1.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "Ipv6IpamCidr": { + "id": "Ipv6IpamCidr", + "path": "aws-cdk-vpcv2-alpha/Vpc-integ-test-2/Ipv6IpamCidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "ipv6IpamPoolId": { + "Fn::GetAtt": [ + "IpamTestPublicPool0C44B7C49", + "IpamPoolId" + ] + }, + "ipv6NetmaskLength": 60, + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + }, + "SecondaryAddress2": { + "id": "SecondaryAddress2", + "path": "aws-cdk-vpcv2-alpha/Vpc-integ-test-2/SecondaryAddress2", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.2.0.0/16", + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + }, + "SecondaryAddress3": { + "id": "SecondaryAddress3", + "path": "aws-cdk-vpcv2-alpha/Vpc-integ-test-2/SecondaryAddress3", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.3.0.0/16", + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "testsbubnet": { + "id": "testsbubnet", + "path": "aws-cdk-vpcv2-alpha/testsbubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpcv2-alpha/testsbubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "eu-central-1a", + "cidrBlock": "10.1.0.0/24", + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpcv2-alpha/testsbubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpcv2-alpha/testsbubnet/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpcv2-alpha/testsbubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "testsbubnetRouteTableF40F025B" + }, + "subnetId": { + "Ref": "testsbubnetSubnet77337845" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "testsubnet": { + "id": "testsubnet", + "path": "aws-cdk-vpcv2-alpha/testsubnet", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpcv2-alpha/testsubnet/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "eu-central-1b", + "cidrBlock": "10.2.0.0/24", + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpcv2-alpha/testsubnet/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpcv2-alpha/testsubnet/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpcv2-alpha/testsubnet/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "testsubnetRouteTable55223C61" + }, + "subnetId": { + "Ref": "testsubnetSubnetDD417829" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "validateIpv6": { + "id": "validateIpv6", + "path": "aws-cdk-vpcv2-alpha/validateIpv6", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpcv2-alpha/validateIpv6/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "eu-central-1b", + "cidrBlock": "10.3.0.0/24", + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpcv2-alpha/validateIpv6/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpcv2-alpha/validateIpv6/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Fn::GetAtt": [ + "Vpcintegtest20DAD8F9D", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpcv2-alpha/validateIpv6/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "validateIpv6RouteTable10861B00" + }, + "subnetId": { + "Ref": "validateIpv6Subnet07BD40AE" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-vpcv2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-vpcv2-alpha/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-vpcv2-alpha/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integtest-model": { + "id": "integtest-model", + "path": "integtest-model", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model/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/aws-ec2-alpha/test/integ.vpc-v2-alpha.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.ts new file mode 100644 index 0000000000000..6074d53f5ea9e --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.vpc-v2-alpha.ts @@ -0,0 +1,108 @@ +// /* +// * Our integration tests act as snapshot tests to make sure the rendered template is stable. +// * If any changes to the result are required, +// * you need to perform an actual CloudFormation deployment of this application, +// * and, if it is successful, a new snapshot will be written out. +// * +// * For more information on CDK integ tests, +// * see the main CONTRIBUTING.md file. +// */ + +import * as vpc_v2 from '../lib/vpc-v2'; +import { AddressFamily, AwsServiceName, Ipam, IpamPoolPublicIpSource } from '../lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { SubnetV2, IpCidr } from '../lib/subnet-v2'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-vpcv2-alpha'); + +const ipam = new Ipam(stack, 'IpamTest', { + operatingRegion: ['eu-central-1'], +}); + +/**Test Ipam Pool Ipv4 */ + +const pool1 = ipam.privateScope.addPool('PrivatePool0', { + addressFamily: AddressFamily.IP_V4, + ipv4ProvisionedCidrs: ['10.2.0.0/16'], + locale: 'eu-central-1', +}); + +const pool2 = ipam.publicScope.addPool('PublicPool0', { + addressFamily: AddressFamily.IP_V6, + awsService: AwsServiceName.EC2, + locale: 'eu-central-1', + publicIpSource: IpamPoolPublicIpSource.AMAZON, +}); +pool2.provisionCidr('PublicPool0Cidr', { netmaskLength: 52 } ); + +/** Test Ipv4 Primary and Secondary address */ +new vpc_v2.VpcV2(stack, 'VPC-integ-test-1', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [ + vpc_v2.IpAddresses.ipv4Ipam({ + ipamPool: pool1, + netmaskLength: 20, + cidrBlockName: 'ipv4IpamCidr', + }), + //Test secondary ipv6 address + vpc_v2.IpAddresses.amazonProvidedIpv6({ + cidrBlockName: 'AmazonProvided', + }), + ], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +/** + * Integ test for VPC with IPAM pool to be run with --no-clean + */ +const vpc = new vpc_v2.VpcV2(stack, 'Vpc-integ-test-2', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.ipv6Ipam({ + ipamPool: pool2, + netmaskLength: 60, + cidrBlockName: 'Ipv6IpamCidr', + }), + vpc_v2.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'SecondaryAddress2', + }), + vpc_v2.IpAddresses.ipv4('10.3.0.0/16', { + cidrBlockName: 'SecondaryAddress3', + }, + )], +}); + +new SubnetV2(stack, 'testsbubnet', { + vpc, + availabilityZone: 'eu-central-1a', + ipv4CidrBlock: new IpCidr('10.1.0.0/24'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +new SubnetV2(stack, 'testsubnet', { + vpc, + availabilityZone: 'eu-central-1b', + ipv4CidrBlock: new IpCidr('10.2.0.0/24'), + //Test secondary ipv6 address after IPAM pool creation + //ipv6CidrBlock: new Ipv6Cidr('2001:db8:1::/64'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +//validate ipv6 +new SubnetV2(stack, 'validateIpv6', { + vpc, + ipv4CidrBlock: new IpCidr('10.3.0.0/24'), + availabilityZone: 'eu-central-1b', + //Test secondary ipv6 address after IPAM pool creation + //ipv6CidrBlock: new Ipv6Cidr('2001:db8::/48'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/ipam.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/ipam.test.ts new file mode 100644 index 0000000000000..7d5db75bcd7e2 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/ipam.test.ts @@ -0,0 +1,150 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as cdk from 'aws-cdk-lib'; +import * as vpc from '../lib'; +import { AddressFamily, Ipam, IpamPoolPublicIpSource } from '../lib'; + +describe('IPAM Test', () => { + let stack: cdk.Stack; + let ipam: Ipam; + + beforeEach(() => { + const envUSA = { region: 'us-west-2' }; + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app, 'IPAMTestStack', { + env: envUSA, + }); + ipam = new Ipam(stack, 'Ipam', { + operatingRegion: ['us-west-2'], + }); + }); + + test('Creates IP Pool under Public Scope', () => { + + const pool = ipam.publicScope.addPool('Public', { + addressFamily: AddressFamily.IP_V6, + awsService: vpc.AwsServiceName.EC2, + locale: 'us-west-2', + publicIpSource: IpamPoolPublicIpSource.AMAZON, + }); + + new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.2.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6Ipam({ + ipamPool: pool, + netmaskLength: 52, + cidrBlockName: 'Ipv6Ipam', + })], + }); + Template.fromStack(stack).hasResourceProperties( + 'AWS::EC2::IPAMPool', + { + AddressFamily: 'ipv6', + IpamScopeId: 'DefaultPublicScope', + Locale: 'us-west-2', + }, + ); //End Template + }); // End Test + + test('Creates IP Pool under Private Scope', () => { + + const pool = ipam.privateScope.addPool('Private', { + addressFamily: vpc.AddressFamily.IP_V4, + ipv4ProvisionedCidrs: ['10.2.0.0/16'], + locale: 'us-west-2', + }); + + new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.2.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4Ipam({ + ipamPool: pool, + netmaskLength: 20, + cidrBlockName: 'SecondaryIpv4', + })], + }); + Template.fromStack(stack).hasResourceProperties( + 'AWS::EC2::IPAMPool', + { + AddressFamily: 'ipv4', + IpamScopeId: 'DefaultPrivateScope', + Locale: 'us-west-2', + }, + ); //End Template + }); + + test('Creates IPAM CIDR pool under public scope for IPv6', () => { + // Create IPAM resources + const ipamIpv6 = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-2'], + }); + const poolOptions: vpc.PoolOptions = { + addressFamily: AddressFamily.IP_V6, + awsService: vpc.AwsServiceName.EC2, + publicIpSource: IpamPoolPublicIpSource.AMAZON, + locale: 'us-west-2', + }; + ipamIpv6.publicScope.addPool('TestPool', poolOptions); + + // Define the expected CloudFormation template + const expectedTemplate = { + Resources: { + Ipam50346F82: { Type: 'AWS::EC2::IPAM' }, + TestIpamDBF92BA8: { Type: 'AWS::EC2::IPAM' }, + TestIpamTestPool5D90F91B: { + Type: 'AWS::EC2::IPAMPool', + Properties: { + AddressFamily: 'ipv6', + IpamScopeId: 'DefaultPublicScope', + Locale: 'us-west-2', + }, + }, + }, + }; + // // Assert that the generated template matches the expected template + Template.fromStack(stack).templateMatches(expectedTemplate); + }); + + test('Get region from stack env', () => { + // Create IPAM resources + const ipamRegion = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-2'], + }); + const poolOptions: vpc.PoolOptions = { + addressFamily: AddressFamily.IP_V6, + awsService: vpc.AwsServiceName.EC2, + publicIpSource: IpamPoolPublicIpSource.AMAZON, + locale: 'us-west-2', + }; + ipamRegion.publicScope.addPool('TestPool', poolOptions); + + // Define the expected CloudFormation template + const expectedTemplate = { + Resources: { + Ipam50346F82: { Type: 'AWS::EC2::IPAM' }, + TestIpamDBF92BA8: { Type: 'AWS::EC2::IPAM' }, + TestIpamTestPool5D90F91B: { + Type: 'AWS::EC2::IPAMPool', + Properties: { + AddressFamily: 'ipv6', + IpamScopeId: 'DefaultPublicScope', + Locale: 'us-west-2', + }, + }, + }, + }; + // // Assert that the generated template matches the expected template + Template.fromStack(stack).templateMatches(expectedTemplate); + }); + + test('Creates IPAM with default scopes', () => { + new Ipam(stack, 'TestIpam', { + }); + Template.fromStack(stack).hasResource( + 'AWS::EC2::IPAM', {}, + ); + }); + +});// End Test \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/route.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/route.test.ts new file mode 100644 index 0000000000000..e5dc355fc1aea --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/route.test.ts @@ -0,0 +1,674 @@ +import * as cdk from 'aws-cdk-lib'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { CfnEIP, GatewayVpcEndpoint, GatewayVpcEndpointAwsService, SubnetType, VpnConnectionType } from 'aws-cdk-lib/aws-ec2'; +import * as route from '../lib/route'; +import { Template } from 'aws-cdk-lib/assertions'; + +describe('EC2 Routing', () => { + let stack: cdk.Stack; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + let routeTable: route.RouteTable; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); + myVpc = new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.amazonProvidedIpv6({ + cidrBlockName: 'AmazonIpv6', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }); + routeTable = new route.RouteTable(stack, 'TestRouteTable', { + vpc: myVpc, + }); + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr(cdk.Fn.select(0, myVpc.ipv6CidrBlocks)), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + routeTable: routeTable, + }); + }); + + test('Route to EIGW', () => { + const eigw = new route.EgressOnlyInternetGateway(stack, 'TestEIGW', { + vpc: myVpc, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: eigw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // EIGW should be in stack + TestEIGW4E4CDA8D: { + Type: 'AWS::EC2::EgressOnlyInternetGateway', + Properties: { + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', 'VpcId', + ], + }, + }, + }, + // Route linking IP to EIGW should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + EgressOnlyInternetGatewayId: { + 'Fn::GetAtt': [ + 'TestEIGW4E4CDA8D', 'Id', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', 'RouteTableId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to VPN Gateway', () => { + const vpngw = new route.VPNGateway(stack, 'TestVpnGw', { + type: VpnConnectionType.IPSEC_1, + vpc: myVpc, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: vpngw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // VPN Gateway should be in stack + TestVpnGwIGW11AF5344: { + Type: 'AWS::EC2::VPNGateway', + Properties: { + Type: 'ipsec.1', + }, + }, + // Route linking IP to VPN GW should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + GatewayId: { + 'Fn::GetAtt': [ + 'TestVpnGwIGW11AF5344', 'VPNGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', 'RouteTableId', + ], + }, + }, + }, + // Route Gateway attachment should be in stack + TestRouteGWAttachmentDD69361B: { + Type: 'AWS::EC2::VPCGatewayAttachment', + Properties: { + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', 'VpcId', + ], + }, + VpnGatewayId: { + 'Fn::GetAtt': [ + 'TestVpnGwIGW11AF5344', 'VPNGatewayId', + ], + }, + }, + }, + }, + }); + }), + + test('Route to VPN Gateway with optional properties', () => { + new route.VPNGateway(stack, 'TestVpnGw', { + type: VpnConnectionType.IPSEC_1, + vpc: myVpc, + amazonSideAsn: 12345678, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // VPN Gateway should be in stack + TestVpnGwIGW11AF5344: { + Type: 'AWS::EC2::VPNGateway', + Properties: { + AmazonSideAsn: 12345678, + Type: 'ipsec.1', + }, + }, + }, + }); + }), + + test('Route to Internet Gateway', () => { + const igw = new route.InternetGateway(stack, 'TestIGW', { + vpc: myVpc, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: igw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // Internet Gateway should be in stack + TestIGW1B4DB37D: { + Type: 'AWS::EC2::InternetGateway', + }, + // Route linking IP to IGW should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + GatewayId: { + 'Fn::GetAtt': [ + 'TestIGW1B4DB37D', 'InternetGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', 'RouteTableId', + ], + }, + }, + }, + // Route Gateway attachment should be in stack + TestRouteGWAttachmentDD69361B: { + Type: 'AWS::EC2::VPCGatewayAttachment', + Properties: { + InternetGatewayId: { + 'Fn::GetAtt': [ + 'TestIGW1B4DB37D', 'InternetGatewayId', + ], + }, + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', 'VpcId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to private NAT Gateway', () => { + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + connectivityType: route.NatConnectivityType.PRIVATE, + privateIpAddress: '10.0.0.42', + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + ConnectivityType: 'private', + PrivateIpAddress: '10.0.0.42', + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + // Route linking private IP to NAT Gateway should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + NatGatewayId: { + 'Fn::GetAtt': [ + 'TestNATGWNATGatewayBE4F6F2D', + 'NatGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to private NAT Gateway with secondary IP addresses', () => { + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + connectivityType: route.NatConnectivityType.PRIVATE, + privateIpAddress: '10.0.0.42', + secondaryPrivateIpAddresses: [ + '10.0.1.0/28', + '10.0.2.0/28', + ], + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + ConnectivityType: 'private', + PrivateIpAddress: '10.0.0.42', + SecondaryPrivateIpAddresses: [ + '10.0.1.0/28', + '10.0.2.0/28', + ], + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + + }, + }); + }); + + test('Route to private NAT Gateway with secondary IP count', () => { + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + connectivityType: route.NatConnectivityType.PRIVATE, + privateIpAddress: '10.0.0.42', + secondaryPrivateIpAddressCount: 2, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + ConnectivityType: 'private', + PrivateIpAddress: '10.0.0.42', + SecondaryPrivateIpAddressCount: 2, + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + // Route linking private IP to NAT Gateway should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + NatGatewayId: { + 'Fn::GetAtt': [ + 'TestNATGWNATGatewayBE4F6F2D', + 'NatGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to public NAT Gateway', () => { + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + // Route linking private IP to NAT Gateway should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + NatGatewayId: { + 'Fn::GetAtt': [ + 'TestNATGWNATGatewayBE4F6F2D', + 'NatGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + }, + }, + // EIP should be created when not provided + TestNATGWEIP0A279819: { + Type: 'AWS::EC2::EIP', + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + }, + }); + }); + + test('Route to public NAT Gateway with provided EIP', () => { + const eip = new CfnEIP(stack, 'MyEIP', { + domain: myVpc.vpcId, + }); + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + allocationId: eip.attrAllocationId, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + // Route linking private IP to NAT Gateway should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + NatGatewayId: { + 'Fn::GetAtt': [ + 'TestNATGWNATGatewayBE4F6F2D', + 'NatGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + }, + }, + // EIP should be in stack + MyEIP: { + Type: 'AWS::EC2::EIP', + Properties: { + Domain: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to public NAT Gateway with many parameters', () => { + const natgw = new route.NatGateway(stack, 'TestNATGW', { + subnet: mySubnet, + connectivityType: route.NatConnectivityType.PUBLIC, + maxDrainDuration: cdk.Duration.seconds(2001), + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { gateway: natgw }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // NAT Gateway should be in stack + TestNATGWNATGatewayBE4F6F2D: { + Type: 'AWS::EC2::NatGateway', + Properties: { + AllocationId: { + 'Fn::GetAtt': [ + 'TestNATGWEIP0A279819', + 'AllocationId', + ], + }, + ConnectivityType: 'public', + MaxDrainDurationSeconds: 2001, + SubnetId: { + Ref: 'TestSubnet2A4BE4CA', + }, + }, + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + // Route linking private IP to NAT Gateway should be in stack + TestRoute4CB59404: { + Type: 'AWS::EC2::Route', + Properties: { + DestinationCidrBlock: '0.0.0.0/0', + NatGatewayId: { + 'Fn::GetAtt': [ + 'TestNATGWNATGatewayBE4F6F2D', + 'NatGatewayId', + ], + }, + RouteTableId: { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + }, + }, + // EIP should be created when not provided + TestNATGWEIP0A279819: { + Type: 'AWS::EC2::EIP', + DependsOn: [ + 'TestSubnetRouteTableAssociationFE267B30', + ], + }, + }, + }); + }); + + test('Route to DynamoDB Endpoint', () => { + const dynamodb = new GatewayVpcEndpoint(stack, 'TestDB', { + vpc: myVpc, + service: GatewayVpcEndpointAwsService.DYNAMODB, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { endpoint: dynamodb }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // DynamoDB endpoint should be in stack + TestDB27CDA92F: { + Type: 'AWS::EC2::VPCEndpoint', + Properties: { + RouteTableIds: [ + { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + ], + ServiceName: { + 'Fn::Join': [ + '', + [ + 'com.amazonaws.', + { Ref: 'AWS::Region' }, + '.dynamodb', + ], + ], + }, + VpcEndpointType: 'Gateway', + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to S3 Endpoint', () => { + const dynamodb = new GatewayVpcEndpoint(stack, 'TestS3', { + vpc: myVpc, + service: GatewayVpcEndpointAwsService.S3, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { endpoint: dynamodb }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // S3 endpoint should be in stack + TestS38FCC715C: { + Type: 'AWS::EC2::VPCEndpoint', + Properties: { + RouteTableIds: [ + { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + ], + ServiceName: { + 'Fn::Join': [ + '', + [ + 'com.amazonaws.', + { Ref: 'AWS::Region' }, + '.s3', + ], + ], + }, + VpcEndpointType: 'Gateway', + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + }); + + test('Route to S3 Express Endpoint', () => { + const dynamodb = new GatewayVpcEndpoint(stack, 'TestS3E', { + vpc: myVpc, + service: GatewayVpcEndpointAwsService.S3_EXPRESS, + }); + new route.Route(stack, 'TestRoute', { + routeTable: routeTable, + destination: '0.0.0.0/0', + target: { endpoint: dynamodb }, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + // S3 endpoint should be in stack + TestS3E055E5994: { + Type: 'AWS::EC2::VPCEndpoint', + Properties: { + RouteTableIds: [ + { + 'Fn::GetAtt': [ + 'TestRouteTableC34C2E1C', + 'RouteTableId', + ], + }, + ], + ServiceName: { + 'Fn::Join': [ + '', + [ + 'com.amazonaws.', + { Ref: 'AWS::Region' }, + '.s3express', + ], + ], + }, + VpcEndpointType: 'Gateway', + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + }); + +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts new file mode 100644 index 0000000000000..42289b359cece --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts @@ -0,0 +1,303 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as cdk from 'aws-cdk-lib'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { NetworkAcl, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { AddressFamily, AwsServiceName, Ipam, IpamPoolPublicIpSource } from '../lib/ipam'; +import { createTestSubnet } from './util'; + +/** + * Test suite for the SubnetV2 class. + * Verifies the correct behavior and functionality of creating and managing subnets within a VpcV2 instance. + */ +describe('Subnet V2 with custom IP and routing', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); + + }); + + test('should create a subnet with valid input parameters', () => { + + const testVpc = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'Secondary1', + })], + }); + + const subnetConfig = { + vpcV2: testVpc, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + subnetType: SubnetType.PUBLIC, + }; + + createTestSubnet(stack, subnetConfig); + + Template.fromStack(stack).templateMatches({ + Resources: { + TestVPCD26570D8: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + }, + }, + TestSubnet2A4BE4CA: { + Type: 'AWS::EC2::Subnet', + Properties: { + CidrBlock: '10.1.0.0/24', + AvailabilityZone: 'us-east-1a', + VpcId: { + 'Fn::GetAtt': [ + 'TestVPCD26570D8', + 'VpcId', + ], + }, + }, + }, + }, + }); + + }); + + test('Should throw error if overlapping CIDR block(IPv4) for the subnet', () => { + const testVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'Secondary1', + })], + }); + + const subnetConfig = { + vpcV2: testVPC, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + subnetType: SubnetType.PUBLIC, + }; + + createTestSubnet(stack, subnetConfig); + + // Define a second subnet with an overlapping CIDR range + expect(() => new subnet.SubnetV2(stack, 'InvalidSubnet', { + vpc: testVPC, + ipv4CidrBlock: new subnet.IpCidr('10.1.0.0/24'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + })).toThrow('CIDR block should not overlap with existing subnet blocks'); + }); + + test('Should throw error if invalid CIDR block', () => { + const testVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'Secondary1', + })], + }); + + expect(() => new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: testVPC, + ipv4CidrBlock: new subnet.IpCidr('10.3.0.0/23'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + })).toThrow('CIDR block should be within the range of VPC'); + }); + + test('Should throw error if VPC does not support IPv6', () => { + const TestVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'Secondary1', + })], + }); + expect(() => new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: TestVPC, + ipv4CidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr('2001:db8:1::/64'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + })).toThrow('To use IPv6, the VPC must enable IPv6 support.'); + }); + + test('Create Subnet with IPv6 if it is Amazon Provided Ipv6 is enabled on VPC', () => { + const testVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.amazonProvidedIpv6({ + cidrBlockName: 'AmazonIpv6', + })], + }); + + const subnetConfig = { + vpcV2: testVPC, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6Cidr: new subnet.IpCidr('2001:db8:1::/64'), + subnetType: SubnetType.PUBLIC, + }; + createTestSubnet(stack, subnetConfig); + Template.fromStack(stack).templateMatches({ + Resources: { + TestVPCD26570D8: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + }, + }, + TestSubnet2A4BE4CA: { + Type: 'AWS::EC2::Subnet', + Properties: { + CidrBlock: '10.1.0.0/24', + AvailabilityZone: 'us-east-1a', + VpcId: { + 'Fn::GetAtt': [ + 'TestVPCD26570D8', + 'VpcId', + ], + }, + Ipv6CidrBlock: '2001:db8:1::/64', + }, + }, + }, + }); + }); + + test('Create Subnet with IPv6 if it is Ipam Ipv6 is enabled on VPC', () => { + const ipam = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-1'], + }); + const pool = ipam.publicScope.addPool('PublicPool0', { + addressFamily: AddressFamily.IP_V6, + awsService: AwsServiceName.EC2, + publicIpSource: IpamPoolPublicIpSource.AMAZON, + locale: 'us-west-1', + }); + const TestVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6Ipam({ + ipamPool: pool, + netmaskLength: 60, + cidrBlockName: 'ipv6Ipam', + })], + }); + + new subnet.SubnetV2(stack, 'IpamSubnet', { + vpc: TestVPC, + ipv4CidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr('2001:db8:1::/64'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + }); + Template.fromStack(stack).templateMatches({ + Resources: { + TestIpamDBF92BA8: { Type: 'AWS::EC2::IPAM' }, + TestIpamPublicPool0588A338B: { + Type: 'AWS::EC2::IPAMPool', + Properties: + { + AddressFamily: 'ipv6', + IpamScopeId: 'DefaultPublicScope', + }, + }, + TestVPCD26570D8: { Type: 'AWS::EC2::VPC' }, + TestVPCipv6Ipam6024F9EC: { Type: 'AWS::EC2::VPCCidrBlock' }, + IpamSubnet78671F8A: { + Type: 'AWS::EC2::Subnet', + Properties: { + CidrBlock: '10.1.0.0/24', + AvailabilityZone: 'us-east-1a', + VpcId: { 'Fn::GetAtt': ['TestVPCD26570D8', 'VpcId'] }, + Ipv6CidrBlock: '2001:db8:1::/64', + }, + }, + }, + }); + }); + + test('Should throw error if overlapping CIDR block(IPv6) for the subnet', () => { + const ipam = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-1'], + }); + const pool = ipam.publicScope.addPool('PublicPool0', { + addressFamily: AddressFamily.IP_V6, + awsService: AwsServiceName.EC2, + publicIpSource: IpamPoolPublicIpSource.AMAZON, + locale: 'us-west-1', + }); + const testVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6Ipam({ + ipamPool: pool, + netmaskLength: 60, + cidrBlockName: 'ipv6Ipam', + })], + }); + + const subnetConfig = { + vpcV2: testVPC, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr('2001:db8:1::/64'), + subnetType: SubnetType.PUBLIC, + }; + createTestSubnet(stack, subnetConfig); + + // Define a second subnet with an overlapping CIDR range + expect(() => new subnet.SubnetV2(stack, 'OverlappingSubnet', { + vpc: testVPC, + ipv4CidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr('2001:db8:1:1::/64'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + })).toThrow('CIDR block should not overlap with existing subnet blocks'); + }); + + test('should store the subnet to VPC by subnet type', () => { + const testVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + }); + + const subnetConfig = { + vpcV2: testVPC, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + subnetType: SubnetType.PUBLIC, + }; + const testsubnet = createTestSubnet(stack, subnetConfig); + + /** + * Test case: Verify that the subnet is correctly stored in the VPC's collection of public subnets. + * Expected outcome: The testsubnet should be the only public subnet in the VPC. + */ + expect(testVPC.publicSubnets.length).toEqual(1); + expect(testVPC.publicSubnets[0]).toEqual(testsubnet); + }); + + test('should associate a NetworkAcl with the subnet', () => { + const testVpc = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + }); + + const subnetConfig = { + vpcV2: testVpc, + availabilityZone: 'us-east-1a', + cidrBlock: new subnet.IpCidr('10.1.0.0/24'), + subnetType: SubnetType.PUBLIC, + }; + const testsubnet = createTestSubnet(stack, subnetConfig); + + const networkAcl = new NetworkAcl(stack, 'TestNetworkAcl', { + vpc: testVpc, + }); + + testsubnet.associateNetworkAcl('TestAssociation', networkAcl); + + expect(Template.fromStack(stack).hasResource('AWS::EC2::SubnetNetworkAclAssociation', {})); + }); + +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/util.ts b/packages/@aws-cdk/aws-ec2-alpha/test/util.ts new file mode 100644 index 0000000000000..89fb42c30861b --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/util.ts @@ -0,0 +1,27 @@ +import * as cdk from 'aws-cdk-lib'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { AddressFamily } from '../lib'; + +export function createTestSubnet( + stack: cdk.Stack, + config: { + vpcV2: vpc.VpcV2; + availabilityZone: string; + cidrBlock: subnet.IpCidr; + subnetType: SubnetType; + addressFamily?: AddressFamily; + ipv6Cidr?: subnet.IpCidr; + }, +): subnet.SubnetV2 { + const { vpcV2, availabilityZone, cidrBlock, subnetType, ipv6Cidr } = config; + + return new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: vpcV2, + availabilityZone, + ipv4CidrBlock: cidrBlock, + subnetType, + ipv6CidrBlock: ipv6Cidr, + }); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts new file mode 100644 index 0000000000000..bd5e6fb7161a8 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts @@ -0,0 +1,260 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import * as cdk from 'aws-cdk-lib'; +import * as vpc from '../lib/vpc-v2'; +import { AddressFamily, AwsServiceName, Ipam, IpamPoolPublicIpSource } from '../lib'; + +describe('Vpc V2 with full control', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); + }); + + test('VPC with primary address', () => { + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + Template.fromStack(stack).templateMatches({ + Resources: { + TestVpcE77CE678: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + EnableDnsHostnames: true, + EnableDnsSupport: true, + }, + }, + }, + }); + }); + + test('VPC with secondary IPv4 address', () => { + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.2.0.0/16', { + cidrBlockName: 'SecondaryAddress', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + Template.fromStack(stack).templateMatches({ + Resources: { + TestVpcE77CE678: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + EnableDnsHostnames: true, + EnableDnsSupport: true, + }, + }, + TestVpcSecondaryAddressD76FCD9C: { + Type: 'AWS::EC2::VPCCidrBlock', + Properties: { + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + + }); + + test('VPC throws error with incorrect cidr range (IPv4)', () => { + expect(() => { + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('192.168.0.0/16', { + cidrBlockName: 'SecondaryIpv4', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + }).toThrow('CIDR block should be in the same RFC 1918 range in the VPC'); + }); + + test('VPC supports secondary Amazon Provided IPv6 address', () => { + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.amazonProvidedIpv6({ cidrBlockName: 'AmazonProvided' })], + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + Template.fromStack(stack).templateMatches({ + Resources: { + TestVpcE77CE678: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + EnableDnsHostnames: true, + EnableDnsSupport: true, + }, + }, + TestVpcAmazonProvided569F7097: { + Type: 'AWS::EC2::VPCCidrBlock', + Properties: { + AmazonProvidedIpv6CidrBlock: true, //Amazon Provided IPv6 address + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + }, + }, + }, + }); + + }); + + test('VPC Primary IP from Ipv4 Ipam', () => { + + const ipam = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-1'], + }); + + const pool = ipam.privateScope.addPool('PrivatePool0', { + addressFamily: AddressFamily.IP_V4, + ipv4ProvisionedCidrs: ['10.1.0.1/24'], + locale: 'us-west-1', + }); + + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4Ipam({ + ipamPool: pool, + netmaskLength: 28, + cidrBlockName: 'IPv4Ipam', + }), + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + Template.fromStack(stack).templateMatches({ + Resources: { + TestIpamDBF92BA8: { Type: 'AWS::EC2::IPAM' }, + TestIpamPrivatePool0E8589980: { + Type: 'AWS::EC2::IPAMPool', + Properties: { + AddressFamily: 'ipv4', + IpamScopeId: 'DefaultPrivateScope', + Locale: 'us-west-1', + ProvisionedCidrs: [ + { + Cidr: '10.1.0.1/24', + }, + ], + }, + }, + TestVpcE77CE678: { + Type: 'AWS::EC2::VPC', + Properties: { + Ipv4IpamPoolId: { + 'Fn::GetAtt': [ + 'TestIpamPrivatePool0E8589980', + 'IpamPoolId', + ], + }, + EnableDnsHostnames: true, + EnableDnsSupport: true, + }, + }, + }, + }); + }); + + test('VPC Secondary IP from Ipv6 Ipam', () => { + const ipam = new Ipam(stack, 'TestIpam', { + operatingRegion: ['us-west-1'], + }); + + const pool = ipam.publicScope.addPool('PublicPool0', { + addressFamily: AddressFamily.IP_V6, + awsService: AwsServiceName.EC2, + publicIpSource: IpamPoolPublicIpSource.AMAZON, + locale: 'us-west-1', + }); + pool.provisionCidr('PublicPoolCidr', { + netmaskLength: 60, + }); + + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6Ipam({ + ipamPool: pool, + netmaskLength: 64, + cidrBlockName: 'IPv6Ipam', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }, + ); + Template.fromStack(stack).templateMatches({ + Resources: { + TestIpamDBF92BA8: { Type: 'AWS::EC2::IPAM' }, + TestIpamPublicPool0588A338B: { + Type: 'AWS::EC2::IPAMPool', + Properties: { + AddressFamily: 'ipv6', + AwsService: 'ec2', + IpamScopeId: 'DefaultPublicScope', + PublicIpSource: 'amazon', + }, + }, + // Test Amazon Provided IPAM IPv6 + TestIpamPublicPool0PublicPoolCidrB0FF20F7: { + Type: 'AWS::EC2::IPAMPoolCidr', + Properties: { + IpamPoolId: { + 'Fn::GetAtt': [ + 'TestIpamPublicPool0588A338B', + 'IpamPoolId', + ], + }, + NetmaskLength: 60, + }, + }, + TestVpcE77CE678: { + Type: 'AWS::EC2::VPC', + Properties: { + CidrBlock: '10.1.0.0/16', + EnableDnsHostnames: true, + EnableDnsSupport: true, + }, + }, + TestVpcIPv6Ipam178145A5: { + Type: 'AWS::EC2::VPCCidrBlock', + Properties: { + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + Ipv6IpamPoolId: { + 'Fn::GetAtt': [ + 'TestIpamPublicPool0588A338B', + 'IpamPoolId', + ], + }, + Ipv6NetmaskLength: 64, + }, + }, + }, + }); + }); +}); + diff --git a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES index 2c9a5a75dad60..30c90c16203a6 100644 --- a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES @@ -3832,4 +3832,4 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------- +---------------- \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md index be8cfb6c4d69c..aad87ef49fbde 100644 --- a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md +++ b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md @@ -1355,4 +1355,4 @@ for more details. | 2.148.0 | `false` | `true` | - + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index daba47a532a73..b446bece17399 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16824,4 +16824,4 @@ zip-stream@^4.1.0: dependencies: archiver-utils "^3.0.4" compress-commons "^4.1.2" - readable-stream "^3.6.0" + readable-stream "^3.6.0" \ No newline at end of file From 5ee6cde8a6cc7c31d9fcde5567eb9988d663bcf3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:55:36 +0000 Subject: [PATCH 06/12] chore(deps): bump certifi from 2023.7.22 to 2024.7.4 in /packages/@aws-cdk/aws-lambda-python-alpha/test/lambda-handler-project/shared (#31052) Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.7.22 to 2024.7.4.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=certifi&package-manager=pip&previous-version=2023.7.22&new-version=2024.7.4)](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).
--- .../test/lambda-handler-project/shared/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda-python-alpha/test/lambda-handler-project/shared/requirements.txt b/packages/@aws-cdk/aws-lambda-python-alpha/test/lambda-handler-project/shared/requirements.txt index 404d7b7716fe8..dedc6c4f75539 100644 --- a/packages/@aws-cdk/aws-lambda-python-alpha/test/lambda-handler-project/shared/requirements.txt +++ b/packages/@aws-cdk/aws-lambda-python-alpha/test/lambda-handler-project/shared/requirements.txt @@ -1,5 +1,5 @@ # Lock versions of pip packages -certifi==2023.7.22 +certifi==2024.7.4 chardet==3.0.4 idna==3.7 urllib3==1.26.18 From b17bd1dbfc200a6881ab3e64bbf0d9246490015a Mon Sep 17 00:00:00 2001 From: Tom Keller <1083460+kellertk@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:03:04 -0700 Subject: [PATCH 07/12] chore: add needs-triage to issue templates (#31056) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .github/ISSUE_TEMPLATE/notice.yml | 4 ++-- .github/ISSUE_TEMPLATE/region.yml | 4 ++-- .github/ISSUE_TEMPLATE/tracking.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/notice.yml b/.github/ISSUE_TEMPLATE/notice.yml index f75640e0258c3..f90f63deb325e 100644 --- a/.github/ISSUE_TEMPLATE/notice.yml +++ b/.github/ISSUE_TEMPLATE/notice.yml @@ -1,8 +1,8 @@ --- name: "❗ Notice" -description: Post a notice for a high impact issue +description: Post a notice for a high impact issue. Internal CDK team use only. title: "❗ NOTICE (module name): (short notice description)" -labels: [p0, management/tracking] +labels: [needs-triage, management/tracking] body: - type: dropdown attributes: diff --git a/.github/ISSUE_TEMPLATE/region.yml b/.github/ISSUE_TEMPLATE/region.yml index 0e6ed816993f4..8ef3aa3ca8835 100644 --- a/.github/ISSUE_TEMPLATE/region.yml +++ b/.github/ISSUE_TEMPLATE/region.yml @@ -1,7 +1,7 @@ name: New Region -description: Register a new region. +description: Register a new region. Internal CDK team use only. title: "Register new region: [region]" -labels: ["@aws-cdk/region-info", "feature-request", "p1", "effort/medium"] +labels: ["@aws-cdk/region-info", "feature-request", needs-triage, "effort/medium"] body: - type: input id: ROUTE_53_BUCKET_WEBSITE_ZONE_IDS diff --git a/.github/ISSUE_TEMPLATE/tracking.yml b/.github/ISSUE_TEMPLATE/tracking.yml index 0ecfc903b002c..798be3162f769 100644 --- a/.github/ISSUE_TEMPLATE/tracking.yml +++ b/.github/ISSUE_TEMPLATE/tracking.yml @@ -1,7 +1,7 @@ name: Tracking Issue -description: Add a module tracking issue (internal use only) +description: Add a module tracking issue. Internal CDK team use only. title: "Tracking: [service]" -labels: [management/tracking] +labels: [needs-triage, management/tracking] body: - type: markdown attributes: From abc78bfa613453185e59d5d9a17e5c5cfb5437b3 Mon Sep 17 00:00:00 2001 From: John Dukewich <37190801+jdukewich@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:00:08 -0400 Subject: [PATCH 08/12] feat(ec2): security group lookup via filters (#30625) ### Issue # (if applicable) Closes #30331. ### Reason for this change This will improve the security group lookup functionality for importing existing security groups into a CDK stack. ### Description of changes I added the ability to lookup existing security groups via more filters. Filters are supported by the [DescribeSecurityGroups API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html), and using these filters can be immensely useful for looking up existing security groups, especially if your account or organization follows predictable rules regarding things like security group tags. ### Description of how you validated changes I added unit tests similar to the ones that test the normal lookup by ID or name. ### 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* --- .../LookupStack.assets.json | 20 + .../LookupStack.template.json | 36 ++ ...efaultTestDeployAssert9466B7BF.assets.json | 19 + ...aultTestDeployAssert9466B7BF.template.json | 36 ++ .../StackWithSg.assets.json | 34 ++ .../StackWithSg.template.json | 233 +++++++++++ .../__entrypoint__.js | 155 +++++++ .../index.js | 1 + .../cdk.out | 1 + .../integ.json | 13 + .../manifest.json | 253 +++++++++++ .../tree.json | 392 ++++++++++++++++++ .../test/integ.security-group-lookup.ts | 56 +++ packages/aws-cdk-lib/aws-ec2/README.md | 12 +- .../aws-cdk-lib/aws-ec2/lib/security-group.ts | 57 ++- .../aws-ec2/test/security-group.test.ts | 24 ++ .../lib/cloud-assembly/context-queries.ts | 28 ++ .../schema/cloud-assembly.schema.json | 22 + .../schema/cloud-assembly.version.json | 2 +- .../lib/context-providers/security-groups.ts | 30 +- .../context-providers/security-groups.test.ts | 87 +++- 21 files changed, 1485 insertions(+), 26 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json new file mode 100644 index 0000000000000..fc94649590768 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json @@ -0,0 +1,20 @@ +{ + "version": "37.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "LookupStack.template.json", + "packaging": "file" + }, + "destinations": { + "12345678-test-region": { + "bucketName": "cdk-hnb659fds-assets-12345678-test-region", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "region": "test-region", + "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.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.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json new file mode 100644 index 0000000000000..e67d33537caf4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json @@ -0,0 +1,19 @@ +{ + "version": "37.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "SgLookupTestDefaultTestDeployAssert9466B7BF.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.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.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.security-group-lookup.js.snapshot/StackWithSg.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json new file mode 100644 index 0000000000000..a65bbb573ca89 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json @@ -0,0 +1,34 @@ +{ + "version": "37.0.0", + "files": { + "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1": { + "source": { + "path": "asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1", + "packaging": "zip" + }, + "destinations": { + "12345678-test-region": { + "bucketName": "cdk-hnb659fds-assets-12345678-test-region", + "objectKey": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.zip", + "region": "test-region", + "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" + } + } + }, + "e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9": { + "source": { + "path": "StackWithSg.template.json", + "packaging": "file" + }, + "destinations": { + "12345678-test-region": { + "bucketName": "cdk-hnb659fds-assets-12345678-test-region", + "objectKey": "e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9.json", + "region": "test-region", + "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json new file mode 100644 index 0000000000000..eefe64d08796d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json @@ -0,0 +1,233 @@ +{ + "Resources": { + "MyVpcF9F0CA6F": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "my-vpc-name" + } + ] + } + }, + "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "DefaultSecurityGroup" + ] + }, + "Account": "12345678" + }, + "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:test-region:12345678:security-group/", + { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", + "S3Key": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.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" + ] + }, + "MySgAFDC270F2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "StackWithSg/MySgA", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "myTag", + "Value": "my-value" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MySgB343D3C61": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "StackWithSg/MySgB", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "myTagKey", + "Value": "true" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MySgC50C8732C": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "my-description", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MySgDA51BA0C2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "ownerId description", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + } + }, + "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.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js new file mode 100644 index 0000000000000..02033f55cf612 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js @@ -0,0 +1,155 @@ +"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, + }; + const parsedUrl = url.parse(event.ResponseURL); + const loggingSafeUrl = `${parsedUrl.protocol}//${parsedUrl.hostname}/${parsedUrl.pathname}?***`; + exports.external.log('submit response to cloudformation', loggingSafeUrl, json); + const responseBody = JSON.stringify(json); + 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, requestBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, (response) => { + response.resume(); // Consume the response but don't care about it + if (!response.statusCode || response.statusCode >= 400) { + reject(new Error(`Unsuccessful HTTP response: ${response.statusCode}`)); + } + else { + resolve(); + } + }); + request.on('error', reject); + request.write(requestBody); + 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)); +} diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js new file mode 100644 index 0000000000000..013bcaffd8fe5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/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.security-group-lookup.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out new file mode 100644 index 0000000000000..079dd58c72d69 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"37.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json new file mode 100644 index 0000000000000..adc4aec587718 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "enableLookups": true, + "version": "37.0.0", + "testCases": { + "SgLookupTest/DefaultTest": { + "stacks": [ + "StackWithSg" + ], + "assertionStack": "SgLookupTest/DefaultTest/DeployAssert", + "assertionStackName": "SgLookupTestDefaultTestDeployAssert9466B7BF" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json new file mode 100644 index 0000000000000..2f8ff36aefa99 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json @@ -0,0 +1,253 @@ +{ + "version": "37.0.0", + "artifacts": { + "StackWithSg.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "StackWithSg.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "StackWithSg": { + "type": "aws:cloudformation:stack", + "environment": "aws://12345678/test-region", + "properties": { + "templateFile": "StackWithSg.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-deploy-role-12345678-test-region", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-cfn-exec-role-12345678-test-region", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-12345678-test-region/e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "StackWithSg.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "StackWithSg.assets" + ], + "metadata": { + "/StackWithSg/MyVpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcF9F0CA6F" + } + ], + "/StackWithSg/MyVpc/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62" + } + ], + "/StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/StackWithSg/MySgA/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MySgAFDC270F2" + } + ], + "/StackWithSg/MySgB/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MySgB343D3C61" + } + ], + "/StackWithSg/MySgC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MySgC50C8732C" + } + ], + "/StackWithSg/MySgD/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MySgDA51BA0C2" + } + ], + "/StackWithSg/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/StackWithSg/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "StackWithSg" + }, + "LookupStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "LookupStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "LookupStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://12345678/test-region", + "properties": { + "templateFile": "LookupStack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-deploy-role-12345678-test-region", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-cfn-exec-role-12345678-test-region", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-12345678-test-region/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "LookupStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "StackWithSg", + "LookupStack.assets" + ], + "metadata": { + "/LookupStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/LookupStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "LookupStack" + }, + "SgLookupTestDefaultTestDeployAssert9466B7BF.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SgLookupTestDefaultTestDeployAssert9466B7BF": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SgLookupTestDefaultTestDeployAssert9466B7BF.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": [ + "SgLookupTestDefaultTestDeployAssert9466B7BF.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": [ + "SgLookupTestDefaultTestDeployAssert9466B7BF.assets" + ], + "metadata": { + "/SgLookupTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SgLookupTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SgLookupTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + }, + "missing": [ + { + "key": "security-group:account=12345678:region=test-region:tags.myTag.0=my-value", + "provider": "security-group", + "props": { + "account": "12345678", + "region": "test-region", + "tags": { + "myTag": [ + "my-value" + ] + }, + "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" + } + }, + { + "key": "security-group:account=12345678:region=test-region:tagKeys.0=myTagKey", + "provider": "security-group", + "props": { + "account": "12345678", + "region": "test-region", + "tagKeys": [ + "myTagKey" + ], + "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" + } + }, + { + "key": "security-group:account=12345678:description=my-description:region=test-region", + "provider": "security-group", + "props": { + "account": "12345678", + "region": "test-region", + "description": "my-description", + "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" + } + }, + { + "key": "security-group:account=12345678:description=ownerId description:ownerId=12345678:region=test-region", + "provider": "security-group", + "props": { + "account": "12345678", + "region": "test-region", + "description": "ownerId description", + "ownerId": "12345678", + "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" + } + } + ] +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json new file mode 100644 index 0000000000000..bf8c406b81c9e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json @@ -0,0 +1,392 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "StackWithSg": { + "id": "StackWithSg", + "path": "StackWithSg", + "children": { + "MyVpc": { + "id": "MyVpc", + "path": "StackWithSg/MyVpc", + "children": { + "Resource": { + "id": "Resource", + "path": "StackWithSg/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": "my-vpc-name" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "StackWithSg/MyVpc/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "StackWithSg/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" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "MySgA": { + "id": "MySgA", + "path": "StackWithSg/MySgA", + "children": { + "Resource": { + "id": "Resource", + "path": "StackWithSg/MySgA/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "StackWithSg/MySgA", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "myTag", + "value": "my-value" + } + ], + "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" + } + }, + "MySgB": { + "id": "MySgB", + "path": "StackWithSg/MySgB", + "children": { + "Resource": { + "id": "Resource", + "path": "StackWithSg/MySgB/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "StackWithSg/MySgB", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "myTagKey", + "value": "true" + } + ], + "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" + } + }, + "MySgC": { + "id": "MySgC", + "path": "StackWithSg/MySgC", + "children": { + "Resource": { + "id": "Resource", + "path": "StackWithSg/MySgC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "my-description", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "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" + } + }, + "MySgD": { + "id": "MySgD", + "path": "StackWithSg/MySgD", + "children": { + "Resource": { + "id": "Resource", + "path": "StackWithSg/MySgD/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "ownerId description", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "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" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "StackWithSg/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "StackWithSg/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "LookupStack": { + "id": "LookupStack", + "path": "LookupStack", + "children": { + "SgFromLookupTags": { + "id": "SgFromLookupTags", + "path": "LookupStack/SgFromLookupTags", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "SgFromLookupTagKeys": { + "id": "SgFromLookupTagKeys", + "path": "LookupStack/SgFromLookupTagKeys", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "SgFromLookupDescription": { + "id": "SgFromLookupDescription", + "path": "LookupStack/SgFromLookupDescription", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "SgFromLookupOwnerId": { + "id": "SgFromLookupOwnerId", + "path": "LookupStack/SgFromLookupOwnerId", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "LookupStack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "LookupStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "SgLookupTest": { + "id": "SgLookupTest", + "path": "SgLookupTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "SgLookupTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "SgLookupTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "SgLookupTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "SgLookupTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "SgLookupTest/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.security-group-lookup.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts new file mode 100644 index 0000000000000..1030c57274991 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts @@ -0,0 +1,56 @@ +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; + +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +const app = new cdk.App(); + +const env = { + account: process.env.CDK_INTEG_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_INTEG_REGION || process.env.CDK_DEFAULT_REGION, +}; + +// Deploy the security groups to lookup +const stack = new cdk.Stack(app, 'StackWithSg', { env }); +const testVpc = new ec2.Vpc(stack, 'MyVpc', { + vpcName: 'my-vpc-name', + ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), + subnetConfiguration: [], + natGateways: 0, +}); +const testSgA = new ec2.SecurityGroup(stack, 'MySgA', { vpc: testVpc }); +cdk.Tags.of(testSgA).add('myTag', 'my-value'); +const testSgB = new ec2.SecurityGroup(stack, 'MySgB', { vpc: testVpc }); +cdk.Tags.of(testSgB).add('myTagKey', 'true'); +new ec2.SecurityGroup(stack, 'MySgC', { vpc: testVpc, description: 'my-description' }); +new ec2.SecurityGroup(stack, 'MySgD', { vpc: testVpc, description: 'ownerId description' }); + +// Now perform the lookups +const lookupStack = new cdk.Stack(app, 'LookupStack', { env }); +lookupStack.addDependency(stack); +ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupTags', { + tags: { + myTag: ['my-value'], + }, +}); + +ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupTagKeys', { + tagKeys: ['myTagKey'], +}); + +ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupDescription', { + description: 'my-description', +}); + +ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupOwnerId', { + description: 'ownerId description', + ownerId: process.env.CDK_INTEG_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, +}); + +new IntegTest(app, 'SgLookupTest', { + testCases: [stack], + enableLookups: true, +}); + +app.synth(); + diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index 686eb78ed2a3f..86e0fd78ee07c 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -843,13 +843,23 @@ Alternatively, use lookup methods to import security groups if you do not know t const sg = ec2.SecurityGroup.fromLookupByName(this, 'SecurityGroupLookup', 'security-group-name', vpc); ``` +You can perform lookups based on filter conditions detailed in the [API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html). +```ts +const sg = ec2.SecurityGroup.fromLookupByFilters(this, 'SecurityGroupLookup', { + ownerId: "012345678901", + description: "my description", + tagKeys: ["tagA", "tagB"], + tags: { tagC: ["valueC", "otherValueC"], tagD: ["valueD"] } +}); +``` + If the security group ID is known and configuration details are unknown, use method `SecurityGroup.fromLookupById` instead. This method will lookup property `allowAllOutbound` from the current configuration of the security group. ```ts const sg = ec2.SecurityGroup.fromLookupById(this, 'SecurityGroupLookup', 'sg-1234'); ``` -The result of `SecurityGroup.fromLookupByName` and `SecurityGroup.fromLookupById` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. +The result of `SecurityGroup.fromLookupByName`, `SecurityGroup.fromLookupById`, and `SecurityGroup.fromLookupByFilters` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. ### Cross Stack Connections diff --git a/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts b/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts index e774c1f9de3af..b9c75b7589350 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts @@ -387,6 +387,13 @@ export class SecurityGroup extends SecurityGroupBase { return this.fromLookupAttributes(scope, id, { securityGroupName, vpc }); } + /** + * Look up a security group by filters + */ + public static fromLookupByFilters(scope: Construct, id: string, filters: SecurityGroupLookupOptions) { + return this.fromLookupAttributes(scope, id, filters); + } + /** * Import an existing security group into this app. * @@ -434,7 +441,15 @@ export class SecurityGroup extends SecurityGroupBase { * Look up a security group. */ private static fromLookupAttributes(scope: Construct, id: string, options: SecurityGroupLookupOptions) { - if (Token.isUnresolved(options.securityGroupId) || Token.isUnresolved(options.securityGroupName) || Token.isUnresolved(options.vpc?.vpcId)) { + if ([ + options.securityGroupId, + options.securityGroupName, + options.vpc?.vpcId, + options.description, + options.ownerId, + options.tagKeys, + options.tags, + ].some(opt => Token.isUnresolved(opt))) { throw new Error('All arguments to look up a security group must be concrete (no Tokens)'); } @@ -444,6 +459,10 @@ export class SecurityGroup extends SecurityGroupBase { securityGroupId: options.securityGroupId, securityGroupName: options.securityGroupName, vpcId: options.vpc?.vpcId, + description: options.description, + ownerId: options.ownerId, + tagKeys: options.tagKeys, + tags: options.tags, }, dummyValue: { securityGroupId: 'sg-12345678', @@ -816,13 +835,13 @@ function isAllTrafficRule(rule: any) { * * Either `securityGroupName` or `securityGroupId` has to be specified. */ -interface SecurityGroupLookupOptions { +export interface SecurityGroupLookupOptions { /** * The name of the security group * * If given, will import the SecurityGroup with this name. * - * @default Don't filter on securityGroupName + * @default - Don't filter on securityGroupName */ readonly securityGroupName?: string; @@ -831,7 +850,7 @@ interface SecurityGroupLookupOptions { * * If given, will import the SecurityGroup with this ID. * - * @default Don't filter on securityGroupId + * @default - Don't filter on securityGroupId */ readonly securityGroupId?: string; @@ -840,7 +859,35 @@ interface SecurityGroupLookupOptions { * * If given, will filter the SecurityGroup based on the VPC. * - * @default Don't filter on VPC + * @default - Don't filter on VPC */ readonly vpc?: IVpc; + + /** + * Security group description + * + * @default - Don't filter on description + */ + readonly description?: string; + + /** + * Account ID of the owner of the security group + * + * @default - Don't filter on owner ID + */ + readonly ownerId?: string; + + /** + * The keys of tags assigned to the security group + * + * @default - Don't filter on tag keys + */ + readonly tagKeys?: string[]; + + /** + * The key/value combination of a tag assigned to the security group + * + * @default - Don't filter on tags + */ + readonly tags?: Record; } diff --git a/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts b/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts index 50e7f9ae5f224..cd98bd1689181 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts @@ -596,6 +596,30 @@ describe('security group lookup', () => { }); + test('can look up a security group by filters', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack', { + env: { + account: '1234', + region: 'us-east-1', + }, + }); + + // WHEN + const securityGroup = SecurityGroup.fromLookupByFilters(stack, 'SG1', { + ownerId: '012345678901', + description: 'my description', + tagKeys: ['tagA', 'tagB'], + tags: { tagC: ['valueC', 'otherValueC'], tagD: ['valueD'] }, + }); + + // THEN + expect(securityGroup.securityGroupId).toEqual('sg-12345678'); + expect(securityGroup.allowAllOutbound).toEqual(true); + + }); + test('can look up a security group and use it as a peer', () => { // GIVEN const app = new App(); diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts b/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts index bd35d023dfe69..92fd11f9ea376 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts +++ b/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts @@ -449,6 +449,34 @@ export interface SecurityGroupContextQuery { * @default - None */ readonly vpcId?: string; + + /** + * Security group description + * + * @default - None + */ + readonly description?: string; + + /** + * Account ID of the owner of the security group + * + * @default - None + */ + readonly ownerId?: string; + + /** + * The keys of tags assigned to the security group + * + * @default - None + */ + readonly tagKeys?: string[]; + + /** + * The key/value combination of a tag assigned to the security group + * + * @default - None + */ + readonly tags?: Record; } /** diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json index 279dfbe369073..2dc1ceae0d7d9 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json +++ b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json @@ -870,6 +870,25 @@ "vpcId": { "description": "VPC ID (Default - None)", "type": "string" + }, + "description": { + "description": "Security group description (Default - None)", + "type": "string" + }, + "ownerId": { + "description": "Account ID of the owner of the security group (Default - None)", + "type": "string" + }, + "tagKeys": { + "description": "The keys of tags assigned to the security group (Default - None)", + "type": "array", + "items": { + "type": "string" + } + }, + "tags": { + "description": "The key/value combination of a tag assigned to the security group (Default - None)", + "$ref": "#/definitions/Record" } }, "required": [ @@ -877,6 +896,9 @@ "region" ] }, + "Record": { + "type": "object" + }, "KeyContextQuery": { "description": "Query input for looking up a KMS Key", "type": "object", diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json index 1f0068d32659a..079dd58c72d69 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json +++ b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json @@ -1 +1 @@ -{"version":"36.0.0"} \ No newline at end of file +{"version":"37.0.0"} \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/security-groups.ts b/packages/aws-cdk/lib/context-providers/security-groups.ts index 19372df9af842..fa68fa4129e23 100644 --- a/packages/aws-cdk/lib/context-providers/security-groups.ts +++ b/packages/aws-cdk/lib/context-providers/security-groups.ts @@ -17,10 +17,6 @@ export class SecurityGroupContextProviderPlugin implements ContextProviderPlugin throw new Error('\'securityGroupId\' and \'securityGroupName\' can not be specified both when looking up a security group'); } - if (!args.securityGroupId && !args.securityGroupName) { - throw new Error('\'securityGroupId\' or \'securityGroupName\' must be specified to look up a security group'); - } - const options = { assumeRoleArn: args.lookupRoleArn }; const ec2 = (await this.aws.forEnvironment(cxapi.EnvironmentUtils.make(account, region), Mode.ForReading, options)).sdk.ec2(); @@ -37,6 +33,32 @@ export class SecurityGroupContextProviderPlugin implements ContextProviderPlugin Values: [args.securityGroupName], }); } + if (args.description) { + filters.push({ + Name: 'description', + Values: [args.description], + }); + } + if (args.tagKeys) { + filters.push({ + Name: 'tag-key', + Values: args.tagKeys, + }); + } + if (args.ownerId) { + filters.push({ + Name: 'owner-id', + Values: [args.ownerId], + }); + } + if (args.tags) { + Object.entries(args.tags).forEach(([key, values]) => { + filters.push({ + Name: `tag:${key}`, + Values: values, + }); + }); + } const response = await ec2.describeSecurityGroups({ GroupIds: args.securityGroupId ? [args.securityGroupId] : undefined, diff --git a/packages/aws-cdk/test/context-providers/security-groups.test.ts b/packages/aws-cdk/test/context-providers/security-groups.test.ts index c7bdc586ad7bc..2477336d98b93 100644 --- a/packages/aws-cdk/test/context-providers/security-groups.test.ts +++ b/packages/aws-cdk/test/context-providers/security-groups.test.ts @@ -1,7 +1,9 @@ +import * as AWS from 'aws-sdk-mock'; /* eslint-disable import/order */ import * as aws from 'aws-sdk'; -import * as AWS from 'aws-sdk-mock'; -import { hasAllTrafficEgress, SecurityGroupContextProviderPlugin } from '../../lib/context-providers/security-groups'; + +import { SecurityGroupContextProviderPlugin, hasAllTrafficEgress } from '../../lib/context-providers/security-groups'; + import { MockSdkProvider } from '../util/mock-sdk'; AWS.setSDK(require.resolve('aws-sdk')); @@ -226,6 +228,74 @@ describe('security group context provider plugin', () => { expect(res.allowAllOutbound).toEqual(true); }); + test('looks up by security group description, owner id, tag keys, and tags', async () => { + // GIVEN + const provider = new SecurityGroupContextProviderPlugin(mockSDK); + + AWS.mock('EC2', 'describeSecurityGroups', (_params: aws.EC2.DescribeSecurityGroupsRequest, cb: AwsCallback) => { + expect(_params).toEqual({ + GroupIds: undefined, + Filters: [ + { + Name: 'description', + Values: ['my description'], + }, + { + Name: 'tag-key', + Values: ['tagA', 'tagB'], + }, + { + Name: 'owner-id', + Values: ['012345678901'], + }, + { + Name: 'tag:tagC', + Values: ['valueC', 'otherValueC'], + }, + { + Name: 'tag:tagD', + Values: ['valueD'], + }, + ], + }); + cb(null, { + SecurityGroups: [ + { + GroupId: 'sg-1234', + IpPermissionsEgress: [ + { + IpProtocol: '-1', + IpRanges: [ + { CidrIp: '0.0.0.0/0' }, + ], + }, + { + IpProtocol: '-1', + Ipv6Ranges: [ + { CidrIpv6: '::/0' }, + ], + }, + ], + }, + ], + }); + }); + + // WHEN + const res = await provider.getValue({ + account: '1234', + region: 'us-east-1', + ownerId: '012345678901', + description: 'my description', + tagKeys: ['tagA', 'tagB'], + tags: { tagC: ['valueC', 'otherValueC'], tagD: ['valueD'] }, + }); + + // THEN + expect(res.securityGroupId).toEqual('sg-1234'); + expect(res.allowAllOutbound).toEqual(true); + }); + test('detects non all-outbound egress', async () => { // GIVEN const provider = new SecurityGroupContextProviderPlugin(mockSDK); @@ -319,19 +389,6 @@ describe('security group context provider plugin', () => { ).rejects.toThrow(/\'securityGroupId\' and \'securityGroupName\' can not be specified both when looking up a security group/i); }); - test('errors when neither securityGroupId nor securityGroupName are specified', async () => { - // GIVEN - const provider = new SecurityGroupContextProviderPlugin(mockSDK); - - // WHEN - await expect( - provider.getValue({ - account: '1234', - region: 'us-east-1', - }), - ).rejects.toThrow(/\'securityGroupId\' or \'securityGroupName\' must be specified to look up a security group/i); - }); - test('identifies allTrafficEgress from SecurityGroup permissions', () => { expect( hasAllTrafficEgress({ From d5a19bb3eeda50a7b08e2b814dfcf76e6ac21fdc Mon Sep 17 00:00:00 2001 From: Lee Date: Thu, 8 Aug 2024 19:44:53 +0100 Subject: [PATCH 09/12] feat(dynamodb): adding on-demand-throughput to table (#30725) ### Issue # (if applicable) Closes #30091 ### Reason for this change New DynamoDB feature that was just released ### Description of changes Added `maxReadRequestUnits` and `maxWriteRequestUnits` for PAY_PER_REQUEST tables ### Description of how you validated changes Tests on `integ.dynamodb.ondemand.ts` ### 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-global-table-v2.assets.json | 20 ++ .../aws-cdk-global-table-v2.template.json | 117 +++++++ ...efaultTestDeployAssertF1A4FD2A.assets.json | 19 + ...aultTestDeployAssertF1A4FD2A.template.json | 36 ++ .../cdk.out | 1 + .../integ.json | 16 + .../manifest.json | 121 +++++++ .../tree.json | 196 +++++++++++ .../integ.dynamodb-v2.max-request-units.ts | 41 +++ .../aws-cdk-global-table.assets.json | 20 ++ .../aws-cdk-global-table.template.json | 247 +++++++++++++ ...efaultTestDeployAssertA2A9E81F.assets.json | 19 + ...aultTestDeployAssertA2A9E81F.template.json | 36 ++ .../cdk.out | 1 + .../integ.json | 16 + .../manifest.json | 133 +++++++ .../tree.json | 328 ++++++++++++++++++ .../test/integ.dynamodb-v2.ondemand.ts | 60 ++++ .../integ.json | 10 - .../tree.json | 2 +- .../aws-cdk-dynamodb.assets.json | 6 +- .../aws-cdk-dynamodb.template.json | 70 ++-- .../cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 17 +- .../tree.json | 140 ++++---- .../test/integ.dynamodb.ondemand.ts | 4 + packages/aws-cdk-lib/aws-dynamodb/README.md | 13 + .../aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md | 11 + .../aws-cdk-lib/aws-dynamodb/lib/billing.ts | 27 +- .../aws-cdk-lib/aws-dynamodb/lib/table-v2.ts | 75 +++- .../aws-cdk-lib/aws-dynamodb/lib/table.ts | 51 +++ .../aws-dynamodb/test/billing.test.ts | 26 ++ .../aws-dynamodb/test/dynamodb.test.ts | 69 ++++ .../aws-dynamodb/test/table-v2.test.ts | 155 +++++++++ 35 files changed, 1987 insertions(+), 120 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.ts create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.assets.json new file mode 100644 index 0000000000000..a07133b76fc7d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.assets.json @@ -0,0 +1,20 @@ +{ + "version": "36.0.0", + "files": { + "f6c3259c52a142bbcf580bb47c14037f7819c4cebfb51d6c8586c38bc79c5509": { + "source": { + "path": "aws-cdk-global-table-v2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-eu-west-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1", + "objectKey": "f6c3259c52a142bbcf580bb47c14037f7819c4cebfb51d6c8586c38bc79c5509.json", + "region": "eu-west-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-eu-west-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.template.json new file mode 100644 index 0000000000000..35b13b4c70e59 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/aws-cdk-global-table-v2.template.json @@ -0,0 +1,117 @@ +{ + "Resources": { + "GlobalTableV212B4E024": { + "Type": "AWS::DynamoDB::GlobalTable", + "Properties": { + "AttributeDefinitions": [ + { + "AttributeName": "pk", + "AttributeType": "S" + }, + { + "AttributeName": "sk", + "AttributeType": "N" + } + ], + "BillingMode": "PAY_PER_REQUEST", + "GlobalSecondaryIndexes": [ + { + "IndexName": "gsi2", + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + } + ], + "Projection": { + "ProjectionType": "ALL" + }, + "WriteOnDemandThroughputSettings": { + "MaxWriteRequestUnits": 2001 + } + } + ], + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + }, + { + "AttributeName": "sk", + "KeyType": "RANGE" + } + ], + "Replicas": [ + { + "GlobalSecondaryIndexes": [ + { + "IndexName": "gsi2", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 2001 + } + } + ], + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 222 + }, + "Region": "us-east-1" + }, + { + "GlobalSecondaryIndexes": [ + { + "IndexName": "gsi2", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 2001 + } + } + ], + "Region": "eu-west-1" + } + ], + "StreamSpecification": { + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "TableName": "my-global-table-v2", + "WriteOnDemandThroughputSettings": { + "MaxWriteRequestUnits": 10 + } + }, + "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-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets.json new file mode 100644 index 0000000000000..02772f0375026 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.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-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.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-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.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-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/integ.json new file mode 100644 index 0000000000000..d1446d6169277 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/integ.json @@ -0,0 +1,16 @@ +{ + "version": "36.0.0", + "testCases": { + "aws-cdk-global-table-integ-v2/DefaultTest": { + "stacks": [ + "aws-cdk-global-table-v2" + ], + "regions": [ + "eu-west-1" + ], + "stackUpdateWorkflow": false, + "assertionStack": "aws-cdk-global-table-integ-v2/DefaultTest/DeployAssert", + "assertionStackName": "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/manifest.json new file mode 100644 index 0000000000000..0377675ebe18a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/manifest.json @@ -0,0 +1,121 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-global-table-v2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-global-table-v2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-global-table-v2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/eu-west-1", + "properties": { + "templateFile": "aws-cdk-global-table-v2.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-eu-west-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-eu-west-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/f6c3259c52a142bbcf580bb47c14037f7819c4cebfb51d6c8586c38bc79c5509.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-global-table-v2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-eu-west-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-global-table-v2.assets" + ], + "metadata": { + "/aws-cdk-global-table-v2/GlobalTableV2": [ + { + "type": "aws:cdk:hasPhysicalName", + "data": { + "Ref": "GlobalTableV212B4E024" + } + } + ], + "/aws-cdk-global-table-v2/GlobalTableV2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "GlobalTableV212B4E024" + } + ], + "/aws-cdk-global-table-v2/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-global-table-v2/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-global-table-v2" + }, + "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.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": [ + "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.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": [ + "awscdkglobaltableintegv2DefaultTestDeployAssertF1A4FD2A.assets" + ], + "metadata": { + "/aws-cdk-global-table-integ-v2/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-global-table-integ-v2/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-global-table-integ-v2/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-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/tree.json new file mode 100644 index 0000000000000..574bf311dffef --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.js.snapshot/tree.json @@ -0,0 +1,196 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-global-table-v2": { + "id": "aws-cdk-global-table-v2", + "path": "aws-cdk-global-table-v2", + "children": { + "GlobalTableV2": { + "id": "GlobalTableV2", + "path": "aws-cdk-global-table-v2/GlobalTableV2", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-global-table-v2/GlobalTableV2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::GlobalTable", + "aws:cdk:cloudformation:props": { + "attributeDefinitions": [ + { + "attributeName": "pk", + "attributeType": "S" + }, + { + "attributeName": "sk", + "attributeType": "N" + } + ], + "billingMode": "PAY_PER_REQUEST", + "globalSecondaryIndexes": [ + { + "indexName": "gsi2", + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + } + ], + "projection": { + "projectionType": "ALL" + }, + "writeOnDemandThroughputSettings": { + "maxWriteRequestUnits": 2001 + } + } + ], + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + }, + { + "attributeName": "sk", + "keyType": "RANGE" + } + ], + "replicas": [ + { + "region": "us-east-1", + "globalSecondaryIndexes": [ + { + "indexName": "gsi2", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 2001 + } + } + ], + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 222 + } + }, + { + "region": "eu-west-1", + "globalSecondaryIndexes": [ + { + "indexName": "gsi2", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 2001 + } + } + ] + } + ], + "streamSpecification": { + "streamViewType": "NEW_AND_OLD_IMAGES" + }, + "tableName": "my-global-table-v2", + "writeOnDemandThroughputSettings": { + "maxWriteRequestUnits": 10 + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.CfnGlobalTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.TableBaseV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-global-table-v2/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-global-table-v2/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-global-table-integ-v2": { + "id": "aws-cdk-global-table-integ-v2", + "path": "aws-cdk-global-table-integ-v2", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "aws-cdk-global-table-integ-v2/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-global-table-integ-v2/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "aws-cdk-global-table-integ-v2/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-global-table-integ-v2/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-global-table-integ-v2/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-dynamodb/test/integ.dynamodb-v2.max-request-units.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.ts new file mode 100644 index 0000000000000..794266767b156 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.max-request-units.ts @@ -0,0 +1,41 @@ +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { AttributeType, Billing, TableV2 } from 'aws-cdk-lib/aws-dynamodb'; +import { Construct } from 'constructs'; + +class TestStack extends Stack { + public constructor(scope: Construct, id: string, props: StackProps) { + super(scope, id, props); + + new TableV2(this, 'GlobalTableV2', { + tableName: 'my-global-table-v2', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + sortKey: { name: 'sk', type: AttributeType.NUMBER }, + billing: Billing.onDemand({ + maxWriteRequestUnits: 10, + }), + removalPolicy: RemovalPolicy.DESTROY, + replicas: [ + { + region: 'us-east-1', + maxReadRequestUnits: 222, + }, + ], + globalSecondaryIndexes: [ + { + indexName: 'gsi2', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + maxReadRequestUnits: 2001, + maxWriteRequestUnits: 2001, + }, + ], + }); + } +} + +const app = new App(); +new IntegTest(app, 'aws-cdk-global-table-integ-v2', { + testCases: [new TestStack(app, 'aws-cdk-global-table-v2', { env: { region: 'eu-west-1' } })], + regions: ['eu-west-1'], + stackUpdateWorkflow: false, +}); \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.assets.json new file mode 100644 index 0000000000000..aa94a2c7845ca --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.assets.json @@ -0,0 +1,20 @@ +{ + "version": "36.0.0", + "files": { + "cc5278f2745ed14e48839e10ba3e84d52a026101a039e164e937d90f16b69c34": { + "source": { + "path": "aws-cdk-global-table.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "cc5278f2745ed14e48839e10ba3e84d52a026101a039e164e937d90f16b69c34.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.template.json new file mode 100644 index 0000000000000..e1e71ad2043c7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/aws-cdk-global-table.template.json @@ -0,0 +1,247 @@ +{ + "Resources": { + "Stream790BDEE4": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "RetentionPeriodHours": 24, + "ShardCount": 1, + "StreamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "GlobalTable89F068B2": { + "Type": "AWS::DynamoDB::GlobalTable", + "Properties": { + "AttributeDefinitions": [ + { + "AttributeName": "pk", + "AttributeType": "S" + }, + { + "AttributeName": "sk", + "AttributeType": "N" + } + ], + "BillingMode": "PAY_PER_REQUEST", + "GlobalSecondaryIndexes": [ + { + "IndexName": "gsi1", + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + } + ], + "Projection": { + "ProjectionType": "ALL" + } + }, + { + "IndexName": "gsi2", + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + } + ], + "Projection": { + "ProjectionType": "ALL" + }, + "WriteOnDemandThroughputSettings": { + "MaxWriteRequestUnits": 2001 + } + } + ], + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + }, + { + "AttributeName": "sk", + "KeyType": "RANGE" + } + ], + "LocalSecondaryIndexes": [ + { + "IndexName": "lsi", + "KeySchema": [ + { + "AttributeName": "pk", + "KeyType": "HASH" + }, + { + "AttributeName": "sk", + "KeyType": "RANGE" + } + ], + "Projection": { + "ProjectionType": "ALL" + } + } + ], + "Replicas": [ + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "GlobalSecondaryIndexes": [ + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "IndexName": "gsi1", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 1002 + } + }, + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "IndexName": "gsi2", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 2001 + } + } + ], + "PointInTimeRecoverySpecification": { + "PointInTimeRecoveryEnabled": true + }, + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 222 + }, + "Region": "eu-west-1", + "TableClass": "STANDARD_INFREQUENT_ACCESS" + }, + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "GlobalSecondaryIndexes": [ + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "IndexName": "gsi1", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 1002 + } + }, + { + "ContributorInsightsSpecification": { + "Enabled": true + }, + "IndexName": "gsi2", + "ReadOnDemandThroughputSettings": { + "MaxReadRequestUnits": 2001 + } + } + ], + "KinesisStreamSpecification": { + "StreamArn": { + "Fn::GetAtt": [ + "Stream790BDEE4", + "Arn" + ] + } + }, + "PointInTimeRecoverySpecification": { + "PointInTimeRecoveryEnabled": true + }, + "Region": "us-east-1", + "TableClass": "STANDARD_INFREQUENT_ACCESS", + "Tags": [ + { + "Key": "primaryTableTagKey", + "Value": "primaryTableTagValue" + } + ] + } + ], + "SSESpecification": { + "SSEEnabled": true, + "SSEType": "KMS" + }, + "StreamSpecification": { + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "TableName": "my-global-table", + "TimeToLiveSpecification": { + "AttributeName": "attr", + "Enabled": true + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Conditions": { + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-north-1" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-northwest-1" + ] + } + ] + } + }, + "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-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets.json new file mode 100644 index 0000000000000..0a9ffc385b09a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.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-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.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-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.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-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/integ.json new file mode 100644 index 0000000000000..15437c63539c9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/integ.json @@ -0,0 +1,16 @@ +{ + "version": "36.0.0", + "testCases": { + "aws-cdk-global-table-integ/DefaultTest": { + "stacks": [ + "aws-cdk-global-table" + ], + "regions": [ + "us-east-1" + ], + "stackUpdateWorkflow": false, + "assertionStack": "aws-cdk-global-table-integ/DefaultTest/DeployAssert", + "assertionStackName": "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/manifest.json new file mode 100644 index 0000000000000..f36374c4697b1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/manifest.json @@ -0,0 +1,133 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-global-table.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-global-table.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-global-table": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-east-1", + "properties": { + "templateFile": "aws-cdk-global-table.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/cc5278f2745ed14e48839e10ba3e84d52a026101a039e164e937d90f16b69c34.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-global-table.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-east-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-global-table.assets" + ], + "metadata": { + "/aws-cdk-global-table/Stream/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stream790BDEE4" + } + ], + "/aws-cdk-global-table/AwsCdkKinesisEncryptedStreamsUnsupportedRegions": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions" + } + ], + "/aws-cdk-global-table/GlobalTable": [ + { + "type": "aws:cdk:hasPhysicalName", + "data": { + "Ref": "GlobalTable89F068B2" + } + } + ], + "/aws-cdk-global-table/GlobalTable/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "GlobalTable89F068B2" + } + ], + "/aws-cdk-global-table/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-global-table/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-global-table" + }, + "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.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": [ + "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.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": [ + "awscdkglobaltableintegDefaultTestDeployAssertA2A9E81F.assets" + ], + "metadata": { + "/aws-cdk-global-table-integ/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-global-table-integ/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-global-table-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-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/tree.json new file mode 100644 index 0000000000000..963c19fb401dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.js.snapshot/tree.json @@ -0,0 +1,328 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-global-table": { + "id": "aws-cdk-global-table", + "path": "aws-cdk-global-table", + "children": { + "Stream": { + "id": "Stream", + "path": "aws-cdk-global-table/Stream", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-global-table/Stream/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::Stream", + "aws:cdk:cloudformation:props": { + "retentionPeriodHours": 24, + "shardCount": 1, + "streamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnStream", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.Stream", + "version": "0.0.0" + } + }, + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "id": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "path": "aws-cdk-global-table/AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnCondition", + "version": "0.0.0" + } + }, + "GlobalTable": { + "id": "GlobalTable", + "path": "aws-cdk-global-table/GlobalTable", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-global-table/GlobalTable/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::GlobalTable", + "aws:cdk:cloudformation:props": { + "attributeDefinitions": [ + { + "attributeName": "pk", + "attributeType": "S" + }, + { + "attributeName": "sk", + "attributeType": "N" + } + ], + "billingMode": "PAY_PER_REQUEST", + "globalSecondaryIndexes": [ + { + "indexName": "gsi1", + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + } + ], + "projection": { + "projectionType": "ALL" + } + }, + { + "indexName": "gsi2", + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + } + ], + "projection": { + "projectionType": "ALL" + }, + "writeOnDemandThroughputSettings": { + "maxWriteRequestUnits": 2001 + } + } + ], + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + }, + { + "attributeName": "sk", + "keyType": "RANGE" + } + ], + "localSecondaryIndexes": [ + { + "indexName": "lsi", + "keySchema": [ + { + "attributeName": "pk", + "keyType": "HASH" + }, + { + "attributeName": "sk", + "keyType": "RANGE" + } + ], + "projection": { + "projectionType": "ALL" + } + } + ], + "replicas": [ + { + "region": "eu-west-1", + "globalSecondaryIndexes": [ + { + "indexName": "gsi1", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 1002 + }, + "contributorInsightsSpecification": { + "enabled": true + } + }, + { + "indexName": "gsi2", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 2001 + }, + "contributorInsightsSpecification": { + "enabled": true + } + } + ], + "tableClass": "STANDARD_INFREQUENT_ACCESS", + "contributorInsightsSpecification": { + "enabled": true + }, + "pointInTimeRecoverySpecification": { + "pointInTimeRecoveryEnabled": true + }, + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 222 + } + }, + { + "region": "us-east-1", + "globalSecondaryIndexes": [ + { + "indexName": "gsi1", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 1002 + }, + "contributorInsightsSpecification": { + "enabled": true + } + }, + { + "indexName": "gsi2", + "readOnDemandThroughputSettings": { + "maxReadRequestUnits": 2001 + }, + "contributorInsightsSpecification": { + "enabled": true + } + } + ], + "tableClass": "STANDARD_INFREQUENT_ACCESS", + "kinesisStreamSpecification": { + "streamArn": { + "Fn::GetAtt": [ + "Stream790BDEE4", + "Arn" + ] + } + }, + "contributorInsightsSpecification": { + "enabled": true + }, + "pointInTimeRecoverySpecification": { + "pointInTimeRecoveryEnabled": true + }, + "tags": [ + { + "key": "primaryTableTagKey", + "value": "primaryTableTagValue" + } + ] + } + ], + "sseSpecification": { + "sseEnabled": true, + "sseType": "KMS" + }, + "streamSpecification": { + "streamViewType": "NEW_AND_OLD_IMAGES" + }, + "tableName": "my-global-table", + "timeToLiveSpecification": { + "attributeName": "attr", + "enabled": true + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.CfnGlobalTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.TableBaseV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-global-table/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-global-table/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-cdk-global-table-integ": { + "id": "aws-cdk-global-table-integ", + "path": "aws-cdk-global-table-integ", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "aws-cdk-global-table-integ/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-global-table-integ/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "aws-cdk-global-table-integ/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-global-table-integ/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-global-table-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-dynamodb/test/integ.dynamodb-v2.ondemand.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.ts new file mode 100644 index 0000000000000..c2070e0b45754 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.ondemand.ts @@ -0,0 +1,60 @@ +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { AttributeType, Billing, TableV2, TableClass, TableEncryptionV2 } from 'aws-cdk-lib/aws-dynamodb'; +import { Stream } from 'aws-cdk-lib/aws-kinesis'; +import { Construct } from 'constructs'; + +class TestStack extends Stack { + public constructor(scope: Construct, id: string, props: StackProps) { + super(scope, id, props); + + const stream = new Stream(this, 'Stream'); + + new TableV2(this, 'GlobalTable', { + tableName: 'my-global-table', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + sortKey: { name: 'sk', type: AttributeType.NUMBER }, + billing: Billing.onDemand(), + encryption: TableEncryptionV2.awsManagedKey(), + contributorInsights: true, + pointInTimeRecovery: true, + tableClass: TableClass.STANDARD_INFREQUENT_ACCESS, + timeToLiveAttribute: 'attr', + removalPolicy: RemovalPolicy.DESTROY, + kinesisStream: stream, + replicas: [ + { + region: 'eu-west-1', + maxReadRequestUnits: 222, + }, + ], + globalSecondaryIndexes: [ + { + indexName: 'gsi1', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + maxReadRequestUnits: 1002, + }, + { + indexName: 'gsi2', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + maxReadRequestUnits: 2001, + maxWriteRequestUnits: 2001, + }, + ], + localSecondaryIndexes: [ + { + indexName: 'lsi', + sortKey: { name: 'sk', type: AttributeType.NUMBER }, + }, + ], + tags: [{ key: 'primaryTableTagKey', value: 'primaryTableTagValue' }], + }); + } +} + +const app = new App(); +new IntegTest(app, 'aws-cdk-global-table-integ', { + testCases: [new TestStack(app, 'aws-cdk-global-table', { env: { region: 'us-east-1' } })], + regions: ['us-east-1'], + stackUpdateWorkflow: false, +}); \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/integ.json index 32e11a1d2250a..5e8e335699b08 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/integ.json @@ -5,16 +5,6 @@ "stacks": [ "ResourcePolicyTest-v2" ], - "regions": [ - "us-east-1" - ], - "cdkCommandOptions": { - "deploy": { - "args": { - "rollback": true - } - } - }, "assertionStack": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert", "assertionStackName": "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/tree.json index 3a0a1c50405d4..8417b42605972 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.js.snapshot/tree.json @@ -71,7 +71,7 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_dynamodb.TableV2", + "fqn": "aws-cdk-lib.aws_dynamodb.TableBaseV2", "version": "0.0.0" } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.assets.json index fd6b84f880be7..a06498ad4deee 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "36.0.0", "files": { - "6721dc6f360c620369b9c3be4b289ff536e0faa87f39bac615b56ff31b2c609e": { + "4413d3171770b8ef5d6566130e7d33ddf852ba9ac51a59b9aea634446217bb3f": { "source": { "path": "aws-cdk-dynamodb.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6721dc6f360c620369b9c3be4b289ff536e0faa87f39bac615b56ff31b2c609e.json", + "objectKey": "4413d3171770b8ef5d6566130e7d33ddf852ba9ac51a59b9aea634446217bb3f.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-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.template.json index 4b943cf19b09d..6c7b3cd8fad33 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/aws-cdk-dynamodb.template.json @@ -3,19 +3,23 @@ "TableCD117FA1": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ + "AttributeDefinitions": [ { "AttributeName": "hashKey", - "KeyType": "HASH" + "AttributeType": "S" } ], - "AttributeDefinitions": [ + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ { "AttributeName": "hashKey", - "AttributeType": "S" + "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST" + "OnDemandThroughput": { + "MaxReadRequestUnits": 100, + "MaxWriteRequestUnits": 200 + } }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -23,16 +27,6 @@ "TableWithGlobalAndLocalSecondaryIndexBC540710": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - }, - { - "AttributeName": "sortKey", - "KeyType": "RANGE" - } - ], "AttributeDefinitions": [ { "AttributeName": "hashKey", @@ -65,6 +59,10 @@ "KeyType": "HASH" } ], + "OnDemandThroughput": { + "MaxReadRequestUnits": 100, + "MaxWriteRequestUnits": 100 + }, "Projection": { "ProjectionType": "ALL" } @@ -146,6 +144,16 @@ } } ], + "KeySchema": [ + { + "AttributeName": "hashKey", + "KeyType": "HASH" + }, + { + "AttributeName": "sortKey", + "KeyType": "RANGE" + } + ], "LocalSecondaryIndexes": [ { "IndexName": "LSI-PartitionAndTableSortKey", @@ -250,12 +258,6 @@ "TableWithGlobalSecondaryIndexCC8E841E": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - } - ], "AttributeDefinitions": [ { "AttributeName": "hashKey", @@ -280,6 +282,12 @@ "ProjectionType": "ALL" } } + ], + "KeySchema": [ + { + "AttributeName": "hashKey", + "KeyType": "HASH" + } ] }, "UpdateReplacePolicy": "Delete", @@ -288,16 +296,6 @@ "TableWithLocalSecondaryIndex4DA3D08F": { "Type": "AWS::DynamoDB::Table", "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - }, - { - "AttributeName": "sortKey", - "KeyType": "RANGE" - } - ], "AttributeDefinitions": [ { "AttributeName": "hashKey", @@ -313,6 +311,16 @@ } ], "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ + { + "AttributeName": "hashKey", + "KeyType": "HASH" + }, + { + "AttributeName": "sortKey", + "KeyType": "RANGE" + } + ], "LocalSecondaryIndexes": [ { "IndexName": "LSI-PartitionAndSortKey", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/cdk.out index 588d7b269d34f..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/integ.json index 8c1bf3f2a284a..41061cbfbe3ba 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "36.0.0", "testCases": { "integ.dynamodb.ondemand": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/manifest.json index fda20497ff2a4..46a693620203b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "36.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-dynamodb.assets": { "type": "cdk:asset-manifest", "properties": { @@ -20,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "aws-cdk-dynamodb.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}/6721dc6f360c620369b9c3be4b289ff536e0faa87f39bac615b56ff31b2c609e.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4413d3171770b8ef5d6566130e7d33ddf852ba9ac51a59b9aea634446217bb3f.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -77,6 +72,12 @@ ] }, "displayName": "aws-cdk-dynamodb" + }, + "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-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/tree.json index e5ea52068becf..c149e06017f7a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-dynamodb": { "id": "aws-cdk-dynamodb", "path": "aws-cdk-dynamodb", @@ -26,23 +18,27 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", "aws:cdk:cloudformation:props": { - "keySchema": [ + "attributeDefinitions": [ { "attributeName": "hashKey", - "keyType": "HASH" + "attributeType": "S" } ], - "attributeDefinitions": [ + "billingMode": "PAY_PER_REQUEST", + "keySchema": [ { "attributeName": "hashKey", - "attributeType": "S" + "keyType": "HASH" } ], - "billingMode": "PAY_PER_REQUEST" + "onDemandThroughput": { + "maxReadRequestUnits": 100, + "maxWriteRequestUnits": 200 + } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "fqn": "aws-cdk-lib.aws_dynamodb.CfnTable", "version": "0.0.0" } }, @@ -50,13 +46,13 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/Table/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", + "fqn": "aws-cdk-lib.aws_dynamodb.Table", "version": "0.0.0" } }, @@ -70,16 +66,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - }, - { - "attributeName": "sortKey", - "keyType": "RANGE" - } - ], "attributeDefinitions": [ { "attributeName": "hashKey", @@ -114,6 +100,10 @@ ], "projection": { "projectionType": "ALL" + }, + "onDemandThroughput": { + "maxReadRequestUnits": 100, + "maxWriteRequestUnits": 100 } }, { @@ -193,6 +183,16 @@ } } ], + "keySchema": [ + { + "attributeName": "hashKey", + "keyType": "HASH" + }, + { + "attributeName": "sortKey", + "keyType": "RANGE" + } + ], "localSecondaryIndexes": [ { "indexName": "LSI-PartitionAndTableSortKey", @@ -293,7 +293,7 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "fqn": "aws-cdk-lib.aws_dynamodb.CfnTable", "version": "0.0.0" } }, @@ -301,13 +301,13 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalAndLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", + "fqn": "aws-cdk-lib.aws_dynamodb.Table", "version": "0.0.0" } }, @@ -321,12 +321,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - } - ], "attributeDefinitions": [ { "attributeName": "hashKey", @@ -351,11 +345,17 @@ "projectionType": "ALL" } } + ], + "keySchema": [ + { + "attributeName": "hashKey", + "keyType": "HASH" + } ] } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "fqn": "aws-cdk-lib.aws_dynamodb.CfnTable", "version": "0.0.0" } }, @@ -363,13 +363,13 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", + "fqn": "aws-cdk-lib.aws_dynamodb.Table", "version": "0.0.0" } }, @@ -383,16 +383,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - }, - { - "attributeName": "sortKey", - "keyType": "RANGE" - } - ], "attributeDefinitions": [ { "attributeName": "hashKey", @@ -408,6 +398,16 @@ } ], "billingMode": "PAY_PER_REQUEST", + "keySchema": [ + { + "attributeName": "hashKey", + "keyType": "HASH" + }, + { + "attributeName": "sortKey", + "keyType": "RANGE" + } + ], "localSecondaryIndexes": [ { "indexName": "LSI-PartitionAndSortKey", @@ -429,7 +429,7 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "fqn": "aws-cdk-lib.aws_dynamodb.CfnTable", "version": "0.0.0" } }, @@ -437,26 +437,50 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", + "fqn": "aws-cdk-lib.aws_dynamodb.Table", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-dynamodb/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-dynamodb/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "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-dynamodb/test/integ.dynamodb.ondemand.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.ts index 5a82c86155d65..e28fe9af89c43 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb.ondemand.ts @@ -45,6 +45,8 @@ new Table(stack, TABLE, { billingMode: BillingMode.PAY_PER_REQUEST, partitionKey: TABLE_PARTITION_KEY, removalPolicy: RemovalPolicy.DESTROY, + maxReadRequestUnits: 100, + maxWriteRequestUnits: 200, }); const tableWithGlobalAndLocalSecondaryIndex = new Table(stack, TABLE_WITH_GLOBAL_AND_LOCAL_SECONDARY_INDEX, { @@ -63,6 +65,8 @@ Tags.of(tableWithGlobalAndLocalSecondaryIndex).add('Environment', 'Production'); tableWithGlobalAndLocalSecondaryIndex.addGlobalSecondaryIndex({ indexName: GSI_TEST_CASE_1, partitionKey: GSI_PARTITION_KEY, + maxReadRequestUnits: 100, + maxWriteRequestUnits: 100, }); tableWithGlobalAndLocalSecondaryIndex.addGlobalSecondaryIndex({ indexName: GSI_TEST_CASE_2, diff --git a/packages/aws-cdk-lib/aws-dynamodb/README.md b/packages/aws-cdk-lib/aws-dynamodb/README.md index 83d3e35c7d2f2..24e09c418b6ae 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/README.md +++ b/packages/aws-cdk-lib/aws-dynamodb/README.md @@ -148,6 +148,7 @@ Note: You can create an instance of the `TableV2` construct with as many `replic The `TableV2` construct can be configured with on-demand or provisioned billing: * On-demand - The default option. This is a flexible billing option capable of serving requests without capacity planning. The billing mode will be `PAY_PER_REQUEST`. +* You can optionally specify the `maxReadRequestUnits` or `maxWriteRequestUnits` on individual tables and associated global secondary indexes (GSIs). When you configure maximum throughput for an on-demand table, throughput requests that exceed the maximum amount specified will be throttled. * Provisioned - Specify the `readCapacity` and `writeCapacity` that you need for your application. The billing mode will be `PROVISIONED`. Capacity can be configured using one of the following modes: * Fixed - provisioned throughput capacity is configured with a fixed number of I/O operations per second. * Autoscaled - provisioned throughput capacity is dynamically adjusted on your behalf in response to actual traffic patterns. @@ -163,6 +164,18 @@ const table = new dynamodb.TableV2(this, 'Table', { }) ``` +The following example shows how to configure `TableV2` with on-demand billing with optional maximum throughput configured: + +```ts +const table = new dynamodb.TableV2(this, 'Table', { + partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING }, + billing: dynamodb.Billing.onDemand({ + maxReadRequestUnits: 100, + maxWriteRequestUnits: 115, + }), +}) +``` + When using provisioned billing, you must also specify `readCapacity` and `writeCapacity`. You can choose to configure `readCapacity` with fixed capacity or autoscaled capacity, but `writeCapacity` can only be configured with autoscaled capacity. The following example shows how to configure `TableV2` with provisioned billing: ```ts diff --git a/packages/aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md b/packages/aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md index ae5049af56cd8..34cf25434d6b2 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md +++ b/packages/aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md @@ -46,6 +46,17 @@ const table = new dynamodb.Table(this, 'Table', { }); ``` +You can specify a maximum read or write request units when using PAY_PER_REQUEST billing mode: + +```ts +const table = new dynamodb.Table(this, 'Table', { + partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING }, + billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, + maxReadRequestUnits: 100, + maxWriteRequestUnits: 200, +}); +``` + Further reading: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode. diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/billing.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/billing.ts index c319a7023f709..bc05c312226fa 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/billing.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/billing.ts @@ -16,6 +16,27 @@ export interface ThroughputProps { readonly writeCapacity: Capacity; } +/** + * Properties used to configure maximum throughput for an on-demand table. + */ +export interface MaxThroughputProps { + /** + * The max read request units. + * @default - if table mode is on-demand and this property is undefined, + * no maximum throughput limit will be put in place for read requests. + * This property is only applicable for tables using on-demand mode. + */ + readonly maxReadRequestUnits?: number; + + /** + * The max write request units. + * @default - if table mode is on-demand and this property is undefined, + * no maximum throughput limit will be put in place for write requests. + * This property is only applicable for tables using on-demand mode. + */ + readonly maxWriteRequestUnits?: number; +} + /** * Represents how capacity is managed and how you are charged for read and write throughput * for a DynamoDB table. @@ -26,14 +47,14 @@ export abstract class Billing { * * Note: Billing mode will be PAY_PER_REQUEST. */ - public static onDemand(): Billing { + public static onDemand(props?: MaxThroughputProps): Billing { return new (class extends Billing { public _renderReadCapacity() { - return undefined; + return props?.maxReadRequestUnits; } public _renderWriteCapacity() { - return undefined; + return props?.maxWriteRequestUnits; } }) (BillingMode.PAY_PER_REQUEST); } diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts index a309c994d33ad..65e3c588968e5 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts @@ -40,6 +40,15 @@ export interface ReplicaGlobalSecondaryIndexOptions { * @default - inherited from the primary table */ readonly readCapacity?: Capacity; + + /** + * The maximum read request units for a specific global secondary index on a replica table. + * + * Note: This can only be configured if primary table billing is PAY_PER_REQUEST. + * + * @default - inherited from the primary table + */ + readonly maxReadRequestUnits?: number; } /** @@ -75,6 +84,24 @@ export interface GlobalSecondaryIndexPropsV2 extends SecondaryIndexProps { * @default - inherited from the primary table. */ readonly writeCapacity?: Capacity; + + /** + * The maximum read request units. + * + * Note: This can only be configured if the primary table billing is PAY_PER_REQUEST. + * + * @default - inherited from the primary table. + */ + readonly maxReadRequestUnits?: number; + + /** + * The maximum write request units. + * + * Note: This can only be configured if the primary table billing is PAY_PER_REQUEST. + * + * @default - inherited from the primary table. + */ + readonly maxWriteRequestUnits?: number; } /** @@ -149,6 +176,15 @@ export interface ReplicaTableProps extends TableOptionsV2 { */ readonly readCapacity?: Capacity; + /** + * The maxium read request units. + * + * Note: This can only be configured if the primary table billing is PAY_PER_REQUEST. + * + * @default - inherited from the primary table + */ + readonly maxReadRequestUnits?: number; + /** * Options used to configure global secondary index properties. * @@ -459,6 +495,9 @@ export class TableV2 extends TableBaseV2 { private readonly readProvisioning?: CfnGlobalTable.ReadProvisionedThroughputSettingsProperty; private readonly writeProvisioning?: CfnGlobalTable.WriteProvisionedThroughputSettingsProperty; + private readonly maxReadRequestUnits?: number; + private readonly maxWriteRequestUnits?: number; + private readonly replicaTables = new Map(); private readonly replicaKeys: { [region: string]: IKey } = {}; private readonly replicaTableArns: string[] = []; @@ -467,6 +506,7 @@ export class TableV2 extends TableBaseV2 { private readonly globalSecondaryIndexes = new Map(); private readonly localSecondaryIndexes = new Map(); private readonly globalSecondaryIndexReadCapacitys = new Map(); + private readonly globalSecondaryIndexMaxReadUnits = new Map(); public constructor(scope: Construct, id: string, props: TablePropsV2) { super(scope, id, { physicalName: props.tableName ?? PhysicalName.GENERATE_IF_NEEDED }); @@ -485,9 +525,15 @@ export class TableV2 extends TableBaseV2 { this.addKey(props.sortKey, RANGE_KEY_TYPE); } - this.billingMode = props.billing?.mode ?? BillingMode.PAY_PER_REQUEST; - this.readProvisioning = props.billing?._renderReadCapacity(); - this.writeProvisioning = props.billing?._renderWriteCapacity(); + if (props.billing?.mode === BillingMode.PAY_PER_REQUEST || props.billing?.mode === undefined) { + this.maxReadRequestUnits = props.billing?._renderReadCapacity(); + this.maxWriteRequestUnits = props.billing?._renderWriteCapacity(); + this.billingMode = BillingMode.PAY_PER_REQUEST; + } else { + this.readProvisioning = props.billing?._renderReadCapacity(); + this.writeProvisioning = props.billing?._renderWriteCapacity(); + this.billingMode = props.billing.mode; + } props.globalSecondaryIndexes?.forEach(gsi => this.addGlobalSecondaryIndex(gsi)); props.localSecondaryIndexes?.forEach(lsi => this.addLocalSecondaryIndex(lsi)); @@ -501,6 +547,9 @@ export class TableV2 extends TableBaseV2 { localSecondaryIndexes: Lazy.any({ produce: () => this.renderLocalIndexes() }, { omitEmptyArray: true }), billingMode: this.billingMode, writeProvisionedThroughputSettings: this.writeProvisioning, + writeOnDemandThroughputSettings: this.maxWriteRequestUnits + ? { maxWriteRequestUnits: this.maxWriteRequestUnits } + : undefined, streamSpecification: Lazy.any( { produce: () => props.dynamoStream ? { streamViewType: props.dynamoStream } : this.renderStreamSpecification() }, ), @@ -636,6 +685,11 @@ export class TableV2 extends TableBaseV2 { ? props.readCapacity._renderReadCapacity() : this.readProvisioning, tags: props.tags, + readOnDemandThroughputSettings: props.maxReadRequestUnits + ? { maxReadRequestUnits: props.maxReadRequestUnits } + : this.maxReadRequestUnits + ? { maxReadRequestUnits: this.maxReadRequestUnits } + : undefined, resourcePolicy: resourcePolicy ? { policyDocument: resourcePolicy } : undefined, @@ -649,11 +703,18 @@ export class TableV2 extends TableBaseV2 { props.readCapacity && this.globalSecondaryIndexReadCapacitys.set(props.indexName, props.readCapacity); const writeProvisionedThroughputSettings = props.writeCapacity ? props.writeCapacity._renderWriteCapacity() : this.writeProvisioning; + props.maxReadRequestUnits && this.globalSecondaryIndexMaxReadUnits.set(props.indexName, props.maxReadRequestUnits); + + const writeOnDemandThroughputSettings: CfnGlobalTable.WriteOnDemandThroughputSettingsProperty | undefined = props.maxWriteRequestUnits + ? { maxWriteRequestUnits: props.maxWriteRequestUnits } + : undefined; + return { indexName: props.indexName, keySchema, projection, writeProvisionedThroughputSettings, + writeOnDemandThroughputSettings, }; } @@ -678,18 +739,24 @@ export class TableV2 extends TableBaseV2 { const indexName = gsi.indexName; let contributorInsights = this.tableOptions.contributorInsights; let readCapacity = this.globalSecondaryIndexReadCapacitys.get(indexName); - + let maxReadRequestUnits = this.globalSecondaryIndexMaxReadUnits.get(indexName); if (indexNamesFromOptions.includes(indexName)) { const indexOptions = options[indexName]; contributorInsights = indexOptions.contributorInsights; readCapacity = indexOptions.readCapacity; + maxReadRequestUnits = indexOptions.maxReadRequestUnits; } const readProvisionedThroughputSettings = readCapacity?._renderReadCapacity() ?? this.readProvisioning; + const readOnDemandThroughputSettings: CfnGlobalTable.ReadOnDemandThroughputSettingsProperty | undefined = maxReadRequestUnits + ? { maxReadRequestUnits: maxReadRequestUnits } + : undefined; + replicaGlobalSecondaryIndexes.push({ indexName, readProvisionedThroughputSettings, + readOnDemandThroughputSettings, contributorInsightsSpecification: contributorInsights !== undefined ? { enabled: contributorInsights } : undefined, diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts index a9127cabf957a..33bd67411b000 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts @@ -233,6 +233,25 @@ export interface TableOptions extends SchemaOptions { */ readonly writeCapacity?: number; + /** + * The maximum read request units for the table. Careful if you add Global Secondary Indexes, as + * those will share the table's maximum on-demand throughput. + * + * Can only be provided if billingMode is PAY_PER_REQUEST. + * + * @default - on-demand throughput is disabled + */ + readonly maxReadRequestUnits?: number; + /** + * The write request units for the table. Careful if you add Global Secondary Indexes, as + * those will share the table's maximum on-demand throughput. + * + * Can only be provided if billingMode is PAY_PER_REQUEST. + * + * @default - on-demand throughput is disabled + */ + readonly maxWriteRequestUnits?: number; + /** * Specify how you are charged for read and write throughput and how you manage capacity. * @@ -418,6 +437,24 @@ export interface GlobalSecondaryIndexProps extends SecondaryIndexProps, SchemaOp * @default 5 */ readonly writeCapacity?: number; + + /** + * The maximum read request units for the global secondary index. + * + * Can only be provided if table billingMode is PAY_PER_REQUEST. + * + * @default - on-demand throughput is disabled + */ + readonly maxReadRequestUnits?: number; + + /** + * The maximum write request units for the global secondary index. + * + * Can only be provided if table billingMode is PAY_PER_REQUEST. + * + * @default - on-demand throughput is disabled + */ + readonly maxWriteRequestUnits?: number; } /** @@ -1124,6 +1161,13 @@ export class Table extends TableBase { readCapacityUnits: props.readCapacity || 5, writeCapacityUnits: props.writeCapacity || 5, }, + ...(props.maxReadRequestUnits || props.maxWriteRequestUnits ? + { + onDemandThroughput: this.billingMode === BillingMode.PROVISIONED ? undefined : { + maxReadRequestUnits: props.maxReadRequestUnits || undefined, + maxWriteRequestUnits: props.maxWriteRequestUnits || undefined, + }, + } : undefined), sseSpecification, streamSpecification, tableClass: props.tableClass, @@ -1189,6 +1233,13 @@ export class Table extends TableBase { readCapacityUnits: props.readCapacity || 5, writeCapacityUnits: props.writeCapacity || 5, }, + ...(props.maxReadRequestUnits || props.maxWriteRequestUnits ? + { + onDemandThroughput: this.billingMode === BillingMode.PROVISIONED ? undefined : { + maxReadRequestUnits: props.maxReadRequestUnits || undefined, + maxWriteRequestUnits: props.maxWriteRequestUnits || undefined, + }, + } : undefined), }); this.secondaryIndexSchemas.set(props.indexName, { diff --git a/packages/aws-cdk-lib/aws-dynamodb/test/billing.test.ts b/packages/aws-cdk-lib/aws-dynamodb/test/billing.test.ts index e62cb924ab282..adda6cb779a97 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/test/billing.test.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/test/billing.test.ts @@ -48,3 +48,29 @@ describe('provisioned billing', () => { expect(billing.mode).toEqual(BillingMode.PROVISIONED); }); }); + +describe('max throughput on-demand billing', () => { + // GIVEN + let billing: Billing; + beforeEach(() => { + billing = Billing.onDemand({ + maxReadRequestUnits: 10, + maxWriteRequestUnits: 100, + }); + }); + + test('render read capacity', () => { + // WHEN / THEN + expect(billing._renderReadCapacity()).toBe(10); + }); + + test('render write capacity', () => { + // WHEN / THEN + expect(billing._renderWriteCapacity()).toBe(100); + }); + + test('billing mode is PAY_PER_REQUEST', () => { + // WHEN / THEN + expect(billing.mode).toEqual(BillingMode.PAY_PER_REQUEST); + }); +}); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-dynamodb/test/dynamodb.test.ts b/packages/aws-cdk-lib/aws-dynamodb/test/dynamodb.test.ts index 39598ee4f588a..4be16524b2ca3 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/test/dynamodb.test.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/test/dynamodb.test.ts @@ -762,6 +762,75 @@ describe('when billing mode is PAY_PER_REQUEST', () => { writeCapacity: 1, })).toThrow(/PAY_PER_REQUEST/); }); + + test('when specifying maximum throughput for on-demand', () => { + stack = new Stack(); + new Table(stack, CONSTRUCT_NAME, { + tableName: TABLE_NAME, + billingMode: BillingMode.PAY_PER_REQUEST, + partitionKey: TABLE_PARTITION_KEY, + maxReadRequestUnits: 10, + maxWriteRequestUnits: 5, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', + { + KeySchema: [ + { AttributeName: 'hashKey', KeyType: 'HASH' }, + ], + BillingMode: 'PAY_PER_REQUEST', + AttributeDefinitions: [ + { AttributeName: 'hashKey', AttributeType: 'S' }, + ], + TableName: 'MyTable', + OnDemandThroughput: { + MaxReadRequestUnits: 10, + MaxWriteRequestUnits: 5, + }, + }, + ); + }); + + test('when specifying maximum throughput for on-demand-indexes', () => { + stack = new Stack(); + const table = new Table(stack, CONSTRUCT_NAME, { + tableName: TABLE_NAME, + billingMode: BillingMode.PAY_PER_REQUEST, + partitionKey: TABLE_PARTITION_KEY, + maxReadRequestUnits: 10, + maxWriteRequestUnits: 5, + }); + table.addGlobalSecondaryIndex({ + maxReadRequestUnits: 10, + maxWriteRequestUnits: 20, + indexName: 'gsi1', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', + { + KeySchema: [{ AttributeName: 'hashKey', KeyType: 'HASH' }], + BillingMode: 'PAY_PER_REQUEST', + AttributeDefinitions: [ + { AttributeName: 'hashKey', AttributeType: 'S' }, + { AttributeName: 'pk', AttributeType: 'S' }, + ], + TableName: 'MyTable', + OnDemandThroughput: { + MaxReadRequestUnits: 10, + MaxWriteRequestUnits: 5, + }, + GlobalSecondaryIndexes: [{ + IndexName: 'gsi1', + KeySchema: [{ AttributeName: 'pk', KeyType: 'HASH' }], + OnDemandThroughput: { + MaxReadRequestUnits: 10, + MaxWriteRequestUnits: 20, + }, + }], + }, + ); + }); }); describe('schema details', () => { diff --git a/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts b/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts index 81e9205211a0b..63bbf3319b73e 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts @@ -1029,6 +1029,161 @@ describe('table', () => { table.replica('us-west-2'); }).toThrow('Replica tables are not supported in a region agnostic stack'); }); + + test('with on-demand maximum throughput', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + // WHEN + new TableV2(stack, 'Table', { + partitionKey: { name: 'pk', type: AttributeType.STRING }, + billing: Billing.onDemand({ + maxReadRequestUnits: 10, + maxWriteRequestUnits: 10, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + KeySchema: [ + { AttributeName: 'pk', KeyType: 'HASH' }, + ], + AttributeDefinitions: [ + { AttributeName: 'pk', AttributeType: 'S' }, + ], + WriteOnDemandThroughputSettings: { + MaxWriteRequestUnits: 10, + }, + BillingMode: 'PAY_PER_REQUEST', + StreamSpecification: Match.absent(), + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + ReadOnDemandThroughputSettings: { + MaxReadRequestUnits: 10, + }, + }, + ], + }); + Template.fromStack(stack).hasResource('AWS::DynamoDB::GlobalTable', { DeletionPolicy: CfnDeletionPolicy.RETAIN }); + }); + + test('with on-demand maximum throughput - read only', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + // WHEN + new TableV2(stack, 'Table', { + partitionKey: { name: 'pk', type: AttributeType.STRING }, + billing: Billing.onDemand({ + maxReadRequestUnits: 10, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + KeySchema: [ + { AttributeName: 'pk', KeyType: 'HASH' }, + ], + AttributeDefinitions: [ + { AttributeName: 'pk', AttributeType: 'S' }, + ], + BillingMode: 'PAY_PER_REQUEST', + StreamSpecification: Match.absent(), + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + ReadOnDemandThroughputSettings: { + MaxReadRequestUnits: 10, + }, + }, + ], + }); + Template.fromStack(stack).hasResource('AWS::DynamoDB::GlobalTable', { DeletionPolicy: CfnDeletionPolicy.RETAIN }); + }); + + test('with on-demand maximum throughput - index', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + // WHEN + new TableV2(stack, 'Table', { + partitionKey: { name: 'pk', type: AttributeType.STRING }, + globalSecondaryIndexes: [ + { + indexName: 'gsi1', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + maxReadRequestUnits: 100, + }, + { + indexName: 'gsi2', + partitionKey: { name: 'pk', type: AttributeType.STRING }, + maxReadRequestUnits: 1, + maxWriteRequestUnits: 1, + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + KeySchema: [ + { AttributeName: 'pk', KeyType: 'HASH' }, + ], + AttributeDefinitions: [ + { AttributeName: 'pk', AttributeType: 'S' }, + ], + GlobalSecondaryIndexes: [ + { + IndexName: 'gsi1', + KeySchema: [ + { AttributeName: 'pk', KeyType: 'HASH' }, + ], + Projection: { + ProjectionType: 'ALL', + }, + }, + { + IndexName: 'gsi2', + KeySchema: [ + { AttributeName: 'pk', KeyType: 'HASH' }, + ], + Projection: { + ProjectionType: 'ALL', + }, + WriteOnDemandThroughputSettings: { + MaxWriteRequestUnits: 1, + }, + }, + ], + BillingMode: 'PAY_PER_REQUEST', + StreamSpecification: Match.absent(), + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + GlobalSecondaryIndexes: [{ + IndexName: 'gsi1', + ReadOnDemandThroughputSettings: { + MaxReadRequestUnits: 100, + }, + }, + { + IndexName: 'gsi2', + ReadOnDemandThroughputSettings: { + MaxReadRequestUnits: 1, + }, + }], + }, + ], + }); + Template.fromStack(stack).hasResource('AWS::DynamoDB::GlobalTable', { DeletionPolicy: CfnDeletionPolicy.RETAIN }); + }); + }); describe('replica tables', () => { From 79b5cd2390508e7b5c3d5c93001e30387bf88a4e Mon Sep 17 00:00:00 2001 From: Kendra Neil <53584728+TheRealAmazonKendra@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:26:26 -0700 Subject: [PATCH 10/12] revert: feat(ec2): security group lookup via filters (#31065) Reverts aws/aws-cdk#30625 --- .../LookupStack.assets.json | 20 - .../LookupStack.template.json | 36 -- ...efaultTestDeployAssert9466B7BF.assets.json | 19 - ...aultTestDeployAssert9466B7BF.template.json | 36 -- .../StackWithSg.assets.json | 34 -- .../StackWithSg.template.json | 233 ----------- .../__entrypoint__.js | 155 ------- .../index.js | 1 - .../cdk.out | 1 - .../integ.json | 13 - .../manifest.json | 253 ----------- .../tree.json | 392 ------------------ .../test/integ.security-group-lookup.ts | 56 --- packages/aws-cdk-lib/aws-ec2/README.md | 12 +- .../aws-cdk-lib/aws-ec2/lib/security-group.ts | 57 +-- .../aws-ec2/test/security-group.test.ts | 24 -- .../lib/cloud-assembly/context-queries.ts | 28 -- .../schema/cloud-assembly.schema.json | 22 - .../schema/cloud-assembly.version.json | 2 +- .../lib/context-providers/security-groups.ts | 30 +- .../context-providers/security-groups.test.ts | 87 +--- 21 files changed, 26 insertions(+), 1485 deletions(-) delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json deleted file mode 100644 index fc94649590768..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.assets.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "37.0.0", - "files": { - "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { - "source": { - "path": "LookupStack.template.json", - "packaging": "file" - }, - "destinations": { - "12345678-test-region": { - "bucketName": "cdk-hnb659fds-assets-12345678-test-region", - "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", - "region": "test-region", - "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" - } - } - } - }, - "dockerImages": {} -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json deleted file mode 100644 index ad9d0fb73d1dd..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/LookupStack.template.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "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.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json deleted file mode 100644 index e67d33537caf4..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "37.0.0", - "files": { - "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { - "source": { - "path": "SgLookupTestDefaultTestDeployAssert9466B7BF.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.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json deleted file mode 100644 index ad9d0fb73d1dd..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/SgLookupTestDefaultTestDeployAssert9466B7BF.template.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "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.security-group-lookup.js.snapshot/StackWithSg.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json deleted file mode 100644 index a65bbb573ca89..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.assets.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "version": "37.0.0", - "files": { - "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1": { - "source": { - "path": "asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1", - "packaging": "zip" - }, - "destinations": { - "12345678-test-region": { - "bucketName": "cdk-hnb659fds-assets-12345678-test-region", - "objectKey": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.zip", - "region": "test-region", - "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" - } - } - }, - "e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9": { - "source": { - "path": "StackWithSg.template.json", - "packaging": "file" - }, - "destinations": { - "12345678-test-region": { - "bucketName": "cdk-hnb659fds-assets-12345678-test-region", - "objectKey": "e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9.json", - "region": "test-region", - "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-file-publishing-role-12345678-test-region" - } - } - } - }, - "dockerImages": {} -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json deleted file mode 100644 index eefe64d08796d..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/StackWithSg.template.json +++ /dev/null @@ -1,233 +0,0 @@ -{ - "Resources": { - "MyVpcF9F0CA6F": { - "Type": "AWS::EC2::VPC", - "Properties": { - "CidrBlock": "10.0.0.0/16", - "EnableDnsHostnames": true, - "EnableDnsSupport": true, - "InstanceTenancy": "default", - "Tags": [ - { - "Key": "Name", - "Value": "my-vpc-name" - } - ] - } - }, - "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62": { - "Type": "Custom::VpcRestrictDefaultSG", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", - "Arn" - ] - }, - "DefaultSecurityGroupId": { - "Fn::GetAtt": [ - "MyVpcF9F0CA6F", - "DefaultSecurityGroup" - ] - }, - "Account": "12345678" - }, - "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:test-region:12345678:security-group/", - { - "Fn::GetAtt": [ - "MyVpcF9F0CA6F", - "DefaultSecurityGroup" - ] - } - ] - ] - } - ] - } - ] - } - } - ] - } - }, - "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": "cdk-hnb659fds-assets-12345678-test-region", - "S3Key": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.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" - ] - }, - "MySgAFDC270F2": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "StackWithSg/MySgA", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "Tags": [ - { - "Key": "myTag", - "Value": "my-value" - } - ], - "VpcId": { - "Ref": "MyVpcF9F0CA6F" - } - } - }, - "MySgB343D3C61": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "StackWithSg/MySgB", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "Tags": [ - { - "Key": "myTagKey", - "Value": "true" - } - ], - "VpcId": { - "Ref": "MyVpcF9F0CA6F" - } - } - }, - "MySgC50C8732C": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "my-description", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "VpcId": { - "Ref": "MyVpcF9F0CA6F" - } - } - }, - "MySgDA51BA0C2": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "ownerId description", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "VpcId": { - "Ref": "MyVpcF9F0CA6F" - } - } - } - }, - "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.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js deleted file mode 100644 index 02033f55cf612..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/__entrypoint__.js +++ /dev/null @@ -1,155 +0,0 @@ -"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, - }; - const parsedUrl = url.parse(event.ResponseURL); - const loggingSafeUrl = `${parsedUrl.protocol}//${parsedUrl.hostname}/${parsedUrl.pathname}?***`; - exports.external.log('submit response to cloudformation', loggingSafeUrl, json); - const responseBody = JSON.stringify(json); - 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, requestBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, (response) => { - response.resume(); // Consume the response but don't care about it - if (!response.statusCode || response.statusCode >= 400) { - reject(new Error(`Unsuccessful HTTP response: ${response.statusCode}`)); - } - else { - resolve(); - } - }); - request.on('error', reject); - request.write(requestBody); - 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)); -} diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js deleted file mode 100644 index 013bcaffd8fe5..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1/index.js +++ /dev/null @@ -1 +0,0 @@ -"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.security-group-lookup.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out deleted file mode 100644 index 079dd58c72d69..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/cdk.out +++ /dev/null @@ -1 +0,0 @@ -{"version":"37.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json deleted file mode 100644 index adc4aec587718..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/integ.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "enableLookups": true, - "version": "37.0.0", - "testCases": { - "SgLookupTest/DefaultTest": { - "stacks": [ - "StackWithSg" - ], - "assertionStack": "SgLookupTest/DefaultTest/DeployAssert", - "assertionStackName": "SgLookupTestDefaultTestDeployAssert9466B7BF" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json deleted file mode 100644 index 2f8ff36aefa99..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/manifest.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "version": "37.0.0", - "artifacts": { - "StackWithSg.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "StackWithSg.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "StackWithSg": { - "type": "aws:cloudformation:stack", - "environment": "aws://12345678/test-region", - "properties": { - "templateFile": "StackWithSg.template.json", - "terminationProtection": false, - "validateOnSynth": false, - "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-deploy-role-12345678-test-region", - "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-cfn-exec-role-12345678-test-region", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-12345678-test-region/e205a0cabbb47f8c8f8f543d0ad04ed8b26973d67ffd51d9583342d4ad69a2a9.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", - "additionalDependencies": [ - "StackWithSg.assets" - ], - "lookupRole": { - "arn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region", - "requiresBootstrapStackVersion": 8, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "dependencies": [ - "StackWithSg.assets" - ], - "metadata": { - "/StackWithSg/MyVpc/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MyVpcF9F0CA6F" - } - ], - "/StackWithSg/MyVpc/RestrictDefaultSecurityGroupCustomResource/Default": [ - { - "type": "aws:cdk:logicalId", - "data": "MyVpcRestrictDefaultSecurityGroupCustomResourceA4FCCD62" - } - ], - "/StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ - { - "type": "aws:cdk:logicalId", - "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" - } - ], - "/StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ - { - "type": "aws:cdk:logicalId", - "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" - } - ], - "/StackWithSg/MySgA/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MySgAFDC270F2" - } - ], - "/StackWithSg/MySgB/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MySgB343D3C61" - } - ], - "/StackWithSg/MySgC/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MySgC50C8732C" - } - ], - "/StackWithSg/MySgD/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MySgDA51BA0C2" - } - ], - "/StackWithSg/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/StackWithSg/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "StackWithSg" - }, - "LookupStack.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "LookupStack.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "LookupStack": { - "type": "aws:cloudformation:stack", - "environment": "aws://12345678/test-region", - "properties": { - "templateFile": "LookupStack.template.json", - "terminationProtection": false, - "validateOnSynth": false, - "assumeRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-deploy-role-12345678-test-region", - "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-cfn-exec-role-12345678-test-region", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-12345678-test-region/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", - "additionalDependencies": [ - "LookupStack.assets" - ], - "lookupRole": { - "arn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region", - "requiresBootstrapStackVersion": 8, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "dependencies": [ - "StackWithSg", - "LookupStack.assets" - ], - "metadata": { - "/LookupStack/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/LookupStack/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "LookupStack" - }, - "SgLookupTestDefaultTestDeployAssert9466B7BF.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "SgLookupTestDefaultTestDeployAssert9466B7BF.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "SgLookupTestDefaultTestDeployAssert9466B7BF": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "SgLookupTestDefaultTestDeployAssert9466B7BF.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": [ - "SgLookupTestDefaultTestDeployAssert9466B7BF.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": [ - "SgLookupTestDefaultTestDeployAssert9466B7BF.assets" - ], - "metadata": { - "/SgLookupTest/DefaultTest/DeployAssert/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/SgLookupTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "SgLookupTest/DefaultTest/DeployAssert" - }, - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - } - }, - "missing": [ - { - "key": "security-group:account=12345678:region=test-region:tags.myTag.0=my-value", - "provider": "security-group", - "props": { - "account": "12345678", - "region": "test-region", - "tags": { - "myTag": [ - "my-value" - ] - }, - "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" - } - }, - { - "key": "security-group:account=12345678:region=test-region:tagKeys.0=myTagKey", - "provider": "security-group", - "props": { - "account": "12345678", - "region": "test-region", - "tagKeys": [ - "myTagKey" - ], - "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" - } - }, - { - "key": "security-group:account=12345678:description=my-description:region=test-region", - "provider": "security-group", - "props": { - "account": "12345678", - "region": "test-region", - "description": "my-description", - "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" - } - }, - { - "key": "security-group:account=12345678:description=ownerId description:ownerId=12345678:region=test-region", - "provider": "security-group", - "props": { - "account": "12345678", - "region": "test-region", - "description": "ownerId description", - "ownerId": "12345678", - "lookupRoleArn": "arn:${AWS::Partition}:iam::12345678:role/cdk-hnb659fds-lookup-role-12345678-test-region" - } - } - ] -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json deleted file mode 100644 index bf8c406b81c9e..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.js.snapshot/tree.json +++ /dev/null @@ -1,392 +0,0 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "StackWithSg": { - "id": "StackWithSg", - "path": "StackWithSg", - "children": { - "MyVpc": { - "id": "MyVpc", - "path": "StackWithSg/MyVpc", - "children": { - "Resource": { - "id": "Resource", - "path": "StackWithSg/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": "my-vpc-name" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", - "version": "0.0.0" - } - }, - "RestrictDefaultSecurityGroupCustomResource": { - "id": "RestrictDefaultSecurityGroupCustomResource", - "path": "StackWithSg/MyVpc/RestrictDefaultSecurityGroupCustomResource", - "children": { - "Default": { - "id": "Default", - "path": "StackWithSg/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" - } - }, - "Custom::VpcRestrictDefaultSGCustomResourceProvider": { - "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", - "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider", - "children": { - "Staging": { - "id": "Staging", - "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", - "constructInfo": { - "fqn": "aws-cdk-lib.AssetStaging", - "version": "0.0.0" - } - }, - "Role": { - "id": "Role", - "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnResource", - "version": "0.0.0" - } - }, - "Handler": { - "id": "Handler", - "path": "StackWithSg/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnResource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.CustomResourceProviderBase", - "version": "0.0.0" - } - }, - "MySgA": { - "id": "MySgA", - "path": "StackWithSg/MySgA", - "children": { - "Resource": { - "id": "Resource", - "path": "StackWithSg/MySgA/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", - "aws:cdk:cloudformation:props": { - "groupDescription": "StackWithSg/MySgA", - "securityGroupEgress": [ - { - "cidrIp": "0.0.0.0/0", - "description": "Allow all outbound traffic by default", - "ipProtocol": "-1" - } - ], - "tags": [ - { - "key": "myTag", - "value": "my-value" - } - ], - "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" - } - }, - "MySgB": { - "id": "MySgB", - "path": "StackWithSg/MySgB", - "children": { - "Resource": { - "id": "Resource", - "path": "StackWithSg/MySgB/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", - "aws:cdk:cloudformation:props": { - "groupDescription": "StackWithSg/MySgB", - "securityGroupEgress": [ - { - "cidrIp": "0.0.0.0/0", - "description": "Allow all outbound traffic by default", - "ipProtocol": "-1" - } - ], - "tags": [ - { - "key": "myTagKey", - "value": "true" - } - ], - "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" - } - }, - "MySgC": { - "id": "MySgC", - "path": "StackWithSg/MySgC", - "children": { - "Resource": { - "id": "Resource", - "path": "StackWithSg/MySgC/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", - "aws:cdk:cloudformation:props": { - "groupDescription": "my-description", - "securityGroupEgress": [ - { - "cidrIp": "0.0.0.0/0", - "description": "Allow all outbound traffic by default", - "ipProtocol": "-1" - } - ], - "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" - } - }, - "MySgD": { - "id": "MySgD", - "path": "StackWithSg/MySgD", - "children": { - "Resource": { - "id": "Resource", - "path": "StackWithSg/MySgD/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", - "aws:cdk:cloudformation:props": { - "groupDescription": "ownerId description", - "securityGroupEgress": [ - { - "cidrIp": "0.0.0.0/0", - "description": "Allow all outbound traffic by default", - "ipProtocol": "-1" - } - ], - "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" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "StackWithSg/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "StackWithSg/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - }, - "LookupStack": { - "id": "LookupStack", - "path": "LookupStack", - "children": { - "SgFromLookupTags": { - "id": "SgFromLookupTags", - "path": "LookupStack/SgFromLookupTags", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "SgFromLookupTagKeys": { - "id": "SgFromLookupTagKeys", - "path": "LookupStack/SgFromLookupTagKeys", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "SgFromLookupDescription": { - "id": "SgFromLookupDescription", - "path": "LookupStack/SgFromLookupDescription", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "SgFromLookupOwnerId": { - "id": "SgFromLookupOwnerId", - "path": "LookupStack/SgFromLookupOwnerId", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "LookupStack/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "LookupStack/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - }, - "SgLookupTest": { - "id": "SgLookupTest", - "path": "SgLookupTest", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "SgLookupTest/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "SgLookupTest/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "SgLookupTest/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "SgLookupTest/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "SgLookupTest/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.security-group-lookup.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts deleted file mode 100644 index 1030c57274991..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.security-group-lookup.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as cdk from 'aws-cdk-lib'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; - -import { IntegTest } from '@aws-cdk/integ-tests-alpha'; - -const app = new cdk.App(); - -const env = { - account: process.env.CDK_INTEG_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_INTEG_REGION || process.env.CDK_DEFAULT_REGION, -}; - -// Deploy the security groups to lookup -const stack = new cdk.Stack(app, 'StackWithSg', { env }); -const testVpc = new ec2.Vpc(stack, 'MyVpc', { - vpcName: 'my-vpc-name', - ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), - subnetConfiguration: [], - natGateways: 0, -}); -const testSgA = new ec2.SecurityGroup(stack, 'MySgA', { vpc: testVpc }); -cdk.Tags.of(testSgA).add('myTag', 'my-value'); -const testSgB = new ec2.SecurityGroup(stack, 'MySgB', { vpc: testVpc }); -cdk.Tags.of(testSgB).add('myTagKey', 'true'); -new ec2.SecurityGroup(stack, 'MySgC', { vpc: testVpc, description: 'my-description' }); -new ec2.SecurityGroup(stack, 'MySgD', { vpc: testVpc, description: 'ownerId description' }); - -// Now perform the lookups -const lookupStack = new cdk.Stack(app, 'LookupStack', { env }); -lookupStack.addDependency(stack); -ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupTags', { - tags: { - myTag: ['my-value'], - }, -}); - -ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupTagKeys', { - tagKeys: ['myTagKey'], -}); - -ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupDescription', { - description: 'my-description', -}); - -ec2.SecurityGroup.fromLookupByFilters(lookupStack, 'SgFromLookupOwnerId', { - description: 'ownerId description', - ownerId: process.env.CDK_INTEG_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, -}); - -new IntegTest(app, 'SgLookupTest', { - testCases: [stack], - enableLookups: true, -}); - -app.synth(); - diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index 86e0fd78ee07c..686eb78ed2a3f 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -843,23 +843,13 @@ Alternatively, use lookup methods to import security groups if you do not know t const sg = ec2.SecurityGroup.fromLookupByName(this, 'SecurityGroupLookup', 'security-group-name', vpc); ``` -You can perform lookups based on filter conditions detailed in the [API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html). -```ts -const sg = ec2.SecurityGroup.fromLookupByFilters(this, 'SecurityGroupLookup', { - ownerId: "012345678901", - description: "my description", - tagKeys: ["tagA", "tagB"], - tags: { tagC: ["valueC", "otherValueC"], tagD: ["valueD"] } -}); -``` - If the security group ID is known and configuration details are unknown, use method `SecurityGroup.fromLookupById` instead. This method will lookup property `allowAllOutbound` from the current configuration of the security group. ```ts const sg = ec2.SecurityGroup.fromLookupById(this, 'SecurityGroupLookup', 'sg-1234'); ``` -The result of `SecurityGroup.fromLookupByName`, `SecurityGroup.fromLookupById`, and `SecurityGroup.fromLookupByFilters` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. +The result of `SecurityGroup.fromLookupByName` and `SecurityGroup.fromLookupById` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. ### Cross Stack Connections diff --git a/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts b/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts index b9c75b7589350..e774c1f9de3af 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts @@ -387,13 +387,6 @@ export class SecurityGroup extends SecurityGroupBase { return this.fromLookupAttributes(scope, id, { securityGroupName, vpc }); } - /** - * Look up a security group by filters - */ - public static fromLookupByFilters(scope: Construct, id: string, filters: SecurityGroupLookupOptions) { - return this.fromLookupAttributes(scope, id, filters); - } - /** * Import an existing security group into this app. * @@ -441,15 +434,7 @@ export class SecurityGroup extends SecurityGroupBase { * Look up a security group. */ private static fromLookupAttributes(scope: Construct, id: string, options: SecurityGroupLookupOptions) { - if ([ - options.securityGroupId, - options.securityGroupName, - options.vpc?.vpcId, - options.description, - options.ownerId, - options.tagKeys, - options.tags, - ].some(opt => Token.isUnresolved(opt))) { + if (Token.isUnresolved(options.securityGroupId) || Token.isUnresolved(options.securityGroupName) || Token.isUnresolved(options.vpc?.vpcId)) { throw new Error('All arguments to look up a security group must be concrete (no Tokens)'); } @@ -459,10 +444,6 @@ export class SecurityGroup extends SecurityGroupBase { securityGroupId: options.securityGroupId, securityGroupName: options.securityGroupName, vpcId: options.vpc?.vpcId, - description: options.description, - ownerId: options.ownerId, - tagKeys: options.tagKeys, - tags: options.tags, }, dummyValue: { securityGroupId: 'sg-12345678', @@ -835,13 +816,13 @@ function isAllTrafficRule(rule: any) { * * Either `securityGroupName` or `securityGroupId` has to be specified. */ -export interface SecurityGroupLookupOptions { +interface SecurityGroupLookupOptions { /** * The name of the security group * * If given, will import the SecurityGroup with this name. * - * @default - Don't filter on securityGroupName + * @default Don't filter on securityGroupName */ readonly securityGroupName?: string; @@ -850,7 +831,7 @@ export interface SecurityGroupLookupOptions { * * If given, will import the SecurityGroup with this ID. * - * @default - Don't filter on securityGroupId + * @default Don't filter on securityGroupId */ readonly securityGroupId?: string; @@ -859,35 +840,7 @@ export interface SecurityGroupLookupOptions { * * If given, will filter the SecurityGroup based on the VPC. * - * @default - Don't filter on VPC + * @default Don't filter on VPC */ readonly vpc?: IVpc; - - /** - * Security group description - * - * @default - Don't filter on description - */ - readonly description?: string; - - /** - * Account ID of the owner of the security group - * - * @default - Don't filter on owner ID - */ - readonly ownerId?: string; - - /** - * The keys of tags assigned to the security group - * - * @default - Don't filter on tag keys - */ - readonly tagKeys?: string[]; - - /** - * The key/value combination of a tag assigned to the security group - * - * @default - Don't filter on tags - */ - readonly tags?: Record; } diff --git a/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts b/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts index cd98bd1689181..50e7f9ae5f224 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/security-group.test.ts @@ -596,30 +596,6 @@ describe('security group lookup', () => { }); - test('can look up a security group by filters', () => { - // GIVEN - const app = new App(); - const stack = new Stack(app, 'stack', { - env: { - account: '1234', - region: 'us-east-1', - }, - }); - - // WHEN - const securityGroup = SecurityGroup.fromLookupByFilters(stack, 'SG1', { - ownerId: '012345678901', - description: 'my description', - tagKeys: ['tagA', 'tagB'], - tags: { tagC: ['valueC', 'otherValueC'], tagD: ['valueD'] }, - }); - - // THEN - expect(securityGroup.securityGroupId).toEqual('sg-12345678'); - expect(securityGroup.allowAllOutbound).toEqual(true); - - }); - test('can look up a security group and use it as a peer', () => { // GIVEN const app = new App(); diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts b/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts index 92fd11f9ea376..bd35d023dfe69 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts +++ b/packages/aws-cdk-lib/cloud-assembly-schema/lib/cloud-assembly/context-queries.ts @@ -449,34 +449,6 @@ export interface SecurityGroupContextQuery { * @default - None */ readonly vpcId?: string; - - /** - * Security group description - * - * @default - None - */ - readonly description?: string; - - /** - * Account ID of the owner of the security group - * - * @default - None - */ - readonly ownerId?: string; - - /** - * The keys of tags assigned to the security group - * - * @default - None - */ - readonly tagKeys?: string[]; - - /** - * The key/value combination of a tag assigned to the security group - * - * @default - None - */ - readonly tags?: Record; } /** diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json index 2dc1ceae0d7d9..279dfbe369073 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json +++ b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.schema.json @@ -870,25 +870,6 @@ "vpcId": { "description": "VPC ID (Default - None)", "type": "string" - }, - "description": { - "description": "Security group description (Default - None)", - "type": "string" - }, - "ownerId": { - "description": "Account ID of the owner of the security group (Default - None)", - "type": "string" - }, - "tagKeys": { - "description": "The keys of tags assigned to the security group (Default - None)", - "type": "array", - "items": { - "type": "string" - } - }, - "tags": { - "description": "The key/value combination of a tag assigned to the security group (Default - None)", - "$ref": "#/definitions/Record" } }, "required": [ @@ -896,9 +877,6 @@ "region" ] }, - "Record": { - "type": "object" - }, "KeyContextQuery": { "description": "Query input for looking up a KMS Key", "type": "object", diff --git a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json index 079dd58c72d69..1f0068d32659a 100644 --- a/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json +++ b/packages/aws-cdk-lib/cloud-assembly-schema/schema/cloud-assembly.version.json @@ -1 +1 @@ -{"version":"37.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/security-groups.ts b/packages/aws-cdk/lib/context-providers/security-groups.ts index fa68fa4129e23..19372df9af842 100644 --- a/packages/aws-cdk/lib/context-providers/security-groups.ts +++ b/packages/aws-cdk/lib/context-providers/security-groups.ts @@ -17,6 +17,10 @@ export class SecurityGroupContextProviderPlugin implements ContextProviderPlugin throw new Error('\'securityGroupId\' and \'securityGroupName\' can not be specified both when looking up a security group'); } + if (!args.securityGroupId && !args.securityGroupName) { + throw new Error('\'securityGroupId\' or \'securityGroupName\' must be specified to look up a security group'); + } + const options = { assumeRoleArn: args.lookupRoleArn }; const ec2 = (await this.aws.forEnvironment(cxapi.EnvironmentUtils.make(account, region), Mode.ForReading, options)).sdk.ec2(); @@ -33,32 +37,6 @@ export class SecurityGroupContextProviderPlugin implements ContextProviderPlugin Values: [args.securityGroupName], }); } - if (args.description) { - filters.push({ - Name: 'description', - Values: [args.description], - }); - } - if (args.tagKeys) { - filters.push({ - Name: 'tag-key', - Values: args.tagKeys, - }); - } - if (args.ownerId) { - filters.push({ - Name: 'owner-id', - Values: [args.ownerId], - }); - } - if (args.tags) { - Object.entries(args.tags).forEach(([key, values]) => { - filters.push({ - Name: `tag:${key}`, - Values: values, - }); - }); - } const response = await ec2.describeSecurityGroups({ GroupIds: args.securityGroupId ? [args.securityGroupId] : undefined, diff --git a/packages/aws-cdk/test/context-providers/security-groups.test.ts b/packages/aws-cdk/test/context-providers/security-groups.test.ts index 2477336d98b93..c7bdc586ad7bc 100644 --- a/packages/aws-cdk/test/context-providers/security-groups.test.ts +++ b/packages/aws-cdk/test/context-providers/security-groups.test.ts @@ -1,9 +1,7 @@ -import * as AWS from 'aws-sdk-mock'; /* eslint-disable import/order */ import * as aws from 'aws-sdk'; - -import { SecurityGroupContextProviderPlugin, hasAllTrafficEgress } from '../../lib/context-providers/security-groups'; - +import * as AWS from 'aws-sdk-mock'; +import { hasAllTrafficEgress, SecurityGroupContextProviderPlugin } from '../../lib/context-providers/security-groups'; import { MockSdkProvider } from '../util/mock-sdk'; AWS.setSDK(require.resolve('aws-sdk')); @@ -228,74 +226,6 @@ describe('security group context provider plugin', () => { expect(res.allowAllOutbound).toEqual(true); }); - test('looks up by security group description, owner id, tag keys, and tags', async () => { - // GIVEN - const provider = new SecurityGroupContextProviderPlugin(mockSDK); - - AWS.mock('EC2', 'describeSecurityGroups', (_params: aws.EC2.DescribeSecurityGroupsRequest, cb: AwsCallback) => { - expect(_params).toEqual({ - GroupIds: undefined, - Filters: [ - { - Name: 'description', - Values: ['my description'], - }, - { - Name: 'tag-key', - Values: ['tagA', 'tagB'], - }, - { - Name: 'owner-id', - Values: ['012345678901'], - }, - { - Name: 'tag:tagC', - Values: ['valueC', 'otherValueC'], - }, - { - Name: 'tag:tagD', - Values: ['valueD'], - }, - ], - }); - cb(null, { - SecurityGroups: [ - { - GroupId: 'sg-1234', - IpPermissionsEgress: [ - { - IpProtocol: '-1', - IpRanges: [ - { CidrIp: '0.0.0.0/0' }, - ], - }, - { - IpProtocol: '-1', - Ipv6Ranges: [ - { CidrIpv6: '::/0' }, - ], - }, - ], - }, - ], - }); - }); - - // WHEN - const res = await provider.getValue({ - account: '1234', - region: 'us-east-1', - ownerId: '012345678901', - description: 'my description', - tagKeys: ['tagA', 'tagB'], - tags: { tagC: ['valueC', 'otherValueC'], tagD: ['valueD'] }, - }); - - // THEN - expect(res.securityGroupId).toEqual('sg-1234'); - expect(res.allowAllOutbound).toEqual(true); - }); - test('detects non all-outbound egress', async () => { // GIVEN const provider = new SecurityGroupContextProviderPlugin(mockSDK); @@ -389,6 +319,19 @@ describe('security group context provider plugin', () => { ).rejects.toThrow(/\'securityGroupId\' and \'securityGroupName\' can not be specified both when looking up a security group/i); }); + test('errors when neither securityGroupId nor securityGroupName are specified', async () => { + // GIVEN + const provider = new SecurityGroupContextProviderPlugin(mockSDK); + + // WHEN + await expect( + provider.getValue({ + account: '1234', + region: 'us-east-1', + }), + ).rejects.toThrow(/\'securityGroupId\' or \'securityGroupName\' must be specified to look up a security group/i); + }); + test('identifies allTrafficEgress from SecurityGroup permissions', () => { expect( hasAllTrafficEgress({ From 1e7c690f5ec404d7c620dc54692999fee67b3eaf Mon Sep 17 00:00:00 2001 From: Leonardo Gama <51037424+Leo10Gama@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:39:18 -0700 Subject: [PATCH 11/12] fix(ec2): prevent deduplication of init command args (#30821) ### Issue # (if applicable) Closes #26221 ### Reason for this change Previously, using `ec2.InitCommand.argvCommand()` would remove some duplicate strings in the input array. This produces an incorrect command in the template, leading to unexpected behaviour. ### Description of changes An additional line was added to the `deepMerge` function that is called in the `InitConfig.bindForType()` method, which checks the key of the input array, preventing it from becoming a set (removing duplicates) if it is a list of commands. ### Description of how you validated changes A unit test was added to generate an `AWS::CloudFormation::Init` resource identical to the one reproduced in the issue. The test was run and failed before the changes were made, and following the changes in `cfn-init.ts`, the test passed. ### 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* --- ...c2-multiple-instances-in-stack.assets.json | 4 +- ...-multiple-instances-in-stack.template.json | 25 +++++++- .../manifest.json | 7 ++- .../tree.json | 2 +- .../test/integ.instance-init-multiple.ts | 6 ++ .../manifest.json | 14 ++--- packages/aws-cdk-lib/aws-ec2/lib/cfn-init.ts | 15 +++-- .../aws-cdk-lib/aws-ec2/test/cfn-init.test.ts | 62 +++++++++++++++++++ 8 files changed, 115 insertions(+), 20 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.assets.json index 37139758282cd..efd673ae6169d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.assets.json @@ -40,7 +40,7 @@ } } }, - "55adc2a4d264e77d2c794df6cb13dd26ee0a9986d5b00a9bfe3cd48b6e0b2dfe": { + "db1c5d9623e5e22db4e511f52daf89f93fb1cbb8f325df40d03d5c50413e63a3": { "source": { "path": "integ-ec2-multiple-instances-in-stack.template.json", "packaging": "file" @@ -48,7 +48,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "55adc2a4d264e77d2c794df6cb13dd26ee0a9986d5b00a9bfe3cd48b6e0b2dfe.json", + "objectKey": "db1c5d9623e5e22db4e511f52daf89f93fb1cbb8f325df40d03d5c50413e63a3.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-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.template.json index 787b41606da14..e09958092be8c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/integ-ec2-multiple-instances-in-stack.template.json @@ -906,7 +906,7 @@ "Fn::Join": [ "", [ - "#!/bin/bash\n# fingerprint: 8787022e9944cbeb\n(\n set +e\n /opt/aws/bin/cfn-init -v --region ", + "#!/bin/bash\n# fingerprint: 370d9b2dcf8bf44b\n(\n set +e\n /opt/aws/bin/cfn-init -v --region ", { "Ref": "AWS::Region" }, @@ -955,6 +955,29 @@ "owner": "root", "group": "root" } + }, + "commands": { + "000": { + "command": [ + "useradd", + "-u", + "1001", + "-g", + "1001", + "eguser" + ] + }, + "001": { + "command": [ + "useradd", + "-a", + "-u", + "1001", + "-g", + "1001", + "eguser" + ] + } } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/manifest.json index 9d805bac6514b..bd244eaf3c6a4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.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}/55adc2a4d264e77d2c794df6cb13dd26ee0a9986d5b00a9bfe3cd48b6e0b2dfe.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/db1c5d9623e5e22db4e511f52daf89f93fb1cbb8f325df40d03d5c50413e63a3.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -259,7 +259,10 @@ "/integ-ec2-multiple-instances-in-stack/SecondInstance/Resource": [ { "type": "aws:cdk:logicalId", - "data": "SecondInstance4834A636" + "data": "SecondInstance4834A636", + "trace": [ + "!!DESTRUCTIVE_CHANGES: MAY_REPLACE" + ] } ], "/integ-ec2-multiple-instances-in-stack/BootstrapVersion": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/tree.json index e556e0419844d..11c69d2c333ad 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.js.snapshot/tree.json @@ -1265,7 +1265,7 @@ "Fn::Join": [ "", [ - "#!/bin/bash\n# fingerprint: 8787022e9944cbeb\n(\n set +e\n /opt/aws/bin/cfn-init -v --region ", + "#!/bin/bash\n# fingerprint: 370d9b2dcf8bf44b\n(\n set +e\n /opt/aws/bin/cfn-init -v --region ", { "Ref": "AWS::Region" }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.ts index 87a8ab87c74e6..de01a25b4715f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init-multiple.ts @@ -55,6 +55,12 @@ class TestStack extends cdk.Stack { '/target/path/config.json', path.join(tmpDir, 'testConfigFile2'), ), + ec2.InitCommand.argvCommand([ + 'useradd', '-u', '1001', '-g', '1001', 'eguser', + ]), + ec2.InitCommand.argvCommand([ + 'useradd', '-a', '-u', '1001', '-g', '1001', 'eguser', + ]), ]), }, }), diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init.js.snapshot/manifest.json index b0e1d19683224..e49e7eba966a3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-init.js.snapshot/manifest.json @@ -199,7 +199,10 @@ "/integ-init/Instance2/Resource": [ { "type": "aws:cdk:logicalId", - "data": "Instance255F3526574cbd507dfce8b71" + "data": "Instance255F3526574cbd507dfce8b71", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] } ], "/integ-init/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ @@ -219,15 +222,6 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } - ], - "Instance255F35265a0c5f577d761edb0": [ - { - "type": "aws:cdk:logicalId", - "data": "Instance255F35265a0c5f577d761edb0", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" - ] - } ] }, "displayName": "integ-init" diff --git a/packages/aws-cdk-lib/aws-ec2/lib/cfn-init.ts b/packages/aws-cdk-lib/aws-ec2/lib/cfn-init.ts index bf055b4b27a41..e97992612b233 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/cfn-init.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/cfn-init.ts @@ -311,10 +311,17 @@ function deepMerge(target?: Record, src?: Record) { if (target[key] && !Array.isArray(target[key])) { throw new Error(`Trying to merge array [${value}] into a non-array '${target[key]}'`); } - target[key] = Array.from(new Set([ - ...target[key] ?? [], - ...value, - ])); + if (key === 'command') { // don't deduplicate command arguments + target[key] = new Array( + ...target[key] ?? [], + ...value, + ); + } else { + target[key] = Array.from(new Set([ + ...target[key] ?? [], + ...value, + ])); + } continue; } if (typeof value === 'object' && value) { diff --git a/packages/aws-cdk-lib/aws-ec2/test/cfn-init.test.ts b/packages/aws-cdk-lib/aws-ec2/test/cfn-init.test.ts index bf6823a598988..0a7f5f3a7181b 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/cfn-init.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/cfn-init.test.ts @@ -136,6 +136,68 @@ test('empty configs are not rendered', () => { }); }); +test('duplicate config arguments not deduplicated', () => { + //GIVEN + const config = new ec2.InitConfig([ + ec2.InitCommand.argvCommand([ + 'useradd', '-u', '1001', '-g', '1001', 'eguser', + ]), + ec2.InitCommand.argvCommand([ + 'useradd', '-a', '-u', '1001', '-g', '1001', 'eguser', + ]), + ]); + + // WHEN + const init = ec2.CloudFormationInit.fromConfigSets({ + configSets: { default: ['config'] }, + configs: { config }, + }); + init.attach(resource, linuxOptions()); + + // THEN + expectMetadataLike({ + 'AWS::CloudFormation::Init': { + configSets: { + default: ['config'], + }, + config: { + commands: { + '000': { + command: ['useradd', '-u', '1001', '-g', '1001', 'eguser'], + }, + '001': { + command: ['useradd', '-a', '-u', '1001', '-g', '1001', 'eguser'], + }, + }, + }, + }, + }); +}); + +test('deepMerge properly deduplicates non-command arguments', () => { + // WHEN + const config = new ec2.InitConfig([ + ec2.InitSource.fromUrl('/tmp/blinky', 'https://amazon.com/blinky.zip'), + ec2.InitSource.fromUrl('/tmp/blinky', 'https://amazon.com/blinky.zip'), + ec2.InitSource.fromUrl('/tmp/pinky', 'https://amazon.com/pinky.zip'), + ec2.InitSource.fromUrl('/tmp/pinky', 'https://amazon.com/pinky.zip'), + ec2.InitSource.fromUrl('/tmp/inky', 'https://amazon.com/inky.zip'), + ec2.InitSource.fromUrl('/tmp/clyde', 'https://amazon.com/blinky.zip'), + ec2.InitSource.fromUrl('/tmp/clyde', 'https://amazon.com/blinky.zip'), + ec2.InitSource.fromUrl('/tmp/clyde', 'https://amazon.com/blinky.zip'), + ]); + + // THEN + expect(config._bind(stack, linuxOptions()).config).toEqual(expect.objectContaining({ + sources: { + '/tmp/blinky': 'https://amazon.com/blinky.zip', + '/tmp/pinky': 'https://amazon.com/pinky.zip', + '/tmp/inky': 'https://amazon.com/inky.zip', + '/tmp/clyde': 'https://amazon.com/blinky.zip', + }, + })); +}); + describe('userdata', () => { let simpleInit: ec2.CloudFormationInit; beforeEach(() => { From 7c4f423bf14af996203b090429b8c59bd32f50d8 Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Sat, 10 Aug 2024 04:24:32 +0900 Subject: [PATCH 12/12] feat(elasticloadbalancingv2): connection logs for ALB (#30599) ### Reason for this change ALB can output connection logs as well as access logs to the S3 bucket, but this is not yet supported by L2 Construct. https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html ### Description of changes The implementation is almost the same as for access logs. However, since connection logs are not supported by NLB, but only by ALB, the `logConnectionLogs` method is added to the `ApplicationLoadBalancer` instead of the `BaseLoadBalancer`. The needed BucketPolicy is described in the documentation only as follows, but to support buckets that still use the ACL, it is necessary to set the same policy that is currently set in the access logs. ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::elb-account-id:root" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::bucket-name/prefix/AWSLogs/aws-account-id/*" } ] } ``` https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html#attach-bucket-policy-connection ### Description of how you validated changes add unit tests 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* --- .../aws-cdk-elbv2-integ.assets.json | 6 +- .../aws-cdk-elbv2-integ.template.json | 196 +++++++++- .../cdk.out | 2 +- ...efaultTestDeployAssertAEFAB19B.assets.json | 2 +- .../integ.json | 2 +- .../manifest.json | 16 +- .../tree.json | 231 +++++++++++- .../test/integ.alb.extended.log.ts | 10 +- ...-alb-log-imported-bucket-integ.assets.json | 6 +- ...lb-log-imported-bucket-integ.template.json | 73 +++- .../cdk.out | 2 +- ...efaultTestDeployAssert163162C1.assets.json | 2 +- .../integ.json | 2 +- .../manifest.json | 8 +- .../tree.json | 225 +++++++----- .../test/integ.alb.log.imported-bucket.ts | 1 + .../aws-cdk-elbv2-integ.assets.json | 4 +- .../aws-cdk-elbv2-integ.template.json | 87 ++++- .../integ.alb.log.js.snapshot/manifest.json | 2 +- .../test/integ.alb.log.js.snapshot/tree.json | 87 ++++- .../test/integ.alb.log.ts | 1 + .../aws-elasticloadbalancingv2/README.md | 16 + .../lib/alb/application-load-balancer.ts | 62 ++++ .../test/alb/load-balancer.test.ts | 339 ++++++++++++++++++ 24 files changed, 1234 insertions(+), 148 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json index 5f6c1f273d748..627c94b6f11d6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "33.0.0", + "version": "36.0.0", "files": { - "07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55": { + "dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77": { "source": { "path": "aws-cdk-elbv2-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55.json", + "objectKey": "dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json index ce3d2ff8e018f..428814b9ed734 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json @@ -412,6 +412,20 @@ { "Key": "access_logs.s3.prefix", "Value": "" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "" } ], "Scheme": "internet-facing", @@ -434,7 +448,8 @@ "Type": "application" }, "DependsOn": [ - "LBALBAccessLogsBucket6AE92937", + "LBALBAccessLogsBucketPolicy1E4EBAFE", + "LBALBConnectionLogsBucketPolicy62509153", "VPCPublicSubnet1DefaultRoute91CEF279", "VPCPublicSubnet1RouteTableAssociation0B0896DC", "VPCPublicSubnet2DefaultRouteB7481BBA", @@ -647,6 +662,185 @@ } } }, + "LBALBConnectionLogsBucket4BFA48DB": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "LoggingConfiguration": { + "LogFilePrefix": "selflog/" + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "VersioningConfiguration": { + "Status": "Enabled" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LBALBConnectionLogsBucketPolicy62509153": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + }, + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "logging.s3.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/selflog/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + } + } + }, "LBListener49E825B4": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "Properties": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out index 560dae10d018f..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"33.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json index c98fca8690504..dc7f5be9c0bd5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json index b013204787762..28a35b8f9fe2f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "testCases": { "cdk-integ-alb-extended-log/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json index e13264e6591cb..0e3250c83fd85 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "artifacts": { "aws-cdk-elbv2-integ.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -196,6 +196,18 @@ "data": "LBALBAccessLogsBucketPolicy1E4EBAFE" } ], + "/aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBALBConnectionLogsBucket4BFA48DB" + } + ], + "/aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBALBConnectionLogsBucketPolicy62509153" + } + ], "/aws-cdk-elbv2-integ/LB/Listener/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json index 42f17234eebb4..c87d487493897 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json @@ -679,6 +679,20 @@ { "key": "access_logs.s3.prefix", "value": "" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "" } ], "scheme": "internet-facing", @@ -964,6 +978,219 @@ "version": "0.0.0" } }, + "ALBConnectionLogsBucket": { + "id": "ALBConnectionLogsBucket", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketEncryption": { + "serverSideEncryptionConfiguration": [ + { + "serverSideEncryptionByDefault": { + "sseAlgorithm": "AES256" + } + } + ] + }, + "loggingConfiguration": { + "logFilePrefix": "selflog/" + }, + "publicAccessBlockConfiguration": { + "blockPublicAcls": true, + "blockPublicPolicy": true, + "ignorePublicAcls": true, + "restrictPublicBuckets": true + }, + "versioningConfiguration": { + "status": "Enabled" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + }, + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "logging.s3.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/selflog/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, "Listener": { "id": "Listener", "path": "aws-cdk-elbv2-integ/LB/Listener", @@ -1089,7 +1316,7 @@ "path": "cdk-integ-alb-extended-log/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } }, "DeployAssert": { @@ -1135,7 +1362,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts index 17b1a0009461e..5fc676d118357 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts @@ -18,8 +18,16 @@ class ExtendedLB extends elbv2.ApplicationLoadBalancer { serverAccessLogsPrefix: 'selflog/', enforceSSL: true, }); - this.logAccessLogs(accessLogsBucket); + + const connectionLogsBucket = new s3.Bucket(this, 'ALBConnectionLogsBucket', { + blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, + encryption: s3.BucketEncryption.S3_MANAGED, + versioned: true, + serverAccessLogsPrefix: 'selflog/', + enforceSSL: true, + }); + this.logConnectionLogs(connectionLogsBucket); } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json index 3e91c58d25201..9234509c27957 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { - "d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b": { + "7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046": { "source": { "path": "aws-cdk-alb-log-imported-bucket-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b.json", + "objectKey": "7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json index e596a9c1e41e8..ff10559471e6d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json @@ -438,6 +438,47 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, "Resource": { "Fn::Join": [ "", @@ -445,21 +486,16 @@ "arn:aws:s3:::", { "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" + } ] ] } }, { - "Action": "s3:GetBucketAcl", + "Action": "s3:PutObject", "Effect": "Allow", "Principal": { - "Service": "delivery.logs.amazonaws.com" + "AWS": "arn:aws:iam::797873946194:root" }, "Resource": { "Fn::Join": [ @@ -468,7 +504,12 @@ "arn:aws:s3:::", { "Ref": "Bucket83908E77" - } + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] ] } @@ -499,6 +540,20 @@ { "Key": "access_logs.s3.prefix", "Value": "prefix" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "Bucket83908E77" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "prefix-connection-log" } ], "Scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out index 2313ab5436501..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"34.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json index e45f2e7f3aa99..33278825135ec 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json index 5198aa8d08cc7..c2f7d046cc525 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "testCases": { "cdk-integ-alb-log-imported-bucket/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json index 4c9a325295e57..e0362c5216bff 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "artifacts": { "aws-cdk-alb-log-imported-bucket-integ.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -178,10 +178,10 @@ "data": "Bucket83908E77" } ], - "/aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy/Resource": [ + "/aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImportedBucketPolicy71C80354" + "data": "ImportedBucketPolicyAE50CA2C" } ], "/aws-cdk-alb-log-imported-bucket-integ/LB/Resource": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json index ebc9d24af07a2..f5423598f7b90 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json @@ -676,110 +676,149 @@ "ImportedBucket": { "id": "ImportedBucket", "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + }, + "ImportedBucketPolicy": { + "id": "ImportedBucketPolicy", + "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy", "children": { - "Policy": { - "id": "Policy", - "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", - "aws:cdk:cloudformation:props": { - "bucket": { - "Ref": "Bucket83908E77" + "Resource": { + "id": "Resource", + "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "Bucket83908E77" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } }, - "policyDocument": { - "Statement": [ + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": [ { - "Action": "s3:PutObject", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam::797873946194:root" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" - ] + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] - } + ] }, { - "Action": "s3:PutObject", - "Condition": { - "StringEquals": { - "s3:x-amz-acl": "bucket-owner-full-control" - } - }, - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" - ] + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] - } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - } - ] - ] - } + ] } - ], - "Version": "2012-10-17" + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + } + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", - "version": "0.0.0" + ], + "Version": "2012-10-17" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", "version": "0.0.0" } }, @@ -811,6 +850,20 @@ { "key": "access_logs.s3.prefix", "value": "prefix" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "Bucket83908E77" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "prefix-connection-log" } ], "scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts index 0aefeaa37378e..cd79500605179 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts @@ -27,6 +27,7 @@ const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { }); lb.logAccessLogs(importedBucket, 'prefix'); +lb.logConnectionLogs(importedBucket, 'prefix-connection-log'); const listener = lb.addListener('Listener', { port: 80, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json index 462409afac89d..19a55187da880 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json @@ -15,7 +15,7 @@ } } }, - "e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97": { + "c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8": { "source": { "path": "aws-cdk-elbv2-integ.template.json", "packaging": "file" @@ -23,7 +23,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97.json", + "objectKey": "c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json index 49fdcd32c9472..77f2b0a8c6b32 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json @@ -487,6 +487,64 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, "Resource": { "Fn::Join": [ "", @@ -497,7 +555,7 @@ "Arn" ] }, - "/prefix/AWSLogs/", + "/prefix-connection-log/AWSLogs/", { "Ref": "AWS::AccountId" }, @@ -505,19 +563,6 @@ ] ] } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "Bucket83908E77", - "Arn" - ] - } } ], "Version": "2012-10-17" @@ -622,6 +667,20 @@ { "Key": "access_logs.s3.prefix", "Value": "prefix" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "Bucket83908E77" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "prefix-connection-log" } ], "Scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json index 0cd90bc7f55a6..1fe10a574fc59 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json index 90720258641d3..819371b497c9a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json @@ -764,6 +764,64 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, "Resource": { "Fn::Join": [ "", @@ -774,7 +832,7 @@ "Arn" ] }, - "/prefix/AWSLogs/", + "/prefix-connection-log/AWSLogs/", { "Ref": "AWS::AccountId" }, @@ -782,19 +840,6 @@ ] ] } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "Bucket83908E77", - "Arn" - ] - } } ], "Version": "2012-10-17" @@ -898,6 +943,20 @@ { "key": "access_logs.s3.prefix", "value": "prefix" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "Bucket83908E77" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "prefix-connection-log" } ], "scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts index cab793d0e6a35..69a96e98340f6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts @@ -25,6 +25,7 @@ const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { }); lb.logAccessLogs(bucket, 'prefix'); +lb.logConnectionLogs(bucket, 'prefix-connection-log'); const listener = lb.addListener('Listener', { port: 80, diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md index 0f16e99b08917..3fbbce053d021 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md @@ -267,6 +267,22 @@ lb.logAccessLogs(bucket); ``` +### Setting up Connection Log Bucket on Application Load Balancer + +Like access log bucket, the only server-side encryption option that's supported is Amazon S3-managed keys (SSE-S3). For more information +Documentation: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html + +```ts +declare const vpc: ec2.Vpc; + +const bucket = new s3.Bucket(this, 'ALBConnectionLogsBucket',{ + encryption: s3.BucketEncryption.S3_MANAGED, +}); + +const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc }); +lb.logConnectionLogs(bucket); +``` + ## Defining a Network Load Balancer Network Load Balancers are defined in a similar way to Application Load diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts index 0ec173c7b77df..2636e26abbdd5 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts @@ -312,6 +312,68 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic } } + /** + * Enable connection logging for this load balancer. + * + * A region must be specified on the stack containing the load balancer; you cannot enable logging on + * environment-agnostic stacks. + * + * @see https://docs.aws.amazon.com/cdk/latest/guide/environments.html + */ + public logConnectionLogs(bucket: s3.IBucket, prefix?: string) { + /** + * KMS key encryption is not supported on Connection Log bucket for ALB, the bucket must use Amazon S3-managed keys (SSE-S3). + * See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html#bucket-permissions-troubleshooting-connection + */ + if (bucket.encryptionKey) { + throw new Error('Encryption key detected. Bucket encryption using KMS keys is unsupported'); + } + + prefix = prefix || ''; + this.setAttribute('connection_logs.s3.enabled', 'true'); + this.setAttribute('connection_logs.s3.bucket', bucket.bucketName.toString()); + this.setAttribute('connection_logs.s3.prefix', prefix); + + // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html + const logsDeliveryServicePrincipal = new ServicePrincipal('delivery.logs.amazonaws.com'); + bucket.addToResourcePolicy(new PolicyStatement({ + actions: ['s3:PutObject'], + principals: [this.resourcePolicyPrincipal()], + resources: [ + bucket.arnForObjects(`${prefix ? prefix + '/' : ''}AWSLogs/${Stack.of(this).account}/*`), + ], + })); + // We still need this policy for the bucket using the ACL + bucket.addToResourcePolicy( + new PolicyStatement({ + actions: ['s3:PutObject'], + principals: [logsDeliveryServicePrincipal], + resources: [ + bucket.arnForObjects(`${prefix ? prefix + '/' : ''}AWSLogs/${Stack.of(this).account}/*`), + ], + conditions: { + StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' }, + }, + }), + ); + bucket.addToResourcePolicy( + new PolicyStatement({ + actions: ['s3:GetBucketAcl'], + principals: [logsDeliveryServicePrincipal], + resources: [bucket.bucketArn], + }), + ); + + // make sure the bucket's policy is created before the ALB (see https://github.com/aws/aws-cdk/issues/1633) + // at the L1 level to avoid creating a circular dependency (see https://github.com/aws/aws-cdk/issues/27528 + // and https://github.com/aws/aws-cdk/issues/27928) + const lb = this.node.defaultChild; + const bucketPolicy = bucket.policy?.node.defaultChild; + if (lb && bucketPolicy && CfnResource.isCfnResource(lb) && CfnResource.isCfnResource(bucketPolicy)) { + lb.addDependency(bucketPolicy); + } + } + /** * Add a security group to this load balancer */ diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts index 958a881846fab..6838181872275 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts @@ -645,6 +645,345 @@ describe('tests', () => { }); }); + describe('logConnectionLogs', () => { + + class ExtendedLB extends elbv2.ApplicationLoadBalancer { + constructor(scope: Construct, id: string, vpc: ec2.IVpc) { + super(scope, id, { vpc }); + + const connectionLogsBucket = new s3.Bucket(this, 'ALBConnectionLogsBucket', { + blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, + encryption: s3.BucketEncryption.S3_MANAGED, + versioned: true, + serverAccessLogsPrefix: 'selflog/', + enforceSSL: true, + }); + + this.logConnectionLogs(connectionLogsBucket); + } + } + + function loggingSetup(withEncryption: boolean = false ): { stack: cdk.Stack; bucket: s3.Bucket; lb: elbv2.ApplicationLoadBalancer } { + const app = new cdk.App(); + const stack = new cdk.Stack(app, undefined, { env: { region: 'us-east-1' } }); + const vpc = new ec2.Vpc(stack, 'Stack'); + let bucketProps = {}; + if (withEncryption) { + const kmsKey = new Key(stack, 'TestKMSKey'); + bucketProps = { ...bucketProps, encryption: s3.BucketEncryption.KMS, encyptionKey: kmsKey }; + } + const bucket = new s3.Bucket(stack, 'ConnectionLogBucket', { ...bucketProps }); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + return { stack, bucket, lb }; + } + + test('sets load balancer attributes', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + //THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: { Ref: 'ConnectionLogBucketFDE8490A' }, + }, + { + Key: 'connection_logs.s3.prefix', + Value: '', + }, + ]), + }); + }); + + test('adds a dependency on the bucket', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify the ALB depends on the bucket policy + Template.fromStack(stack).hasResource('AWS::ElasticLoadBalancingV2::LoadBalancer', { + DependsOn: ['ConnectionLogBucketPolicyF17C8635'], + }); + }); + + test('logging bucket permissions', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('connection logging with prefix', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket, 'prefix-of-connection-logs'); + + // THEN + // verify that the LB attributes reference the bucket + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: { Ref: 'ConnectionLogBucketFDE8490A' }, + }, + { + Key: 'connection_logs.s3.prefix', + Value: 'prefix-of-connection-logs', + }, + ]), + }); + + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/prefix-of-connection-logs/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/prefix-of-connection-logs/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('bucket with KMS throws validation error', () => { + //GIVEN + const { stack, bucket, lb } = loggingSetup(true); + + // WHEN + const logConnectionLogFunctionTest = () => lb.logConnectionLogs(bucket); + + // THEN + // verify failure in case the connection log bucket is encrypted with KMS + expect(logConnectionLogFunctionTest).toThrow('Encryption key detected. Bucket encryption using KMS keys is unsupported'); + + }); + + test('connection logging on imported bucket', () => { + // GIVEN + const { stack, lb } = loggingSetup(); + + const bucket = s3.Bucket.fromBucketName(stack, 'ImportedConnectionLoggingBucket', 'imported-bucket'); + // Imported buckets have `autoCreatePolicy` disabled by default + bucket.policy = new s3.BucketPolicy(stack, 'ImportedConnectionLoggingBucketPolicy', { + bucket, + }); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify that the LB attributes reference the bucket + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: 'imported-bucket', + }, + { + Key: 'connection_logs.s3.prefix', + Value: '', + }, + ]), + }); + + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket/AWSLogs/', + { Ref: 'AWS::AccountId' }, + '/*', + ], + ], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket/AWSLogs/', + { Ref: 'AWS::AccountId' }, + '/*', + ], + ], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket', + ], + ], + }, + }, + ], + }, + }); + + // verify the ALB depends on the bucket policy + Template.fromStack(stack).hasResource('AWS::ElasticLoadBalancingV2::LoadBalancer', { + DependsOn: ['ImportedConnectionLoggingBucketPolicy548EEC12'], + }); + }); + + test('does not add circular dependency on bucket with extended load balancer', () => { + // GIVEN + const { stack } = loggingSetup(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + + // WHEN + new ExtendedLB(stack, 'ExtendedLB', vpc); + + // THEN + Template.fromStack(stack).hasResource('AWS::S3::Bucket', { + Type: 'AWS::S3::Bucket', + Properties: { + AccessControl: 'LogDeliveryWrite', + BucketEncryption: { + ServerSideEncryptionConfiguration: [ + { + ServerSideEncryptionByDefault: { + SSEAlgorithm: 'AES256', + }, + }, + ], + }, + LoggingConfiguration: { + LogFilePrefix: 'selflog/', + }, + OwnershipControls: { + Rules: [ + { + ObjectOwnership: 'ObjectWriter', + }, + ], + }, + PublicAccessBlockConfiguration: { + BlockPublicAcls: true, + BlockPublicPolicy: true, + IgnorePublicAcls: true, + RestrictPublicBuckets: true, + }, + VersioningConfiguration: { + Status: 'Enabled', + }, + }, + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + DependsOn: Match.absent(), + }); + }); + }); + test('Exercise metrics', () => { // GIVEN const stack = new cdk.Stack();