diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index 9682da4675bda..f7580ebb38ef8 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.172.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.171.1-alpha.0...v2.172.0-alpha.0) (2024-12-06) + + +### Features + +* **ec2:** default BastionHostLinux to use Amazon Linux 2023 (under feature flag) ([#31996](https://github.com/aws/aws-cdk/issues/31996)) ([bf77e51](https://github.com/aws/aws-cdk/commit/bf77e51c90e3da972c464430d579695163160a13)), closes [#29493](https://github.com/aws/aws-cdk/issues/29493) [#29493](https://github.com/aws/aws-cdk/issues/29493) +* **ec2:** instance support passing IAM instance profile ([#32073](https://github.com/aws/aws-cdk/issues/32073)) ([cf89d0f](https://github.com/aws/aws-cdk/commit/cf89d0f67f6d03bdeec38a4ffb48d3cda59db7cc)), closes [#8348](https://github.com/aws/aws-cdk/issues/8348) +* **neptune:** auto minor version upgrade for an instance ([#31988](https://github.com/aws/aws-cdk/issues/31988)) ([d95db49](https://github.com/aws/aws-cdk/commit/d95db491f7c1fd11dd42299f99d40fd94b0d642f)) +* **pipes:** add LogDestination implementation ([#31672](https://github.com/aws/aws-cdk/issues/31672)) ([af5345e](https://github.com/aws/aws-cdk/commit/af5345e9ed2528bde2af6cd4b2428654b096eb93)), closes [#31671](https://github.com/aws/aws-cdk/issues/31671) +* **pipes-targets:** add API Gateway ([#31954](https://github.com/aws/aws-cdk/issues/31954)) ([c77536f](https://github.com/aws/aws-cdk/commit/c77536f8999e221c8d6dae5742f484a04b05bac5)) +* **redshift:** execute resource action ([#31995](https://github.com/aws/aws-cdk/issues/31995)) ([40835a0](https://github.com/aws/aws-cdk/commit/40835a01536509daefa44e5e4cad5d8829d8dd1c)) + + +### Bug Fixes + +* **scheduler-targets-alpha:** incorrect validation of maximumEventAge ([#32284](https://github.com/aws/aws-cdk/issues/32284)) ([2eebc59](https://github.com/aws/aws-cdk/commit/2eebc5913966f0266efbad65c3f137c07c75270b)) + ## [2.171.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.171.0-alpha.0...v2.171.1-alpha.0) (2024-11-27) ## [2.171.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.170.0-alpha.0...v2.171.0-alpha.0) (2024-11-25) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index 42cf512a04cd9..71b5f4db75fa5 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -2,6 +2,44 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.172.0](https://github.com/aws/aws-cdk/compare/v2.171.1...v2.172.0) (2024-12-06) + + +### ⚠ BREAKING CHANGES TO EXPERIMENTAL FEATURES + +* **apigateway:** We will be removing deprecated `APIGatewayV2` constructs from `aws-apigateway` module. + +*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* + +### Features + +* **aspects:** priority-ordered aspect invocation ([#32097](https://github.com/aws/aws-cdk/issues/32097)) ([8ccdff4](https://github.com/aws/aws-cdk/commit/8ccdff4ee083d66f73259223ba75ba0b8a0752a0)), closes [#21341](https://github.com/aws/aws-cdk/issues/21341) [/github.com/aws/aws-cdk/blob/8b495f9ec157c0b00674715f62b1bbcabf2096ac/packages/aws-cdk-lib/core/lib/private/synthesis.ts#L217](https://github.com/aws//github.com/aws/aws-cdk/blob/8b495f9ec157c0b00674715f62b1bbcabf2096ac/packages/aws-cdk-lib/core/lib/private/synthesis.ts/issues/L217) +* **cognito:** new `cloudFrontEndpoint` method for user pool domain without custom resource ([#31402](https://github.com/aws/aws-cdk/issues/31402)) ([deeb2ad](https://github.com/aws/aws-cdk/commit/deeb2ad0bc38101a9f1fa8162ad5d6008900a98d)), closes [#31342](https://github.com/aws/aws-cdk/issues/31342) [/github.com/go-to-k/aws-cdk/blob/fcbdc769e681f1f915cdc8cd7aa3a565d807884d/packages/aws-cdk-lib/aws-route53-targets/lib/userpool-domain.ts#L14](https://github.com/aws//github.com/go-to-k/aws-cdk/blob/fcbdc769e681f1f915cdc8cd7aa3a565d807884d/packages/aws-cdk-lib/aws-route53-targets/lib/userpool-domain.ts/issues/L14) +* **cognito:** support for ALLOW_USER_AUTH explicit auth flow ([#32273](https://github.com/aws/aws-cdk/issues/32273)) ([c5bcfdc](https://github.com/aws/aws-cdk/commit/c5bcfdc57aa763539b31f4e7f6f115f707c401a4)) +* **elasticloadbalancingv2:** ip address type for both network and application target group ([#32189](https://github.com/aws/aws-cdk/issues/32189)) ([7cc5f30](https://github.com/aws/aws-cdk/commit/7cc5f305c839048454240f8d6db1614e2dfa4c53)) +* **events:** add filter rules for prefixEqualsIgnoreCase, suffixEqualsIgnoreCase, wildcard, and anythingBut* matches ([#32063](https://github.com/aws/aws-cdk/issues/32063)) ([0ce71fc](https://github.com/aws/aws-cdk/commit/0ce71fc50cffffc04d9d1bc9c98c9c04e77bfe1f)), closes [#28462](https://github.com/aws/aws-cdk/issues/28462) +* **lambda-nodejs:** add bun support ([#31770](https://github.com/aws/aws-cdk/issues/31770)) ([aed8ad1](https://github.com/aws/aws-cdk/commit/aed8ad10c3d86497be34b2889466f770910d36ef)), closes [#31753](https://github.com/aws/aws-cdk/issues/31753) [#31753](https://github.com/aws/aws-cdk/issues/31753) +* **rds:** limitless database cluster ([#32151](https://github.com/aws/aws-cdk/issues/32151)) ([f4c19c7](https://github.com/aws/aws-cdk/commit/f4c19c71ca8a34188f1d26f756ef5b3ec218b5c2)) +* **ses:** add support to disable account-level suppression list ([#32168](https://github.com/aws/aws-cdk/issues/32168)) ([bb50c1a](https://github.com/aws/aws-cdk/commit/bb50c1abc8c507e2b877a952377adc607b936eab)), closes [#32149](https://github.com/aws/aws-cdk/issues/32149) +* update L1 CloudFormation resource definitions ([#32272](https://github.com/aws/aws-cdk/issues/32272)) ([421d327](https://github.com/aws/aws-cdk/commit/421d32708f5018353b2c5db1751cb3415412b985)) +* update L1 CloudFormation resource definitions ([#32356](https://github.com/aws/aws-cdk/issues/32356)) ([9e6bb24](https://github.com/aws/aws-cdk/commit/9e6bb24f533c11bbb74a30a729566f91f5d6a13f)) +* **route53-targets:** add `AppSync` route53 target ([#31976](https://github.com/aws/aws-cdk/issues/31976)) ([dc7574a](https://github.com/aws/aws-cdk/commit/dc7574a3c048fdb58ca1ac996dbe46fd54b59993)), closes [#26109](https://github.com/aws/aws-cdk/issues/26109) + + +### Bug Fixes + +* **apigateway:** remove deprecated apigatewayv2 from aws-apigateway module ([#32297](https://github.com/aws/aws-cdk/issues/32297)) ([4db9565](https://github.com/aws/aws-cdk/commit/4db956597b41bb9d7dd8e1d65b39643772065353)) +* **appsync:** `appsync.HttpDataSourceProps` erroneously extends `BaseDataSourceProps` ([#32065](https://github.com/aws/aws-cdk/issues/32065)) ([4e7f5c4](https://github.com/aws/aws-cdk/commit/4e7f5c4469509ed4e1d586a9c5263f19b540a7bd)), closes [#29689](https://github.com/aws/aws-cdk/issues/29689) +* **cli:** assume role calls are skipping the proxy ([#32291](https://github.com/aws/aws-cdk/issues/32291)) ([6c0f74e](https://github.com/aws/aws-cdk/commit/6c0f74e4b37b8ef81c927adca1112680d0bf2ad0)) +* **cli:** lambda hotswap fails if `lambda:GetFunctionConfiguration` action is not allowed ([#32301](https://github.com/aws/aws-cdk/issues/32301)) ([be000a2](https://github.com/aws/aws-cdk/commit/be000a251b781b0b0870930992793df5a2fc4b01)), closes [/github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdatedV2.ts#L10](https://github.com/aws//github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdatedV2.ts/issues/L10) [/github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdated.ts#L13](https://github.com/aws//github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdated.ts/issues/L13) +* **cli:** mfa code is not requested when `$AWS_PROFILE` is used ([#32313](https://github.com/aws/aws-cdk/issues/32313)) ([6458439](https://github.com/aws/aws-cdk/commit/6458439b08f9ce1f49c1137dd85bb582550a5f52)), closes [#32312](https://github.com/aws/aws-cdk/issues/32312) +* **cli:** remove source maps ([#32317](https://github.com/aws/aws-cdk/issues/32317)) ([512cf95](https://github.com/aws/aws-cdk/commit/512cf952f3971cd302fb1cca7c24149b43832280)), closes [#19930](https://github.com/aws/aws-cdk/issues/19930) [#19930](https://github.com/aws/aws-cdk/issues/19930) +* **cli:** short-lived credentials are not refreshed ([#32354](https://github.com/aws/aws-cdk/issues/32354)) ([058a0bf](https://github.com/aws/aws-cdk/commit/058a0bfc22036230252fcbc026576260723f6d28)) +* **cli:** warns about missing `--no-rollback` flag that is present ([#32309](https://github.com/aws/aws-cdk/issues/32309)) ([559d676](https://github.com/aws/aws-cdk/commit/559d676e2989739b38491b1f767face839d39f69)), closes [#32295](https://github.com/aws/aws-cdk/issues/32295) +* **cloudformation-include:** drops unknown policy attributes ([#32321](https://github.com/aws/aws-cdk/issues/32321)) ([20edc7f](https://github.com/aws/aws-cdk/commit/20edc7fe5e891461a8188d306dcc0f776041cf8f)) +* **cloudfront:** propagate `originAccessControlId` CloudFront Origin property to CloudFormation templates ([#32020](https://github.com/aws/aws-cdk/issues/32020)) ([f9708a6](https://github.com/aws/aws-cdk/commit/f9708a634ceaef7f62e8193443ea30fe9e2fbad6)), closes [#32018](https://github.com/aws/aws-cdk/issues/32018) +* **iam:** `Role.addManagedPolicy()` does not work for imported roles `IRole` [#8307](https://github.com/aws/aws-cdk/issues/8307) ([#31212](https://github.com/aws/aws-cdk/issues/31212)) ([c78ef1b](https://github.com/aws/aws-cdk/commit/c78ef1b43a18e1ffc93fcbdee9dd2e91fa750a36)), closes [/github.com/aws/aws-cdk/blob/823ff6e03899f790a4cb1c43f92a02cc906ac356/packages/aws-cdk-lib/aws-iam/lib/identity-base.ts#L17-L21](https://github.com/aws//github.com/aws/aws-cdk/blob/823ff6e03899f790a4cb1c43f92a02cc906ac356/packages/aws-cdk-lib/aws-iam/lib/identity-base.ts/issues/L17-L21) + ## [2.171.1](https://github.com/aws/aws-cdk/compare/v2.171.0...v2.171.1) (2024-11-27) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.assets.json new file mode 100644 index 0000000000000..34d0c4649041f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "fa46958bcb246c27c21906c9bf41a44bce7f9613a3d90335588eedc4daeb49dd": { + "source": { + "path": "NlbEnablePrefixForIpv6NatStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "fa46958bcb246c27c21906c9bf41a44bce7f9613a3d90335588eedc4daeb49dd.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-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.template.json new file mode 100644 index 0000000000000..a5031e0a2dafc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStack.template.json @@ -0,0 +1,707 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc" + } + ] + } + }, + "Vpcipv6cidr40D3CB78": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": true, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "Ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78", + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1DefaultRoute6A21265FB": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationIpv6CidrBlock": "::/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": true, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "Ipv6CidrBlock": { + "Fn::Select": [ + 1, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78", + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2DefaultRoute63E63096C": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationIpv6CidrBlock": "::/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet1SubnetE48C5737": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": true, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "Ipv6CidrBlock": { + "Fn::Select": [ + 2, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet1RouteTable4771E3E5": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet1RouteTableAssociationD300FCBB": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcIsolatedSubnet1RouteTable4771E3E5" + }, + "SubnetId": { + "Ref": "VpcIsolatedSubnet1SubnetE48C5737" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet2Subnet16364B91": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": true, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "Ipv6CidrBlock": { + "Fn::Select": [ + 3, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet2RouteTable1D30AF7D": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIsolatedSubnet2RouteTableAssociationF7B18CCA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcIsolatedSubnet2RouteTable1D30AF7D" + }, + "SubnetId": { + "Ref": "VpcIsolatedSubnet2Subnet16364B91" + } + }, + "DependsOn": [ + "Vpcipv6cidr40D3CB78" + ] + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "NlbEnablePrefixForIpv6NatStack/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcEIGW61416F369": { + "Type": "AWS::EC2::EgressOnlyInternetGateway", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "DisabledLbSgB7154DC8": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "NlbEnablePrefixForIpv6NatStack/DisabledLbSg", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "DisabledLbF70482DB": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "EnablePrefixForIpv6SourceNat": "off", + "IpAddressType": "dualstack", + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "DisabledLbSgB7154DC8", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "Type": "network" + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1DefaultRoute6A21265FB", + "VpcPublicSubnet1RouteTableAssociation97140677", + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2DefaultRoute63E63096C", + "VpcPublicSubnet2RouteTableAssociationDD5762D8" + ] + }, + "DisabledLbTcpListener070B4D6E": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "TcpTargetGroupD98C5CDB" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "DisabledLbF70482DB" + }, + "Port": 1229, + "Protocol": "TCP" + } + }, + "TcpTargetGroupD98C5CDB": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "IpAddressType": "ipv6", + "Port": 1229, + "Protocol": "TCP", + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "EnabledLbSg11D53248": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "NlbEnablePrefixForIpv6NatStack/EnabledLbSg", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "EnabledLb9F3E8D30": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "EnablePrefixForIpv6SourceNat": "on", + "IpAddressType": "dualstack", + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EnabledLbSg11D53248", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "Type": "network" + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1DefaultRoute6A21265FB", + "VpcPublicSubnet1RouteTableAssociation97140677", + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2DefaultRoute63E63096C", + "VpcPublicSubnet2RouteTableAssociationDD5762D8" + ] + }, + "EnabledLbUdpListener550E1122": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "UdpTargetGroup5F89FEC0" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "EnabledLb9F3E8D30" + }, + "Port": 1229, + "Protocol": "UDP" + } + }, + "EnabledLbTcpWithUdpListenerBBFA335D": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "TcpWithUdpTargetGroup827EE6D7" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "EnabledLb9F3E8D30" + }, + "Port": 3502, + "Protocol": "TCP_UDP" + } + }, + "UdpTargetGroup5F89FEC0": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "IpAddressType": "ipv6", + "Port": 1229, + "Protocol": "UDP", + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "TcpWithUdpTargetGroup827EE6D7": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "IpAddressType": "ipv6", + "Port": 3502, + "Protocol": "TCP_UDP", + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + } + }, + "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-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets.json new file mode 100644 index 0000000000000..a47c44feab324 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.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-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.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-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/integ.json new file mode 100644 index 0000000000000..2512b45a69413 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "38.0.1", + "testCases": { + "NlbEnablePrefixForIpv6NatStackTest/DefaultTest": { + "stacks": [ + "NlbEnablePrefixForIpv6NatStack" + ], + "assertionStack": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert", + "assertionStackName": "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/manifest.json new file mode 100644 index 0000000000000..c9ae9e3d676a6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/manifest.json @@ -0,0 +1,311 @@ +{ + "version": "38.0.1", + "artifacts": { + "NlbEnablePrefixForIpv6NatStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "NlbEnablePrefixForIpv6NatStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "NlbEnablePrefixForIpv6NatStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "NlbEnablePrefixForIpv6NatStack.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}/fa46958bcb246c27c21906c9bf41a44bce7f9613a3d90335588eedc4daeb49dd.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "NlbEnablePrefixForIpv6NatStack.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": [ + "NlbEnablePrefixForIpv6NatStack.assets" + ], + "metadata": { + "/NlbEnablePrefixForIpv6NatStack/Vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpc8378EB38" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/ipv6cidr": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpcipv6cidr40D3CB78" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1Subnet5C2D37C4" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTable6C95E38E" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTableAssociation97140677" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/DefaultRoute6": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute6A21265FB" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTable94F7E489" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTableAssociationDD5762D8" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2DefaultRoute97F91067" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/DefaultRoute6": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2DefaultRoute63E63096C" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet1SubnetE48C5737" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet1RouteTable4771E3E5" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet1RouteTableAssociationD300FCBB" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet2Subnet16364B91" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet2RouteTable1D30AF7D" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIsolatedSubnet2RouteTableAssociationF7B18CCA" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIGWD7BA715C" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcVPCGWBF912B6E" + } + ], + "/NlbEnablePrefixForIpv6NatStack/Vpc/EIGW6": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcEIGW61416F369" + } + ], + "/NlbEnablePrefixForIpv6NatStack/DisabledLbSg/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DisabledLbSgB7154DC8" + } + ], + "/NlbEnablePrefixForIpv6NatStack/DisabledLb/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DisabledLbF70482DB" + } + ], + "/NlbEnablePrefixForIpv6NatStack/DisabledLb/TcpListener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DisabledLbTcpListener070B4D6E" + } + ], + "/NlbEnablePrefixForIpv6NatStack/TcpTargetGroup": [ + { + "type": "aws:cdk:warning", + "data": "When creating an empty TargetGroup, you should specify a 'targetType' (this warning may become an error in the future). [ack: @aws-cdk/aws-elbv2:targetGroupSpecifyTargetTypeForEmptyTargetGroup]" + } + ], + "/NlbEnablePrefixForIpv6NatStack/TcpTargetGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TcpTargetGroupD98C5CDB" + } + ], + "/NlbEnablePrefixForIpv6NatStack/EnabledLbSg/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EnabledLbSg11D53248" + } + ], + "/NlbEnablePrefixForIpv6NatStack/EnabledLb/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EnabledLb9F3E8D30" + } + ], + "/NlbEnablePrefixForIpv6NatStack/EnabledLb/UdpListener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EnabledLbUdpListener550E1122" + } + ], + "/NlbEnablePrefixForIpv6NatStack/EnabledLb/TcpWithUdpListener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EnabledLbTcpWithUdpListenerBBFA335D" + } + ], + "/NlbEnablePrefixForIpv6NatStack/UdpTargetGroup": [ + { + "type": "aws:cdk:warning", + "data": "When creating an empty TargetGroup, you should specify a 'targetType' (this warning may become an error in the future). [ack: @aws-cdk/aws-elbv2:targetGroupSpecifyTargetTypeForEmptyTargetGroup]" + } + ], + "/NlbEnablePrefixForIpv6NatStack/UdpTargetGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "UdpTargetGroup5F89FEC0" + } + ], + "/NlbEnablePrefixForIpv6NatStack/TcpWithUdpTargetGroup": [ + { + "type": "aws:cdk:warning", + "data": "When creating an empty TargetGroup, you should specify a 'targetType' (this warning may become an error in the future). [ack: @aws-cdk/aws-elbv2:targetGroupSpecifyTargetTypeForEmptyTargetGroup]" + } + ], + "/NlbEnablePrefixForIpv6NatStack/TcpWithUdpTargetGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TcpWithUdpTargetGroup827EE6D7" + } + ], + "/NlbEnablePrefixForIpv6NatStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/NlbEnablePrefixForIpv6NatStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "NlbEnablePrefixForIpv6NatStack" + }, + "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.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": [ + "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.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": [ + "NlbEnablePrefixForIpv6NatStackTestDefaultTestDeployAssert4C17D694.assets" + ], + "metadata": { + "/NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "NlbEnablePrefixForIpv6NatStackTest/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-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/tree.json new file mode 100644 index 0000000000000..75cb2ae8bbbe6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.js.snapshot/tree.json @@ -0,0 +1,1134 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "NlbEnablePrefixForIpv6NatStack": { + "id": "NlbEnablePrefixForIpv6NatStack", + "path": "NlbEnablePrefixForIpv6NatStack", + "children": { + "Vpc": { + "id": "Vpc", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "ipv6cidr": { + "id": "ipv6cidr", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/ipv6cidr", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": true, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "ipv6CidrBlock": { + "Fn::Select": [ + 0, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "Acl": { + "id": "Acl", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DefaultRoute6": { + "id": "DefaultRoute6", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet1/DefaultRoute6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationIpv6CidrBlock": "::/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": true, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "ipv6CidrBlock": { + "Fn::Select": [ + 1, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "Acl": { + "id": "Acl", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DefaultRoute6": { + "id": "DefaultRoute6", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/PublicSubnet2/DefaultRoute6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationIpv6CidrBlock": "::/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "IsolatedSubnet1": { + "id": "IsolatedSubnet1", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": true, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "ipv6CidrBlock": { + "Fn::Select": [ + 2, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "Acl": { + "id": "Acl", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcIsolatedSubnet1RouteTable4771E3E5" + }, + "subnetId": { + "Ref": "VpcIsolatedSubnet1SubnetE48C5737" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "IsolatedSubnet2": { + "id": "IsolatedSubnet2", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": true, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "ipv6CidrBlock": { + "Fn::Select": [ + 3, + { + "Fn::Cidr": [ + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "Vpc8378EB38", + "Ipv6CidrBlocks" + ] + } + ] + }, + 4, + "64" + ] + } + ] + }, + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Isolated" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Isolated" + }, + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "Acl": { + "id": "Acl", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/Acl", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IsolatedSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcIsolatedSubnet2RouteTable1D30AF7D" + }, + "subnetId": { + "Ref": "VpcIsolatedSubnet2Subnet16364B91" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "IGW": { + "id": "IGW", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "NlbEnablePrefixForIpv6NatStack/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "EIGW6": { + "id": "EIGW6", + "path": "NlbEnablePrefixForIpv6NatStack/Vpc/EIGW6", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EgressOnlyInternetGateway", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DisabledLbSg": { + "id": "DisabledLbSg", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLbSg", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLbSg/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "NlbEnablePrefixForIpv6NatStack/DisabledLbSg", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DisabledLb": { + "id": "DisabledLb", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLb", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLb/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "aws:cdk:cloudformation:props": { + "enablePrefixForIpv6SourceNat": "off", + "ipAddressType": "dualstack", + "loadBalancerAttributes": [ + { + "key": "deletion_protection.enabled", + "value": "false" + } + ], + "scheme": "internet-facing", + "securityGroups": [ + { + "Fn::GetAtt": [ + "DisabledLbSgB7154DC8", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "type": "network" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "TcpListener": { + "id": "TcpListener", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLb/TcpListener", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/DisabledLb/TcpListener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "defaultActions": [ + { + "type": "forward", + "targetGroupArn": { + "Ref": "TcpTargetGroupD98C5CDB" + } + } + ], + "loadBalancerArn": { + "Ref": "DisabledLbF70482DB" + }, + "port": 1229, + "protocol": "TCP" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "TcpTargetGroup": { + "id": "TcpTargetGroup", + "path": "NlbEnablePrefixForIpv6NatStack/TcpTargetGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/TcpTargetGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "ipAddressType": "ipv6", + "port": 1229, + "protocol": "TCP", + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "EnabledLbSg": { + "id": "EnabledLbSg", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLbSg", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLbSg/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "NlbEnablePrefixForIpv6NatStack/EnabledLbSg", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "EnabledLb": { + "id": "EnabledLb", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "aws:cdk:cloudformation:props": { + "enablePrefixForIpv6SourceNat": "on", + "ipAddressType": "dualstack", + "loadBalancerAttributes": [ + { + "key": "deletion_protection.enabled", + "value": "false" + } + ], + "scheme": "internet-facing", + "securityGroups": [ + { + "Fn::GetAtt": [ + "EnabledLbSg11D53248", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "type": "network" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "UdpListener": { + "id": "UdpListener", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb/UdpListener", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb/UdpListener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "defaultActions": [ + { + "type": "forward", + "targetGroupArn": { + "Ref": "UdpTargetGroup5F89FEC0" + } + } + ], + "loadBalancerArn": { + "Ref": "EnabledLb9F3E8D30" + }, + "port": 1229, + "protocol": "UDP" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "TcpWithUdpListener": { + "id": "TcpWithUdpListener", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb/TcpWithUdpListener", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/EnabledLb/TcpWithUdpListener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "defaultActions": [ + { + "type": "forward", + "targetGroupArn": { + "Ref": "TcpWithUdpTargetGroup827EE6D7" + } + } + ], + "loadBalancerArn": { + "Ref": "EnabledLb9F3E8D30" + }, + "port": 3502, + "protocol": "TCP_UDP" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "UdpTargetGroup": { + "id": "UdpTargetGroup", + "path": "NlbEnablePrefixForIpv6NatStack/UdpTargetGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/UdpTargetGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "ipAddressType": "ipv6", + "port": 1229, + "protocol": "UDP", + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "TcpWithUdpTargetGroup": { + "id": "TcpWithUdpTargetGroup", + "path": "NlbEnablePrefixForIpv6NatStack/TcpWithUdpTargetGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "NlbEnablePrefixForIpv6NatStack/TcpWithUdpTargetGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "ipAddressType": "ipv6", + "port": 3502, + "protocol": "TCP_UDP", + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "NlbEnablePrefixForIpv6NatStack/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "NlbEnablePrefixForIpv6NatStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "NlbEnablePrefixForIpv6NatStackTest": { + "id": "NlbEnablePrefixForIpv6NatStackTest", + "path": "NlbEnablePrefixForIpv6NatStackTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "NlbEnablePrefixForIpv6NatStackTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "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.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.ts new file mode 100644 index 0000000000000..f33dcb18f61b5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.nlb-enable-prefix-for-ipv6-nat.ts @@ -0,0 +1,73 @@ +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'NlbEnablePrefixForIpv6NatStack'); + +const vpc = new ec2.Vpc(stack, 'Vpc', { + restrictDefaultSecurityGroup: false, + maxAzs: 2, + ipProtocol: ec2.IpProtocol.DUAL_STACK, + natGateways: 0, +}); + +const disabledNlb = new elbv2.NetworkLoadBalancer(stack, 'DisabledLb', { + vpc, + internetFacing: true, + securityGroups: [ + new ec2.SecurityGroup(stack, 'DisabledLbSg', { vpc }), + ], + enablePrefixForIpv6SourceNat: false, + ipAddressType: elbv2.IpAddressType.DUAL_STACK, +}); + +const tcpListener = disabledNlb.addListener('TcpListener', { + port: 1229, + protocol: elbv2.Protocol.TCP, +}); +const tcpTargetGroup = new elbv2.NetworkTargetGroup(stack, 'TcpTargetGroup', { + vpc, + port: 1229, + protocol: elbv2.Protocol.TCP, + ipAddressType: elbv2.TargetGroupIpAddressType.IPV6, +}); +tcpListener.addTargetGroups('TcpTargetGroup', tcpTargetGroup); + +const enabledNlb = new elbv2.NetworkLoadBalancer(stack, 'EnabledLb', { + vpc, + internetFacing: true, + securityGroups: [ + new ec2.SecurityGroup(stack, 'EnabledLbSg', { vpc }), + ], + ipAddressType: elbv2.IpAddressType.DUAL_STACK, + enablePrefixForIpv6SourceNat: true, +}); +const udpListener = enabledNlb.addListener('UdpListener', { + port: 1229, + protocol: elbv2.Protocol.UDP, +}); +const udpTargetGroup = new elbv2.NetworkTargetGroup(stack, 'UdpTargetGroup', { + vpc, + port: 1229, + protocol: elbv2.Protocol.UDP, + ipAddressType: elbv2.TargetGroupIpAddressType.IPV6, +}); +udpListener.addTargetGroups('TargetGroup', udpTargetGroup); + +const tcpWithUdpListener = enabledNlb.addListener('TcpWithUdpListener', { + port: 3502, + protocol: elbv2.Protocol.TCP_UDP, +}); +const tcpWithUdpTargetGroup = new elbv2.NetworkTargetGroup(stack, 'TcpWithUdpTargetGroup', { + vpc, + port: 3502, + protocol: elbv2.Protocol.TCP_UDP, + ipAddressType: elbv2.TargetGroupIpAddressType.IPV6, +}); +tcpWithUdpListener.addTargetGroups('TcpWithUdpTargetGroup', tcpWithUdpTargetGroup); + +new integ.IntegTest(app, 'NlbEnablePrefixForIpv6NatStackTest', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 09298cdf533b9..beab2ec9a1cad 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -23,8 +23,8 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-cdk/aws-service-spec": "^0.1.36", - "@aws-cdk/service-spec-types": "^0.0.103", + "@aws-cdk/aws-service-spec": "^0.1.37", + "@aws-cdk/service-spec-types": "^0.0.104", "chalk": "^4", "diff": "^5.2.0", "fast-deep-equal": "^3.1.3", diff --git a/packages/@aws-cdk/integ-runner/package.json b/packages/@aws-cdk/integ-runner/package.json index 60e68d52c8819..ea18202dc0dd9 100644 --- a/packages/@aws-cdk/integ-runner/package.json +++ b/packages/@aws-cdk/integ-runner/package.json @@ -74,7 +74,7 @@ "@aws-cdk/cloud-assembly-schema": "^38.0.0", "@aws-cdk/cloudformation-diff": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "@aws-cdk/aws-service-spec": "^0.1.36", + "@aws-cdk/aws-service-spec": "^0.1.37", "cdk-assets": "3.0.0-rc.32", "@aws-cdk/cdk-cli-wrapper": "0.0.0", "aws-cdk": "0.0.0", diff --git a/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts b/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts index e38c2456ebcb5..e0105d02ce4dd 100644 --- a/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts +++ b/packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts @@ -1759,6 +1759,9 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements if (props.blockDevices) { throw new Error('Setting \'blockDevices\' must not be set when \'launchTemplate\' or \'mixedInstancesPolicy\' is set'); } + if (props.requireImdsv2) { + throw new Error('Setting \'requireImdsv2\' must not be set when \'launchTemplate\' or \'mixedInstancesPolicy\' is set'); + } } /** diff --git a/packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts b/packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts index 1ccbdd5f423ba..2b78904dd300c 100644 --- a/packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts +++ b/packages/aws-cdk-lib/aws-autoscaling/test/auto-scaling-group.test.ts @@ -2947,6 +2947,26 @@ describe('InstanceMaintenancePolicy', () => { }); }).toThrow(/The difference between minHealthyPercentage and maxHealthyPercentage cannot be greater than 100, got 200/); }); + + test('throws if requireImdsv2 set when launchTemplate is set', () => { + // GIVEN + const stack = new cdk.Stack(); + stack.node.setContext(AUTOSCALING_GENERATE_LAUNCH_TEMPLATE, true); + const vpc = mockVpc(stack); + const lt = LaunchTemplate.fromLaunchTemplateAttributes(stack, 'imported-lt', { + launchTemplateId: 'test-lt-id', + versionNumber: '0', + }); + + // THEN + expect(() => { + new autoscaling.AutoScalingGroup(stack, 'MyFleet', { + vpc, + launchTemplate: lt, + requireImdsv2: true, + }); + }).toThrow(/Setting \'requireImdsv2\' must not be set when \'launchTemplate\' or \'mixedInstancesPolicy\' is set/); + }); }); function mockSecurityGroup(stack: cdk.Stack) { diff --git a/packages/aws-cdk-lib/aws-bedrock/lib/foundation-model.ts b/packages/aws-cdk-lib/aws-bedrock/lib/foundation-model.ts index 6986cffe1a2d2..39985388fabaa 100644 --- a/packages/aws-cdk-lib/aws-bedrock/lib/foundation-model.ts +++ b/packages/aws-cdk-lib/aws-bedrock/lib/foundation-model.ts @@ -59,6 +59,9 @@ export class FoundationModelIdentifier { /** Base model "amazon.titan-embed-image-v1". */ public static readonly AMAZON_TITAN_MULTIMODAL_EMBEDDINGS_G1_V1 = new FoundationModelIdentifier('amazon.titan-embed-image-v1'); + /** Base model "amazon.rerank-v1:0". */ + public static readonly AMAZON_RERANK_V1 = new FoundationModelIdentifier('amazon.rerank-v1:0'); + /** Base model "amazon.nova-canvas-v1:0". */ public static readonly AMAZON_NOVA_CANVAS_V1_0 = new FoundationModelIdentifier('amazon.nova-canvas-v1:0'); @@ -191,6 +194,9 @@ export class FoundationModelIdentifier { /** Base model "cohere.command-r-v1:0". */ public static readonly COHERE_COMMAND_R_PLUS_V1 = new FoundationModelIdentifier('cohere.command-r-plus-v1:0'); + /** Base model "cohere.rerank-v3-5:0". */ + public static readonly COHERE_RERANK_V3_5 = new FoundationModelIdentifier('cohere.rerank-v3-5:0'); + /** Base model "cohere.embed-english-v3". */ public static readonly COHERE_EMBED_ENGLISH_V3 = new FoundationModelIdentifier('cohere.embed-english-v3'); diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts index d79048c94e9c2..bc946b15e260e 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts @@ -425,6 +425,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly CODECOMMIT_GIT_FIPS = new InterfaceVpcEndpointAwsService('git-codecommit-fips'); public static readonly GLUE = new InterfaceVpcEndpointAwsService('glue'); public static readonly GLUE_DATABREW = new InterfaceVpcEndpointAwsService('databrew'); + public static readonly GLUE_DASHBOARD = new InterfaceVpcEndpointAwsService('glue.dashboard'); public static readonly GRAFANA = new InterfaceVpcEndpointAwsService('grafana'); public static readonly GRAFANA_WORKSPACE = new InterfaceVpcEndpointAwsService('grafana-workspace'); public static readonly GROUNDSTATION = new InterfaceVpcEndpointAwsService('groundstation'); @@ -442,6 +443,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly IMAGE_BUILDER = new InterfaceVpcEndpointAwsService('imagebuilder'); public static readonly INSPECTOR = new InterfaceVpcEndpointAwsService('inspector2'); public static readonly INSPECTOR_SCAN = new InterfaceVpcEndpointAwsService('inspector-scan'); + public static readonly INVOICING = new InterfaceVpcEndpointAwsService('invoicing'); public static readonly IOT_CORE = new InterfaceVpcEndpointAwsService('iot.data'); public static readonly IOT_CORE_CREDENTIALS = new InterfaceVpcEndpointAwsService('iot.credentials'); public static readonly IOT_CORE_DEVICE_ADVISOR = new InterfaceVpcEndpointAwsService('deviceadvisor.iot'); @@ -562,12 +564,16 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly S3 = new InterfaceVpcEndpointAwsService('s3'); public static readonly S3_OUTPOSTS = new InterfaceVpcEndpointAwsService('s3-outposts'); public static readonly S3_MULTI_REGION_ACCESS_POINTS = new InterfaceVpcEndpointAwsService('s3-global.accesspoint', 'com.amazonaws', undefined, { global: true }); + public static readonly S3_TABLES = new InterfaceVpcEndpointAwsService('s3tables'); + public static readonly SAVINGS_PLANS = new InterfaceVpcEndpointAwsService('savingsplans', 'com.amazonaws', undefined, { global: true }); public static readonly SAGEMAKER_API = new InterfaceVpcEndpointAwsService('sagemaker.api'); + public static readonly SAGEMAKER_DATA_SCIENCE_ASSISTANT = new InterfaceVpcEndpointAwsService('sagemaker-data-science-assistant'); public static readonly SAGEMAKER_EXPERIMENTS = new InterfaceVpcEndpointAwsService('experiments', 'aws.sagemaker'); public static readonly SAGEMAKER_FEATURESTORE_RUNTIME = new InterfaceVpcEndpointAwsService('sagemaker.featurestore-runtime'); public static readonly SAGEMAKER_GEOSPATIAL = new InterfaceVpcEndpointAwsService('sagemaker-geospatial'); public static readonly SAGEMAKER_METRICS = new InterfaceVpcEndpointAwsService('sagemaker.metrics'); public static readonly SAGEMAKER_NOTEBOOK = new InterfaceVpcEndpointAwsService('notebook', 'aws.sagemaker'); + public static readonly SAGEMAKER_PARTNER_APP = new InterfaceVpcEndpointAwsService('partner-app', 'aws.sagemaker'); public static readonly SAGEMAKER_RUNTIME = new InterfaceVpcEndpointAwsService('sagemaker.runtime'); public static readonly SAGEMAKER_RUNTIME_FIPS = new InterfaceVpcEndpointAwsService('sagemaker.runtime-fips'); public static readonly SAGEMAKER_STUDIO = new InterfaceVpcEndpointAwsService('studio', 'aws.sagemaker'); diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md index 2d839918f3cb8..f55effba63631 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md @@ -366,7 +366,6 @@ and [Register targets with your Target Group](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-register-targets.html) for more information. - ### Dualstack Network Load Balancer You can create a dualstack Network Load Balancer using the `ipAddressType` property: @@ -380,7 +379,23 @@ const lb = new elbv2.NetworkLoadBalancer(this, 'LB', { }); ``` -You cannot add UDP or TCP_UDP listeners to a dualstack Network Load Balancer. +You can configure whether to use an IPv6 prefix from each subnet for source NAT by setting `enablePrefixForIpv6SourceNat` to `true`. +This must be enabled if you want to create a dualstack Network Load Balancer with a listener that uses UDP protocol. + +```ts +declare const vpc: ec2.Vpc; + +const lb = new elbv2.NetworkLoadBalancer(this, 'LB', { + vpc, + ipAddressType: elbv2.IpAddressType.DUAL_STACK, + enablePrefixForIpv6SourceNat: true, +}); + +const listener = lb.addListener('Listener', { + port: 1229, + protocol: elbv2.Protocol.UDP, +}); +``` ### Network Load Balancer attributes diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts index 6ef0e006e088f..6b97718474c21 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts @@ -7,7 +7,7 @@ import * as cxschema from '../../../cloud-assembly-schema'; import { Duration, Resource, Lazy, Token } from '../../../core'; import { BaseListener, BaseListenerLookupOptions, IListener } from '../shared/base-listener'; import { HealthCheck } from '../shared/base-target-group'; -import { AlpnPolicy, IpAddressType, Protocol, SslPolicy } from '../shared/enums'; +import { AlpnPolicy, Protocol, SslPolicy } from '../shared/enums'; import { IListenerCertificate } from '../shared/listener-certificate'; import { validateNetworkProtocol } from '../shared/util'; @@ -195,13 +195,6 @@ export class NetworkListener extends BaseListener implements INetworkListener { throw new Error('Protocol must be TLS when alpnPolicy have been specified'); } - if ( - props.loadBalancer.ipAddressType === IpAddressType.DUAL_STACK && - (props.protocol === Protocol.UDP || props.protocol === Protocol.TCP_UDP) - ) { - throw new Error('UDP or TCP_UDP listeners cannot be added to a dualstack network load balancer.'); - } - super(scope, id, { loadBalancerArn: props.loadBalancer.loadBalancerArn, protocol: proto, diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts index a9284e8160d58..7a485b102155e 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts @@ -7,7 +7,7 @@ import { Lazy, Resource } from '../../../core'; import * as cxapi from '../../../cx-api'; import { NetworkELBMetrics } from '../elasticloadbalancingv2-canned-metrics.generated'; import { BaseLoadBalancer, BaseLoadBalancerLookupOptions, BaseLoadBalancerProps, ILoadBalancerV2 } from '../shared/base-load-balancer'; -import { IpAddressType } from '../shared/enums'; +import { IpAddressType, Protocol } from '../shared/enums'; import { parseLoadBalancerFullName } from '../shared/util'; /** @@ -75,6 +75,15 @@ export interface NetworkLoadBalancerProps extends BaseLoadBalancerProps { * @default false */ readonly zonalShift?: boolean; + + /** + * Indicates whether to use an IPv6 prefix from each subnet for source NAT. + * + * The IP address type must be IpAddressType.DUALSTACK. + * + * @default undefined - NLB default behavior is false + */ + readonly enablePrefixForIpv6SourceNat?: boolean; } /** @@ -241,6 +250,7 @@ export class NetworkLoadBalancer extends BaseLoadBalancer implements INetworkLoa public readonly connections: ec2.Connections; private readonly isSecurityGroupsPropertyDefined: boolean; private readonly _enforceSecurityGroupInboundRulesOnPrivateLinkTraffic?: boolean; + private enablePrefixForIpv6SourceNat?: boolean; /** * After the implementation of `IConnectable` (see https://github.com/aws/aws-cdk/pull/28494), the default @@ -262,8 +272,10 @@ export class NetworkLoadBalancer extends BaseLoadBalancer implements INetworkLoa enforceSecurityGroupInboundRulesOnPrivateLinkTraffic: Lazy.string({ produce: () => this.enforceSecurityGroupInboundRulesOnPrivateLinkTraffic, }), + enablePrefixForIpv6SourceNat: props.enablePrefixForIpv6SourceNat === true ? 'on': props.enablePrefixForIpv6SourceNat === false ? 'off' : undefined, }); + this.enablePrefixForIpv6SourceNat = props.enablePrefixForIpv6SourceNat; this.metrics = new NetworkLoadBalancerMetrics(this, this.loadBalancerFullName); this.isSecurityGroupsPropertyDefined = !!props.securityGroups; this.connections = new ec2.Connections({ securityGroups: props.securityGroups }); @@ -288,6 +300,14 @@ export class NetworkLoadBalancer extends BaseLoadBalancer implements INetworkLoa * @returns The newly created listener */ public addListener(id: string, props: BaseNetworkListenerProps): NetworkListener { + // UDP listener with dual stack NLB requires prefix IPv6 source NAT to be enabled + if ( + (props.protocol === Protocol.UDP || props.protocol === Protocol.TCP_UDP) && + (this.ipAddressType === IpAddressType.DUAL_STACK || this.ipAddressType === IpAddressType.DUAL_STACK_WITHOUT_PUBLIC_IPV4) && + this.enablePrefixForIpv6SourceNat !== true + ) { + throw new Error('To add a listener with UDP protocol to a dual stack NLB, \'enablePrefixForIpv6SourceNat\' must be set to true.'); + } return new NetworkListener(this, id, { loadBalancer: this, ...props, diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts index 335670918ac83..fec26773489a9 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts @@ -155,7 +155,7 @@ export interface HealthCheck { * The number of consecutive health check failures required before considering a target unhealthy. * * For Application Load Balancers, the default is 2. For Network Load - * Balancers, this value must be the same as the healthy threshold count. + * Balancers, the range is between 2-10 and can be set accordingly. * * @default 2 */ diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/load-balancer.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/load-balancer.test.ts index 6681443c6b1a9..1e0e6d602e23c 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/load-balancer.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/load-balancer.test.ts @@ -1135,40 +1135,51 @@ describe('tests', () => { IpAddressType: 'dualstack', }); }); + }); - test('Cannot add UDP or TCP_UDP listeners to a dualstack network load balancer', () => { + describe('enable prefix for ipv6 source nat', () => { + test.each([ + { config: true, value: 'on' }, + { config: false, value: 'off' }, + ])('specify EnablePrefixForIpv6SourceNat', ({ config, value }) => { // GIVEN const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'Stack'); // WHEN - const loadBalancer = new elbv2.NetworkLoadBalancer(stack, 'LB', { + new elbv2.NetworkLoadBalancer(stack, 'Lb', { vpc, - internetFacing: true, + enablePrefixForIpv6SourceNat: config, ipAddressType: elbv2.IpAddressType.DUAL_STACK, }); - const targetGroup = new elbv2.NetworkTargetGroup(stack, 'tg', { - vpc: loadBalancer.vpc, - port: 3000, + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Scheme: 'internal', + Type: 'network', + IpAddressType: 'dualstack', + EnablePrefixForIpv6SourceNat: value, + }); + }); + + test.each([false, undefined])('throw error for disabling `enablePrefixForIpv6SourceNat` and add UDP listener', (enablePrefixForIpv6SourceNat) => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.NetworkLoadBalancer(stack, 'Lb', { + vpc, + ipAddressType: elbv2.IpAddressType.DUAL_STACK, + enablePrefixForIpv6SourceNat, }); // THEN expect(() => { - loadBalancer.addListener('listener', { + lb.addListener('Listener', { + port: 80, protocol: elbv2.Protocol.UDP, - port: 3000, - defaultAction: elbv2.NetworkListenerAction.forward([targetGroup]), - }); - }).toThrow(/UDP or TCP_UDP listeners cannot be added to a dualstack network load balancer/); - - expect(() => { - loadBalancer.addListener('listener', { - protocol: elbv2.Protocol.TCP_UDP, - port: 3000, - defaultAction: elbv2.NetworkListenerAction.forward([targetGroup]), + defaultTargetGroups: [new elbv2.NetworkTargetGroup(stack, 'Group', { vpc, port: 80 })], }); - }).toThrow(/UDP or TCP_UDP listeners cannot be added to a dualstack network load balancer/); + }).toThrow('To add a listener with UDP protocol to a dual stack NLB, \'enablePrefixForIpv6SourceNat\' must be set to true.'); }); }); diff --git a/packages/aws-cdk-lib/aws-invoicing/.jsiirc.json b/packages/aws-cdk-lib/aws-invoicing/.jsiirc.json new file mode 100644 index 0000000000000..a0688b60d6628 --- /dev/null +++ b/packages/aws-cdk-lib/aws-invoicing/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "java": { + "package": "software.amazon.awscdk.services.invoicing" + }, + "dotnet": { + "package": "Amazon.CDK.AWS.Invoicing" + }, + "python": { + "module": "aws_cdk.aws_invoicing" + } + } +} diff --git a/packages/aws-cdk-lib/aws-invoicing/README.md b/packages/aws-cdk-lib/aws-invoicing/README.md new file mode 100644 index 0000000000000..f49edcf2601e3 --- /dev/null +++ b/packages/aws-cdk-lib/aws-invoicing/README.md @@ -0,0 +1,39 @@ +# AWS::Invoicing Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as invoicing from 'aws-cdk-lib/aws-invoicing'; +``` + + + +There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed: + +- Search [Construct Hub for Invoicing construct libraries](https://constructs.dev/search?q=invoicing) +- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::Invoicing resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Invoicing.html) directly. + + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::Invoicing](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Invoicing.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.) + + diff --git a/packages/aws-cdk-lib/aws-invoicing/index.ts b/packages/aws-cdk-lib/aws-invoicing/index.ts new file mode 100644 index 0000000000000..f41a696fd204d --- /dev/null +++ b/packages/aws-cdk-lib/aws-invoicing/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/packages/aws-cdk-lib/aws-invoicing/lib/index.ts b/packages/aws-cdk-lib/aws-invoicing/lib/index.ts new file mode 100644 index 0000000000000..479c320abc55f --- /dev/null +++ b/packages/aws-cdk-lib/aws-invoicing/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::Invoicing Cloudformation Resources +export * from './invoicing.generated'; diff --git a/packages/aws-cdk-lib/aws-lambda/lib/function.ts b/packages/aws-cdk-lib/aws-lambda/lib/function.ts index 38481f883b92e..ad239483b50ef 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/function.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/function.ts @@ -30,6 +30,7 @@ import * as logs from '../../aws-logs'; import * as sns from '../../aws-sns'; import * as sqs from '../../aws-sqs'; import { Annotations, ArnFormat, CfnResource, Duration, FeatureFlags, Fn, IAspect, Lazy, Names, Size, Stack, Token } from '../../core'; +import { ValidationError } from '../../core/lib/errors'; import { LAMBDA_RECOGNIZE_LAYER_VERSION } from '../../cx-api'; /** @@ -917,16 +918,16 @@ export class Function extends FunctionBase { if (props.functionName && !Token.isUnresolved(props.functionName)) { if (props.functionName.length > 64) { - throw new Error(`Function name can not be longer than 64 characters but has ${props.functionName.length} characters.`); + throw new ValidationError(`Function name can not be longer than 64 characters but has ${props.functionName.length} characters.`, this); } if (!/^[a-zA-Z0-9-_]+$/.test(props.functionName)) { - throw new Error(`Function name ${props.functionName} can contain only letters, numbers, hyphens, or underscores with no spaces.`); + throw new ValidationError(`Function name ${props.functionName} can contain only letters, numbers, hyphens, or underscores with no spaces.`, this); } } if (props.description && !Token.isUnresolved(props.description)) { if (props.description.length > 256) { - throw new Error(`Function description can not be longer than 256 characters but has ${props.description.length} characters.`); + throw new ValidationError(`Function description can not be longer than 256 characters but has ${props.description.length} characters.`, this); } } @@ -951,10 +952,10 @@ export class Function extends FunctionBase { const config = props.filesystem.config; if (!Token.isUnresolved(config.localMountPath)) { if (!/^\/mnt\/[a-zA-Z0-9-_.]+$/.test(config.localMountPath)) { - throw new Error(`Local mount path should match with ^/mnt/[a-zA-Z0-9-_.]+$ but given ${config.localMountPath}.`); + throw new ValidationError(`Local mount path should match with ^/mnt/[a-zA-Z0-9-_.]+$ but given ${config.localMountPath}.`, this); } if (config.localMountPath.length > 160) { - throw new Error(`Local mount path can not be longer than 160 characters but has ${config.localMountPath.length} characters.`); + throw new ValidationError(`Local mount path can not be longer than 160 characters but has ${config.localMountPath.length} characters.`, this); } } if (config.policies) { @@ -1019,16 +1020,16 @@ export class Function extends FunctionBase { } if (props.architecture && props.architectures !== undefined) { - throw new Error('Either architecture or architectures must be specified but not both.'); + throw new ValidationError('Either architecture or architectures must be specified but not both.', this); } if (props.architectures && props.architectures.length > 1) { - throw new Error('Only one architecture must be specified.'); + throw new ValidationError('Only one architecture must be specified.', this); } this._architecture = props.architecture ?? (props.architectures && props.architectures[0]); if (props.ephemeralStorageSize && !props.ephemeralStorageSize.isUnresolved() && (props.ephemeralStorageSize.toMebibytes() < 512 || props.ephemeralStorageSize.toMebibytes() > 10240)) { - throw new Error(`Ephemeral storage size must be between 512 and 10240 MB, received ${props.ephemeralStorageSize}.`); + throw new ValidationError(`Ephemeral storage size must be between 512 and 10240 MB, received ${props.ephemeralStorageSize}.`, this); } const resource: CfnFunction = new CfnFunction(this, 'Resource', { @@ -1096,7 +1097,7 @@ export class Function extends FunctionBase { if (props.layers) { if (props.runtime === Runtime.FROM_IMAGE) { - throw new Error('Layers are not supported for container image functions'); + throw new ValidationError('Layers are not supported for container image functions', this); } this.addLayers(...props.layers); @@ -1109,7 +1110,7 @@ export class Function extends FunctionBase { // Log retention if (props.logRetention) { if (props.logGroup) { - throw new Error('CDK does not support setting logRetention and logGroup'); + throw new ValidationError('CDK does not support setting logRetention and logGroup', this); } const logRetention = new logs.LogRetention(this, 'LogRetention', { logGroupName: `/aws/lambda/${this.functionName}`, @@ -1137,7 +1138,7 @@ export class Function extends FunctionBase { if (props.filesystem) { if (!props.vpc) { - throw new Error('Cannot configure \'filesystem\' without configuring a VPC.'); + throw new ValidationError('Cannot configure \'filesystem\' without configuring a VPC.', this); } const config = props.filesystem.config; if (config.dependency) { @@ -1201,7 +1202,7 @@ export class Function extends FunctionBase { 'LAMBDA_RUNTIME_DIR', ]; if (reservedEnvironmentVariables.includes(key)) { - throw new Error(`${key} environment variable is reserved by the lambda runtime and can not be set manually. See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html`); + throw new ValidationError(`${key} environment variable is reserved by the lambda runtime and can not be set manually. See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html`, this); } this.environment[key] = { value, ...options }; return this; @@ -1214,24 +1215,24 @@ export class Function extends FunctionBase { */ private getLoggingConfig(props: FunctionProps): CfnFunction.LoggingConfigProperty | undefined { if (props.logFormat && props.loggingFormat) { - throw new Error('Only define LogFormat or LoggingFormat, not both.'); + throw new ValidationError('Only define LogFormat or LoggingFormat, not both.', this); } if (props.applicationLogLevel && props.applicationLogLevelV2) { - throw new Error('Only define applicationLogLevel or applicationLogLevelV2, not both.'); + throw new ValidationError('Only define applicationLogLevel or applicationLogLevelV2, not both.', this); } if (props.systemLogLevel && props.systemLogLevelV2) { - throw new Error('Only define systemLogLevel or systemLogLevelV2, not both.'); + throw new ValidationError('Only define systemLogLevel or systemLogLevelV2, not both.', this); } if (props.applicationLogLevel || props.applicationLogLevelV2 || props.systemLogLevel || props.systemLogLevelV2) { if (props.logFormat !== LogFormat.JSON && props.loggingFormat === undefined) { - throw new Error(`To use ApplicationLogLevel and/or SystemLogLevel you must set LogFormat to '${LogFormat.JSON}', got '${props.logFormat}'.`); + throw new ValidationError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LogFormat to '${LogFormat.JSON}', got '${props.logFormat}'.`, this); } if (props.loggingFormat !== LoggingFormat.JSON && props.logFormat === undefined) { - throw new Error(`To use ApplicationLogLevel and/or SystemLogLevel you must set LoggingFormat to '${LoggingFormat.JSON}', got '${props.loggingFormat}'.`); + throw new ValidationError(`To use ApplicationLogLevel and/or SystemLogLevel you must set LoggingFormat to '${LoggingFormat.JSON}', got '${props.loggingFormat}'.`, this); } } @@ -1268,7 +1269,7 @@ export class Function extends FunctionBase { */ public invalidateVersionBasedOn(x: string) { if (Token.isUnresolved(x)) { - throw new Error('invalidateVersionOn: input may not contain unresolved tokens'); + throw new ValidationError('invalidateVersionOn: input may not contain unresolved tokens', this); } this.hashMixins.push(x); } @@ -1283,11 +1284,11 @@ export class Function extends FunctionBase { public addLayers(...layers: ILayerVersion[]): void { for (const layer of layers) { if (this._layers.length === 5) { - throw new Error('Unable to add layer: this lambda function already uses 5 layers.'); + throw new ValidationError('Unable to add layer: this lambda function already uses 5 layers.', this); } if (layer.compatibleRuntimes && !layer.compatibleRuntimes.find(runtime => runtime.runtimeEquals(this.runtime))) { const runtimes = layer.compatibleRuntimes.map(runtime => runtime.name).join(', '); - throw new Error(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`); + throw new ValidationError(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`, this); } // Currently no validations for compatible architectures since Lambda service @@ -1398,8 +1399,8 @@ export class Function extends FunctionBase { } const envKeys = Object.keys(this.environment); if (envKeys.length !== 0) { - throw new Error(`The function ${this.node.path} contains environment variables [${envKeys}] and is not compatible with Lambda@Edge. \ -Environment variables can be marked for removal when used in Lambda@Edge by setting the \'removeInEdge\' property in the \'addEnvironment()\' API.`); + throw new ValidationError(`The function ${this.node.path} contains environment variables [${envKeys}] and is not compatible with Lambda@Edge. \ +Environment variables can be marked for removal when used in Lambda@Edge by setting the \'removeInEdge\' property in the \'addEnvironment()\' API.`, this); } return; @@ -1435,19 +1436,19 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett } if (props.runtime === Runtime.FROM_IMAGE) { - throw new Error("ADOT Lambda layer can't be configured with container image package type"); + throw new ValidationError("ADOT Lambda layer can't be configured with container image package type", this); } // This is not the complete list of incompatible runtimes and layer types. We are only // checking for common mistakes on a best-effort basis. if (this.runtime === Runtime.GO_1_X) { - throw new Error('Runtime go1.x is not supported by the ADOT Lambda Go SDK'); + throw new ValidationError('Runtime go1.x is not supported by the ADOT Lambda Go SDK', this); } // The Runtime is Python and Adot is set it requires a different EXEC_WRAPPER than the other code bases. if (this.runtime.family === RuntimeFamily.PYTHON && props.adotInstrumentation.execWrapper.valueOf() !== AdotLambdaExecWrapper.INSTRUMENT_HANDLER) { - throw new Error('Python Adot Lambda layer requires AdotLambdaExecWrapper.INSTRUMENT_HANDLER'); + throw new ValidationError('Python Adot Lambda layer requires AdotLambdaExecWrapper.INSTRUMENT_HANDLER', this); } this.addLayers(LayerVersion.fromLayerVersionArn(this, 'AdotLayer', props.adotInstrumentation.layerVersion._bind(this).arn)); @@ -1510,47 +1511,47 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett */ private configureVpc(props: FunctionProps): CfnFunction.VpcConfigProperty | undefined { if (props.securityGroup && props.securityGroups) { - throw new Error('Only one of the function props, securityGroup or securityGroups, is allowed'); + throw new ValidationError('Only one of the function props, securityGroup or securityGroups, is allowed', this); } const hasSecurityGroups = props.securityGroups && props.securityGroups.length > 0; if (!props.vpc) { if (props.allowAllOutbound !== undefined) { - throw new Error('Cannot configure \'allowAllOutbound\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'allowAllOutbound\' without configuring a VPC', this); } if (props.securityGroup) { - throw new Error('Cannot configure \'securityGroup\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'securityGroup\' without configuring a VPC', this); } if (hasSecurityGroups) { - throw new Error('Cannot configure \'securityGroups\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'securityGroups\' without configuring a VPC', this); } if (props.vpcSubnets) { - throw new Error('Cannot configure \'vpcSubnets\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'vpcSubnets\' without configuring a VPC', this); } if (props.ipv6AllowedForDualStack) { - throw new Error('Cannot configure \'ipv6AllowedForDualStack\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'ipv6AllowedForDualStack\' without configuring a VPC', this); } if (props.allowAllIpv6Outbound !== undefined) { - throw new Error('Cannot configure \'allowAllIpv6Outbound\' without configuring a VPC'); + throw new ValidationError('Cannot configure \'allowAllIpv6Outbound\' without configuring a VPC', this); } return undefined; } if (props.allowAllOutbound !== undefined) { if (props.securityGroup) { - throw new Error('Configure \'allowAllOutbound\' directly on the supplied SecurityGroup.'); + throw new ValidationError('Configure \'allowAllOutbound\' directly on the supplied SecurityGroup.', this); } if (hasSecurityGroups) { - throw new Error('Configure \'allowAllOutbound\' directly on the supplied SecurityGroups.'); + throw new ValidationError('Configure \'allowAllOutbound\' directly on the supplied SecurityGroups.', this); } } if (props.allowAllIpv6Outbound !== undefined) { if (props.securityGroup) { - throw new Error('Configure \'allowAllIpv6Outbound\' directly on the supplied SecurityGroup.'); + throw new ValidationError('Configure \'allowAllIpv6Outbound\' directly on the supplied SecurityGroup.', this); } if (hasSecurityGroups) { - throw new Error('Configure \'allowAllIpv6Outbound\' directly on the supplied SecurityGroups.'); + throw new ValidationError('Configure \'allowAllIpv6Outbound\' directly on the supplied SecurityGroups.', this); } } @@ -1585,8 +1586,8 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett const publicSubnetIds = new Set(props.vpc.publicSubnets.map(s => s.subnetId)); for (const subnetId of selectedSubnets.subnetIds) { if (publicSubnetIds.has(subnetId) && !allowPublicSubnet) { - throw new Error('Lambda Functions in a public subnet can NOT access the internet. ' + - 'If you are aware of this limitation and would still like to place the function in a public subnet, set `allowPublicSubnet` to true'); + throw new ValidationError('Lambda Functions in a public subnet can NOT access the internet. ' + + 'If you are aware of this limitation and would still like to place the function in a public subnet, set `allowPublicSubnet` to true', this); } } this.node.addDependency(selectedSubnets.internetConnectivityEstablished); @@ -1622,15 +1623,15 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett Annotations.of(this).addWarningV2('@aws-cdk/aws-lambda:snapStartRequirePublish', 'SnapStart only support published Lambda versions. Ignore if function already have published versions'); if (!props.runtime.supportsSnapStart) { - throw new Error(`SnapStart currently not supported by runtime ${props.runtime.name}`); + throw new ValidationError(`SnapStart currently not supported by runtime ${props.runtime.name}`, this); } if (props.filesystem) { - throw new Error('SnapStart is currently not supported using EFS'); + throw new ValidationError('SnapStart is currently not supported using EFS', this); } if (props.ephemeralStorageSize && props.ephemeralStorageSize?.toMebibytes() > 512) { - throw new Error('SnapStart is currently not supported using more than 512 MiB Ephemeral Storage'); + throw new ValidationError('SnapStart is currently not supported using more than 512 MiB Ephemeral Storage', this); } return props.snapStart._render(); @@ -1648,7 +1649,7 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett throw Error('deadLetterQueue defined but deadLetterQueueEnabled explicitly set to false'); } if (props.deadLetterTopic && (props.deadLetterQueue || props.deadLetterQueueEnabled !== undefined)) { - throw new Error('deadLetterQueue and deadLetterTopic cannot be specified together at the same time'); + throw new ValidationError('deadLetterQueue and deadLetterTopic cannot be specified together at the same time', this); } let deadLetterQueue: sqs.IQueue | sns.ITopic; @@ -1698,7 +1699,7 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett private validateProfiling(props: FunctionProps) { if (!props.runtime.supportsCodeGuruProfiling) { - throw new Error(`CodeGuru profiling is not supported by runtime ${props.runtime.name}`); + throw new ValidationError(`CodeGuru profiling is not supported by runtime ${props.runtime.name}`, this); } if (props.environment && (props.environment.AWS_CODEGURU_PROFILER_GROUP_NAME || props.environment.AWS_CODEGURU_PROFILER_GROUP_ARN diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index 3f09f240df96d..48521aedd2a1b 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -1074,8 +1074,8 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { } private validateServerlessScalingConfig(): void { - if (this.serverlessV2MaxCapacity > 256 || this.serverlessV2MaxCapacity < 0.5) { - throw new Error('serverlessV2MaxCapacity must be >= 0.5 & <= 256'); + if (this.serverlessV2MaxCapacity > 256 || this.serverlessV2MaxCapacity < 1) { + throw new Error('serverlessV2MaxCapacity must be >= 1 & <= 256'); } if (this.serverlessV2MinCapacity > 256 || this.serverlessV2MinCapacity < 0) { @@ -1086,9 +1086,6 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { throw new Error('serverlessV2MaxCapacity must be greater than serverlessV2MinCapacity'); } - if (this.serverlessV2MaxCapacity === 0.5 && this.serverlessV2MinCapacity === 0.5) { - throw new Error('If serverlessV2MinCapacity === 0.5 then serverlessV2MaxCapacity must be >=1'); - } const regexp = new RegExp(/^[0-9]+\.?5?$/); if (!regexp.test(this.serverlessV2MaxCapacity.toString()) || !regexp.test(this.serverlessV2MinCapacity.toString())) { throw new Error('serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments, received '+ diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index 8091945676ea8..56a426d9cc9ec 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -116,11 +116,10 @@ describe('cluster new api', () => { }); test.each([ - [0.5, 300, /serverlessV2MaxCapacity must be >= 0.5 & <= 256/], - [0.5, 0, /serverlessV2MaxCapacity must be >= 0.5 & <= 256/], + [0.5, 300, /serverlessV2MaxCapacity must be >= 1 & <= 256/], + [0.5, 0, /serverlessV2MaxCapacity must be >= 1 & <= 256/], [-1, 1, /serverlessV2MinCapacity must be >= 0 & <= 256/], [300, 1, /serverlessV2MinCapacity must be >= 0 & <= 256/], - [0.5, 0.5, /If serverlessV2MinCapacity === 0.5 then serverlessV2MaxCapacity must be >=1/], [10.1, 12, /serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments/], [12, 12.1, /serverlessV2MinCapacity & serverlessV2MaxCapacity must be in 0.5 step increments/], [5, 1, /serverlessV2MaxCapacity must be greater than serverlessV2MinCapacity/], diff --git a/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts b/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts index 365b73882f810..385a13dcda254 100644 --- a/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts +++ b/packages/aws-cdk-lib/aws-synthetics/lib/canary.ts @@ -745,8 +745,8 @@ const nameRegex: RegExp = /^[0-9a-z_\-]+$/; * @param name - the given name of the canary */ function validateName(name: string) { - if (name.length > 21) { - throw new Error(`Canary name is too large, must be between 1 and 21 characters, but is ${name.length} (got "${name}")`); + if (name.length > 255) { + throw new Error(`Canary name is too large, must be between 1 and 255 characters, but is ${name.length} (got "${name}")`); } if (!nameRegex.test(name)) { throw new Error(`Canary name must be lowercase, numbers, hyphens, or underscores (got "${name}")`); diff --git a/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts b/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts index 286997bd98de9..554553c2be01c 100644 --- a/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts +++ b/packages/aws-cdk-lib/aws-synthetics/test/canary.test.ts @@ -104,23 +104,23 @@ test('Throws when name is specified incorrectly', () => { }), runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_8_0, })) - .toThrowError('Canary name must be lowercase, numbers, hyphens, or underscores (got "My Canary")'); + .toThrow('Canary name must be lowercase, numbers, hyphens, or underscores (got "My Canary")'); }); -test('Throws when name has more than 21 characters', () => { +test('Throws when name has more than 255 characters', () => { // GIVEN const stack = new Stack(); // THEN expect(() => new synthetics.Canary(stack, 'Canary', { - canaryName: 'a'.repeat(22), + canaryName: 'a'.repeat(256), test: synthetics.Test.custom({ handler: 'index.handler', code: synthetics.Code.fromInline('/* Synthetics handler code */'), }), runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_8_0, })) - .toThrowError(`Canary name is too large, must be between 1 and 21 characters, but is 22 (got "${'a'.repeat(22)}")`); + .toThrow(`Canary name is too large, must be between 1 and 255 characters, but is 256 (got "${'a'.repeat(256)}")`); }); test('An existing role can be specified instead of auto-created', () => { @@ -561,7 +561,7 @@ test('Throws when rate above 60 minutes', () => { }), runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_8_0, })) - .toThrowError('Schedule duration must be between 1 and 60 minutes'); + .toThrow('Schedule duration must be between 1 and 60 minutes'); }); test('Throws when rate above is not a whole number of minutes', () => { @@ -577,7 +577,7 @@ test('Throws when rate above is not a whole number of minutes', () => { }), runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_8_0, })) - .toThrowError('\'59 seconds\' cannot be converted into a whole number of minutes.'); + .toThrow('\'59 seconds\' cannot be converted into a whole number of minutes.'); }); test('Can share artifacts bucket between canaries', () => { diff --git a/packages/aws-cdk-lib/core/lib/errors.ts b/packages/aws-cdk-lib/core/lib/errors.ts new file mode 100644 index 0000000000000..727cf0228c396 --- /dev/null +++ b/packages/aws-cdk-lib/core/lib/errors.ts @@ -0,0 +1,145 @@ +import { IConstruct } from 'constructs'; +import { constructInfoFromConstruct } from './helpers-internal'; + +const CONSTRUCT_ERROR_SYMBOL = Symbol.for('@aws-cdk/core.SynthesisError'); +const VALIDATION_ERROR_SYMBOL = Symbol.for('@aws-cdk/core.ValidationError'); + +/** + * Helper to check if an error is a SynthesisErrors + */ +export class Errors { + /** + * Test whether the given errors is a ConstructionError + */ + public static isConstructError(x: any): x is ConstructError { + return x !== null && typeof(x) === 'object' && CONSTRUCT_ERROR_SYMBOL in x; + } + + /** + * Test whether the given error is a ValidationError + */ + public static isValidationError(x: any): x is ValidationError { + return Errors.isConstructError(x) && VALIDATION_ERROR_SYMBOL in x; + } +} + +interface ConstructInfo { + readonly fqn: string; + readonly version: string; +} + +/** + * Generic, abstract error that is thrown from the users app during app construction or synth. + */ +abstract class ConstructError extends Error { + #time: string; + #constructPath?: string; + #constructInfo?: ConstructInfo; + + /** + * The time the error was thrown. + */ + public get time(): string { + return this.#time; + } + + /** + * The level. Always `'error'`. + */ + public get level(): 'error' { + return 'error'; + } + + /** + * The type of the error. + */ + public abstract get type(): string; + + /** + * The path of the construct this error is thrown from, if available. + */ + public get constructPath(): string | undefined { + return this.#constructPath; + } + + /** + * Information on the construct this error is thrown from, if available. + */ + public get constructInfo(): ConstructInfo | undefined { + return this.#constructInfo; + } + + constructor(msg: string, scope?: IConstruct) { + super(msg); + Object.setPrototypeOf(this, ConstructError.prototype); + Object.defineProperty(this, CONSTRUCT_ERROR_SYMBOL, { value: true }); + + this.name = new.target.name; + this.#time = new Date().toISOString(); + this.#constructPath = scope?.node.path; + + if (scope) { + Error.captureStackTrace(this, scope.constructor); + try { + this.#constructInfo = scope ? constructInfoFromConstruct(scope) : undefined; + } catch (_) { + // we don't want to fail if construct info is not available + } + } + + const stack = [ + `${this.name}: ${this.message}`, + ]; + + if (this.constructInfo) { + stack.push(`in ${this.constructInfo?.fqn} at [${this.constructPath}]`); + } else { + stack.push(`in [${this.constructPath}]`); + } + + if (this.stack) { + stack.push(this.stack); + } + + this.stack = this.constructStack(this.stack); + } + + /** + * Helper message to clean-up the stack and amend with construct information. + */ + private constructStack(prev?: string) { + const indent = ' '.repeat(4); + + const stack = [ + `${this.name}: ${this.message}`, + ]; + + if (this.constructInfo) { + stack.push(`${indent}at path [${this.constructPath}] in ${this.constructInfo?.fqn}`); + } else { + stack.push(`${indent}at path [${this.constructPath}]`); + } + + if (prev) { + stack.push(''); + stack.push(...prev.split('\n').slice(1)); + } + + return stack.join('\n'); + } +} + +/** + * An Error that is thrown when a construct has validation errors. + */ +export class ValidationError extends ConstructError { + public get type(): 'validation' { + return 'validation'; + } + + constructor(msg: string, scope: IConstruct) { + super(msg, scope); + Object.setPrototypeOf(this, ValidationError.prototype); + Object.defineProperty(this, VALIDATION_ERROR_SYMBOL, { value: true }); + } +} diff --git a/packages/aws-cdk-lib/core/lib/index.ts b/packages/aws-cdk-lib/core/lib/index.ts index b35e89c0e59e4..9fb4041a136a0 100644 --- a/packages/aws-cdk-lib/core/lib/index.ts +++ b/packages/aws-cdk-lib/core/lib/index.ts @@ -35,6 +35,7 @@ export * from './expiration'; export * from './size'; export * from './stack-trace'; export { Element } from './deps'; +export { Errors } from './errors'; export * from './app'; export * from './context-provider'; diff --git a/packages/aws-cdk-lib/core/test/errors.test.ts b/packages/aws-cdk-lib/core/test/errors.test.ts new file mode 100644 index 0000000000000..a1a7f34de051e --- /dev/null +++ b/packages/aws-cdk-lib/core/test/errors.test.ts @@ -0,0 +1,34 @@ +import { App, Stack } from '../lib'; +import { Errors, ValidationError } from '../lib/errors'; + +jest + .useFakeTimers() + .setSystemTime(new Date('2020-01-01')); + +describe('ValidationError', () => { + test('ValidationError is ValidationError and ConstructError', () => { + const error = new ValidationError('this is an error', new App()); + + expect(Errors.isConstructError(error)).toBe(true); + expect(Errors.isValidationError(error)).toBe(true); + }); + + test('ValidationError data', () => { + const app = new App(); + const stack = new Stack(app, 'MyStack'); + const error = new ValidationError('this is an error', stack); + + expect(error.time).toBe('2020-01-01T00:00:00.000Z'); + expect(error.type).toBe('validation'); + expect(error.level).toBe('error'); + expect(error.constructPath).toBe('MyStack'); + expect(error.constructInfo).toMatchObject({ + // fqns are different when run from compiled JS (first) and dynamically from TS (second) + fqn: expect.stringMatching(/aws-cdk-lib\.Stack|constructs\.Construct/), + version: expect.stringMatching(/^\d+\.\d+\.\d+$/), + }); + expect(error.message).toBe('this is an error'); + expect(error.stack).toContain('ValidationError: this is an error'); + expect(error.stack).toContain('at path [MyStack] in'); + }); +}); diff --git a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md index 005491dbe78b6..ed9e96757c561 100644 --- a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +++ b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md @@ -81,7 +81,8 @@ Flags come in three types: | [@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics](#aws-cdkcorecfnincluderejectcomplexresourceupdatecreatepolicyintrinsics) | When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values. | 2.161.0 | (fix) | | [@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy](#aws-cdkaws-stepfunctions-tasksfixrunecstaskpolicy) | When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN. | 2.163.0 | (fix) | | [@aws-cdk/aws-dynamodb:resourcePolicyPerReplica](#aws-cdkaws-dynamodbresourcepolicyperreplica) | When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas | 2.164.0 | (fix) | -| [@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault](#aws-cdkaws-ec2bastionhostuseamazonlinux2023bydefault) | When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2. | V2NEXT | (default) | +| [@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault](#aws-cdkaws-ec2bastionhostuseamazonlinux2023bydefault) | When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2. | 2.172.0 | (default) | +| [@aws-cdk/core:aspectStabilization](#aws-cdkcoreaspectstabilization) | When enabled, a stabilization loop will be run when invoking Aspects during synthesis. | 2.172.0 | (config) | @@ -197,6 +198,7 @@ are migrating a v1 CDK project to v2, explicitly set any of these flags which do | [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` | | [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | (default) | | `false` | `true` | | [@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask](#aws-cdkaws-stepfunctions-tasksusenews3uriparametersforbedrockinvokemodeltask) | When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model. | (fix) | | `false` | `true` | +| [@aws-cdk/core:aspectStabilization](#aws-cdkcoreaspectstabilization) | When enabled, a stabilization loop will be run when invoking Aspects during synthesis. | (config) | | `false` | `true` | @@ -213,7 +215,8 @@ Here is an example of a `cdk.json` file that restores v1 behavior for these flag "@aws-cdk/aws-lambda:recognizeVersionProps": false, "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, "@aws-cdk/pipelines:reduceAssetRoleTrustScope": false, - "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": false + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": false, + "@aws-cdk/core:aspectStabilization": false } } ``` @@ -1546,9 +1549,25 @@ the latest Amazon Linux 2023 version will be used instead of Amazon Linux 2. | Since | Default | Recommended | | ----- | ----- | ----- | | (not in v1) | | | -| V2NEXT | `false` | `true` | +| 2.172.0 | `false` | `true` | **Compatibility with old behavior:** Disable the feature flag or explicitly pass an Amazon Linux 2 machine image to the BastionHost construct. +### @aws-cdk/core:aspectStabilization + +*When enabled, a stabilization loop will be run when invoking Aspects during synthesis.* (config) + +Currently, when Aspects are invoked in one single pass of the construct tree. +This means that the Aspects that create other Aspects are not run and Aspects that create new nodes of the tree sometimes do not inherit their parent Aspects. + +When this feature flag is enabled, a stabilization loop is run to recurse the construct tree multiple times when invoking Aspects. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.172.0 | `true` | `true` | + + diff --git a/packages/aws-cdk-lib/cx-api/lib/features.ts b/packages/aws-cdk-lib/cx-api/lib/features.ts index 339898ba7a518..120e4a4a6b4d8 100644 --- a/packages/aws-cdk-lib/cx-api/lib/features.ts +++ b/packages/aws-cdk-lib/cx-api/lib/features.ts @@ -1265,7 +1265,7 @@ export const FLAGS: Record = { When this feature flag is enabled, if you do not pass the machineImage property to the BastionHost construct, the latest Amazon Linux 2023 version will be used instead of Amazon Linux 2. `, - introducedIn: { v2: 'V2NEXT' }, + introducedIn: { v2: '2.172.0' }, recommendedValue: true, compatibilityWithOldBehaviorMd: 'Disable the feature flag or explicitly pass an Amazon Linux 2 machine image to the BastionHost construct.', }, @@ -1281,7 +1281,7 @@ export const FLAGS: Record = { When this feature flag is enabled, a stabilization loop is run to recurse the construct tree multiple times when invoking Aspects. `, defaults: { v2: true }, - introducedIn: { v2: 'V2NEXT' }, + introducedIn: { v2: '2.172.0' }, recommendedValue: true, }, }; diff --git a/packages/aws-cdk-lib/index.ts b/packages/aws-cdk-lib/index.ts index b859427964915..3a1ed040cadae 100644 --- a/packages/aws-cdk-lib/index.ts +++ b/packages/aws-cdk-lib/index.ts @@ -131,6 +131,7 @@ export * as aws_imagebuilder from './aws-imagebuilder'; export * as aws_inspector from './aws-inspector'; export * as aws_inspectorv2 from './aws-inspectorv2'; export * as aws_internetmonitor from './aws-internetmonitor'; +export * as aws_invoicing from './aws-invoicing'; export * as aws_iot from './aws-iot'; export * as aws_iot1click from './aws-iot1click'; export * as aws_iotanalytics from './aws-iotanalytics'; diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 7d509f2ada438..398a110c5989b 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -136,7 +136,7 @@ "mime-types": "^2.1.35" }, "devDependencies": { - "@aws-cdk/aws-service-spec": "^0.1.36", + "@aws-cdk/aws-service-spec": "^0.1.37", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/custom-resource-handlers": "0.0.0", "@aws-cdk/pkglint": "0.0.0", @@ -345,6 +345,7 @@ "./aws-inspector": "./aws-inspector/index.js", "./aws-inspectorv2": "./aws-inspectorv2/index.js", "./aws-internetmonitor": "./aws-internetmonitor/index.js", + "./aws-invoicing": "./aws-invoicing/index.js", "./aws-iot": "./aws-iot/index.js", "./aws-iot1click": "./aws-iot1click/index.js", "./aws-iotanalytics": "./aws-iotanalytics/index.js", diff --git a/packages/aws-cdk-lib/scripts/scope-map.json b/packages/aws-cdk-lib/scripts/scope-map.json index f6f3a1375d753..586b54aede737 100644 --- a/packages/aws-cdk-lib/scripts/scope-map.json +++ b/packages/aws-cdk-lib/scripts/scope-map.json @@ -353,6 +353,9 @@ "aws-internetmonitor": [ "AWS::InternetMonitor" ], + "aws-invoicing": [ + "AWS::Invoicing" + ], "aws-iot": [ "AWS::IoT" ], diff --git a/packages/aws-cdk/test/logging.test.ts b/packages/aws-cdk/test/api/logs/cli-logging.test.ts similarity index 65% rename from packages/aws-cdk/test/logging.test.ts rename to packages/aws-cdk/test/api/logs/cli-logging.test.ts index 4a7ae5d254b77..08300a7e64890 100644 --- a/packages/aws-cdk/test/logging.test.ts +++ b/packages/aws-cdk/test/api/logs/cli-logging.test.ts @@ -1,10 +1,16 @@ -import { LogLevel, log, setLogLevel, setCI, data, print, error, warning, success, debug, trace, prefix, withCorkedLogging } from '../lib/logging'; +import { LogLevel, log, setLogLevel, setCI, data, print, error, warning, success, debug, trace, prefix, withCorkedLogging } from '../../../lib/logging'; describe('logging', () => { // Mock streams to capture output let mockStdout: jest.Mock; let mockStderr: jest.Mock; + // Helper function to strip ANSI codes + const stripAnsi = (str: string): string => { + const ansiRegex = /\u001b\[[0-9;]*[a-zA-Z]/g; + return str.replace(ansiRegex, ''); + }; + beforeEach(() => { // Reset log level before each test setLogLevel(LogLevel.INFO); @@ -14,14 +20,14 @@ describe('logging', () => { mockStdout = jest.fn(); mockStderr = jest.fn(); - // Mock the write methods directly + // Mock the write methods directly and strip ANSI codes jest.spyOn(process.stdout, 'write').mockImplementation((chunk: any) => { - mockStdout(chunk.toString()); + mockStdout(stripAnsi(chunk.toString())); return true; }); jest.spyOn(process.stderr, 'write').mockImplementation((chunk: any) => { - mockStderr(chunk.toString()); + mockStderr(stripAnsi(chunk.toString())); return true; }); }); @@ -29,29 +35,30 @@ describe('logging', () => { afterEach(() => { jest.restoreAllMocks(); }); + describe('stream selection', () => { test('data() always writes to stdout', () => { data('test message'); - expect(mockStdout).toHaveBeenCalledWith(expect.stringContaining('test message\n')); + expect(mockStdout).toHaveBeenCalledWith('test message\n'); expect(mockStderr).not.toHaveBeenCalled(); }); test('error() always writes to stderr', () => { error('test error'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('test error\n')); + expect(mockStderr).toHaveBeenCalledWith('test error\n'); expect(mockStdout).not.toHaveBeenCalled(); }); test('print() writes to stderr by default', () => { print('test print'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('test print\n')); + expect(mockStderr).toHaveBeenCalledWith('test print\n'); expect(mockStdout).not.toHaveBeenCalled(); }); test('print() writes to stdout in CI mode', () => { setCI(true); print('test print'); - expect(mockStdout).toHaveBeenCalledWith(expect.stringContaining('test print\n')); + expect(mockStdout).toHaveBeenCalledWith('test print\n'); expect(mockStderr).not.toHaveBeenCalled(); }); }); @@ -62,9 +69,9 @@ describe('logging', () => { error('error message'); warning('warning message'); print('print message'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('error message\n')); - expect(mockStderr).not.toHaveBeenCalledWith(expect.stringContaining('warning message\n')); - expect(mockStderr).not.toHaveBeenCalledWith(expect.stringContaining('print message\n')); + expect(mockStderr).toHaveBeenCalledWith('error message\n'); + expect(mockStderr).not.toHaveBeenCalledWith('warning message\n'); + expect(mockStderr).not.toHaveBeenCalledWith('print message\n'); }); test('debug messages only show at debug level', () => { @@ -74,7 +81,7 @@ describe('logging', () => { setLogLevel(LogLevel.DEBUG); debug('debug message'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('debug message\n')); + expect(mockStderr).toHaveBeenCalledWith('debug message\n'); }); test('trace messages only show at trace level', () => { @@ -84,26 +91,25 @@ describe('logging', () => { setLogLevel(LogLevel.TRACE); trace('trace message'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('trace message\n')); + expect(mockStderr).toHaveBeenCalledWith('trace message\n'); }); }); describe('message formatting', () => { test('formats messages with multiple arguments', () => { print('Value: %d, String: %s', 42, 'test'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('Value: 42, String: test\n')); + expect(mockStderr).toHaveBeenCalledWith('Value: 42, String: test\n'); }); test('handles prefix correctly', () => { const prefixedLog = prefix('PREFIX'); prefixedLog('test message'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('PREFIX test message\n')); + expect(mockStderr).toHaveBeenCalledWith('PREFIX test message\n'); }); test('handles custom styles', () => { success('success message'); - // Note: actual styling will depend on chalk, but we can verify the message is there - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('success message\n')); + expect(mockStderr).toHaveBeenCalledWith('success message\n'); }); }); @@ -115,8 +121,8 @@ describe('logging', () => { expect(mockStderr).not.toHaveBeenCalled(); }); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('message 1\n')); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('message 2\n')); + expect(mockStderr).toHaveBeenCalledWith('message 1\n'); + expect(mockStderr).toHaveBeenCalledWith('message 2\n'); }); test('handles nested corking correctly', async () => { @@ -130,9 +136,9 @@ describe('logging', () => { }); expect(mockStderr).toHaveBeenCalledTimes(3); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('outer 1\n')); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('inner\n')); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('outer 2\n')); + expect(mockStderr).toHaveBeenCalledWith('outer 1\n'); + expect(mockStderr).toHaveBeenCalledWith('inner\n'); + expect(mockStderr).toHaveBeenCalledWith('outer 2\n'); }); }); @@ -145,7 +151,7 @@ describe('logging', () => { prefix: 'PREFIX', }); expect(mockStderr).toHaveBeenCalledWith( - expect.stringMatching(/PREFIX \[\d{2}:\d{2}:\d{2}\] test message\n/), + expect.stringMatching(/^PREFIX \[\d{2}:\d{2}:\d{2}\] test message\n$/), ); }); }); diff --git a/packages/aws-cdk/test/api/logs/logs-monitor.test.ts b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts index 85f903e7681a8..4bdb7f96bd0a4 100644 --- a/packages/aws-cdk/test/api/logs/logs-monitor.test.ts +++ b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts @@ -1,16 +1,25 @@ import { FilterLogEventsCommand, type FilteredLogEvent } from '@aws-sdk/client-cloudwatch-logs'; -import { blue, yellow } from 'chalk'; import { CloudWatchLogEventMonitor } from '../../../lib/api/logs/logs-monitor'; import { sleep } from '../../util'; import { MockSdk, mockCloudWatchClient } from '../../util/mock-sdk'; +// Helper function to strip ANSI codes +const stripAnsi = (str: string): string => { + const ansiRegex = /\u001b\[[0-9;]*[a-zA-Z]/g; + return str.replace(ansiRegex, ''); +}; + let sdk: MockSdk; let stderrMock: jest.SpyInstance; let monitor: CloudWatchLogEventMonitor; beforeEach(() => { monitor = new CloudWatchLogEventMonitor(new Date(T100)); - stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { - return true; + stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation((chunk: any) => { + // Strip ANSI codes when capturing output + if (typeof chunk === 'string') { + return stripAnsi(chunk) as unknown as boolean; + } + return stripAnsi(chunk.toString()) as unknown as boolean; }); sdk = new MockSdk(); }); @@ -44,7 +53,7 @@ test('process events', async () => { // THEN const expectedLocaleTimeString = eventDate.toLocaleTimeString(); expect(stderrMock).toHaveBeenCalledTimes(1); - expect(stderrMock.mock.calls[0][0]).toContain(`[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} message`); + expect(stripAnsi(stderrMock.mock.calls[0][0])).toContain(`[loggroup] ${expectedLocaleTimeString} message`); }); test('process truncated events', async () => { @@ -76,9 +85,9 @@ test('process truncated events', async () => { // THEN const expectedLocaleTimeString = eventDate.toLocaleTimeString(); expect(stderrMock).toHaveBeenCalledTimes(101); - expect(stderrMock.mock.calls[0][0]).toContain(`[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} message`); - expect(stderrMock.mock.calls[100][0]).toContain( - `[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} >>> \`watch\` shows only the first 100 log messages - the rest have been truncated...`, + expect(stripAnsi(stderrMock.mock.calls[0][0])).toContain(`[loggroup] ${expectedLocaleTimeString} message0`); + expect(stripAnsi(stderrMock.mock.calls[100][0])).toContain( + `[loggroup] ${expectedLocaleTimeString} >>> \`watch\` shows only the first 100 log messages - the rest have been truncated...`, ); }); diff --git a/tools/@aws-cdk/spec2cdk/package.json b/tools/@aws-cdk/spec2cdk/package.json index b2e9aa8f606d0..b3ea047386690 100644 --- a/tools/@aws-cdk/spec2cdk/package.json +++ b/tools/@aws-cdk/spec2cdk/package.json @@ -32,9 +32,9 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-cdk/aws-service-spec": "^0.1.36", - "@aws-cdk/service-spec-importers": "^0.0.57", - "@aws-cdk/service-spec-types": "^0.0.103", + "@aws-cdk/aws-service-spec": "^0.1.37", + "@aws-cdk/service-spec-importers": "^0.0.58", + "@aws-cdk/service-spec-types": "^0.0.104", "@cdklabs/tskb": "^0.0.3", "@cdklabs/typewriter": "^0.0.3", "camelcase": "^6", diff --git a/version.v2.json b/version.v2.json index 841a865f4d1b3..6508e95648e0d 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.171.1", - "alphaVersion": "2.171.1-alpha.0" + "version": "2.172.0", + "alphaVersion": "2.172.0-alpha.0" } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a808475e25a25..e6708045bb24c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -63,12 +63,12 @@ resolved "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz#6d3c7860354d4856a7e75375f2f0ecab313b4989" integrity sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A== -"@aws-cdk/aws-service-spec@^0.1.36": - version "0.1.36" - resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.36.tgz#a64c518bd246c7d7ab1fdda12da6e1bbb0a34822" - integrity sha512-Pgs70xwtV4tUdDpslutB3+JqBp1+Q9WLd3kVkgTyUiGJU7Db6wQ9oLHNKRF41mtO31VYo+oyVmH8eomFfqvXew== +"@aws-cdk/aws-service-spec@^0.1.37": + version "0.1.37" + resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.37.tgz#39e78a07079fc276f2f2bfdb31c3c7226939a04a" + integrity sha512-WFGAvjslG8Jdj9XmzDtV4JbsWEmLj8K9pA882mc6iNK59l4ocGt2GqS4n3JuzRdzoEpzcVYqfgrqGUuV1ez7vg== dependencies: - "@aws-cdk/service-spec-types" "^0.0.103" + "@aws-cdk/service-spec-types" "^0.0.104" "@cdklabs/tskb" "^0.0.3" "@aws-cdk/cloud-assembly-schema@^38.0.0", "@aws-cdk/cloud-assembly-schema@^38.0.1": @@ -106,12 +106,12 @@ resolved "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v31/-/lambda-layer-kubectl-v31-2.0.0.tgz#d87799d7d0d5dad77af45281a36942e4b7996b6b" integrity sha512-8JI0sMDbqCubOyt1TbQFEwicYok9KYSrNSfzREgjGJcoPy17/Kd0gbe44ATyLMfjae7dExUhhwKMhr6GK7Hmrw== -"@aws-cdk/service-spec-importers@^0.0.57": - version "0.0.57" - resolved "https://registry.npmjs.org/@aws-cdk/service-spec-importers/-/service-spec-importers-0.0.57.tgz#d4c6021e7477bae4f86f0db8f2d85cabcb6a2840" - integrity sha512-7i5ZUFHNeLvvJo9bWVn9HQC5y+kka+sNgtAc1apzqx1IeL0TW/11ZQiWCav+uIhs60xnZZHgeT+iSgpMyApBCw== +"@aws-cdk/service-spec-importers@^0.0.58": + version "0.0.58" + resolved "https://registry.npmjs.org/@aws-cdk/service-spec-importers/-/service-spec-importers-0.0.58.tgz#8fdd3ef8d10247cb948f5021bd67c9d56f47ef62" + integrity sha512-qyjPFYGeuqVxrR5xa4GmDeL/w24nmbaE1gGbc/Li5Xd7f4jINvCjCV9SMaMXz5o/nJRpKs6BQVpMWWYKWXr97A== dependencies: - "@aws-cdk/service-spec-types" "^0.0.102" + "@aws-cdk/service-spec-types" "^0.0.104" "@cdklabs/tskb" "^0.0.3" ajv "^6" canonicalize "^2.0.0" @@ -122,17 +122,10 @@ glob "^8" sort-json "^2.0.1" -"@aws-cdk/service-spec-types@^0.0.102": - version "0.0.102" - resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.102.tgz#1a7554556a4890c6ccfe62b7d15c4f9297c11e3d" - integrity sha512-CL9hyaPB4C4mcMinkO56uRHFlgtuy57LlpzQv3Qc3Z9FIElK8KG76GDD1SCy+FE/7B13EpIVJmJFRCvjJvyNng== - dependencies: - "@cdklabs/tskb" "^0.0.3" - -"@aws-cdk/service-spec-types@^0.0.103": - version "0.0.103" - resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.103.tgz#0519026090f40fb1937f84683800594662ab9f41" - integrity sha512-gt2mx0GpwmY0jQxDtxREskqHGtAvUwRU5YtTA65cdGwkjh/TXlw7nUXnHgG+JRQFrfvCIgqL1D+SB18UAo2zvA== +"@aws-cdk/service-spec-types@^0.0.104": + version "0.0.104" + resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.104.tgz#9f7e632ee00c5f6d2c68b3950fa118c663beef64" + integrity sha512-VMDgWLLmCXV81VzI9tOGZ6AQWOSQvXEGlIemaJZRmO3mK9foZtO068PFZbY92h/5BO0WCUh5JJII5g3pFqKQRQ== dependencies: "@cdklabs/tskb" "^0.0.3" @@ -12724,6 +12717,11 @@ ip-regex@^4.1.0: resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -12732,11 +12730,6 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -16699,11 +16692,6 @@ qrcode-terminal@^0.12.0: resolved "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - qs@6.13.0: version "6.13.0" resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" @@ -16711,6 +16699,11 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -18683,16 +18676,16 @@ utility-types@^3.10.0: resolved "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" + integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== + uuid@^10.0.0: version "10.0.0" resolved "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" @@ -19091,7 +19084,7 @@ xmlbuilder@~11.0.0: resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==