diff --git a/.github/workflows/github-merit-badger.yml b/.github/workflows/github-merit-badger.yml index 29e2df649f483..07d6dbe71a32e 100644 --- a/.github/workflows/github-merit-badger.yml +++ b/.github/workflows/github-merit-badger.yml @@ -17,4 +17,4 @@ jobs: badges: '[beginning-contributor,repeat-contributor,valued-contributor,admired-contributor,star-contributor,distinguished-contributor]' thresholds: '[0,3,6,13,25,50]' badge-type: 'achievement' - ignore-usernames: '[RomainMuller,rix0rrr,Jerry-AWS,MrArnoldPalmer,iliapolo,otaviomacedo,madeline-k,kaizencc,comcalvi,corymhall,peterwoodworth,ryparker,TheRealAmazonKendra,vinayak-kukreja,Naumel,mrgrain,pahud,cgarvis,aws-cdk-automation,dependabot[bot],mergify[bot]]' + ignore-usernames: '[RomainMuller,rix0rrr,Jerry-AWS,MrArnoldPalmer,iliapolo,otaviomacedo,madeline-k,kaizencc,comcalvi,corymhall,peterwoodworth,ryparker,TheRealAmazonKendra,vinayak-kukreja,Naumel,mrgrain,pahud,cgarvis,kellertk,aws-cdk-automation,dependabot[bot],mergify[bot]]' diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index ef8f8536a1b32..17ef1024519e5 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -282,5 +282,7 @@ env: {"area":"@aws-cdk/yaml-cfn","keywords":["aws-yaml-cfn","yaml-cfn"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["kaizencc"]}, {"area":"@aws-cdk/aws-lightsail","keywords":["lightsail","aws-lightsail"],"labels":["@aws-cdk/aws-lightsail"],"assignees":["corymhall"]}, {"area":"@aws-cdk/aws-aps","keywords":["aps","aws-aps","prometheus"],"labels":["@aws-cdk/aws-aps"],"assignees":["corymhall"]}, - {"area":"@aws-cdk/triggers","keywords":["trigger","triggers"],"labels":["@aws-cdk/triggers"],"assignees":["otaviomacedo"]} + {"area":"@aws-cdk/triggers","keywords":["trigger","triggers"],"labels":["@aws-cdk/triggers"],"assignees":["otaviomacedo"]}, + {"area":"@aws-cdk/integ-tests","keywords":["integ-tests", "integ"],"labels":["@aws-cdk/integ-tests"],"assignees":["corymhall"]}, + {"area":"@aws-cdk/integ-runner","keywords":["integ-runner"],"labels":["@aws-cdk/integ-runner"],"assignees":["corymhall"]} ] diff --git a/.mergify.yml b/.mergify.yml index 1e5748e68ce04..0869261bf3472 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -10,7 +10,7 @@ pull_request_rules: label: add: [ contribution/core ] conditions: - - author~=^(RomainMuller|rix0rrr|Jerry-AWS|MrArnoldPalmer|iliapolo|uttarasridhar|otaviomacedo|madeline-k|kaizencc|comcalvi|corymhall|peterwoodworth|ryparker|TheRealAmazonKendra|yuth|vinayak-kukreja|Naumel|mrgrain|pahud|cgarvis)$ + - author~=^(RomainMuller|rix0rrr|Jerry-AWS|MrArnoldPalmer|iliapolo|uttarasridhar|otaviomacedo|madeline-k|kaizencc|comcalvi|corymhall|peterwoodworth|ryparker|TheRealAmazonKendra|yuth|vinayak-kukreja|Naumel|mrgrain|pahud|cgarvis|kellertk)$ - -label~="contribution/core" - name: automatic merge actions: @@ -95,6 +95,7 @@ pull_request_rules: - base=main - -merged - -closed + - changes-requested-reviews-by!=aws-cdk-automation - name: if fails conventional commits actions: comment: diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index bd32608800e35..96c1041b6d4b0 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -2,6 +2,16 @@ 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.45.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.44.0-alpha.0...v2.45.0-alpha.0) (2022-10-06) + + +### Features + +* **gamelift:** add Build L2 constructs for GameLift ([#22313](https://github.com/aws/aws-cdk/issues/22313)) ([983d26e](https://github.com/aws/aws-cdk/commit/983d26e4e7cbb40fe1148ec635efe8093d850835)) +* **gamelift:** add Script L2 Construct for GameLift ([#22343](https://github.com/aws/aws-cdk/issues/22343)) ([da181ba](https://github.com/aws/aws-cdk/commit/da181bac2a7fee2cad8915006d4501074fcb04d4)) +* **neptune:** enable cloudwatch logs exports ([#22004](https://github.com/aws/aws-cdk/issues/22004)) ([2b2bb01](https://github.com/aws/aws-cdk/commit/2b2bb01dbe00c79e7f5a0513a2e1f76f6cdcbc11)), closes [#20248](https://github.com/aws/aws-cdk/issues/20248) [#15888](https://github.com/aws/aws-cdk/issues/15888) +* **servicecatalogappregistry:** application-associator L2 Construct ([#22024](https://github.com/aws/aws-cdk/issues/22024)) ([a2b7a46](https://github.com/aws/aws-cdk/commit/a2b7a4624638a458bfb6e8e09c67a77e48e1d167)) + ## [2.44.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.43.1-alpha.0...v2.44.0-alpha.0) (2022-09-28) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index 009aa8a98341f..05d967857aacb 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -2,6 +2,38 @@ 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.45.0](https://github.com/aws/aws-cdk/compare/v2.44.0...v2.45.0) (2022-10-06) + + +### Features + +* add `addMetadata()` method to `Stack` ([#22337](https://github.com/aws/aws-cdk/issues/22337)) ([61b2ab7](https://github.com/aws/aws-cdk/commit/61b2ab79f2a044dcceba7fec1a01629873aa4517)) +* **apigateway:** add accessLogField static method ([#22322](https://github.com/aws/aws-cdk/issues/22322)) ([3ce8e47](https://github.com/aws/aws-cdk/commit/3ce8e47159c5f108c2f20d10714117762ad99ffd)), closes [#21650](https://github.com/aws/aws-cdk/issues/21650) +* **apigateway:** create BasePathMapping without stage ([#21488](https://github.com/aws/aws-cdk/issues/21488)) ([9bb213c](https://github.com/aws/aws-cdk/commit/9bb213c326ec79aca71bb646decd799f8c4954cd)), closes [#15806](https://github.com/aws/aws-cdk/issues/15806) +* **aws-cloudwatch:** composite alarm actions suppression ([#22330](https://github.com/aws/aws-cdk/issues/22330)) ([19c945e](https://github.com/aws/aws-cdk/commit/19c945e280baa0c074e4d278c5b418042d595fa6)) +* **cfn-include:** allow cyclical dependencies ([#22126](https://github.com/aws/aws-cdk/issues/22126)) ([2c8195a](https://github.com/aws/aws-cdk/commit/2c8195a0ee0b2832ade598259a4bae5e3ea25eaa)) +* **cfnspec:** cloudformation spec v91.0.0 ([#22305](https://github.com/aws/aws-cdk/issues/22305)) ([0358d51](https://github.com/aws/aws-cdk/commit/0358d51954b3ae32c6d7bdb490d498ab743770ec)) +* **codedeploy:** CodeDeploy deployment config constructs for Lambda and ECS ([#22159](https://github.com/aws/aws-cdk/issues/22159)) ([6840d8e](https://github.com/aws/aws-cdk/commit/6840d8e43381793bd7a51191bddaffc4cb6641d6)) +* **codepipeline-actions:** add elastic beanstalk deploy action ([#22135](https://github.com/aws/aws-cdk/issues/22135)) ([d8acc8a](https://github.com/aws/aws-cdk/commit/d8acc8aa07867be1b1b3cad05b67dab2d7bc3252)), closes [#2516](https://github.com/aws/aws-cdk/issues/2516) +* **core:** allow overriding the stage name ([#22223](https://github.com/aws/aws-cdk/issues/22223)) ([3d227e5](https://github.com/aws/aws-cdk/commit/3d227e5e8a7452af85470e6e617dd785dcfb6fbe)), closes [40aws-cdk/core/lib/stage.ts#L139](https://github.com/40aws-cdk/core/lib/stage.ts/issues/L139) [40aws-cdk/core/lib/stack.ts#L1139-L1143](https://github.com/40aws-cdk/core/lib/stack.ts/issues/L1139-L1143) [40aws-cdk/core/lib/stack.ts#L106-L111](https://github.com/40aws-cdk/core/lib/stack.ts/issues/L106-L111) +* **core:** make `StackSynthesizer` easier to subclass ([#22308](https://github.com/aws/aws-cdk/issues/22308)) ([8b2b381](https://github.com/aws/aws-cdk/commit/8b2b38187b709a4e9a37a4de043a84267a9ec937)) +* **sqs:** add SQS managed server side encryption ([#21591](https://github.com/aws/aws-cdk/issues/21591)) ([fa137eb](https://github.com/aws/aws-cdk/commit/fa137eb9f57a0956dae512e41b7a400b401d5642)), closes [#17770](https://github.com/aws/aws-cdk/issues/17770) + + +### Bug Fixes + +* **certificatemanager:** unable to set removal policy on DnsValidatedCertificate ([#22122](https://github.com/aws/aws-cdk/issues/22122)) ([bae6554](https://github.com/aws/aws-cdk/commit/bae655419c2f0805c4fa3ea7ef20704539bbb44c)), closes [#22040](https://github.com/aws/aws-cdk/issues/22040) [#22040](https://github.com/aws/aws-cdk/issues/22040) [#20649](https://github.com/aws/aws-cdk/issues/20649) [#14519](https://github.com/aws/aws-cdk/issues/14519) +* **cli:** large context causes E2BIG error during synthesis on Linux ([#21373](https://github.com/aws/aws-cdk/issues/21373)) ([7040168](https://github.com/aws/aws-cdk/commit/7040168f21f81421b78c44955b39cfca21c6c22d)), closes [#21230](https://github.com/aws/aws-cdk/issues/21230) [#19261](https://github.com/aws/aws-cdk/issues/19261) +* **core:** addPropertyOverride doesn't work for all intrinsics ([#22294](https://github.com/aws/aws-cdk/issues/22294)) ([e2deca0](https://github.com/aws/aws-cdk/commit/e2deca0f1981f09c9d32c11c8359400191a7d753)), closes [#20608](https://github.com/aws/aws-cdk/issues/20608) [#19971](https://github.com/aws/aws-cdk/issues/19971) +* **ec2:** cannot allow all ipv6 traffic ([#22279](https://github.com/aws/aws-cdk/issues/22279)) ([f7bbc94](https://github.com/aws/aws-cdk/commit/f7bbc943f00f3e0ceeb0ed03ec03bb36af5b3cb9)), closes [#7094](https://github.com/aws/aws-cdk/issues/7094) +* **init:** freshly generated go project doesn't build ([#22310](https://github.com/aws/aws-cdk/issues/22310)) ([c6a4e71](https://github.com/aws/aws-cdk/commit/c6a4e71067299b0e0ad65f31e9eec15a4e80ebdb)) +* **region-info:** SSM service principals are incorrect in opt-in regions ([#22327](https://github.com/aws/aws-cdk/issues/22327)) ([b7f0889](https://github.com/aws/aws-cdk/commit/b7f08895c884c9e4e8b672e62f6c7515fa65b3a8)) +* **s3:** Bucket Key cannot be used with KMS_MANAGED key ([#22331](https://github.com/aws/aws-cdk/issues/22331)) ([63d3c54](https://github.com/aws/aws-cdk/commit/63d3c541e571dffe3efab83e69fa9718eef14411)) +* **sns:** race condition exists between sqs queue policy and sns subscription ([#21797](https://github.com/aws/aws-cdk/issues/21797)) ([cf43b03](https://github.com/aws/aws-cdk/commit/cf43b03c0c6231f93ca1db0b24df7c623d55dd2b)) +* **sqs:** SSE-SQS is enabled by default and can't be disabled ([#22321](https://github.com/aws/aws-cdk/issues/22321)) ([43547d3](https://github.com/aws/aws-cdk/commit/43547d3544a02f76c287abfc26570a02cfae65c6)), closes [#22137](https://github.com/aws/aws-cdk/issues/22137) +* **step-functions:** arn is not valid across partitions ([#22314](https://github.com/aws/aws-cdk/issues/22314)) ([6e16ffe](https://github.com/aws/aws-cdk/commit/6e16ffe8e49f6a5d4ba076ba3d66f564daded96b)) +* **stepfunctions-tasks:** emrcontainers has incorrect validation of entry point arguments ([#22242](https://github.com/aws/aws-cdk/issues/22242)) ([a006b9a](https://github.com/aws/aws-cdk/commit/a006b9a9ec7f743ce276f98bfbdac12a8ee13872)), closes [#22061](https://github.com/aws/aws-cdk/issues/22061) + ## [2.44.0](https://github.com/aws/aws-cdk/compare/v2.43.1...v2.44.0) (2022-09-28) diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/publish-subscribe.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/publish-subscribe.integ.snapshot/aws-ecs-integ.template.json new file mode 100644 index 0000000000000..56b3d569d5be4 --- /dev/null +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/publish-subscribe.integ.snapshot/aws-ecs-integ.template.json @@ -0,0 +1,1343 @@ +{ + "Resources": { + "productionenvironmentvpcAEB47DF7": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet1Subnet8D92C089": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet1" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet1RouteTable6E9ABC21": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet1" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet1RouteTableAssociationA8117374": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPublicSubnet1RouteTable6E9ABC21" + }, + "SubnetId": { + "Ref": "productionenvironmentvpcPublicSubnet1Subnet8D92C089" + } + } + }, + "productionenvironmentvpcPublicSubnet1DefaultRoute524C894D": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPublicSubnet1RouteTable6E9ABC21" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "productionenvironmentvpcIGWE7C39890" + } + }, + "DependsOn": [ + "productionenvironmentvpcVPCGW1B428D07" + ] + }, + "productionenvironmentvpcPublicSubnet1EIP54BA88DB": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet1" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet1NATGateway6075E4CA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "productionenvironmentvpcPublicSubnet1Subnet8D92C089" + }, + "AllocationId": { + "Fn::GetAtt": [ + "productionenvironmentvpcPublicSubnet1EIP54BA88DB", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet1" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet2Subnet298E6C31": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet2" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet2RouteTable842A68D7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet2" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet2RouteTableAssociation0A7549F3": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPublicSubnet2RouteTable842A68D7" + }, + "SubnetId": { + "Ref": "productionenvironmentvpcPublicSubnet2Subnet298E6C31" + } + } + }, + "productionenvironmentvpcPublicSubnet2DefaultRoute92CD697D": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPublicSubnet2RouteTable842A68D7" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "productionenvironmentvpcIGWE7C39890" + } + }, + "DependsOn": [ + "productionenvironmentvpcVPCGW1B428D07" + ] + }, + "productionenvironmentvpcPublicSubnet2EIP14CA46AA": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet2" + } + ] + } + }, + "productionenvironmentvpcPublicSubnet2NATGatewayE1850FCC": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "productionenvironmentvpcPublicSubnet2Subnet298E6C31" + }, + "AllocationId": { + "Fn::GetAtt": [ + "productionenvironmentvpcPublicSubnet2EIP14CA46AA", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PublicSubnet2" + } + ] + } + }, + "productionenvironmentvpcPrivateSubnet1Subnet53F632E6": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PrivateSubnet1" + } + ] + } + }, + "productionenvironmentvpcPrivateSubnet1RouteTable2C6DFF0C": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PrivateSubnet1" + } + ] + } + }, + "productionenvironmentvpcPrivateSubnet1RouteTableAssociation8BA32463": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPrivateSubnet1RouteTable2C6DFF0C" + }, + "SubnetId": { + "Ref": "productionenvironmentvpcPrivateSubnet1Subnet53F632E6" + } + } + }, + "productionenvironmentvpcPrivateSubnet1DefaultRouteFBB3DE6C": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPrivateSubnet1RouteTable2C6DFF0C" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "productionenvironmentvpcPublicSubnet1NATGateway6075E4CA" + } + } + }, + "productionenvironmentvpcPrivateSubnet2Subnet756FB93C": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PrivateSubnet2" + } + ] + } + }, + "productionenvironmentvpcPrivateSubnet2RouteTable2F77D0D2": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc/PrivateSubnet2" + } + ] + } + }, + "productionenvironmentvpcPrivateSubnet2RouteTableAssociation09188261": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPrivateSubnet2RouteTable2F77D0D2" + }, + "SubnetId": { + "Ref": "productionenvironmentvpcPrivateSubnet2Subnet756FB93C" + } + } + }, + "productionenvironmentvpcPrivateSubnet2DefaultRoute5F9AB6C1": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "productionenvironmentvpcPrivateSubnet2RouteTable2F77D0D2" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "productionenvironmentvpcPublicSubnet2NATGatewayE1850FCC" + } + } + }, + "productionenvironmentvpcIGWE7C39890": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/production-environment-vpc" + } + ] + } + }, + "productionenvironmentvpcVPCGW1B428D07": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + }, + "InternetGatewayId": { + "Ref": "productionenvironmentvpcIGWE7C39890" + } + } + }, + "productionenvironmentclusterC6599D2D": { + "Type": "AWS::ECS::Cluster" + }, + "signupD2AAA171": { + "Type": "AWS::SNS::Topic" + }, + "delete1CCE71FF": { + "Type": "AWS::SNS::Topic" + }, + "PublishertaskdefinitionTaskRoleE8655AA5": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PublishertaskdefinitionTaskRoleDefaultPolicyD6E49F15": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": [ + { + "Ref": "delete1CCE71FF" + }, + { + "Ref": "signupD2AAA171" + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PublishertaskdefinitionTaskRoleDefaultPolicyD6E49F15", + "Roles": [ + { + "Ref": "PublishertaskdefinitionTaskRoleE8655AA5" + } + ] + } + }, + "PublishertaskdefinitionA4324C64": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Cpu": 256, + "Environment": [ + { + "Name": "PORT", + "Value": "80" + }, + { + "Name": "SIGN-UP_TOPIC_ARN", + "Value": { + "Ref": "signupD2AAA171" + } + }, + { + "Name": "DELETE_TOPIC_ARN", + "Value": { + "Ref": "delete1CCE71FF" + } + } + ], + "Essential": true, + "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "PublisherlogsDF0C1067" + }, + "awslogs-stream-prefix": "Publisher", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "Memory": 512, + "Name": "app", + "PortMappings": [ + { + "ContainerPort": 80, + "Protocol": "tcp" + } + ], + "Ulimits": [ + { + "HardLimit": 1024000, + "Name": "nofile", + "SoftLimit": 1024000 + } + ] + } + ], + "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "PublishertaskdefinitionExecutionRole5C00C542", + "Arn" + ] + }, + "Family": "awsecsintegPublishertaskdefinitionD50610D0", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "EC2", + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "PublishertaskdefinitionTaskRoleE8655AA5", + "Arn" + ] + } + } + }, + "PublishertaskdefinitionExecutionRole5C00C542": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PublishertaskdefinitionExecutionRoleDefaultPolicy681FD8E6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PublisherlogsDF0C1067", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PublishertaskdefinitionExecutionRoleDefaultPolicy681FD8E6", + "Roles": [ + { + "Ref": "PublishertaskdefinitionExecutionRole5C00C542" + } + ] + } + }, + "PublisherlogsDF0C1067": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "Publisher-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "PublisherserviceService9EB00F60": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "productionenvironmentclusterC6599D2D" + }, + "DeploymentConfiguration": { + "MaximumPercent": 200, + "MinimumHealthyPercent": 100 + }, + "DesiredCount": 1, + "EnableECSManagedTags": false, + "LaunchType": "FARGATE", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "PublisherserviceSecurityGroupC7B0C0D0", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "productionenvironmentvpcPrivateSubnet1Subnet53F632E6" + }, + { + "Ref": "productionenvironmentvpcPrivateSubnet2Subnet756FB93C" + } + ] + } + }, + "TaskDefinition": { + "Ref": "PublishertaskdefinitionA4324C64" + } + } + }, + "PublisherserviceSecurityGroupC7B0C0D0": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-integ/Publisher-service/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + } + } + }, + "signupqueue33AFF2E6": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "signupqueuePolicy185ADC00": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Ref": "signupD2AAA171" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "signupqueue33AFF2E6" + } + ] + } + }, + "signupqueueawsecsintegsignup8DE00B29CE828029": { + "Type": "AWS::SNS::Subscription", + "DependsOn": "signupqueuePolicy185ADC00", + "Properties": { + "Protocol": "sqs", + "TopicArn": { + "Ref": "signupD2AAA171" + }, + "Endpoint": { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "Arn" + ] + } + } + }, + "EventsDeadLetterQueue404572C7": { + "Type": "AWS::SQS::Queue", + "Properties": { + "MessageRetentionPeriod": 1209600 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "EventsQueueB96EB0D2": { + "Type": "AWS::SQS::Queue", + "Properties": { + "RedrivePolicy": { + "deadLetterTargetArn": { + "Fn::GetAtt": [ + "EventsDeadLetterQueue404572C7", + "Arn" + ] + }, + "maxReceiveCount": 3 + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "EventsQueuePolicyF3E925EC": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Ref": "delete1CCE71FF" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "EventsQueueB96EB0D2" + } + ] + } + }, + "EventsQueueawsecsintegdeleteF56807768162F4C0": { + "Type": "AWS::SNS::Subscription", + "DependsOn": "EventsQueuePolicyF3E925EC", + "Properties": { + "Protocol": "sqs", + "TopicArn": { + "Ref": "delete1CCE71FF" + }, + "Endpoint": { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "Arn" + ] + } + } + }, + "WorkertaskdefinitionTaskRole1EBF20D6": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "WorkertaskdefinitionTaskRoleDefaultPolicy45EAFD8C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "WorkertaskdefinitionTaskRoleDefaultPolicy45EAFD8C", + "Roles": [ + { + "Ref": "WorkertaskdefinitionTaskRole1EBF20D6" + } + ] + } + }, + "WorkertaskdefinitionBF93A675": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Cpu": 256, + "Environment": [ + { + "Name": "PORT", + "Value": "80" + }, + { + "Name": "WORKER_QUEUE_URI", + "Value": { + "Ref": "EventsQueueB96EB0D2" + } + } + ], + "Essential": true, + "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "Workerlogs2994AC4D" + }, + "awslogs-stream-prefix": "Worker", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, + "Memory": 512, + "Name": "app", + "PortMappings": [ + { + "ContainerPort": 80, + "Protocol": "tcp" + } + ], + "Ulimits": [ + { + "HardLimit": 1024000, + "Name": "nofile", + "SoftLimit": 1024000 + } + ] + } + ], + "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "WorkertaskdefinitionExecutionRole3C1A1848", + "Arn" + ] + }, + "Family": "awsecsintegWorkertaskdefinition32B60762", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "EC2", + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "WorkertaskdefinitionTaskRole1EBF20D6", + "Arn" + ] + } + } + }, + "WorkertaskdefinitionExecutionRole3C1A1848": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "WorkertaskdefinitionExecutionRoleDefaultPolicy6E199B19": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Workerlogs2994AC4D", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "WorkertaskdefinitionExecutionRoleDefaultPolicy6E199B19", + "Roles": [ + { + "Ref": "WorkertaskdefinitionExecutionRole3C1A1848" + } + ] + } + }, + "Workerlogs2994AC4D": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "Worker-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "WorkerserviceService68C5A5C3": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "productionenvironmentclusterC6599D2D" + }, + "DeploymentConfiguration": { + "MaximumPercent": 200, + "MinimumHealthyPercent": 100 + }, + "EnableECSManagedTags": false, + "LaunchType": "FARGATE", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "AssignPublicIp": "DISABLED", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "WorkerserviceSecurityGroup1CDDB904", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "productionenvironmentvpcPrivateSubnet1Subnet53F632E6" + }, + { + "Ref": "productionenvironmentvpcPrivateSubnet2Subnet756FB93C" + } + ] + } + }, + "TaskDefinition": { + "Ref": "WorkertaskdefinitionBF93A675" + } + } + }, + "WorkerserviceSecurityGroup1CDDB904": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-integ/Worker-service/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "productionenvironmentvpcAEB47DF7" + } + } + }, + "WorkerserviceTaskCountTarget6636D808": { + "Type": "AWS::ApplicationAutoScaling::ScalableTarget", + "Properties": { + "MaxCapacity": 10, + "MinCapacity": 1, + "ResourceId": { + "Fn::Join": [ + "", + [ + "service/", + { + "Ref": "productionenvironmentclusterC6599D2D" + }, + "/", + { + "Fn::GetAtt": [ + "WorkerserviceService68C5A5C3", + "Name" + ] + } + ] + ] + }, + "RoleARN": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService" + ] + ] + }, + "ScalableDimension": "ecs:service:DesiredCount", + "ServiceNamespace": "ecs" + } + }, + "WorkerserviceTaskCountTargetEventsQueueautoscalingpolicyD12B62ED": { + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "Properties": { + "PolicyName": "awsecsintegWorkerserviceTaskCountTargetEventsQueueautoscalingpolicyDBD40B57", + "PolicyType": "TargetTrackingScaling", + "ScalingTargetId": { + "Ref": "WorkerserviceTaskCountTarget6636D808" + }, + "TargetTrackingScalingPolicyConfiguration": { + "CustomizedMetricSpecification": { + "Dimensions": [ + { + "Name": "QueueName", + "Value": { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "QueueName" + ] + } + } + ], + "MetricName": "BacklogPerTask", + "Namespace": "production-Worker", + "Statistic": "Average", + "Unit": "Count" + }, + "TargetValue": 15 + } + } + }, + "WorkerserviceTaskCountTargetsignupqueueautoscalingpolicyB7321DB7": { + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + "Properties": { + "PolicyName": "awsecsintegWorkerserviceTaskCountTargetsignupqueueautoscalingpolicyDF93FC37", + "PolicyType": "TargetTrackingScaling", + "ScalingTargetId": { + "Ref": "WorkerserviceTaskCountTarget6636D808" + }, + "TargetTrackingScalingPolicyConfiguration": { + "CustomizedMetricSpecification": { + "Dimensions": [ + { + "Name": "QueueName", + "Value": { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "QueueName" + ] + } + } + ], + "MetricName": "BacklogPerTask", + "Namespace": "production-Worker", + "Statistic": "Average", + "Unit": "Count" + }, + "TargetValue": 30 + } + } + }, + "BackLogPerTaskCalculatorFunctionServiceRoleEFA723A4": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "BackLogPerTaskCalculatorFunctionServiceRoleDefaultPolicyB6B10266": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "ecs:DescribeServices", + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "productionenvironmentclusterC6599D2D", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": { + "Ref": "WorkerserviceService68C5A5C3" + } + }, + { + "Action": [ + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BackLogPerTaskCalculatorFunctionServiceRoleDefaultPolicyB6B10266", + "Roles": [ + { + "Ref": "BackLogPerTaskCalculatorFunctionServiceRoleEFA723A4" + } + ] + } + }, + "BackLogPerTaskCalculatorFunction95AA21D5": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3Bucket1FFDEA8D" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B" + } + ] + } + ] + } + ] + ] + } + }, + "Role": { + "Fn::GetAtt": [ + "BackLogPerTaskCalculatorFunctionServiceRoleEFA723A4", + "Arn" + ] + }, + "Environment": { + "Variables": { + "CLUSTER_NAME": { + "Ref": "productionenvironmentclusterC6599D2D" + }, + "SERVICE_NAME": { + "Fn::GetAtt": [ + "WorkerserviceService68C5A5C3", + "Name" + ] + }, + "NAMESPACE": "production-Worker", + "QUEUE_NAMES": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "EventsQueueB96EB0D2", + "QueueName" + ] + }, + ",", + { + "Fn::GetAtt": [ + "signupqueue33AFF2E6", + "QueueName" + ] + } + ] + ] + } + } + }, + "Handler": "index.queue_handler", + "Runtime": "python3.9" + }, + "DependsOn": [ + "BackLogPerTaskCalculatorFunctionServiceRoleDefaultPolicyB6B10266", + "BackLogPerTaskCalculatorFunctionServiceRoleEFA723A4" + ] + }, + "BacklogPerTaskScheduledRuleB871DD15": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "BackLogPerTaskCalculatorFunction95AA21D5", + "Arn" + ] + }, + "Id": "Target0" + } + ] + } + }, + "BacklogPerTaskScheduledRuleAllowEventRuleawsecsintegBackLogPerTaskCalculatorFunctionEB2B91C7CCD725BB": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "BackLogPerTaskCalculatorFunction95AA21D5", + "Arn" + ] + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "BacklogPerTaskScheduledRuleB871DD15", + "Arn" + ] + } + } + }, + "WorkerBackLogPerTaskCalculatorLogsA4B5AF42": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "BackLogPerTaskCalculatorFunction95AA21D5" + } + ] + ] + }, + "RetentionInDays": 3 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3Bucket1FFDEA8D": { + "Type": "String", + "Description": "S3 bucket for asset \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" + }, + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B": { + "Type": "String", + "Description": "S3 key for asset version \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" + }, + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91ArtifactHashC1953821": { + "Type": "String", + "Description": "Artifact hash for asset \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index 83f86fe6e2f95..62ae9b8ae0aaa 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -34,6 +34,11 @@ const templateJson = '{ "Resources": ... }'; /* The CloudFormation template as J const template = Template.fromString(templateJson); ``` +**Cyclical Resources Note** + +If allowing cyclical references is desired, for example in the case of unprocessed Transform templates, supply TemplateParsingOptions and +set skipCyclicalDependenciesCheck to true. In all other cases, will fail on detecting cyclical dependencies. + ## Full Template Match The simplest assertion would be to assert that the template matches a given diff --git a/packages/@aws-cdk/assertions/lib/template.ts b/packages/@aws-cdk/assertions/lib/template.ts index 0dffd428da27a..ccc77ad555ec7 100644 --- a/packages/@aws-cdk/assertions/lib/template.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -21,34 +21,42 @@ export class Template { /** * Base your assertions on the CloudFormation template synthesized by a CDK `Stack`. * @param stack the CDK Stack to run assertions on + * @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular + * dependencies. */ - public static fromStack(stack: Stack): Template { - return new Template(toTemplate(stack)); + public static fromStack(stack: Stack, templateParsingOptions?: TemplateParsingOptions): Template { + return new Template(toTemplate(stack), templateParsingOptions); } /** * Base your assertions from an existing CloudFormation template formatted as an in-memory * JSON object. * @param template the CloudFormation template formatted as a nested set of records + * @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular + * dependencies. */ - public static fromJSON(template: { [key: string] : any }): Template { - return new Template(template); + public static fromJSON(template: { [key: string] : any }, templateParsingOptions?: TemplateParsingOptions): Template { + return new Template(template, templateParsingOptions); } /** * Base your assertions from an existing CloudFormation template formatted as a * JSON string. * @param template the CloudFormation template in + * @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular + * dependencies. */ - public static fromString(template: string): Template { - return new Template(JSON.parse(template)); + public static fromString(template: string, templateParsingOptions?: TemplateParsingOptions): Template { + return new Template(JSON.parse(template), templateParsingOptions); } private readonly template: TemplateType; - private constructor(template: { [key: string]: any }) { + private constructor(template: { [key: string]: any }, templateParsingOptions: TemplateParsingOptions = {}) { this.template = template as TemplateType; - checkTemplateForCyclicDependencies(this.template); + if (!templateParsingOptions?.skipCyclicalDependenciesCheck ?? true) { + checkTemplateForCyclicDependencies(this.template); + } } /** @@ -243,6 +251,20 @@ export class Template { } } +/** + * Options to configure template parsing behavior, such as disregarding circular + * dependencies. + */ +export interface TemplateParsingOptions { + /** + * If set to true, will skip checking for cyclical / circular dependencies. Should be set to false other than for + * templates that are valid despite containing cycles, such as unprocessed transform stacks. + * + * @default false + */ + readonly skipCyclicalDependenciesCheck?: boolean; +} + function toTemplate(stack: Stack): any { const root = stack.node.root; if (!Stage.isStage(root)) { @@ -255,4 +277,4 @@ function toTemplate(stack: Stack): any { return JSON.parse(fs.readFileSync(path.join(assembly.directory, stack.templateFile)).toString('utf-8')); } return assembly.getStackArtifact(stack.artifactId).template; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index bae0a27ce2b0d..13354ca3614eb 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -1194,6 +1194,27 @@ describe('Template', () => { }); }).toThrow(/dependency cycle/); }); + + test('does not throw when given a template with cyclic dependencies if check is skipped', () => { + expect(() => { + Template.fromJSON({ + Resources: { + Res1: { + Type: 'Foo', + Properties: { + Thing: { Ref: 'Res2' }, + }, + }, + Res2: { + Type: 'Foo', + DependsOn: ['Res1'], + }, + }, + }, { + skipCyclicalDependenciesCheck: true, + }); + }).not.toThrow(/dependency cycle/); + }); }); function expectToThrow(fn: () => void, msgs: (RegExp | string)[], done: jest.DoneCallback): void { diff --git a/packages/@aws-cdk/aws-apigateway/README.md b/packages/@aws-cdk/aws-apigateway/README.md index 10c5c811f87ae..7ba211fb371ef 100644 --- a/packages/@aws-cdk/aws-apigateway/README.md +++ b/packages/@aws-cdk/aws-apigateway/README.md @@ -950,8 +950,8 @@ domain.addBasePathMapping(api1, { basePath: 'go-to-api1' }); domain.addBasePathMapping(api2, { basePath: 'boom' }); ``` -You can specify the API `Stage` to which this base path URL will map to. By default, this will be the -`deploymentStage` of the `RestApi`. +By default, the base path URL will map to the `deploymentStage` of the `RestApi`. +You can specify a different API `Stage` to which the base path URL will map to. ```ts declare const domain: apigateway.DomainName; @@ -966,6 +966,19 @@ const betaStage = new apigateway.Stage(this, 'beta-stage', { domain.addBasePathMapping(restapi, { basePath: 'api/beta', stage: betaStage }); ``` +It is possible to create a base path mapping without associating it with a +stage by using the `attachToStage` property. When set to `false`, the stage must be +included in the URL when invoking the API. For example, + will invoke the stage named `prod` from the +`myapi` base path mapping. + +```ts +declare const domain: apigateway.DomainName; +declare const api: apigateway.RestApi; + +domain.addBasePathMapping(api, { basePath: 'myapi', attachToStage: false }); +``` + If you don't specify `basePath`, all URLs under this domain will be mapped to the API, and you won't be able to map another API to the same domain: @@ -978,6 +991,23 @@ domain.addBasePathMapping(api); This can also be achieved through the `mapping` configuration when defining the domain as demonstrated above. +Base path mappings can also be created with the `BasePathMapping` resource. + +```ts +declare const api: apigateway.RestApi; + +const domainName = apigateway.DomainName.fromDomainNameAttributes(this, 'DomainName', { + domainName: 'domainName', + domainNameAliasHostedZoneId: 'domainNameAliasHostedZoneId', + domainNameAliasTarget: 'domainNameAliasTarget', +}); + +new apigateway.BasePathMapping(this, 'BasePathMapping', { + domainName: domainName, + restApi: api, +}); +``` + If you wish to setup this domain with an Amazon Route53 alias, use the `targets.ApiGatewayDomain`: ```ts @@ -1055,7 +1085,8 @@ new apigateway.RestApi(this, 'books', { deployOptions: { accessLogDestination: new apigateway.LogGroupLogDestination(logGroup), accessLogFormat: apigateway.AccessLogFormat.custom( - `${apigateway.AccessLogField.contextRequestId()} ${apigateway.AccessLogField.contextErrorMessage()} ${apigateway.AccessLogField.contextErrorMessageString()}` + `${apigateway.AccessLogField.contextRequestId()} ${apigateway.AccessLogField.contextErrorMessage()} ${apigateway.AccessLogField.contextErrorMessageString()} + ${apigateway.AccessLogField.contextAuthorizerError()} ${apigateway.AccessLogField.contextAuthorizerIntegrationStatus()}` ) } }); diff --git a/packages/@aws-cdk/aws-apigateway/lib/access-log.ts b/packages/@aws-cdk/aws-apigateway/lib/access-log.ts index 77b13ec342fbb..7c5b13d3a6204 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/access-log.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/access-log.ts @@ -243,6 +243,66 @@ export class AccessLogField { return '$context.identity.sourceIp'; } + /** + * The PEM-encoded client certificate that the client presented during mutual TLS authentication. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertPem() { + return '$context.identity.clientCert.clientCertPem'; + } + + /** + * The distinguished name of the subject of the certificate that a client presents. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertSubjectDN() { + return '$context.identity.clientCert.subjectDN'; + } + + /** + * The distinguished name of the issuer of the certificate that a client presents. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertIssunerDN() { + return '$context.identity.clientCert.issuerDN'; + } + + /** + * The serial number of the certificate. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertSerialNumber() { + return '$context.identity.clientCert.serialNumber'; + } + + /** + * The date before which the certificate is invalid. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertValidityNotBefore() { + return '$context.identity.clientCert.validity.notBefore'; + } + + /** + * The date after which the certificate is invalid. + * Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. + * Present only in access logs if mutual TLS authentication fails. + */ + + public static contextIdentityClientCertValidityNotAfter() { + return '$context.identity.clientCert.validity.notAfter'; + } + /** * The principal identifier of the user making the request. Used in Lambda authorizers. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html @@ -449,6 +509,121 @@ export class AccessLogField { public static contextStatus() { return '$context.status'; } + + /** + * The authorization error message. + */ + public static contextAuthorizeError() { + return '$context.authorize.error'; + } + + /** + * The authorization latency in ms. + */ + public static contextAuthorizeLatency() { + return '$context.authorize.latency'; + } + + /** + * The status code returned from an authorization attempt. + */ + public static contextAuthorizeStatus() { + return '$context.authorize.status'; + } + + /** + * The error message returned from an authorizer. + */ + public static contextAuthorizerError() { + return '$context.authorizer.error'; + } + + /** + * The status code returned from a Lambda authorizer. + */ + public static contextAuthorizerIntegrationStatus() { + return '$context.authorizer.integrationStatus'; + } + + /** + * The authorizer latency in ms. + */ + public static contextAuthorizerLatency() { + return '$context.authorizer.latency'; + } + + /** + * The AWS endpoint's request ID. + */ + public static contextAuthorizerRequestId() { + return '$context.authorizer.requestId'; + } + + /** + * The status code returned from an authorizer. + */ + public static contextAuthorizerStatus() { + return '$context.authorizer.status'; + } + + /** + * The error message returned from an authentication attempt. + */ + public static contextAuthenticateError() { + return '$context.authenticate.error'; + } + + /** + * The authentication latency in ms. + */ + public static contextAuthenticateLatency() { + return '$context.authenticate.latency'; + } + + /** + * The status code returned from an authentication attempt. + */ + public static contextAuthenticateStatus() { + return '$context.authenticate.status'; + } + + /** + * The path for an API mapping that an incoming request matched. + * Applicable when a client uses a custom domain name to access an API. For example if a client sends a request to + * https://api.example.com/v1/orders/1234, and the request matches the API mapping with the path v1/orders, the value is v1/orders. + * @see https://docs.aws.amazon.com/en_jp/apigateway/latest/developerguide/rest-api-mappings.html + */ + public static contextCustomDomainBasePathMatched() { + return '$context.customDomain.basePathMatched'; + } + + /** + * A string that contains an integration error message. + */ + public static contextIntegrationErrorMessage() { + return '$context.integrationErrorMessage'; + } + + /** + * The error message returned from AWS WAF. + */ + public static contextWafError() { + return '$context.waf.error'; + } + + /** + * The AWS WAF latency in ms. + */ + public static contextWafLatency() { + return '$context.waf.latency'; + } + + /** + * The status code returned from AWS WAF. + */ + public static contextWafStatus() { + return '$context.waf.status'; + } } /** diff --git a/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts b/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts index d87fe8536f099..066ec229b832f 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts @@ -22,6 +22,14 @@ export interface BasePathMappingOptions { * @default - map to deploymentStage of restApi otherwise stage needs to pass in URL */ readonly stage?: Stage; + + /** + * Whether to attach the base path mapping to a stage. + * Use this property to create a base path mapping without attaching it to the Rest API default stage. + * This property is ignored if `stage` is provided. + * @default - true + */ + readonly attachToStage?: boolean; } export interface BasePathMappingProps extends BasePathMappingOptions { @@ -53,9 +61,12 @@ export class BasePathMapping extends Resource { } } + const attachToStage = props.attachToStage ?? true; + // if restApi is an owned API and it has a deployment stage, map all requests // to that stage. otherwise, the stage will have to be specified in the URL. - const stage = props.stage ?? (props.restApi instanceof RestApiBase + // if props.attachToStage is false, then do not attach to the stage. + const stage = props.stage ?? (props.restApi instanceof RestApiBase && attachToStage ? props.restApi.deploymentStage : undefined); @@ -63,7 +74,7 @@ export class BasePathMapping extends Resource { basePath: props.basePath, domainName: props.domainName.domainName, restApiId: props.restApi.restApiId, - stage: stage && stage.stageName, + stage: stage?.stageName, }); } } diff --git a/packages/@aws-cdk/aws-apigateway/test/access-log.test.ts b/packages/@aws-cdk/aws-apigateway/test/access-log.test.ts index dcd89fcdc69f2..b6c4675fd89ed 100644 --- a/packages/@aws-cdk/aws-apigateway/test/access-log.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/access-log.test.ts @@ -37,7 +37,13 @@ describe('access log', () => { sub: apigateway.AccessLogField.contextAuthorizerClaims('sub'), email: apigateway.AccessLogField.contextAuthorizerClaims('email'), }, + clientCertPem: apigateway.AccessLogField.contextIdentityClientCertPem(), + subjectDN: apigateway.AccessLogField.contextIdentityClientCertSubjectDN(), + issunerDN: apigateway.AccessLogField.contextIdentityClientCertIssunerDN(), + serialNumber: apigateway.AccessLogField.contextIdentityClientCertSerialNumber(), + validityNotBefore: apigateway.AccessLogField.contextIdentityClientCertValidityNotBefore(), + validityNotAfter: apigateway.AccessLogField.contextIdentityClientCertValidityNotAfter(), })); - expect(testFormat.toString()).toEqual('{"requestId":"$context.requestId","sourceIp":"$context.identity.sourceIp","method":"$context.httpMethod","callerAccountId":"$context.identity.accountId","ownerAccountId":"$context.accountId","userContext":{"sub":"$context.authorizer.claims.sub","email":"$context.authorizer.claims.email"}}'); + expect(testFormat.toString()).toEqual('{"requestId":"$context.requestId","sourceIp":"$context.identity.sourceIp","method":"$context.httpMethod","callerAccountId":"$context.identity.accountId","ownerAccountId":"$context.accountId","userContext":{"sub":"$context.authorizer.claims.sub","email":"$context.authorizer.claims.email"},"clientCertPem":"$context.identity.clientCert.clientCertPem","subjectDN":"$context.identity.clientCert.subjectDN","issunerDN":"$context.identity.clientCert.issuerDN","serialNumber":"$context.identity.clientCert.serialNumber","validityNotBefore":"$context.identity.clientCert.validity.notBefore","validityNotAfter":"$context.identity.clientCert.validity.notAfter"}'); }); }); diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.assets.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.assets.json new file mode 100644 index 0000000000000..bd656b5bfc38c --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "basepathmappingDefaultTestDeployAssertDA82B6F0.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.template.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/basepathmappingDefaultTestDeployAssertDA82B6F0.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/integ.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/integ.json new file mode 100644 index 0000000000000..c270139cd5cfe --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "base-path-mapping/DefaultTest": { + "stacks": [ + "test-stack" + ], + "assertionStack": "base-path-mapping/DefaultTest/DeployAssert", + "assertionStackName": "basepathmappingDefaultTestDeployAssertDA82B6F0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..a57c7ce4a9fcd --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/manifest.json @@ -0,0 +1,147 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "test-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "test-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-stack.template.json", + "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}/4328166cfc76604ab46a2a088da69e6631472872129e804d27c8b5336c842774.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "test-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "test-stack.assets" + ], + "metadata": { + "/test-stack/Api/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiF70053CD" + } + ], + "/test-stack/Api/Deployment/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiDeploymentB17BE62Df672ad8455f9678e4a3db5854bdb8d73" + } + ], + "/test-stack/Api/DeploymentStage.prod/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiDeploymentStageprod3EB9684E" + } + ], + "/test-stack/Api/Endpoint": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiEndpoint4F160690" + } + ], + "/test-stack/Api/Default/GET/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ApiGET9257B917" + } + ], + "/test-stack/MappingOne/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MappingOneAB5D4FD4" + } + ], + "/test-stack/MappingTwo/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MappingTwo551C79ED" + } + ], + "/test-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/test-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "test-stack" + }, + "basepathmappingDefaultTestDeployAssertDA82B6F0.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "basepathmappingDefaultTestDeployAssertDA82B6F0.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "basepathmappingDefaultTestDeployAssertDA82B6F0": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "basepathmappingDefaultTestDeployAssertDA82B6F0.template.json", + "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": [ + "basepathmappingDefaultTestDeployAssertDA82B6F0.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": [ + "basepathmappingDefaultTestDeployAssertDA82B6F0.assets" + ], + "metadata": { + "/base-path-mapping/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/base-path-mapping/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "base-path-mapping/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.assets.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.assets.json new file mode 100644 index 0000000000000..a2ac187057b56 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "4328166cfc76604ab46a2a088da69e6631472872129e804d27c8b5336c842774": { + "source": { + "path": "test-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4328166cfc76604ab46a2a088da69e6631472872129e804d27c8b5336c842774.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.template.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.template.json new file mode 100644 index 0000000000000..52d687e8b3f2d --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/test-stack.template.json @@ -0,0 +1,137 @@ +{ + "Resources": { + "ApiF70053CD": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Name": "Api" + } + }, + "ApiDeploymentB17BE62Df672ad8455f9678e4a3db5854bdb8d73": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ApiF70053CD" + }, + "Description": "Automatically created by the RestApi construct" + }, + "DependsOn": [ + "ApiGET9257B917" + ] + }, + "ApiDeploymentStageprod3EB9684E": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "RestApiId": { + "Ref": "ApiF70053CD" + }, + "DeploymentId": { + "Ref": "ApiDeploymentB17BE62Df672ad8455f9678e4a3db5854bdb8d73" + }, + "StageName": "prod" + } + }, + "ApiGET9257B917": { + "Type": "AWS::ApiGateway::Method", + "Properties": { + "HttpMethod": "GET", + "ResourceId": { + "Fn::GetAtt": [ + "ApiF70053CD", + "RootResourceId" + ] + }, + "RestApiId": { + "Ref": "ApiF70053CD" + }, + "AuthorizationType": "NONE", + "Integration": { + "Type": "MOCK" + } + } + }, + "MappingOneAB5D4FD4": { + "Type": "AWS::ApiGateway::BasePathMapping", + "Properties": { + "DomainName": "domainName", + "RestApiId": { + "Ref": "ApiF70053CD" + }, + "Stage": { + "Ref": "ApiDeploymentStageprod3EB9684E" + } + } + }, + "MappingTwo551C79ED": { + "Type": "AWS::ApiGateway::BasePathMapping", + "Properties": { + "DomainName": "domainName", + "BasePath": "path", + "RestApiId": { + "Ref": "ApiF70053CD" + } + } + } + }, + "Outputs": { + "ApiEndpoint4F160690": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { + "Ref": "ApiF70053CD" + }, + ".execute-api.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Ref": "ApiDeploymentStageprod3EB9684E" + }, + "/" + ] + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/tree.json b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/tree.json new file mode 100644 index 0000000000000..2a9baa7dc204d --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.integ.snapshot/tree.json @@ -0,0 +1,269 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "test-stack": { + "id": "test-stack", + "path": "test-stack", + "children": { + "Api": { + "id": "Api", + "path": "test-stack/Api", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/Api/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::RestApi", + "aws:cdk:cloudformation:props": { + "name": "Api" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnRestApi", + "version": "0.0.0" + } + }, + "Deployment": { + "id": "Deployment", + "path": "test-stack/Api/Deployment", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/Api/Deployment/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::Deployment", + "aws:cdk:cloudformation:props": { + "restApiId": { + "Ref": "ApiF70053CD" + }, + "description": "Automatically created by the RestApi construct" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnDeployment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.Deployment", + "version": "0.0.0" + } + }, + "DeploymentStage.prod": { + "id": "DeploymentStage.prod", + "path": "test-stack/Api/DeploymentStage.prod", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/Api/DeploymentStage.prod/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::Stage", + "aws:cdk:cloudformation:props": { + "restApiId": { + "Ref": "ApiF70053CD" + }, + "deploymentId": { + "Ref": "ApiDeploymentB17BE62Df672ad8455f9678e4a3db5854bdb8d73" + }, + "stageName": "prod" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnStage", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.Stage", + "version": "0.0.0" + } + }, + "Endpoint": { + "id": "Endpoint", + "path": "test-stack/Api/Endpoint", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "test-stack/Api/Default", + "children": { + "GET": { + "id": "GET", + "path": "test-stack/Api/Default/GET", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/Api/Default/GET/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::Method", + "aws:cdk:cloudformation:props": { + "httpMethod": "GET", + "resourceId": { + "Fn::GetAtt": [ + "ApiF70053CD", + "RootResourceId" + ] + }, + "restApiId": { + "Ref": "ApiF70053CD" + }, + "authorizationType": "NONE", + "integration": { + "type": "MOCK" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnMethod", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.Method", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.ResourceBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.RestApi", + "version": "0.0.0" + } + }, + "Domain": { + "id": "Domain", + "path": "test-stack/Domain", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MappingOne": { + "id": "MappingOne", + "path": "test-stack/MappingOne", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/MappingOne/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::BasePathMapping", + "aws:cdk:cloudformation:props": { + "domainName": "domainName", + "restApiId": { + "Ref": "ApiF70053CD" + }, + "stage": { + "Ref": "ApiDeploymentStageprod3EB9684E" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnBasePathMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.BasePathMapping", + "version": "0.0.0" + } + }, + "MappingTwo": { + "id": "MappingTwo", + "path": "test-stack/MappingTwo", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/MappingTwo/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ApiGateway::BasePathMapping", + "aws:cdk:cloudformation:props": { + "domainName": "domainName", + "basePath": "path", + "restApiId": { + "Ref": "ApiF70053CD" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.CfnBasePathMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-apigateway.BasePathMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "base-path-mapping": { + "id": "base-path-mapping", + "path": "base-path-mapping", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "base-path-mapping/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "base-path-mapping/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "base-path-mapping/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts index a886b3c957dad..c3da93e83ba26 100644 --- a/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/base-path-mapping.test.ts @@ -1,4 +1,4 @@ -import { Template } from '@aws-cdk/assertions'; +import { Match, Template } from '@aws-cdk/assertions'; import * as acm from '@aws-cdk/aws-certificatemanager'; import * as cdk from '@aws-cdk/core'; import * as apigw from '../lib'; @@ -25,6 +25,7 @@ describe('BasePathMapping', () => { Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::BasePathMapping', { DomainName: { Ref: 'MyDomainE4943FBC' }, RestApiId: { Ref: 'MyApi49610EDF' }, + Stage: { Ref: 'MyApiDeploymentStageprodE1054AF0' }, }); }); @@ -97,6 +98,7 @@ describe('BasePathMapping', () => { restApi: api, domainName: domain, stage, + attachToStage: true, }); // THEN @@ -104,4 +106,28 @@ describe('BasePathMapping', () => { Stage: { Ref: 'MyStage572B0482' }, }); }); + + test('specify attachToStage property', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have atleast one method. + const domain = new apigw.DomainName(stack, 'MyDomain', { + domainName: 'example.com', + certificate: acm.Certificate.fromCertificateArn(stack, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'), + endpointType: apigw.EndpointType.REGIONAL, + }); + + // WHEN + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + attachToStage: false, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::BasePathMapping', { + Stage: Match.absent(), + }); + }); }); diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.ts b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.ts new file mode 100644 index 0000000000000..9d3a31a3a205e --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.ts @@ -0,0 +1,39 @@ +import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import * as apigateway from '../lib'; + +export class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string) { + super(scope, id); + + const restApi = new apigateway.RestApi(this, 'Api'); + + restApi.root.addMethod('GET'); + + const domainName = apigateway.DomainName.fromDomainNameAttributes(this, 'Domain', { + domainName: 'domainName', + domainNameAliasHostedZoneId: 'domainNameAliasHostedZoneId', + domainNameAliasTarget: 'domainNameAliasTarget', + }); + + new apigateway.BasePathMapping(this, 'MappingOne', { + domainName, + restApi, + }); + + new apigateway.BasePathMapping(this, 'MappingTwo', { + domainName, + restApi, + basePath: 'path', + attachToStage: false, + }); + } +} + +const app = new cdk.App(); + +const testStack = new TestStack(app, 'test-stack'); + +new IntegTest(app, 'base-path-mapping', { + testCases: [testStack], +}); diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.access-log.ts b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.access-log.ts index 085429a4a70d6..c7ca5480cdd6d 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.access-log.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.access-log.ts @@ -17,6 +17,12 @@ class Test extends cdk.Stack { sub: apigateway.AccessLogField.contextAuthorizerClaims('sub'), email: apigateway.AccessLogField.contextAuthorizerClaims('email'), }, + clientCertPem: apigateway.AccessLogField.contextIdentityClientCertPem(), + subjectDN: apigateway.AccessLogField.contextIdentityClientCertSubjectDN(), + issunerDN: apigateway.AccessLogField.contextIdentityClientCertIssunerDN(), + serialNumber: apigateway.AccessLogField.contextIdentityClientCertSerialNumber(), + validityNotBefore: apigateway.AccessLogField.contextIdentityClientCertValidityNotBefore(), + validityNotAfter: apigateway.AccessLogField.contextIdentityClientCertValidityNotAfter(), })); const logGroup = new logs.LogGroup(this, 'MyLogGroup'); diff --git a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/manifest.json index e9a6bd1d33e07..4ca3a2ad14567 100644 --- a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/manifest.json @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bfcd014ed17d9d37eb988448edc7e87eb2ab77e6f7508bf3de2714a6322c99b3.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0605fe9fb02ad31c3236b358b7605999f20ba079969b6fad8e9cd3878d869ee6.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.assets.json b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.assets.json index c13870f1eec0b..a00497689b941 100644 --- a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.assets.json +++ b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.assets.json @@ -1,7 +1,7 @@ { "version": "21.0.0", "files": { - "bfcd014ed17d9d37eb988448edc7e87eb2ab77e6f7508bf3de2714a6322c99b3": { + "0605fe9fb02ad31c3236b358b7605999f20ba079969b6fad8e9cd3878d869ee6": { "source": { "path": "test-apigateway-access-logs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "bfcd014ed17d9d37eb988448edc7e87eb2ab77e6f7508bf3de2714a6322c99b3.json", + "objectKey": "0605fe9fb02ad31c3236b358b7605999f20ba079969b6fad8e9cd3878d869ee6.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.template.json b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.template.json index f20a96de67427..f2f64ce616180 100644 --- a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.template.json +++ b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/test-apigateway-access-logs.template.json @@ -88,7 +88,7 @@ "Arn" ] }, - "Format": "{\"requestId\":\"$context.requestId\",\"sourceIp\":\"$context.identity.sourceIp\",\"method\":\"$context.httpMethod\",\"callerAccountId\":\"$context.identity.accountId\",\"ownerAccountId\":\"$context.accountId\",\"userContext\":{\"sub\":\"$context.authorizer.claims.sub\",\"email\":\"$context.authorizer.claims.email\"}}" + "Format": "{\"requestId\":\"$context.requestId\",\"sourceIp\":\"$context.identity.sourceIp\",\"method\":\"$context.httpMethod\",\"callerAccountId\":\"$context.identity.accountId\",\"ownerAccountId\":\"$context.accountId\",\"userContext\":{\"sub\":\"$context.authorizer.claims.sub\",\"email\":\"$context.authorizer.claims.email\"},\"clientCertPem\":\"$context.identity.clientCert.clientCertPem\",\"subjectDN\":\"$context.identity.clientCert.subjectDN\",\"issunerDN\":\"$context.identity.clientCert.issuerDN\",\"serialNumber\":\"$context.identity.clientCert.serialNumber\",\"validityNotBefore\":\"$context.identity.clientCert.validity.notBefore\",\"validityNotAfter\":\"$context.identity.clientCert.validity.notAfter\"}" }, "DeploymentId": { "Ref": "MyApiDeploymentECB0D05E81594d6748b4b291f993111a5070d710" diff --git a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/tree.json b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/tree.json index 4520e2a77abb1..3232b7bf7191c 100644 --- a/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-apigateway/test/restapi.access-log.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "test-apigateway-access-logs": { @@ -173,7 +173,7 @@ "Arn" ] }, - "format": "{\"requestId\":\"$context.requestId\",\"sourceIp\":\"$context.identity.sourceIp\",\"method\":\"$context.httpMethod\",\"callerAccountId\":\"$context.identity.accountId\",\"ownerAccountId\":\"$context.accountId\",\"userContext\":{\"sub\":\"$context.authorizer.claims.sub\",\"email\":\"$context.authorizer.claims.email\"}}" + "format": "{\"requestId\":\"$context.requestId\",\"sourceIp\":\"$context.identity.sourceIp\",\"method\":\"$context.httpMethod\",\"callerAccountId\":\"$context.identity.accountId\",\"ownerAccountId\":\"$context.accountId\",\"userContext\":{\"sub\":\"$context.authorizer.claims.sub\",\"email\":\"$context.authorizer.claims.email\"},\"clientCertPem\":\"$context.identity.clientCert.clientCertPem\",\"subjectDN\":\"$context.identity.clientCert.subjectDN\",\"issunerDN\":\"$context.identity.clientCert.issuerDN\",\"serialNumber\":\"$context.identity.clientCert.serialNumber\",\"validityNotBefore\":\"$context.identity.clientCert.validity.notBefore\",\"validityNotAfter\":\"$context.identity.clientCert.validity.notAfter\"}" }, "deploymentId": { "Ref": "MyApiDeploymentECB0D05E81594d6748b4b291f993111a5070d710" @@ -272,7 +272,7 @@ "path": "apigateway-access-logs/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "DeployAssert": { diff --git a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/lib/index.js b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/lib/index.js index 48261e12d82e5..3794bfcee0769 100644 --- a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/lib/index.js +++ b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/lib/index.js @@ -65,6 +65,23 @@ let report = function (event, context, responseStatus, physicalResourceId, respo }); }; +/** + * Adds tags to an existing certificate + * + * @param {string} certificateArn the ARN of the certificate to add tags to + * @param {string} region the region the certificate exists in + * @param {map} tags Tags to add to the requested certificate + */ +const addTags = async function(certificateArn, region, tags) { + const result = Array.from(Object.entries(tags)).map(([Key, Value]) => ({ Key, Value })) + const acm = new aws.ACM({ region }); + + await acm.addTagsToCertificate({ + CertificateArn: certificateArn, + Tags: result, + }).promise(); +} + /** * Requests a public certificate from AWS Certificate Manager, using DNS validation. * The hosted zone ID must refer to a **public** Route53-managed DNS zone that is authoritative @@ -75,10 +92,9 @@ let report = function (event, context, responseStatus, physicalResourceId, respo * @param {string} requestId the CloudFormation request ID * @param {string} domainName the Common Name (CN) field for the requested certificate * @param {string} hostedZoneId the Route53 Hosted Zone ID - * @param {map} tags Tags to add to the requested certificate * @returns {string} Validated certificate ARN */ -const requestCertificate = async function (requestId, domainName, subjectAlternativeNames, certificateTransparencyLoggingPreference, hostedZoneId, region, route53Endpoint, tags) { +const requestCertificate = async function (requestId, domainName, subjectAlternativeNames, certificateTransparencyLoggingPreference, hostedZoneId, region, route53Endpoint) { const crypto = require('crypto'); const acm = new aws.ACM({ region }); const route53 = route53Endpoint ? new aws.Route53({ endpoint: route53Endpoint }) : new aws.Route53(); @@ -101,16 +117,6 @@ const requestCertificate = async function (requestId, domainName, subjectAlterna console.log(`Certificate ARN: ${reqCertResponse.CertificateArn}`); - - if (!!tags) { - const result = Array.from(Object.entries(tags)).map(([Key, Value]) => ({ Key, Value })) - - await acm.addTagsToCertificate({ - CertificateArn: reqCertResponse.CertificateArn, - Tags: result, - }).promise(); - } - console.log('Waiting for ACM to provide DNS records for validation...'); let records = []; @@ -275,6 +281,25 @@ async function commitRoute53Records(route53, records, hostedZoneId, action = 'UP }).promise(); } +/** + * Determines whether an update request should request a new certificate + * + * @param {map} oldParams the previously process request parameters + * @param {map} newParams the current process request parameters + * @param {string} physicalResourceId the physicalResourceId + * @returns {boolean} whether or not to request a new certificate + */ +function shouldUpdate(oldParams, newParams, physicalResourceId) { + if (!oldParams) return true; + if (oldParams.DomainName !== newParams.DomainName) return true; + if (oldParams.SubjectAlternativeNames !== newParams.SubjectAlternativeNames) return true; + if (oldParams.CertificateTransparencyLoggingPreference !== newParams.CertificateTransparencyLoggingPreference) return true; + if (oldParams.HostedZoneId !== newParams.HostedZoneId) return true; + if (oldParams.Region !== newParams.Region) return true; + if (!physicalResourceId || !physicalResourceId.startsWith('arn:')) return true; + return false; +} + /** * Main handler, invoked by Lambda */ @@ -282,28 +307,43 @@ exports.certificateRequestHandler = async function (event, context) { var responseData = {}; var physicalResourceId; var certificateArn; + async function processRequest() { + certificateArn = await requestCertificate( + event.RequestId, + event.ResourceProperties.DomainName, + event.ResourceProperties.SubjectAlternativeNames, + event.ResourceProperties.CertificateTransparencyLoggingPreference, + event.ResourceProperties.HostedZoneId, + event.ResourceProperties.Region, + event.ResourceProperties.Route53Endpoint, + ); + responseData.Arn = physicalResourceId = certificateArn; + } try { switch (event.RequestType) { case 'Create': + await processRequest(); + if (event.ResourceProperties.Tags && physicalResourceId.startsWith('arn:')) { + await addTags(physicalResourceId, event.ResourceProperties.Region, event.ResourceProperties.Tags); + } + break; case 'Update': - certificateArn = await requestCertificate( - event.RequestId, - event.ResourceProperties.DomainName, - event.ResourceProperties.SubjectAlternativeNames, - event.ResourceProperties.CertificateTransparencyLoggingPreference, - event.ResourceProperties.HostedZoneId, - event.ResourceProperties.Region, - event.ResourceProperties.Route53Endpoint, - event.ResourceProperties.Tags, - ); - responseData.Arn = physicalResourceId = certificateArn; + if (shouldUpdate(event.OldResourceProperties, event.ResourceProperties, event.PhysicalResourceId)) { + await processRequest(); + } else { + responseData.Arn = physicalResourceId = event.PhysicalResourceId; + } + if (event.ResourceProperties.Tags && physicalResourceId.startsWith('arn:')) { + await addTags(physicalResourceId, event.ResourceProperties.Region, event.ResourceProperties.Tags); + } break; case 'Delete': physicalResourceId = event.PhysicalResourceId; + const removalPolicy = event.ResourceProperties.RemovalPolicy ?? 'destroy'; // If the resource didn't create correctly, the physical resource ID won't be the // certificate ARN, so don't try to delete it in that case. - if (physicalResourceId.startsWith('arn:')) { + if (physicalResourceId.startsWith('arn:') && removalPolicy === 'destroy') { await deleteCertificate( physicalResourceId, event.ResourceProperties.Region, diff --git a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/test/handler.test.js b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/test/handler.test.js index 37697f69b6e2e..be4f4fb20ba21 100644 --- a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/test/handler.test.js +++ b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/test/handler.test.js @@ -869,6 +869,243 @@ describe('DNS Validated Certificate Handler', () => { }); }); + test('Update operation requests a certificate', () => { + const requestCertificateFake = sinon.fake.resolves({ + CertificateArn: testCertificateArn, + }); + + const describeCertificateFake = sinon.stub(); + describeCertificateFake.onFirstCall().resolves({ + Certificate: { + CertificateArn: testCertificateArn + } + }); + describeCertificateFake.resolves({ + Certificate: { + CertificateArn: testCertificateArn, + DomainValidationOptions: [{ + ValidationStatus: 'SUCCESS', + ResourceRecord: { + Name: testRRName, + Type: 'CNAME', + Value: testRRValue + } + }] + } + }); + + const addTagsToCertificateFake = sinon.fake.resolves({}); + + const changeResourceRecordSetsFake = sinon.fake.resolves({ + ChangeInfo: { + Id: 'bogus' + } + }); + + AWS.mock('ACM', 'requestCertificate', requestCertificateFake); + AWS.mock('ACM', 'describeCertificate', describeCertificateFake); + AWS.mock('Route53', 'changeResourceRecordSets', changeResourceRecordSetsFake); + AWS.mock('ACM', 'addTagsToCertificate', addTagsToCertificateFake); + + const request = nock(ResponseURL).put('/', body => { + return body.Status === 'SUCCESS'; + }).reply(200); + + return LambdaTester(handler.certificateRequestHandler) + .event({ + RequestType: 'Update', + RequestId: testRequestId, + OldResourceProperties: { + DomainName: 'example.com', + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: testTags + }, + ResourceProperties: { + DomainName: testDomainName, + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: testTags + } + }) + .expectResolve(() => { + sinon.assert.calledWith(requestCertificateFake, sinon.match({ + DomainName: testDomainName, + ValidationMethod: 'DNS', + Options: { + CertificateTransparencyLoggingPreference: undefined + } + })); + sinon.assert.calledWith(changeResourceRecordSetsFake, sinon.match({ + ChangeBatch: { + Changes: [{ + Action: 'UPSERT', + ResourceRecordSet: { + Name: testRRName, + Type: 'CNAME', + TTL: 60, + ResourceRecords: [{ + Value: testRRValue + }] + } + }] + }, + HostedZoneId: testHostedZoneId + })); + sinon.assert.calledWith(addTagsToCertificateFake, sinon.match({ + "CertificateArn": testCertificateArn, + "Tags": testTagsValue, + })); + expect(request.isDone()).toBe(true); + }); + }); + + test('Update operation updates tags only', () => { + const requestCertificateFake = sinon.fake.resolves({ + CertificateArn: testCertificateArn, + }); + + const describeCertificateFake = sinon.stub(); + describeCertificateFake.onFirstCall().resolves({ + Certificate: { + CertificateArn: testCertificateArn + } + }); + describeCertificateFake.resolves({ + Certificate: { + CertificateArn: testCertificateArn, + DomainValidationOptions: [{ + ValidationStatus: 'SUCCESS', + ResourceRecord: { + Name: testRRName, + Type: 'CNAME', + Value: testRRValue + } + }] + } + }); + + const addTagsToCertificateFake = sinon.fake.resolves({}); + + const changeResourceRecordSetsFake = sinon.fake.resolves({ + ChangeInfo: { + Id: 'bogus' + } + }); + + AWS.mock('ACM', 'requestCertificate', requestCertificateFake); + AWS.mock('ACM', 'describeCertificate', describeCertificateFake); + AWS.mock('Route53', 'changeResourceRecordSets', changeResourceRecordSetsFake); + AWS.mock('ACM', 'addTagsToCertificate', addTagsToCertificateFake); + + const request = nock(ResponseURL).put('/', body => { + return body.Status === 'SUCCESS'; + }).reply(200); + + return LambdaTester(handler.certificateRequestHandler) + .event({ + RequestType: 'Update', + RequestId: testRequestId, + PhysicalResourceId: testCertificateArn, + OldResourceProperties: { + DomainName: testDomainName, + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: testTags, + }, + ResourceProperties: { + DomainName: testDomainName, + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: { + ...testTags, + Tag4: 'Value4', + }, + } + }) + .expectResolve(() => { + sinon.assert.notCalled(requestCertificateFake); + sinon.assert.notCalled(changeResourceRecordSetsFake); + sinon.assert.calledWith(addTagsToCertificateFake, sinon.match({ + "CertificateArn": testCertificateArn, + "Tags": [{ Key: 'Tag1', Value: 'Test1' }, { Key: 'Tag2', Value: 'Test2' }, { Key: 'Tag4', Value: 'Value4' }], + })); + expect(request.isDone()).toBe(true); + }); + }); + + test('Update operation does not request certificate if removal policy is changed', () => { + const requestCertificateFake = sinon.fake.resolves({ + CertificateArn: testCertificateArn, + }); + + const describeCertificateFake = sinon.stub(); + describeCertificateFake.onFirstCall().resolves({ + Certificate: { + CertificateArn: testCertificateArn + } + }); + describeCertificateFake.resolves({ + Certificate: { + CertificateArn: testCertificateArn, + DomainValidationOptions: [{ + ValidationStatus: 'SUCCESS', + ResourceRecord: { + Name: testRRName, + Type: 'CNAME', + Value: testRRValue + } + }] + } + }); + + const addTagsToCertificateFake = sinon.fake.resolves({}); + + const changeResourceRecordSetsFake = sinon.fake.resolves({ + ChangeInfo: { + Id: 'bogus' + } + }); + + AWS.mock('ACM', 'requestCertificate', requestCertificateFake); + AWS.mock('ACM', 'describeCertificate', describeCertificateFake); + AWS.mock('Route53', 'changeResourceRecordSets', changeResourceRecordSetsFake); + AWS.mock('ACM', 'addTagsToCertificate', addTagsToCertificateFake); + + const request = nock(ResponseURL).put('/', body => { + return body.Status === 'SUCCESS'; + }).reply(200); + + return LambdaTester(handler.certificateRequestHandler) + .event({ + RequestType: 'Update', + RequestId: testRequestId, + PhysicalResourceId: testCertificateArn, + OldResourceProperties: { + DomainName: testDomainName, + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: testTags, + }, + ResourceProperties: { + DomainName: testDomainName, + HostedZoneId: testHostedZoneId, + Region: 'us-east-1', + Tags: testTags, + RemovalPolicy: 'retain', + } + }) + .expectResolve(() => { + sinon.assert.notCalled(requestCertificateFake); + sinon.assert.notCalled(changeResourceRecordSetsFake); + sinon.assert.calledWith(addTagsToCertificateFake, sinon.match({ + "CertificateArn": testCertificateArn, + "Tags": testTagsValue, + })); + expect(request.isDone()).toBe(true); + }); + }); + test('Delete operation succeeds if certificate becomes not-in-use', () => { const usedByArn = 'arn:aws:cloudfront::123456789012:distribution/d111111abcdef8'; diff --git a/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts b/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts index eb4044cb7833f..b01062021fb2a 100644 --- a/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts +++ b/packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts @@ -79,6 +79,7 @@ export class DnsValidatedCertificate extends CertificateBase implements ICertifi private normalizedZoneName: string; private hostedZoneId: string; private domainName: string; + private _removalPolicy?: cdk.RemovalPolicy; constructor(scope: Construct, id: string, props: DnsValidatedCertificateProps) { super(scope, id); @@ -132,6 +133,7 @@ export class DnsValidatedCertificate extends CertificateBase implements ICertifi HostedZoneId: this.hostedZoneId, Region: props.region, Route53Endpoint: props.route53Endpoint, + RemovalPolicy: cdk.Lazy.any({ produce: () => this._removalPolicy }), // Custom resources properties are always converted to strings; might as well be explict here. CleanupRecords: props.cleanupRoute53Records ? 'true' : undefined, Tags: cdk.Lazy.list({ produce: () => this.tags.renderTags() }), @@ -143,6 +145,10 @@ export class DnsValidatedCertificate extends CertificateBase implements ICertifi this.node.addValidation({ validate: () => this.validateDnsValidatedCertificate() }); } + public applyRemovalPolicy(policy: cdk.RemovalPolicy): void { + this._removalPolicy = policy; + } + private validateDnsValidatedCertificate(): string[] { const errors: string[] = []; // Ensure the zone name is a parent zone of the certificate domain name diff --git a/packages/@aws-cdk/aws-certificatemanager/package.json b/packages/@aws-cdk/aws-certificatemanager/package.json index 2b396cdee2abe..5a6c030175093 100644 --- a/packages/@aws-cdk/aws-certificatemanager/package.json +++ b/packages/@aws-cdk/aws-certificatemanager/package.json @@ -81,6 +81,8 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", + "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/asset.ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672/index.js b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/asset.ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672/index.js new file mode 100644 index 0000000000000..3794bfcee0769 --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/asset.ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672/index.js @@ -0,0 +1,437 @@ +'use strict'; + +const aws = require('aws-sdk'); + +const defaultSleep = function (ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +}; + +// These are used for test purposes only +let defaultResponseURL; +let waiter; +let sleep = defaultSleep; +let random = Math.random; +let maxAttempts = 10; + +/** + * Upload a CloudFormation response object to S3. + * + * @param {object} event the Lambda event payload received by the handler function + * @param {object} context the Lambda context received by the handler function + * @param {string} responseStatus the response status, either 'SUCCESS' or 'FAILED' + * @param {string} physicalResourceId CloudFormation physical resource ID + * @param {object} [responseData] arbitrary response data object + * @param {string} [reason] reason for failure, if any, to convey to the user + * @returns {Promise} Promise that is resolved on success, or rejected on connection error or HTTP error response + */ +let report = function (event, context, responseStatus, physicalResourceId, responseData, reason) { + return new Promise((resolve, reject) => { + const https = require('https'); + const { URL } = require('url'); + + var responseBody = JSON.stringify({ + Status: responseStatus, + Reason: reason, + PhysicalResourceId: physicalResourceId || context.logStreamName, + StackId: event.StackId, + RequestId: event.RequestId, + LogicalResourceId: event.LogicalResourceId, + Data: responseData + }); + + const parsedUrl = new URL(event.ResponseURL || defaultResponseURL); + const options = { + hostname: parsedUrl.hostname, + port: 443, + path: parsedUrl.pathname + parsedUrl.search, + method: 'PUT', + headers: { + 'Content-Type': '', + 'Content-Length': responseBody.length + } + }; + + https.request(options) + .on('error', reject) + .on('response', res => { + res.resume(); + if (res.statusCode >= 400) { + reject(new Error(`Server returned error ${res.statusCode}: ${res.statusMessage}`)); + } else { + resolve(); + } + }) + .end(responseBody, 'utf8'); + }); +}; + +/** + * Adds tags to an existing certificate + * + * @param {string} certificateArn the ARN of the certificate to add tags to + * @param {string} region the region the certificate exists in + * @param {map} tags Tags to add to the requested certificate + */ +const addTags = async function(certificateArn, region, tags) { + const result = Array.from(Object.entries(tags)).map(([Key, Value]) => ({ Key, Value })) + const acm = new aws.ACM({ region }); + + await acm.addTagsToCertificate({ + CertificateArn: certificateArn, + Tags: result, + }).promise(); +} + +/** + * Requests a public certificate from AWS Certificate Manager, using DNS validation. + * The hosted zone ID must refer to a **public** Route53-managed DNS zone that is authoritative + * for the suffix of the certificate's Common Name (CN). For example, if the CN is + * `*.example.com`, the hosted zone ID must point to a Route 53 zone authoritative + * for `example.com`. + * + * @param {string} requestId the CloudFormation request ID + * @param {string} domainName the Common Name (CN) field for the requested certificate + * @param {string} hostedZoneId the Route53 Hosted Zone ID + * @returns {string} Validated certificate ARN + */ +const requestCertificate = async function (requestId, domainName, subjectAlternativeNames, certificateTransparencyLoggingPreference, hostedZoneId, region, route53Endpoint) { + const crypto = require('crypto'); + const acm = new aws.ACM({ region }); + const route53 = route53Endpoint ? new aws.Route53({ endpoint: route53Endpoint }) : new aws.Route53(); + if (waiter) { + // Used by the test suite, since waiters aren't mockable yet + route53.waitFor = acm.waitFor = waiter; + } + + console.log(`Requesting certificate for ${domainName}`); + + const reqCertResponse = await acm.requestCertificate({ + DomainName: domainName, + SubjectAlternativeNames: subjectAlternativeNames, + Options: { + CertificateTransparencyLoggingPreference: certificateTransparencyLoggingPreference + }, + IdempotencyToken: crypto.createHash('sha256').update(requestId).digest('hex').slice(0, 32), + ValidationMethod: 'DNS' + }).promise(); + + console.log(`Certificate ARN: ${reqCertResponse.CertificateArn}`); + + console.log('Waiting for ACM to provide DNS records for validation...'); + + let records = []; + for (let attempt = 0; attempt < maxAttempts && !records.length; attempt++) { + const { Certificate } = await acm.describeCertificate({ + CertificateArn: reqCertResponse.CertificateArn + }).promise(); + + records = getDomainValidationRecords(Certificate); + if (!records.length) { + // Exponential backoff with jitter based on 200ms base + // component of backoff fixed to ensure minimum total wait time on + // slow targets. + const base = Math.pow(2, attempt); + await sleep(random() * base * 50 + base * 150); + } + } + if (!records.length) { + throw new Error(`Response from describeCertificate did not contain DomainValidationOptions after ${maxAttempts} attempts.`) + } + + console.log(`Upserting ${records.length} DNS records into zone ${hostedZoneId}:`); + + await commitRoute53Records(route53, records, hostedZoneId); + + console.log('Waiting for validation...'); + await acm.waitFor('certificateValidated', { + // Wait up to 9 minutes and 30 seconds + $waiter: { + delay: 30, + maxAttempts: 19 + }, + CertificateArn: reqCertResponse.CertificateArn + }).promise(); + + return reqCertResponse.CertificateArn; +}; + +/** + * Deletes a certificate from AWS Certificate Manager (ACM) by its ARN. + * If the certificate does not exist, the function will return normally. + * + * @param {string} arn The certificate ARN + */ +const deleteCertificate = async function (arn, region, hostedZoneId, route53Endpoint, cleanupRecords) { + const acm = new aws.ACM({ region }); + const route53 = route53Endpoint ? new aws.Route53({ endpoint: route53Endpoint }) : new aws.Route53(); + if (waiter) { + // Used by the test suite, since waiters aren't mockable yet + route53.waitFor = acm.waitFor = waiter; + } + + try { + console.log(`Waiting for certificate ${arn} to become unused`); + + let inUseByResources; + let records = []; + for (let attempt = 0; attempt < maxAttempts; attempt++) { + const { Certificate } = await acm.describeCertificate({ + CertificateArn: arn + }).promise(); + + if (cleanupRecords) { + records = getDomainValidationRecords(Certificate); + } + inUseByResources = Certificate.InUseBy || []; + + if (inUseByResources.length || !records.length) { + // Exponential backoff with jitter based on 200ms base + // component of backoff fixed to ensure minimum total wait time on + // slow targets. + const base = Math.pow(2, attempt); + await sleep(random() * base * 50 + base * 150); + } else { + break; + } + } + + if (inUseByResources.length) { + throw new Error(`Response from describeCertificate did not contain an empty InUseBy list after ${maxAttempts} attempts.`) + } + if (cleanupRecords && !records.length) { + throw new Error(`Response from describeCertificate did not contain DomainValidationOptions after ${maxAttempts} attempts.`) + } + + console.log(`Deleting certificate ${arn}`); + + await acm.deleteCertificate({ + CertificateArn: arn + }).promise(); + + if (cleanupRecords) { + console.log(`Deleting ${records.length} DNS records from zone ${hostedZoneId}:`); + + await commitRoute53Records(route53, records, hostedZoneId, 'DELETE'); + } + + } catch (err) { + if (err.name !== 'ResourceNotFoundException') { + throw err; + } + } +}; + +/** + * Retrieve the unique domain validation options as records to be upserted (or deleted) from Route53. + * + * Returns an empty array ([]) if the domain validation options is empty or the records are not yet ready. + */ +function getDomainValidationRecords(certificate) { + const options = certificate.DomainValidationOptions || []; + // Ensure all records are ready; there is (at least a theory there's) a chance of a partial response here in rare cases. + if (options.length > 0 && options.every(opt => opt && !!opt.ResourceRecord)) { + // some alternative names will produce the same validation record + // as the main domain (eg. example.com + *.example.com) + // filtering duplicates to avoid errors with adding the same record + // to the route53 zone twice + const unique = options + .map((val) => val.ResourceRecord) + .reduce((acc, cur) => { + acc[cur.Name] = cur; + return acc; + }, {}); + return Object.keys(unique).sort().map(key => unique[key]); + } + return []; +} + +/** + * Execute Route53 ChangeResourceRecordSets for a set of records within a Hosted Zone, + * and wait for the records to commit. Defaults to an 'UPSERT' action. + */ +async function commitRoute53Records(route53, records, hostedZoneId, action = 'UPSERT') { + const changeBatch = await route53.changeResourceRecordSets({ + ChangeBatch: { + Changes: records.map((record) => { + console.log(`${record.Name} ${record.Type} ${record.Value}`); + return { + Action: action, + ResourceRecordSet: { + Name: record.Name, + Type: record.Type, + TTL: 60, + ResourceRecords: [{ + Value: record.Value + }] + } + }; + }), + }, + HostedZoneId: hostedZoneId + }).promise(); + + console.log('Waiting for DNS records to commit...'); + await route53.waitFor('resourceRecordSetsChanged', { + // Wait up to 5 minutes + $waiter: { + delay: 30, + maxAttempts: 10 + }, + Id: changeBatch.ChangeInfo.Id + }).promise(); +} + +/** + * Determines whether an update request should request a new certificate + * + * @param {map} oldParams the previously process request parameters + * @param {map} newParams the current process request parameters + * @param {string} physicalResourceId the physicalResourceId + * @returns {boolean} whether or not to request a new certificate + */ +function shouldUpdate(oldParams, newParams, physicalResourceId) { + if (!oldParams) return true; + if (oldParams.DomainName !== newParams.DomainName) return true; + if (oldParams.SubjectAlternativeNames !== newParams.SubjectAlternativeNames) return true; + if (oldParams.CertificateTransparencyLoggingPreference !== newParams.CertificateTransparencyLoggingPreference) return true; + if (oldParams.HostedZoneId !== newParams.HostedZoneId) return true; + if (oldParams.Region !== newParams.Region) return true; + if (!physicalResourceId || !physicalResourceId.startsWith('arn:')) return true; + return false; +} + +/** + * Main handler, invoked by Lambda + */ +exports.certificateRequestHandler = async function (event, context) { + var responseData = {}; + var physicalResourceId; + var certificateArn; + async function processRequest() { + certificateArn = await requestCertificate( + event.RequestId, + event.ResourceProperties.DomainName, + event.ResourceProperties.SubjectAlternativeNames, + event.ResourceProperties.CertificateTransparencyLoggingPreference, + event.ResourceProperties.HostedZoneId, + event.ResourceProperties.Region, + event.ResourceProperties.Route53Endpoint, + ); + responseData.Arn = physicalResourceId = certificateArn; + } + + try { + switch (event.RequestType) { + case 'Create': + await processRequest(); + if (event.ResourceProperties.Tags && physicalResourceId.startsWith('arn:')) { + await addTags(physicalResourceId, event.ResourceProperties.Region, event.ResourceProperties.Tags); + } + break; + case 'Update': + if (shouldUpdate(event.OldResourceProperties, event.ResourceProperties, event.PhysicalResourceId)) { + await processRequest(); + } else { + responseData.Arn = physicalResourceId = event.PhysicalResourceId; + } + if (event.ResourceProperties.Tags && physicalResourceId.startsWith('arn:')) { + await addTags(physicalResourceId, event.ResourceProperties.Region, event.ResourceProperties.Tags); + } + break; + case 'Delete': + physicalResourceId = event.PhysicalResourceId; + const removalPolicy = event.ResourceProperties.RemovalPolicy ?? 'destroy'; + // If the resource didn't create correctly, the physical resource ID won't be the + // certificate ARN, so don't try to delete it in that case. + if (physicalResourceId.startsWith('arn:') && removalPolicy === 'destroy') { + await deleteCertificate( + physicalResourceId, + event.ResourceProperties.Region, + event.ResourceProperties.HostedZoneId, + event.ResourceProperties.Route53Endpoint, + event.ResourceProperties.CleanupRecords === "true", + ); + } + break; + default: + throw new Error(`Unsupported request type ${event.RequestType}`); + } + + console.log(`Uploading SUCCESS response to S3...`); + await report(event, context, 'SUCCESS', physicalResourceId, responseData); + console.log('Done.'); + } catch (err) { + console.log(`Caught error ${err}. Uploading FAILED message to S3.`); + await report(event, context, 'FAILED', physicalResourceId, null, err.message); + } +}; + +/** + * @private + */ +exports.withReporter = function (reporter) { + report = reporter; +}; + +/** + * @private + */ +exports.withDefaultResponseURL = function (url) { + defaultResponseURL = url; +}; + +/** + * @private + */ +exports.withWaiter = function (w) { + waiter = w; +}; + +/** + * @private + */ +exports.resetWaiter = function () { + waiter = undefined; +}; + +/** + * @private + */ +exports.withSleep = function (s) { + sleep = s; +} + +/** + * @private + */ +exports.resetSleep = function () { + sleep = defaultSleep; +} + +/** + * @private + */ +exports.withRandom = function (r) { + random = r; +} + +/** + * @private + */ +exports.resetRandom = function () { + random = Math.random; +} + +/** + * @private + */ +exports.withMaxAttempts = function (ma) { + maxAttempts = ma; +} + +/** + * @private + */ +exports.resetMaxAttempts = function () { + maxAttempts = 10; +} diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.assets.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.assets.json new file mode 100644 index 0000000000000..5aaa44e3f2869 --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672": { + "source": { + "path": "asset.ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "5b59fa131b8bdd3fda9d78a8b7a199cff546fd4f13ffe4d1a707fa21f18f6146": { + "source": { + "path": "integ-dns-validated-certificate.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5b59fa131b8bdd3fda9d78a8b7a199cff546fd4f13ffe4d1a707fa21f18f6146.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.template.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.template.json new file mode 100644 index 0000000000000..612bb403b5d0c --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ-dns-validated-certificate.template.json @@ -0,0 +1,188 @@ +{ + "Resources": { + "CertificateCertificateRequestorFunctionServiceRoleC04C13DA": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "CertificateCertificateRequestorFunctionServiceRoleDefaultPolicy3C8845BC": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "acm:AddTagsToCertificate", + "acm:DeleteCertificate", + "acm:DescribeCertificate", + "acm:RequestCertificate", + "route53:GetChange" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "route53:changeResourceRecordSets", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":route53:::hostedzone/Z23ABC4XYZL05B" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "CertificateCertificateRequestorFunctionServiceRoleDefaultPolicy3C8845BC", + "Roles": [ + { + "Ref": "CertificateCertificateRequestorFunctionServiceRoleC04C13DA" + } + ] + } + }, + "CertificateCertificateRequestorFunction5E845413": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672.zip" + }, + "Role": { + "Fn::GetAtt": [ + "CertificateCertificateRequestorFunctionServiceRoleC04C13DA", + "Arn" + ] + }, + "Handler": "index.certificateRequestHandler", + "Runtime": "nodejs14.x", + "Timeout": 900 + }, + "DependsOn": [ + "CertificateCertificateRequestorFunctionServiceRoleDefaultPolicy3C8845BC", + "CertificateCertificateRequestorFunctionServiceRoleC04C13DA" + ] + }, + "CertificateCertificateRequestorResource2890C6B7": { + "Type": "AWS::CloudFormation::CustomResource", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CertificateCertificateRequestorFunction5E845413", + "Arn" + ] + }, + "DomainName": "*.example.com", + "HostedZoneId": "Z23ABC4XYZL05B", + "RemovalPolicy": "retain" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "CertificateArn": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { + "Ref": "AWS::Region" + }, + ".console.aws.amazon.com/acm/home?region=", + { + "Ref": "AWS::Region" + }, + "#/certificates/", + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "/", + { + "Fn::GetAtt": [ + "CertificateCertificateRequestorResource2890C6B7", + "Arn" + ] + } + ] + } + ] + } + ] + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ.json new file mode 100644 index 0000000000000..11b3ba887235c --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "enableLookups": true, + "version": "21.0.0", + "testCases": { + "integ-test/DefaultTest": { + "stacks": [ + "integ-dns-validated-certificate" + ], + "diffAssets": true, + "assertionStack": "integ-test/DefaultTest/DeployAssert", + "assertionStackName": "integtestDefaultTestDeployAssert24D5C536" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json new file mode 100644 index 0000000000000..c6322e79691df --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestDefaultTestDeployAssert24D5C536.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/integtestDefaultTestDeployAssert24D5C536.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..9f6568a8b811f --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "integ-dns-validated-certificate.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-dns-validated-certificate.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-dns-validated-certificate": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-dns-validated-certificate.template.json", + "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}/5b59fa131b8bdd3fda9d78a8b7a199cff546fd4f13ffe4d1a707fa21f18f6146.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-dns-validated-certificate.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-dns-validated-certificate.assets" + ], + "metadata": { + "/integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CertificateCertificateRequestorFunctionServiceRoleC04C13DA" + } + ], + "/integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CertificateCertificateRequestorFunctionServiceRoleDefaultPolicy3C8845BC" + } + ], + "/integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CertificateCertificateRequestorFunction5E845413" + } + ], + "/integ-dns-validated-certificate/Certificate/CertificateRequestorResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "CertificateCertificateRequestorResource2890C6B7" + } + ], + "/integ-dns-validated-certificate/CertificateArn": [ + { + "type": "aws:cdk:logicalId", + "data": "CertificateArn" + } + ], + "/integ-dns-validated-certificate/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-dns-validated-certificate/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-dns-validated-certificate" + }, + "integtestDefaultTestDeployAssert24D5C536.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestDefaultTestDeployAssert24D5C536.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestDefaultTestDeployAssert24D5C536": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestDefaultTestDeployAssert24D5C536.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integtestDefaultTestDeployAssert24D5C536.assets" + ], + "metadata": { + "/integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-test/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/tree.json b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/tree.json new file mode 100644 index 0000000000000..5f0cd725d482e --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.integ.snapshot/tree.json @@ -0,0 +1,285 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.102" + } + }, + "integ-dns-validated-certificate": { + "id": "integ-dns-validated-certificate", + "path": "integ-dns-validated-certificate", + "children": { + "HostedZone": { + "id": "HostedZone", + "path": "integ-dns-validated-certificate/HostedZone", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Certificate": { + "id": "Certificate", + "path": "integ-dns-validated-certificate/Certificate", + "children": { + "CertificateRequestorFunction": { + "id": "CertificateRequestorFunction", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "acm:AddTagsToCertificate", + "acm:DeleteCertificate", + "acm:DescribeCertificate", + "acm:RequestCertificate", + "route53:GetChange" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "route53:changeResourceRecordSets", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":route53:::hostedzone/Z23ABC4XYZL05B" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "CertificateCertificateRequestorFunctionServiceRoleDefaultPolicy3C8845BC", + "roles": [ + { + "Ref": "CertificateCertificateRequestorFunctionServiceRoleC04C13DA" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "ef671dfd26b6dde1f73a4325587504813605a928622ebc466f4d0de6a0f3b672.zip" + }, + "role": { + "Fn::GetAtt": [ + "CertificateCertificateRequestorFunctionServiceRoleC04C13DA", + "Arn" + ] + }, + "handler": "index.certificateRequestHandler", + "runtime": "nodejs14.x", + "timeout": 900 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "CertificateRequestorResource": { + "id": "CertificateRequestorResource", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorResource", + "children": { + "Default": { + "id": "Default", + "path": "integ-dns-validated-certificate/Certificate/CertificateRequestorResource/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-certificatemanager.DnsValidatedCertificate", + "version": "0.0.0" + } + }, + "CertificateArn": { + "id": "CertificateArn", + "path": "integ-dns-validated-certificate/CertificateArn", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "integ-test": { + "id": "integ-test", + "path": "integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.102" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-test/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts index 5ed77764de122..688a17ef25a69 100644 --- a/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts +++ b/packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts @@ -1,7 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import { HostedZone, PublicHostedZone } from '@aws-cdk/aws-route53'; -import { App, Stack, Token, Tags } from '@aws-cdk/core'; +import { App, Stack, Token, Tags, RemovalPolicy } from '@aws-cdk/core'; import { DnsValidatedCertificate } from '../lib/dns-validated-certificate'; test('creates CloudFormation Custom Resource', () => { @@ -266,4 +266,36 @@ test('test transparency logging settings is passed to the custom resource', () = }, CertificateTransparencyLoggingPreference: 'DISABLED', }); -}); \ No newline at end of file +}); + +test('can set removal policy', () => { + const stack = new Stack(); + + const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', { + zoneName: 'example.com', + }); + + const cert = new DnsValidatedCertificate(stack, 'Certificate', { + domainName: 'test.example.com', + hostedZone: exampleDotComZone, + subjectAlternativeNames: ['test2.example.com'], + cleanupRoute53Records: true, + }); + cert.applyRemovalPolicy(RemovalPolicy.RETAIN); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFormation::CustomResource', { + DomainName: 'test.example.com', + SubjectAlternativeNames: ['test2.example.com'], + RemovalPolicy: 'retain', + ServiceToken: { + 'Fn::GetAtt': [ + 'CertificateCertificateRequestorFunction5E845413', + 'Arn', + ], + }, + HostedZoneId: { + Ref: 'ExampleDotCom4D1B83AA', + }, + CleanupRecords: 'true', + }); +}); diff --git a/packages/@aws-cdk/aws-certificatemanager/test/integ.dns-validated-certificate.ts b/packages/@aws-cdk/aws-certificatemanager/test/integ.dns-validated-certificate.ts new file mode 100644 index 0000000000000..b5717d16b0005 --- /dev/null +++ b/packages/@aws-cdk/aws-certificatemanager/test/integ.dns-validated-certificate.ts @@ -0,0 +1,50 @@ +import { PublicHostedZone } from '@aws-cdk/aws-route53'; +import { App, Stack, RemovalPolicy, CfnOutput, Fn } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import { DnsValidatedCertificate, CertificateValidation } from '../lib'; + +/** + * In order to test this you need to have a valid public hosted zone that you can use + * to request certificates for. Currently there is not a great way to test scenarios that involve + * multiple deploys so this is what I did to test these scenarios. + * + * 1. comment out the `cert.applyRemovalPolicy` line to create the certificate + * 2. Run `yarn integ --update-on-failed --no-clean` + * 3. uncomment the line to apply the removal policy + * 4. Run `yarn integ --update-on-failed --no-clean` to validate that changing + * that property does not cause a new certificate to be created + * 5. Run `yarn integ --force` to run the test again. Since we didn't pass `--no-clean` + * the stack will be deleted + * 6. Validate that the certificate was not deleted. + * 7. Delete the certificate manually. + */ + +const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID; +if (!hostedZoneId) throw new Error('For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID"'); +const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME; +if (!hostedZoneName) throw new Error('For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME"'); +const domainName = process.env.CDK_INTEG_DOMAIN_NAME ?? process.env.DOMAIN_NAME; +if (!domainName) throw new Error('For this test you must provide your own Domain Name as an env var "DOMAIN_NAME"'); + +const app = new App(); +const stack = new Stack(app, 'integ-dns-validated-certificate'); +const hostedZone = PublicHostedZone.fromHostedZoneAttributes(stack, 'HostedZone', { + hostedZoneId, + zoneName: hostedZoneName, +}); + +const cert = new DnsValidatedCertificate(stack, 'Certificate', { + domainName, + hostedZone, + validation: CertificateValidation.fromDns(hostedZone), +}); +cert.applyRemovalPolicy(RemovalPolicy.RETAIN); +new CfnOutput(stack, 'CertificateArn', { + value: `https://${stack.region}.console.aws.amazon.com/acm/home?region=${stack.region}#/certificates/${Fn.select(1, Fn.split('/', cert.certificateArn))}`, +}); + +new IntegTest(app, 'integ-test', { + testCases: [stack], + diffAssets: true, + enableLookups: true, +}); diff --git a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.integ.snapshot/nested-stacks-test.template.json b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.integ.snapshot/nested-stacks-test.template.json index fdf6b0f116170..1ebcfc8679fec 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.integ.snapshot/nested-stacks-test.template.json +++ b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.integ.snapshot/nested-stacks-test.template.json @@ -91,6 +91,7 @@ }, "SubscriberQueuenestedstackstestNestedStack1topic089C5EB1396F65087": { "Type": "AWS::SNS::Subscription", + "DependsOn": "SubscriberQueuePolicy25A0799E", "Properties": { "Protocol": "sqs", "TopicArn": { @@ -109,6 +110,7 @@ }, "SubscriberQueuenestedstackstestNestedStack1topic1150E1A929A2C267E": { "Type": "AWS::SNS::Subscription", + "DependsOn": "SubscriberQueuePolicy25A0799E", "Properties": { "Protocol": "sqs", "TopicArn": { @@ -127,6 +129,7 @@ }, "SubscriberQueuenestedstackstestNestedStack1topic209B8719858511914": { "Type": "AWS::SNS::Subscription", + "DependsOn": "SubscriberQueuePolicy25A0799E", "Properties": { "Protocol": "sqs", "TopicArn": { diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index 1f87ad8b169a1..c62002d5343c2 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -288,6 +288,30 @@ new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', { }); ``` +#### Actions Suppressor + +If you want to disable actions of a Composite Alarm based on a certain condition, you can use [Actions Suppression](https://www.amazonaws.cn/en/new/2022/amazon-cloudwatch-supports-composite-alarm-actions-suppression/). + +```ts +declare const childAlarm1: cloudwatch.Alarm; +declare const childAlarm2: cloudwatch.Alarm; +declare const onAlarmAction: cloudwatch.IAlarmAction; +declare const onOkAction: cloudwatch.IAlarmAction; +declare const actionsSuppressor: cloudwatch.Alarm; + +const alarmRule = cloudwatch.AlarmRule.anyOf(alarm1, alarm2); + +const myCompositeAlarm = new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', { + alarmRule, + actionsSuppressor, +}); +myCompositeAlarm.addAlarmActions(onAlarmAction); +myComposireAlarm.addOkAction(onOkAction); +``` + +In the provided example, if `actionsSuppressor` is in `ALARM` state, `onAlarmAction` won't be triggered even if `myCompositeAlarm` goes into `ALARM` state. +Similar, if `actionsSuppressor` is in `ALARM` state and `myCompositeAlarm` goes from `ALARM` into `OK` state, `onOkAction` won't be triggered. + ### A note on units In CloudWatch, Metrics datums are emitted with units, such as `seconds` or diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/composite-alarm.ts b/packages/@aws-cdk/aws-cloudwatch/lib/composite-alarm.ts index 08f0db1b0880c..e2a412209e5c4 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/composite-alarm.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/composite-alarm.ts @@ -1,4 +1,4 @@ -import { ArnFormat, Lazy, Names, Stack } from '@aws-cdk/core'; +import { ArnFormat, Lazy, Names, Stack, Duration } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { AlarmBase, IAlarm, IAlarmRule } from './alarm-base'; import { CfnCompositeAlarm } from './cloudwatch.generated'; @@ -18,14 +18,14 @@ export interface CompositeAlarmProps { /** * Description for the alarm * - * @default No description + * @default - No description. */ readonly alarmDescription?: string; /** * Name of the alarm * - * @default Automatically generated name + * @default - Automatically generated name. */ readonly compositeAlarmName?: string; @@ -34,6 +34,28 @@ export interface CompositeAlarmProps { */ readonly alarmRule: IAlarmRule; + /** + * Actions will be suppressed if the suppressor alarm is in the ALARM state. + * + * @default - alarm will not be suppressed. + */ + readonly actionsSuppressor?: IAlarm; + + /** + * The maximum duration that the composite alarm waits after suppressor alarm goes out of the ALARM state. + * After this time, the composite alarm performs its actions. + * + * @default - 1 minute extension period will be set. + */ + readonly actionsSuppressorExtensionPeriod?: Duration; + + /** + * The maximum duration that the composite alarm waits for the suppressor alarm to go into the ALARM state. + * After this time, the composite alarm performs its actions. + * + * @default - 1 minute wait period will be set. + */ + readonly actionsSuppressorWaitPeriod?: Duration; } /** @@ -98,6 +120,17 @@ export class CompositeAlarm extends AlarmBase { throw new Error('Alarm Rule expression cannot be greater than 10240 characters, please reduce the conditions in the Alarm Rule'); } + let extensionPeriod = props.actionsSuppressorExtensionPeriod; + let waitPeriod = props.actionsSuppressorWaitPeriod; + if (props.actionsSuppressor === undefined) { + if (extensionPeriod !== undefined || waitPeriod !== undefined) { + throw new Error('ActionsSuppressor Extension/Wait Periods require an ActionsSuppressor to be set.'); + } + } else { + extensionPeriod = extensionPeriod ?? Duration.minutes(1); + waitPeriod = waitPeriod ?? Duration.minutes(1); + } + this.alarmRule = props.alarmRule.renderAlarmRule(); const alarm = new CfnCompositeAlarm(this, 'Resource', { @@ -108,6 +141,9 @@ export class CompositeAlarm extends AlarmBase { alarmActions: Lazy.list({ produce: () => this.alarmActionArns }), insufficientDataActions: Lazy.list({ produce: (() => this.insufficientDataActionArns) }), okActions: Lazy.list({ produce: () => this.okActionArns }), + actionsSuppressor: props.actionsSuppressor?.alarmArn, + actionsSuppressorExtensionPeriod: extensionPeriod?.toSeconds(), + actionsSuppressorWaitPeriod: waitPeriod?.toSeconds(), }); this.alarmName = this.getResourceNameAttribute(alarm.ref); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.assets.json b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.assets.json index 26cab6f7698f3..6f57ae7b8f1e6 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.assets.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237": { + "ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4": { "source": { "path": "CompositeAlarmIntegrationTest.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237.json", + "objectKey": "ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.template.json b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.template.json index ac9522e52679c..c03f0bcf32b15 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.template.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.template.json @@ -107,7 +107,15 @@ "\")))) OR FALSE)" ] ] - } + }, + "ActionsSuppressor": { + "Fn::GetAtt": [ + "Alarm548383B2F", + "Arn" + ] + }, + "ActionsSuppressorExtensionPeriod": 60, + "ActionsSuppressorWaitPeriod": 60 } } }, diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/integ.json b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/integ.json index 923f46cb8791c..62f015a9b23aa 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { "integ.composite-alarm": { "stacks": [ diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/manifest.json index 0f228a394fe33..28faccf6ea43f 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/tree.json b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/tree.json index a9869726361c3..55ac27b6607a0 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.108" } }, "CompositeAlarmIntegrationTest": { @@ -220,7 +220,15 @@ "\")))) OR FALSE)" ] ] - } + }, + "actionsSuppressor": { + "Fn::GetAtt": [ + "Alarm548383B2F", + "Arn" + ] + }, + "actionsSuppressorExtensionPeriod": 60, + "actionsSuppressorWaitPeriod": 60 } }, "constructInfo": { @@ -236,14 +244,14 @@ } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts index 0633f455eadbf..ad229dbbc5605 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts @@ -1,5 +1,5 @@ import { Template } from '@aws-cdk/assertions'; -import { Stack } from '@aws-cdk/core'; +import { Duration, Stack } from '@aws-cdk/core'; import { Alarm, AlarmRule, AlarmState, CompositeAlarm, Metric } from '../lib'; describe('CompositeAlarm', () => { @@ -109,4 +109,90 @@ describe('CompositeAlarm', () => { }); + test('test action suppressor translates to a correct CFN properties', () => { + const stack = new Stack(); + + const testMetric = new Metric({ + namespace: 'CDK/Test', + metricName: 'Metric', + }); + + const actionsSuppressor = new Alarm(stack, 'Alarm1', { + metric: testMetric, + threshold: 100, + evaluationPeriods: 3, + }); + + + const alarmRule = AlarmRule.fromBoolean(true); + + new CompositeAlarm(stack, 'CompositeAlarm', { + alarmRule, + actionsSuppressor, + actionsSuppressorExtensionPeriod: Duration.minutes(2), + actionsSuppressorWaitPeriod: Duration.minutes(5), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::CompositeAlarm', { + AlarmName: 'CompositeAlarm', + ActionsSuppressor: { + 'Fn::GetAtt': [ + 'Alarm1F9009D71', + 'Arn', + ], + }, + ActionsSuppressorExtensionPeriod: 120, + ActionsSuppressorWaitPeriod: 300, + }); + }); + + test('test wait and extension periods set without action suppressor', () => { + const stack = new Stack(); + + const alarmRule = AlarmRule.fromBoolean(true); + + var createAlarm = () => new CompositeAlarm(stack, 'CompositeAlarm', { + alarmRule, + actionsSuppressorExtensionPeriod: Duration.minutes(2), + actionsSuppressorWaitPeriod: Duration.minutes(5), + }); + + expect(createAlarm).toThrow('ActionsSuppressor Extension/Wait Periods require an ActionsSuppressor to be set.'); + }); + + test('test action suppressor has correct defaults set', () => { + const stack = new Stack(); + + const testMetric = new Metric({ + namespace: 'CDK/Test', + metricName: 'Metric', + }); + + const actionsSuppressor = new Alarm(stack, 'Alarm1', { + metric: testMetric, + threshold: 100, + evaluationPeriods: 3, + }); + + + const alarmRule = AlarmRule.fromBoolean(true); + + new CompositeAlarm(stack, 'CompositeAlarm', { + alarmRule, + actionsSuppressor, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::CompositeAlarm', { + AlarmName: 'CompositeAlarm', + ActionsSuppressor: { + 'Fn::GetAtt': [ + 'Alarm1F9009D71', + 'Arn', + ], + }, + ActionsSuppressorExtensionPeriod: 60, + ActionsSuppressorWaitPeriod: 60, + }); + }); + }); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/integ.composite-alarm.ts b/packages/@aws-cdk/aws-cloudwatch/test/integ.composite-alarm.ts index e4ed35c19c17f..a668b775ee8f5 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/integ.composite-alarm.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/integ.composite-alarm.ts @@ -57,6 +57,7 @@ class CompositeAlarmIntegrationTest extends Stack { new CompositeAlarm(this, 'CompositeAlarm', { alarmRule, + actionsSuppressor: alarm5, }); } diff --git a/packages/@aws-cdk/aws-codedeploy/README.md b/packages/@aws-cdk/aws-codedeploy/README.md index 2608c706022ea..ec5449698294a 100644 --- a/packages/@aws-cdk/aws-codedeploy/README.md +++ b/packages/@aws-cdk/aws-codedeploy/README.md @@ -15,7 +15,7 @@ AWS CodeDeploy is a deployment service that automates application deployments to Amazon EC2 instances, on-premises instances, serverless Lambda functions, or Amazon ECS services. -The CDK currently supports Amazon EC2, on-premise and AWS Lambda applications. +The CDK currently supports Amazon EC2, on-premise, AWS Lambda, and Amazon ECS applications. ## EC2/on-premise Applications @@ -143,7 +143,7 @@ const deploymentGroup = new codedeploy.ServerDeploymentGroup(this, 'DeploymentGr }); ``` -## Deployment Configurations +## EC2/on-premise Deployment Configurations You can also pass a Deployment Configuration when creating the Deployment Group: @@ -226,41 +226,6 @@ In order to deploy a new version of this function: 2. Re-deploy the stack (this will trigger a deployment). 3. Monitor the CodeDeploy deployment as traffic shifts between the versions. - -### Create a custom Deployment Config - -CodeDeploy for Lambda comes with built-in configurations for traffic shifting. -If you want to specify your own strategy, -you can do so with the CustomLambdaDeploymentConfig construct, -letting you specify precisely how fast a new function version is deployed. - -```ts -const config = new codedeploy.CustomLambdaDeploymentConfig(this, 'CustomConfig', { - type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, - interval: Duration.minutes(1), - percentage: 5, -}); - -declare const application: codedeploy.LambdaApplication; -declare const alias: lambda.Alias; -const deploymentGroup = new codedeploy.LambdaDeploymentGroup(this, 'BlueGreenDeployment', { - application, - alias, - deploymentConfig: config, -}); -``` - -You can specify a custom name for your deployment config, but if you do you will not be able to update the interval/percentage through CDK. - -```ts -const config = new codedeploy.CustomLambdaDeploymentConfig(this, 'CustomConfig', { - type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, - interval: Duration.minutes(1), - percentage: 5, - deploymentConfigName: 'MyDeploymentConfig', -}); -``` - ### Rollbacks and Alarms CodeDeploy will roll back if the deployment fails. You can optionally trigger a rollback when one or more alarms are in a failed state: @@ -327,3 +292,127 @@ const deploymentGroup = codedeploy.LambdaDeploymentGroup.fromLambdaDeploymentGro deploymentGroupName: 'MyExistingDeploymentGroup', }); ``` + +## Lambda Deployment Configurations + +CodeDeploy for Lambda comes with predefined configurations for traffic shifting. +The predefined configurations are available as LambdaDeploymentConfig constants. + +```ts +const config = codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_30MINUTES; + +declare const application: codedeploy.LambdaApplication; +declare const alias: lambda.Alias; +const deploymentGroup = new codedeploy.LambdaDeploymentGroup(this, 'BlueGreenDeployment', { + application, + alias, + deploymentConfig: config, +}); +``` + +If you want to specify your own strategy, +you can do so with the LambdaDeploymentConfig construct, +letting you specify precisely how fast a new function version is deployed. + +```ts +const config = new codedeploy.LambdaDeploymentConfig(this, 'CustomConfig', { + trafficRoutingConfig: new codedeploy.TimeBasedCanaryTrafficRoutingConfig({ + interval: cdk.Duration.minutes(15), + percentage: 5, + }), +}); + +declare const application: codedeploy.LambdaApplication; +declare const alias: lambda.Alias; +const deploymentGroup = new codedeploy.LambdaDeploymentGroup(this, 'BlueGreenDeployment', { + application, + alias, + deploymentConfig: config, +}); +``` + +You can specify a custom name for your deployment config, but if you do you will not be able to update the interval/percentage through CDK. + +```ts +const config = new codedeploy.LambdaDeploymentConfig(this, 'CustomConfig', { + trafficRoutingConfig: new codedeploy.TimeBasedCanaryTrafficRoutingConfig({ + interval: cdk.Duration.minutes(15), + percentage: 5, + }), + deploymentConfigName: 'MyDeploymentConfig', +}); +``` + +To import an already existing Deployment Config: + +```ts +const deploymentConfig = codedeploy.LambdaDeploymentConfig.fromLambdaDeploymentConfigName( + this, + 'ExistingDeploymentConfiguration', + 'MyExistingDeploymentConfiguration', +); +``` + +## ECS Applications + +To create a new CodeDeploy Application that deploys an ECS service: + +```ts +const application = new codedeploy.EcsApplication(this, 'CodeDeployApplication', { + applicationName: 'MyApplication', // optional property +}); +``` + +To import an already existing Application: + +```ts +const application = codedeploy.EcsApplication.fromEcsApplicationName( + this, + 'ExistingCodeDeployApplication', + 'MyExistingApplication', +); +``` + +## ECS Deployment Configurations + +CodeDeploy for ECS comes with predefined configurations for traffic shifting. +The predefined configurations are available as LambdaDeploymentConfig constants. + +```ts +const config = codedeploy.EcsDeploymentConfig.CANARY_10PERCENT_5MINUTES; +``` + +If you want to specify your own strategy, +you can do so with the EcsDeploymentConfig construct, +letting you specify precisely how fast an ECS service is deployed. + +```ts +new codedeploy.EcsDeploymentConfig(this, 'CustomConfig', { + trafficRoutingConfig: new codedeploy.TimeBasedCanaryTrafficRoutingConfig({ + interval: cdk.Duration.minutes(15), + percentage: 5, + }), +}); +``` + +You can specify a custom name for your deployment config, but if you do you will not be able to update the interval/percentage through CDK. + +```ts +const config = new codedeploy.EcsDeploymentConfig(this, 'CustomConfig', { + trafficRoutingConfig: new codedeploy.TimeBasedCanaryTrafficRoutingConfig({ + interval: cdk.Duration.minutes(15), + percentage: 5, + }), + deploymentConfigName: 'MyDeploymentConfig', +}); +``` + +Or import an existing one: + +```ts +const deploymentConfig = codedeploy.EcsDeploymentConfig.fromEcsDeploymentConfigName( + this, + 'ExistingDeploymentConfiguration', + 'MyExistingDeploymentConfiguration', +); +``` diff --git a/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts new file mode 100644 index 0000000000000..0cd04ae3628c5 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts @@ -0,0 +1,171 @@ +import { ArnFormat, Resource, Stack } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { CfnDeploymentConfig } from './codedeploy.generated'; +import { MinimumHealthyHosts } from './host-health-config'; +import { TrafficRouting } from './traffic-routing-config'; +import { arnForDeploymentConfig, validateName } from './utils'; + +/** + * The base class for ServerDeploymentConfig, EcsDeploymentConfig, + * and LambdaDeploymentConfig deployment configurations. + */ +export interface IBaseDeploymentConfig { + /** + * The physical, human-readable name of the Deployment Configuration. + * @attribute + */ + readonly deploymentConfigName: string; + + /** + * The ARN of the Deployment Configuration. + * @attribute + */ + readonly deploymentConfigArn: string; +} + +/** + * Construction properties of {@link BaseDeploymentConfig}. + */ +export interface BaseDeploymentConfigOptions { + /** + * The physical, human-readable name of the Deployment Configuration. + * @default - automatically generated name + */ + readonly deploymentConfigName?: string; +} + +/** + * The compute platform of a deployment configuration + */ +export enum ComputePlatform { + /** + * The deployment will target EC2 instances or on-premise servers + */ + SERVER = 'Server', + + /** + * The deployment will target a Lambda function + */ + LAMBDA = 'Lambda', + + /** + * The deployment will target an ECS server + */ + ECS = 'ECS' +} + +/** + * Complete base deployment config properties that are required to be supplied by the implementation + * of the BaseDeploymentConfig class. + */ +export interface BaseDeploymentConfigProps extends BaseDeploymentConfigOptions { + /** + * The destination compute platform for the deployment. + * + * @default ComputePlatform.Server + */ + readonly computePlatform?: ComputePlatform; + + /** + * The configuration that specifies how traffic is shifted during a deployment. + * Only applicable to ECS and Lambda deployments, and must not be specified for Server deployments. + * @default None + */ + readonly trafficRouting?: TrafficRouting; + + /** + * Minimum number of healthy hosts. + * @default None + */ + readonly minimumHealthyHosts?: MinimumHealthyHosts; +} + +/** + * The base class for ServerDeploymentConfig, EcsDeploymentConfig, + * and LambdaDeploymentConfig deployment configurations. + * + * @resource AWS::CodeDeploy::DeploymentConfig + */ +export abstract class BaseDeploymentConfig extends Resource implements IBaseDeploymentConfig { + /** + * Import a custom Deployment Configuration for a Deployment Group defined outside the CDK. + * + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct + * @param deploymentConfigName the name of the referenced custom Deployment Configuration + * @returns a Construct representing a reference to an existing custom Deployment Configuration + */ + protected static fromDeploymentConfigName(scope: Construct, id: string, deploymentConfigName: string): IBaseDeploymentConfig { + ignore(id); + const arn = Stack.of(scope).formatArn({ + service: 'codedeploy', + resource: 'deploymentconfig', + resourceName: deploymentConfigName, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); + return { + deploymentConfigName: deploymentConfigName, + deploymentConfigArn: arn, + }; + } + + /** + * This method should be used only for static references to predefined deployment configurations, + * like EcsDeploymentConfig.ALL_AT_ONCE + * @param name the name of the referenced custom Deployment Configuration + * @returns a reference to an existing custom Deployment Configuration + */ + protected static deploymentConfig(name: string): IBaseDeploymentConfig { + return { + deploymentConfigName: name, + deploymentConfigArn: arnForDeploymentConfig(name), + }; + } + + /** + * The name of the deployment config + * @attribute + */ + public readonly deploymentConfigName: string; + + /** + * The arn of the deployment config + * @attribute + */ + public readonly deploymentConfigArn: string; + + public constructor(scope: Construct, id: string, props?: BaseDeploymentConfigProps) { + super(scope, id, { + physicalName: props?.deploymentConfigName, + }); + + // Traffic routing is not applicable to Server-based deployment configs + if (props?.trafficRouting && (props?.computePlatform === undefined || props?.computePlatform === ComputePlatform.SERVER)) { + throw new Error('Traffic routing config must not be specified for a Server-base deployment configuration'); + } + + // Minimum healthy hosts is only applicable to Server-based deployment configs + if (props?.minimumHealthyHosts && props?.computePlatform && props?.computePlatform !== ComputePlatform.SERVER) { + throw new Error('Minimum healthy hosts config must only be specified for a Server-base deployment configuration'); + } + + const resource = new CfnDeploymentConfig(this, 'Resource', { + deploymentConfigName: this.physicalName, + computePlatform: props?.computePlatform, + trafficRoutingConfig: props?.trafficRouting?.bind(this), + minimumHealthyHosts: props?.minimumHealthyHosts?._json, + }); + + this.deploymentConfigName = this.getResourceNameAttribute(resource.ref); + this.deploymentConfigArn = this.getResourceArnAttribute(arnForDeploymentConfig(resource.ref), { + service: 'codedeploy', + resource: 'deploymentconfig', + resourceName: this.physicalName, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); + + this.node.addValidation({ validate: () => validateName('Deployment config', this.physicalName) }); + } +} + +function ignore(_x: any) { return; } diff --git a/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts index f9f41e12202a7..cd1f96aa50945 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts @@ -1,52 +1,69 @@ import { Construct } from 'constructs'; -import { arnForDeploymentConfig } from '../utils'; +import { BaseDeploymentConfig, BaseDeploymentConfigOptions, ComputePlatform, IBaseDeploymentConfig } from '../base-deployment-config'; +import { TrafficRouting } from '../traffic-routing-config'; /** * The Deployment Configuration of an ECS Deployment Group. + * + * If you're managing the Deployment Configuration alongside the rest of your CDK resources, + * use the {@link EcsDeploymentConfig} class. + * + * If you want to reference an already existing deployment configuration, + * or one defined in a different CDK Stack, + * use the {@link EcsDeploymentConfig#fromEcsDeploymentConfigName} method. + * * The default, pre-defined Configurations are available as constants on the {@link EcsDeploymentConfig} class * (for example, `EcsDeploymentConfig.AllAtOnce`). - * - * Note: CloudFormation does not currently support creating custom ECS configs outside - * of using a custom resource. You can import custom deployment config created outside the - * CDK or via a custom resource with {@link EcsDeploymentConfig#fromEcsDeploymentConfigName}. */ -export interface IEcsDeploymentConfig { - readonly deploymentConfigName: string; - readonly deploymentConfigArn: string; +export interface IEcsDeploymentConfig extends IBaseDeploymentConfig { +} + +/** + * Construction properties of {@link EcsDeploymentConfig}. + */ +export interface EcsDeploymentConfigProps extends BaseDeploymentConfigOptions { + /** + * The configuration that specifies how traffic is shifted from the 'blue' + * target group to the 'green' target group during a deployment. + * @default AllAtOnce + */ + readonly trafficRouting?: TrafficRouting; } /** * A custom Deployment Configuration for an ECS Deployment Group. * - * Note: This class currently stands as namespaced container of the default configurations - * until CloudFormation supports custom ECS Deployment Configs. Until then it is closed - * (private constructor) and does not extend {@link Construct} - * * @resource AWS::CodeDeploy::DeploymentConfig */ -export class EcsDeploymentConfig { - public static readonly ALL_AT_ONCE = deploymentConfig('CodeDeployDefault.ECSAllAtOnce'); +export class EcsDeploymentConfig extends BaseDeploymentConfig implements IEcsDeploymentConfig { + /** CodeDeploy predefined deployment configuration that shifts all traffic to the updated ECS task set at once. */ + public static readonly ALL_AT_ONCE = EcsDeploymentConfig.deploymentConfig('CodeDeployDefault.ECSAllAtOnce'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every minute until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_1MINUTES = EcsDeploymentConfig.deploymentConfig('CodeDeployDefault.ECSLinear10PercentEvery1Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every three minutes until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_3MINUTES = EcsDeploymentConfig.deploymentConfig('CodeDeployDefault.ECSLinear10PercentEvery3Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed five minutes later. */ + public static readonly CANARY_10PERCENT_5MINUTES = EcsDeploymentConfig.deploymentConfig('CodeDeployDefault.ECSCanary10Percent5Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed 15 minutes later. */ + public static readonly CANARY_10PERCENT_15MINUTES = EcsDeploymentConfig.deploymentConfig('CodeDeployDefault.ECSCanary10Percent15Minutes'); /** * Import a custom Deployment Configuration for an ECS Deployment Group defined outside the CDK. * - * @param _scope the parent Construct for this new Construct - * @param _id the logical ID of this new Construct + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct * @param ecsDeploymentConfigName the name of the referenced custom Deployment Configuration * @returns a Construct representing a reference to an existing custom Deployment Configuration */ - public static fromEcsDeploymentConfigName(_scope: Construct, _id: string, ecsDeploymentConfigName: string): IEcsDeploymentConfig { - return deploymentConfig(ecsDeploymentConfigName); + public static fromEcsDeploymentConfigName(scope: Construct, id: string, ecsDeploymentConfigName: string): IEcsDeploymentConfig { + return this.fromDeploymentConfigName(scope, id, ecsDeploymentConfigName); } - private constructor() { - // nothing to do until CFN supports custom ECS deployment configurations + public constructor(scope: Construct, id: string, props?: EcsDeploymentConfigProps) { + super(scope, id, { + ...props, + computePlatform: ComputePlatform.ECS, + trafficRouting: props?.trafficRouting ?? TrafficRouting.allAtOnce(), + }); } } - -function deploymentConfig(name: string): IEcsDeploymentConfig { - return { - deploymentConfigName: name, - deploymentConfigArn: arnForDeploymentConfig(name), - }; -} diff --git a/packages/@aws-cdk/aws-codedeploy/lib/host-health-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/host-health-config.ts new file mode 100644 index 0000000000000..26117518ed090 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/lib/host-health-config.ts @@ -0,0 +1,36 @@ +import { CfnDeploymentConfig } from './codedeploy.generated'; + +/** + * Minimum number of healthy hosts for a server deployment. + */ +export class MinimumHealthyHosts { + + /** + * The minimum healhty hosts threshold expressed as an absolute number. + */ + public static count(value: number): MinimumHealthyHosts { + return new MinimumHealthyHosts({ + type: 'HOST_COUNT', + value, + }); + } + + /** + * The minmum healhty hosts threshold expressed as a percentage of the fleet. + */ + public static percentage(value: number): MinimumHealthyHosts { + return new MinimumHealthyHosts({ + type: 'FLEET_PERCENT', + value, + }); + } + + private constructor(private readonly json: CfnDeploymentConfig.MinimumHealthyHostsProperty) { } + + /** + * @internal + */ + public get _json() { + return this.json; + } +} diff --git a/packages/@aws-cdk/aws-codedeploy/lib/index.ts b/packages/@aws-cdk/aws-codedeploy/lib/index.ts index 147f27580b874..47dd10cc39190 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/index.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/index.ts @@ -1,4 +1,7 @@ +export * from './base-deployment-config'; +export * from './host-health-config'; export * from './rollback-config'; +export * from './traffic-routing-config'; export * from './ecs'; export * from './lambda'; export * from './server'; diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/custom-deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/custom-deployment-config.ts index 726a7781c2dd3..fe4ceeb249af2 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/custom-deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/custom-deployment-config.ts @@ -6,26 +6,31 @@ import { ILambdaDeploymentConfig } from './deployment-config'; /** * Lambda Deployment config type + * @deprecated Use `LambdaDeploymentConfig` */ export enum CustomLambdaDeploymentConfigType { /** * Canary deployment type + * @deprecated Use `LambdaDeploymentConfig` */ CANARY = 'Canary', /** * Linear deployment type + * @deprecated Use `LambdaDeploymentConfig` */ LINEAR = 'Linear' } /** * Properties of a reference to a CodeDeploy Lambda Deployment Configuration. + * @deprecated Use `LambdaDeploymentConfig` */ export interface CustomLambdaDeploymentConfigProps { /** * The type of deployment config, either CANARY or LINEAR + * @deprecated Use `LambdaDeploymentConfig` */ readonly type: CustomLambdaDeploymentConfigType; @@ -33,6 +38,7 @@ export interface CustomLambdaDeploymentConfigProps { * The integer percentage of traffic to shift: * - For LINEAR, the percentage to shift every interval * - For CANARY, the percentage to shift until the interval passes, before the full deployment + * @deprecated Use `LambdaDeploymentConfig` */ readonly percentage: number; @@ -40,6 +46,7 @@ export interface CustomLambdaDeploymentConfigProps { * The interval, in number of minutes: * - For LINEAR, how frequently additional traffic is shifted * - For CANARY, how long to shift traffic before the full deployment + * @deprecated Use `LambdaDeploymentConfig` */ readonly interval: Duration; @@ -47,6 +54,7 @@ export interface CustomLambdaDeploymentConfigProps { * The verbatim name of the deployment config. Must be unique per account/region. * Other parameters cannot be updated if this name is provided. * @default - automatically generated name + * @deprecated Use `LambdaDeploymentConfig` */ readonly deploymentConfigName?: string; } @@ -54,18 +62,21 @@ export interface CustomLambdaDeploymentConfigProps { /** * A custom Deployment Configuration for a Lambda Deployment Group. * @resource AWS::CodeDeploy::DeploymentGroup + * @deprecated CloudFormation now supports Lambda deployment configurations without custom resources. Use {@link LambdaDeploymentConfig}. */ export class CustomLambdaDeploymentConfig extends Resource implements ILambdaDeploymentConfig { /** * The name of the deployment config * @attribute + * @deprecated Use `LambdaDeploymentConfig` */ public readonly deploymentConfigName: string; /** * The arn of the deployment config * @attribute + * @deprecated Use `LambdaDeploymentConfig` */ public readonly deploymentConfigArn: string; diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts index 594d994942f46..18690f239d820 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts @@ -1,18 +1,21 @@ import { Construct } from 'constructs'; -import { arnForDeploymentConfig } from '../utils'; +import { BaseDeploymentConfig, BaseDeploymentConfigOptions, ComputePlatform, IBaseDeploymentConfig } from '../base-deployment-config'; +import { TrafficRouting } from '../traffic-routing-config'; /** * The Deployment Configuration of a Lambda Deployment Group. + * + * If you're managing the Deployment Configuration alongside the rest of your CDK resources, + * use the {@link LambdaDeploymentConfig} class. + * + * If you want to reference an already existing deployment configuration, + * or one defined in a different CDK Stack, + * use the {@link LambdaDeploymentConfig#fromLambdaDeploymentConfigName} method. + * * The default, pre-defined Configurations are available as constants on the {@link LambdaDeploymentConfig} class * (`LambdaDeploymentConfig.AllAtOnce`, `LambdaDeploymentConfig.Canary10Percent30Minutes`, etc.). - * - * Note: CloudFormation does not currently support creating custom lambda configs outside - * of using a custom resource. You can import custom deployment config created outside the - * CDK or via a custom resource with {@link LambdaDeploymentConfig#import}. */ -export interface ILambdaDeploymentConfig { - readonly deploymentConfigName: string; - readonly deploymentConfigArn: string; +export interface ILambdaDeploymentConfig extends IBaseDeploymentConfig { } /** @@ -28,46 +31,72 @@ export interface LambdaDeploymentConfigImportProps { readonly deploymentConfigName: string; } +/** + * Construction properties of {@link LambdaDeploymentConfig}. + */ +export interface LambdaDeploymentConfigProps extends BaseDeploymentConfigOptions { + /** + * The configuration that specifies how traffic is shifted from the 'blue' + * target group to the 'green' target group during a deployment. + * @default AllAtOnce + */ + readonly trafficRouting?: TrafficRouting; +} + /** * A custom Deployment Configuration for a Lambda Deployment Group. - * - * Note: This class currently stands as namespaced container of the default configurations - * until CloudFormation supports custom Lambda Deployment Configs. Until then it is closed - * (private constructor) and does not extend {@link Construct} - * * @resource AWS::CodeDeploy::DeploymentConfig */ -export class LambdaDeploymentConfig { - public static readonly ALL_AT_ONCE = deploymentConfig('CodeDeployDefault.LambdaAllAtOnce'); - public static readonly CANARY_10PERCENT_30MINUTES = deploymentConfig('CodeDeployDefault.LambdaCanary10Percent30Minutes'); - public static readonly CANARY_10PERCENT_5MINUTES = deploymentConfig('CodeDeployDefault.LambdaCanary10Percent5Minutes'); - public static readonly CANARY_10PERCENT_10MINUTES = deploymentConfig('CodeDeployDefault.LambdaCanary10Percent10Minutes'); - public static readonly CANARY_10PERCENT_15MINUTES = deploymentConfig('CodeDeployDefault.LambdaCanary10Percent15Minutes'); - public static readonly LINEAR_10PERCENT_EVERY_10MINUTES = deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery10Minutes'); - public static readonly LINEAR_10PERCENT_EVERY_1MINUTE = deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery1Minute'); - public static readonly LINEAR_10PERCENT_EVERY_2MINUTES = deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery2Minutes'); - public static readonly LINEAR_10PERCENT_EVERY_3MINUTES = deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery3Minutes'); +export class LambdaDeploymentConfig extends BaseDeploymentConfig implements ILambdaDeploymentConfig { + /** CodeDeploy predefined deployment configuration that shifts all traffic to the updated Lambda function at once. */ + public static readonly ALL_AT_ONCE = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaAllAtOnce'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed 30 minutes later. */ + public static readonly CANARY_10PERCENT_30MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaCanary10Percent30Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed five minutes later. */ + public static readonly CANARY_10PERCENT_5MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaCanary10Percent5Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed 10 minutes later. */ + public static readonly CANARY_10PERCENT_10MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaCanary10Percent10Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed 15 minutes later. */ + public static readonly CANARY_10PERCENT_15MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaCanary10Percent15Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every 10 minutes until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_10MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery10Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every minute until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_1MINUTE = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery1Minute'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every two minutes until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_2MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery2Minutes'); + /** CodeDeploy predefined deployment configuration that shifts 10 percent of traffic every three minutes until all traffic is shifted. */ + public static readonly LINEAR_10PERCENT_EVERY_3MINUTES = LambdaDeploymentConfig.deploymentConfig('CodeDeployDefault.LambdaLinear10PercentEvery3Minutes'); + + /** + * Import a Deployment Configuration for a Lambda Deployment Group defined outside the CDK. + * + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct + * @param lambdaDeploymentConfigName the name of the Lambda Deployment Configuration to import + * @returns a Construct representing a reference to an existing Lambda Deployment Configuration + */ + public static fromLambdaDeploymentConfigName(scope: Construct, id: string, lambdaDeploymentConfigName: string): ILambdaDeploymentConfig { + return this.fromDeploymentConfigName(scope, id, lambdaDeploymentConfigName); + } /** - * Import a custom Deployment Configuration for a Lambda Deployment Group defined outside the CDK. + * Import a Deployment Configuration for a Lambda Deployment Group defined outside the CDK. * * @param _scope the parent Construct for this new Construct * @param _id the logical ID of this new Construct * @param props the properties of the referenced custom Deployment Configuration * @returns a Construct representing a reference to an existing custom Deployment Configuration + * @deprecated use `fromLambdaDeploymentConfigName` */ - public static import(_scope:Construct, _id: string, props: LambdaDeploymentConfigImportProps): ILambdaDeploymentConfig { - return deploymentConfig(props.deploymentConfigName); + public static import(_scope: Construct, _id: string, props: LambdaDeploymentConfigImportProps): ILambdaDeploymentConfig { + return this.fromLambdaDeploymentConfigName(_scope, _id, props.deploymentConfigName); } - private constructor() { - // nothing to do until CFN supports custom lambda deployment configurations + public constructor(scope: Construct, id: string, props?: LambdaDeploymentConfigProps) { + super(scope, id, { + ...props, + computePlatform: ComputePlatform.LAMBDA, + trafficRouting: props?.trafficRouting ?? TrafficRouting.allAtOnce(), + }); } } - -function deploymentConfig(name: string): ILambdaDeploymentConfig { - return { - deploymentConfigName: name, - deploymentConfigArn: arnForDeploymentConfig(name), - }; -} diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-config.ts index 7ddb0ec1d37d9..97a9357cbe0bc 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-config.ts @@ -1,7 +1,6 @@ -import * as cdk from '@aws-cdk/core'; import { Construct } from 'constructs'; -import { CfnDeploymentConfig } from '../codedeploy.generated'; -import { arnForDeploymentConfig, validateName } from '../utils'; +import { BaseDeploymentConfig, BaseDeploymentConfigOptions, IBaseDeploymentConfig } from '../base-deployment-config'; +import { MinimumHealthyHosts } from '../host-health-config'; /** * The Deployment Configuration of an EC2/on-premise Deployment Group. @@ -10,64 +9,13 @@ import { arnForDeploymentConfig, validateName } from '../utils'; * To create a custom Deployment Configuration, * instantiate the {@link ServerDeploymentConfig} Construct. */ -export interface IServerDeploymentConfig { - /** - * @attribute - */ - readonly deploymentConfigName: string; - - /** - * @attribute - */ - readonly deploymentConfigArn: string; -} - -/** - * Minimum number of healthy hosts for a server deployment. - */ -export class MinimumHealthyHosts { - - /** - * The minimum healhty hosts threshold expressed as an absolute number. - */ - public static count(value: number): MinimumHealthyHosts { - return new MinimumHealthyHosts({ - type: 'HOST_COUNT', - value, - }); - } - - /** - * The minmum healhty hosts threshold expressed as a percentage of the fleet. - */ - public static percentage(value: number): MinimumHealthyHosts { - return new MinimumHealthyHosts({ - type: 'FLEET_PERCENT', - value, - }); - } - - private constructor(private readonly json: CfnDeploymentConfig.MinimumHealthyHostsProperty) { } - - /** - * @internal - */ - public get _json() { - return this.json; - } +export interface IServerDeploymentConfig extends IBaseDeploymentConfig { } /** * Construction properties of {@link ServerDeploymentConfig}. */ -export interface ServerDeploymentConfigProps { - /** - * The physical, human-readable name of the Deployment Configuration. - * - * @default a name will be auto-generated - */ - readonly deploymentConfigName?: string; - +export interface ServerDeploymentConfigProps extends BaseDeploymentConfigOptions { /** * Minimum number of healthy hosts. */ @@ -79,10 +27,25 @@ export interface ServerDeploymentConfigProps { * * @resource AWS::CodeDeploy::DeploymentConfig */ -export class ServerDeploymentConfig extends cdk.Resource implements IServerDeploymentConfig { - public static readonly ONE_AT_A_TIME = deploymentConfig('CodeDeployDefault.OneAtATime'); - public static readonly HALF_AT_A_TIME = deploymentConfig('CodeDeployDefault.HalfAtATime'); - public static readonly ALL_AT_ONCE = deploymentConfig('CodeDeployDefault.AllAtOnce'); +export class ServerDeploymentConfig extends BaseDeploymentConfig implements IServerDeploymentConfig { + /** + * The CodeDeployDefault.OneAtATime predefined deployment configuration for EC2/on-premises compute platform + * + * @see https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-configurations.html#deployment-configuration-server + */ + public static readonly ONE_AT_A_TIME = ServerDeploymentConfig.deploymentConfig('CodeDeployDefault.OneAtATime'); + /** + * The CodeDeployDefault.HalfAtATime predefined deployment configuration for EC2/on-premises compute platform + * + * @see https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-configurations.html#deployment-configuration-server + */ + public static readonly HALF_AT_A_TIME = ServerDeploymentConfig.deploymentConfig('CodeDeployDefault.HalfAtATime'); + /** + * The CodeDeployDefault.AllAtOnce predefined deployment configuration for EC2/on-premises compute platform + * + * @see https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-configurations.html#deployment-configuration-server + */ + public static readonly ALL_AT_ONCE = ServerDeploymentConfig.deploymentConfig('CodeDeployDefault.AllAtOnce'); /** * Import a custom Deployment Configuration for an EC2/on-premise Deployment Group defined either outside the CDK app, @@ -97,37 +60,10 @@ export class ServerDeploymentConfig extends cdk.Resource implements IServerDeplo scope: Construct, id: string, serverDeploymentConfigName: string): IServerDeploymentConfig { - - ignore(scope); - ignore(id); - return deploymentConfig(serverDeploymentConfigName); + return this.fromDeploymentConfigName(scope, id, serverDeploymentConfigName); } - public readonly deploymentConfigName: string; - public readonly deploymentConfigArn: string; - constructor(scope: Construct, id: string, props: ServerDeploymentConfigProps) { - super(scope, id, { - physicalName: props.deploymentConfigName, - }); - - const resource = new CfnDeploymentConfig(this, 'Resource', { - deploymentConfigName: this.physicalName, - minimumHealthyHosts: props.minimumHealthyHosts._json, - }); - - this.deploymentConfigName = resource.ref; - this.deploymentConfigArn = arnForDeploymentConfig(this.deploymentConfigName); - - this.node.addValidation({ validate: () => validateName('Deployment config', this.physicalName) }); + super(scope, id, props); } } - -function deploymentConfig(name: string): IServerDeploymentConfig { - return { - deploymentConfigName: name, - deploymentConfigArn: arnForDeploymentConfig(name), - }; -} - -function ignore(_x: any) { return; } diff --git a/packages/@aws-cdk/aws-codedeploy/lib/traffic-routing-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/traffic-routing-config.ts new file mode 100644 index 0000000000000..2aa86c8e1f40f --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/lib/traffic-routing-config.ts @@ -0,0 +1,194 @@ +import { Duration } from '@aws-cdk/core'; +import { Construct } from 'constructs'; + +/** + * Represents the structure to pass into the underlying CfnDeploymentConfig class. + */ +export interface TrafficRoutingConfig { + /** + * The type of traffic shifting ( `TimeBasedCanary` or `TimeBasedLinear` ) used by a deployment configuration. + */ + readonly type: string; + + /** + * A configuration that shifts traffic from one version of a Lambda function or ECS task set to another in two increments. + * @default none + */ + readonly timeBasedCanary?: CanaryTrafficRoutingConfig; + + /** + * A configuration that shifts traffic from one version of a Lambda function or Amazon ECS task set to another in equal increments, with an equal number of minutes between each increment. + * @default none + */ + readonly timeBasedLinear?: LinearTrafficRoutingConfig; +} + +/** + * Represents the configuration specific to canary traffic shifting. + */ +export interface CanaryTrafficRoutingConfig { + /** + * The number of minutes between the first and second traffic shifts of a `TimeBasedCanary` deployment. + */ + readonly canaryInterval: number; + + /** + * The percentage of traffic to shift in the first increment of a `TimeBasedCanary` deployment. + */ + readonly canaryPercentage: number; +} + +/** + * Represents the configuration specific to linear traffic shifting. + */ +export interface LinearTrafficRoutingConfig { + /** + * The number of minutes between each incremental traffic shift of a `TimeBasedLinear` deployment. + */ + readonly linearInterval: number; + + /** + * The percentage of traffic that is shifted at the start of each increment of a `TimeBasedLinear` deployment. + */ + readonly linearPercentage: number; +} + +/** + * Represents how traffic is shifted during a CodeDeploy deployment. + */ +export abstract class TrafficRouting { + /** + * Shifts 100% of traffic in a single shift. + */ + public static allAtOnce(): TrafficRouting { + return new AllAtOnceTrafficRouting(); + } + + /** + * Shifts a specified percentage of traffic, waits for a specified amount of time, then shifts the rest of traffic. + */ + public static timeBasedCanary(props: TimeBasedCanaryTrafficRoutingProps): TrafficRouting { + return new TimeBasedCanaryTrafficRouting(props); + } + + /** + * Keeps shifting a specified percentage of traffic until reaching 100%, waiting for a specified amount of time in between each traffic shift. + */ + public static timeBasedLinear(props: TimeBasedLinearTrafficRoutingProps): TrafficRouting { + return new TimeBasedLinearTrafficRouting(props); + } + + /** + * Returns the traffic routing configuration. + */ + public abstract bind(scope: Construct): TrafficRoutingConfig; +} + +/** + * Common properties of traffic shifting routing configurations + */ +export interface BaseTrafficShiftingConfigProps { + /** + * The amount of time between traffic shifts. + */ + readonly interval: Duration; + + /** + * The percentage to increase traffic on each traffic shift. + */ + readonly percentage: number; +} + +/** + * Define a traffic routing config of type 'AllAtOnce'. + */ +export class AllAtOnceTrafficRouting extends TrafficRouting { + constructor() { + super(); + } + + /** + * Return a TrafficRoutingConfig of type `AllAtOnce`. + */ + bind(_scope: Construct): TrafficRoutingConfig { + return { + type: 'AllAtOnce', + }; + } +} + +/** + * Construction properties for {@link TimeBasedCanaryTrafficRouting}. + */ +export interface TimeBasedCanaryTrafficRoutingProps extends BaseTrafficShiftingConfigProps {} + +/** + * Define a traffic routing config of type 'TimeBasedCanary'. + */ +export class TimeBasedCanaryTrafficRouting extends TrafficRouting { + /** + * The amount of time between additional traffic shifts. + */ + readonly interval: Duration; + /** + * The percentage to increase traffic on each traffic shift. + */ + readonly percentage: number; + + constructor(props: TimeBasedCanaryTrafficRoutingProps) { + super(); + this.interval = props.interval; + this.percentage = props.percentage; + } + + /** + * Return a TrafficRoutingConfig of type `TimeBasedCanary`. + */ + bind(_scope: Construct): TrafficRoutingConfig { + return { + type: 'TimeBasedCanary', + timeBasedCanary: { + canaryInterval: this.interval.toMinutes(), + canaryPercentage: this.percentage, + }, + }; + } +} + +/** + * Construction properties for {@link TimeBasedLinearTrafficRouting}. + */ +export interface TimeBasedLinearTrafficRoutingProps extends BaseTrafficShiftingConfigProps {} + +/** + * Define a traffic routing config of type 'TimeBasedLinear'. + */ +export class TimeBasedLinearTrafficRouting extends TrafficRouting { + /** + * The amount of time between additional traffic shifts. + */ + readonly interval: Duration; + /** + * The percentage to increase traffic on each traffic shift. + */ + readonly percentage: number; + + constructor(props: TimeBasedLinearTrafficRoutingProps) { + super(); + this.interval = props.interval; + this.percentage = props.percentage; + } + + /** + * Return a TrafficRoutingConfig of type `TimeBasedLinear`. + */ + bind(_scope: Construct): TrafficRoutingConfig { + return { + type: 'TimeBasedLinear', + timeBasedLinear: { + linearInterval: this.interval.toMinutes(), + linearPercentage: this.percentage, + }, + }; + } +} diff --git a/packages/@aws-cdk/aws-codedeploy/package.json b/packages/@aws-cdk/aws-codedeploy/package.json index 9077c1ba954d2..4cb2301eb5303 100644 --- a/packages/@aws-cdk/aws-codedeploy/package.json +++ b/packages/@aws-cdk/aws-codedeploy/package.json @@ -86,6 +86,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", @@ -124,32 +125,23 @@ "awslint": { "exclude": [ "construct-interface-extends-iconstruct:@aws-cdk/aws-codedeploy.IServerDeploymentConfig", + "construct-interface-extends-iconstruct:@aws-cdk/aws-codedeploy.ILambdaDeploymentConfig", + "construct-interface-extends-iconstruct:@aws-cdk/aws-codedeploy.IEcsDeploymentConfig", "resource-interface-extends-resource:@aws-cdk/aws-codedeploy.IServerDeploymentConfig", - "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentConfig.deploymentConfigArn", + "resource-interface-extends-resource:@aws-cdk/aws-codedeploy.ILambdaDeploymentConfig", + "resource-interface-extends-resource:@aws-cdk/aws-codedeploy.IEcsDeploymentConfig", + "no-static-import:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.import", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup.role", "docs-public-apis:@aws-cdk/aws-codedeploy.InstanceTagSet.instanceTagGroups", "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.ALL_AT_ONCE", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_10MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_15MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_30MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_10MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_1MINUTE", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_2MINUTES", - "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentConfig.LINEAR_10PERCENT_EVERY_3MINUTES", "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentGroup", "docs-public-apis:@aws-cdk/aws-codedeploy.LambdaDeploymentGroup.role", "docs-public-apis:@aws-cdk/aws-codedeploy.LoadBalancer.generation", "docs-public-apis:@aws-cdk/aws-codedeploy.LoadBalancer.name", "docs-public-apis:@aws-cdk/aws-codedeploy.ServerApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.ServerApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentConfig.ALL_AT_ONCE", - "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentConfig.HALF_AT_A_TIME", - "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentConfig.ONE_AT_A_TIME", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup.autoScalingGroups", - "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentConfig.deploymentConfigName", "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentGroup.application", "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentGroup.deploymentConfig", "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentGroup.deploymentGroupArn", @@ -158,12 +150,8 @@ "docs-public-apis:@aws-cdk/aws-codedeploy.ServerDeploymentGroup.role", "docs-public-apis:@aws-cdk/aws-codedeploy.ILambdaApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.ILambdaApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.ILambdaDeploymentConfig.deploymentConfigArn", - "docs-public-apis:@aws-cdk/aws-codedeploy.ILambdaDeploymentConfig.deploymentConfigName", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentConfig.deploymentConfigArn", - "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentConfig.deploymentConfigName", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup.application", "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup.deploymentConfig", @@ -171,11 +159,8 @@ "docs-public-apis:@aws-cdk/aws-codedeploy.IServerDeploymentGroup.deploymentGroupName", "docs-public-apis:@aws-cdk/aws-codedeploy.EcsApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.EcsApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.EcsDeploymentConfig.ALL_AT_ONCE", "docs-public-apis:@aws-cdk/aws-codedeploy.IEcsApplication.applicationArn", "docs-public-apis:@aws-cdk/aws-codedeploy.IEcsApplication.applicationName", - "docs-public-apis:@aws-cdk/aws-codedeploy.IEcsDeploymentConfig.deploymentConfigArn", - "docs-public-apis:@aws-cdk/aws-codedeploy.IEcsDeploymentConfig.deploymentConfigName", "props-physical-name:@aws-cdk/aws-codedeploy.CustomLambdaDeploymentConfigProps" ] }, diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/application.test.ts b/packages/@aws-cdk/aws-codedeploy/test/ecs/application.test.ts index a5661c3538f14..c907bb4c38740 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/ecs/application.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/application.test.ts @@ -43,4 +43,13 @@ describe('CodeDeploy ECS Application', () => { expect(() => app.synth()).toThrow('Application name: "my name" can only contain letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), + (plus signs), = (equals signs), , (commas), @ (at signs), - (minus signs).'); }); + + test('can be imported', () => { + const stack = new cdk.Stack(); + + const application = codedeploy.EcsApplication.fromEcsApplicationName(stack, 'MyApp', 'MyApp'); + + expect(application).not.toEqual(undefined); + expect(application.applicationName).toEqual('MyApp'); + }); }); diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets.json new file mode 100644 index 0000000000000..fa8c0147c3faa --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.template.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.assets.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.assets.json new file mode 100644 index 0000000000000..1ba080dd4d5d9 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "d38ba84a2fd21dc7efb6bafa53ff6671f4f79544905c0de9f396847a2d782a1d": { + "source": { + "path": "aws-cdk-codedeploy-ecs-config.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "d38ba84a2fd21dc7efb6bafa53ff6671f4f79544905c0de9f396847a2d782a1d.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.template.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.template.json new file mode 100644 index 0000000000000..5d1696e08036f --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/aws-cdk-codedeploy-ecs-config.template.json @@ -0,0 +1,51 @@ +{ + "Resources": { + "LinearConfig531CF4AA": { + "Type": "AWS::CodeDeploy::DeploymentConfig", + "Properties": { + "ComputePlatform": "ECS", + "TrafficRoutingConfig": { + "TimeBasedLinear": { + "LinearInterval": 1, + "LinearPercentage": 5 + }, + "Type": "TimeBasedLinear" + } + } + } + }, + "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." + } + ] + } + } +} diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/integ.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/integ.json new file mode 100644 index 0000000000000..8c91633c88ae6 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "EcsDeploymentConfigTest/DefaultTest": { + "stacks": [ + "aws-cdk-codedeploy-ecs-config" + ], + "assertionStack": "EcsDeploymentConfigTest/DefaultTest/DeployAssert", + "assertionStackName": "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..c6dd83b5144dd --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/manifest.json @@ -0,0 +1,111 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-codedeploy-ecs-config.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-codedeploy-ecs-config.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-codedeploy-ecs-config": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-codedeploy-ecs-config.template.json", + "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}/d38ba84a2fd21dc7efb6bafa53ff6671f4f79544905c0de9f396847a2d782a1d.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-codedeploy-ecs-config.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-codedeploy-ecs-config.assets" + ], + "metadata": { + "/aws-cdk-codedeploy-ecs-config/LinearConfig/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LinearConfig531CF4AA" + } + ], + "/aws-cdk-codedeploy-ecs-config/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-codedeploy-ecs-config/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-codedeploy-ecs-config" + }, + "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.template.json", + "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": [ + "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.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": [ + "EcsDeploymentConfigTestDefaultTestDeployAssertA6573788.assets" + ], + "metadata": { + "/EcsDeploymentConfigTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/EcsDeploymentConfigTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "EcsDeploymentConfigTest/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/tree.json b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/tree.json new file mode 100644 index 0000000000000..58546bcc2f842 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.integ.snapshot/tree.json @@ -0,0 +1,99 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "aws-cdk-codedeploy-ecs-config": { + "id": "aws-cdk-codedeploy-ecs-config", + "path": "aws-cdk-codedeploy-ecs-config", + "children": { + "LinearConfig": { + "id": "LinearConfig", + "path": "aws-cdk-codedeploy-ecs-config/LinearConfig", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codedeploy-ecs-config/LinearConfig/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeDeploy::DeploymentConfig", + "aws:cdk:cloudformation:props": { + "computePlatform": "ECS", + "deploymentConfigName": "awscdkcodedeployecsconfigLinearConfig12E7AC8B.EcsLinear5PercentEvery1Minutes", + "trafficRoutingConfig": { + "type": "TimeBasedLinear", + "timeBasedLinear": { + "linearInterval": 1, + "linearPercentage": 5 + } + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codedeploy.CfnDeploymentConfig", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codedeploy.EcsDeploymentConfig", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "EcsDeploymentConfigTest": { + "id": "EcsDeploymentConfigTest", + "path": "EcsDeploymentConfigTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "EcsDeploymentConfigTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "EcsDeploymentConfigTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "EcsDeploymentConfigTest/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.test.ts b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.test.ts new file mode 100644 index 0000000000000..3dc660e10bb08 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-config.test.ts @@ -0,0 +1,142 @@ +import { Template } from '@aws-cdk/assertions'; +import * as cdk from '@aws-cdk/core'; +import * as codedeploy from '../../lib'; +import { TrafficRouting } from '../../lib'; + +/* eslint-disable quote-props */ + +let stack: cdk.Stack; + +beforeEach(() => { + stack = new cdk.Stack(); +}); + +test('can create default config', () => { + // WHEN + new codedeploy.EcsDeploymentConfig(stack, 'MyConfig'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'ECS', + 'TrafficRoutingConfig': { + 'Type': 'AllAtOnce', + }, + }); +}); + +test('can create all-at-once config', () => { + // WHEN + new codedeploy.EcsDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.allAtOnce(), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'ECS', + 'TrafficRoutingConfig': { + 'Type': 'AllAtOnce', + }, + }); +}); + +test('can create linear config', () => { + // WHEN + new codedeploy.EcsDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedLinear({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'ECS', + 'TrafficRoutingConfig': { + 'TimeBasedLinear': { + 'LinearInterval': 1, + 'LinearPercentage': 5, + }, + 'Type': 'TimeBasedLinear', + }, + }); +}); + +test('can create canary config', () => { + // WHEN + new codedeploy.EcsDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'ECS', + 'TrafficRoutingConfig': { + 'TimeBasedCanary': { + 'CanaryInterval': 1, + 'CanaryPercentage': 5, + }, + 'Type': 'TimeBasedCanary', + }, + }); +}); + +test('can create a config with a specific name', () => { + // WHEN + new codedeploy.EcsDeploymentConfig(stack, 'MyConfig', { + deploymentConfigName: 'MyCanaryConfig', + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'ECS', + 'DeploymentConfigName': 'MyCanaryConfig', + 'TrafficRoutingConfig': { + 'TimeBasedCanary': { + 'CanaryInterval': 1, + 'CanaryPercentage': 5, + }, + 'Type': 'TimeBasedCanary', + }, + }); +}); + +test('can be imported', () => { + const deploymentConfig = codedeploy.EcsDeploymentConfig.fromEcsDeploymentConfigName(stack, 'MyDC', 'MyDC'); + + expect(deploymentConfig).not.toEqual(undefined); +}); + +test('fail with more than 100 characters in name', () => { + const app = new cdk.App(); + const stackWithApp = new cdk.Stack(app); + new codedeploy.EcsDeploymentConfig(stackWithApp, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + deploymentConfigName: 'a'.repeat(101), + }); + + expect(() => app.synth()).toThrow(`Deployment config name: "${'a'.repeat(101)}" can be a max of 100 characters.`); +}); + +test('fail with unallowed characters in name', () => { + const app = new cdk.App(); + const stackWithApp = new cdk.Stack(app); + new codedeploy.EcsDeploymentConfig(stackWithApp, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + deploymentConfigName: 'my name', + }); + + expect(() => app.synth()).toThrow('Deployment config name: "my name" can only contain letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), + (plus signs), = (equals signs), , (commas), @ (at signs), - (minus signs).'); +}); diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/integ.deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/test/ecs/integ.deployment-config.ts new file mode 100644 index 0000000000000..651ed7efa0962 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/integ.deployment-config.ts @@ -0,0 +1,19 @@ +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import * as codedeploy from '../../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-ecs-config'); + +new codedeploy.EcsDeploymentConfig(stack, 'LinearConfig', { + trafficRouting: codedeploy.TrafficRouting.timeBasedLinear({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), +}); + +new integ.IntegTest(app, 'EcsDeploymentConfigTest', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/application.test.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/application.test.ts index 4b870c53c0e1d..7832ef202c949 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/lambda/application.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/application.test.ts @@ -41,4 +41,13 @@ describe('CodeDeploy Lambda Application', () => { expect(() => app.synth()).toThrow('Application name: "my name" can only contain letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), + (plus signs), = (equals signs), , (commas), @ (at signs), - (minus signs).'); }); + + test('can be imported', () => { + const stack = new cdk.Stack(); + + const application = codedeploy.LambdaApplication.fromLambdaApplicationName(stack, 'MyApp', 'MyApp'); + + expect(application).not.toEqual(undefined); + expect(application.applicationName).toEqual('MyApp'); + }); }); diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/custom-deployment-config.test.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/custom-deployment-config.test.ts index 4498ed8522f73..20af6c7147751 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/lambda/custom-deployment-config.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/custom-deployment-config.test.ts @@ -1,5 +1,6 @@ import { Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; +import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import * as cdk from '@aws-cdk/core'; import * as codedeploy from '../../lib'; @@ -30,7 +31,7 @@ beforeEach(() => { }); -test('custom resource created', () => { +testDeprecated('custom resource created', () => { // WHEN const config = new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', { type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, @@ -75,7 +76,7 @@ test('custom resource created', () => { }); }); -test('custom resource created with specific name', () => { +testDeprecated('custom resource created with specific name', () => { // WHEN const config = new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', { type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, @@ -97,7 +98,7 @@ test('custom resource created with specific name', () => { }); }); -test('fail with more than 100 characters in name', () => { +testDeprecated('fail with more than 100 characters in name', () => { const app = new cdk.App(); const stackWithApp = new cdk.Stack(app); new codedeploy.CustomLambdaDeploymentConfig(stackWithApp, 'CustomConfig', { @@ -110,7 +111,7 @@ test('fail with more than 100 characters in name', () => { expect(() => app.synth()).toThrow(`Deployment config name: "${'a'.repeat(101)}" can be a max of 100 characters.`); }); -test('fail with unallowed characters in name', () => { +testDeprecated('fail with unallowed characters in name', () => { const app = new cdk.App(); const stackWithApp = new cdk.Stack(app); new codedeploy.CustomLambdaDeploymentConfig(stackWithApp, 'CustomConfig', { @@ -123,7 +124,7 @@ test('fail with unallowed characters in name', () => { expect(() => app.synth()).toThrow('Deployment config name: "my name" can only contain letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), + (plus signs), = (equals signs), , (commas), @ (at signs), - (minus signs).'); }); -test('can create linear custom config', () => { +testDeprecated('can create linear custom config', () => { // WHEN const config = new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', { type: codedeploy.CustomLambdaDeploymentConfigType.LINEAR, @@ -142,7 +143,7 @@ test('can create linear custom config', () => { }); }); -test('can create canary custom config', () => { +testDeprecated('can create canary custom config', () => { // WHEN const config = new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', { type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, @@ -161,7 +162,7 @@ test('can create canary custom config', () => { }); }); -test('dependency on the config exists to ensure ordering', () => { +testDeprecated('dependency on the config exists to ensure ordering', () => { // WHEN const config = new codedeploy.CustomLambdaDeploymentConfig(stack, 'CustomConfig', { type: codedeploy.CustomLambdaDeploymentConfigType.CANARY, diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets.json new file mode 100644 index 0000000000000..bd67c83d14603 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.template.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.assets.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.assets.json new file mode 100644 index 0000000000000..d861f05e2c9fb --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "681328df6a987c681a4d5cafad61efbf97e5934c41842c8fc92c113ee39a6b28": { + "source": { + "path": "aws-cdk-codedeploy-lambda-config.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "681328df6a987c681a4d5cafad61efbf97e5934c41842c8fc92c113ee39a6b28.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.template.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.template.json new file mode 100644 index 0000000000000..2c5dddc618a4a --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/aws-cdk-codedeploy-lambda-config.template.json @@ -0,0 +1,51 @@ +{ + "Resources": { + "LinearConfig531CF4AA": { + "Type": "AWS::CodeDeploy::DeploymentConfig", + "Properties": { + "ComputePlatform": "Lambda", + "TrafficRoutingConfig": { + "TimeBasedLinear": { + "LinearInterval": 1, + "LinearPercentage": 5 + }, + "Type": "TimeBasedLinear" + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/integ.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/integ.json new file mode 100644 index 0000000000000..094127896a86e --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "LambdaDeploymentConfigTest/DefaultTest": { + "stacks": [ + "aws-cdk-codedeploy-lambda-config" + ], + "assertionStack": "LambdaDeploymentConfigTest/DefaultTest/DeployAssert", + "assertionStackName": "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..c6fc338e7e046 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/manifest.json @@ -0,0 +1,111 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-codedeploy-lambda-config.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-codedeploy-lambda-config.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-codedeploy-lambda-config": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-codedeploy-lambda-config.template.json", + "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}/681328df6a987c681a4d5cafad61efbf97e5934c41842c8fc92c113ee39a6b28.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-codedeploy-lambda-config.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-codedeploy-lambda-config.assets" + ], + "metadata": { + "/aws-cdk-codedeploy-lambda-config/LinearConfig/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LinearConfig531CF4AA" + } + ], + "/aws-cdk-codedeploy-lambda-config/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-codedeploy-lambda-config/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-codedeploy-lambda-config" + }, + "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.template.json", + "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": [ + "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.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": [ + "LambdaDeploymentConfigTestDefaultTestDeployAssert161B09F6.assets" + ], + "metadata": { + "/LambdaDeploymentConfigTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/LambdaDeploymentConfigTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "LambdaDeploymentConfigTest/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/tree.json b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/tree.json new file mode 100644 index 0000000000000..9f9a449ffe63b --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.integ.snapshot/tree.json @@ -0,0 +1,99 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "aws-cdk-codedeploy-lambda-config": { + "id": "aws-cdk-codedeploy-lambda-config", + "path": "aws-cdk-codedeploy-lambda-config", + "children": { + "LinearConfig": { + "id": "LinearConfig", + "path": "aws-cdk-codedeploy-lambda-config/LinearConfig", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codedeploy-lambda-config/LinearConfig/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeDeploy::DeploymentConfig", + "aws:cdk:cloudformation:props": { + "computePlatform": "Lambda", + "deploymentConfigName": "awscdkcodedeploylambdaconfigLinearConfig655064A4.LambdaLinear5PercentEvery1Minutes", + "trafficRoutingConfig": { + "type": "TimeBasedLinear", + "timeBasedLinear": { + "linearInterval": 1, + "linearPercentage": 5 + } + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codedeploy.CfnDeploymentConfig", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codedeploy.LambdaDeploymentConfig", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "LambdaDeploymentConfigTest": { + "id": "LambdaDeploymentConfigTest", + "path": "LambdaDeploymentConfigTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "LambdaDeploymentConfigTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "LambdaDeploymentConfigTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "LambdaDeploymentConfigTest/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.test.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.test.ts new file mode 100644 index 0000000000000..b50e897bf366d --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-config.test.ts @@ -0,0 +1,142 @@ +import { Template } from '@aws-cdk/assertions'; +import * as cdk from '@aws-cdk/core'; +import * as codedeploy from '../../lib'; +import { TrafficRouting } from '../../lib'; + +/* eslint-disable quote-props */ + +let stack: cdk.Stack; + +beforeEach(() => { + stack = new cdk.Stack(); +}); + +test('can create default config', () => { + // WHEN + new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'Lambda', + 'TrafficRoutingConfig': { + 'Type': 'AllAtOnce', + }, + }); +}); + +test('can create all-at-once config', () => { + // WHEN + new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.allAtOnce(), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'Lambda', + 'TrafficRoutingConfig': { + 'Type': 'AllAtOnce', + }, + }); +}); + +test('can create linear config', () => { + // WHEN + new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedLinear({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'Lambda', + 'TrafficRoutingConfig': { + 'TimeBasedLinear': { + 'LinearInterval': 1, + 'LinearPercentage': 5, + }, + 'Type': 'TimeBasedLinear', + }, + }); +}); + +test('can create canary config', () => { + // WHEN + new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'Lambda', + 'TrafficRoutingConfig': { + 'TimeBasedCanary': { + 'CanaryInterval': 1, + 'CanaryPercentage': 5, + }, + 'Type': 'TimeBasedCanary', + }, + }); +}); + +test('can create a config with a specific name', () => { + // WHEN + new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig', { + deploymentConfigName: 'MyCanaryConfig', + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CodeDeploy::DeploymentConfig', { + 'ComputePlatform': 'Lambda', + 'DeploymentConfigName': 'MyCanaryConfig', + 'TrafficRoutingConfig': { + 'TimeBasedCanary': { + 'CanaryInterval': 1, + 'CanaryPercentage': 5, + }, + 'Type': 'TimeBasedCanary', + }, + }); +}); + +test('can be imported', () => { + const deploymentConfig = codedeploy.LambdaDeploymentConfig.fromLambdaDeploymentConfigName(stack, 'MyDC', 'MyDC'); + + expect(deploymentConfig).not.toEqual(undefined); +}); + +test('fail with more than 100 characters in name', () => { + const app = new cdk.App(); + const stackWithApp = new cdk.Stack(app); + new codedeploy.LambdaDeploymentConfig(stackWithApp, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + deploymentConfigName: 'a'.repeat(101), + }); + + expect(() => app.synth()).toThrow(`Deployment config name: "${'a'.repeat(101)}" can be a max of 100 characters.`); +}); + +test('fail with unallowed characters in name', () => { + const app = new cdk.App(); + const stackWithApp = new cdk.Stack(app); + new codedeploy.LambdaDeploymentConfig(stackWithApp, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + deploymentConfigName: 'my name', + }); + + expect(() => app.synth()).toThrow('Deployment config name: "my name" can only contain letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), + (plus signs), = (equals signs), , (commas), @ (at signs), - (minus signs).'); +}); diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts index 9fc6049e9a2c5..959c98bbce139 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts @@ -4,6 +4,7 @@ import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; import * as codedeploy from '../../lib'; +import { TrafficRouting } from '../../lib'; function mockFunction(stack: cdk.Stack, id: string) { return new lambda.Function(stack, id, { @@ -629,3 +630,31 @@ describe('imported with fromLambdaDeploymentGroupAttributes', () => { expect(importedGroup.deploymentConfig).toEqual(codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES); }); }); + +test('dependency on the config exists to ensure ordering', () => { + // WHEN + const stack = new cdk.Stack(); + const application = new codedeploy.LambdaApplication(stack, 'MyApp'); + const alias = mockAlias(stack); + const config = new codedeploy.LambdaDeploymentConfig(stack, 'MyConfig', { + trafficRouting: TrafficRouting.timeBasedCanary({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), + }); + new codedeploy.LambdaDeploymentGroup(stack, 'MyDG', { + application, + alias, + deploymentConfig: config, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::CodeDeploy::DeploymentGroup', { + Properties: { + DeploymentConfigName: stack.resolve(config.deploymentConfigName), + }, + DependsOn: [ + stack.getLogicalId(config.node.defaultChild as codedeploy.CfnDeploymentConfig), + ], + }); +}); diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/integ.deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/integ.deployment-config.ts new file mode 100644 index 0000000000000..de578cb7eb648 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/integ.deployment-config.ts @@ -0,0 +1,19 @@ +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import * as codedeploy from '../../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-codedeploy-lambda-config'); + +new codedeploy.LambdaDeploymentConfig(stack, 'LinearConfig', { + trafficRouting: codedeploy.TrafficRouting.timeBasedLinear({ + interval: cdk.Duration.minutes(1), + percentage: 5, + }), +}); + +new integ.IntegTest(app, 'LambdaDeploymentConfigTest', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-codepipeline-actions/README.md b/packages/@aws-cdk/aws-codepipeline-actions/README.md index 0d04e0b241187..3a3c211e46ae7 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/README.md +++ b/packages/@aws-cdk/aws-codepipeline-actions/README.md @@ -945,6 +945,28 @@ new codepipeline.Pipeline(this, 'Pipeline', { }); ``` +### Elastic Beanstalk Deployment + +To deploy an Elastic Beanstalk Application in CodePipeline: + +```ts +const sourceOutput = new codepipeline.Artifact(); +const targetBucket = new s3.Bucket(this, 'MyBucket'); + +const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); +const deployAction = new codepipeline_actions.ElasticBeanstalkDeployAction({ + actionName: 'ElasticBeanstalkDeploy', + input: sourceOutput, + environmentName: 'envName', + applicationName: 'appName', +}); + +const deployStage = pipeline.addStage({ + stageName: 'Deploy', + actions: [deployAction], +}); +``` + ### Alexa Skill You can deploy to Alexa using CodePipeline with the following Action: diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/elastic-beanstalk/deploy-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/elastic-beanstalk/deploy-action.ts new file mode 100644 index 0000000000000..a356078c74a69 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/elastic-beanstalk/deploy-action.ts @@ -0,0 +1,66 @@ +import * as codepipeline from '@aws-cdk/aws-codepipeline'; +import { Construct } from 'constructs'; +import { Action } from '../action'; +import { deployArtifactBounds } from '../common'; + +/** + * Construction properties of the {@link ElasticBeanstalkDeployAction Elastic Beanstalk deploy CodePipeline Action}. + */ +export interface ElasticBeanstalkDeployActionProps extends codepipeline.CommonAwsActionProps { + /** + * The source to use as input for deployment. + */ + readonly input: codepipeline.Artifact; + + /** + * The name of the AWS Elastic Beanstalk application to deploy. + */ + readonly applicationName: string; + + /** + * The name of the AWS Elastic Beanstalk environment to deploy to. + */ + readonly environmentName: string; +} + +/** + * CodePipeline action to deploy an AWS ElasticBeanstalk Application. + */ +export class ElasticBeanstalkDeployAction extends Action { + private readonly applicationName: string; + private readonly environmentName: string; + + constructor(props: ElasticBeanstalkDeployActionProps) { + super({ + ...props, + category: codepipeline.ActionCategory.DEPLOY, + provider: 'ElasticBeanstalk', + artifactBounds: deployArtifactBounds(), + inputs: [props.input], + }); + + this.applicationName = props.applicationName; + this.environmentName = props.environmentName; + } + + protected bound( + _scope: Construct, + _stage: codepipeline.IStage, + options: codepipeline.ActionBindOptions, + ): codepipeline.ActionConfig { + + // Per https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.iam.managed-policies.html + // it doesn't seem we can scope this down further for the codepipeline action. + options.role.addManagedPolicy({ managedPolicyArn: 'arn:aws:iam::aws:policy/AdministratorAccess-AWSElasticBeanstalk' }); + + // the Action's Role needs to read from the Bucket to get artifacts + options.bucket.grantRead(options.role); + + return { + configuration: { + ApplicationName: this.applicationName, + EnvironmentName: this.environmentName, + }, + }; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts index a0d665eddd886..e82e34232e931 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts @@ -8,6 +8,7 @@ export * from './codedeploy/ecs-deploy-action'; export * from './codedeploy/server-deploy-action'; export * from './ecr/source-action'; export * from './ecs/deploy-action'; +export * from './elastic-beanstalk/deploy-action'; export * from './github/source-action'; export * from './jenkins/jenkins-action'; export * from './jenkins/jenkins-provider'; diff --git a/packages/@aws-cdk/aws-codepipeline-actions/package.json b/packages/@aws-cdk/aws-codepipeline-actions/package.json index c8e37b02fd3ec..ab49ad77e0451 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/package.json +++ b/packages/@aws-cdk/aws-codepipeline-actions/package.json @@ -80,6 +80,7 @@ "@aws-cdk/aws-cloudtrail": "0.0.0", "@aws-cdk/aws-codestarnotifications": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", + "@aws-cdk/aws-s3-deployment": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", @@ -99,6 +100,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-ecr": "0.0.0", "@aws-cdk/aws-ecs": "0.0.0", + "@aws-cdk/aws-elasticbeanstalk": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-events-targets": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", @@ -122,6 +124,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-ecr": "0.0.0", "@aws-cdk/aws-ecs": "0.0.0", + "@aws-cdk/aws-elasticbeanstalk": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-events-targets": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/assets/nodejs.zip b/packages/@aws-cdk/aws-codepipeline-actions/test/assets/nodejs.zip new file mode 100644 index 0000000000000..4810a50d131d9 Binary files /dev/null and b/packages/@aws-cdk/aws-codepipeline-actions/test/assets/nodejs.zip differ diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/elastic-beanstalk/elastic-beanstalk-deploy-action.test.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/elastic-beanstalk/elastic-beanstalk-deploy-action.test.ts new file mode 100644 index 0000000000000..16855d3342f11 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/elastic-beanstalk/elastic-beanstalk-deploy-action.test.ts @@ -0,0 +1,126 @@ +import { Template } from '@aws-cdk/assertions'; +import * as codepipeline from '@aws-cdk/aws-codepipeline'; +import { Bucket } from '@aws-cdk/aws-s3'; +import { App, Stack } from '@aws-cdk/core'; +import { ElasticBeanstalkDeployAction, S3SourceAction, S3Trigger } from '../../lib'; + +describe('elastic beanstalk deploy action tests', () => { + test('region and account are action region and account when set', () => { + const stack = buildPipelineStack(); + Template.fromStack(stack).hasResourceProperties('AWS::CodePipeline::Pipeline', { + Stages: [ + { + Actions: [ + { + ActionTypeId: { + Category: 'Source', + Owner: 'AWS', + Provider: 'S3', + Version: '1', + }, + Configuration: { + S3Bucket: { + Ref: 'MyBucketF68F3FF0', + }, + S3ObjectKey: 'some/path/to', + PollForSourceChanges: true, + }, + Name: 'Source', + OutputArtifacts: [ + { + Name: 'Artifact_Source_Source', + }, + ], + RoleArn: { + 'Fn::GetAtt': [ + 'MyPipelineSourceCodePipelineActionRoleAA05D76F', + 'Arn', + ], + }, + RunOrder: 1, + }, + ], + Name: 'Source', + }, + { + Actions: [ + { + ActionTypeId: { + Category: 'Deploy', + Owner: 'AWS', + Provider: 'ElasticBeanstalk', + Version: '1', + }, + Configuration: { + ApplicationName: 'testApplication', + EnvironmentName: 'env-testApplication', + }, + InputArtifacts: [ + { + Name: 'Artifact_Source_Source', + }, + ], + Name: 'Deploy', + RoleArn: { + 'Fn::GetAtt': [ + 'MyPipelineDeployCodePipelineActionRole742BD48A', + 'Arn', + ], + }, + RunOrder: 1, + }, + ], + Name: 'Deploy', + }, + ], + ArtifactStore: { + EncryptionKey: { + Id: { + 'Fn::GetAtt': [ + 'MyPipelineArtifactsBucketEncryptionKey8BF0A7F3', + 'Arn', + ], + }, + Type: 'KMS', + }, + Location: { + Ref: 'MyPipelineArtifactsBucket727923DD', + }, + Type: 'S3', + }, + }); + }); +}); + +function buildPipelineStack(): Stack { + const app = new App(); + const stack = new Stack(app); + const sourceOutput = new codepipeline.Artifact(); + const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline'); + pipeline.addStage({ + stageName: 'Source', + actions: [ + new S3SourceAction({ + actionName: 'Source', + bucket: new Bucket(stack, 'MyBucket'), + bucketKey: 'some/path/to', + output: sourceOutput, + trigger: S3Trigger.POLL, + }), + ], + }); + + pipeline.addStage({ + stageName: 'Deploy', + actions: [ + new ElasticBeanstalkDeployAction({ + actionName: 'Deploy', + applicationName: 'testApplication', + environmentName: 'env-testApplication', + input: sourceOutput, + }), + ], + }); + + return stack; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeilne-elastic-beanstalk-deploy.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeilne-elastic-beanstalk-deploy.ts new file mode 100644 index 0000000000000..631c3d6f84c26 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeilne-elastic-beanstalk-deploy.ts @@ -0,0 +1,147 @@ +import * as path from 'path'; +import * as codepipeline from '@aws-cdk/aws-codepipeline'; +import * as elasticbeanstalk from '@aws-cdk/aws-elasticbeanstalk'; +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as deploy from '@aws-cdk/aws-s3-deployment'; +import { App, Fn, RemovalPolicy, Stack } from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import * as cpactions from '../lib'; + +/** + * To validate that the deployment actually succeeds, perform the following actions: + * + * 1. Delete the snapshot + * 2. Run `yarn integ --update-on-failed --no-clean` + * 3. Navigate to CodePipeline in the console and click 'Release change' + * - Before releasing the change, the pipeline will show a failure because it + * attempts to run on creation but the elastic beanstalk environment is not yet ready + * 4. Navigate to Elastic Beanstalk and click on the URL for the application just deployed + * - You should see 'Congratulations' message + * 5. Manually delete the 'aws-cdk-codepipeline-elastic-beanstalk-deploy' stack + */ + +const app = new App(); + +const stack = new Stack(app, 'aws-cdk-codepipeline-elastic-beanstalk-deploy'); + +const bucket = new s3.Bucket(stack, 'PipelineBucket', { + versioned: true, + removalPolicy: RemovalPolicy.DESTROY, + autoDeleteObjects: true, +}); + +const artifact = new deploy.BucketDeployment(stack, 'DeployApp', { + sources: [deploy.Source.asset(path.join(__dirname, 'assets/nodejs.zip'))], + destinationBucket: bucket, + extract: false, +}); + +const serviceRole = new iam.Role(stack, 'service-role', { + roleName: 'codepipeline-elasticbeanstalk-action-test-serivce-role', + assumedBy: new iam.ServicePrincipal('elasticbeanstalk.amazonaws.com'), + managedPolicies: [ + { + managedPolicyArn: 'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth', + }, + { + managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy', + }, + ], +}); + +const instanceProfileRole = new iam.Role(stack, 'instance-profile-role', { + roleName: 'codepipeline-elasticbeanstalk-action-test-instance-profile-role', + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), + managedPolicies: [ + { + managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier', + }, + { + managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker', + }, + { + managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier', + }, + ], +}); + +const instanceProfile = new iam.CfnInstanceProfile(stack, 'instance-profile', { + roles: [instanceProfileRole.roleName], + instanceProfileName: instanceProfileRole.roleName, +}); + +const beanstalkApp = new elasticbeanstalk.CfnApplication(stack, 'beastalk-app', { + applicationName: 'codepipeline-test-app', +}); + +const beanstalkEnv = new elasticbeanstalk.CfnEnvironment(stack, 'beanstlk-env', { + applicationName: beanstalkApp.applicationName!, + environmentName: 'codepipeline-test-env', + solutionStackName: '64bit Amazon Linux 2 v5.5.6 running Node.js 16', + optionSettings: [ + { + namespace: 'aws:autoscaling:launchconfiguration', + optionName: 'IamInstanceProfile', + value: instanceProfile.instanceProfileName, + }, + { + namespace: 'aws:elasticbeanstalk:environment', + optionName: 'ServiceRole', + value: serviceRole.roleName, + }, + { + namespace: 'aws:elasticbeanstalk:environment', + optionName: 'LoadBalancerType', + value: 'application', + }, + { + namespace: 'aws:elasticbeanstalk:managedactions', + optionName: 'ServiceRoleForManagedUpdates', + value: 'AWSServiceRoleForElasticBeanstalkManagedUpdates', + }, + ], +}); + +beanstalkEnv.addDependsOn(instanceProfile); +beanstalkEnv.addDependsOn(beanstalkApp); + +const pipeline = new codepipeline.Pipeline(stack, 'Pipeline', { + artifactBucket: bucket, +}); + +const sourceOutput = new codepipeline.Artifact('SourceArtifact'); +const sourceAction = new cpactions.S3SourceAction({ + actionName: 'Source', + output: sourceOutput, + bucket, + bucketKey: Fn.select(0, artifact.objectKeys), +}); + +pipeline.addStage({ + stageName: 'Source', + actions: [ + sourceAction, + ], +}); + +const deployAction = new cpactions.ElasticBeanstalkDeployAction({ + actionName: 'Deploy', + input: sourceOutput, + environmentName: beanstalkEnv.environmentName!, + applicationName: beanstalkApp.applicationName!, +}); + +pipeline.addStage({ + stageName: 'Deploy', + actions: [ + deployAction, + ], +}); + +new integ.IntegTest(app, 'codepipeline-elastic-beanstalk-deploy', { + testCases: [stack], + stackUpdateWorkflow: false, +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.assets.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.assets.json new file mode 100644 index 0000000000000..9de2d1dbcc771 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.assets.json @@ -0,0 +1,71 @@ +{ + "version": "21.0.0", + "files": { + "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26": { + "source": { + "path": "asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc": { + "source": { + "path": "asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6ddcf10002539818a9256eff3fb2b22aa09298d8f946e26ba121c175a600c44e": { + "source": { + "path": "asset.6ddcf10002539818a9256eff3fb2b22aa09298d8f946e26ba121c175a600c44e", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6ddcf10002539818a9256eff3fb2b22aa09298d8f946e26ba121c175a600c44e.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6a9a0507c3e2bfac9749f257bdd3d9f313c01ee3984ad7bf373597c341863d6f": { + "source": { + "path": "asset.6a9a0507c3e2bfac9749f257bdd3d9f313c01ee3984ad7bf373597c341863d6f.zip", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6a9a0507c3e2bfac9749f257bdd3d9f313c01ee3984ad7bf373597c341863d6f.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "41fa0558ddcbfbd77d585fbccca6c3d2435c64c4949b651ff2c2e22ca3c5690e": { + "source": { + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "41fa0558ddcbfbd77d585fbccca6c3d2435c64c4949b651ff2c2e22ca3c5690e.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.template.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.template.json new file mode 100644 index 0000000000000..d8c77c41abaff --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/aws-cdk-codepipeline-elastic-beanstalk-deploy.template.json @@ -0,0 +1,877 @@ +{ + "Resources": { + "PipelineBucketB967BD35": { + "Type": "AWS::S3::Bucket", + "Properties": { + "Tags": [ + { + "Key": "aws-cdk:auto-delete-objects", + "Value": "true" + }, + { + "Key": "aws-cdk:cr-owned:46838d62", + "Value": "true" + } + ], + "VersioningConfiguration": { + "Status": "Enabled" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "PipelineBucketPolicyD65CDEF5": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "PipelineBucketB967BD35" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineBucketAutoDeleteObjectsCustomResource5F37E165": { + "Type": "Custom::S3AutoDeleteObjects", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F", + "Arn" + ] + }, + "BucketName": { + "Ref": "PipelineBucketB967BD35" + } + }, + "DependsOn": [ + "PipelineBucketPolicyD65CDEF5" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ] + } + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Description": { + "Fn::Join": [ + "", + [ + "Lambda function for auto-deleting objects in ", + { + "Ref": "PipelineBucketB967BD35" + }, + " S3 bucket." + ] + ] + } + }, + "DependsOn": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + ] + }, + "DeployAppAwsCliLayerAEF99B2F": { + "Type": "AWS::Lambda::LayerVersion", + "Properties": { + "Content": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip" + }, + "Description": "/opt/awscli/aws" + } + }, + "DeployAppCustomResourceDEE6DDD6": { + "Type": "Custom::CDKBucketDeployment", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536", + "Arn" + ] + }, + "SourceBucketNames": [ + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ], + "SourceObjectKeys": [ + "6a9a0507c3e2bfac9749f257bdd3d9f313c01ee3984ad7bf373597c341863d6f.zip" + ], + "DestinationBucketName": { + "Ref": "PipelineBucketB967BD35" + }, + "Extract": false, + "Prune": true + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "Roles": [ + { + "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ] + } + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "6ddcf10002539818a9256eff3fb2b22aa09298d8f946e26ba121c175a600c44e.zip" + }, + "Role": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", + "Arn" + ] + }, + "Handler": "index.handler", + "Layers": [ + { + "Ref": "DeployAppAwsCliLayerAEF99B2F" + } + ], + "Runtime": "python3.9", + "Timeout": 900 + }, + "DependsOn": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + ] + }, + "servicerole2C3CD20E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "elasticbeanstalk.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy" + ], + "RoleName": "codepipeline-elasticbeanstalk-action-test-serivce-role" + } + }, + "instanceprofilerole786BCBC7": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier" + ], + "RoleName": "codepipeline-elasticbeanstalk-action-test-instance-profile-role" + } + }, + "instanceprofile": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "instanceprofilerole786BCBC7" + } + ], + "InstanceProfileName": { + "Ref": "instanceprofilerole786BCBC7" + } + } + }, + "beastalkapp": { + "Type": "AWS::ElasticBeanstalk::Application", + "Properties": { + "ApplicationName": "codepipeline-test-app" + } + }, + "beanstlkenv": { + "Type": "AWS::ElasticBeanstalk::Environment", + "Properties": { + "ApplicationName": "codepipeline-test-app", + "EnvironmentName": "codepipeline-test-env", + "OptionSettings": [ + { + "Namespace": "aws:autoscaling:launchconfiguration", + "OptionName": "IamInstanceProfile", + "Value": { + "Ref": "instanceprofilerole786BCBC7" + } + }, + { + "Namespace": "aws:elasticbeanstalk:environment", + "OptionName": "ServiceRole", + "Value": { + "Ref": "servicerole2C3CD20E" + } + }, + { + "Namespace": "aws:elasticbeanstalk:environment", + "OptionName": "LoadBalancerType", + "Value": "application" + }, + { + "Namespace": "aws:elasticbeanstalk:managedactions", + "OptionName": "ServiceRoleForManagedUpdates", + "Value": "AWSServiceRoleForElasticBeanstalkManagedUpdates" + } + ], + "SolutionStackName": "64bit Amazon Linux 2 v5.5.6 running Node.js 16" + }, + "DependsOn": [ + "beastalkapp", + "instanceprofile" + ] + }, + "PipelineRoleD68726F7": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineRoleDefaultPolicyC7A05455": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineDeployCodePipelineActionRole8B83082E", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "PipelineSourceCodePipelineActionRoleC6F9E7F5", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineRoleDefaultPolicyC7A05455", + "Roles": [ + { + "Ref": "PipelineRoleD68726F7" + } + ] + } + }, + "PipelineC660917D": { + "Type": "AWS::CodePipeline::Pipeline", + "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "PipelineRoleD68726F7", + "Arn" + ] + }, + "Stages": [ + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Source", + "Owner": "AWS", + "Provider": "S3", + "Version": "1" + }, + "Configuration": { + "S3Bucket": { + "Ref": "PipelineBucketB967BD35" + }, + "S3ObjectKey": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "DeployAppCustomResourceDEE6DDD6", + "SourceObjectKeys" + ] + } + ] + } + }, + "Name": "Source", + "OutputArtifacts": [ + { + "Name": "SourceArtifact" + } + ], + "RoleArn": { + "Fn::GetAtt": [ + "PipelineSourceCodePipelineActionRoleC6F9E7F5", + "Arn" + ] + }, + "RunOrder": 1 + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Deploy", + "Owner": "AWS", + "Provider": "ElasticBeanstalk", + "Version": "1" + }, + "Configuration": { + "ApplicationName": "codepipeline-test-app", + "EnvironmentName": "codepipeline-test-env" + }, + "InputArtifacts": [ + { + "Name": "SourceArtifact" + } + ], + "Name": "Deploy", + "RoleArn": { + "Fn::GetAtt": [ + "PipelineDeployCodePipelineActionRole8B83082E", + "Arn" + ] + }, + "RunOrder": 1 + } + ], + "Name": "Deploy" + } + ], + "ArtifactStore": { + "Location": { + "Ref": "PipelineBucketB967BD35" + }, + "Type": "S3" + } + }, + "DependsOn": [ + "PipelineRoleDefaultPolicyC7A05455", + "PipelineRoleD68726F7" + ] + }, + "PipelineSourceCodePipelineActionRoleC6F9E7F5": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineSourceCodePipelineActionRoleDefaultPolicy2D565925": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/", + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "DeployAppCustomResourceDEE6DDD6", + "SourceObjectKeys" + ] + } + ] + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineSourceCodePipelineActionRoleDefaultPolicy2D565925", + "Roles": [ + { + "Ref": "PipelineSourceCodePipelineActionRoleC6F9E7F5" + } + ] + } + }, + "PipelineDeployCodePipelineActionRole8B83082E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/AdministratorAccess-AWSElasticBeanstalk" + ] + } + }, + "PipelineDeployCodePipelineActionRoleDefaultPolicyEE6D615B": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineDeployCodePipelineActionRoleDefaultPolicyEE6D615B", + "Roles": [ + { + "Ref": "PipelineDeployCodePipelineActionRole8B83082E" + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets.json new file mode 100644 index 0000000000000..9ace40765b682 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.template.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/integ.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/integ.json new file mode 100644 index 0000000000000..f6b5be49154e4 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "21.0.0", + "testCases": { + "codepipeline-elastic-beanstalk-deploy/DefaultTest": { + "stacks": [ + "aws-cdk-codepipeline-elastic-beanstalk-deploy" + ], + "stackUpdateWorkflow": false, + "assertionStack": "codepipeline-elastic-beanstalk-deploy/DefaultTest/DeployAssert", + "assertionStackName": "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..7f3de22166c07 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/manifest.json @@ -0,0 +1,237 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-codepipeline-elastic-beanstalk-deploy.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-codepipeline-elastic-beanstalk-deploy.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-codepipeline-elastic-beanstalk-deploy": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-codepipeline-elastic-beanstalk-deploy.template.json", + "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}/41fa0558ddcbfbd77d585fbccca6c3d2435c64c4949b651ff2c2e22ca3c5690e.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-codepipeline-elastic-beanstalk-deploy.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-codepipeline-elastic-beanstalk-deploy.assets" + ], + "metadata": { + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBucketB967BD35" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBucketPolicyD65CDEF5" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/AutoDeleteObjectsCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBucketAutoDeleteObjectsCustomResource5F37E165" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DeployAppAwsCliLayerAEF99B2F" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/CustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "DeployAppCustomResourceDEE6DDD6" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/service-role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "servicerole2C3CD20E" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/instance-profile-role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "instanceprofilerole786BCBC7" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/instance-profile": [ + { + "type": "aws:cdk:logicalId", + "data": "instanceprofile" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/beastalk-app": [ + { + "type": "aws:cdk:logicalId", + "data": "beastalkapp" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/beanstlk-env": [ + { + "type": "aws:cdk:logicalId", + "data": "beanstlkenv" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineRoleD68726F7" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineRoleDefaultPolicyC7A05455" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineC660917D" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineSourceCodePipelineActionRoleC6F9E7F5" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineSourceCodePipelineActionRoleDefaultPolicy2D565925" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineDeployCodePipelineActionRole8B83082E" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineDeployCodePipelineActionRoleDefaultPolicyEE6D615B" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-codepipeline-elastic-beanstalk-deploy/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-codepipeline-elastic-beanstalk-deploy" + }, + "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.template.json", + "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": [ + "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.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": [ + "codepipelineelasticbeanstalkdeployDefaultTestDeployAssert785E452B.assets" + ], + "metadata": { + "/codepipeline-elastic-beanstalk-deploy/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/codepipeline-elastic-beanstalk-deploy/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "codepipeline-elastic-beanstalk-deploy/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/tree.json b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/tree.json new file mode 100644 index 0000000000000..634f9bcc6feab --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/pipeilne-elastic-beanstalk-deploy.integ.snapshot/tree.json @@ -0,0 +1,1289 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + }, + "aws-cdk-codepipeline-elastic-beanstalk-deploy": { + "id": "aws-cdk-codepipeline-elastic-beanstalk-deploy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy", + "children": { + "PipelineBucket": { + "id": "PipelineBucket", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "aws-cdk:auto-delete-objects", + "value": "true" + }, + { + "key": "aws-cdk:cr-owned:46838d62", + "value": "true" + } + ], + "versioningConfiguration": { + "status": "Enabled" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "PipelineBucketB967BD35" + }, + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketPolicy", + "version": "0.0.0" + } + }, + "AutoDeleteObjectsCustomResource": { + "id": "AutoDeleteObjectsCustomResource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/AutoDeleteObjectsCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/PipelineBucket/AutoDeleteObjectsCustomResource/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.Bucket", + "version": "0.0.0" + } + }, + "Custom::S3AutoDeleteObjectsCustomResourceProvider": { + "id": "Custom::S3AutoDeleteObjectsCustomResourceProvider", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResourceProvider", + "version": "0.0.0" + } + }, + "DeployApp": { + "id": "DeployApp", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp", + "children": { + "AwsCliLayer": { + "id": "AwsCliLayer", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer", + "children": { + "Code": { + "id": "Code", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/AwsCliLayer/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::LayerVersion", + "aws:cdk:cloudformation:props": { + "content": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip" + }, + "description": "/opt/awscli/aws" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnLayerVersion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/lambda-layer-awscli.AwsCliLayer", + "version": "0.0.0" + } + }, + "CustomResourceHandler": { + "id": "CustomResourceHandler", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/CustomResourceHandler", + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.SingletonFunction", + "version": "0.0.0" + } + }, + "Asset1": { + "id": "Asset1", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/Asset1", + "children": { + "Stage": { + "id": "Stage", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/Asset1/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/Asset1/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "CustomResource": { + "id": "CustomResource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/CustomResource", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/DeployApp/CustomResource/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-deployment.BucketDeployment", + "version": "0.0.0" + } + }, + "Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C": { + "id": "Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "roles": [ + { + "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "6ddcf10002539818a9256eff3fb2b22aa09298d8f946e26ba121c175a600c44e.zip" + }, + "role": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", + "Arn" + ] + }, + "handler": "index.handler", + "layers": [ + { + "Ref": "DeployAppAwsCliLayerAEF99B2F" + } + ], + "runtime": "python3.9", + "timeout": 900 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "service-role": { + "id": "service-role", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/service-role", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/service-role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "elasticbeanstalk.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy" + ], + "roleName": "codepipeline-elasticbeanstalk-action-test-serivce-role" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "instance-profile-role": { + "id": "instance-profile-role", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/instance-profile-role", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/instance-profile-role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker", + "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier" + ], + "roleName": "codepipeline-elasticbeanstalk-action-test-instance-profile-role" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "instance-profile": { + "id": "instance-profile", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/instance-profile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "instanceprofilerole786BCBC7" + } + ], + "instanceProfileName": { + "Ref": "instanceprofilerole786BCBC7" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "beastalk-app": { + "id": "beastalk-app", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/beastalk-app", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticBeanstalk::Application", + "aws:cdk:cloudformation:props": { + "applicationName": "codepipeline-test-app" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticbeanstalk.CfnApplication", + "version": "0.0.0" + } + }, + "beanstlk-env": { + "id": "beanstlk-env", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/beanstlk-env", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticBeanstalk::Environment", + "aws:cdk:cloudformation:props": { + "applicationName": "codepipeline-test-app", + "environmentName": "codepipeline-test-env", + "optionSettings": [ + { + "namespace": "aws:autoscaling:launchconfiguration", + "optionName": "IamInstanceProfile", + "value": { + "Ref": "instanceprofilerole786BCBC7" + } + }, + { + "namespace": "aws:elasticbeanstalk:environment", + "optionName": "ServiceRole", + "value": { + "Ref": "servicerole2C3CD20E" + } + }, + { + "namespace": "aws:elasticbeanstalk:environment", + "optionName": "LoadBalancerType", + "value": "application" + }, + { + "namespace": "aws:elasticbeanstalk:managedactions", + "optionName": "ServiceRoleForManagedUpdates", + "value": "AWSServiceRoleForElasticBeanstalkManagedUpdates" + } + ], + "solutionStackName": "64bit Amazon Linux 2 v5.5.6 running Node.js 16" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticbeanstalk.CfnEnvironment", + "version": "0.0.0" + } + }, + "Pipeline": { + "id": "Pipeline", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline", + "children": { + "Role": { + "id": "Role", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineDeployCodePipelineActionRole8B83082E", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "PipelineSourceCodePipelineActionRoleC6F9E7F5", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineRoleDefaultPolicyC7A05455", + "roles": [ + { + "Ref": "PipelineRoleD68726F7" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodePipeline::Pipeline", + "aws:cdk:cloudformation:props": { + "roleArn": { + "Fn::GetAtt": [ + "PipelineRoleD68726F7", + "Arn" + ] + }, + "stages": [ + { + "name": "Source", + "actions": [ + { + "name": "Source", + "outputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "actionTypeId": { + "category": "Source", + "version": "1", + "owner": "AWS", + "provider": "S3" + }, + "configuration": { + "S3Bucket": { + "Ref": "PipelineBucketB967BD35" + }, + "S3ObjectKey": { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "DeployAppCustomResourceDEE6DDD6", + "SourceObjectKeys" + ] + } + ] + } + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "PipelineSourceCodePipelineActionRoleC6F9E7F5", + "Arn" + ] + } + } + ] + }, + { + "name": "Deploy", + "actions": [ + { + "name": "Deploy", + "inputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "actionTypeId": { + "category": "Deploy", + "version": "1", + "owner": "AWS", + "provider": "ElasticBeanstalk" + }, + "configuration": { + "ApplicationName": "codepipeline-test-app", + "EnvironmentName": "codepipeline-test-env" + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "PipelineDeployCodePipelineActionRole8B83082E", + "Arn" + ] + } + } + ] + } + ], + "artifactStore": { + "type": "S3", + "location": { + "Ref": "PipelineBucketB967BD35" + } + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codepipeline.CfnPipeline", + "version": "0.0.0" + } + }, + "Source": { + "id": "Source", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source", + "children": { + "Source": { + "id": "Source", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/", + { + "Fn::Select": [ + 0, + { + "Fn::GetAtt": [ + "DeployAppCustomResourceDEE6DDD6", + "SourceObjectKeys" + ] + } + ] + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineSourceCodePipelineActionRoleDefaultPolicy2D565925", + "roles": [ + { + "Ref": "PipelineSourceCodePipelineActionRoleC6F9E7F5" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + }, + "Deploy": { + "id": "Deploy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy", + "children": { + "Deploy": { + "id": "Deploy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy", + "children": { + "CodePipelineActionRole": { + "id": "CodePipelineActionRole", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + "arn:aws:iam::aws:policy/AdministratorAccess-AWSElasticBeanstalk" + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-codepipeline-elastic-beanstalk-deploy/Pipeline/Deploy/Deploy/CodePipelineActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "PipelineBucketB967BD35", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineDeployCodePipelineActionRoleDefaultPolicyEE6D615B", + "roles": [ + { + "Ref": "PipelineDeployCodePipelineActionRole8B83082E" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-codepipeline.Pipeline", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "codepipeline-elastic-beanstalk-deploy": { + "id": "codepipeline-elastic-beanstalk-deploy", + "path": "codepipeline-elastic-beanstalk-deploy", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "codepipeline-elastic-beanstalk-deploy/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "codepipeline-elastic-beanstalk-deploy/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "codepipeline-elastic-beanstalk-deploy/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-connectcampaigns/.eslintrc.js b/packages/@aws-cdk/aws-connectcampaigns/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-connectcampaigns/.gitignore b/packages/@aws-cdk/aws-connectcampaigns/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-connectcampaigns/.npmignore b/packages/@aws-cdk/aws-connectcampaigns/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-connectcampaigns/LICENSE b/packages/@aws-cdk/aws-connectcampaigns/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-connectcampaigns/NOTICE b/packages/@aws-cdk/aws-connectcampaigns/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-connectcampaigns/README.md b/packages/@aws-cdk/aws-connectcampaigns/README.md new file mode 100644 index 0000000000000..9907005b69233 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/README.md @@ -0,0 +1,39 @@ +# AWS::ConnectCampaigns 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 connectcampaigns from '@aws-cdk/aws-connectcampaigns'; +``` + + + +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 ConnectCampaigns construct libraries](https://constructs.dev/search?q=connectcampaigns) +- 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::ConnectCampaigns resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_ConnectCampaigns.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::ConnectCampaigns](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_ConnectCampaigns.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/aws-connectcampaigns/jest.config.js b/packages/@aws-cdk/aws-connectcampaigns/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-connectcampaigns/lib/index.ts b/packages/@aws-cdk/aws-connectcampaigns/lib/index.ts new file mode 100644 index 0000000000000..499bff43d3f05 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::ConnectCampaigns CloudFormation Resources: +export * from './connectcampaigns.generated'; diff --git a/packages/@aws-cdk/aws-connectcampaigns/package.json b/packages/@aws-cdk/aws-connectcampaigns/package.json new file mode 100644 index 0000000000000..d44f1f3ecf094 --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/package.json @@ -0,0 +1,113 @@ +{ + "name": "@aws-cdk/aws-connectcampaigns", + "version": "0.0.0", + "description": "AWS::ConnectCampaigns Construct Library", + "private": true, + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.ConnectCampaigns", + "packageId": "Amazon.CDK.AWS.ConnectCampaigns", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.connectcampaigns", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "connectcampaigns" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ], + "distName": "aws-cdk.aws-connectcampaigns", + "module": "aws_cdk.aws_connectcampaigns" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-connectcampaigns" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::ConnectCampaigns", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::ConnectCampaigns", + "aws-connectcampaigns" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.5.2" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-connectcampaigns/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-connectcampaigns/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-connectcampaigns/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts b/packages/@aws-cdk/aws-connectcampaigns/test/connectcampaigns.test.ts similarity index 100% rename from packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts rename to packages/@aws-cdk/aws-connectcampaigns/test/connectcampaigns.test.ts diff --git a/packages/@aws-cdk/aws-ec2/lib/security-group.ts b/packages/@aws-cdk/aws-ec2/lib/security-group.ts index c2ce04b51bb13..c5c0ad3753df1 100644 --- a/packages/@aws-cdk/aws-ec2/lib/security-group.ts +++ b/packages/@aws-cdk/aws-ec2/lib/security-group.ts @@ -63,6 +63,7 @@ abstract class SecurityGroupBase extends Resource implements ISecurityGroup { public abstract readonly securityGroupId: string; public abstract readonly allowAllOutbound: boolean; + public abstract readonly allowAllIpv6Outbound: boolean; public readonly canInlineRule = false; public readonly connections: Connections = new Connections({ securityGroups: [this] }); @@ -237,10 +238,25 @@ export interface SecurityGroupProps { * outbound traffic. If this is set to false, no outbound traffic will be allowed by * default and all egress traffic must be explicitly authorized. * + * To allow all ipv6 traffic use allowAllIpv6Outbound + * * @default true */ readonly allowAllOutbound?: boolean; + /** + * Whether to allow all outbound ipv6 traffic by default. + * + * If this is set to true, there will only be a single egress rule which allows all + * outbound ipv6 traffic. If this is set to false, no outbound traffic will be allowed by + * default and all egress ipv6 traffic must be explicitly authorized. + * + * To allow all ipv4 traffic use allowAllOutbound + * + * @default false + */ + readonly allowAllIpv6Outbound?: boolean; + /** * Whether to disable inline ingress and egress rule optimization. * @@ -274,6 +290,17 @@ export interface SecurityGroupImportOptions { */ readonly allowAllOutbound?: boolean; + /** + * Mark the SecurityGroup as having been created allowing all outbound ipv6 traffic + * + * Only if this is set to false will egress rules for ipv6 be added to this security + * group. Be aware, this would undo any potential "all outbound traffic" + * default. + * + * @default false + */ + readonly allowAllIpv6Outbound?: boolean; + /** * If a SecurityGroup is mutable CDK can add rules to existing groups * @@ -360,6 +387,7 @@ export class SecurityGroup extends SecurityGroupBase { class MutableImport extends SecurityGroupBase { public securityGroupId = securityGroupId; public allowAllOutbound = options.allowAllOutbound ?? true; + public allowAllIpv6Outbound = options.allowAllIpv6Outbound ?? false; public addEgressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean) { // Only if allowAllOutbound has been disabled @@ -372,6 +400,7 @@ export class SecurityGroup extends SecurityGroupBase { class ImmutableImport extends SecurityGroupBase { public securityGroupId = securityGroupId; public allowAllOutbound = options.allowAllOutbound ?? true; + public allowAllIpv6Outbound = options.allowAllIpv6Outbound ?? false; public addEgressRule(_peer: IPeer, _connection: Port, _description?: string, _remoteRule?: boolean) { // do nothing @@ -441,6 +470,11 @@ export class SecurityGroup extends SecurityGroupBase { */ public readonly allowAllOutbound: boolean; + /** + * Whether the SecurityGroup has been configured to allow all outbound ipv6 traffic + */ + public readonly allowAllIpv6Outbound: boolean; + private readonly securityGroup: CfnSecurityGroup; private readonly directIngressRules: CfnSecurityGroup.IngressProperty[] = []; private readonly directEgressRules: CfnSecurityGroup.EgressProperty[] = []; @@ -458,6 +492,7 @@ export class SecurityGroup extends SecurityGroupBase { const groupDescription = props.description || this.node.path; this.allowAllOutbound = props.allowAllOutbound !== false; + this.allowAllIpv6Outbound = props.allowAllIpv6Outbound ?? false; this.disableInlineRules = props.disableInlineRules !== undefined ? !!props.disableInlineRules : @@ -476,6 +511,7 @@ export class SecurityGroup extends SecurityGroupBase { this.securityGroupName = this.securityGroup.ref; this.addDefaultEgressRule(); + this.addDefaultIpv6EgressRule(); } public addIngressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean) { @@ -496,7 +532,9 @@ export class SecurityGroup extends SecurityGroupBase { } public addEgressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean) { - if (this.allowAllOutbound) { + const isIpv6 = peer.toEgressRuleConfig().hasOwnProperty('cidrIpv6'); + + if (!isIpv6 && this.allowAllOutbound) { // In the case of "allowAllOutbound", we don't add any more rules. There // is only one rule which allows all traffic and that subsumes any other // rule. @@ -504,13 +542,23 @@ export class SecurityGroup extends SecurityGroupBase { Annotations.of(this).addWarning('Ignoring Egress rule since \'allowAllOutbound\' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup'); } return; - } else { + } else if (!isIpv6 && !this.allowAllOutbound) { // Otherwise, if the bogus rule exists we can now remove it because the // presence of any other rule will get rid of EC2's implicit "all // outbound" rule anyway. this.removeNoTrafficRule(); } + if (isIpv6 && this.allowAllIpv6Outbound) { + // In the case of "allowAllIpv6Outbound", we don't add any more rules. There + // is only one rule which allows all traffic and that subsumes any other + // rule. + if (!remoteRule) { // Warn only if addEgressRule() was explicitely called + Annotations.of(this).addWarning('Ignoring Egress rule since \'allowAllIpv6Outbound\' is set to true; To add customized rules, set allowAllIpv6Outbound=false on the SecurityGroup'); + } + return; + } + if (!peer.canInlineRule || !connection.canInlineRule || this.disableInlineRules) { super.addEgressRule(peer, connection, description, remoteRule); return; @@ -532,7 +580,7 @@ export class SecurityGroup extends SecurityGroupBase { // to "allOutbound=true" mode, because we might have already emitted // EgressRule objects (which count as rules added later) and there's no way // to recall those. Better to prevent this for now. - throw new Error('Cannot add an "all traffic" egress rule in this way; set allowAllOutbound=true on the SecurityGroup instead.'); + throw new Error('Cannot add an "all traffic" egress rule in this way; set allowAllOutbound=true (for ipv6) or allowAllIpv6Outbound=true (for ipv6) on the SecurityGroup instead.'); } this.addDirectEgressRule(rule); @@ -596,6 +644,31 @@ export class SecurityGroup extends SecurityGroupBase { } } + /** + * Add a allow all ipv6 egress rule to the securityGroup + * + * This depends on allowAllIpv6Outbound: + * + * - If allowAllIpv6Outbound is true, we will add an allow all rule. + * - If allowAllOutbound is false, we don't do anything since EC2 does not add + * a default allow all ipv6 rule. + */ + private addDefaultIpv6EgressRule() { + const description = 'Allow all outbound ipv6 traffic by default'; + const peer = Peer.anyIpv6(); + if (this.allowAllIpv6Outbound) { + if (this.disableInlineRules) { + super.addEgressRule(peer, Port.allTraffic(), description, false); + } else { + this.directEgressRules.push({ + ipProtocol: '-1', + cidrIp: peer.uniqueId, + description, + }); + } + } + } + /** * Remove the bogus rule if it exists */ @@ -721,7 +794,7 @@ function egressRulesEqual(a: CfnSecurityGroup.EgressProperty, b: CfnSecurityGrou * Whether this rule refers to all traffic */ function isAllTrafficRule(rule: any) { - return rule.cidrIp === '0.0.0.0/0' && rule.ipProtocol === '-1'; + return (rule.cidrIp === '0.0.0.0/0' || rule.cidrIpv6 === '::/0') && rule.ipProtocol === '-1'; } /** diff --git a/packages/@aws-cdk/aws-ec2/test/security-group.test.ts b/packages/@aws-cdk/aws-ec2/test/security-group.test.ts index 4624d2a648b72..bee7ec9cceede 100644 --- a/packages/@aws-cdk/aws-ec2/test/security-group.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/security-group.test.ts @@ -24,7 +24,59 @@ describe('security group', () => { }, ], }); + }); + + test('security group can allows all ipv6 outbound traffic by default', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VPC'); + + // WHEN + new SecurityGroup(stack, 'SG1', { vpc, allowAllIpv6Outbound: true }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { + SecurityGroupEgress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'Allow all outbound traffic by default', + IpProtocol: '-1', + }, + { + CidrIp: '::/0', + Description: 'Allow all outbound ipv6 traffic by default', + IpProtocol: '-1', + }, + ], + }); + }); + + test('can add ipv6 rules even if allowAllOutbound=true', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VPC'); + // WHEN + const sg = new SecurityGroup(stack, 'SG1', { vpc }); + sg.addEgressRule(Peer.ipv6('2001:db8::/128'), Port.tcp(80)); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { + SecurityGroupEgress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'Allow all outbound traffic by default', + IpProtocol: '-1', + }, + { + CidrIpv6: '2001:db8::/128', + Description: 'from 2001:db8::/128:80', + FromPort: 80, + ToPort: 80, + IpProtocol: 'tcp', + }, + ], + }); }); @@ -96,8 +148,6 @@ describe('security group', () => { }, ], }); - - }); test('all outbound rule cannot be added after creation', () => { @@ -110,8 +160,18 @@ describe('security group', () => { expect(() => { sg.addEgressRule(Peer.anyIpv4(), Port.allTraffic(), 'All traffic'); }).toThrow(/Cannot add/); + }); + test('all ipv6 outbound rule cannot be added after creation', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VPC'); + // WHEN + const sg = new SecurityGroup(stack, 'SG1', { vpc, allowAllOutbound: false }); + expect(() => { + sg.addEgressRule(Peer.anyIpv6(), Port.allTraffic(), 'All traffic'); + }).toThrow(/Cannot add/); }); test('immutable imports do not add rules', () => { @@ -171,7 +231,7 @@ describe('security group', () => { // GIVEN const stack = new Stack(undefined, 'TestStack', { env: { account: '12345678', region: 'dummy' } }); const vpc = new Vpc(stack, 'VPC'); - const sg = new SecurityGroup(stack, 'SG', { vpc }); + const sg = new SecurityGroup(stack, 'SG', { vpc, allowAllIpv6Outbound: true }); const peers = [ new SecurityGroup(stack, 'PeerGroup', { vpc }), diff --git a/packages/@aws-cdk/aws-ecr-assets/test/custom-synthesis.test.ts b/packages/@aws-cdk/aws-ecr-assets/test/custom-synthesis.test.ts new file mode 100644 index 0000000000000..40c886682dc0d --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/custom-synthesis.test.ts @@ -0,0 +1,94 @@ +/** + * This file asserts that it is possible to write a custom stacksynthesizer that will synthesize + * ONE thing to the asset manifest, while returning another thing (including tokens) to the + * CloudFormation template -- without reaching into the library internals + */ + +import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; +import { StackSynthesizer, FileAssetSource, FileAssetLocation, DockerImageAssetSource, DockerImageAssetLocation, ISynthesisSession, App, Stack, AssetManifestBuilder, CfnParameter, CfnResource } from '@aws-cdk/core'; +import { AssetManifestArtifact } from '@aws-cdk/cx-api'; +import { DockerImageAsset } from '../lib'; + +test('use custom synthesizer', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'Stack', { + synthesizer: new CustomSynthesizer(), + }); + + // WHEN + const asset = new DockerImageAsset(stack, 'MyAsset', { + directory: path.join(__dirname, 'demo-image'), + }); + new CfnResource(stack, 'TestResource', { + type: 'CDK::TestResource', + properties: { + ImageUri: asset.imageUri, + ImageTag: asset.imageTag, + }, + }); + + // THEN + const assembly = app.synth(); + const stackArtifact = assembly.getStackArtifact(stack.artifactId); + const assetArtifact = stackArtifact.dependencies[0] as AssetManifestArtifact; + + const stackTemplate = Template.fromJSON(stackArtifact.template); + stackTemplate.hasResourceProperties('CDK::TestResource', { + ImageUri: { 'Fn::Sub': '${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/${RepositoryName}:0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14' }, + ImageTag: '0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14', + }); + + expect(assetArtifact.contents).toEqual(expect.objectContaining({ + dockerImages: expect.objectContaining({ + '0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14': { + destinations: { + 'current_account-current_region': { + repositoryName: 'write-repo', + imageTag: '0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14', + }, + }, + source: { + directory: 'asset.0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14', + }, + }, + }), + })); +}); + +class CustomSynthesizer extends StackSynthesizer { + private readonly manifest = new AssetManifestBuilder(); + private parameter?: CfnParameter; + + bind(stack: Stack) { + super.bind(stack); + + this.parameter = new CfnParameter(stack, 'RepositoryName'); + } + + addFileAsset(asset: FileAssetSource): FileAssetLocation { + void(asset); + throw new Error('file assets not supported here'); + } + + addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { + const dest = this.manifest.defaultAddDockerImageAsset(this.boundStack, asset, { + repositoryName: 'write-repo', + }); + return this.cloudFormationLocationFromDockerImageAsset({ + ...dest, + repositoryName: ['${', this.parameter!.logicalId, '}'].join(''), + }); + } + + synthesize(session: ISynthesisSession): void { + // NOTE: Explicitly not adding template to asset manifest + this.synthesizeTemplate(session); + const assetManifestId = this.manifest.emitManifest(this.boundStack, session); + + this.emitArtifact(session, { + additionalDependencies: [assetManifestId], + }); + } +} diff --git a/packages/@aws-cdk/aws-events-targets/test/codebuild/project-events.integ.snapshot/aws-cdk-codebuild-events.template.json b/packages/@aws-cdk/aws-events-targets/test/codebuild/project-events.integ.snapshot/aws-cdk-codebuild-events.template.json index 54a4e956859bc..4d8c799d34fb8 100644 --- a/packages/@aws-cdk/aws-events-targets/test/codebuild/project-events.integ.snapshot/aws-cdk-codebuild-events.template.json +++ b/packages/@aws-cdk/aws-events-targets/test/codebuild/project-events.integ.snapshot/aws-cdk-codebuild-events.template.json @@ -396,6 +396,7 @@ }, "MyQueueawscdkcodebuildeventsMyTopic550011DCF72DE3ED": { "Type": "AWS::SNS::Subscription", + "DependsOn": "MyQueuePolicy6BBEDDAC", "Properties": { "Protocol": "sqs", "TopicArn": { diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.assets.json b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.assets.json index 1b3718f1a4912..ec3e525fe1cf8 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.assets.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.assets.json @@ -1,20 +1,20 @@ { "version": "21.0.0", "files": { - "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7": { + "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb": { "source": { - "path": "asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle", + "path": "asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip", + "objectKey": "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e0e91fa96756b94719efc2b0e2ea19fcd9c842b56f185f07700616554fcd0eb7": { + "68c9fd01db97c536686e52c360f3ffd305a7e923768b7a0cac2f9e3ba23198e3": { "source": { "path": "LogGroupDefaultTestDeployAssert353EE07A.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e0e91fa96756b94719efc2b0e2ea19fcd9c842b56f185f07700616554fcd0eb7.json", + "objectKey": "68c9fd01db97c536686e52c360f3ffd305a7e923768b7a0cac2f9e3ba23198e3.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.template.json b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.template.json index a50165fcc794a..d9784190797b1 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.template.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/LogGroupDefaultTestDeployAssert353EE07A.template.json @@ -14,14 +14,14 @@ "parameters": { "Entries": [ { - "Detail": "{\"date\":\"abc1661947671805\"}", + "Detail": "{\"date\":\"abc1663960602347\"}", "DetailType": "cdk-integ-custom-rule", "Source": "cdk-integ" } ] }, "flattenResponse": "false", - "salt": "1661947671807" + "salt": "1663960602348" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -93,7 +93,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.zip" + "S3Key": "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.zip" }, "Timeout": 120, "Handler": "index.handler", @@ -116,39 +116,17 @@ }, "service": "CloudWatchLogs", "api": "filterLogEvents", + "expected": "{\"$StringLike\":\"abc1663960602347\"}", + "actualPath": "events.0.message", "parameters": { "logGroupName": { "Fn::ImportValue": "log-group-events:ExportsOutputRefloggroup2F19C5C9B4F4C6918" }, - "startTime": "1661947671805", + "startTime": "1663960602347", "limit": 1 }, "flattenResponse": "true", - "salt": "1661947671807" - }, - "DependsOn": [ - "AwsApiCallEventBridgeputEvents" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "AwsApiCallCloudWatchLogsfilterLogEventsAssertEqualsCloudWatchLogsfilterLogEvents148E959E": { - "Type": "Custom::DeployAssert@AssertEquals", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", - "Arn" - ] - }, - "actual": { - "Fn::GetAtt": [ - "AwsApiCallCloudWatchLogsfilterLogEvents", - "apiCallResponse.events.0.message" - ] - }, - "expected": "{\"$StringLike\":\"abc1661947671805\"}", - "salt": "1661947671808" + "salt": "1663960602348" }, "DependsOn": [ "AwsApiCallEventBridgeputEvents" @@ -158,11 +136,11 @@ } }, "Outputs": { - "AssertionResultsAssertEqualsCloudWatchLogsfilterLogEvents": { + "AssertionResultsAwsApiCallCloudWatchLogsfilterLogEvents": { "Value": { "Fn::GetAtt": [ - "AwsApiCallCloudWatchLogsfilterLogEventsAssertEqualsCloudWatchLogsfilterLogEvents148E959E", - "data" + "AwsApiCallCloudWatchLogsfilterLogEvents", + "assertion" ] } } diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js similarity index 88% rename from packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js rename to packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js index ba956d47f51fe..a9e7e7241efc7 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js @@ -404,20 +404,11 @@ var CustomResourceHandler = class { } async handle() { try { - console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); const response = await this.processEvent(this.event.ResourceProperties); - console.log(`Event output : ${JSON.stringify(response)}`); - await this.respond({ - status: "SUCCESS", - reason: "OK", - data: response - }); + return response; } catch (e) { console.log(e); - await this.respond({ - status: "FAILED", - reason: e.message ?? "Internal Error" - }); + throw e; } finally { clearTimeout(this.timeout); } @@ -479,7 +470,8 @@ var AssertionHandler = class extends CustomResourceHandler { matchResult.finished(); if (matchResult.hasFailed()) { result = { - data: JSON.stringify({ + failed: true, + assertion: JSON.stringify({ status: "fail", message: [ ...matchResult.toHumanStrings(), @@ -488,11 +480,11 @@ var AssertionHandler = class extends CustomResourceHandler { }) }; if (request2.failDeployment) { - throw new Error(result.data); + throw new Error(result.assertion); } } else { result = { - data: JSON.stringify({ + assertion: JSON.stringify({ status: "success" }) }; @@ -562,7 +554,10 @@ function flatten(object) { {}, ...function _flatten(child, path = []) { return [].concat(...Object.keys(child).map((key) => { - const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + let childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + if (typeof childKey === "string") { + childKey = isJsonString(childKey); + } return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; })); }(object) @@ -572,6 +567,9 @@ var AwsApiCallHandler = class extends CustomResourceHandler { async processEvent(request2) { const AWS = require("aws-sdk"); console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + if (!Object.prototype.hasOwnProperty.call(AWS, request2.service)) { + throw Error(`Service ${request2.service} does not exist in AWS SDK version ${AWS.VERSION}.`); + } const service = new AWS[request2.service](); const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); console.log(`SDK response received ${JSON.stringify(response)}`); @@ -582,9 +580,18 @@ var AwsApiCallHandler = class extends CustomResourceHandler { const flatData = { ...flatten(respond) }; - return request2.flattenResponse === "true" ? flatData : respond; + const resp = request2.flattenResponse === "true" ? flatData : respond; + console.log(`Returning result ${JSON.stringify(resp)}`); + return resp; } }; +function isJsonString(value) { + try { + return JSON.parse(value); + } catch { + return value; + } +} // lib/assertions/providers/lambda-handler/types.ts var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; @@ -592,18 +599,68 @@ var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; // lib/assertions/providers/lambda-handler/index.ts async function handler(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); const provider = createResourceHandler(event, context); - await provider.handle(); + try { + if (event.RequestType === "Delete") { + await provider.respond({ + status: "SUCCESS", + reason: "OK" + }); + return; + } + const result = await provider.handle(); + const actualPath = event.ResourceProperties.actualPath; + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + if ("expected" in event.ResourceProperties) { + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + try { + const assertionResult = await assertion.handle(); + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: { + ...assertionResult, + ...result + } + }); + return; + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + return; } function createResourceHandler(event, context) { if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { return new AwsApiCallHandler(event, context); - } - switch (event.ResourceType) { - case ASSERT_RESOURCE_TYPE: - return new AssertionHandler(event, context); - default: - throw new Error(`Unsupported resource type "${event.ResourceType}`); + } else if (event.ResourceType.startsWith(ASSERT_RESOURCE_TYPE)) { + return new AssertionHandler(event, context); + } else { + throw new Error(`Unsupported resource type "${event.ResourceType}`); } } // Annotate the CommonJS export names for ESM import in node: diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/manifest.json index fcee46ad9fd83..a149563bbc6a4 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/manifest.json @@ -166,7 +166,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e0e91fa96756b94719efc2b0e2ea19fcd9c842b56f185f07700616554fcd0eb7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/68c9fd01db97c536686e52c360f3ffd305a7e923768b7a0cac2f9e3ba23198e3.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -207,16 +207,10 @@ "data": "AwsApiCallCloudWatchLogsfilterLogEvents" } ], - "/LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/Default/Default": [ + "/LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertionResults": [ { "type": "aws:cdk:logicalId", - "data": "AwsApiCallCloudWatchLogsfilterLogEventsAssertEqualsCloudWatchLogsfilterLogEvents148E959E" - } - ], - "/LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/AssertionResults": [ - { - "type": "aws:cdk:logicalId", - "data": "AssertionResultsAssertEqualsCloudWatchLogsfilterLogEvents" + "data": "AssertionResultsAwsApiCallCloudWatchLogsfilterLogEvents" } ], "/LogGroup/DefaultTest/DeployAssert/BootstrapVersion": [ diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/tree.json b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/tree.json index dbb926ac7a6a2..1c3937a9c1c29 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } }, "log-group-events": { @@ -663,7 +663,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } } }, @@ -685,7 +685,7 @@ "path": "LogGroup/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } }, "DeployAssert": { @@ -705,7 +705,7 @@ "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallEventBridgeputEvents/SdkProvider/AssertionsProvider", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } } }, @@ -769,7 +769,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } }, "AwsApiCallCloudWatchLogsfilterLogEvents": { @@ -785,7 +785,7 @@ "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/SdkProvider/AssertionsProvider", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.102" } } }, @@ -812,57 +812,11 @@ "version": "0.0.0" } }, - "AssertEqualsCloudWatchLogsfilterLogEvents": { - "id": "AssertEqualsCloudWatchLogsfilterLogEvents", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents", - "children": { - "AssertionProvider": { - "id": "AssertionProvider", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/AssertionProvider", - "children": { - "AssertionsProvider": { - "id": "AssertionsProvider", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/AssertionProvider/AssertionsProvider", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests.AssertionsProvider", - "version": "0.0.0" - } - }, - "Default": { - "id": "Default", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/Default", - "children": { - "Default": { - "id": "Default", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/Default/Default", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnResource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.CustomResource", - "version": "0.0.0" - } - }, - "AssertionResults": { - "id": "AssertionResults", - "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertEqualsCloudWatchLogsfilterLogEvents/AssertionResults", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnOutput", - "version": "0.0.0" - } - } - }, + "AssertionResults": { + "id": "AssertionResults", + "path": "LogGroup/DefaultTest/DeployAssert/AwsApiCallCloudWatchLogsfilterLogEvents/AssertionResults", "constructInfo": { - "fqn": "@aws-cdk/integ-tests.EqualsAssertion", + "fqn": "@aws-cdk/core.CfnOutput", "version": "0.0.0" } } diff --git a/packages/@aws-cdk/aws-events-targets/test/sns/sns-event-rule-target.integ.snapshot/aws-cdk-sns-event-target.template.json b/packages/@aws-cdk/aws-events-targets/test/sns/sns-event-rule-target.integ.snapshot/aws-cdk-sns-event-target.template.json index a667accb07652..cd1aa126d0ea2 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sns/sns-event-rule-target.integ.snapshot/aws-cdk-sns-event-target.template.json +++ b/packages/@aws-cdk/aws-events-targets/test/sns/sns-event-rule-target.integ.snapshot/aws-cdk-sns-event-target.template.json @@ -94,6 +94,7 @@ }, "MyQueueawscdksnseventtargetMyTopicB7575CD87304D383": { "Type": "AWS::SNS::Subscription", + "DependsOn": "MyQueuePolicy6BBEDDAC", "Properties": { "Protocol": "sqs", "TopicArn": { diff --git a/packages/@aws-cdk/aws-gamelift/.gitignore b/packages/@aws-cdk/aws-gamelift/.gitignore index 6d05bba61dfa7..da70d0d9db790 100644 --- a/packages/@aws-cdk/aws-gamelift/.gitignore +++ b/packages/@aws-cdk/aws-gamelift/.gitignore @@ -21,3 +21,7 @@ junit.xml !**/*.integ.snapshot/**/asset.*/*.d.ts !**/*.integ.snapshot/**/asset.*/** + +#include game build js file +!test/my-game-build/*.js +!test/my-game-script/*.js diff --git a/packages/@aws-cdk/aws-gamelift/README.md b/packages/@aws-cdk/aws-gamelift/README.md index 5cc87f2e9eafc..48a572920d223 100644 --- a/packages/@aws-cdk/aws-gamelift/README.md +++ b/packages/@aws-cdk/aws-gamelift/README.md @@ -9,31 +9,103 @@ > > [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + --- -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. +[Amazon GameLift](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-intro.html) is a service used +to deploy, operate, and scale dedicated, low-cost servers in the cloud for session-based multiplayer games. Built +on AWS global computing infrastructure, GameLift helps deliver high-performance, high-reliability game servers +while dynamically scaling your resource usage to meet worldwide player demand. -```ts nofixture -import * as gamelift from '@aws-cdk/aws-gamelift'; -``` +GameLift is composed of three main components: + +* GameLift FlexMatch which is a customizable matchmaking service for +multiplayer games. With FlexMatch, you can +build a custom set of rules that defines what a multiplayer match looks like +for your game, and determines how to +evaluate and select compatible players for each match. You can also customize +key aspects of the matchmaking +process to fit your game, including fine-tuning the matching algorithm. + +* GameLift hosting for custom or realtime servers which helps you deploy, +operate, and scale dedicated game servers. It regulates the resources needed to +host games, finds available game servers to host new game sessions, and puts +players into games. + +* GameLift FleetIQ to optimize the use of low-cost Amazon Elastic Compute Cloud +(Amazon EC2) Spot Instances for cloud-based game hosting. With GameLift +FleetIQ, you can work directly with your hosting resources in Amazon EC2 and +Amazon EC2 Auto Scaling while taking advantage of GameLift optimizations to +deliver inexpensive, resilient game hosting for your players + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define components for your matchmaking +configuration or game server fleet management system. + +## GameLift Hosting + +### Defining a GameLift Fleet + +GameLift helps you deploy, operate, and scale dedicated game servers for +session-based multiplayer games. It helps you regulate the resources needed to +host your games, finds available game servers to host new game sessions, and +puts players into games. - +### Uploading builds and scripts to GameLift -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: +Before deploying your GameLift-enabled multiplayer game servers for hosting with the GameLift service, you need to upload +your game server files. This section provides guidance on preparing and uploading custom game server build +files or Realtime Servers server script files. When you upload files, you create a GameLift build or script resource, which +you then deploy on fleets of hosting resources. -- Search [Construct Hub for GameLift construct libraries](https://constructs.dev/search?q=gamelift) -- 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::GameLift resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_GameLift.html) directly. +To troubleshoot fleet activation problems related to the server script, see [Debug GameLift fleet issues](https://docs.aws.amazon.com/gamelift/latest/developerguide/fleets-creating-debug.html). +#### Upload a custom server build to GameLift - +Before uploading your configured game server to GameLift for hosting, package the game build files into a build directory. +This directory must include all components required to run your game servers and host game sessions, including the following: -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. +* Game server binaries – The binary files required to run the game server. A build can include binaries for multiple game +servers built to run on the same platform. For a list of supported platforms, see [Download Amazon GameLift SDKs](https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-supported.html). -For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::GameLift](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_GameLift.html). +* Dependencies – Any dependent files that your game server executables require to run. Examples include assets, configuration +files, and dependent libraries. -(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.) +* Install script – A script file to handle tasks that are required to fully install your game build on GameLift hosting +servers. Place this file at the root of the build directory. GameLift runs the install script as part of fleet creation. - +You can set up any application in your build, including your install script, to access your resources securely on other AWS +services. + +```ts +declare const bucket: s3.Bucket; +new gamelift.Build(this, 'Build', { + content: gamelift.Content.fromBucket(bucket, "sample-asset-key") +}); +``` + +#### Upload a realtime server Script + +Your server script can include one or more files combined into a single .zip file for uploading. The .zip file must contain +all files that your script needs to run. + +You can store your zipped script files in either a local file directory or in an Amazon Simple Storage Service (Amazon S3) +bucket or defines a directory asset which is archived as a .zip file and uploaded to S3 during deployment. + +After you create the script resource, GameLift deploys the script with a new Realtime Servers fleet. GameLift installs your +server script onto each instance in the fleet, placing the script files in `/local/game`. + +```ts +declare const bucket: s3.Bucket; +new gamelift.Script(this, 'Script', { + content: gamelift.Content.fromBucket(bucket, "sample-asset-key") +}); +``` diff --git a/packages/@aws-cdk/aws-gamelift/lib/build.ts b/packages/@aws-cdk/aws-gamelift/lib/build.ts new file mode 100644 index 0000000000000..a2d4422e47453 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/lib/build.ts @@ -0,0 +1,213 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3_assets from '@aws-cdk/aws-s3-assets'; +import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { Content } from './content'; +import { CfnBuild } from './gamelift.generated'; + +/** + * Your custom-built game server software that runs on GameLift and hosts game sessions for your players. + * A game build represents the set of files that run your game server on a particular operating system. + * You can have many different builds, such as for different flavors of your game. + * The game build must be integrated with the GameLift service. + * You upload game build files to the GameLift service in the Regions where you plan to set up fleets. + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-build-cli-uploading.html + */ +export interface IBuild extends cdk.IResource, iam.IGrantable { + + /** + * The Identifier of the build. + * + * @attribute + */ + readonly buildId: string; +} + +/** + * Base class for new and imported GameLift server build. + */ +export abstract class BuildBase extends cdk.Resource implements IBuild { + /** + * The Identifier of the build. + */ + public abstract readonly buildId: string; + + public abstract readonly grantPrincipal: iam.IPrincipal; +} + +/** + * The operating system that the game server binaries are built to run on. + */ +export enum OperatingSystem { + AMAZON_LINUX = 'AMAZON_LINUX', + AMAZON_LINUX_2 = 'AMAZON_LINUX_2', + WINDOWS_2012 = 'WINDOWS_2012' +} + + +/** + * Represents a Build content defined outside of this stack. + */ +export interface BuildAttributes { + /** + * The identifier of the build + */ + readonly buildId: string; + /** + * The IAM role assumed by GameLift to access server build in S3. + * @default - undefined + */ + readonly role?: iam.IRole; +} + +/** + * Properties for a new build + */ +export interface BuildProps { + /** + * Name of this build + * + * @default No name + */ + readonly buildName?: string; + + /** + * Version of this build + * + * @default No version + */ + readonly buildVersion?: string; + + /** + * The operating system that the game server binaries are built to run on. + * + * @default No version + */ + readonly operatingSystem?: OperatingSystem; + + /** + * The game build file storage + */ + readonly content: Content; + + /** + * The IAM role assumed by GameLift to access server build in S3. + * If providing a custom role, it needs to trust the GameLift service principal (gamelift.amazonaws.com) and be granted sufficient permissions + * to have Read access to a specific key content into a specific S3 bucket. + * Below an example of required permission: + * { + * "Version": "2012-10-17", + * "Statement": [{ + * "Effect": "Allow", + * "Action": [ + * "s3:GetObject", + * "s3:GetObjectVersion" + * ], + * "Resource": "arn:aws:s3:::bucket-name/object-name" + * }] + *} + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-access-storage-loc + * + * @default - a role will be created with default permissions. + */ + readonly role?: iam.IRole; +} + +/** + * A GameLift build, that is installed and runs on instances in an Amazon GameLift fleet. It consists of + * a zip file with all of the components of the game server build. + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-build-cli-uploading.html + * + * @resource AWS::GameLift::Build + */ +export class Build extends BuildBase { + + /** + * Create a new Build from s3 content + */ + static fromBucket(scope: Construct, id: string, bucket: s3.IBucket, key: string, objectVersion?: string) { + return new Build(scope, id, { + content: Content.fromBucket(bucket, key, objectVersion), + }); + } + + /** + * Create a new Build from asset content + */ + static fromAsset(scope: Construct, id: string, path: string, options?: s3_assets.AssetOptions) { + return new Build(scope, id, { + content: Content.fromAsset(path, options), + }); + } + + /** + * Import a build into CDK using its identifier + */ + static fromBuildId(scope: Construct, id: string, buildId: string): IBuild { + return this.fromBuildAttributes(scope, id, { buildId }); + } + + /** + * Import an existing build from its attributes. + */ + static fromBuildAttributes(scope: Construct, id: string, attrs: BuildAttributes): IBuild { + class Import extends BuildBase { + public readonly buildId = attrs.buildId; + public readonly grantPrincipal = attrs.role ?? new iam.UnknownPrincipal({ resource: this }); + } + + return new Import(scope, id); + } + + /** + * The Identifier of the build. + */ + public readonly buildId: string; + + /** + * The IAM role GameLift assumes to acccess server build content. + */ + public readonly role: iam.IRole; + + /** + * The principal this GameLift Build is using. + */ + public readonly grantPrincipal: iam.IPrincipal; + + constructor(scope: Construct, id: string, props: BuildProps) { + super(scope, id, { + physicalName: props.buildName, + }); + + if (props.buildName && !cdk.Token.isUnresolved(props.buildName)) { + if (props.buildName.length > 1024) { + throw new Error(`Build name can not be longer than 1024 characters but has ${props.buildName.length} characters.`); + } + } + this.role = props.role ?? new iam.Role(this, 'ServiceRole', { + assumedBy: new iam.ServicePrincipal('gamelift.amazonaws.com'), + }); + this.grantPrincipal = this.role; + const content = props.content.bind(this, this.role); + + const resource = new CfnBuild(this, 'Resource', { + name: props.buildName, + version: props.buildVersion, + operatingSystem: props.operatingSystem, + storageLocation: { + bucket: content.s3Location && content.s3Location.bucketName, + key: content.s3Location && content.s3Location.objectKey, + objectVersion: content.s3Location && content.s3Location.objectVersion, + roleArn: this.role.roleArn, + }, + }); + + this.buildId = resource.ref; + } + + +} diff --git a/packages/@aws-cdk/aws-gamelift/lib/content.ts b/packages/@aws-cdk/aws-gamelift/lib/content.ts new file mode 100644 index 0000000000000..3c510757b3880 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/lib/content.ts @@ -0,0 +1,110 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3_assets from '@aws-cdk/aws-s3-assets'; +import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; + +/** + * Before deploying your GameLift-enabled multiplayer game servers for hosting with the GameLift service, you need to upload your game server files. + * The class helps you on preparing and uploading custom game server build files or Realtime Servers server script files. + */ +export abstract class Content { + /** + * Game content as an S3 object. + * @param bucket The S3 bucket + * @param key The object key + * @param objectVersion Optional S3 ob ject version + */ + public static fromBucket(bucket: s3.IBucket, key: string, objectVersion?: string): S3Content { + return new S3Content(bucket, key, objectVersion); + } + + + /** + * Loads the game content from a local disk path. + * + * @param path Either a directory with the game content bundle or a .zip file + */ + public static fromAsset(path: string, options?: s3_assets.AssetOptions): AssetContent { + return new AssetContent(path, options); + } + + /** + * Called when the Build is initialized to allow this object to bind + */ + public abstract bind(scope: Construct, grantable: iam.IGrantable): ContentConfig; + +} + +/** + * Result of binding `Content` into a `Build`. + */ +export interface ContentConfig { + /** + * The location of the content in S3. + */ + readonly s3Location: s3.Location; +} + +/** + * Game content from an S3 archive. + */ +export class S3Content extends Content { + + constructor(private readonly bucket: s3.IBucket, private key: string, private objectVersion?: string) { + super(); + if (!bucket.bucketName) { + throw new Error('bucketName is undefined for the provided bucket'); + } + } + + public bind(_scope: Construct, grantable: iam.IGrantable): ContentConfig { + this.bucket.grantRead(grantable, this.key); + return { + s3Location: { + bucketName: this.bucket.bucketName, + objectKey: this.key, + objectVersion: this.objectVersion, + }, + }; + } +} + +/** + * Game content from a local directory. + */ +export class AssetContent extends Content { + private asset?: s3_assets.Asset; + + /** + * @param path The path to the asset file or directory. + */ + constructor(public readonly path: string, private readonly options: s3_assets.AssetOptions = { }) { + super(); + } + + public bind(scope: Construct, grantable: iam.IGrantable): ContentConfig { + // If the same AssetContent is used multiple times, retain only the first instantiation. + if (!this.asset) { + this.asset = new s3_assets.Asset(scope, 'Content', { + path: this.path, + ...this.options, + }); + } else if (cdk.Stack.of(this.asset) !== cdk.Stack.of(scope)) { + throw new Error(`Asset is already associated with another stack '${cdk.Stack.of(this.asset).stackName}'. ` + + 'Create a new Content instance for every stack.'); + } + this.asset.grantRead(grantable); + + if (!this.asset.isZipArchive) { + throw new Error(`Asset must be a .zip file or a directory (${this.path})`); + } + + return { + s3Location: { + bucketName: this.asset.s3BucketName, + objectKey: this.asset.s3ObjectKey, + }, + }; + } +} diff --git a/packages/@aws-cdk/aws-gamelift/lib/index.ts b/packages/@aws-cdk/aws-gamelift/lib/index.ts index 843bf2236645e..13cc0c8eada9c 100644 --- a/packages/@aws-cdk/aws-gamelift/lib/index.ts +++ b/packages/@aws-cdk/aws-gamelift/lib/index.ts @@ -1,2 +1,6 @@ +export * from './content'; +export * from './build'; +export * from './script'; + // AWS::GameLift CloudFormation Resources: export * from './gamelift.generated'; diff --git a/packages/@aws-cdk/aws-gamelift/lib/script.ts b/packages/@aws-cdk/aws-gamelift/lib/script.ts new file mode 100644 index 0000000000000..f387388732486 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/lib/script.ts @@ -0,0 +1,243 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3_assets from '@aws-cdk/aws-s3-assets'; +import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { Content } from './content'; +import { CfnScript } from './gamelift.generated'; + +/** + * Your configuration and custom game logic for use with Realtime Servers. + * Realtime Servers are provided by GameLift to use instead of a custom-built game server. + * You configure Realtime Servers for your game clients by creating a script using JavaScript, + * and add custom game logic as appropriate to host game sessions for your players. + * You upload the Realtime script to the GameLift service in the Regions where you plan to set up fleets. + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/realtime-script-uploading.html + */ +export interface IScript extends cdk.IResource, iam.IGrantable { + + /** + * The Identifier of the realtime server script. + * + * @attribute + */ + readonly scriptId: string; + + /** + * The ARN of the realtime server script. + * + * @attribute + */ + readonly scriptArn: string; +} + +/** + * Base class for new and imported GameLift realtime server script. + */ +export abstract class ScriptBase extends cdk.Resource implements IScript { + /** + * The Identifier of the realtime server script. + */ + public abstract readonly scriptId: string; + public abstract readonly scriptArn: string; + + public abstract readonly grantPrincipal: iam.IPrincipal; +} + +/** + * Represents a Script content defined outside of this stack. + */ +export interface ScriptAttributes { + /** + * The ARN of the realtime server script + */ + readonly scriptArn: string; + /** + * The IAM role assumed by GameLift to access server script in S3. + * @default - undefined + */ + readonly role?: iam.IRole; +} + +/** + * Properties for a new realtime server script + */ +export interface ScriptProps { + /** + * Name of this realtime server script + * + * @default No name + */ + readonly scriptName?: string; + + /** + * Version of this realtime server script + * + * @default No version + */ + readonly scriptVersion?: string; + + /** + * The game content + */ + readonly content: Content; + + /** + * The IAM role assumed by GameLift to access server script in S3. + * If providing a custom role, it needs to trust the GameLift service principal (gamelift.amazonaws.com) and be granted sufficient permissions + * to have Read access to a specific key content into a specific S3 bucket. + * Below an example of required permission: + * { + * "Version": "2012-10-17", + * "Statement": [{ + * "Effect": "Allow", + * "Action": [ + * "s3:GetObject", + * "s3:GetObjectVersion" + * ], + * "Resource": "arn:aws:s3:::bucket-name/object-name" + * }] + *} + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-access-storage-loc + * + * @default - a role will be created with default permissions. + */ + readonly role?: iam.IRole; +} + +/** + * A GameLift script, that is installed and runs on instances in an Amazon GameLift fleet. It consists of + * a zip file with all of the components of the realtime game server script. + * + * @see https://docs.aws.amazon.com/gamelift/latest/developerguide/realtime-script-uploading.html + * + * @resource AWS::GameLift::Script + */ +export class Script extends ScriptBase { + + /** + * Create a new realtime server script from s3 content + */ + static fromBucket(scope: Construct, id: string, bucket: s3.IBucket, key: string, objectVersion?: string) { + return new Script(scope, id, { + content: Content.fromBucket(bucket, key, objectVersion), + }); + } + + /** + * Create a new realtime server script from asset content + */ + static fromAsset(scope: Construct, id: string, path: string, options?: s3_assets.AssetOptions) { + return new Script(scope, id, { + content: Content.fromAsset(path, options), + }); + } + + /** + * Import a script into CDK using its ARN + */ + static fromScriptArn(scope: Construct, id: string, scriptArn: string): IScript { + return this.fromScriptAttributes(scope, id, { scriptArn }); + } + + /** + * Import an existing realtime server script from its attributes. + */ + static fromScriptAttributes(scope: Construct, id: string, attrs: ScriptAttributes): IScript { + const scriptArn = attrs.scriptArn; + const scriptId = extractIdFromArn(attrs.scriptArn); + const role = attrs.role; + + class Import extends ScriptBase { + public readonly scriptArn = scriptArn; + public readonly scriptId = scriptId; + public readonly grantPrincipal:iam.IPrincipal; + public readonly role = role + + constructor(s: Construct, i: string) { + super(s, i, { + environmentFromArn: scriptArn, + }); + + this.grantPrincipal = this.role || new iam.UnknownPrincipal({ resource: this }); + } + } + + return new Import(scope, id); + } + + /** + * The Identifier of the realtime server script. + */ + public readonly scriptId: string; + + /** + * The ARN of the realtime server script. + */ + public readonly scriptArn: string; + + /** + * The IAM role GameLift assumes to acccess server script content. + */ + public readonly role: iam.IRole; + + /** + * The principal this GameLift script is using. + */ + public readonly grantPrincipal: iam.IPrincipal; + + constructor(scope: Construct, id: string, props: ScriptProps) { + super(scope, id, { + physicalName: props.scriptName, + }); + + if (props.scriptName && !cdk.Token.isUnresolved(props.scriptName)) { + if (props.scriptName.length > 1024) { + throw new Error(`Script name can not be longer than 1024 characters but has ${props.scriptName.length} characters.`); + } + } + this.role = props.role ?? new iam.Role(this, 'ServiceRole', { + assumedBy: new iam.ServicePrincipal('gamelift.amazonaws.com'), + }); + this.grantPrincipal = this.role; + const content = props.content.bind(this, this.role); + + const resource = new CfnScript(this, 'Resource', { + name: props.scriptName, + version: props.scriptVersion, + storageLocation: { + bucket: content.s3Location && content.s3Location.bucketName, + key: content.s3Location && content.s3Location.objectKey, + objectVersion: content.s3Location && content.s3Location.objectVersion, + roleArn: this.role.roleArn, + }, + }); + + this.scriptId = this.getResourceNameAttribute(resource.ref); + this.scriptArn = this.getResourceArnAttribute(resource.attrArn, { + service: 'gamelift', + resource: `script/${this.physicalName}`, + arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, + }); + } +} + +/** + * Given an opaque (token) ARN, returns a CloudFormation expression that extracts the script + * identifier from the ARN. + * + * Script ARNs look like this: + * + * arn:aws:gamelift:region:account-id:script/script-identifier + * + * ..which means that in order to extract the `script-identifier` component from the ARN, we can + * split the ARN using ":" and select the component in index 5 then split using "/" and select the component in index 1. + * + * @returns the script identifier from his ARN + */ +function extractIdFromArn(arn: string) { + const splitValue = cdk.Fn.select(5, cdk.Fn.split(':', arn)); + return cdk.Fn.select(1, cdk.Fn.split('/', splitValue)); +} diff --git a/packages/@aws-cdk/aws-gamelift/package.json b/packages/@aws-cdk/aws-gamelift/package.json index 19f96730ef99e..6f133644d1d2b 100644 --- a/packages/@aws-cdk/aws-gamelift/package.json +++ b/packages/@aws-cdk/aws-gamelift/package.json @@ -82,24 +82,54 @@ "devDependencies": { "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.5.2" + "@aws-cdk/cx-api": "0.0.0", + "@types/jest": "^27.5.2", + "jest": "^27.5.1" }, "dependencies": { "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-events": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/aws-s3-assets": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", + "@aws-cdk/region-info": "0.0.0", "constructs": "^10.0.0" }, "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-events": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/aws-s3-assets": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", + "@aws-cdk/region-info": "0.0.0", "constructs": "^10.0.0" }, "engines": { "node": ">= 14.15.0" }, + "awslint": { + "exclude": [ + "docs-public-apis:@aws-cdk/aws-gamelift.OperatingSystem.AMAZON_LINUX", + "docs-public-apis:@aws-cdk/aws-gamelift.OperatingSystem.AMAZON_LINUX_2", + "docs-public-apis:@aws-cdk/aws-gamelift.OperatingSystem.WINDOWS_2012" + ] + }, "stability": "experimental", - "maturity": "cfn-only", + "maturity": "experimental", "awscdkio": { "announce": false }, diff --git a/packages/@aws-cdk/aws-gamelift/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-gamelift/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..4a4c332becb50 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/rosetta/default.ts-fixture @@ -0,0 +1,16 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Duration, Size, Stack } from '@aws-cdk/core'; +import * as gamelift from '@aws-cdk/aws-gamelift'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as kms from '@aws-cdk/aws-kms'; +import * as iam from '@aws-cdk/aws-iam'; +import * as path from 'path'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js new file mode 100644 index 0000000000000..73c02658c48d9 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js @@ -0,0 +1 @@ +console.log('Hello World'); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.assets.json b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.assets.json new file mode 100644 index 0000000000000..d27cd073bc49a --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7": { + "source": { + "path": "asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222": { + "source": { + "path": "aws-gamelift-build.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.template.json b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.template.json new file mode 100644 index 0000000000000..394b49a1b66ff --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/aws-gamelift-build.template.json @@ -0,0 +1,129 @@ +{ + "Resources": { + "BuildServiceRole1F57E904": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "gamelift.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "BuildServiceRoleDefaultPolicyCB7101C6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BuildServiceRoleDefaultPolicyCB7101C6", + "Roles": [ + { + "Ref": "BuildServiceRole1F57E904" + } + ] + } + }, + "Build45A36621": { + "Type": "AWS::GameLift::Build", + "Properties": { + "StorageLocation": { + "Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "Key": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "RoleArn": { + "Fn::GetAtt": [ + "BuildServiceRole1F57E904", + "Arn" + ] + } + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } + } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/integ.json b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/integ.json new file mode 100644 index 0000000000000..f646149706bea --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "version": "21.0.0", + "testCases": { + "integ.build": { + "stacks": [ + "aws-gamelift-build" + ], + "diffAssets": false, + "stackUpdateWorkflow": true + } + }, + "synthContext": {}, + "enableLookups": false +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..43fe5eb776640 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/manifest.json @@ -0,0 +1,64 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-gamelift-build.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-gamelift-build.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-gamelift-build": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-gamelift-build.template.json", + "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}/9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-gamelift-build.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-gamelift-build.assets" + ], + "metadata": { + "/aws-gamelift-build/Build/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildServiceRole1F57E904" + } + ], + "/aws-gamelift-build/Build/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BuildServiceRoleDefaultPolicyCB7101C6" + } + ], + "/aws-gamelift-build/Build/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Build45A36621" + } + ] + }, + "displayName": "aws-gamelift-build" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/tree.json b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/tree.json new file mode 100644 index 0000000000000..96d14a552e490 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.integ.snapshot/tree.json @@ -0,0 +1,202 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.33" + } + }, + "build-test-assets": { + "id": "build-test-assets", + "path": "build-test-assets", + "children": { + "Build": { + "id": "Build", + "path": "build-test-assets/Build", + "children": { + "Service Role": { + "id": "Service Role", + "path": "build-test-assets/Build/Service Role", + "children": { + "Resource": { + "id": "Resource", + "path": "build-test-assets/Build/Service Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "gamelift.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "build-test-assets/Build/Service Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "build-test-assets/Build/Service Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "BuildServiceRoleDefaultPolicy90803718", + "roles": [ + { + "Ref": "BuildServiceRole4643E19E" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Content": { + "id": "Content", + "path": "build-test-assets/Build/Content", + "children": { + "Stage": { + "id": "Stage", + "path": "build-test-assets/Build/Content/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "build-test-assets/Build/Content/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "build-test-assets/Build/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::GameLift::Build", + "aws:cdk:cloudformation:props": { + "storageLocation": { + "bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "key": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "roleArn": { + "Fn::GetAtt": [ + "BuildServiceRole4643E19E", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-gamelift.CfnBuild", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-gamelift.Build", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/build.test.ts b/packages/@aws-cdk/aws-gamelift/test/build.test.ts new file mode 100644 index 0000000000000..9e5b6bd6855db --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/build.test.ts @@ -0,0 +1,235 @@ +import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as gamelift from '../lib'; + +describe('build', () => { + const buildId = 'test-identifier'; + const buildName = 'test-build'; + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + stack = new cdk.Stack(app); + }); + + describe('.fromBuildId()', () => { + test('with required fields', () => { + const build = gamelift.Build.fromBuildId(stack, 'ImportedBuild', buildId); + + expect(build.buildId).toEqual(buildId); + expect(build.grantPrincipal).toEqual(new iam.UnknownPrincipal({ resource: build })); + }); + }); + + describe('.fromBuildAttributes()', () => { + test('with required attrs only', () => { + const build = gamelift.Build.fromBuildAttributes(stack, 'ImportedBuild', { buildId }); + + expect(build.buildId).toEqual(buildId); + expect(build.grantPrincipal).toEqual(new iam.UnknownPrincipal({ resource: build })); + }); + + test('with all attrs', () => { + const role = iam.Role.fromRoleArn(stack, 'Role', 'arn:aws:iam::123456789012:role/TestRole'); + const build = gamelift.Build.fromBuildAttributes(stack, 'ImportedBuild', { buildId, role }); + + expect(buildId).toEqual(buildId); + expect(build.grantPrincipal).toEqual(role); + }); + }); + + describe('new', () => { + const localAsset = path.join(__dirname, 'my-game-build'); + const contentBucketName = 'bucketname'; + const contentBucketAccessStatement = { + Action: [ + 's3:GetObject*', + 's3:GetBucket*', + 's3:List*', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + `:s3:::${contentBucketName}`, + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + `:s3:::${contentBucketName}/content`, + ], + ], + }, + ], + }; + let contentBucket: s3.IBucket; + let content: gamelift.Content; + let build: gamelift.Build; + let defaultProps: gamelift.BuildProps; + + beforeEach(() => { + contentBucket = s3.Bucket.fromBucketName(stack, 'ContentBucket', contentBucketName); + content = gamelift.Content.fromBucket(contentBucket, 'content'); + defaultProps = { + content, + }; + }); + + describe('.fromAsset()', () => { + test('should create a new build from asset', () => { + build = gamelift.Build.fromAsset(stack, 'ImportedBuild', localAsset); + + expect(stack.node.metadata.find(m => m.type === 'aws:cdk:asset')).toBeDefined(); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + Bucket: { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + }, + }); + + }); + }); + + describe('.fromBucket()', () => { + test('should create a new build from bucket', () => { + build = gamelift.Build.fromBucket(stack, 'ImportedBuild', contentBucket, 'content'); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + Bucket: 'bucketname', + Key: 'content', + }, + }); + + }); + }); + + describe('with necessary props only', () => { + beforeEach(() => { + build = new gamelift.Build(stack, 'Build', defaultProps); + }); + + test('should create a role and use it with the build', () => { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'gamelift.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + + // Role policy should grant reading from the assets bucket + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + contentBucketAccessStatement, + ], + }, + Roles: [ + { + Ref: 'BuildServiceRole1F57E904', + }, + ], + }); + + // check the build using the role + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + Bucket: 'bucketname', + Key: 'content', + RoleArn: { + 'Fn::GetAtt': [ + 'BuildServiceRole1F57E904', + 'Arn', + ], + }, + }, + }); + }); + + test('should return correct buildId from CloudFormation', () => { + expect(stack.resolve(build.buildId)).toEqual({ Ref: 'Build45A36621' }); + }); + + test('with a custom role should use it and set it in CloudFormation', () => { + const role = iam.Role.fromRoleArn(stack, 'Role', 'arn:aws:iam::123456789012:role/TestRole'); + build = new gamelift.Build(stack, 'BuildWithRole', { + ...defaultProps, + role, + }); + + expect(build.grantPrincipal).toEqual(role); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + RoleArn: role.roleArn, + }, + }); + }); + + test('with a custom buildName should set it in CloudFormation', () => { + build = new gamelift.Build(stack, 'BuildWithName', { + ...defaultProps, + buildName: buildName, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + Name: buildName, + }); + }); + + test('with all optional attributes should set it in CloudFormation', () => { + build = new gamelift.Build(stack, 'BuildWithName', { + ...defaultProps, + buildName: buildName, + operatingSystem: gamelift.OperatingSystem.AMAZON_LINUX_2, + buildVersion: '1.0', + }); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + Name: buildName, + OperatingSystem: gamelift.OperatingSystem.AMAZON_LINUX_2, + Version: '1.0', + }); + }); + + test('with an incorrect buildName (>1024)', () => { + let incorrectBuildName = ''; + for (let i = 0; i < 1025; i++) { + incorrectBuildName += 'A'; + } + + expect(() => new gamelift.Build(stack, 'BuildWithWrongName', { + content, + buildName: incorrectBuildName, + })).toThrow(/Build name can not be longer than 1024 characters but has 1025 characters./); + }); + }); + }); +}); + + diff --git a/packages/@aws-cdk/aws-gamelift/test/content.test.ts b/packages/@aws-cdk/aws-gamelift/test/content.test.ts new file mode 100644 index 0000000000000..0c1f6e0617121 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/content.test.ts @@ -0,0 +1,280 @@ +import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as gamelift from '../lib'; + +describe('Code', () => { + let stack: cdk.Stack; + let content: gamelift.Content; + + beforeEach(() => { + const app = new cdk.App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + stack = new cdk.Stack(app, 'Stack'); + }); + + describe('.fromBucket()', () => { + const key = 'content'; + let bucket: s3.IBucket; + + test('with valid bucket name and key and bound by build sets the right path and grants the build permissions to read from it', () => { + bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'bucketname'); + content = gamelift.Content.fromBucket(bucket, key); + new gamelift.Build(stack, 'Build1', { + content: content, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + Bucket: 'bucketname', + Key: 'content', + }, + }); + + // Role policy should grant reading from the assets bucket + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3:GetObject*', + 's3:GetBucket*', + 's3:List*', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:::bucketname', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:::bucketname/content', + ], + ], + }, + ], + }, + ], + }, + Roles: [ + { + Ref: 'Build1ServiceRole24FABCB7', + }, + ], + }); + }); + }); + + describe('.fromAsset()', () => { + const directoryPath = path.join(__dirname, 'my-game-build'); + + beforeEach(() => { + content = gamelift.Content.fromAsset(directoryPath); + }); + + test("with valid and existing file path and bound to job sets job's script location and permissions stack metadata", () => { + new gamelift.Build(stack, 'Build1', { + content: content, + }); + + expect(stack.node.metadata.find(m => m.type === 'aws:cdk:asset')).toBeDefined(); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation: { + Bucket: { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + Key: { + 'Fn::Join': [ + '', + [ + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3VersionKey720D3160', + }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3VersionKey720D3160', + }, + ], + }, + ], + }, + ], + ], + }, + RoleArn: { + 'Fn::GetAtt': [ + 'Build1ServiceRole24FABCB7', + 'Arn', + ], + }, + }, + }); + // Role policy should grant reading from the assets bucket + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 's3:GetObject*', + 's3:GetBucket*', + 's3:List*', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:::', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:::', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + '/*', + ], + ], + }, + ], + }, + ], + }, + Roles: [ + { + Ref: 'Build1ServiceRole24FABCB7', + }, + ], + }); + }); + + test('with an unsupported file path throws', () => { + // GIVEN + const fileAsset = gamelift.Content.fromAsset(path.join(__dirname, 'my-game-build', 'index.js')); + + // THEN + expect(() => new gamelift.Build(stack, 'Build1', { content: fileAsset })) + .toThrow(/Asset must be a \.zip file or a directory/); + }); + + test('used in more than 1 build in the same stack should be reused', () => { + new gamelift.Build(stack, 'Build1', { + content: content, + }); + new gamelift.Build(stack, 'Build2', { + content: content, + }); + const StorageLocation = { + Bucket: { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + Key: { + 'Fn::Join': [ + '', + [ + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3VersionKey720D3160', + }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3VersionKey720D3160', + }, + ], + }, + ], + }, + ], + ], + }, + RoleArn: { + 'Fn::GetAtt': [ + 'Build1ServiceRole24FABCB7', + 'Arn', + ], + }, + }; + + expect(stack.node.metadata.find(m => m.type === 'aws:cdk:asset')).toBeDefined(); + // Job1 and Job2 use reuse the asset + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation, + }); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Build', { + StorageLocation, + }); + }); + + test('throws if trying to rebind in another stack', () => { + new gamelift.Build(stack, 'Build1', { + content, + }); + const differentStack = new cdk.Stack(); + + expect(() => new gamelift.Build(differentStack, 'Build2', { + content, + })).toThrow(/Asset is already associated with another stack/); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.build.ts b/packages/@aws-cdk/aws-gamelift/test/integ.build.ts new file mode 100644 index 0000000000000..d216cbccd9212 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/integ.build.ts @@ -0,0 +1,13 @@ +import * as path from 'path'; +import * as cdk from '@aws-cdk/core'; +import * as gamelift from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-gamelift-build'); + +new gamelift.Build(stack, 'Build', { + content: gamelift.Content.fromAsset(path.join(__dirname, 'my-game-build')), +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.script.ts b/packages/@aws-cdk/aws-gamelift/test/integ.script.ts new file mode 100644 index 0000000000000..fb85f5b00ab37 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/integ.script.ts @@ -0,0 +1,13 @@ +import * as path from 'path'; +import * as cdk from '@aws-cdk/core'; +import * as gamelift from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-gamelift-script'); + +new gamelift.Script(stack, 'Script', { + content: gamelift.Content.fromAsset(path.join(__dirname, 'my-game-script')), +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-gamelift/test/my-game-build.zip b/packages/@aws-cdk/aws-gamelift/test/my-game-build.zip new file mode 100644 index 0000000000000..4a13be08c2721 Binary files /dev/null and b/packages/@aws-cdk/aws-gamelift/test/my-game-build.zip differ diff --git a/packages/@aws-cdk/aws-gamelift/test/my-game-build/index.js b/packages/@aws-cdk/aws-gamelift/test/my-game-build/index.js new file mode 100644 index 0000000000000..73c02658c48d9 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/my-game-build/index.js @@ -0,0 +1 @@ +console.log('Hello World'); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/my-game-script/index.js b/packages/@aws-cdk/aws-gamelift/test/my-game-script/index.js new file mode 100644 index 0000000000000..73c02658c48d9 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/my-game-script/index.js @@ -0,0 +1 @@ +console.log('Hello World'); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js new file mode 100644 index 0000000000000..73c02658c48d9 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7/index.js @@ -0,0 +1 @@ +console.log('Hello World'); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.assets.json b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.assets.json new file mode 100644 index 0000000000000..b5db81d532125 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7": { + "source": { + "path": "asset.6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222": { + "source": { + "path": "aws-gamelift-script.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.template.json b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.template.json new file mode 100644 index 0000000000000..fe0c724ffaad9 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/aws-gamelift-script.template.json @@ -0,0 +1,129 @@ +{ + "Resources": { + "ScriptServiceRole23DD8079": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "gamelift.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ScriptServiceRoleDefaultPolicyEE85DAE7": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ScriptServiceRoleDefaultPolicyEE85DAE7", + "Roles": [ + { + "Ref": "ScriptServiceRole23DD8079" + } + ] + } + }, + "Script09016516": { + "Type": "AWS::GameLift::Script", + "Properties": { + "StorageLocation": { + "Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "Key": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "RoleArn": { + "Fn::GetAtt": [ + "ScriptServiceRole23DD8079", + "Arn" + ] + } + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } + } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/integ.json b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/integ.json new file mode 100644 index 0000000000000..87f04519b0e06 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "version": "21.0.0", + "testCases": { + "integ.script": { + "stacks": [ + "aws-gamelift-script" + ], + "diffAssets": false, + "stackUpdateWorkflow": true + } + }, + "synthContext": {}, + "enableLookups": false +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..5bc5612710eb2 --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/manifest.json @@ -0,0 +1,64 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-gamelift-script.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-gamelift-script.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-gamelift-script": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-gamelift-script.template.json", + "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}/9c561e93c7a2947a15dba683670660e922cf493e17b2a6f8ca03cf221442c222.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-gamelift-script.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-gamelift-script.assets" + ], + "metadata": { + "/aws-gamelift-script/Script/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ScriptServiceRole23DD8079" + } + ], + "/aws-gamelift-script/Script/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ScriptServiceRoleDefaultPolicyEE85DAE7" + } + ], + "/aws-gamelift-script/Script/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Script09016516" + } + ] + }, + "displayName": "aws-gamelift-script" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/tree.json b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/tree.json new file mode 100644 index 0000000000000..8a6195c91e0cc --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.integ.snapshot/tree.json @@ -0,0 +1,202 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.33" + } + }, + "script-test-assets": { + "id": "script-test-assets", + "path": "script-test-assets", + "children": { + "Script": { + "id": "Script", + "path": "script-test-assets/Script", + "children": { + "Service Role": { + "id": "Service Role", + "path": "script-test-assets/Script/Service Role", + "children": { + "Resource": { + "id": "Resource", + "path": "script-test-assets/Script/Service Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "gamelift.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "script-test-assets/Script/Service Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "script-test-assets/Script/Service Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "ScriptServiceRoleDefaultPolicy90803718", + "roles": [ + { + "Ref": "ScriptServiceRole4643E19E" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Content": { + "id": "Content", + "path": "script-test-assets/Script/Content", + "children": { + "Stage": { + "id": "Stage", + "path": "script-test-assets/Script/Content/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "script-test-assets/Script/Content/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "script-test-assets/Script/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::GameLift::Script", + "aws:cdk:cloudformation:props": { + "storageLocation": { + "bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "key": "6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7.zip", + "roleArn": { + "Fn::GetAtt": [ + "ScriptServiceRole4643E19E", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-gamelift.CfnScript", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-gamelift.Script", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/script.test.ts b/packages/@aws-cdk/aws-gamelift/test/script.test.ts new file mode 100644 index 0000000000000..b7c5efc2f075d --- /dev/null +++ b/packages/@aws-cdk/aws-gamelift/test/script.test.ts @@ -0,0 +1,245 @@ +import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as gamelift from '../lib'; + +describe('script', () => { + const scriptId = 'script-test-identifier'; + const scriptArn = `arn:aws:gamelift:script-region:123456789012:script/${scriptId}`; + const scriptName = 'test-script'; + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + stack = new cdk.Stack(app, 'Base', { + env: { account: '111111111111', region: 'stack-region' }, + }); + }); + + describe('.fromScriptArn()', () => { + test('with required fields', () => { + const script = gamelift.Script.fromScriptArn(stack, 'ImportedScript', scriptArn); + + expect(script.scriptArn).toEqual(scriptArn); + expect(script.grantPrincipal).toEqual(new iam.UnknownPrincipal({ resource: script })); + }); + }); + + describe('.fromScriptAttributes()', () => { + test('with required attrs only', () => { + const script = gamelift.Script.fromScriptAttributes(stack, 'ImportedScript', { scriptArn }); + + expect(script.scriptId).toEqual(scriptId); + expect(script.scriptArn).toEqual(scriptArn); + expect(script.env.account).toEqual('123456789012'); + expect(script.env.region).toEqual('script-region'); + expect(script.grantPrincipal).toEqual(new iam.UnknownPrincipal({ resource: script })); + }); + + test('with all attrs', () => { + const role = iam.Role.fromRoleArn(stack, 'Role', 'arn:aws:iam::123456789012:role/TestRole'); + const script = gamelift.Script.fromScriptAttributes(stack, 'ImportedScript', { scriptArn, role }); + + expect(scriptId).toEqual(scriptId); + expect(script.grantPrincipal).toEqual(role); + }); + }); + + describe('new', () => { + const localAsset = path.join(__dirname, 'my-game-script'); + const contentBucketName = 'bucketname'; + const contentBucketAccessStatement = { + Action: [ + 's3:GetObject*', + 's3:GetBucket*', + 's3:List*', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + `:s3:::${contentBucketName}`, + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + `:s3:::${contentBucketName}/content`, + ], + ], + }, + ], + }; + let contentBucket: s3.IBucket; + let content: gamelift.Content; + let script: gamelift.Script; + let defaultProps: gamelift.ScriptProps; + + beforeEach(() => { + contentBucket = s3.Bucket.fromBucketName(stack, 'ContentBucket', contentBucketName); + content = gamelift.Content.fromBucket(contentBucket, 'content'); + defaultProps = { + content, + }; + }); + + describe('.fromAsset()', () => { + test('should create a new script from asset', () => { + script = gamelift.Script.fromAsset(stack, 'ImportedScript', localAsset); + + expect(stack.node.metadata.find(m => m.type === 'aws:cdk:asset')).toBeDefined(); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + StorageLocation: { + Bucket: { + Ref: 'AssetParameters6019bfc8ab05a24b0ae9b5d8f4585cbfc7d1c30a23286d0b25ce7066a368a5d7S3Bucket72AA8348', + }, + }, + }); + + }); + }); + + describe('.fromBucket()', () => { + test('should create a new script from bucket', () => { + script = gamelift.Script.fromBucket(stack, 'ImportedScript', contentBucket, 'content'); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + StorageLocation: { + Bucket: 'bucketname', + Key: 'content', + }, + }); + + }); + }); + + describe('with necessary props only', () => { + beforeEach(() => { + script = new gamelift.Script(stack, 'Script', defaultProps); + }); + + test('should create a role and use it with the script', () => { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'gamelift.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + + // Role policy should grant reading from the assets bucket + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + contentBucketAccessStatement, + ], + }, + Roles: [ + { + Ref: 'ScriptServiceRole23DD8079', + }, + ], + }); + + // check the script using the role + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + StorageLocation: { + Bucket: 'bucketname', + Key: 'content', + RoleArn: { + 'Fn::GetAtt': [ + 'ScriptServiceRole23DD8079', + 'Arn', + ], + }, + }, + }); + }); + + test('should return correct script attributes from CloudFormation', () => { + expect(stack.resolve(script.scriptId)).toEqual({ Ref: 'Script09016516' }); + expect(stack.resolve(script.scriptArn)).toEqual({ + 'Fn::GetAtt': [ + 'Script09016516', + 'Arn', + ], + }); + }); + + test('with a custom role should use it and set it in CloudFormation', () => { + const role = iam.Role.fromRoleArn(stack, 'Role', 'arn:aws:iam::123456789012:role/TestRole'); + script = new gamelift.Script(stack, 'ScriptWithRole', { + ...defaultProps, + role, + }); + + expect(script.grantPrincipal).toEqual(role); + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + StorageLocation: { + RoleArn: role.roleArn, + }, + }); + }); + + test('with a custom scriptName should set it in CloudFormation', () => { + script = new gamelift.Script(stack, 'ScriptWithName', { + ...defaultProps, + scriptName: scriptName, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + Name: scriptName, + }); + }); + + test('with all optional attributes should set it in CloudFormation', () => { + script = new gamelift.Script(stack, 'ScriptWithName', { + ...defaultProps, + scriptName: scriptName, + scriptVersion: '1.0', + }); + + Template.fromStack(stack).hasResourceProperties('AWS::GameLift::Script', { + Name: scriptName, + Version: '1.0', + }); + }); + + test('with an incorrect scriptName (>1024)', () => { + let incorrectScriptName = ''; + for (let i = 0; i < 1025; i++) { + incorrectScriptName += 'A'; + } + + expect(() => new gamelift.Script(stack, 'ScriptWithWrongName', { + content, + scriptName: incorrectScriptName, + })).toThrow(/Script name can not be longer than 1024 characters but has 1025 characters./); + }); + }); + }); +}); + + diff --git a/packages/@aws-cdk/aws-iam/test/principals.test.ts b/packages/@aws-cdk/aws-iam/test/principals.test.ts index e3b1078d2a933..37dc662121854 100644 --- a/packages/@aws-cdk/aws-iam/test/principals.test.ts +++ b/packages/@aws-cdk/aws-iam/test/principals.test.ts @@ -311,10 +311,10 @@ test('ServicePrincipalName returns just a string representing the principal', () // GIVEN const usEastStack = new Stack(undefined, undefined, { env: { region: 'us-east-1' } }); const afSouthStack = new Stack(undefined, undefined, { env: { region: 'af-south-1' } }); - const principalName = iam.ServicePrincipal.servicePrincipalName('ssm.amazonaws.com'); + const principalName = iam.ServicePrincipal.servicePrincipalName('states.amazonaws.com'); - expect(usEastStack.resolve(principalName)).toEqual('ssm.amazonaws.com'); - expect(afSouthStack.resolve(principalName)).toEqual('ssm.af-south-1.amazonaws.com'); + expect(usEastStack.resolve(principalName)).toEqual('states.us-east-1.amazonaws.com'); + expect(afSouthStack.resolve(principalName)).toEqual('states.af-south-1.amazonaws.com'); }); test('Passing non-string as accountId parameter in AccountPrincipal constructor should throw error', () => { @@ -327,14 +327,14 @@ test('ServicePrincipal in agnostic stack generates lookup table', () => { // WHEN new iam.Role(stack, 'Role', { - assumedBy: new iam.ServicePrincipal('ssm.amazonaws.com'), + assumedBy: new iam.ServicePrincipal('states.amazonaws.com'), }); // THEN const template = Template.fromStack(stack); const mappings = template.findMappings('ServiceprincipalMap'); - expect(mappings.ServiceprincipalMap['af-south-1']?.ssm).toEqual('ssm.af-south-1.amazonaws.com'); - expect(mappings.ServiceprincipalMap['us-east-1']?.ssm).toEqual('ssm.amazonaws.com'); + expect(mappings.ServiceprincipalMap['af-south-1']?.states).toEqual('states.af-south-1.amazonaws.com'); + expect(mappings.ServiceprincipalMap['us-east-1']?.states).toEqual('states.us-east-1.amazonaws.com'); }); test('Can enable session tags', () => { diff --git a/packages/@aws-cdk/aws-iotfleetwise/.eslintrc.js b/packages/@aws-cdk/aws-iotfleetwise/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iotfleetwise/.gitignore b/packages/@aws-cdk/aws-iotfleetwise/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-iotfleetwise/.npmignore b/packages/@aws-cdk/aws-iotfleetwise/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-iotfleetwise/LICENSE b/packages/@aws-cdk/aws-iotfleetwise/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-iotfleetwise/NOTICE b/packages/@aws-cdk/aws-iotfleetwise/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-iotfleetwise/README.md b/packages/@aws-cdk/aws-iotfleetwise/README.md new file mode 100644 index 0000000000000..7f35430c20e38 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/README.md @@ -0,0 +1,39 @@ +# AWS::IoTFleetWise 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 iotfleetwise from '@aws-cdk/aws-iotfleetwise'; +``` + + + +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 IoTFleetWise construct libraries](https://constructs.dev/search?q=iotfleetwise) +- 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::IoTFleetWise resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_IoTFleetWise.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::IoTFleetWise](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_IoTFleetWise.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/aws-iotfleetwise/jest.config.js b/packages/@aws-cdk/aws-iotfleetwise/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iotfleetwise/lib/index.ts b/packages/@aws-cdk/aws-iotfleetwise/lib/index.ts new file mode 100644 index 0000000000000..f19aa86d3a93b --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::IoTFleetWise CloudFormation Resources: +export * from './iotfleetwise.generated'; diff --git a/packages/@aws-cdk/aws-iotfleetwise/package.json b/packages/@aws-cdk/aws-iotfleetwise/package.json new file mode 100644 index 0000000000000..42c3a63631dad --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/package.json @@ -0,0 +1,113 @@ +{ + "name": "@aws-cdk/aws-iotfleetwise", + "version": "0.0.0", + "description": "AWS::IoTFleetWise Construct Library", + "private": true, + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.IoTFleetWise", + "packageId": "Amazon.CDK.AWS.IoTFleetWise", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.iotfleetwise", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "iotfleetwise" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ], + "distName": "aws-cdk.aws-iotfleetwise", + "module": "aws_cdk.aws_iotfleetwise" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-iotfleetwise" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::IoTFleetWise", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::IoTFleetWise", + "aws-iotfleetwise" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.5.2" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-iotfleetwise/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-iotfleetwise/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-iotfleetwise/test/iotfleetwise.test.ts b/packages/@aws-cdk/aws-iotfleetwise/test/iotfleetwise.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-iotfleetwise/test/iotfleetwise.test.ts @@ -0,0 +1,6 @@ +import '@aws-cdk/assertions'; +import {} from '../lib'; + +test('No tests are specified for this package', () => { + expect(true).toBe(true); +}); diff --git a/packages/@aws-cdk/aws-neptune/README.md b/packages/@aws-cdk/aws-neptune/README.md index 36433215ce57e..cc11a50e94e04 100644 --- a/packages/@aws-cdk/aws-neptune/README.md +++ b/packages/@aws-cdk/aws-neptune/README.md @@ -144,6 +144,38 @@ new neptune.DatabaseCluster(this, 'Cluster', { }); ``` +## Logging + +Neptune supports various methods for monitoring performance and usage. One of those methods is logging + +1. Neptune provides logs e.g. audit logs which can be viewed or downloaded via the AWS Console. Audit logs can be enabled using the `neptune_enable_audit_log` parameter in `ClusterParameterGroup` or `ParameterGroup` +2. Neptune provides the ability to export those logs to CloudWatch Logs + +```ts +// Cluster parameter group with the neptune_enable_audit_log param set to 1 +const clusterParameterGroup = new neptune.ClusterParameterGroup(this, 'ClusterParams', { + description: 'Cluster parameter group', + parameters: { + neptune_enable_audit_log: '1' + }, +}); + +const cluster = new neptune.DatabaseCluster(this, 'Database', { + vpc, + instanceType: neptune.InstanceType.R5_LARGE, + // Audit logs are enabled via the clusterParameterGroup + clusterParameterGroup, + // Optionally configuring audit logs to be exported to CloudWatch Logs + cloudwatchLogsExports: [neptune.LogType.AUDIT], + // Optionally set a retention period on exported CloudWatch Logs + cloudwatchLogsRetention: logs.RetentionDays.ONE_MONTH, +}); +``` + +For more information on monitoring, refer to https://docs.aws.amazon.com/neptune/latest/userguide/monitoring.html. +For more information on audit logs, refer to https://docs.aws.amazon.com/neptune/latest/userguide/auditing.html. +For more information on exporting logs to CloudWatch Logs, refer to https://docs.aws.amazon.com/neptune/latest/userguide/cloudwatch-logs.html. + ## Metrics Both `DatabaseCluster` and `DatabaseInstance` provide a `metric()` method to help with cluster-level and instance-level monitoring. diff --git a/packages/@aws-cdk/aws-neptune/lib/cluster.ts b/packages/@aws-cdk/aws-neptune/lib/cluster.ts index f2e998332c304..aeea9780541b1 100644 --- a/packages/@aws-cdk/aws-neptune/lib/cluster.ts +++ b/packages/@aws-cdk/aws-neptune/lib/cluster.ts @@ -2,6 +2,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; +import * as logs from '@aws-cdk/aws-logs'; import { Aws, Duration, IResource, Lazy, RemovalPolicy, Resource, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Endpoint } from './endpoint'; @@ -71,6 +72,26 @@ export class EngineVersion { public constructor(public readonly version: string) {} } +/** + * Neptune log types that can be exported to CloudWatch logs + * + * @see https://docs.aws.amazon.com/neptune/latest/userguide/cloudwatch-logs.html + */ +export class LogType { + /** + * Audit logs + * + * @see https://docs.aws.amazon.com/neptune/latest/userguide/auditing.html + */ + public static readonly AUDIT = new LogType('audit'); + + /** + * Constructor for specifying a custom log type + * @param value the log type + */ + public constructor(public readonly value: string) {} +} + /** * Properties for a new database cluster */ @@ -243,6 +264,34 @@ export interface DatabaseClusterProps { * @default - false */ readonly autoMinorVersionUpgrade?: boolean; + + /** + * The list of log types that need to be enabled for exporting to + * CloudWatch Logs. + * + * @see https://docs.aws.amazon.com/neptune/latest/userguide/cloudwatch-logs.html + * @see https://docs.aws.amazon.com/neptune/latest/userguide/auditing.html#auditing-enable + * + * @default - no log exports + */ + readonly cloudwatchLogsExports?: LogType[]; + + /** + * The number of days log events are kept in CloudWatch Logs. When updating + * this property, unsetting it doesn't remove the log retention policy. To + * remove the retention policy, set the value to `Infinity`. + * + * @default - logs never expire + */ + readonly cloudwatchLogsRetention?: logs.RetentionDays; + + /** + * The IAM role for the Lambda function associated with the custom resource + * that sets the retention policy. + * + * @default - a new role is created. + */ + readonly cloudwatchLogsRetentionRole?: iam.IRole; } /** @@ -529,6 +578,8 @@ export class DatabaseCluster extends DatabaseClusterBase implements IDatabaseClu preferredMaintenanceWindow: props.preferredMaintenanceWindow, // Encryption kmsKeyId: props.kmsKey?.keyArn, + // CloudWatch Logs exports + enableCloudwatchLogsExports: props.cloudwatchLogsExports?.map(logType => logType.value), storageEncrypted, }); @@ -543,6 +594,18 @@ export class DatabaseCluster extends DatabaseClusterBase implements IDatabaseClu this.clusterEndpoint = new Endpoint(cluster.attrEndpoint, port); this.clusterReadEndpoint = new Endpoint(cluster.attrReadEndpoint, port); + // Log retention + const retention = props.cloudwatchLogsRetention; + if (retention) { + props.cloudwatchLogsExports?.forEach(logType => { + new logs.LogRetention(this, `${logType}LogRetention`, { + logGroupName: `/aws/neptune/${this.clusterIdentifier}/${logType.value}`, + role: props.cloudwatchLogsRetentionRole, + retention, + }); + }); + } + // Create the instances const instanceCount = props.instances ?? DatabaseCluster.DEFAULT_NUM_INSTANCES; if (instanceCount < 1) { diff --git a/packages/@aws-cdk/aws-neptune/package.json b/packages/@aws-cdk/aws-neptune/package.json index 6b38c7760a3bf..c63290eaa732a 100644 --- a/packages/@aws-cdk/aws-neptune/package.json +++ b/packages/@aws-cdk/aws-neptune/package.json @@ -94,6 +94,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, @@ -102,6 +103,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, diff --git a/packages/@aws-cdk/aws-neptune/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-neptune/rosetta/default.ts-fixture index 63e17311b5dc5..c42645f4be506 100644 --- a/packages/@aws-cdk/aws-neptune/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-neptune/rosetta/default.ts-fixture @@ -2,6 +2,7 @@ import { Duration, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import * as iam from '@aws-cdk/aws-iam'; import * as ec2 from '@aws-cdk/aws-ec2'; +import * as logs from '@aws-cdk/aws-logs'; import * as neptune from '@aws-cdk/aws-neptune'; class Fixture extends Stack { diff --git a/packages/@aws-cdk/aws-neptune/test/cluster-ev12.integ.snapshot/tree.json b/packages/@aws-cdk/aws-neptune/test/cluster-ev12.integ.snapshot/tree.json index 9fe2fa8dea40d..3d59ec3056b67 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster-ev12.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-neptune/test/cluster-ev12.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.92" + "version": "10.1.95" } }, "aws-cdk-neptune-integ": { @@ -1026,7 +1026,7 @@ "path": "ClusterTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.92" + "version": "10.1.95" } }, "DeployAssert": { diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts new file mode 100644 index 0000000000000..9bbf5854684b6 --- /dev/null +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts @@ -0,0 +1 @@ +export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context): Promise; diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js new file mode 100644 index 0000000000000..d8d501f248a23 --- /dev/null +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js @@ -0,0 +1,209 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.handler = void 0; +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +/** + * Creates a log group and doesn't throw if it exists. + * + * @param logGroupName the name of the log group to create. + * @param region to create the log group in + * @param options CloudWatch API SDK options. + */ +async function createLogGroupSafe(logGroupName, region, options) { + // If we set the log retention for a lambda, then due to the async nature of + // Lambda logging there could be a race condition when the same log group is + // already being created by the lambda execution. This can sometime result in + // an error "OperationAbortedException: A conflicting operation is currently + // in progress...Please try again." + // To avoid an error, we do as requested and try again. + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); + return; + } + catch (error) { + if (error.code === 'ResourceAlreadyExistsException') { + // The log group is already created by the lambda execution + return; + } + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } + else { + // The log group is still being created by another execution but we are out of retries + throw new Error('Out of attempts to create a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} +//delete a log group +async function deleteLogGroup(logGroupName, region, options) { + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + await cloudwatchlogs.deleteLogGroup({ logGroupName }).promise(); + return; + } + catch (error) { + if (error.code === 'ResourceNotFoundException') { + // The log group doesn't exist + return; + } + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } + else { + // The log group is still being deleted by another execution but we are out of retries + throw new Error('Out of attempts to delete a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} +/** + * Puts or deletes a retention policy on a log group. + * + * @param logGroupName the name of the log group to create + * @param region the region of the log group + * @param options CloudWatch API SDK options. + * @param retentionInDays the number of days to retain the log events in the specified log group. + */ +async function setRetentionPolicy(logGroupName, region, options, retentionInDays) { + // The same as in createLogGroupSafe(), here we could end up with the race + // condition where a log group is either already being created or its retention + // policy is being updated. This would result in an OperationAbortedException, + // which we will try to catch and retry the command a number of times before failing + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + if (!retentionInDays) { + await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); + } + else { + await cloudwatchlogs.putRetentionPolicy({ logGroupName, retentionInDays }).promise(); + } + return; + } + catch (error) { + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } + else { + // The log group is still being created by another execution but we are out of retries + throw new Error('Out of attempts to create a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} +async function handler(event, context) { + try { + console.log(JSON.stringify({ ...event, ResponseURL: '...' })); + // The target log group + const logGroupName = event.ResourceProperties.LogGroupName; + // The region of the target log group + const logGroupRegion = event.ResourceProperties.LogGroupRegion; + // Parse to AWS SDK retry options + const retryOptions = parseRetryOptions(event.ResourceProperties.SdkRetry); + if (event.RequestType === 'Create' || event.RequestType === 'Update') { + // Act on the target log group + await createLogGroupSafe(logGroupName, logGroupRegion, retryOptions); + await setRetentionPolicy(logGroupName, logGroupRegion, retryOptions, parseInt(event.ResourceProperties.RetentionInDays, 10)); + if (event.RequestType === 'Create') { + // Set a retention policy of 1 day on the logs of this very function. + // Due to the async nature of the log group creation, the log group for this function might + // still be not created yet at this point. Therefore we attempt to create it. + // In case it is being created, createLogGroupSafe will handle the conflict. + const region = process.env.AWS_REGION; + await createLogGroupSafe(`/aws/lambda/${context.functionName}`, region, retryOptions); + // If createLogGroupSafe fails, the log group is not created even after multiple attempts. + // In this case we have nothing to set the retention policy on but an exception will skip + // the next line. + await setRetentionPolicy(`/aws/lambda/${context.functionName}`, region, retryOptions, 1); + } + } + //When the requestType is delete, delete the log group if the removal policy is delete + if (event.RequestType === 'Delete' && event.ResourceProperties.RemovalPolicy === 'destroy') { + await deleteLogGroup(logGroupName, logGroupRegion, retryOptions); + //else retain the log group + } + await respond('SUCCESS', 'OK', logGroupName); + } + catch (e) { + console.log(e); + await respond('FAILED', e.message, event.ResourceProperties.LogGroupName); + } + function respond(responseStatus, reason, physicalResourceId) { + const responseBody = JSON.stringify({ + Status: responseStatus, + Reason: reason, + PhysicalResourceId: physicalResourceId, + StackId: event.StackId, + RequestId: event.RequestId, + LogicalResourceId: event.LogicalResourceId, + Data: { + // Add log group name as part of the response so that it's available via Fn::GetAtt + LogGroupName: event.ResourceProperties.LogGroupName, + }, + }); + console.log('Responding', responseBody); + // eslint-disable-next-line @typescript-eslint/no-require-imports + const parsedUrl = require('url').parse(event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + return new Promise((resolve, reject) => { + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const request = require('https').request(requestOptions, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); + } + function parseRetryOptions(rawOptions) { + const retryOptions = {}; + if (rawOptions) { + if (rawOptions.maxRetries) { + retryOptions.maxRetries = parseInt(rawOptions.maxRetries, 10); + } + if (rawOptions.base) { + retryOptions.retryOptions = { + base: parseInt(rawOptions.base, 10), + }; + } + } + return retryOptions; + } +} +exports.handler = handler; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0JBQStCOzs7QUFFL0IsNkRBQTZEO0FBQzdELCtCQUErQjtBQVMvQjs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsa0JBQWtCLENBQUMsWUFBb0IsRUFBRSxNQUFlLEVBQUUsT0FBeUI7SUFDaEcsNEVBQTRFO0lBQzVFLDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UsNEVBQTRFO0lBQzVFLG1DQUFtQztJQUNuQyx1REFBdUQ7SUFDdkQsSUFBSSxVQUFVLEdBQUcsT0FBTyxFQUFFLFVBQVUsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1RSxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7SUFDeEYsR0FBRztRQUNELElBQUk7WUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDaEcsTUFBTSxjQUFjLENBQUMsY0FBYyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRSxPQUFPO1NBQ1I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxnQ0FBZ0MsRUFBRTtnQkFDbkQsMkRBQTJEO2dCQUMzRCxPQUFPO2FBQ1I7WUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQzlDLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtvQkFDbEIsVUFBVSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDekQsU0FBUztpQkFDVjtxQkFBTTtvQkFDTCxzRkFBc0Y7b0JBQ3RGLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztpQkFDekQ7YUFDRjtZQUNELE1BQU0sS0FBSyxDQUFDO1NBQ2I7S0FDRixRQUFRLElBQUksRUFBRSxDQUFDLG9DQUFvQztBQUN0RCxDQUFDO0FBRUQsb0JBQW9CO0FBQ3BCLEtBQUssVUFBVSxjQUFjLENBQUMsWUFBb0IsRUFBRSxNQUFlLEVBQUUsT0FBeUI7SUFDNUYsSUFBSSxVQUFVLEdBQUcsT0FBTyxFQUFFLFVBQVUsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1RSxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7SUFDeEYsR0FBRztRQUNELElBQUk7WUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDaEcsTUFBTSxjQUFjLENBQUMsY0FBYyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRSxPQUFPO1NBQ1I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDOUMsOEJBQThCO2dCQUM5QixPQUFPO2FBQ1I7WUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQzlDLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtvQkFDbEIsVUFBVSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDekQsU0FBUztpQkFDVjtxQkFBTTtvQkFDTCxzRkFBc0Y7b0JBQ3RGLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztpQkFDekQ7YUFDRjtZQUNELE1BQU0sS0FBSyxDQUFDO1NBQ2I7S0FDRixRQUFRLElBQUksRUFBRSxDQUFDLG9DQUFvQztBQUN0RCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxZQUFvQixFQUFFLE1BQWUsRUFBRSxPQUF5QixFQUFFLGVBQXdCO0lBQzFILDBFQUEwRTtJQUMxRSwrRUFBK0U7SUFDL0UsOEVBQThFO0lBQzlFLG9GQUFvRjtJQUNwRixJQUFJLFVBQVUsR0FBRyxPQUFPLEVBQUUsVUFBVSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQzVFLE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxZQUFZLEVBQUUsSUFBSSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUN4RixHQUFHO1FBQ0QsSUFBSTtZQUNGLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNoRyxJQUFJLENBQUMsZUFBZSxFQUFFO2dCQUNwQixNQUFNLGNBQWMsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDeEU7aUJBQU07Z0JBQ0wsTUFBTSxjQUFjLENBQUMsa0JBQWtCLENBQUMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUN0RjtZQUNELE9BQU87U0FFUjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUM5QyxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUU7b0JBQ2xCLFVBQVUsRUFBRSxDQUFDO29CQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBQ3pELFNBQVM7aUJBQ1Y7cUJBQU07b0JBQ0wsc0ZBQXNGO29CQUN0RixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7aUJBQ3pEO2FBQ0Y7WUFDRCxNQUFNLEtBQUssQ0FBQztTQUNiO0tBQ0YsUUFBUSxJQUFJLEVBQUUsQ0FBQyxvQ0FBb0M7QUFDdEQsQ0FBQztBQUVNLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0QsRUFBRSxPQUEwQjtJQUMxRyxJQUFJO1FBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztRQUU5RCx1QkFBdUI7UUFDdkIsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQztRQUUzRCxxQ0FBcUM7UUFDckMsTUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGNBQWMsQ0FBQztRQUUvRCxpQ0FBaUM7UUFDakMsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTFFLElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7WUFDcEUsOEJBQThCO1lBQzlCLE1BQU0sa0JBQWtCLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNyRSxNQUFNLGtCQUFrQixDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFN0gsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMscUVBQXFFO2dCQUNyRSwyRkFBMkY7Z0JBQzNGLDZFQUE2RTtnQkFDN0UsNEVBQTRFO2dCQUM1RSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQztnQkFDdEMsTUFBTSxrQkFBa0IsQ0FBQyxlQUFlLE9BQU8sQ0FBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ3RGLDBGQUEwRjtnQkFDMUYseUZBQXlGO2dCQUN6RixpQkFBaUI7Z0JBQ2pCLE1BQU0sa0JBQWtCLENBQUMsZUFBZSxPQUFPLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQzthQUMxRjtTQUNGO1FBRUQsc0ZBQXNGO1FBQ3RGLElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUU7WUFDMUYsTUFBTSxjQUFjLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNqRSwyQkFBMkI7U0FDNUI7UUFFRCxNQUFNLE9BQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO0tBQzlDO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWYsTUFBTSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO0tBQzNFO0lBRUQsU0FBUyxPQUFPLENBQUMsY0FBc0IsRUFBRSxNQUFjLEVBQUUsa0JBQTBCO1FBQ2pGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDbEMsTUFBTSxFQUFFLGNBQWM7WUFDdEIsTUFBTSxFQUFFLE1BQU07WUFDZCxrQkFBa0IsRUFBRSxrQkFBa0I7WUFDdEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztZQUMxQixpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1lBQzFDLElBQUksRUFBRTtnQkFDSixtRkFBbUY7Z0JBQ25GLFlBQVksRUFBRSxLQUFLLENBQUMsa0JBQWtCLENBQUMsWUFBWTthQUNwRDtTQUNGLENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBRXhDLGlFQUFpRTtRQUNqRSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxNQUFNLGNBQWMsR0FBRztZQUNyQixRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7WUFDNUIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO1lBQ3BCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsTUFBTSxFQUFFO1NBQ3ZFLENBQUM7UUFFRixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUk7Z0JBQ0YsaUVBQWlFO2dCQUNqRSxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDbEUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQzthQUNmO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ1g7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxTQUFTLGlCQUFpQixDQUFDLFVBQWU7UUFDeEMsTUFBTSxZQUFZLEdBQW9CLEVBQUUsQ0FBQztRQUN6QyxJQUFJLFVBQVUsRUFBRTtZQUNkLElBQUksVUFBVSxDQUFDLFVBQVUsRUFBRTtnQkFDekIsWUFBWSxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQzthQUMvRDtZQUNELElBQUksVUFBVSxDQUFDLElBQUksRUFBRTtnQkFDbkIsWUFBWSxDQUFDLFlBQVksR0FBRztvQkFDMUIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztpQkFDcEMsQ0FBQzthQUNIO1NBQ0Y7UUFDRCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0FBQ0gsQ0FBQztBQWpHRCwwQkFpR0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgUmV0cnlEZWxheU9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmludGVyZmFjZSBTZGtSZXRyeU9wdGlvbnMge1xuICBtYXhSZXRyaWVzPzogbnVtYmVyO1xuICByZXRyeU9wdGlvbnM/OiBSZXRyeURlbGF5T3B0aW9ucztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbG9nIGdyb3VwIGFuZCBkb2Vzbid0IHRocm93IGlmIGl0IGV4aXN0cy5cbiAqXG4gKiBAcGFyYW0gbG9nR3JvdXBOYW1lIHRoZSBuYW1lIG9mIHRoZSBsb2cgZ3JvdXAgdG8gY3JlYXRlLlxuICogQHBhcmFtIHJlZ2lvbiB0byBjcmVhdGUgdGhlIGxvZyBncm91cCBpblxuICogQHBhcmFtIG9wdGlvbnMgQ2xvdWRXYXRjaCBBUEkgU0RLIG9wdGlvbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUxvZ0dyb3VwU2FmZShsb2dHcm91cE5hbWU6IHN0cmluZywgcmVnaW9uPzogc3RyaW5nLCBvcHRpb25zPzogU2RrUmV0cnlPcHRpb25zKSB7XG4gIC8vIElmIHdlIHNldCB0aGUgbG9nIHJldGVudGlvbiBmb3IgYSBsYW1iZGEsIHRoZW4gZHVlIHRvIHRoZSBhc3luYyBuYXR1cmUgb2ZcbiAgLy8gTGFtYmRhIGxvZ2dpbmcgdGhlcmUgY291bGQgYmUgYSByYWNlIGNvbmRpdGlvbiB3aGVuIHRoZSBzYW1lIGxvZyBncm91cCBpc1xuICAvLyBhbHJlYWR5IGJlaW5nIGNyZWF0ZWQgYnkgdGhlIGxhbWJkYSBleGVjdXRpb24uIFRoaXMgY2FuIHNvbWV0aW1lIHJlc3VsdCBpblxuICAvLyBhbiBlcnJvciBcIk9wZXJhdGlvbkFib3J0ZWRFeGNlcHRpb246IEEgY29uZmxpY3Rpbmcgb3BlcmF0aW9uIGlzIGN1cnJlbnRseVxuICAvLyBpbiBwcm9ncmVzcy4uLlBsZWFzZSB0cnkgYWdhaW4uXCJcbiAgLy8gVG8gYXZvaWQgYW4gZXJyb3IsIHdlIGRvIGFzIHJlcXVlc3RlZCBhbmQgdHJ5IGFnYWluLlxuICBsZXQgcmV0cnlDb3VudCA9IG9wdGlvbnM/Lm1heFJldHJpZXMgPT0gdW5kZWZpbmVkID8gMTAgOiBvcHRpb25zLm1heFJldHJpZXM7XG4gIGNvbnN0IGRlbGF5ID0gb3B0aW9ucz8ucmV0cnlPcHRpb25zPy5iYXNlID09IHVuZGVmaW5lZCA/IDEwIDogb3B0aW9ucy5yZXRyeU9wdGlvbnMuYmFzZTtcbiAgZG8ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjbG91ZHdhdGNobG9ncyA9IG5ldyBBV1MuQ2xvdWRXYXRjaExvZ3MoeyBhcGlWZXJzaW9uOiAnMjAxNC0wMy0yOCcsIHJlZ2lvbiwgLi4ub3B0aW9ucyB9KTtcbiAgICAgIGF3YWl0IGNsb3Vkd2F0Y2hsb2dzLmNyZWF0ZUxvZ0dyb3VwKHsgbG9nR3JvdXBOYW1lIH0pLnByb21pc2UoKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdSZXNvdXJjZUFscmVhZHlFeGlzdHNFeGNlcHRpb24nKSB7XG4gICAgICAgIC8vIFRoZSBsb2cgZ3JvdXAgaXMgYWxyZWFkeSBjcmVhdGVkIGJ5IHRoZSBsYW1iZGEgZXhlY3V0aW9uXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChlcnJvci5jb2RlID09PSAnT3BlcmF0aW9uQWJvcnRlZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgaWYgKHJldHJ5Q291bnQgPiAwKSB7XG4gICAgICAgICAgcmV0cnlDb3VudC0tO1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSkpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFRoZSBsb2cgZ3JvdXAgaXMgc3RpbGwgYmVpbmcgY3JlYXRlZCBieSBhbm90aGVyIGV4ZWN1dGlvbiBidXQgd2UgYXJlIG91dCBvZiByZXRyaWVzXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPdXQgb2YgYXR0ZW1wdHMgdG8gY3JlYXRlIGEgbG9nR3JvdXAnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9IHdoaWxlICh0cnVlKTsgLy8gZXhpdCBoYXBwZW5zIG9uIHJldHJ5IGNvdW50IGNoZWNrXG59XG5cbi8vZGVsZXRlIGEgbG9nIGdyb3VwXG5hc3luYyBmdW5jdGlvbiBkZWxldGVMb2dHcm91cChsb2dHcm91cE5hbWU6IHN0cmluZywgcmVnaW9uPzogc3RyaW5nLCBvcHRpb25zPzogU2RrUmV0cnlPcHRpb25zKSB7XG4gIGxldCByZXRyeUNvdW50ID0gb3B0aW9ucz8ubWF4UmV0cmllcyA9PSB1bmRlZmluZWQgPyAxMCA6IG9wdGlvbnMubWF4UmV0cmllcztcbiAgY29uc3QgZGVsYXkgPSBvcHRpb25zPy5yZXRyeU9wdGlvbnM/LmJhc2UgPT0gdW5kZWZpbmVkID8gMTAgOiBvcHRpb25zLnJldHJ5T3B0aW9ucy5iYXNlO1xuICBkbyB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsb3Vkd2F0Y2hsb2dzID0gbmV3IEFXUy5DbG91ZFdhdGNoTG9ncyh7IGFwaVZlcnNpb246ICcyMDE0LTAzLTI4JywgcmVnaW9uLCAuLi5vcHRpb25zIH0pO1xuICAgICAgYXdhaXQgY2xvdWR3YXRjaGxvZ3MuZGVsZXRlTG9nR3JvdXAoeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIC8vIFRoZSBsb2cgZ3JvdXAgZG9lc24ndCBleGlzdFxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ09wZXJhdGlvbkFib3J0ZWRFeGNlcHRpb24nKSB7XG4gICAgICAgIGlmIChyZXRyeUNvdW50ID4gMCkge1xuICAgICAgICAgIHJldHJ5Q291bnQtLTtcbiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgZGVsYXkpKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBUaGUgbG9nIGdyb3VwIGlzIHN0aWxsIGJlaW5nIGRlbGV0ZWQgYnkgYW5vdGhlciBleGVjdXRpb24gYnV0IHdlIGFyZSBvdXQgb2YgcmV0cmllc1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT3V0IG9mIGF0dGVtcHRzIHRvIGRlbGV0ZSBhIGxvZ0dyb3VwJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfSB3aGlsZSAodHJ1ZSk7IC8vIGV4aXQgaGFwcGVucyBvbiByZXRyeSBjb3VudCBjaGVja1xufVxuXG4vKipcbiAqIFB1dHMgb3IgZGVsZXRlcyBhIHJldGVudGlvbiBwb2xpY3kgb24gYSBsb2cgZ3JvdXAuXG4gKlxuICogQHBhcmFtIGxvZ0dyb3VwTmFtZSB0aGUgbmFtZSBvZiB0aGUgbG9nIGdyb3VwIHRvIGNyZWF0ZVxuICogQHBhcmFtIHJlZ2lvbiB0aGUgcmVnaW9uIG9mIHRoZSBsb2cgZ3JvdXBcbiAqIEBwYXJhbSBvcHRpb25zIENsb3VkV2F0Y2ggQVBJIFNESyBvcHRpb25zLlxuICogQHBhcmFtIHJldGVudGlvbkluRGF5cyB0aGUgbnVtYmVyIG9mIGRheXMgdG8gcmV0YWluIHRoZSBsb2cgZXZlbnRzIGluIHRoZSBzcGVjaWZpZWQgbG9nIGdyb3VwLlxuICovXG5hc3luYyBmdW5jdGlvbiBzZXRSZXRlbnRpb25Qb2xpY3kobG9nR3JvdXBOYW1lOiBzdHJpbmcsIHJlZ2lvbj86IHN0cmluZywgb3B0aW9ucz86IFNka1JldHJ5T3B0aW9ucywgcmV0ZW50aW9uSW5EYXlzPzogbnVtYmVyKSB7XG4gIC8vIFRoZSBzYW1lIGFzIGluIGNyZWF0ZUxvZ0dyb3VwU2FmZSgpLCBoZXJlIHdlIGNvdWxkIGVuZCB1cCB3aXRoIHRoZSByYWNlXG4gIC8vIGNvbmRpdGlvbiB3aGVyZSBhIGxvZyBncm91cCBpcyBlaXRoZXIgYWxyZWFkeSBiZWluZyBjcmVhdGVkIG9yIGl0cyByZXRlbnRpb25cbiAgLy8gcG9saWN5IGlzIGJlaW5nIHVwZGF0ZWQuIFRoaXMgd291bGQgcmVzdWx0IGluIGFuIE9wZXJhdGlvbkFib3J0ZWRFeGNlcHRpb24sXG4gIC8vIHdoaWNoIHdlIHdpbGwgdHJ5IHRvIGNhdGNoIGFuZCByZXRyeSB0aGUgY29tbWFuZCBhIG51bWJlciBvZiB0aW1lcyBiZWZvcmUgZmFpbGluZ1xuICBsZXQgcmV0cnlDb3VudCA9IG9wdGlvbnM/Lm1heFJldHJpZXMgPT0gdW5kZWZpbmVkID8gMTAgOiBvcHRpb25zLm1heFJldHJpZXM7XG4gIGNvbnN0IGRlbGF5ID0gb3B0aW9ucz8ucmV0cnlPcHRpb25zPy5iYXNlID09IHVuZGVmaW5lZCA/IDEwIDogb3B0aW9ucy5yZXRyeU9wdGlvbnMuYmFzZTtcbiAgZG8ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjbG91ZHdhdGNobG9ncyA9IG5ldyBBV1MuQ2xvdWRXYXRjaExvZ3MoeyBhcGlWZXJzaW9uOiAnMjAxNC0wMy0yOCcsIHJlZ2lvbiwgLi4ub3B0aW9ucyB9KTtcbiAgICAgIGlmICghcmV0ZW50aW9uSW5EYXlzKSB7XG4gICAgICAgIGF3YWl0IGNsb3Vkd2F0Y2hsb2dzLmRlbGV0ZVJldGVudGlvblBvbGljeSh7IGxvZ0dyb3VwTmFtZSB9KS5wcm9taXNlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBjbG91ZHdhdGNobG9ncy5wdXRSZXRlbnRpb25Qb2xpY3koeyBsb2dHcm91cE5hbWUsIHJldGVudGlvbkluRGF5cyB9KS5wcm9taXNlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG5cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdPcGVyYXRpb25BYm9ydGVkRXhjZXB0aW9uJykge1xuICAgICAgICBpZiAocmV0cnlDb3VudCA+IDApIHtcbiAgICAgICAgICByZXRyeUNvdW50LS07XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5KSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVGhlIGxvZyBncm91cCBpcyBzdGlsbCBiZWluZyBjcmVhdGVkIGJ5IGFub3RoZXIgZXhlY3V0aW9uIGJ1dCB3ZSBhcmUgb3V0IG9mIHJldHJpZXNcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ091dCBvZiBhdHRlbXB0cyB0byBjcmVhdGUgYSBsb2dHcm91cCcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH0gd2hpbGUgKHRydWUpOyAvLyBleGl0IGhhcHBlbnMgb24gcmV0cnkgY291bnQgY2hlY2tcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIHRyeSB7XG4gICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoeyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH0pKTtcblxuICAgIC8vIFRoZSB0YXJnZXQgbG9nIGdyb3VwXG4gICAgY29uc3QgbG9nR3JvdXBOYW1lID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkxvZ0dyb3VwTmFtZTtcblxuICAgIC8vIFRoZSByZWdpb24gb2YgdGhlIHRhcmdldCBsb2cgZ3JvdXBcbiAgICBjb25zdCBsb2dHcm91cFJlZ2lvbiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cFJlZ2lvbjtcblxuICAgIC8vIFBhcnNlIHRvIEFXUyBTREsgcmV0cnkgb3B0aW9uc1xuICAgIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHBhcnNlUmV0cnlPcHRpb25zKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5TZGtSZXRyeSk7XG5cbiAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnIHx8IGV2ZW50LlJlcXVlc3RUeXBlID09PSAnVXBkYXRlJykge1xuICAgICAgLy8gQWN0IG9uIHRoZSB0YXJnZXQgbG9nIGdyb3VwXG4gICAgICBhd2FpdCBjcmVhdGVMb2dHcm91cFNhZmUobG9nR3JvdXBOYW1lLCBsb2dHcm91cFJlZ2lvbiwgcmV0cnlPcHRpb25zKTtcbiAgICAgIGF3YWl0IHNldFJldGVudGlvblBvbGljeShsb2dHcm91cE5hbWUsIGxvZ0dyb3VwUmVnaW9uLCByZXRyeU9wdGlvbnMsIHBhcnNlSW50KGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5SZXRlbnRpb25JbkRheXMsIDEwKSk7XG5cbiAgICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScpIHtcbiAgICAgICAgLy8gU2V0IGEgcmV0ZW50aW9uIHBvbGljeSBvZiAxIGRheSBvbiB0aGUgbG9ncyBvZiB0aGlzIHZlcnkgZnVuY3Rpb24uXG4gICAgICAgIC8vIER1ZSB0byB0aGUgYXN5bmMgbmF0dXJlIG9mIHRoZSBsb2cgZ3JvdXAgY3JlYXRpb24sIHRoZSBsb2cgZ3JvdXAgZm9yIHRoaXMgZnVuY3Rpb24gbWlnaHRcbiAgICAgICAgLy8gc3RpbGwgYmUgbm90IGNyZWF0ZWQgeWV0IGF0IHRoaXMgcG9pbnQuIFRoZXJlZm9yZSB3ZSBhdHRlbXB0IHRvIGNyZWF0ZSBpdC5cbiAgICAgICAgLy8gSW4gY2FzZSBpdCBpcyBiZWluZyBjcmVhdGVkLCBjcmVhdGVMb2dHcm91cFNhZmUgd2lsbCBoYW5kbGUgdGhlIGNvbmZsaWN0LlxuICAgICAgICBjb25zdCByZWdpb24gPSBwcm9jZXNzLmVudi5BV1NfUkVHSU9OO1xuICAgICAgICBhd2FpdCBjcmVhdGVMb2dHcm91cFNhZmUoYC9hd3MvbGFtYmRhLyR7Y29udGV4dC5mdW5jdGlvbk5hbWV9YCwgcmVnaW9uLCByZXRyeU9wdGlvbnMpO1xuICAgICAgICAvLyBJZiBjcmVhdGVMb2dHcm91cFNhZmUgZmFpbHMsIHRoZSBsb2cgZ3JvdXAgaXMgbm90IGNyZWF0ZWQgZXZlbiBhZnRlciBtdWx0aXBsZSBhdHRlbXB0cy5cbiAgICAgICAgLy8gSW4gdGhpcyBjYXNlIHdlIGhhdmUgbm90aGluZyB0byBzZXQgdGhlIHJldGVudGlvbiBwb2xpY3kgb24gYnV0IGFuIGV4Y2VwdGlvbiB3aWxsIHNraXBcbiAgICAgICAgLy8gdGhlIG5leHQgbGluZS5cbiAgICAgICAgYXdhaXQgc2V0UmV0ZW50aW9uUG9saWN5KGAvYXdzL2xhbWJkYS8ke2NvbnRleHQuZnVuY3Rpb25OYW1lfWAsIHJlZ2lvbiwgcmV0cnlPcHRpb25zLCAxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL1doZW4gdGhlIHJlcXVlc3RUeXBlIGlzIGRlbGV0ZSwgZGVsZXRlIHRoZSBsb2cgZ3JvdXAgaWYgdGhlIHJlbW92YWwgcG9saWN5IGlzIGRlbGV0ZVxuICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScgJiYgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlJlbW92YWxQb2xpY3kgPT09ICdkZXN0cm95Jykge1xuICAgICAgYXdhaXQgZGVsZXRlTG9nR3JvdXAobG9nR3JvdXBOYW1lLCBsb2dHcm91cFJlZ2lvbiwgcmV0cnlPcHRpb25zKTtcbiAgICAgIC8vZWxzZSByZXRhaW4gdGhlIGxvZyBncm91cFxuICAgIH1cblxuICAgIGF3YWl0IHJlc3BvbmQoJ1NVQ0NFU1MnLCAnT0snLCBsb2dHcm91cE5hbWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc29sZS5sb2coZSk7XG5cbiAgICBhd2FpdCByZXNwb25kKCdGQUlMRUQnLCBlLm1lc3NhZ2UsIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cE5hbWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzcG9uZChyZXNwb25zZVN0YXR1czogc3RyaW5nLCByZWFzb246IHN0cmluZywgcGh5c2ljYWxSZXNvdXJjZUlkOiBzdHJpbmcpIHtcbiAgICBjb25zdCByZXNwb25zZUJvZHkgPSBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBTdGF0dXM6IHJlc3BvbnNlU3RhdHVzLFxuICAgICAgUmVhc29uOiByZWFzb24sXG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgICBSZXF1ZXN0SWQ6IGV2ZW50LlJlcXVlc3RJZCxcbiAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICAgIERhdGE6IHtcbiAgICAgICAgLy8gQWRkIGxvZyBncm91cCBuYW1lIGFzIHBhcnQgb2YgdGhlIHJlc3BvbnNlIHNvIHRoYXQgaXQncyBhdmFpbGFibGUgdmlhIEZuOjpHZXRBdHRcbiAgICAgICAgTG9nR3JvdXBOYW1lOiBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuTG9nR3JvdXBOYW1lLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKCdSZXNwb25kaW5nJywgcmVzcG9uc2VCb2R5KTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgcGFyc2VkVXJsID0gcmVxdWlyZSgndXJsJykucGFyc2UoZXZlbnQuUmVzcG9uc2VVUkwpO1xuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiByZXNwb25zZUJvZHkubGVuZ3RoIH0sXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgICAgICBjb25zdCByZXF1ZXN0ID0gcmVxdWlyZSgnaHR0cHMnKS5yZXF1ZXN0KHJlcXVlc3RPcHRpb25zLCByZXNvbHZlKTtcbiAgICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlUmV0cnlPcHRpb25zKHJhd09wdGlvbnM6IGFueSk6IFNka1JldHJ5T3B0aW9ucyB7XG4gICAgY29uc3QgcmV0cnlPcHRpb25zOiBTZGtSZXRyeU9wdGlvbnMgPSB7fTtcbiAgICBpZiAocmF3T3B0aW9ucykge1xuICAgICAgaWYgKHJhd09wdGlvbnMubWF4UmV0cmllcykge1xuICAgICAgICByZXRyeU9wdGlvbnMubWF4UmV0cmllcyA9IHBhcnNlSW50KHJhd09wdGlvbnMubWF4UmV0cmllcywgMTApO1xuICAgICAgfVxuICAgICAgaWYgKHJhd09wdGlvbnMuYmFzZSkge1xuICAgICAgICByZXRyeU9wdGlvbnMucmV0cnlPcHRpb25zID0ge1xuICAgICAgICAgIGJhc2U6IHBhcnNlSW50KHJhd09wdGlvbnMuYmFzZSwgMTApLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0cnlPcHRpb25zO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts new file mode 100644 index 0000000000000..1bb38a9f3d774 --- /dev/null +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts @@ -0,0 +1,221 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as AWS from 'aws-sdk'; +// eslint-disable-next-line import/no-extraneous-dependencies +import type { RetryDelayOptions } from 'aws-sdk/lib/config-base'; + +interface SdkRetryOptions { + maxRetries?: number; + retryOptions?: RetryDelayOptions; +} + +/** + * Creates a log group and doesn't throw if it exists. + * + * @param logGroupName the name of the log group to create. + * @param region to create the log group in + * @param options CloudWatch API SDK options. + */ +async function createLogGroupSafe(logGroupName: string, region?: string, options?: SdkRetryOptions) { + // If we set the log retention for a lambda, then due to the async nature of + // Lambda logging there could be a race condition when the same log group is + // already being created by the lambda execution. This can sometime result in + // an error "OperationAbortedException: A conflicting operation is currently + // in progress...Please try again." + // To avoid an error, we do as requested and try again. + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + await cloudwatchlogs.createLogGroup({ logGroupName }).promise(); + return; + } catch (error) { + if (error.code === 'ResourceAlreadyExistsException') { + // The log group is already created by the lambda execution + return; + } + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } else { + // The log group is still being created by another execution but we are out of retries + throw new Error('Out of attempts to create a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} + +//delete a log group +async function deleteLogGroup(logGroupName: string, region?: string, options?: SdkRetryOptions) { + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + await cloudwatchlogs.deleteLogGroup({ logGroupName }).promise(); + return; + } catch (error) { + if (error.code === 'ResourceNotFoundException') { + // The log group doesn't exist + return; + } + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } else { + // The log group is still being deleted by another execution but we are out of retries + throw new Error('Out of attempts to delete a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} + +/** + * Puts or deletes a retention policy on a log group. + * + * @param logGroupName the name of the log group to create + * @param region the region of the log group + * @param options CloudWatch API SDK options. + * @param retentionInDays the number of days to retain the log events in the specified log group. + */ +async function setRetentionPolicy(logGroupName: string, region?: string, options?: SdkRetryOptions, retentionInDays?: number) { + // The same as in createLogGroupSafe(), here we could end up with the race + // condition where a log group is either already being created or its retention + // policy is being updated. This would result in an OperationAbortedException, + // which we will try to catch and retry the command a number of times before failing + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; + do { + try { + const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); + if (!retentionInDays) { + await cloudwatchlogs.deleteRetentionPolicy({ logGroupName }).promise(); + } else { + await cloudwatchlogs.putRetentionPolicy({ logGroupName, retentionInDays }).promise(); + } + return; + + } catch (error) { + if (error.code === 'OperationAbortedException') { + if (retryCount > 0) { + retryCount--; + await new Promise(resolve => setTimeout(resolve, delay)); + continue; + } else { + // The log group is still being created by another execution but we are out of retries + throw new Error('Out of attempts to create a logGroup'); + } + } + throw error; + } + } while (true); // exit happens on retry count check +} + +export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) { + try { + console.log(JSON.stringify({ ...event, ResponseURL: '...' })); + + // The target log group + const logGroupName = event.ResourceProperties.LogGroupName; + + // The region of the target log group + const logGroupRegion = event.ResourceProperties.LogGroupRegion; + + // Parse to AWS SDK retry options + const retryOptions = parseRetryOptions(event.ResourceProperties.SdkRetry); + + if (event.RequestType === 'Create' || event.RequestType === 'Update') { + // Act on the target log group + await createLogGroupSafe(logGroupName, logGroupRegion, retryOptions); + await setRetentionPolicy(logGroupName, logGroupRegion, retryOptions, parseInt(event.ResourceProperties.RetentionInDays, 10)); + + if (event.RequestType === 'Create') { + // Set a retention policy of 1 day on the logs of this very function. + // Due to the async nature of the log group creation, the log group for this function might + // still be not created yet at this point. Therefore we attempt to create it. + // In case it is being created, createLogGroupSafe will handle the conflict. + const region = process.env.AWS_REGION; + await createLogGroupSafe(`/aws/lambda/${context.functionName}`, region, retryOptions); + // If createLogGroupSafe fails, the log group is not created even after multiple attempts. + // In this case we have nothing to set the retention policy on but an exception will skip + // the next line. + await setRetentionPolicy(`/aws/lambda/${context.functionName}`, region, retryOptions, 1); + } + } + + //When the requestType is delete, delete the log group if the removal policy is delete + if (event.RequestType === 'Delete' && event.ResourceProperties.RemovalPolicy === 'destroy') { + await deleteLogGroup(logGroupName, logGroupRegion, retryOptions); + //else retain the log group + } + + await respond('SUCCESS', 'OK', logGroupName); + } catch (e) { + console.log(e); + + await respond('FAILED', e.message, event.ResourceProperties.LogGroupName); + } + + function respond(responseStatus: string, reason: string, physicalResourceId: string) { + const responseBody = JSON.stringify({ + Status: responseStatus, + Reason: reason, + PhysicalResourceId: physicalResourceId, + StackId: event.StackId, + RequestId: event.RequestId, + LogicalResourceId: event.LogicalResourceId, + Data: { + // Add log group name as part of the response so that it's available via Fn::GetAtt + LogGroupName: event.ResourceProperties.LogGroupName, + }, + }); + + console.log('Responding', responseBody); + + // eslint-disable-next-line @typescript-eslint/no-require-imports + const parsedUrl = require('url').parse(event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + + return new Promise((resolve, reject) => { + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const request = require('https').request(requestOptions, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } catch (e) { + reject(e); + } + }); + } + + function parseRetryOptions(rawOptions: any): SdkRetryOptions { + const retryOptions: SdkRetryOptions = {}; + if (rawOptions) { + if (rawOptions.maxRetries) { + retryOptions.maxRetries = parseInt(rawOptions.maxRetries, 10); + } + if (rawOptions.base) { + retryOptions.retryOptions = { + base: parseInt(rawOptions.base, 10), + }; + } + } + return retryOptions; + } +} diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.assets.json b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.assets.json index 8bbc76301c8f1..8d39fb0cb4004 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.assets.json +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.assets.json @@ -1,7 +1,20 @@ { "version": "21.0.0", "files": { - "c3aa283b33e47bc3d0cb943f014017d1742247b6577982270570cb6cbf5a778c": { + "d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347": { + "source": { + "path": "asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "504b6e69f5a409c7e8b08db3671b8fddadb27136582ed9def88ffb8c48114426": { "source": { "path": "aws-cdk-neptune-integ.template.json", "packaging": "file" @@ -9,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c3aa283b33e47bc3d0cb943f014017d1742247b6577982270570cb6cbf5a778c.json", + "objectKey": "504b6e69f5a409c7e8b08db3671b8fddadb27136582ed9def88ffb8c48114426.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.template.json b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.template.json index 15290913fcbd9..54fae188894cd 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.template.json +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/aws-cdk-neptune-integ.template.json @@ -502,6 +502,9 @@ "DBSubnetGroupName": { "Ref": "DatabaseSubnets3C9252C9" }, + "EnableCloudwatchLogsExports": [ + "audit" + ], "KmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -521,6 +524,30 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "DatabaseobjectObjectLogRetentionA247AF0C": { + "Type": "Custom::LogRetention", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn" + ] + }, + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/neptune/", + { + "Ref": "DatabaseB269D8BB" + }, + "/audit" + ] + ] + }, + "RetentionInDays": 30 + } + }, "DatabaseInstance1844F58FD": { "Type": "AWS::Neptune::DBInstance", "Properties": { @@ -539,6 +566,84 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347.zip" + }, + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn" + ] + } + }, + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + ] + }, "Alarm7103F465": { "Type": "AWS::CloudWatch::Alarm", "Properties": { diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/manifest.json index add010df1aabf..c78bd3f24b901 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/manifest.json @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c3aa283b33e47bc3d0cb943f014017d1742247b6577982270570cb6cbf5a778c.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/504b6e69f5a409c7e8b08db3671b8fddadb27136582ed9def88ffb8c48114426.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -213,12 +213,36 @@ "data": "DatabaseB269D8BB" } ], + "/aws-cdk-neptune-integ/Database/[object Object]LogRetention/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseobjectObjectLogRetentionA247AF0C" + } + ], "/aws-cdk-neptune-integ/Database/Instance1": [ { "type": "aws:cdk:logicalId", "data": "DatabaseInstance1844F58FD" } ], + "/aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ], + "/aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB" + } + ], + "/aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A" + } + ], "/aws-cdk-neptune-integ/Alarm/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/tree.json b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/tree.json index 1ca55bc53da8a..1b2fd3ec2a559 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-neptune/test/cluster.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.92" + "version": "10.1.95" } }, "aws-cdk-neptune-integ": { @@ -855,6 +855,9 @@ "dbSubnetGroupName": { "Ref": "DatabaseSubnets3C9252C9" }, + "enableCloudwatchLogsExports": [ + "audit" + ], "kmsKeyId": { "Fn::GetAtt": [ "DbSecurity381C2C15", @@ -877,6 +880,24 @@ "version": "0.0.0" } }, + "[object Object]LogRetention": { + "id": "[object Object]LogRetention", + "path": "aws-cdk-neptune-integ/Database/[object Object]LogRetention", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-neptune-integ/Database/[object Object]LogRetention/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-logs.LogRetention", + "version": "0.0.0" + } + }, "Instance1": { "id": "Instance1", "path": "aws-cdk-neptune-integ/Database/Instance1", @@ -901,6 +922,141 @@ "version": "0.0.0" } }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a": { + "id": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "children": { + "Code": { + "id": "Code", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "ServiceRole": { + "id": "ServiceRole", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-neptune-integ/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, "Alarm": { "id": "Alarm", "path": "aws-cdk-neptune-integ/Alarm", @@ -911,7 +1067,7 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", "aws:cdk:cloudformation:props": { - "comparisonOperator": "GreaterThanThreshold", + "comparisonOperator": "LessThanThreshold", "evaluationPeriods": 1, "dimensions": [ { @@ -921,11 +1077,11 @@ } } ], - "metricName": "SparqlErrors", + "metricName": "SparqlRequestsPerSec", "namespace": "AWS/Neptune", "period": 300, - "statistic": "Sum", - "threshold": 0 + "statistic": "Average", + "threshold": 1 } }, "constructInfo": { @@ -958,7 +1114,7 @@ "path": "ClusterTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.92" + "version": "10.1.95" } }, "DeployAssert": { diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts index b0b2873572eb8..650a36fb3e28a 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts @@ -3,9 +3,10 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; +import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; -import { ClusterParameterGroup, DatabaseCluster, EngineVersion, InstanceType } from '../lib'; +import { ClusterParameterGroup, DatabaseCluster, EngineVersion, InstanceType, LogType } from '../lib'; describe('DatabaseCluster', () => { @@ -661,6 +662,59 @@ describe('DatabaseCluster', () => { }); + test('cloudwatchLogsExports is enabled when configured', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Cluster', { + vpc, + instanceType: InstanceType.R5_LARGE, + cloudwatchLogsExports: [LogType.AUDIT], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { + EnableCloudwatchLogsExports: ['audit'], + }); + Template.fromStack(stack).resourceCountIs('Custom::LogRetention', 0); + }); + + test('cloudwatchLogsExports log retention is enabled when configured', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Cluster', { + vpc, + instanceType: InstanceType.R5_LARGE, + cloudwatchLogsExports: [LogType.AUDIT], + cloudwatchLogsRetention: logs.RetentionDays.ONE_MONTH, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { + EnableCloudwatchLogsExports: ['audit'], + }); + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { + LogGroupName: { + 'Fn::Join': [ + '', + [ + '/aws/neptune/', + { + Ref: 'ClusterEB0386A7', + }, + '/audit', + ], + ], + }, + RetentionInDays: 30, + }); + }); + test('metric - constructs metric with correct namespace and dimension and inputs', () => { // GIVEN const stack = testStack(); diff --git a/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts b/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts index 1b8d4156ef6f5..08fe4a0232db9 100644 --- a/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts +++ b/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts @@ -1,9 +1,10 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as kms from '@aws-cdk/aws-kms'; +import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; import * as integ from '@aws-cdk/integ-tests'; -import { DatabaseCluster, InstanceType } from '../lib'; +import { DatabaseCluster, InstanceType, LogType } from '../lib'; import { ClusterParameterGroup } from '../lib/parameter-group'; /* @@ -40,6 +41,8 @@ const cluster = new DatabaseCluster(stack, 'Database', { kmsKey, removalPolicy: cdk.RemovalPolicy.DESTROY, autoMinorVersionUpgrade: true, + cloudwatchLogsExports: [LogType.AUDIT], + cloudwatchLogsRetention: logs.RetentionDays.ONE_MONTH, }); cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts index db5b00c545b2a..37af190258d2a 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts @@ -245,6 +245,16 @@ export class AuroraEngineVersion { public static readonly VER_1_22_4 = AuroraEngineVersion.builtIn_5_6('1.22.4'); /** Version "5.6.mysql_aurora.1.22.5". */ public static readonly VER_1_22_5 = AuroraEngineVersion.builtIn_5_6('1.22.5'); + /** Version "5.6.mysql_aurora.1.23.0". */ + public static readonly VER_1_23_0 = AuroraEngineVersion.builtIn_5_6('1.23.0'); + /** Version "5.6.mysql_aurora.1.23.1". */ + public static readonly VER_1_23_1 = AuroraEngineVersion.builtIn_5_6('1.23.1'); + /** Version "5.6.mysql_aurora.1.23.2". */ + public static readonly VER_1_23_2 = AuroraEngineVersion.builtIn_5_6('1.23.2'); + /** Version "5.6.mysql_aurora.1.23.3". */ + public static readonly VER_1_23_3 = AuroraEngineVersion.builtIn_5_6('1.23.3'); + /** Version "5.6.mysql_aurora.1.23.4". */ + public static readonly VER_1_23_4 = AuroraEngineVersion.builtIn_5_6('1.23.4'); /** * Create a new AuroraEngineVersion with an arbitrary version. @@ -406,6 +416,8 @@ export class AuroraMysqlEngineVersion { public static readonly VER_3_01_1 = AuroraMysqlEngineVersion.builtIn_8_0('3.01.1'); /** Version "8.0.mysql_aurora.3.02.0". */ public static readonly VER_3_02_0 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.0'); + /** Version "8.0.mysql_aurora.3.02.1". */ + public static readonly VER_3_02_1 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.1'); /** * Create a new AuroraMysqlEngineVersion with an arbitrary version. diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index 211bbfd154b31..cada0ef139c4a 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -350,6 +350,8 @@ export class MariaDbEngineVersion { public static readonly VER_10_6_7 = MariaDbEngineVersion.of('10.6.7', '10.6'); /** Version "10.6.8". */ public static readonly VER_10_6_8 = MariaDbEngineVersion.of('10.6.8', '10.6'); + /** Version "10.6.10". */ + public static readonly VER_10_6_10 = MariaDbEngineVersion.of('10.6.10', '10.6'); /** * Create a new MariaDbEngineVersion with an arbitrary version. @@ -546,6 +548,10 @@ export class MysqlEngineVersion { public static readonly VER_5_7_36 = MysqlEngineVersion.of('5.7.36', '5.7'); /** Version "5.7.37". */ public static readonly VER_5_7_37 = MysqlEngineVersion.of('5.7.37', '5.7'); + /** Version "5.7.38". */ + public static readonly VER_5_7_38 = MysqlEngineVersion.of('5.7.38', '5.7'); + /** Version "5.7.39". */ + public static readonly VER_5_7_39 = MysqlEngineVersion.of('5.7.39', '5.7'); /** Version "8.0" (only a major version, without a specific minor version). */ public static readonly VER_8_0 = MysqlEngineVersion.of('8.0', '8.0'); diff --git a/packages/@aws-cdk/aws-rolesanywhere/.eslintrc.js b/packages/@aws-cdk/aws-rolesanywhere/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-rolesanywhere/.gitignore b/packages/@aws-cdk/aws-rolesanywhere/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-rolesanywhere/.npmignore b/packages/@aws-cdk/aws-rolesanywhere/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-rolesanywhere/LICENSE b/packages/@aws-cdk/aws-rolesanywhere/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-rolesanywhere/NOTICE b/packages/@aws-cdk/aws-rolesanywhere/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-rolesanywhere/README.md b/packages/@aws-cdk/aws-rolesanywhere/README.md new file mode 100644 index 0000000000000..c532af2542813 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/README.md @@ -0,0 +1,39 @@ +# AWS::RolesAnywhere 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 rolesanywhere from '@aws-cdk/aws-rolesanywhere'; +``` + + + +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 RolesAnywhere construct libraries](https://constructs.dev/search?q=rolesanywhere) +- 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::RolesAnywhere resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_RolesAnywhere.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::RolesAnywhere](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_RolesAnywhere.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/aws-rolesanywhere/jest.config.js b/packages/@aws-cdk/aws-rolesanywhere/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-rolesanywhere/lib/index.ts b/packages/@aws-cdk/aws-rolesanywhere/lib/index.ts new file mode 100644 index 0000000000000..f6a46d6ee3c94 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::RolesAnywhere CloudFormation Resources: +export * from './rolesanywhere.generated'; diff --git a/packages/@aws-cdk/aws-rolesanywhere/package.json b/packages/@aws-cdk/aws-rolesanywhere/package.json new file mode 100644 index 0000000000000..bd962a1be422b --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/package.json @@ -0,0 +1,113 @@ +{ + "name": "@aws-cdk/aws-rolesanywhere", + "version": "0.0.0", + "description": "AWS::RolesAnywhere Construct Library", + "private": true, + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.RolesAnywhere", + "packageId": "Amazon.CDK.AWS.RolesAnywhere", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.rolesanywhere", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "rolesanywhere" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ], + "distName": "aws-cdk.aws-rolesanywhere", + "module": "aws_cdk.aws_rolesanywhere" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-rolesanywhere" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::RolesAnywhere", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::RolesAnywhere", + "aws-rolesanywhere" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.5.2" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0", + "constructs": "^10.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-rolesanywhere/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-rolesanywhere/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-rolesanywhere/test/rolesanywhere.test.ts b/packages/@aws-cdk/aws-rolesanywhere/test/rolesanywhere.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-rolesanywhere/test/rolesanywhere.test.ts @@ -0,0 +1,6 @@ +import '@aws-cdk/assertions'; +import {} from '../lib'; + +test('No tests are specified for this package', () => { + expect(true).toBe(true); +}); diff --git a/packages/@aws-cdk/aws-s3-assets/test/custom-synthesis.test.ts b/packages/@aws-cdk/aws-s3-assets/test/custom-synthesis.test.ts new file mode 100644 index 0000000000000..525ccdb01f46c --- /dev/null +++ b/packages/@aws-cdk/aws-s3-assets/test/custom-synthesis.test.ts @@ -0,0 +1,99 @@ +/** + * This file asserts that it is possible to write a custom stacksynthesizer that will synthesize + * ONE thing to the asset manifest, while returning another thing (including tokens) to the + * CloudFormation template -- without reaching into the library internals + */ + +import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; +import { StackSynthesizer, FileAssetSource, FileAssetLocation, DockerImageAssetSource, DockerImageAssetLocation, ISynthesisSession, App, Stack, AssetManifestBuilder, CfnParameter, CfnResource } from '@aws-cdk/core'; +import { AssetManifestArtifact } from '@aws-cdk/cx-api'; +import { Asset } from '../lib'; + +test('use custom synthesizer', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'Stack', { + synthesizer: new CustomSynthesizer(), + }); + + // WHEN + const asset = new Asset(stack, 'MyAsset', { + path: path.join(__dirname, 'file-asset.txt'), + }); + new CfnResource(stack, 'TestResource', { + type: 'CDK::TestResource', + properties: { + Bucket: asset.s3BucketName, + ObjectKey: asset.s3ObjectKey, + S3Url: asset.s3ObjectUrl, + HttpUrl: asset.httpUrl, + }, + }); + + // THEN + const assembly = app.synth(); + const stackArtifact = assembly.getStackArtifact(stack.artifactId); + const assetArtifact = stackArtifact.dependencies[0] as AssetManifestArtifact; + + const stackTemplate = Template.fromJSON(stackArtifact.template); + stackTemplate.hasResourceProperties('CDK::TestResource', { + Bucket: { 'Fn::Sub': '${BucketName}' }, + ObjectKey: '78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt', + S3Url: { 'Fn::Sub': 's3://${BucketName}/78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt' }, + HttpUrl: { 'Fn::Sub': 'https://s3.${AWS::Region}.${AWS::URLSuffix}/${BucketName}/78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt' }, + }); + + expect(assetArtifact.contents).toEqual(expect.objectContaining({ + files: expect.objectContaining({ + '78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197': { + destinations: { + 'current_account-current_region': { + bucketName: 'write-bucket', + objectKey: '78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt', + }, + }, + source: { + packaging: 'file', + path: 'asset.78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt', + }, + }, + }), + })); +}); + +class CustomSynthesizer extends StackSynthesizer { + private readonly manifest = new AssetManifestBuilder(); + private parameter?: CfnParameter; + + bind(stack: Stack) { + super.bind(stack); + + this.parameter = new CfnParameter(stack, 'BucketName'); + } + + addFileAsset(asset: FileAssetSource): FileAssetLocation { + const dest = this.manifest.defaultAddFileAsset(this.boundStack, asset, { + bucketName: 'write-bucket', + }); + return this.cloudFormationLocationFromFileAsset({ + ...dest, + bucketName: ['${', this.parameter!.logicalId, '}'].join(''), + }); + } + + addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { + void(asset); + throw new Error('Docker images are not supported here'); + } + + synthesize(session: ISynthesisSession): void { + const templateAsset = this.addFileAsset(this.synthesizeTemplate(session)); + const assetManifestId = this.manifest.emitManifest(this.boundStack, session); + + this.emitArtifact(session, { + stackTemplateAssetObjectUrl: templateAsset.s3ObjectUrlWithPlaceholders, + additionalDependencies: [assetManifestId], + }); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 4093110014dec..60c5498a33794 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -1354,10 +1354,15 @@ export interface BucketProps { readonly enforceSSL?: boolean; /** - * Specifies whether Amazon S3 should use an S3 Bucket Key with server-side - * encryption using KMS (SSE-KMS) for new objects in the bucket. + * Whether Amazon S3 should use its own intermediary key to generate data keys. * - * Only relevant, when Encryption is set to {@link BucketEncryption.KMS} + * Only relevant when using KMS for encryption. + * + * - If not enabled, every object GET and PUT will cause an API call to KMS (with the + * attendant cost implications of that). + * - If enabled, S3 will use its own time-limited key instead. + * + * Only relevant, when Encryption is set to `BucketEncryption.KMS` or `BucketEncryption.KMS_MANAGED`. * * @default - false */ @@ -1943,7 +1948,7 @@ export class Bucket extends BucketBase { } // if bucketKeyEnabled is set, encryption must be set to KMS. - if (props.bucketKeyEnabled && encryptionType !== BucketEncryption.KMS) { + if (props.bucketKeyEnabled && ![BucketEncryption.KMS, BucketEncryption.KMS_MANAGED].includes(encryptionType)) { throw new Error(`bucketKeyEnabled is specified, so 'encryption' must be set to KMS (value: ${encryptionType})`); } @@ -1983,7 +1988,10 @@ export class Bucket extends BucketBase { if (encryptionType === BucketEncryption.KMS_MANAGED) { const bucketEncryption = { serverSideEncryptionConfiguration: [ - { serverSideEncryptionByDefault: { sseAlgorithm: 'aws:kms' } }, + { + bucketKeyEnabled: props.bucketKeyEnabled, + serverSideEncryptionByDefault: { sseAlgorithm: 'aws:kms' }, + }, ], }; return { bucketEncryption }; @@ -2288,17 +2296,17 @@ export enum BucketEncryption { /** * Objects in the bucket are not encrypted. */ - UNENCRYPTED = 'NONE', + UNENCRYPTED = 'UNENCRYPTED', /** * Server-side KMS encryption with a master key managed by KMS. */ - KMS_MANAGED = 'MANAGED', + KMS_MANAGED = 'KMS_MANAGED', /** * Server-side encryption with a master key managed by S3. */ - S3_MANAGED = 'S3MANAGED', + S3_MANAGED = 'S3_MANAGED', /** * Server-side encryption with a KMS key managed by the user. diff --git a/packages/@aws-cdk/aws-s3/test/bucket.test.ts b/packages/@aws-cdk/aws-s3/test/bucket.test.ts index 5396f6504d585..ed727d615578a 100644 --- a/packages/@aws-cdk/aws-s3/test/bucket.test.ts +++ b/packages/@aws-cdk/aws-s3/test/bucket.test.ts @@ -306,25 +306,19 @@ describe('bucket', () => { }); }); - test('bucketKeyEnabled can be enabled', () => { + test.each([s3.BucketEncryption.KMS, s3.BucketEncryption.KMS_MANAGED])('bucketKeyEnabled can be enabled with %p encryption', (encryption) => { const stack = new cdk.Stack(); - new s3.Bucket(stack, 'MyBucket', { bucketKeyEnabled: true, encryption: s3.BucketEncryption.KMS }); + new s3.Bucket(stack, 'MyBucket', { bucketKeyEnabled: true, encryption }); Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { 'BucketEncryption': { 'ServerSideEncryptionConfiguration': [ { 'BucketKeyEnabled': true, - 'ServerSideEncryptionByDefault': { - 'KMSMasterKeyID': { - 'Fn::GetAtt': [ - 'MyBucketKeyC17130CF', - 'Arn', - ], - }, + 'ServerSideEncryptionByDefault': Match.objectLike({ 'SSEAlgorithm': 'aws:kms', - }, + }), }, ], }, @@ -336,10 +330,10 @@ describe('bucket', () => { expect(() => { new s3.Bucket(stack, 'MyBucket', { bucketKeyEnabled: true, encryption: s3.BucketEncryption.S3_MANAGED }); - }).toThrow("bucketKeyEnabled is specified, so 'encryption' must be set to KMS (value: S3MANAGED)"); + }).toThrow("bucketKeyEnabled is specified, so 'encryption' must be set to KMS (value: S3_MANAGED)"); expect(() => { new s3.Bucket(stack, 'MyBucket3', { bucketKeyEnabled: true }); - }).toThrow("bucketKeyEnabled is specified, so 'encryption' must be set to KMS (value: NONE)"); + }).toThrow("bucketKeyEnabled is specified, so 'encryption' must be set to KMS (value: UNENCRYPTED)"); }); diff --git a/packages/@aws-cdk/aws-servicecatalog/lib/private/product-stack-synthesizer.ts b/packages/@aws-cdk/aws-servicecatalog/lib/private/product-stack-synthesizer.ts index 4840a7e756fe5..73f6e740d1790 100644 --- a/packages/@aws-cdk/aws-servicecatalog/lib/private/product-stack-synthesizer.ts +++ b/packages/@aws-cdk/aws-servicecatalog/lib/private/product-stack-synthesizer.ts @@ -6,15 +6,6 @@ import * as cdk from '@aws-cdk/core'; * Interoperates with the StackSynthesizer of the parent stack. */ export class ProductStackSynthesizer extends cdk.StackSynthesizer { - private stack?: cdk.Stack; - - public bind(stack: cdk.Stack): void { - if (this.stack !== undefined) { - throw new Error('A Stack Synthesizer can only be bound once, create a new instance to use with a different Stack'); - } - this.stack = stack; - } - public addFileAsset(_asset: cdk.FileAssetSource): cdk.FileAssetLocation { throw new Error('Service Catalog Product Stacks cannot use Assets'); } @@ -24,11 +15,8 @@ export class ProductStackSynthesizer extends cdk.StackSynthesizer { } public synthesize(session: cdk.ISynthesisSession): void { - if (!this.stack) { - throw new Error('You must call bindStack() first'); - } // Synthesize the template, but don't emit as a cloud assembly artifact. // It will be registered as an S3 asset of its parent instead. - this.synthesizeStackTemplate(this.stack, session); + this.synthesizeTemplate(session); } } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/README.md b/packages/@aws-cdk/aws-servicecatalogappregistry/README.md index e96a13bc8b2db..c65fd7a66b2a6 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/README.md +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/README.md @@ -21,12 +21,13 @@ -[AWS Service Catalog App Registry](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/appregistry.html) +[AWS Service Catalog App Registry](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/appregistry.html) enables organizations to create and manage repositores of applications and associated resources. ## Table Of Contents - [Application](#application) +- [Application-Associator](#application-associator) - [Attribute-Group](#attribute-group) - [Associations](#associations) - [Associating application with an attribute group](#attribute-group-association) @@ -44,11 +45,11 @@ import * as appreg from '@aws-cdk/aws-servicecatalogappregistry'; ## Application An AppRegistry application enables you to define your applications and associated resources. -The application name must be unique at the account level, but is mutable. +The application name must be unique at the account level and it's immutable. ```ts const application = new appreg.Application(this, 'MyFirstApplication', { - applicationName: 'MyFirstApplicationName', + applicationName: 'MyFirstApplicationName', description: 'description for my application', // the description is optional }); ``` @@ -64,6 +65,77 @@ const importedApplication = appreg.Application.fromApplicationArn( ); ``` +## Application-Associator + +If you want to create an Application named `MyAssociatedApplication` in account `123456789012` and region `us-east-1` +and want to associate all stacks in the `App` scope to `MyAssociatedApplication`, then use as shown in the example below: + +```ts +const app = new App(); +const associatedApp = new appreg.ApplicationAssociator(app, 'AssociatedApplication', { + applicationName: 'MyAssociatedApplication', + description: 'Testing associated application', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + env: {account: '123456789012', region: 'us-east-1'}, + }, +}); +``` + +If you want to re-use an existing Application with ARN: `arn:aws:servicecatalog:us-east-1:123456789012:/applications/applicationId` +and want to associate all stacks in the `App` scope to your imported application, then use as shown in the example below: + +```ts +const app = new App(); +const associatedApp = new appreg.ApplicationAssociator(app, 'AssociatedApplication', { + applicationArnValue: 'arn:aws:servicecatalog:us-east-1:123456789012:/applications/applicationId', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, +}); +``` + +If you are using CDK Pipelines to deploy your application, the application stacks will be inside Stages, and +ApplicationAssociator will not be able to find them. Call `associateStage` on each Stage object before adding it to the +Pipeline, as shown in the example below: + +```ts +import * as cdk from "@aws-cdk/core"; +import * as codepipeline from "@aws-cdk/pipelines"; +import * as codecommit from "@aws-cdk/aws-codecommit"; +declare const repo: codecommit.Repository; +declare const pipeline: codepipeline.CodePipeline; +declare const beta: cdk.Stage; +class ApplicationPipelineStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props: ApplicationPipelineStackProps) { + super(scope, id, props); + + //associate the stage to application associator. + props.application.associateStage(beta); + pipeline.addStage(beta); + } +}; + +interface ApplicationPipelineStackProps extends cdk.StackProps { + application: appreg.ApplicationAssociator; +}; + +const app = new App(); +const associatedApp = new appreg.ApplicationAssociator(app, 'AssociatedApplication', { + applicationName: 'MyPipelineAssociatedApplication', + description: 'Testing pipeline associated app', + stackProps: { + stackName: 'MyPipelineAssociatedApplicationStack', + env: {account: '123456789012', region: 'us-east-1'}, + }, +}); + +const cdkPipeline = new ApplicationPipelineStack(app, 'CDKApplicationPipelineStack', { + application: associatedApp, + env: {account: '123456789012', region: 'us-east-1'}, +}); +``` + ## Attribute Group An AppRegistry attribute group acts as a container for user-defined attributes for an application. @@ -71,7 +143,7 @@ Metadata is attached in a machine-readble format to integrate with automated wor ```ts const attributeGroup = new appreg.AttributeGroup(this, 'MyFirstAttributeGroup', { - attributeGroupName: 'MyFirstAttributeGroupName', + attributeGroupName: 'MyFirstAttributeGroupName', description: 'description for my attribute group', // the description is optional, attributes: { project: 'foo', @@ -104,7 +176,7 @@ Resources are CloudFormation stacks that you can associate with an application t stacks together to enable metadata rich insights into your applications and resources. A Cloudformation stack can only be associated with one appregistry application. If a stack is associated with multiple applications in your app or is already associated with one, -CDK will fail at deploy time. +CDK will fail at deploy time. ### Associating application with an attribute group diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application-associator.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application-associator.ts new file mode 100644 index 0000000000000..226e9d6c452ec --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application-associator.ts @@ -0,0 +1,100 @@ +import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { IApplication, Application } from './application'; +import { CheckedStageStackAssociator } from './aspects/stack-associator'; + +/** + * Properties for a Service Catalog AppRegistry AutoApplication + */ +export interface ApplicationAssociatorProps { + /** + * Enforces a particular physical application name. + * + * @default - No name. + */ + readonly applicationName?: string; + + /** + * Enforces a particular application arn. + * + * @default - No application arn. + */ + readonly applicationArnValue?: string; + + /** + * Application description. + * + * @default - No description. + */ + readonly description?: string; + + /** + * Stack properties. + * + */ + readonly stackProps: cdk.StackProps; +} + +/** + * An AppRegistry construct to automatically create an application with the given name and description. + * + * The application name must be unique at the account level and it's immutable. + * This construct will automatically associate all stacks in the given scope, however + * in case of a `Pipeline` stack, stage underneath the pipeline will not automatically be associated and + * needs to be associated separately. + * + * If cross account stack is detected, then this construct will automatically share the application to consumer accounts. + * Cross account feature will only work for non environment agnostic stacks. + */ +export class ApplicationAssociator extends Construct { + /** + * Created or imported application. + */ + private readonly application: IApplication; + private readonly associatedStages: Set = new Set(); + + constructor(scope: cdk.App, id: string, props: ApplicationAssociatorProps) { + super(scope, id); + + const applicationStack = new cdk.Stack(scope, 'ApplicationAssociatorStack', props.stackProps); + + if (!!props.applicationArnValue) { + this.application = Application.fromApplicationArn(applicationStack, 'ImportedApplication', props.applicationArnValue); + } else if (!!props.applicationName) { + this.application = new Application(applicationStack, 'DefaultCdkApplication', { + applicationName: props.applicationName, + description: props.description, + }); + } else { + throw new Error('Please provide either ARN or application name.'); + } + + cdk.Aspects.of(scope).add(new CheckedStageStackAssociator(this)); + } + + /** + * Associate this application with the given stage. + * + */ + public associateStage(stage: cdk.Stage): cdk.Stage { + this.associatedStages.add(stage); + cdk.Aspects.of(stage).add(new CheckedStageStackAssociator(this)); + return stage; + } + + /** + * Validates if a stage is already associated to the application. + * + */ + public isStageAssociated(stage: cdk.Stage): boolean { + return this.associatedStages.has(stage); + } + + /** + * Get the AppRegistry application. + * + */ + get appRegistryApplication() { + return this.application; + } +} diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application.ts index 256de4099afd0..eb5112e45287e 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/application.ts @@ -2,8 +2,10 @@ import { CfnResourceShare } from '@aws-cdk/aws-ram'; import * as cdk from '@aws-cdk/core'; import { Names } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import { StageStackAssociator } from './aspects/stack-associator'; import { IAttributeGroup } from './attribute-group'; import { getPrincipalsforSharing, hashValues, ShareOptions, SharePermission } from './common'; +import { isAccountUnresolved } from './private/utils'; import { InputValidator } from './private/validation'; import { CfnApplication, CfnAttributeGroupAssociation, CfnResourceAssociation } from './servicecatalogappregistry.generated'; @@ -27,7 +29,13 @@ export interface IApplication extends cdk.IResource { readonly applicationId: string; /** - * Associate thisapplication with an attribute group. + * The name of the application. + * @attribute + */ + readonly applicationName?: string; + + /** + * Associate this application with an attribute group. * * @param attributeGroup AppRegistry attribute group */ @@ -36,16 +44,34 @@ export interface IApplication extends cdk.IResource { /** * Associate this application with a CloudFormation stack. * + * @deprecated Use `associateApplicationWithStack` instead. * @param stack a CFN stack */ associateStack(stack: cdk.Stack): void; + /** + * Associate a Cloudformation statck with the application in the given stack. + * + * @param stack a CFN stack + */ + associateApplicationWithStack(stack: cdk.Stack): void; + /** * Share this application with other IAM entities, accounts, or OUs. * * @param shareOptions The options for the share. */ shareApplication(shareOptions: ShareOptions): void; + + /** + * Associate this application with all stacks under the construct node. + * NOTE: This method won't automatically register stacks under pipeline stages, + * and requires association of each pipeline stage by calling this method with stage Construct. + * + * @param construct cdk Construct + */ + associateAllStacksInScope(construct: Construct): void; + } /** @@ -67,6 +93,7 @@ export interface ApplicationProps { abstract class ApplicationBase extends cdk.Resource implements IApplication { public abstract readonly applicationArn: string; public abstract readonly applicationId: string; + public abstract readonly applicationName?: string; private readonly associatedAttributeGroups: Set = new Set(); private readonly associatedResources: Set = new Set(); @@ -89,6 +116,8 @@ abstract class ApplicationBase extends cdk.Resource implements IApplication { * Associate a stack with the application * If the resource is already associated, it will ignore duplicate request. * A stack can only be associated with one application. + * + * @deprecated Use `associateApplicationWithStack` instead. */ public associateStack(stack: cdk.Stack): void { if (!this.associatedResources.has(stack.node.addr)) { @@ -102,6 +131,27 @@ abstract class ApplicationBase extends cdk.Resource implements IApplication { } } + /** + * Associate stack with the application in the stack passed as parameter. + * + * If the stack is already associated, it will ignore duplicate request. + * A stack can only be associated with one application. + */ + public associateApplicationWithStack(stack: cdk.Stack): void { + if (!this.associatedResources.has(stack.node.addr)) { + new CfnResourceAssociation(stack, 'AppRegistryAssociation', { + application: stack === cdk.Stack.of(this) ? this.applicationId : this.applicationName ?? this.applicationId, + resource: stack.stackId, + resourceType: 'CFN_STACK', + }); + + this.associatedResources.add(stack.node.addr); + if (stack !== cdk.Stack.of(this) && this.isSameAccount(stack) && !this.isStageScope(stack)) { + stack.addDependency(cdk.Stack.of(this)); + } + } + } + /** * Share an application with accounts, organizations and OUs, and IAM roles and users. * The application will become available to end users within those principals. @@ -120,6 +170,17 @@ abstract class ApplicationBase extends cdk.Resource implements IApplication { }); } + /** + * Associate all stacks present in construct's aspect with application. + * + * NOTE: This method won't automatically register stacks under pipeline stages, + * and requires association of each pipeline stage by calling this method with stage Construct. + * + */ + public associateAllStacksInScope(scope: Construct): void { + cdk.Aspects.of(scope).add(new StageStackAssociator(this)); + } + /** * Create a unique id */ @@ -139,6 +200,21 @@ abstract class ApplicationBase extends cdk.Resource implements IApplication { return shareOptions.sharePermission ?? APPLICATION_READ_ONLY_RAM_PERMISSION_ARN; } } + + /** + * Checks whether a stack is defined in a Stage or not. + */ + private isStageScope(stack : cdk.Stack): boolean { + return !(stack.node.scope instanceof cdk.App) && (stack.node.scope instanceof cdk.Stage); + } + + /** + * Verifies if application and the visited node is deployed in different account. + */ + private isSameAccount(stack: cdk.Stack): boolean { + return isAccountUnresolved(this.env.account, stack.account) || this.env.account === stack.account; + } + } /** @@ -163,6 +239,7 @@ export class Application extends ApplicationBase { class Import extends ApplicationBase { public readonly applicationArn = applicationArn; public readonly applicationId = applicationId!; + public readonly applicationName = undefined; protected generateUniqueHash(resourceAddress: string): string { return hashValues(this.applicationArn, resourceAddress); @@ -176,6 +253,7 @@ export class Application extends ApplicationBase { public readonly applicationArn: string; public readonly applicationId: string; + public readonly applicationName?: string; private readonly nodeAddress: string; constructor(scope: Construct, id: string, props: ApplicationProps) { @@ -190,6 +268,7 @@ export class Application extends ApplicationBase { this.applicationArn = application.attrArn; this.applicationId = application.attrId; + this.applicationName = props.applicationName; this.nodeAddress = cdk.Names.nodeUniqueId(application.node); } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts new file mode 100644 index 0000000000000..593bf8a8265d6 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts @@ -0,0 +1,131 @@ +import { IAspect, Stack, Stage, Annotations } from '@aws-cdk/core'; +import { IConstruct } from 'constructs'; +import { IApplication } from '../application'; +import { ApplicationAssociator } from '../application-associator'; +import { SharePermission } from '../common'; +import { isRegionUnresolved, isAccountUnresolved } from '../private/utils'; + +/** + * Aspect class, this will visit each node from the provided construct once. + * + * For every stack node visited, this class will be responsible to associate + * the stack to the application. + */ +abstract class StackAssociatorBase implements IAspect { + protected abstract readonly application: IApplication; + protected abstract readonly applicationAssociator?: ApplicationAssociator; + + protected readonly sharedAccounts: Set = new Set(); + + public visit(node: IConstruct): void { + // verify if a stage in a particular stack is associated to Application. + node.node.children.forEach((childNode) => { + if (Stage.isStage(childNode)) { + var stageAssociated = this.applicationAssociator?.isStageAssociated(childNode); + if (stageAssociated === false) { + this.error(childNode, 'Associate Stage: ' + childNode.stageName + ' to ensure all stacks in your cdk app are associated with AppRegistry. ' + + 'You can use ApplicationAssociator.associateStage to associate any stage.'); + } + } + }); + + if (Stack.isStack(node)) { + this.handleCrossRegionStack(node); + this.handleCrossAccountStack(node); + this.associate(node); + } + } + + /** + * Associate a stage stack to the given application. + * + * @param node A Stage stack. + */ + private associate(node: Stack): void { + this.application.associateApplicationWithStack(node); + } + + /** + * Adds an error annotation to a node. + * + * @param node The scope to add the error to. + * @param message The error message. + */ + private error(node: IConstruct, message: string): void { + Annotations.of(node).addError(message); + } + + /** + * Adds a warning annotation to a node. + * + * @param node The scope to add the warning to. + * @param message The error message. + */ + private warning(node: IConstruct, message: string): void { + Annotations.of(node).addWarning(message); + } + + /** + * Handle cross-region association. AppRegistry do not support + * cross region association at this moment, + * If any stack is evaluated as cross-region than that of application, + * we will throw an error. + * + * @param node Cfn stack. + */ + private handleCrossRegionStack(node: Stack): void { + if (isRegionUnresolved(this.application.env.region, node.region)) { + this.warning(node, 'Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack.'); + return; + } + + if (node.region != this.application.env.region) { + this.error(node, 'AppRegistry does not support cross region associations. Application region ' + + this.application.env.region + ', stack region ' + node.region); + } + } + + /** + * Handle cross-account association. + * If any stack is evaluated as cross-account than that of application, + * then we will share the application to the stack owning account. + * + * @param node Cfn stack. + */ + private handleCrossAccountStack(node: Stack): void { + if (isAccountUnresolved(this.application.env.account!, node.account)) { + this.warning(node, 'Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack.'); + return; + } + + if (node.account != this.application.env.account && !this.sharedAccounts.has(node.account)) { + this.application.shareApplication({ + accounts: [node.account], + sharePermission: SharePermission.ALLOW_ACCESS, + }); + + this.sharedAccounts.add(node.account); + } + } +} + +export class CheckedStageStackAssociator extends StackAssociatorBase { + protected readonly application: IApplication; + protected readonly applicationAssociator?: ApplicationAssociator; + + constructor(app: ApplicationAssociator) { + super(); + this.application = app.appRegistryApplication; + this.applicationAssociator = app; + } +} + +export class StageStackAssociator extends StackAssociatorBase { + protected readonly application: IApplication; + protected readonly applicationAssociator?: ApplicationAssociator; + + constructor(app: IApplication) { + super(); + this.application = app; + } +} diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/attribute-group.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/attribute-group.ts index ea5a893422aa5..d6dda21fe797d 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/attribute-group.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/attribute-group.ts @@ -1,10 +1,10 @@ import { CfnResourceShare } from '@aws-cdk/aws-ram'; import * as cdk from '@aws-cdk/core'; -import { getPrincipalsforSharing, hashValues, ShareOptions, SharePermission } from './common'; +import { Names } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import { getPrincipalsforSharing, hashValues, ShareOptions, SharePermission } from './common'; import { InputValidator } from './private/validation'; import { CfnAttributeGroup } from './servicecatalogappregistry.generated'; -import { Names } from '@aws-cdk/core'; const ATTRIBUTE_GROUP_READ_ONLY_RAM_PERMISSION_ARN = 'arn:aws:ram::aws:permission/AWSRAMPermissionServiceCatalogAppRegistryAttributeGroupReadOnly'; const ATTRIBUTE_GROUP_ALLOW_ACCESS_RAM_PERMISSION_ARN = 'arn:aws:ram::aws:permission/AWSRAMPermissionServiceCatalogAppRegistryAttributeGroupAllowAssociation'; diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/index.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/index.ts index adbf2a9febfe6..72239c4a1d110 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/index.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/index.ts @@ -1,5 +1,6 @@ export * from './application'; export * from './attribute-group'; +export * from './application-associator'; export * from './common'; // AWS::ServiceCatalogAppRegistry CloudFormation Resources: diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/private/utils.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/private/utils.ts new file mode 100644 index 0000000000000..cdbf97a0f7337 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/private/utils.ts @@ -0,0 +1,22 @@ +import { Token } from '@aws-cdk/core'; + + +/** + * Verifies if application or the visited node is region agnostic. + * + * @param applicationRegion Region of the application. + * @param nodeRegion Region of the visited node. + */ +export function isRegionUnresolved(applicationRegion: string, nodeRegion: string): boolean { + return Token.isUnresolved(applicationRegion) || Token.isUnresolved(nodeRegion); +} + +/** + * Verifies if application or the visited node is account agnostic. + * + * @param applicationAccount Account of the application. + * @param nodeAccount Account of the visited node. + */ +export function isAccountUnresolved(applicationAccount: string, nodeAccount: string): boolean { + return Token.isUnresolved(applicationAccount) || Token.isUnresolved(nodeAccount); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json index f4d1243ef7542..aa5401b6ac812 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json @@ -88,19 +88,24 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", + "@aws-cdk/aws-codecommit": "0.0.0", "@types/jest": "^27.5.2" }, "dependencies": { "@aws-cdk/core": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-ram": "0.0.0", + "@aws-cdk/aws-codepipeline": "0.0.0", + "@aws-cdk/pipelines": "0.0.0", "constructs": "^10.0.0" }, "peerDependencies": { "@aws-cdk/core": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-ram": "0.0.0", - "constructs": "^10.0.0" + "@aws-cdk/aws-codepipeline": "0.0.0", + "constructs": "^10.0.0", + "@aws-cdk/pipelines": "0.0.0" }, "engines": { "node": ">= 14.15.0" @@ -113,5 +118,10 @@ "publishConfig": { "tag": "latest" }, + "awslint": { + "exclude": [ + "construct-ctor:@aws-cdk/aws-servicecatalogappregistry.ApplicationAssociator..params[0]" + ] + }, "private": true } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.assets.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.assets.json new file mode 100644 index 0000000000000..2f99ef79e2174 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "4285054f947789e255e76c75b889b3b216adabb0b3f990c8966c18459cdf7b35": { + "source": { + "path": "ApplicationAssociatorStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "4285054f947789e255e76c75b889b3b216adabb0b3f990c8966c18459cdf7b35.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.template.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.template.json new file mode 100644 index 0000000000000..79c9dec209b9e --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/ApplicationAssociatorStack.template.json @@ -0,0 +1,60 @@ +{ + "Resources": { + "DefaultCdkApplication4573D5A3": { + "Type": "AWS::ServiceCatalogAppRegistry::Application", + "Properties": { + "Name": "AppRegistryAssociatedApplication", + "Description": "Testing AppRegistry ApplicationAssociator" + } + }, + "AppRegistryAssociation": { + "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "Properties": { + "Application": { + "Fn::GetAtt": [ + "DefaultCdkApplication4573D5A3", + "Id" + ] + }, + "Resource": { + "Ref": "AWS::StackId" + }, + "ResourceType": "CFN_STACK" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.assets.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.assets.json new file mode 100644 index 0000000000000..5dec59ac54517 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc": { + "source": { + "path": "integ-servicecatalogappregistry-application.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.template.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.template.json new file mode 100644 index 0000000000000..ecc817b74774a --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ-servicecatalogappregistry-application.template.json @@ -0,0 +1,48 @@ +{ + "Resources": { + "AppRegistryAssociation": { + "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "Properties": { + "Application": "AppRegistryAssociatedApplication", + "Resource": { + "Ref": "AWS::StackId" + }, + "ResourceType": "CFN_STACK" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ.json new file mode 100644 index 0000000000000..1f1a144803dcd --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "version": "21.0.0", + "testCases": { + "integ.application-associator.all-stacks-association": { + "stacks": [ + "integ-servicecatalogappregistry-application" + ], + "diffAssets": false, + "stackUpdateWorkflow": true + } + }, + "synthContext": {}, + "enableLookups": false +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.assets.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.assets.json new file mode 100644 index 0000000000000..65c6d2c1ecf64 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc": { + "source": { + "path": "integservicecatalogappregistryapplicationresourcesStack4399A149.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.template.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.template.json new file mode 100644 index 0000000000000..ecc817b74774a --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/integservicecatalogappregistryapplicationresourcesStack4399A149.template.json @@ -0,0 +1,48 @@ +{ + "Resources": { + "AppRegistryAssociation": { + "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "Properties": { + "Application": "AppRegistryAssociatedApplication", + "Resource": { + "Ref": "AWS::StackId" + }, + "ResourceType": "CFN_STACK" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..65db06b047d68 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/manifest.json @@ -0,0 +1,209 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "integservicecatalogappregistryapplicationresourcesStack4399A149.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integservicecatalogappregistryapplicationresourcesStack4399A149.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integservicecatalogappregistryapplicationresourcesStack4399A149": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integservicecatalogappregistryapplicationresourcesStack4399A149.template.json", + "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}/19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integservicecatalogappregistryapplicationresourcesStack4399A149.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": [ + "ApplicationAssociatorStack", + "integservicecatalogappregistryapplicationresourcesStack4399A149.assets" + ], + "metadata": { + "/integ-servicecatalogappregistry-application/resourcesStack": [ + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + }, + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + } + ], + "/integ-servicecatalogappregistry-application/resourcesStack/AppRegistryAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRegistryAssociation" + } + ], + "/integ-servicecatalogappregistry-application/resourcesStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-servicecatalogappregistry-application/resourcesStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-servicecatalogappregistry-application/resourcesStack" + }, + "integ-servicecatalogappregistry-application.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-servicecatalogappregistry-application.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-servicecatalogappregistry-application": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-servicecatalogappregistry-application.template.json", + "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}/19dd33f3c17e59cafd22b9459b0a8d9bedbd42252737fedb06b2bcdbcf7809cc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-servicecatalogappregistry-application.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": [ + "ApplicationAssociatorStack", + "integ-servicecatalogappregistry-application.assets" + ], + "metadata": { + "/integ-servicecatalogappregistry-application": [ + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + }, + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + } + ], + "/integ-servicecatalogappregistry-application/AppRegistryAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRegistryAssociation" + } + ], + "/integ-servicecatalogappregistry-application/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-servicecatalogappregistry-application/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-servicecatalogappregistry-application" + }, + "ApplicationAssociatorStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ApplicationAssociatorStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ApplicationAssociatorStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ApplicationAssociatorStack.template.json", + "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}/4285054f947789e255e76c75b889b3b216adabb0b3f990c8966c18459cdf7b35.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ApplicationAssociatorStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + }, + "stackName": "AppRegistryApplicationAssociatorStack" + }, + "dependencies": [ + "ApplicationAssociatorStack.assets" + ], + "metadata": { + "/ApplicationAssociatorStack": [ + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + }, + { + "type": "aws:cdk:warning", + "data": "Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack." + } + ], + "/ApplicationAssociatorStack/DefaultCdkApplication/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DefaultCdkApplication4573D5A3" + } + ], + "/ApplicationAssociatorStack/AppRegistryAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRegistryAssociation" + } + ], + "/ApplicationAssociatorStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ApplicationAssociatorStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ApplicationAssociatorStack" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/tree.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/tree.json new file mode 100644 index 0000000000000..078cc92093b86 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.all-stacks-association.integ.snapshot/tree.json @@ -0,0 +1,143 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.95" + } + }, + "integ-servicecatalogappregistry-application": { + "id": "integ-servicecatalogappregistry-application", + "path": "integ-servicecatalogappregistry-application", + "children": { + "resourcesStack": { + "id": "resourcesStack", + "path": "integ-servicecatalogappregistry-application/resourcesStack", + "children": { + "AppRegistryAssociation": { + "id": "AppRegistryAssociation", + "path": "integ-servicecatalogappregistry-application/resourcesStack/AppRegistryAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "aws:cdk:cloudformation:props": { + "application": "AppRegistryAssociatedApplication", + "resource": { + "Ref": "AWS::StackId" + }, + "resourceType": "CFN_STACK" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.CfnResourceAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "AppRegistryAssociation": { + "id": "AppRegistryAssociation", + "path": "integ-servicecatalogappregistry-application/AppRegistryAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "aws:cdk:cloudformation:props": { + "application": "AppRegistryAssociatedApplication", + "resource": { + "Ref": "AWS::StackId" + }, + "resourceType": "CFN_STACK" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.CfnResourceAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "RegisterCdkApplication": { + "id": "RegisterCdkApplication", + "path": "RegisterCdkApplication", + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.ApplicationAssociator", + "version": "0.0.0" + } + }, + "ApplicationAssociatorStack": { + "id": "ApplicationAssociatorStack", + "path": "ApplicationAssociatorStack", + "children": { + "DefaultCdkApplication": { + "id": "DefaultCdkApplication", + "path": "ApplicationAssociatorStack/DefaultCdkApplication", + "children": { + "Resource": { + "id": "Resource", + "path": "ApplicationAssociatorStack/DefaultCdkApplication/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ServiceCatalogAppRegistry::Application", + "aws:cdk:cloudformation:props": { + "name": "AppRegistryAssociatedApplication", + "description": "Testing AppRegistry ApplicationAssociator" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.CfnApplication", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.Application", + "version": "0.0.0" + } + }, + "AppRegistryAssociation": { + "id": "AppRegistryAssociation", + "path": "ApplicationAssociatorStack/AppRegistryAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation", + "aws:cdk:cloudformation:props": { + "application": { + "Fn::GetAtt": [ + "DefaultCdkApplication4573D5A3", + "Id" + ] + }, + "resource": { + "Ref": "AWS::StackId" + }, + "resourceType": "CFN_STACK" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-servicecatalogappregistry.CfnResourceAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.test.ts new file mode 100644 index 0000000000000..de64c0c35b68b --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.test.ts @@ -0,0 +1,196 @@ +import { Annotations, Template } from '@aws-cdk/assertions'; +import * as codecommit from '@aws-cdk/aws-codecommit'; +import * as cdk from '@aws-cdk/core'; +import * as codepipeline from '@aws-cdk/pipelines'; +import { Construct } from 'constructs'; +import * as appreg from '../lib'; + +describe('Scope based Associations with Application within Same Account', () => { + let app: cdk.App; + beforeEach(() => { + app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + }); + test('ApplicationAssociator will associate allStacks created inside cdkApp', () => { + new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + const anotherStack = new AppRegistrySampleStack(app, 'SampleStack'); + Template.fromStack(anotherStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(anotherStack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: 'MyAssociatedApplication', + Resource: { Ref: 'AWS::StackId' }, + }); + }); +}); +describe('Scope based Associations with Application with Cross Region/Account', () => { + let app: cdk.App; + beforeEach(() => { + app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + }); + test('ApplicationAssociator in cross-account associates all stacks created inside cdk app', () => { + new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + const firstStack = new cdk.Stack(app, 'testStack', { + env: { account: 'account2', region: 'region' }, + }); + const nestedStack = new cdk.Stack(firstStack, 'MyFirstStack', { + env: { account: 'account2', region: 'region' }, + }); + Template.fromStack(firstStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(nestedStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + }); + + test('ApplicationAssociator creation failed when neither Application name nor ARN is provided', () => { + expect(() => { + new appreg.ApplicationAssociator(app, 'MyApplication', { + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + }).toThrow(/Please provide either ARN or application name./); + }); + + test('associate resource on imported application', () => { + const resource = new cdk.Stack(app, 'MyStack'); + + new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationArnValue: 'arn:aws:servicecatalog:us-east-1:482211128593:/applications/0a17wtxeg5vilok0sbxfozwpq9', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + + Template.fromStack(resource).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: '0a17wtxeg5vilok0sbxfozwpq9', + Resource: { Ref: 'AWS::StackId' }, + }); + }), + + test('ApplicationAssociator with cross region stacks inside cdkApp throws error', () => { + new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + env: { account: 'account2', region: 'region2' }, + }, + }); + + const crossRegionStack = new cdk.Stack(app, 'crossRegionStack', { + env: { account: 'account', region: 'region' }, + }); + Annotations.fromStack(crossRegionStack).hasError('*', 'AppRegistry does not support cross region associations. Application region region2, stack region region'); + }); + + test('Environment Agnostic ApplicationAssociator with cross region stacks inside cdkApp gives warning', () => { + new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + + const crossRegionStack = new cdk.Stack(app, 'crossRegionStack', { + env: { account: 'account', region: 'region' }, + }); + Annotations.fromStack(crossRegionStack).hasWarning('*', 'Environment agnostic stack determined, AppRegistry association might not work as expected in case you deploy cross-region or cross-account stack.'); + }); + + test('Cdk App Containing Pipeline with stage but stage not associated throws error', () => { + const application = new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + const pipelineStack = new AppRegistrySampleCodePipelineStack(app, 'PipelineStackA', { + application: application, + associateStage: false, + }); + app.synth(); + Annotations.fromStack(pipelineStack).hasError('*', + 'Associate Stage: SampleStage to ensure all stacks in your cdk app are associated with AppRegistry. You can use ApplicationAssociator.associateStage to associate any stage.'); + }); + + test('Cdk App Containing Pipeline with stage and stage associated successfully gets synthesized', () => { + const application = new appreg.ApplicationAssociator(app, 'MyApplication', { + applicationName: 'MyAssociatedApplication', + stackProps: { + stackName: 'MyAssociatedApplicationStack', + }, + }); + const pipelineStack = new AppRegistrySampleCodePipelineStack(app, 'PipelineStackA', { + application: application, + associateStage: true, + }); + app.synth(); + Template.fromStack(pipelineStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + }); +}); + +interface AppRegistrySampleCodePipelineStackProps extends cdk.StackProps { + application: appreg.ApplicationAssociator; + associateStage: boolean; +} + +class AppRegistrySampleCodePipelineStack extends cdk.Stack { + public constructor(scope: Construct, id: string, props: AppRegistrySampleCodePipelineStackProps ) { + super(scope, id, props); + const repo = new codecommit.Repository(this, 'Repo', { + repositoryName: 'MyRepo', + }); + + const pipeline = new codepipeline.CodePipeline(this, 'Pipeline', { + pipelineName: 'MyPipeline', + synth: new codepipeline.CodeBuildStep('SynthStep', { + input: codepipeline.CodePipelineSource.codeCommit(repo, 'main'), + installCommands: [ + 'npm install -g aws-cdk', + ], + commands: [ + 'npm ci', + 'npm run build', + 'npx cdk synth', + ], + }, + ), + }); + + const stage = new AppRegistrySampleStage( + this, + 'SampleStage', + ); + + if (props.associateStage) { + props.application.associateStage(stage); + } + pipeline.addStage(stage); + } +} + +class AppRegistrySampleStage extends cdk.Stage { + public constructor(scope: Construct, id: string, props?: cdk.StageProps) { + super(scope, id, props); + new AppRegistrySampleStack(this, 'SampleStack', {}); + } +} + +class AppRegistrySampleStack extends cdk.Stack { + public constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + } +} diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts index 33f1ca2628cdb..dce0d1147ec44 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts @@ -1,11 +1,11 @@ -import { Template } from '@aws-cdk/assertions'; +import { Annotations, Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; import * as appreg from '../lib'; describe('Application', () => { let stack: cdk.Stack; - beforeEach(() => { const app = new cdk.App({ context: { @@ -207,6 +207,20 @@ describe('Application', () => { }); }), + test('associate resource on imported application', () => { + const resource = new cdk.Stack(stack, 'MyStack'); + + const importedApplication = appreg.Application.fromApplicationArn(stack, 'ImportedApplication', + 'arn:aws:servicecatalog:us-east-1:123456789012:/applications/0bqmvxvgmry0ecc4mjhwypun6i'); + + importedApplication.associateStack(resource); + + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: '0bqmvxvgmry0ecc4mjhwypun6i', + Resource: { 'Fn::ImportValue': 'MyStack:ExportsOutputRefAWSStackIdB2DD5BAA' }, + }); + }), + test('duplicate resource assocations are idempotent', () => { const resource = new cdk.Stack(stack, 'MyStack'); @@ -324,3 +338,116 @@ describe('Application', () => { }); }); }); + +describe('Scope based Associations with Application within Same Account', () => { + let stack: cdk.Stack; + let app: cdk.App; + beforeEach(() => { + app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app, 'cdkApplication'); + }); + + test('Associate Stage in same account will associate allStacks Inside it', () => { + const application = new appreg.Application(stack, 'MyApplication', { + applicationName: 'MyApplication', + }); + const stage = new cdk.Stage(stack, 'MyStage'); + const stageStack = new cdk.Stack(stage, 'MyStack'); + application.associateAllStacksInScope(stage); + expect(stageStack.stackName).toEqual('MyStage-MyStack'); + Template.fromStack(stageStack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: 'MyApplication', + Resource: { Ref: 'AWS::StackId' }, + }); + }); + + + test('Associate Stack in same account will associate allStacks Inside it', () => { + const application = new appreg.Application(stack, 'MyApplication', { + applicationName: 'MyApplication', + }); + + const anotherStack = new AppRegistrySampleStack(app, 'SampleStack'); + application.associateAllStacksInScope(app); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(anotherStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: { 'Fn::GetAtt': ['MyApplication5C63EC1D', 'Id'] }, + Resource: { Ref: 'AWS::StackId' }, + }); + Template.fromStack(anotherStack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: 'MyApplication', + Resource: { Ref: 'AWS::StackId' }, + }); + }); +}); + +describe('Scope based Associations with Application with Cross Region/Account', () => { + let stack: cdk.Stack; + let app: cdk.App; + beforeEach(() => { + app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app, 'CdkApplication', { + env: { account: 'account', region: 'region' }, + }); + }); + + test('associateAllStacksInScope in cross-account associates all stacks from the context passed', () => { + const application = new appreg.Application(stack, 'MyApplication', { + applicationName: 'MyApplication', + }); + const firstStack = new cdk.Stack(app, 'testStack', { + env: { account: 'account2', region: 'region' }, + }); + const nestedStack = new cdk.Stack(firstStack, 'MyFirstStack', { + env: { account: 'account2', region: 'region' }, + }); + application.associateAllStacksInScope(app); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(firstStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(nestedStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + }); + + test('Associate Stage in cross account association will associate allStacks Inside it', () => { + const application = new appreg.Application(stack, 'MyApplication', { + applicationName: 'MyApplication', + }); + const stage = new cdk.Stage(app, 'MyStage', { + env: { account: 'account2', region: 'region' }, + }); + const stageStack = new cdk.Stack(stage, 'MyStack'); + application.associateAllStacksInScope(stage); + Template.fromStack(stageStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(stageStack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Application: 'MyApplication', + Resource: { Ref: 'AWS::StackId' }, + }); + }); + + test('Associate Stage in cross region throw error', () => { + const application = new appreg.Application(stack, 'MyApplication', { + applicationName: 'MyApplication', + }); + const stage = new cdk.Stage(stack, 'MyStage', { + env: { account: 'account1', region: 'region1' }, + }); + const stageStack = new cdk.Stack(stage, 'MyStack'); + application.associateAllStacksInScope(stage); + Annotations.fromStack(stageStack).hasError('*', + 'AppRegistry does not support cross region associations. Application region region, stack region region1'); + }); +}); + +class AppRegistrySampleStack extends cdk.Stack { + public constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + } +} diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application-associator.all-stacks-association.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application-associator.all-stacks-association.ts new file mode 100644 index 0000000000000..afd822dc6dc16 --- /dev/null +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application-associator.all-stacks-association.ts @@ -0,0 +1,20 @@ +/// !cdk-integ integ-servicecatalogappregistry-application +import * as cdk from '@aws-cdk/core'; +import * as appreg from '../lib'; + + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-servicecatalogappregistry-application'); + + +new appreg.ApplicationAssociator(app, 'RegisterCdkApplication', { + applicationName: 'AppRegistryAssociatedApplication', + description: 'Testing AppRegistry ApplicationAssociator', + stackProps: { + stackName: 'AppRegistryApplicationAssociatorStack', + }, +}); + +new cdk.Stack(stack, 'resourcesStack'); + +app.synth(); diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts index 3d9acff2d2a65..ce55f1778265a 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts @@ -40,14 +40,14 @@ export class SqsSubscription implements sns.ITopicSubscription { // add a statement to the queue resource policy which allows this topic // to send messages to the queue. - this.queue.addToResourcePolicy(new iam.PolicyStatement({ + const queuePolicyDependable = this.queue.addToResourcePolicy(new iam.PolicyStatement({ resources: [this.queue.queueArn], actions: ['sqs:SendMessage'], principals: [snsServicePrincipal], conditions: { ArnEquals: { 'aws:SourceArn': topic.topicArn }, }, - })); + })).policyDependable; // if the queue is encrypted, add a statement to the key resource policy // which allows this topic to decrypt KMS keys @@ -77,6 +77,7 @@ export class SqsSubscription implements sns.ITopicSubscription { filterPolicy: this.props.filterPolicy, region: this.regionFromArn(topic), deadLetterQueue: this.props.deadLetterQueue, + subscriptionDependency: queuePolicyDependable, }; } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/sns-sqs.lit.integ.snapshot/aws-cdk-sns-sqs.template.json b/packages/@aws-cdk/aws-sns-subscriptions/test/sns-sqs.lit.integ.snapshot/aws-cdk-sns-sqs.template.json index 35da3fc55b6d7..0abd3a705bc75 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/sns-sqs.lit.integ.snapshot/aws-cdk-sns-sqs.template.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/sns-sqs.lit.integ.snapshot/aws-cdk-sns-sqs.template.json @@ -1,205 +1,206 @@ { - "Resources": { - "MyTopic86869434": { - "Type": "AWS::SNS::Topic" - }, - "EncryptionMasterKey5BD393B9": { - "Type": "AWS::KMS::Key", - "Properties": { - "KeyPolicy": { - "Statement": [ - { - "Action": "kms:*", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" + "Resources": { + "MyTopic86869434": { + "Type": "AWS::SNS::Topic" + }, + "EncryptionMasterKey5BD393B9": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] ] - ] - } - }, - "Resource": "*" - }, - { - "Action": [ - "kms:Decrypt", - "kms:GenerateDataKey" - ], - "Condition": { - "ArnEquals": { - "aws:SourceArn": { - "Ref": "MyTopic86869434" } - } - }, - "Effect": "Allow", - "Principal": { - "Service": "sns.amazonaws.com" + }, + "Resource": "*" }, - "Resource": "*" - } - ], - "Version": "2012-10-17" - } + { + "Action": [ + "kms:Decrypt", + "kms:GenerateDataKey" + ], + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Ref": "MyTopic86869434" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" - }, - "MyQueueE6CA6235": { - "Type": "AWS::SQS::Queue", - "Properties": { - "KmsMasterKeyId": { - "Fn::GetAtt": [ - "EncryptionMasterKey5BD393B9", - "Arn" - ] - } + "MyQueueE6CA6235": { + "Type": "AWS::SQS::Queue", + "Properties": { + "KmsMasterKeyId": { + "Fn::GetAtt": [ + "EncryptionMasterKey5BD393B9", + "Arn" + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "MyQueuePolicy6BBEDDAC": { - "Type": "AWS::SQS::QueuePolicy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sqs:SendMessage", - "Condition": { - "ArnEquals": { - "aws:SourceArn": { - "Ref": "MyTopic86869434" + "MyQueuePolicy6BBEDDAC": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Ref": "MyTopic86869434" + } } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "MyQueueE6CA6235", + "Arn" + ] } - }, - "Effect": "Allow", - "Principal": { - "Service": "sns.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "MyQueueE6CA6235", - "Arn" - ] } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "MyQueueE6CA6235" } - ], - "Version": "2012-10-17" - }, - "Queues": [ - { - "Ref": "MyQueueE6CA6235" - } - ] - } - }, - "MyQueueawscdksnssqsMyTopic9361DEA223429051": { - "Type": "AWS::SNS::Subscription", - "Properties": { - "Protocol": "sqs", - "TopicArn": { - "Ref": "MyTopic86869434" - }, - "Endpoint": { - "Fn::GetAtt": [ - "MyQueueE6CA6235", - "Arn" ] - }, - "RedrivePolicy": { - "deadLetterTargetArn": { + } + }, + "MyQueueawscdksnssqsMyTopic9361DEA223429051": { + "DependsOn": "MyQueuePolicy6BBEDDAC", + "Type": "AWS::SNS::Subscription", + "Properties": { + "Protocol": "sqs", + "TopicArn": { + "Ref": "MyTopic86869434" + }, + "Endpoint": { "Fn::GetAtt": [ - "DeadLetterQueue9F481546", + "MyQueueE6CA6235", "Arn" ] + }, + "RedrivePolicy": { + "deadLetterTargetArn": { + "Fn::GetAtt": [ + "DeadLetterQueue9F481546", + "Arn" + ] + } } } - } - }, - "DeadLetterQueue9F481546": { - "Type": "AWS::SQS::Queue", - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "DeadLetterQueuePolicyB1FB890C": { - "Type": "AWS::SQS::QueuePolicy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sqs:SendMessage", - "Condition": { - "ArnEquals": { - "aws:SourceArn": { - "Ref": "MyTopic86869434" + }, + "DeadLetterQueue9F481546": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "DeadLetterQueuePolicyB1FB890C": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Ref": "MyTopic86869434" + } } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "DeadLetterQueue9F481546", + "Arn" + ] } - }, - "Effect": "Allow", - "Principal": { - "Service": "sns.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "DeadLetterQueue9F481546", - "Arn" - ] } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "DeadLetterQueue9F481546" } - ], - "Version": "2012-10-17" - }, - "Queues": [ + ] + } + } + }, + "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": [ { - "Ref": "DeadLetterQueue9F481546" + "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." } ] } } - }, - "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 + } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns/lib/subscriber.ts b/packages/@aws-cdk/aws-sns/lib/subscriber.ts index a52ee834cab11..34753caf09c2f 100644 --- a/packages/@aws-cdk/aws-sns/lib/subscriber.ts +++ b/packages/@aws-cdk/aws-sns/lib/subscriber.ts @@ -1,4 +1,4 @@ -import { Construct } from 'constructs'; +import { Construct, IDependable } from 'constructs'; import { SubscriptionOptions } from './subscription'; import { ITopic } from './topic-base'; @@ -24,6 +24,15 @@ export interface TopicSubscriptionConfig extends SubscriptionOptions { * subscribing to. */ readonly subscriberId: string; + + /** + * The resources that need to be created before the subscription can be safely created. + * For example for SQS subscription, the subscription needs to have a dependency on the SQS queue policy + * in order for the subscription to successfully deliver messages. + * + * @default - empty list + */ + readonly subscriptionDependency?: IDependable; } /** diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 01a12275d7bb0..4ace7453d7c67 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -80,8 +80,8 @@ export abstract class TopicBase extends Resource implements ITopic { /** * Subscribe some endpoint to this topic */ - public addSubscription(subscription: ITopicSubscription): Subscription { - const subscriptionConfig = subscription.bind(this); + public addSubscription(topicSubscription: ITopicSubscription): Subscription { + const subscriptionConfig = topicSubscription.bind(this); const scope = subscriptionConfig.subscriberScope || this; let id = subscriptionConfig.subscriberId; @@ -95,10 +95,18 @@ export abstract class TopicBase extends Resource implements ITopic { throw new Error(`A subscription with id "${id}" already exists under the scope ${scope.node.path}`); } - return new Subscription(scope, id, { + const subscription = new Subscription(scope, id, { topic: this, ...subscriptionConfig, }); + + // Add dependency for the subscription, for example for SQS subscription + // the queue policy has to deploy before the subscription is created + if (subscriptionConfig.subscriptionDependency) { + subscription.node.addDependency(subscriptionConfig.subscriptionDependency); + } + + return subscription; } /** diff --git a/packages/@aws-cdk/aws-sqs/README.md b/packages/@aws-cdk/aws-sqs/README.md index 11dbb164e5c56..191eb4e6a7c6e 100644 --- a/packages/@aws-cdk/aws-sqs/README.md +++ b/packages/@aws-cdk/aws-sqs/README.md @@ -37,9 +37,16 @@ new sqs.Queue(this, 'Queue'); ## Encryption -If you want to encrypt the queue contents, set the `encryption` property. You can have -the messages encrypted with a key that SQS manages for you, or a key that you -can manage yourself. +By default queues are encrypted using SSE-SQS. If you want to change the encryption mode, set the `encryption` property. +The following encryption modes are supported: + +* KMS key that SQS manages for you +* KMS key that you can managed yourself +* Server-side encryption managed by SQS (SSE-SQS) +* Unencrypted + +To learn more about SSE-SQS on Amazon SQS, please visit the +[Amazon SQS documentation](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html). ```ts // Use managed key @@ -54,6 +61,16 @@ new sqs.Queue(this, 'Queue', { encryption: sqs.QueueEncryption.KMS, encryptionMasterKey: myKey, }); + +// Use SQS managed server side encryption (SSE-SQS) +new sqs.Queue(this, 'Queue', { + encryption: sqs.QueueEncryption.SQS_MANAGED, +}); + +// Unencrypted queue +new sqs.Queue(this, 'Queue', { + encryption: sqs.QueueEncryption.UNENCRYPTED, +}); ``` ## First-In-First-Out (FIFO) queues diff --git a/packages/@aws-cdk/aws-sqs/lib/queue.ts b/packages/@aws-cdk/aws-sqs/lib/queue.ts index 980185f5b7810..4cb972782e03a 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue.ts @@ -87,12 +87,12 @@ export interface QueueProps { * Be aware that encryption is not available in all regions, please see the docs * for current availability details. * - * @default Unencrypted + * @default SQS_MANAGED (SSE-SQS) for newly created queues */ readonly encryption?: QueueEncryption; /** - * External KMS master key to use for queue encryption. + * External KMS key to use for queue encryption. * * Individual messages will be encrypted using data keys. The data keys in * turn will be encrypted using this key, and reused for a maximum of @@ -196,9 +196,9 @@ export enum QueueEncryption { UNENCRYPTED = 'NONE', /** - * Server-side KMS encryption with a master key managed by SQS. + * Server-side KMS encryption with a KMS key managed by SQS. */ - KMS_MANAGED = 'MANAGED', + KMS_MANAGED = 'KMS_MANAGED', /** * Server-side encryption with a KMS key managed by the user. @@ -206,6 +206,14 @@ export enum QueueEncryption { * If `encryptionKey` is specified, this key will be used, otherwise, one will be defined. */ KMS = 'KMS', + + /** + * Server-side encryption key managed by SQS (SSE-SQS). + * + * To learn more about SSE-SQS on Amazon SQS, please visit the + * [Amazon SQS documentation](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html). + */ + SQS_MANAGED = 'SQS_MANAGED' } /** @@ -369,16 +377,28 @@ export class Queue extends QueueBase { this.deadLetterQueue = props.deadLetterQueue; function _determineEncryptionProps(this: Queue): { encryptionProps: EncryptionProps, encryptionMasterKey?: kms.IKey } { - let encryption = props.encryption || QueueEncryption.UNENCRYPTED; + let encryption = props.encryption; + + if (encryption === QueueEncryption.SQS_MANAGED && props.encryptionMasterKey) { + throw new Error("'encryptionMasterKey' is not supported if encryption type 'SQS_MANAGED' is used"); + } if (encryption !== QueueEncryption.KMS && props.encryptionMasterKey) { encryption = QueueEncryption.KMS; // KMS is implied by specifying an encryption key } - if (encryption === QueueEncryption.UNENCRYPTED) { + if (!encryption) { return { encryptionProps: {} }; } + if (encryption === QueueEncryption.UNENCRYPTED) { + return { + encryptionProps: { + sqsManagedSseEnabled: false, + }, + }; + } + if (encryption === QueueEncryption.KMS_MANAGED) { return { encryptionProps: { @@ -402,6 +422,14 @@ export class Queue extends QueueBase { }; } + if (encryption === QueueEncryption.SQS_MANAGED) { + return { + encryptionProps: { + sqsManagedSseEnabled: true, + }, + }; + } + throw new Error(`Unexpected 'encryptionType': ${encryption}`); } } @@ -459,4 +487,5 @@ interface FifoProps { interface EncryptionProps { readonly kmsMasterKeyId?: string; readonly kmsDataKeyReusePeriodSeconds?: number; + readonly sqsManagedSseEnabled?: boolean; } diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index 04f5057ddb54f..496e349f6dd42 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -83,6 +83,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/aws-sqs/test/integ.sqs.ts b/packages/@aws-cdk/aws-sqs/test/integ.sqs.ts index 76c51a0e99cc6..b8e085da4f7cd 100644 --- a/packages/@aws-cdk/aws-sqs/test/integ.sqs.ts +++ b/packages/@aws-cdk/aws-sqs/test/integ.sqs.ts @@ -1,6 +1,7 @@ import { AccountRootPrincipal, Role } from '@aws-cdk/aws-iam'; import { Key } from '@aws-cdk/aws-kms'; import { App, CfnOutput, RemovalPolicy, Stack } from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; import { DeduplicationScope, FifoThroughputLimit, Queue, QueueEncryption } from '../lib'; const app = new App(); @@ -21,6 +22,12 @@ const highThroughputFifo = new Queue(stack, 'HighThroughputFifoQueue', { fifoThroughputLimit: FifoThroughputLimit.PER_MESSAGE_GROUP_ID, deduplicationScope: DeduplicationScope.MESSAGE_GROUP, }); +const sqsManagedEncryptedQueue = new Queue(stack, 'SqsManagedEncryptedQueue', { + encryption: QueueEncryption.SQS_MANAGED, +}); +const unencryptedQueue = new Queue(stack, 'UnencryptedQueue', { + encryption: QueueEncryption.UNENCRYPTED, +}); const role = new Role(stack, 'Role', { assumedBy: new AccountRootPrincipal(), @@ -30,7 +37,13 @@ dlq.grantConsumeMessages(role); queue.grantConsumeMessages(role); fifo.grantConsumeMessages(role); highThroughputFifo.grantConsumeMessages(role); +sqsManagedEncryptedQueue.grantConsumeMessages(role); +unencryptedQueue.grantConsumeMessages(role); new CfnOutput(stack, 'QueueUrl', { value: queue.queueUrl }); +new integ.IntegTest(app, 'SqsTest', { + testCases: [stack], +}); + app.synth(); diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.assets.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.assets.json new file mode 100644 index 0000000000000..92ee85c509105 --- /dev/null +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "SqsTestDefaultTestDeployAssert659366A6.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.template.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/SqsTestDefaultTestDeployAssert659366A6.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.assets.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.assets.json index 3c90c25fc43af..0dc8fd0e3462b 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.assets.json +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "11bd38722e879ee3efdf98cf177f0af6442195bb308e1bde662147a30bf350ed": { + "a660932c356f8eec80b4314b041c64311fd29803603b65a95351137afa8eba04": { "source": { "path": "aws-cdk-sqs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "11bd38722e879ee3efdf98cf177f0af6442195bb308e1bde662147a30bf350ed.json", + "objectKey": "a660932c356f8eec80b4314b041c64311fd29803603b65a95351137afa8eba04.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.template.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.template.json index 88ddbe5512edd..a9fd362411f47 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.template.json +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/aws-cdk-sqs.template.json @@ -81,6 +81,22 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "SqsManagedEncryptedQueue587679B3": { + "Type": "AWS::SQS::Queue", + "Properties": { + "SqsManagedSseEnabled": true + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "UnencryptedQueue57F92F9C": { + "Type": "AWS::SQS::Queue", + "Properties": { + "SqsManagedSseEnabled": false + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "Role1ABCC5F0": { "Type": "AWS::IAM::Role", "Properties": { @@ -151,6 +167,18 @@ "Queue4A7E3555", "Arn" ] + }, + { + "Fn::GetAtt": [ + "SqsManagedEncryptedQueue587679B3", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "UnencryptedQueue57F92F9C", + "Arn" + ] } ] }, diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/integ.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/integ.json index 8fe8a05ed0a46..ef3f2c6411212 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/integ.json +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { - "integ.sqs": { + "SqsTest/DefaultTest": { "stacks": [ "aws-cdk-sqs" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "SqsTest/DefaultTest/DeployAssert", + "assertionStackName": "SqsTestDefaultTestDeployAssert659366A6" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/manifest.json index a12dec654d926..bcb8e707ddd5f 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { "Tree": { "type": "cdk:tree", @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/11bd38722e879ee3efdf98cf177f0af6442195bb308e1bde662147a30bf350ed.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a660932c356f8eec80b4314b041c64311fd29803603b65a95351137afa8eba04.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -69,6 +69,18 @@ "data": "HighThroughputFifoQueue40A0EEE4" } ], + "/aws-cdk-sqs/SqsManagedEncryptedQueue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SqsManagedEncryptedQueue587679B3" + } + ], + "/aws-cdk-sqs/UnencryptedQueue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "UnencryptedQueue57F92F9C" + } + ], "/aws-cdk-sqs/Role/Resource": [ { "type": "aws:cdk:logicalId", @@ -101,6 +113,53 @@ ] }, "displayName": "aws-cdk-sqs" + }, + "SqsTestDefaultTestDeployAssert659366A6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SqsTestDefaultTestDeployAssert659366A6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SqsTestDefaultTestDeployAssert659366A6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SqsTestDefaultTestDeployAssert659366A6.template.json", + "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": [ + "SqsTestDefaultTestDeployAssert659366A6.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": [ + "SqsTestDefaultTestDeployAssert659366A6.assets" + ], + "metadata": { + "/SqsTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SqsTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SqsTest/DefaultTest/DeployAssert" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/tree.json b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/tree.json index 2f6fa70734df1..fe1731181527c 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-sqs/test/sqs.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.108" } }, "aws-cdk-sqs": { @@ -178,6 +178,54 @@ "version": "0.0.0" } }, + "SqsManagedEncryptedQueue": { + "id": "SqsManagedEncryptedQueue", + "path": "aws-cdk-sqs/SqsManagedEncryptedQueue", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-sqs/SqsManagedEncryptedQueue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": { + "sqsManagedSseEnabled": true + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.Queue", + "version": "0.0.0" + } + }, + "UnencryptedQueue": { + "id": "UnencryptedQueue", + "path": "aws-cdk-sqs/UnencryptedQueue", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-sqs/UnencryptedQueue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": { + "sqsManagedSseEnabled": false + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.Queue", + "version": "0.0.0" + } + }, "Role": { "id": "Role", "path": "aws-cdk-sqs/Role", @@ -267,6 +315,18 @@ "Queue4A7E3555", "Arn" ] + }, + { + "Fn::GetAtt": [ + "SqsManagedEncryptedQueue587679B3", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "UnencryptedQueue57F92F9C", + "Arn" + ] } ] }, @@ -312,20 +372,56 @@ "id": "QueueUrl", "path": "aws-cdk-sqs/QueueUrl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "SqsTest": { + "id": "SqsTest", + "path": "SqsTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "SqsTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "SqsTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.108" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "SqsTest/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/test/sqs.test.ts b/packages/@aws-cdk/aws-sqs/test/sqs.test.ts index 6a4d5fda6c02c..8e599ff356f42 100644 --- a/packages/@aws-cdk/aws-sqs/test/sqs.test.ts +++ b/packages/@aws-cdk/aws-sqs/test/sqs.test.ts @@ -429,6 +429,54 @@ describe('queue encryption', () => { }, }); }); + + test('it is possible to use sqs managed server side encryption', () => { + const stack = new Stack(); + + new sqs.Queue(stack, 'Queue', { encryption: sqs.QueueEncryption.SQS_MANAGED }); + Template.fromStack(stack).templateMatches({ + 'Resources': { + 'Queue4A7E3555': { + 'Type': 'AWS::SQS::Queue', + 'Properties': { + 'SqsManagedSseEnabled': true, + }, + 'UpdateReplacePolicy': 'Delete', + 'DeletionPolicy': 'Delete', + }, + }, + }); + }); + + test('it is possible to disable encryption (unencrypted)', () => { + const stack = new Stack(); + + new sqs.Queue(stack, 'Queue', { encryption: sqs.QueueEncryption.UNENCRYPTED }); + Template.fromStack(stack).templateMatches({ + 'Resources': { + 'Queue4A7E3555': { + 'Type': 'AWS::SQS::Queue', + 'Properties': { + 'SqsManagedSseEnabled': false, + }, + 'UpdateReplacePolicy': 'Delete', + 'DeletionPolicy': 'Delete', + }, + }, + }); + }); + + test('encryptionMasterKey is not supported if encryption type SQS_MANAGED is used', () => { + // GIVEN + const stack = new Stack(); + const key = new kms.Key(stack, 'CustomKey'); + + // THEN + expect(() => new sqs.Queue(stack, 'Queue', { + encryption: sqs.QueueEncryption.SQS_MANAGED, + encryptionMasterKey: key, + })).toThrow(/'encryptionMasterKey' is not supported if encryption type 'SQS_MANAGED' is used/); + }); }); test('test ".fifo" suffixed queues register as fifo', () => { diff --git a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.bundle/index.js b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js similarity index 88% rename from packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.bundle/index.js rename to packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js index 09ec17c1ae178..a9e7e7241efc7 100644 --- a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.bundle/index.js +++ b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle/index.js @@ -1,3 +1,4 @@ +"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; @@ -403,20 +404,11 @@ var CustomResourceHandler = class { } async handle() { try { - console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: "..." })}`); const response = await this.processEvent(this.event.ResourceProperties); - console.log(`Event output : ${JSON.stringify(response)}`); - await this.respond({ - status: "SUCCESS", - reason: "OK", - data: response - }); + return response; } catch (e) { console.log(e); - await this.respond({ - status: "FAILED", - reason: e.message ?? "Internal Error" - }); + throw e; } finally { clearTimeout(this.timeout); } @@ -478,7 +470,8 @@ var AssertionHandler = class extends CustomResourceHandler { matchResult.finished(); if (matchResult.hasFailed()) { result = { - data: JSON.stringify({ + failed: true, + assertion: JSON.stringify({ status: "fail", message: [ ...matchResult.toHumanStrings(), @@ -487,11 +480,11 @@ var AssertionHandler = class extends CustomResourceHandler { }) }; if (request2.failDeployment) { - throw new Error(result.data); + throw new Error(result.assertion); } } else { result = { - data: JSON.stringify({ + assertion: JSON.stringify({ status: "success" }) }; @@ -561,7 +554,10 @@ function flatten(object) { {}, ...function _flatten(child, path = []) { return [].concat(...Object.keys(child).map((key) => { - const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + let childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + if (typeof childKey === "string") { + childKey = isJsonString(childKey); + } return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; })); }(object) @@ -571,6 +567,9 @@ var AwsApiCallHandler = class extends CustomResourceHandler { async processEvent(request2) { const AWS = require("aws-sdk"); console.log(`AWS SDK VERSION: ${AWS.VERSION}`); + if (!Object.prototype.hasOwnProperty.call(AWS, request2.service)) { + throw Error(`Service ${request2.service} does not exist in AWS SDK version ${AWS.VERSION}.`); + } const service = new AWS[request2.service](); const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); console.log(`SDK response received ${JSON.stringify(response)}`); @@ -581,9 +580,18 @@ var AwsApiCallHandler = class extends CustomResourceHandler { const flatData = { ...flatten(respond) }; - return request2.flattenResponse === "true" ? flatData : respond; + const resp = request2.flattenResponse === "true" ? flatData : respond; + console.log(`Returning result ${JSON.stringify(resp)}`); + return resp; } }; +function isJsonString(value) { + try { + return JSON.parse(value); + } catch { + return value; + } +} // lib/assertions/providers/lambda-handler/types.ts var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; @@ -591,18 +599,68 @@ var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; // lib/assertions/providers/lambda-handler/index.ts async function handler(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); const provider = createResourceHandler(event, context); - await provider.handle(); + try { + if (event.RequestType === "Delete") { + await provider.respond({ + status: "SUCCESS", + reason: "OK" + }); + return; + } + const result = await provider.handle(); + const actualPath = event.ResourceProperties.actualPath; + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + if ("expected" in event.ResourceProperties) { + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + try { + const assertionResult = await assertion.handle(); + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: { + ...assertionResult, + ...result + } + }); + return; + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + return; } function createResourceHandler(event, context) { if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { return new AwsApiCallHandler(event, context); - } - switch (event.ResourceType) { - case ASSERT_RESOURCE_TYPE: - return new AssertionHandler(event, context); - default: - throw new Error(`Unsupported resource type "${event.ResourceType}`); + } else if (event.ResourceType.startsWith(ASSERT_RESOURCE_TYPE)) { + return new AssertionHandler(event, context); + } else { + throw new Error(`Unsupported resource type "${event.ResourceType}`); } } // Annotate the CommonJS export names for ESM import in node: diff --git a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/manifest.json index aa707e00f12e8..d8e0de9e54959 100644 --- a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/manifest.json @@ -178,7 +178,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ff1de129c8ab3914f9a0758b9422b50fdbd43f6a61767dc5391e7b08231cdc6f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3fdd4225944766d24a4a35fa88db2febd8e7f28bd8ea992c8972583ca24d0b9a.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -201,16 +201,10 @@ "data": "AwsApiCallSSMgetParameters" } ], - "/ssm-string-param/DefaultTest/DeployAssert/AwsApiCallSSMgetParameters/AssertEqualsSSMgetParameters/Default/Default": [ + "/ssm-string-param/DefaultTest/DeployAssert/AwsApiCallSSMgetParameters/AssertionResults": [ { "type": "aws:cdk:logicalId", - "data": "AwsApiCallSSMgetParametersAssertEqualsSSMgetParametersE460052D" - } - ], - "/ssm-string-param/DefaultTest/DeployAssert/AwsApiCallSSMgetParameters/AssertEqualsSSMgetParameters/AssertionResults": [ - { - "type": "aws:cdk:logicalId", - "data": "AssertionResultsAssertEqualsSSMgetParameters" + "data": "AssertionResultsAwsApiCallSSMgetParameters" } ], "/ssm-string-param/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ diff --git a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.assets.json b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.assets.json index 78772a19bf4c0..edc04ad32c05b 100644 --- a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.assets.json +++ b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.assets.json @@ -1,20 +1,20 @@ { "version": "21.0.0", "files": { - "2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72": { + "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb": { "source": { - "path": "asset.2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.bundle", + "path": "asset.d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.bundle", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.zip", + "objectKey": "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "ff1de129c8ab3914f9a0758b9422b50fdbd43f6a61767dc5391e7b08231cdc6f": { + "3fdd4225944766d24a4a35fa88db2febd8e7f28bd8ea992c8972583ca24d0b9a": { "source": { "path": "ssmstringparamDefaultTestDeployAssert9C612E37.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "ff1de129c8ab3914f9a0758b9422b50fdbd43f6a61767dc5391e7b08231cdc6f.json", + "objectKey": "3fdd4225944766d24a4a35fa88db2febd8e7f28bd8ea992c8972583ca24d0b9a.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.template.json b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.template.json index e5af2645c54fc..f0328cc7a02d6 100644 --- a/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.template.json +++ b/packages/@aws-cdk/aws-ssm/test/list-parameter.integ.snapshot/ssmstringparamDefaultTestDeployAssert9C612E37.template.json @@ -11,6 +11,7 @@ }, "service": "SSM", "api": "getParameters", + "expected": "{\"$ObjectLike\":{\"Parameters\":{\"$ArrayWith\":[{\"$ObjectLike\":{\"Value\":\"value1,value2\"}},{\"$ObjectLike\":{\"Value\":\"value1,value2\"}},{\"$ObjectLike\":{\"Value\":\"value1,value2\"}}]}}}", "parameters": { "Names": [ { @@ -25,28 +26,7 @@ ] }, "flattenResponse": "false", - "salt": "1661970076677" - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "AwsApiCallSSMgetParametersAssertEqualsSSMgetParametersE460052D": { - "Type": "Custom::DeployAssert@AssertEquals", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", - "Arn" - ] - }, - "actual": { - "Fn::GetAtt": [ - "AwsApiCallSSMgetParameters", - "apiCallResponse" - ] - }, - "expected": "{\"$ObjectLike\":{\"Parameters\":{\"$ArrayWith\":[{\"$ObjectLike\":{\"Value\":\"value1,value2\"}},{\"$ObjectLike\":{\"Value\":\"value1,value2\"}},{\"$ObjectLike\":{\"Value\":\"value1,value2\"}}]}}}", - "salt": "1661970076678" + "salt": "1663960575818" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -100,7 +80,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "2a53dc40a7dae81c8850e125ab49e5f55d80b7b8ceac86976f2a4119393cab72.zip" + "S3Key": "d47f7e6772bfdf47ecbc070ffe204baf53bacbfbf7814eb407bd8ea108c1c1bb.zip" }, "Timeout": 120, "Handler": "index.handler", @@ -114,11 +94,11 @@ } }, "Outputs": { - "AssertionResultsAssertEqualsSSMgetParameters": { + "AssertionResultsAwsApiCallSSMgetParameters": { "Value": { "Fn::GetAtt": [ - "AwsApiCallSSMgetParametersAssertEqualsSSMgetParametersE460052D", - "data" + "AwsApiCallSSMgetParameters", + "assertion" ] } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts index ba3f68b95abb1..9918535134c67 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts @@ -106,7 +106,15 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { 's3:ListBucketMultipartUploads', 's3:ListMultipartUploadParts', 's3:PutObject'], - resources: [this.props.resultConfiguration?.outputLocation?.bucketName ? `arn:aws:s3:::${this.props.resultConfiguration?.outputLocation?.bucketName}/${this.props.resultConfiguration?.outputLocation?.objectKey}/*` : '*'], // Need S3 location where data is stored or Athena throws an Unable to verify/create output bucket https://docs.aws.amazon.com/athena/latest/ug/security-iam-athena.html + resources: [ + this.props.resultConfiguration?.outputLocation?.bucketName + ? cdk.Stack.of(this).formatArn({ + service: 's3', + resource: this.props.resultConfiguration?.outputLocation?.bucketName, + resourceName: this.props.resultConfiguration?.outputLocation?.objectKey, + }) + : '*', + ], }), ); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/emrcontainers/start-job-run.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/emrcontainers/start-job-run.ts index 02de5afaf5a4a..8671caefe9a96 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/emrcontainers/start-job-run.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/emrcontainers/start-job-run.ts @@ -210,12 +210,12 @@ export class EmrContainersStartJobRun extends sfn.TaskStateBase implements iam.I } private validateEntryPointArguments (entryPointArguments:sfn.TaskInput) { - if (typeof entryPointArguments.value === 'string' && !sfn.JsonPath.isEncodedJsonPath(entryPointArguments.value)) { - throw new Error(`Entry point arguments must be a string array or encoded JSON path, but received a non JSON path string'); - .`); - } - if (!this.isArrayOfStrings(entryPointArguments.value)) { - throw new Error(`Entry point arguments must be a string array or encoded JSON path but received ${typeof entryPointArguments.value}.`); + if (typeof entryPointArguments.value === 'string') { + if (!sfn.JsonPath.isEncodedJsonPath(entryPointArguments.value)) { + throw new Error('Entry point arguments must be a string array or an encoded JSON path, but received a non JSON path string'); + } + } else if (!this.isArrayOfStrings(entryPointArguments.value)) { + throw new Error(`Entry point arguments must be a string array or an encoded JSON path but received ${typeof entryPointArguments.value}.`); } } @@ -280,7 +280,10 @@ export class EmrContainersStartJobRun extends sfn.TaskStateBase implements iam.I jobExecutionRole.addToPrincipalPolicy( new iam.PolicyStatement({ resources: [ - 'arn:aws:logs:*:*:*', + cdk.Stack.of(this).formatArn({ + service: 'logs', + resource: '*', + }), ], actions: [ 'logs:DescribeLogGroups', @@ -301,7 +304,10 @@ export class EmrContainersStartJobRun extends sfn.TaskStateBase implements iam.I this.role.addToPrincipalPolicy( new iam.PolicyStatement({ resources: [ - 'arn:aws:logs:*:*:*', + cdk.Stack.of(this).formatArn({ + service: 'logs', + resource: '*', + }), ], actions: [ 'logs:DescribeLogGroups', diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts index c2936afc2d751..6b3c24b62a045 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts @@ -1,3 +1,4 @@ +import { Template, Match } from '@aws-cdk/assertions'; import * as sfn from '@aws-cdk/aws-stepfunctions'; import * as cdk from '@aws-cdk/core'; import { AthenaStartQueryExecution, EncryptionOption } from '../../lib/athena/start-query-execution'; @@ -174,4 +175,62 @@ describe('Start Query Execution', () => { // THEN expect(stack.resolve(task.toStateJson())).not.toHaveProperty('Parameters.QueryExecutionContext'); }); + + test('bucket arn is formatted as expected in generated policy', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE database', + clientRequestToken: 'unique-client-request-token', + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + }); + + new sfn.StateMachine(stack, 'StateMachine', { + definition: task, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + { + Action: [ + 's3:AbortMultipartUpload', + 's3:ListBucketMultipartUploads', + 's3:ListMultipartUploadParts', + 's3:PutObject', + ], + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':query-results-bucket/folder', + ], + ], + }, + }, + ]), + }), + }); + }); }); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip index cd5a78b26d045..5e88259eaadf5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip index 2b20e7052c639..b51c0dcc7d103 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip index ac6ffb77173eb..dee385f9daf4d 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.assets.json deleted file mode 100644 index 4b513a320626b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.assets.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "version": "21.0.0", - "files": { - "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee": { - "source": { - "path": "asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6": { - "source": { - "path": "asset.2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671": { - "source": { - "path": "asset.3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb": { - "source": { - "path": "asset.d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc": { - "source": { - "path": "asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed": { - "source": { - "path": "asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "7898fbcc6db6b68c168938b50e8d56a7d18b11f8ae6ec9a35bf6066ce31bd5f1": { - "source": { - "path": "awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderA10A0351.nested.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7898fbcc6db6b68c168938b50e8d56a7d18b11f8ae6ec9a35bf6066ce31bd5f1.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "54df503311a78fbc844bf698bbfa009360873e3953c9e41259dd5f7dec3a4f25": { - "source": { - "path": "awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProvider97EB2B07.nested.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "54df503311a78fbc844bf698bbfa009360873e3953c9e41259dd5f7dec3a4f25.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "5df06a818955e286053e36b052b26b0a585b1f9203624e95f1eeda1411934709": { - "source": { - "path": "aws-stepfunctions-tasks-emr-containers-all-services-integ.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "5df06a818955e286053e36b052b26b0a585b1f9203624e95f1eeda1411934709.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - } - }, - "dockerImages": {} -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.template.json deleted file mode 100644 index d91f2d8266cdd..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-integ.template.json +++ /dev/null @@ -1,1564 +0,0 @@ -{ - "Resources": { - "integrationtesteksclusterDefaultVpc395E1A86": { - "Type": "AWS::EC2::VPC", - "Properties": { - "CidrBlock": "10.0.0.0/16", - "EnableDnsHostnames": true, - "EnableDnsSupport": true, - "InstanceTenancy": "default", - "Tags": [ - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.0.0/18", - "MapPublicIpOnLaunch": true, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Public" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Public" - }, - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - } - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - }, - "AllocationId": { - "Fn::GetAtt": [ - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "AllocationId" - ] - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.64.0/18", - "MapPublicIpOnLaunch": true, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Public" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Public" - }, - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - } - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - }, - "AllocationId": { - "Fn::GetAtt": [ - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "AllocationId" - ] - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52" - ] - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.128.0/18", - "MapPublicIpOnLaunch": false, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Private" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Private" - }, - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PrivateSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PrivateSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "NatGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.192.0/18", - "MapPublicIpOnLaunch": false, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Private" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Private" - }, - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PrivateSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc/PrivateSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "NatGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761" - } - } - }, - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F": { - "Type": "AWS::EC2::InternetGateway", - "Properties": { - "Tags": [ - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-all-services-integ/integration-test-eks-cluster/DefaultVpc" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204": { - "Type": "AWS::EC2::VPCGatewayAttachment", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "InternetGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - } - }, - "integrationtesteksclusterRole03F70AF0": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "eks.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKSClusterPolicy" - ] - ] - } - ] - } - }, - "integrationtesteksclusterControlPlaneSecurityGroup6E92F333": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "EKS Control Plane Security Group", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - } - } - }, - "integrationtesteksclusterCreationRoleB98FE02A": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "iam:PassRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "integrationtesteksclusterRole03F70AF0", - "Arn" - ] - } - }, - { - "Action": [ - "eks:CreateCluster", - "eks:DescribeCluster", - "eks:DescribeUpdate", - "eks:DeleteCluster", - "eks:UpdateClusterVersion", - "eks:UpdateClusterConfig", - "eks:CreateFargateProfile", - "eks:TagResource", - "eks:UntagResource" - ], - "Effect": "Allow", - "Resource": [ - "*" - ] - }, - { - "Action": [ - "eks:DescribeFargateProfile", - "eks:DeleteFargateProfile" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "iam:GetRole", - "iam:listAttachedRolePolicies" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": "iam:CreateServiceLinkedRole", - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeNetworkInterfaces", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeRouteTables", - "ec2:DescribeDhcpOptions", - "ec2:DescribeVpcs" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "Roles": [ - { - "Ref": "integrationtesteksclusterCreationRoleB98FE02A" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterE5C0ED98": { - "Type": "Custom::AWSCDK-EKS-Cluster", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", - "Outputs.awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderframeworkonEventFF3F425BArn" - ] - }, - "Config": { - "version": "1.21", - "roleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterRole03F70AF0", - "Arn" - ] - }, - "resourcesVpcConfig": { - "subnetIds": [ - { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - ], - "securityGroupIds": [ - { - "Fn::GetAtt": [ - "integrationtesteksclusterControlPlaneSecurityGroup6E92F333", - "GroupId" - ] - } - ], - "endpointPublicAccess": true, - "endpointPrivateAccess": true - } - }, - "AssumeRoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "AttributesRevision": 2 - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204", - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "integrationtesteksclusterCreationRoleB98FE02A" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0": { - "Type": "AWS::SSM::Parameter", - "Properties": { - "Type": "String", - "Value": "aws:cdk:eks:kubectl-ready" - }, - "DependsOn": [ - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "integrationtesteksclusterCreationRoleB98FE02A", - "integrationtesteksclusterE5C0ED98" - ] - }, - "integrationtesteksclusterMastersRole63B9B0BF": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "integrationtesteksclusterAwsAuthmanifestAEF9C6DF": { - "Type": "Custom::AWSCDK-EKS-KubernetesResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", - "Outputs.awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProviderframeworkonEvent3B33A326Arn" - ] - }, - "Manifest": { - "Fn::Join": [ - "", - [ - "[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"aws-auth\",\"namespace\":\"kube-system\",\"labels\":{\"aws.cdk.eks/prune-c89f1e1be2a935f1b46af591dd13f7d1a5d084570d\":\"\"}},\"data\":{\"mapRoles\":\"[{\\\"rolearn\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - }, - "\\\",\\\"username\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - }, - "\\\",\\\"groups\\\":[\\\"system:masters\\\"]},{\\\"rolearn\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7", - "Arn" - ] - }, - "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]}]\",\"mapUsers\":\"[]\",\"mapAccounts\":\"[]\"}}]" - ] - ] - }, - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "RoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "PruneLabel": "aws.cdk.eks/prune-c89f1e1be2a935f1b46af591dd13f7d1a5d084570d", - "Overwrite": true - }, - "DependsOn": [ - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "ec2.", - { - "Ref": "AWS::URLSuffix" - } - ] - ] - } - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKSWorkerNodePolicy" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKS_CNI_Policy" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - ] - ] - } - ] - } - }, - "integrationtesteksclusterNodegroupDefaultCapacity536CF32C": { - "Type": "AWS::EKS::Nodegroup", - "Properties": { - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "NodeRole": { - "Fn::GetAtt": [ - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7", - "Arn" - ] - }, - "Subnets": [ - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - ], - "AmiType": "AL2_x86_64", - "ForceUpdateEnabled": true, - "InstanceTypes": [ - "m5.xlarge" - ], - "ScalingConfig": { - "DesiredSize": 3, - "MaxSize": 3, - "MinSize": 3 - } - } - }, - "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454": { - "Type": "AWS::CloudFormation::Stack", - "Properties": { - "TemplateURL": { - "Fn::Join": [ - "", - [ - "https://s3.", - { - "Ref": "AWS::Region" - }, - ".", - { - "Ref": "AWS::URLSuffix" - }, - "/", - { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "/7898fbcc6db6b68c168938b50e8d56a7d18b11f8ae6ec9a35bf6066ce31bd5f1.json" - ] - ] - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - } - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B": { - "Type": "AWS::CloudFormation::Stack", - "Properties": { - "TemplateURL": { - "Fn::Join": [ - "", - [ - "https://s3.", - { - "Ref": "AWS::Region" - }, - ".", - { - "Ref": "AWS::URLSuffix" - }, - "/", - { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "/54df503311a78fbc844bf698bbfa009360873e3953c9e41259dd5f7dec3a4f25.json" - ] - ] - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterE5C0ED98", - "Arn" - ] - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetFBC220C4Ref": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet7E4A5E3BRef": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EClusterSecurityGroupId": { - "Fn::GetAtt": [ - "integrationtesteksclusterE5C0ED98", - "ClusterSecurityGroupId" - ] - } - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "JobExecutionRoleF19B4342": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "emr-containers.amazonaws.com" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "JobExecutionRolePolicy6968CCB9": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - "s3:DeleteObject*", - "s3:PutObject", - "s3:PutObjectLegalHold", - "s3:PutObjectRetention", - "s3:PutObjectTagging", - "s3:PutObjectVersionTagging", - "s3:Abort*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "StartaJobRunMonitoringBucket899C33D9", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "StartaJobRunMonitoringBucket899C33D9", - "Arn" - ] - }, - "/*" - ] - ] - } - ] - }, - { - "Action": [ - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "StartaJobRunMonitoringLogGroupD033B7AF", - "Arn" - ] - } - }, - { - "Action": "logs:DescribeLogStreams", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "StartaJobRunMonitoringLogGroupD033B7AF", - "Arn" - ] - } - }, - { - "Action": "logs:DescribeLogGroups", - "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "JobExecutionRolePolicy6968CCB9", - "Roles": [ - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "/", - { - "Fn::Select": [ - 5, - { - "Fn::Split": [ - ":", - { - "Fn::GetAtt": [ - "JobExecutionRoleF19B4342", - "Arn" - ] - } - ] - } - ] - } - ] - } - ] - } - ] - } - }, - "StartaJobRunMonitoringLogGroupD033B7AF": { - "Type": "AWS::Logs::LogGroup", - "Properties": { - "RetentionInDays": 731 - }, - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" - }, - "StartaJobRunMonitoringBucket899C33D9": { - "Type": "AWS::S3::Bucket", - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" - }, - "StateMachineRoleB840431D": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "StateMachineRoleDefaultPolicyDF1E6607": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "emr-containers:CreateVirtualCluster", - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": "iam:CreateServiceLinkedRole", - "Condition": { - "StringLike": { - "iam:AWSServiceName": "emr-containers.amazonaws.com" - } - }, - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":role/aws-service-role/emr-containers.amazonaws.com/AWSServiceRoleForAmazonEMRContainers" - ] - ] - } - }, - { - "Action": "emr-containers:StartJobRun", - "Condition": { - "StringEquals": { - "emr-containers:ExecutionRoleArn": { - "Fn::GetAtt": [ - "JobExecutionRoleF19B4342", - "Arn" - ] - } - } - }, - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":emr-containers:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":/virtualclusters/*" - ] - ] - } - }, - { - "Action": [ - "emr-containers:DescribeJobRun", - "emr-containers:CancelJobRun" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":emr-containers:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":/virtualclusters/*" - ] - ] - } - }, - { - "Action": "emr-containers:DeleteVirtualCluster", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":emr-containers:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":/virtualclusters/*" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", - "Roles": [ - { - "Ref": "StateMachineRoleB840431D" - } - ] - } - }, - "StateMachine2E01A3A5": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{\"StartAt\":\"Create a virtual Cluster\",\"States\":{\"Create a virtual Cluster\":{\"Next\":\"Start a Job Run\",\"Type\":\"Task\",\"ResultPath\":\"$.cluster\",\"Resource\":\"arn:", - { - "Ref": "AWS::Partition" - }, - ":states:::emr-containers:createVirtualCluster\",\"Parameters\":{\"Name\":\"Virtual-Cluster-Name\",\"ContainerProvider\":{\"Id\":\"", - { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "\",\"Info\":{\"EksInfo\":{\"Namespace\":\"default\"}},\"Type\":\"EKS\"}}},\"Start a Job Run\":{\"Next\":\"Delete a Virtual Cluster\",\"Type\":\"Task\",\"ResultPath\":\"$.job\",\"Resource\":\"arn:", - { - "Ref": "AWS::Partition" - }, - ":states:::emr-containers:startJobRun.sync\",\"Parameters\":{\"VirtualClusterId.$\":\"$.cluster.Id\",\"Name\":\"EMR-Containers-Job\",\"ExecutionRoleArn\":\"", - { - "Fn::GetAtt": [ - "JobExecutionRoleF19B4342", - "Arn" - ] - }, - "\",\"ReleaseLabel\":\"emr-6.2.0-latest\",\"JobDriver\":{\"SparkSubmitJobDriver\":{\"EntryPoint\":\"local:///usr/lib/spark/examples/src/main/python/pi.py\",\"EntryPointArguments\":[\"2\"],\"SparkSubmitParameters\":\"--conf spark.driver.memory=512M --conf spark.kubernetes.driver.request.cores=0.2 --conf spark.kubernetes.executor.request.cores=0.2 --conf spark.sql.shuffle.partitions=60 --conf spark.dynamicAllocation.enabled=false\"}},\"ConfigurationOverrides\":{\"ApplicationConfiguration\":[{\"Classification\":\"spark-defaults\",\"Properties\":{\"spark.executor.instances\":\"1\",\"spark.executor.memory\":\"512M\"}}],\"MonitoringConfiguration\":{\"CloudWatchMonitoringConfiguration\":{\"LogGroupName\":\"", - { - "Ref": "StartaJobRunMonitoringLogGroupD033B7AF" - }, - "\"},\"PersistentAppUI\":\"ENABLED\",\"S3MonitoringConfiguration\":{\"LogUri\":\"s3://", - { - "Ref": "StartaJobRunMonitoringBucket899C33D9" - }, - "\"}}}}},\"Delete a Virtual Cluster\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", - { - "Ref": "AWS::Partition" - }, - ":states:::emr-containers:deleteVirtualCluster\",\"Parameters\":{\"Id.$\":\"$.job.VirtualClusterId\"}}},\"TimeoutSeconds\":1200}" - ] - ] - } - }, - "DependsOn": [ - "StateMachineRoleDefaultPolicyDF1E6607", - "StateMachineRoleB840431D" - ] - } - }, - "Outputs": { - "integrationtesteksclusterConfigCommandFA814999": { - "Value": { - "Fn::Join": [ - "", - [ - "aws eks update-kubeconfig --name ", - { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - " --region ", - { - "Ref": "AWS::Region" - }, - " --role-arn ", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - } - ] - ] - } - }, - "integrationtesteksclusterGetTokenCommandD7B92682": { - "Value": { - "Fn::Join": [ - "", - [ - "aws eks get-token --cluster-name ", - { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - " --region ", - { - "Ref": "AWS::Region" - }, - " --role-arn ", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - } - ] - ] - } - }, - "stateMachineArn": { - "Value": { - "Ref": "StateMachine2E01A3A5" - } - } - }, - "Mappings": { - "ServiceprincipalMap": { - "af-south-1": { - "states": "states.af-south-1.amazonaws.com" - }, - "ap-east-1": { - "states": "states.ap-east-1.amazonaws.com" - }, - "ap-northeast-1": { - "states": "states.ap-northeast-1.amazonaws.com" - }, - "ap-northeast-2": { - "states": "states.ap-northeast-2.amazonaws.com" - }, - "ap-northeast-3": { - "states": "states.ap-northeast-3.amazonaws.com" - }, - "ap-south-1": { - "states": "states.ap-south-1.amazonaws.com" - }, - "ap-southeast-1": { - "states": "states.ap-southeast-1.amazonaws.com" - }, - "ap-southeast-2": { - "states": "states.ap-southeast-2.amazonaws.com" - }, - "ap-southeast-3": { - "states": "states.ap-southeast-3.amazonaws.com" - }, - "ca-central-1": { - "states": "states.ca-central-1.amazonaws.com" - }, - "cn-north-1": { - "states": "states.cn-north-1.amazonaws.com" - }, - "cn-northwest-1": { - "states": "states.cn-northwest-1.amazonaws.com" - }, - "eu-central-1": { - "states": "states.eu-central-1.amazonaws.com" - }, - "eu-north-1": { - "states": "states.eu-north-1.amazonaws.com" - }, - "eu-south-1": { - "states": "states.eu-south-1.amazonaws.com" - }, - "eu-south-2": { - "states": "states.eu-south-2.amazonaws.com" - }, - "eu-west-1": { - "states": "states.eu-west-1.amazonaws.com" - }, - "eu-west-2": { - "states": "states.eu-west-2.amazonaws.com" - }, - "eu-west-3": { - "states": "states.eu-west-3.amazonaws.com" - }, - "me-south-1": { - "states": "states.me-south-1.amazonaws.com" - }, - "sa-east-1": { - "states": "states.sa-east-1.amazonaws.com" - }, - "us-east-1": { - "states": "states.us-east-1.amazonaws.com" - }, - "us-east-2": { - "states": "states.us-east-2.amazonaws.com" - }, - "us-gov-east-1": { - "states": "states.us-gov-east-1.amazonaws.com" - }, - "us-gov-west-1": { - "states": "states.us-gov-west-1.amazonaws.com" - }, - "us-iso-east-1": { - "states": "states.amazonaws.com" - }, - "us-iso-west-1": { - "states": "states.amazonaws.com" - }, - "us-isob-east-1": { - "states": "states.amazonaws.com" - }, - "us-west-1": { - "states": "states.us-west-1.amazonaws.com" - }, - "us-west-2": { - "states": "states.us-west-2.amazonaws.com" - } - } - }, - "Parameters": { - "BootstrapVersion": { - "Type": "AWS::SSM::Parameter::Value", - "Default": "/cdk-bootstrap/hnb659fds/version", - "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" - } - }, - "Rules": { - "CheckBootstrapVersion": { - "Assertions": [ - { - "Assert": { - "Fn::Not": [ - { - "Fn::Contains": [ - [ - "1", - "2", - "3", - "4", - "5" - ], - { - "Ref": "BootstrapVersion" - } - ] - } - ] - }, - "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." - } - ] - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json index 2bccc08e57400..042373f52e796 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json @@ -105,7 +105,7 @@ } } }, - "c662f656c61c4a82cb951b84c3fe536eb062ff48b73d70adf502cb20d7f4f046": { + "229a1b96384e2842cbf330c28b09b649d8739fc5697fe7e3b375e9a90b007bb0": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-all-services-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c662f656c61c4a82cb951b84c3fe536eb062ff48b73d70adf502cb20d7f4f046.json", + "objectKey": "229a1b96384e2842cbf330c28b09b649d8739fc5697fe7e3b375e9a90b007bb0.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json index a1ca42923b6dd..3a3637306c5ad 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json @@ -1093,7 +1093,26 @@ { "Action": "logs:DescribeLogGroups", "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } } ], "Version": "2012-10-17" diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderA10A0351.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderA10A0351.nested.template.json deleted file mode 100644 index dbddc28f421b1..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderA10A0351.nested.template.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "Resources": { - "NodeProxyAgentLayer924C1971": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip" - }, - "Description": "/opt/nodejs/node_modules/proxy-agent" - } - }, - "OnEventHandlerServiceRole15A26729": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "OnEventHandlerServiceRoleDefaultPolicyC57085D4": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "OnEventHandlerServiceRoleDefaultPolicyC57085D4", - "Roles": [ - { - "Ref": "OnEventHandlerServiceRole15A26729" - } - ] - } - }, - "OnEventHandler42BEBAE0": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip" - }, - "Role": { - "Fn::GetAtt": [ - "OnEventHandlerServiceRole15A26729", - "Arn" - ] - }, - "Description": "onEvent handler for EKS cluster resource provider", - "Environment": { - "Variables": { - "AWS_STS_REGIONAL_ENDPOINTS": "regional" - } - }, - "Handler": "index.onEvent", - "Layers": [ - { - "Ref": "NodeProxyAgentLayer924C1971" - } - ], - "Runtime": "nodejs14.x", - "Timeout": 60 - }, - "DependsOn": [ - "OnEventHandlerServiceRoleDefaultPolicyC57085D4", - "OnEventHandlerServiceRole15A26729" - ] - }, - "IsCompleteHandlerServiceRole5810CC58": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B", - "Roles": [ - { - "Ref": "IsCompleteHandlerServiceRole5810CC58" - } - ] - } - }, - "IsCompleteHandler7073F4DA": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip" - }, - "Role": { - "Fn::GetAtt": [ - "IsCompleteHandlerServiceRole5810CC58", - "Arn" - ] - }, - "Description": "isComplete handler for EKS cluster resource provider", - "Environment": { - "Variables": { - "AWS_STS_REGIONAL_ENDPOINTS": "regional" - } - }, - "Handler": "index.isComplete", - "Layers": [ - { - "Ref": "NodeProxyAgentLayer924C1971" - } - ], - "Runtime": "nodejs14.x", - "Timeout": 60 - }, - "DependsOn": [ - "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B", - "IsCompleteHandlerServiceRole5810CC58" - ] - }, - "ProviderframeworkonEventServiceRole9FF04296": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "states:StartExecution", - "Effect": "Allow", - "Resource": { - "Ref": "Providerwaiterstatemachine5D4A9DF0" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "Roles": [ - { - "Ref": "ProviderframeworkonEventServiceRole9FF04296" - } - ] - } - }, - "ProviderframeworkonEvent83C1D0A7": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonEventServiceRole9FF04296", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onEvent (aws-stepfunctions-tasks-emr-containers-all-services-integ/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - "WAITER_STATE_MACHINE_ARN": { - "Ref": "Providerwaiterstatemachine5D4A9DF0" - } - } - }, - "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "ProviderframeworkonEventServiceRole9FF04296" - ] - }, - "ProviderframeworkisCompleteServiceRoleB1087139": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC", - "Roles": [ - { - "Ref": "ProviderframeworkisCompleteServiceRoleB1087139" - } - ] - } - }, - "ProviderframeworkisComplete26D7B0CB": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkisCompleteServiceRoleB1087139", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - isComplete (aws-stepfunctions-tasks-emr-containers-all-services-integ/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - } - } - }, - "Handler": "framework.isComplete", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC", - "ProviderframeworkisCompleteServiceRoleB1087139" - ] - }, - "ProviderframeworkonTimeoutServiceRole28643D26": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F", - "Roles": [ - { - "Ref": "ProviderframeworkonTimeoutServiceRole28643D26" - } - ] - } - }, - "ProviderframeworkonTimeout0B47CA38": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonTimeoutServiceRole28643D26", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onTimeout (aws-stepfunctions-tasks-emr-containers-all-services-integ/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - } - } - }, - "Handler": "framework.onTimeout", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F", - "ProviderframeworkonTimeoutServiceRole28643D26" - ] - }, - "ProviderwaiterstatemachineRole0C7159F9": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A", - "Roles": [ - { - "Ref": "ProviderwaiterstatemachineRole0C7159F9" - } - ] - } - }, - "Providerwaiterstatemachine5D4A9DF0": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{\"StartAt\":\"framework-isComplete-task\",\"States\":{\"framework-isComplete-task\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":60,\"MaxAttempts\":60,\"BackoffRate\":1}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"framework-onTimeout-task\"}],\"Type\":\"Task\",\"Resource\":\"", - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - "\"},\"framework-onTimeout-task\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"", - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - "\"}}}" - ] - ] - }, - "RoleArn": { - "Fn::GetAtt": [ - "ProviderwaiterstatemachineRole0C7159F9", - "Arn" - ] - } - }, - "DependsOn": [ - "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A", - "ProviderwaiterstatemachineRole0C7159F9" - ] - } - }, - "Mappings": { - "ServiceprincipalMap": { - "af-south-1": { - "states": "states.af-south-1.amazonaws.com" - }, - "ap-east-1": { - "states": "states.ap-east-1.amazonaws.com" - }, - "ap-northeast-1": { - "states": "states.ap-northeast-1.amazonaws.com" - }, - "ap-northeast-2": { - "states": "states.ap-northeast-2.amazonaws.com" - }, - "ap-northeast-3": { - "states": "states.ap-northeast-3.amazonaws.com" - }, - "ap-south-1": { - "states": "states.ap-south-1.amazonaws.com" - }, - "ap-southeast-1": { - "states": "states.ap-southeast-1.amazonaws.com" - }, - "ap-southeast-2": { - "states": "states.ap-southeast-2.amazonaws.com" - }, - "ap-southeast-3": { - "states": "states.ap-southeast-3.amazonaws.com" - }, - "ca-central-1": { - "states": "states.ca-central-1.amazonaws.com" - }, - "cn-north-1": { - "states": "states.cn-north-1.amazonaws.com" - }, - "cn-northwest-1": { - "states": "states.cn-northwest-1.amazonaws.com" - }, - "eu-central-1": { - "states": "states.eu-central-1.amazonaws.com" - }, - "eu-north-1": { - "states": "states.eu-north-1.amazonaws.com" - }, - "eu-south-1": { - "states": "states.eu-south-1.amazonaws.com" - }, - "eu-south-2": { - "states": "states.eu-south-2.amazonaws.com" - }, - "eu-west-1": { - "states": "states.eu-west-1.amazonaws.com" - }, - "eu-west-2": { - "states": "states.eu-west-2.amazonaws.com" - }, - "eu-west-3": { - "states": "states.eu-west-3.amazonaws.com" - }, - "me-south-1": { - "states": "states.me-south-1.amazonaws.com" - }, - "sa-east-1": { - "states": "states.sa-east-1.amazonaws.com" - }, - "us-east-1": { - "states": "states.us-east-1.amazonaws.com" - }, - "us-east-2": { - "states": "states.us-east-2.amazonaws.com" - }, - "us-gov-east-1": { - "states": "states.us-gov-east-1.amazonaws.com" - }, - "us-gov-west-1": { - "states": "states.us-gov-west-1.amazonaws.com" - }, - "us-iso-east-1": { - "states": "states.amazonaws.com" - }, - "us-iso-west-1": { - "states": "states.amazonaws.com" - }, - "us-isob-east-1": { - "states": "states.amazonaws.com" - }, - "us-west-1": { - "states": "states.us-west-1.amazonaws.com" - }, - "us-west-2": { - "states": "states.us-west-2.amazonaws.com" - } - } - }, - "Outputs": { - "awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksClusterResourceProviderframeworkonEventFF3F425BArn": { - "Value": { - "Fn::GetAtt": [ - "ProviderframeworkonEvent83C1D0A7", - "Arn" - ] - } - } - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn": { - "Type": "String" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProvider97EB2B07.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProvider97EB2B07.nested.template.json deleted file mode 100644 index 00fc1336486bb..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProvider97EB2B07.nested.template.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "Resources": { - "HandlerServiceRoleFCDC14AE": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - ] - ] - } - ] - } - }, - "HandlerServiceRoleDefaultPolicyCBD0CC91": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "eks:DescribeCluster", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EArn" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "HandlerServiceRoleDefaultPolicyCBD0CC91", - "Roles": [ - { - "Ref": "HandlerServiceRoleFCDC14AE" - } - ] - } - }, - "Handler886CB40B": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb.zip" - }, - "Role": { - "Fn::GetAtt": [ - "HandlerServiceRoleFCDC14AE", - "Arn" - ] - }, - "Description": "onEvent handler for EKS kubectl resource provider", - "Handler": "index.handler", - "Layers": [ - { - "Ref": "AwsCliLayerF44AAF94" - }, - { - "Ref": "KubectlLayer600207B5" - } - ], - "MemorySize": 1024, - "Runtime": "python3.7", - "Timeout": 900, - "VpcConfig": { - "SecurityGroupIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EClusterSecurityGroupId" - } - ], - "SubnetIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetFBC220C4Ref" - }, - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet7E4A5E3BRef" - } - ] - } - }, - "DependsOn": [ - "HandlerServiceRoleDefaultPolicyCBD0CC91", - "HandlerServiceRoleFCDC14AE" - ] - }, - "AwsCliLayerF44AAF94": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip" - }, - "Description": "/opt/awscli/aws" - } - }, - "KubectlLayer600207B5": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip" - }, - "Description": "/opt/kubectl/kubectl and /opt/helm/helm" - } - }, - "ProviderframeworkonEventServiceRole9FF04296": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "Roles": [ - { - "Ref": "ProviderframeworkonEventServiceRole9FF04296" - } - ] - } - }, - "ProviderframeworkonEvent83C1D0A7": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonEventServiceRole9FF04296", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onEvent (aws-stepfunctions-tasks-emr-containers-all-services-integ/@aws-cdk--aws-eks.KubectlProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - } - } - }, - "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", - "Timeout": 900, - "VpcConfig": { - "SecurityGroupIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EClusterSecurityGroupId" - } - ], - "SubnetIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetFBC220C4Ref" - }, - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet7E4A5E3BRef" - } - ] - } - }, - "DependsOn": [ - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "ProviderframeworkonEventServiceRole9FF04296" - ] - } - }, - "Outputs": { - "awsstepfunctionstasksemrcontainersallservicesintegawscdkawseksKubectlProviderframeworkonEvent3B33A326Arn": { - "Value": { - "Fn::GetAtt": [ - "ProviderframeworkonEvent83C1D0A7", - "Arn" - ] - } - } - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EArn": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterCreationRole78F8A91EArn": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetFBC220C4Ref": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet7E4A5E3BRef": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersallservicesintegintegrationtestekscluster4FFBB19EClusterSecurityGroupId": { - "Type": "String" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/manifest.json index b3491424494b3..0187031cf8440 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/manifest.json @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c662f656c61c4a82cb951b84c3fe536eb062ff48b73d70adf502cb20d7f4f046.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/229a1b96384e2842cbf330c28b09b649d8739fc5697fe7e3b375e9a90b007bb0.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/tree.json index 138f9448b6fed..60f2a7fb63c61 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/job-submission-workflow.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "aws-stepfunctions-tasks-emr-containers-all-services-test": { @@ -952,7 +952,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "KubectlReadyBarrier": { @@ -2386,7 +2386,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } } }, @@ -2473,7 +2473,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3143,7 +3143,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "JobExecutionRole": { @@ -3270,7 +3270,26 @@ { "Action": "logs:DescribeLogGroups", "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } } ], "Version": "2012-10-17" @@ -3659,7 +3678,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-all-services/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "DeployAssert": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip index cd5a78b26d045..5e88259eaadf5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip index 2b20e7052c639..b51c0dcc7d103 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip index ac6ffb77173eb..dee385f9daf4d 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.assets.json deleted file mode 100644 index f384d82b36be7..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.assets.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "version": "21.0.0", - "files": { - "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee": { - "source": { - "path": "asset.4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6": { - "source": { - "path": "asset.2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671": { - "source": { - "path": "asset.3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb": { - "source": { - "path": "asset.d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc": { - "source": { - "path": "asset.c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed": { - "source": { - "path": "asset.c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286": { - "source": { - "path": "asset.105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "de2da116e1de2db20dc2bc88a1e97df050dde2917a4122674e054e87ee53e334": { - "source": { - "path": "asset.de2da116e1de2db20dc2bc88a1e97df050dde2917a4122674e054e87ee53e334", - "packaging": "zip" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "de2da116e1de2db20dc2bc88a1e97df050dde2917a4122674e054e87ee53e334.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "e9aee046003806e01758c649a83bcecd108c5015299bfe2dcd5420c41ee8f115": { - "source": { - "path": "awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderB5D967DC.nested.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e9aee046003806e01758c649a83bcecd108c5015299bfe2dcd5420c41ee8f115.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "df7788eb8853ac792f558c2a91ce072f996448fc7c85114280f48690f53f285f": { - "source": { - "path": "awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderC26A0FC7.nested.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "df7788eb8853ac792f558c2a91ce072f996448fc7c85114280f48690f53f285f.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "b8f3c7427c2da58140cd8b04dcc8d2561dfcb41089839c4aeebd72d0fb807abe": { - "source": { - "path": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b8f3c7427c2da58140cd8b04dcc8d2561dfcb41089839c4aeebd72d0fb807abe.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - } - }, - "dockerImages": {} -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.template.json deleted file mode 100644 index e3f4fcde73a2f..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test.template.json +++ /dev/null @@ -1,1869 +0,0 @@ -{ - "Resources": { - "integrationtesteksclusterDefaultVpc395E1A86": { - "Type": "AWS::EC2::VPC", - "Properties": { - "CidrBlock": "10.0.0.0/16", - "EnableDnsHostnames": true, - "EnableDnsSupport": true, - "InstanceTenancy": "default", - "Tags": [ - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.0.0/18", - "MapPublicIpOnLaunch": true, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Public" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Public" - }, - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - } - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - }, - "AllocationId": { - "Fn::GetAtt": [ - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "AllocationId" - ] - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet1" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.64.0/18", - "MapPublicIpOnLaunch": true, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Public" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Public" - }, - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - } - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - }, - "AllocationId": { - "Fn::GetAtt": [ - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "AllocationId" - ] - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PublicSubnet2" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52" - ] - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.128.0/18", - "MapPublicIpOnLaunch": false, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Private" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Private" - }, - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PrivateSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PrivateSubnet1" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "NatGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8": { - "Type": "AWS::EC2::Subnet", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "AvailabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "CidrBlock": "10.0.192.0/18", - "MapPublicIpOnLaunch": false, - "Tags": [ - { - "Key": "aws-cdk:subnet-name", - "Value": "Private" - }, - { - "Key": "aws-cdk:subnet-type", - "Value": "Private" - }, - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PrivateSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903": { - "Type": "AWS::EC2::RouteTable", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/internal-elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc/PrivateSubnet2" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5": { - "Type": "AWS::EC2::SubnetRouteTableAssociation", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903" - }, - "SubnetId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - } - }, - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "NatGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761" - } - } - }, - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F": { - "Type": "AWS::EC2::InternetGateway", - "Properties": { - "Tags": [ - { - "Key": "Name", - "Value": "aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/integration-test-eks-cluster/DefaultVpc" - } - ] - } - }, - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204": { - "Type": "AWS::EC2::VPCGatewayAttachment", - "Properties": { - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - }, - "InternetGatewayId": { - "Ref": "integrationtesteksclusterDefaultVpcIGW9ADAFE6F" - } - } - }, - "integrationtesteksclusterRole03F70AF0": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "eks.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKSClusterPolicy" - ] - ] - } - ] - } - }, - "integrationtesteksclusterControlPlaneSecurityGroup6E92F333": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "EKS Control Plane Security Group", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "VpcId": { - "Ref": "integrationtesteksclusterDefaultVpc395E1A86" - } - } - }, - "integrationtesteksclusterCreationRoleB98FE02A": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "iam:PassRole", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "integrationtesteksclusterRole03F70AF0", - "Arn" - ] - } - }, - { - "Action": [ - "eks:CreateCluster", - "eks:DescribeCluster", - "eks:DescribeUpdate", - "eks:DeleteCluster", - "eks:UpdateClusterVersion", - "eks:UpdateClusterConfig", - "eks:CreateFargateProfile", - "eks:TagResource", - "eks:UntagResource" - ], - "Effect": "Allow", - "Resource": [ - "*" - ] - }, - { - "Action": [ - "eks:DescribeFargateProfile", - "eks:DeleteFargateProfile" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "iam:GetRole", - "iam:listAttachedRolePolicies" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": "iam:CreateServiceLinkedRole", - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeNetworkInterfaces", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeRouteTables", - "ec2:DescribeDhcpOptions", - "ec2:DescribeVpcs" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "Roles": [ - { - "Ref": "integrationtesteksclusterCreationRoleB98FE02A" - } - ] - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204" - ] - }, - "integrationtesteksclusterE5C0ED98": { - "Type": "Custom::AWSCDK-EKS-Cluster", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454", - "Outputs.awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderframeworkonEventD439F3D7Arn" - ] - }, - "Config": { - "version": "1.21", - "roleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterRole03F70AF0", - "Arn" - ] - }, - "resourcesVpcConfig": { - "subnetIds": [ - { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - ], - "securityGroupIds": [ - { - "Fn::GetAtt": [ - "integrationtesteksclusterControlPlaneSecurityGroup6E92F333", - "GroupId" - ] - } - ], - "endpointPublicAccess": true, - "endpointPrivateAccess": true - } - }, - "AssumeRoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "AttributesRevision": 2 - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcIGW9ADAFE6F", - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTable4A47F4AC", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableD7E59903", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5", - "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8", - "integrationtesteksclusterDefaultVpcPublicSubnet1DefaultRoute33CE7FC3", - "integrationtesteksclusterDefaultVpcPublicSubnet1EIP62A0A17B", - "integrationtesteksclusterDefaultVpcPublicSubnet1NATGatewayC9C984F9", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTable1D5A7569", - "integrationtesteksclusterDefaultVpcPublicSubnet1RouteTableAssociation4831B6A7", - "integrationtesteksclusterDefaultVpcPublicSubnet1Subnet58061317", - "integrationtesteksclusterDefaultVpcPublicSubnet2DefaultRoute253A231E", - "integrationtesteksclusterDefaultVpcPublicSubnet2EIPFC53AC43", - "integrationtesteksclusterDefaultVpcPublicSubnet2NATGatewayE109B761", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableA4C7B327", - "integrationtesteksclusterDefaultVpcPublicSubnet2RouteTableAssociation62710C52", - "integrationtesteksclusterDefaultVpcPublicSubnet2Subnet68EAAF11", - "integrationtesteksclusterDefaultVpc395E1A86", - "integrationtesteksclusterDefaultVpcVPCGWE4DC2204", - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "integrationtesteksclusterCreationRoleB98FE02A" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0": { - "Type": "AWS::SSM::Parameter", - "Properties": { - "Type": "String", - "Value": "aws:cdk:eks:kubectl-ready" - }, - "DependsOn": [ - "integrationtesteksclusterCreationRoleDefaultPolicy5417802D", - "integrationtesteksclusterCreationRoleB98FE02A", - "integrationtesteksclusterE5C0ED98" - ] - }, - "integrationtesteksclusterMastersRole63B9B0BF": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "integrationtesteksclusterAwsAuthmanifestAEF9C6DF": { - "Type": "Custom::AWSCDK-EKS-KubernetesResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", - "Outputs.awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderframeworkonEvent69C4EA38Arn" - ] - }, - "Manifest": { - "Fn::Join": [ - "", - [ - "[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"aws-auth\",\"namespace\":\"kube-system\",\"labels\":{\"aws.cdk.eks/prune-c89091867a17cdada4a752b4f280c4353e38671b20\":\"\"}},\"data\":{\"mapRoles\":\"[{\\\"rolearn\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - }, - "\\\",\\\"username\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - }, - "\\\",\\\"groups\\\":[\\\"system:masters\\\"]},{\\\"rolearn\\\":\\\"", - { - "Fn::GetAtt": [ - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7", - "Arn" - ] - }, - "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]},{\\\"rolearn\\\":\\\"arn:aws:iam::", - { - "Ref": "AWS::AccountId" - }, - ":role/AWSServiceRoleForAmazonEMRContainers\\\",\\\"username\\\":\\\"emr-containers\\\",\\\"groups\\\":[]}]\",\"mapUsers\":\"[]\",\"mapAccounts\":\"[]\"}}]" - ] - ] - }, - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "RoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "PruneLabel": "aws.cdk.eks/prune-c89091867a17cdada4a752b4f280c4353e38671b20", - "Overwrite": true - }, - "DependsOn": [ - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "ec2.", - { - "Ref": "AWS::URLSuffix" - } - ] - ] - } - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKSWorkerNodePolicy" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEKS_CNI_Policy" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - ] - ] - } - ] - } - }, - "integrationtesteksclusterNodegroupDefaultCapacity536CF32C": { - "Type": "AWS::EKS::Nodegroup", - "Properties": { - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "NodeRole": { - "Fn::GetAtt": [ - "integrationtesteksclusterNodegroupDefaultCapacityNodeGroupRole75D45BA7", - "Arn" - ] - }, - "Subnets": [ - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - } - ], - "AmiType": "AL2_x86_64", - "ForceUpdateEnabled": true, - "InstanceTypes": [ - "m5.xlarge" - ], - "ScalingConfig": { - "DesiredSize": 3, - "MaxSize": 3, - "MinSize": 3 - } - } - }, - "integrationtesteksclustermanifestemrRoleCCE4E328": { - "Type": "Custom::AWSCDK-EKS-KubernetesResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", - "Outputs.awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderframeworkonEvent69C4EA38Arn" - ] - }, - "Manifest": "[{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"emr-containers\",\"namespace\":\"default\",\"labels\":{\"aws.cdk.eks/prune-c8cef729fffd80e01dd767818967a268148bb13a2a\":\"\"}},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"namespaces\"],\"verbs\":[\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"serviceaccounts\",\"services\",\"configmaps\",\"events\",\"pods\",\"pods/log\"],\"verbs\":[\"get\",\"list\",\"watch\",\"describe\",\"create\",\"edit\",\"delete\",\"deletecollection\",\"annotate\",\"patch\",\"label\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"create\",\"patch\",\"delete\",\"watch\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"statefulsets\",\"deployments\"],\"verbs\":[\"get\",\"list\",\"watch\",\"describe\",\"create\",\"edit\",\"delete\",\"annotate\",\"patch\",\"label\"]},{\"apiGroups\":[\"batch\"],\"resources\":[\"jobs\"],\"verbs\":[\"get\",\"list\",\"watch\",\"describe\",\"create\",\"edit\",\"delete\",\"annotate\",\"patch\",\"label\"]},{\"apiGroups\":[\"extensions\"],\"resources\":[\"ingresses\"],\"verbs\":[\"get\",\"list\",\"watch\",\"describe\",\"create\",\"edit\",\"delete\",\"annotate\",\"patch\",\"label\"]},{\"apiGroups\":[\"rbac.authorization.k8s.io\"],\"resources\":[\"roles\",\"rolebindings\"],\"verbs\":[\"get\",\"list\",\"watch\",\"describe\",\"create\",\"edit\",\"delete\",\"deletecollection\",\"annotate\",\"patch\",\"label\"]}]}]", - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "RoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "PruneLabel": "aws.cdk.eks/prune-c8cef729fffd80e01dd767818967a268148bb13a2a" - }, - "DependsOn": [ - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "integrationtesteksclustermanifestemrRoleBind8B35D2A2": { - "Type": "Custom::AWSCDK-EKS-KubernetesResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", - "Outputs.awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderframeworkonEvent69C4EA38Arn" - ] - }, - "Manifest": "[{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"emr-containers\",\"namespace\":\"default\",\"labels\":{\"aws.cdk.eks/prune-c892a3812e60d138dd377a538f9d47aace2a0a8bb6\":\"\"}},\"subjects\":[{\"kind\":\"User\",\"name\":\"emr-containers\",\"apiGroup\":\"rbac.authorization.k8s.io\"}],\"roleRef\":{\"kind\":\"Role\",\"name\":\"emr-containers\",\"apiGroup\":\"rbac.authorization.k8s.io\"}}]", - "ClusterName": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "RoleArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "PruneLabel": "aws.cdk.eks/prune-c892a3812e60d138dd377a538f9d47aace2a0a8bb6" - }, - "DependsOn": [ - "integrationtesteksclusterKubectlReadyBarrier0D4A21B0", - "integrationtesteksclustermanifestemrRoleCCE4E328" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454": { - "Type": "AWS::CloudFormation::Stack", - "Properties": { - "TemplateURL": { - "Fn::Join": [ - "", - [ - "https://s3.", - { - "Ref": "AWS::Region" - }, - ".", - { - "Ref": "AWS::URLSuffix" - }, - "/", - { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "/e9aee046003806e01758c649a83bcecd108c5015299bfe2dcd5420c41ee8f115.json" - ] - ] - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - } - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B": { - "Type": "AWS::CloudFormation::Stack", - "Properties": { - "TemplateURL": { - "Fn::Join": [ - "", - [ - "https://s3.", - { - "Ref": "AWS::Region" - }, - ".", - { - "Ref": "AWS::URLSuffix" - }, - "/", - { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "/df7788eb8853ac792f558c2a91ce072f996448fc7c85114280f48690f53f285f.json" - ] - ] - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterE5C0ED98", - "Arn" - ] - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn": { - "Fn::GetAtt": [ - "integrationtesteksclusterCreationRoleB98FE02A", - "Arn" - ] - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetDFF56EB6Ref": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet1Subnet4E00CAFB" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0E779258Ref": { - "Ref": "integrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0C3539A8" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FClusterSecurityGroupId": { - "Fn::GetAtt": [ - "integrationtesteksclusterE5C0ED98", - "ClusterSecurityGroupId" - ] - } - } - }, - "DependsOn": [ - "integrationtesteksclusterDefaultVpcPrivateSubnet1DefaultRouteCC99A72C", - "integrationtesteksclusterDefaultVpcPrivateSubnet1RouteTableAssociation7482DD1E", - "integrationtesteksclusterDefaultVpcPrivateSubnet2DefaultRoute50FF167F", - "integrationtesteksclusterDefaultVpcPrivateSubnet2RouteTableAssociation99F934D5" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "VirtualCluster": { - "Type": "AWS::EMRContainers::VirtualCluster", - "Properties": { - "ContainerProvider": { - "Id": { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - "Info": { - "EksInfo": { - "Namespace": "default" - } - }, - "Type": "EKS" - }, - "Name": "Virtual-Cluster-Name" - }, - "DependsOn": [ - "integrationtesteksclusterAwsAuthmanifestAEF9C6DF", - "integrationtesteksclustermanifestemrRoleBind8B35D2A2" - ] - }, - "StartaJobRunJobExecutionRole157B6BE1": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "emr-containers.amazonaws.com" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "StartaJobRunJobExecutionRoleDefaultPolicyEA7882C0": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "logs:DescribeLogGroups", - "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StartaJobRunJobExecutionRoleDefaultPolicyEA7882C0", - "Roles": [ - { - "Ref": "StartaJobRunJobExecutionRole157B6BE1" - } - ] - } - }, - "StartaJobRunGetEksClusterInfoD0E31373": { - "Type": "Custom::AWS", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "AWS679f53fac002430cb0da5b7982bd22872D164C4C", - "Arn" - ] - }, - "Create": { - "Fn::Join": [ - "", - [ - "{\"service\":\"EMRcontainers\",\"action\":\"describeVirtualCluster\",\"parameters\":{\"id\":\"", - { - "Fn::GetAtt": [ - "VirtualCluster", - "Id" - ] - }, - "\"},\"outputPaths\":[\"virtualCluster.containerProvider.info.eksInfo.namespace\",\"virtualCluster.containerProvider.id\"],\"physicalResourceId\":{\"id\":\"id\"}}" - ] - ] - }, - "InstallLatestAwsSdk": true - }, - "DependsOn": [ - "StartaJobRunGetEksClusterInfoCustomResourcePolicy7AA7B106" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "StartaJobRunGetEksClusterInfoCustomResourcePolicy7AA7B106": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "emr-containers:DescribeVirtualCluster", - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StartaJobRunGetEksClusterInfoCustomResourcePolicy7AA7B106", - "Roles": [ - { - "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" - } - ] - } - }, - "StartaJobRunawsclilayer110EEF0B": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip" - }, - "Description": "/opt/awscli/aws" - } - }, - "StartaJobRunCustomResourceProviderframeworkonEventServiceRole1D6E2464": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "StartaJobRunCustomResourceProviderframeworkonEventServiceRoleDefaultPolicy95FB1565": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CB6182A5B", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CB6182A5B", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StartaJobRunCustomResourceProviderframeworkonEventServiceRoleDefaultPolicy95FB1565", - "Roles": [ - { - "Ref": "StartaJobRunCustomResourceProviderframeworkonEventServiceRole1D6E2464" - } - ] - } - }, - "StartaJobRunCustomResourceProviderframeworkonEventAC961165": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "StartaJobRunCustomResourceProviderframeworkonEventServiceRole1D6E2464", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onEvent (aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/Start a Job Run/CustomResourceProvider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CB6182A5B", - "Arn" - ] - } - } - }, - "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "StartaJobRunCustomResourceProviderframeworkonEventServiceRoleDefaultPolicy95FB1565", - "StartaJobRunCustomResourceProviderframeworkonEventServiceRole1D6E2464" - ] - }, - "StartaJobRunCustomResource3BD90664": { - "Type": "AWS::CloudFormation::CustomResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "StartaJobRunCustomResourceProviderframeworkonEventAC961165", - "Arn" - ] - }, - "eksNamespace": { - "Fn::GetAtt": [ - "StartaJobRunGetEksClusterInfoD0E31373", - "virtualCluster.containerProvider.info.eksInfo.namespace" - ] - }, - "eksClusterId": { - "Fn::GetAtt": [ - "StartaJobRunGetEksClusterInfoD0E31373", - "virtualCluster.containerProvider.id" - ] - }, - "roleName": { - "Ref": "StartaJobRunJobExecutionRole157B6BE1" - } - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - }, - "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "AWS679f53fac002430cb0da5b7982bd22872D164C4C": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286.zip" - }, - "Role": { - "Fn::GetAtt": [ - "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2", - "Arn" - ] - }, - "Handler": "index.handler", - "Runtime": "nodejs14.x", - "Timeout": 120 - }, - "DependsOn": [ - "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" - ] - }, - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleF99BDB4C": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleDefaultPolicy87B52EEA": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "eks:DescribeCluster", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":eks:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":cluster/", - { - "Fn::GetAtt": [ - "StartaJobRunGetEksClusterInfoD0E31373", - "virtualCluster.containerProvider.id" - ] - } - ] - ] - } - }, - { - "Action": [ - "iam:GetRole", - "iam:UpdateAssumeRolePolicy" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "StartaJobRunJobExecutionRole157B6BE1", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleDefaultPolicy87B52EEA", - "Roles": [ - { - "Ref": "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleF99BDB4C" - } - ] - } - }, - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CB6182A5B": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "de2da116e1de2db20dc2bc88a1e97df050dde2917a4122674e054e87ee53e334.zip" - }, - "Role": { - "Fn::GetAtt": [ - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleF99BDB4C", - "Arn" - ] - }, - "Handler": "index.handler", - "Layers": [ - { - "Ref": "StartaJobRunawsclilayer110EEF0B" - } - ], - "MemorySize": 256, - "Runtime": "python3.9", - "Timeout": 30 - }, - "DependsOn": [ - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleDefaultPolicy87B52EEA", - "SingletonLambda8693BB64968944B69AAFB0CC9EB8757CServiceRoleF99BDB4C" - ] - }, - "StateMachineRoleB840431D": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "StateMachineRoleDefaultPolicyDF1E6607": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "emr-containers:StartJobRun", - "Condition": { - "StringEquals": { - "emr-containers:ExecutionRoleArn": { - "Fn::GetAtt": [ - "StartaJobRunJobExecutionRole157B6BE1", - "Arn" - ] - } - } - }, - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":emr-containers:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":/virtualclusters/", - { - "Fn::GetAtt": [ - "VirtualCluster", - "Id" - ] - } - ] - ] - } - }, - { - "Action": [ - "emr-containers:DescribeJobRun", - "emr-containers:CancelJobRun" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":emr-containers:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":/virtualclusters/", - { - "Fn::GetAtt": [ - "VirtualCluster", - "Id" - ] - }, - "/jobruns/*" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", - "Roles": [ - { - "Ref": "StateMachineRoleB840431D" - } - ] - } - }, - "StateMachine2E01A3A5": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{\"StartAt\":\"Start a Job Run\",\"States\":{\"Start a Job Run\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", - { - "Ref": "AWS::Partition" - }, - ":states:::emr-containers:startJobRun.sync\",\"Parameters\":{\"VirtualClusterId\":\"", - { - "Fn::GetAtt": [ - "VirtualCluster", - "Id" - ] - }, - "\",\"Name\":\"EMR-Containers-Job\",\"ExecutionRoleArn\":\"", - { - "Fn::GetAtt": [ - "StartaJobRunJobExecutionRole157B6BE1", - "Arn" - ] - }, - "\",\"ReleaseLabel\":\"emr-6.2.0-latest\",\"JobDriver\":{\"SparkSubmitJobDriver\":{\"EntryPoint\":\"local:///usr/lib/spark/examples/src/main/python/pi.py\",\"EntryPointArguments\":[\"2\"],\"SparkSubmitParameters\":\"--conf spark.driver.memory=512M --conf spark.kubernetes.driver.request.cores=0.2 --conf spark.kubernetes.executor.request.cores=0.2 --conf spark.sql.shuffle.partitions=60 --conf spark.dynamicAllocation.enabled=false\"}},\"ConfigurationOverrides\":{\"MonitoringConfiguration\":{\"PersistentAppUI\":\"ENABLED\"}}}}},\"TimeoutSeconds\":1000}" - ] - ] - } - }, - "DependsOn": [ - "StateMachineRoleDefaultPolicyDF1E6607", - "StateMachineRoleB840431D" - ] - } - }, - "Outputs": { - "integrationtesteksclusterConfigCommandFA814999": { - "Value": { - "Fn::Join": [ - "", - [ - "aws eks update-kubeconfig --name ", - { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - " --region ", - { - "Ref": "AWS::Region" - }, - " --role-arn ", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - } - ] - ] - } - }, - "integrationtesteksclusterGetTokenCommandD7B92682": { - "Value": { - "Fn::Join": [ - "", - [ - "aws eks get-token --cluster-name ", - { - "Ref": "integrationtesteksclusterE5C0ED98" - }, - " --region ", - { - "Ref": "AWS::Region" - }, - " --role-arn ", - { - "Fn::GetAtt": [ - "integrationtesteksclusterMastersRole63B9B0BF", - "Arn" - ] - } - ] - ] - } - }, - "stateMachineArn": { - "Value": { - "Ref": "StateMachine2E01A3A5" - } - } - }, - "Mappings": { - "ServiceprincipalMap": { - "af-south-1": { - "states": "states.af-south-1.amazonaws.com" - }, - "ap-east-1": { - "states": "states.ap-east-1.amazonaws.com" - }, - "ap-northeast-1": { - "states": "states.ap-northeast-1.amazonaws.com" - }, - "ap-northeast-2": { - "states": "states.ap-northeast-2.amazonaws.com" - }, - "ap-northeast-3": { - "states": "states.ap-northeast-3.amazonaws.com" - }, - "ap-south-1": { - "states": "states.ap-south-1.amazonaws.com" - }, - "ap-southeast-1": { - "states": "states.ap-southeast-1.amazonaws.com" - }, - "ap-southeast-2": { - "states": "states.ap-southeast-2.amazonaws.com" - }, - "ap-southeast-3": { - "states": "states.ap-southeast-3.amazonaws.com" - }, - "ca-central-1": { - "states": "states.ca-central-1.amazonaws.com" - }, - "cn-north-1": { - "states": "states.cn-north-1.amazonaws.com" - }, - "cn-northwest-1": { - "states": "states.cn-northwest-1.amazonaws.com" - }, - "eu-central-1": { - "states": "states.eu-central-1.amazonaws.com" - }, - "eu-north-1": { - "states": "states.eu-north-1.amazonaws.com" - }, - "eu-south-1": { - "states": "states.eu-south-1.amazonaws.com" - }, - "eu-south-2": { - "states": "states.eu-south-2.amazonaws.com" - }, - "eu-west-1": { - "states": "states.eu-west-1.amazonaws.com" - }, - "eu-west-2": { - "states": "states.eu-west-2.amazonaws.com" - }, - "eu-west-3": { - "states": "states.eu-west-3.amazonaws.com" - }, - "me-south-1": { - "states": "states.me-south-1.amazonaws.com" - }, - "sa-east-1": { - "states": "states.sa-east-1.amazonaws.com" - }, - "us-east-1": { - "states": "states.us-east-1.amazonaws.com" - }, - "us-east-2": { - "states": "states.us-east-2.amazonaws.com" - }, - "us-gov-east-1": { - "states": "states.us-gov-east-1.amazonaws.com" - }, - "us-gov-west-1": { - "states": "states.us-gov-west-1.amazonaws.com" - }, - "us-iso-east-1": { - "states": "states.amazonaws.com" - }, - "us-iso-west-1": { - "states": "states.amazonaws.com" - }, - "us-isob-east-1": { - "states": "states.amazonaws.com" - }, - "us-west-1": { - "states": "states.us-west-1.amazonaws.com" - }, - "us-west-2": { - "states": "states.us-west-2.amazonaws.com" - } - } - }, - "Parameters": { - "BootstrapVersion": { - "Type": "AWS::SSM::Parameter::Value", - "Default": "/cdk-bootstrap/hnb659fds/version", - "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" - } - }, - "Rules": { - "CheckBootstrapVersion": { - "Assertions": [ - { - "Assert": { - "Fn::Not": [ - { - "Fn::Contains": [ - [ - "1", - "2", - "3", - "4", - "5" - ], - { - "Ref": "BootstrapVersion" - } - ] - } - ] - }, - "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." - } - ] - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json index 5e8231343c32d..af33422f4284b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json @@ -131,7 +131,7 @@ } } }, - "f8478e4f5adc52f32316a1ee08a418807f272a788ad96491c685f0cac3240b21": { + "de5999b0b9f5565873884b194ad31fb92542ba44f3f4d52561f75ba8fa14f142": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json", "packaging": "file" @@ -139,7 +139,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f8478e4f5adc52f32316a1ee08a418807f272a788ad96491c685f0cac3240b21.json", + "objectKey": "de5999b0b9f5565873884b194ad31fb92542ba44f3f4d52561f75ba8fa14f142.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json index 1eec6a01d8d9d..260d57d2a597a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json @@ -1122,7 +1122,26 @@ { "Action": "logs:DescribeLogGroups", "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } } ], "Version": "2012-10-17" diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderB5D967DC.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderB5D967DC.nested.template.json deleted file mode 100644 index 21894e82f6b3b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderB5D967DC.nested.template.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "Resources": { - "NodeProxyAgentLayer924C1971": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "4288ebb3652acdf2d828b7db7ca44a7162a401ace50ebb4026e84b18a02a06ee.zip" - }, - "Description": "/opt/nodejs/node_modules/proxy-agent" - } - }, - "OnEventHandlerServiceRole15A26729": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "OnEventHandlerServiceRoleDefaultPolicyC57085D4": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "OnEventHandlerServiceRoleDefaultPolicyC57085D4", - "Roles": [ - { - "Ref": "OnEventHandlerServiceRole15A26729" - } - ] - } - }, - "OnEventHandler42BEBAE0": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip" - }, - "Role": { - "Fn::GetAtt": [ - "OnEventHandlerServiceRole15A26729", - "Arn" - ] - }, - "Description": "onEvent handler for EKS cluster resource provider", - "Environment": { - "Variables": { - "AWS_STS_REGIONAL_ENDPOINTS": "regional" - } - }, - "Handler": "index.onEvent", - "Layers": [ - { - "Ref": "NodeProxyAgentLayer924C1971" - } - ], - "Runtime": "nodejs14.x", - "Timeout": 60 - }, - "DependsOn": [ - "OnEventHandlerServiceRoleDefaultPolicyC57085D4", - "OnEventHandlerServiceRole15A26729" - ] - }, - "IsCompleteHandlerServiceRole5810CC58": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B", - "Roles": [ - { - "Ref": "IsCompleteHandlerServiceRole5810CC58" - } - ] - } - }, - "IsCompleteHandler7073F4DA": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "2c98a634e36e3f2a1c1a78958953ed173e2c6cf8446c15dabbef67d4e30b33d6.zip" - }, - "Role": { - "Fn::GetAtt": [ - "IsCompleteHandlerServiceRole5810CC58", - "Arn" - ] - }, - "Description": "isComplete handler for EKS cluster resource provider", - "Environment": { - "Variables": { - "AWS_STS_REGIONAL_ENDPOINTS": "regional" - } - }, - "Handler": "index.isComplete", - "Layers": [ - { - "Ref": "NodeProxyAgentLayer924C1971" - } - ], - "Runtime": "nodejs14.x", - "Timeout": 60 - }, - "DependsOn": [ - "IsCompleteHandlerServiceRoleDefaultPolicy8F64197B", - "IsCompleteHandlerServiceRole5810CC58" - ] - }, - "ProviderframeworkonEventServiceRole9FF04296": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "states:StartExecution", - "Effect": "Allow", - "Resource": { - "Ref": "Providerwaiterstatemachine5D4A9DF0" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "Roles": [ - { - "Ref": "ProviderframeworkonEventServiceRole9FF04296" - } - ] - } - }, - "ProviderframeworkonEvent83C1D0A7": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonEventServiceRole9FF04296", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onEvent (aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - "WAITER_STATE_MACHINE_ARN": { - "Ref": "Providerwaiterstatemachine5D4A9DF0" - } - } - }, - "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "ProviderframeworkonEventServiceRole9FF04296" - ] - }, - "ProviderframeworkisCompleteServiceRoleB1087139": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC", - "Roles": [ - { - "Ref": "ProviderframeworkisCompleteServiceRoleB1087139" - } - ] - } - }, - "ProviderframeworkisComplete26D7B0CB": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkisCompleteServiceRoleB1087139", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - isComplete (aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - } - } - }, - "Handler": "framework.isComplete", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkisCompleteServiceRoleDefaultPolicy2E7140AC", - "ProviderframeworkisCompleteServiceRoleB1087139" - ] - }, - "ProviderframeworkonTimeoutServiceRole28643D26": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F", - "Roles": [ - { - "Ref": "ProviderframeworkonTimeoutServiceRole28643D26" - } - ] - } - }, - "ProviderframeworkonTimeout0B47CA38": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonTimeoutServiceRole28643D26", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onTimeout (aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/@aws-cdk--aws-eks.ClusterResourceProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "OnEventHandler42BEBAE0", - "Arn" - ] - }, - "USER_IS_COMPLETE_FUNCTION_ARN": { - "Fn::GetAtt": [ - "IsCompleteHandler7073F4DA", - "Arn" - ] - } - } - }, - "Handler": "framework.onTimeout", - "Runtime": "nodejs14.x", - "Timeout": 900 - }, - "DependsOn": [ - "ProviderframeworkonTimeoutServiceRoleDefaultPolicy2688969F", - "ProviderframeworkonTimeoutServiceRole28643D26" - ] - }, - "ProviderwaiterstatemachineRole0C7159F9": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::FindInMap": [ - "ServiceprincipalMap", - { - "Ref": "AWS::Region" - }, - "states" - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - }, - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A", - "Roles": [ - { - "Ref": "ProviderwaiterstatemachineRole0C7159F9" - } - ] - } - }, - "Providerwaiterstatemachine5D4A9DF0": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{\"StartAt\":\"framework-isComplete-task\",\"States\":{\"framework-isComplete-task\":{\"End\":true,\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":60,\"MaxAttempts\":60,\"BackoffRate\":1}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"framework-onTimeout-task\"}],\"Type\":\"Task\",\"Resource\":\"", - { - "Fn::GetAtt": [ - "ProviderframeworkisComplete26D7B0CB", - "Arn" - ] - }, - "\"},\"framework-onTimeout-task\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"", - { - "Fn::GetAtt": [ - "ProviderframeworkonTimeout0B47CA38", - "Arn" - ] - }, - "\"}}}" - ] - ] - }, - "RoleArn": { - "Fn::GetAtt": [ - "ProviderwaiterstatemachineRole0C7159F9", - "Arn" - ] - } - }, - "DependsOn": [ - "ProviderwaiterstatemachineRoleDefaultPolicyD3C3DA1A", - "ProviderwaiterstatemachineRole0C7159F9" - ] - } - }, - "Mappings": { - "ServiceprincipalMap": { - "af-south-1": { - "states": "states.af-south-1.amazonaws.com" - }, - "ap-east-1": { - "states": "states.ap-east-1.amazonaws.com" - }, - "ap-northeast-1": { - "states": "states.ap-northeast-1.amazonaws.com" - }, - "ap-northeast-2": { - "states": "states.ap-northeast-2.amazonaws.com" - }, - "ap-northeast-3": { - "states": "states.ap-northeast-3.amazonaws.com" - }, - "ap-south-1": { - "states": "states.ap-south-1.amazonaws.com" - }, - "ap-southeast-1": { - "states": "states.ap-southeast-1.amazonaws.com" - }, - "ap-southeast-2": { - "states": "states.ap-southeast-2.amazonaws.com" - }, - "ap-southeast-3": { - "states": "states.ap-southeast-3.amazonaws.com" - }, - "ca-central-1": { - "states": "states.ca-central-1.amazonaws.com" - }, - "cn-north-1": { - "states": "states.cn-north-1.amazonaws.com" - }, - "cn-northwest-1": { - "states": "states.cn-northwest-1.amazonaws.com" - }, - "eu-central-1": { - "states": "states.eu-central-1.amazonaws.com" - }, - "eu-north-1": { - "states": "states.eu-north-1.amazonaws.com" - }, - "eu-south-1": { - "states": "states.eu-south-1.amazonaws.com" - }, - "eu-south-2": { - "states": "states.eu-south-2.amazonaws.com" - }, - "eu-west-1": { - "states": "states.eu-west-1.amazonaws.com" - }, - "eu-west-2": { - "states": "states.eu-west-2.amazonaws.com" - }, - "eu-west-3": { - "states": "states.eu-west-3.amazonaws.com" - }, - "me-south-1": { - "states": "states.me-south-1.amazonaws.com" - }, - "sa-east-1": { - "states": "states.sa-east-1.amazonaws.com" - }, - "us-east-1": { - "states": "states.us-east-1.amazonaws.com" - }, - "us-east-2": { - "states": "states.us-east-2.amazonaws.com" - }, - "us-gov-east-1": { - "states": "states.us-gov-east-1.amazonaws.com" - }, - "us-gov-west-1": { - "states": "states.us-gov-west-1.amazonaws.com" - }, - "us-iso-east-1": { - "states": "states.amazonaws.com" - }, - "us-iso-west-1": { - "states": "states.amazonaws.com" - }, - "us-isob-east-1": { - "states": "states.amazonaws.com" - }, - "us-west-1": { - "states": "states.us-west-1.amazonaws.com" - }, - "us-west-2": { - "states": "states.us-west-2.amazonaws.com" - } - } - }, - "Outputs": { - "awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksClusterResourceProviderframeworkonEventD439F3D7Arn": { - "Value": { - "Fn::GetAtt": [ - "ProviderframeworkonEvent83C1D0A7", - "Arn" - ] - } - } - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn": { - "Type": "String" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderC26A0FC7.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderC26A0FC7.nested.template.json deleted file mode 100644 index 5e5dd15f728cc..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderC26A0FC7.nested.template.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "Resources": { - "HandlerServiceRoleFCDC14AE": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - ] - ] - } - ] - } - }, - "HandlerServiceRoleDefaultPolicyCBD0CC91": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "eks:DescribeCluster", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FArn" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Resource": { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn" - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "HandlerServiceRoleDefaultPolicyCBD0CC91", - "Roles": [ - { - "Ref": "HandlerServiceRoleFCDC14AE" - } - ] - } - }, - "Handler886CB40B": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "d01d4b7367b49a3e222279017fe50e41d6b2272d436b2e82038d0036deb2cdcb.zip" - }, - "Role": { - "Fn::GetAtt": [ - "HandlerServiceRoleFCDC14AE", - "Arn" - ] - }, - "Description": "onEvent handler for EKS kubectl resource provider", - "Handler": "index.handler", - "Layers": [ - { - "Ref": "AwsCliLayerF44AAF94" - }, - { - "Ref": "KubectlLayer600207B5" - } - ], - "MemorySize": 1024, - "Runtime": "python3.7", - "Timeout": 900, - "VpcConfig": { - "SecurityGroupIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FClusterSecurityGroupId" - } - ], - "SubnetIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetDFF56EB6Ref" - }, - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0E779258Ref" - } - ] - } - }, - "DependsOn": [ - "HandlerServiceRoleDefaultPolicyCBD0CC91", - "HandlerServiceRoleFCDC14AE" - ] - }, - "AwsCliLayerF44AAF94": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "c409e6c5845f1f349df8cd84e160bf6f1c35d2b060b63e1f032f9bd39d4542cc.zip" - }, - "Description": "/opt/awscli/aws" - } - }, - "KubectlLayer600207B5": { - "Type": "AWS::Lambda::LayerVersion", - "Properties": { - "Content": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "c6964dbf0c556ec82ce09622e99ad6f6d4e488cdaac0ef9e8492e078ec61ffed.zip" - }, - "Description": "/opt/kubectl/kubectl and /opt/helm/helm" - } - }, - "ProviderframeworkonEventServiceRole9FF04296": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" - ] - ] - } - ] - } - }, - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "lambda:InvokeFunction", - "Effect": "Allow", - "Resource": [ - { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - }, - ":*" - ] - ] - } - ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "Roles": [ - { - "Ref": "ProviderframeworkonEventServiceRole9FF04296" - } - ] - } - }, - "ProviderframeworkonEvent83C1D0A7": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" - }, - "S3Key": "3b263c2ad043fd069ef446753788c36e595c82b51a70478e58258c8ef7471671.zip" - }, - "Role": { - "Fn::GetAtt": [ - "ProviderframeworkonEventServiceRole9FF04296", - "Arn" - ] - }, - "Description": "AWS CDK resource provider framework - onEvent (aws-stepfunctions-tasks-emr-containers-start-job-run-integ-test/@aws-cdk--aws-eks.KubectlProvider/Provider)", - "Environment": { - "Variables": { - "USER_ON_EVENT_FUNCTION_ARN": { - "Fn::GetAtt": [ - "Handler886CB40B", - "Arn" - ] - } - } - }, - "Handler": "framework.onEvent", - "Runtime": "nodejs14.x", - "Timeout": 900, - "VpcConfig": { - "SecurityGroupIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FClusterSecurityGroupId" - } - ], - "SubnetIds": [ - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetDFF56EB6Ref" - }, - { - "Ref": "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0E779258Ref" - } - ] - } - }, - "DependsOn": [ - "ProviderframeworkonEventServiceRoleDefaultPolicy48CD2133", - "ProviderframeworkonEventServiceRole9FF04296" - ] - } - }, - "Outputs": { - "awsstepfunctionstasksemrcontainersstartjobrunintegtestawscdkawseksKubectlProviderframeworkonEvent69C4EA38Arn": { - "Value": { - "Fn::GetAtt": [ - "ProviderframeworkonEvent83C1D0A7", - "Arn" - ] - } - } - }, - "Parameters": { - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FArn": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterCreationRole19DB152EArn": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet1SubnetDFF56EB6Ref": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtesteksclusterDefaultVpcPrivateSubnet2Subnet0E779258Ref": { - "Type": "String" - }, - "referencetoawsstepfunctionstasksemrcontainersstartjobrunintegtestintegrationtestekscluster4D8C900FClusterSecurityGroupId": { - "Type": "String" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/manifest.json index 884cc97dee388..2faef8f276e65 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/manifest.json @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f8478e4f5adc52f32316a1ee08a418807f272a788ad96491c685f0cac3240b21.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/de5999b0b9f5565873884b194ad31fb92542ba44f3f4d52561f75ba8fa14f142.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/tree.json index 530f5ec58830e..4bff8bcb351fd 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "aws-stepfunctions-tasks-emr-containers-start-job-run-test": { @@ -952,7 +952,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "KubectlReadyBarrier": { @@ -2442,7 +2442,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } } }, @@ -2529,7 +2529,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3199,7 +3199,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "Virtual Cluster": { @@ -3277,7 +3277,26 @@ { "Action": "logs:DescribeLogGroups", "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:*" + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":*" + ] + ] + } } ], "Version": "2012-10-17" @@ -4214,7 +4233,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-start-job-run/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.95" + "version": "10.1.108" } }, "DeployAssert": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.test.ts index 363d79521fd54..b6ce8e6baf28c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/start-job-run.test.ts @@ -170,6 +170,30 @@ describe('Invoke EMR Containers Start Job Run with ', () => { }); }); + test('Job Driver with Entry Point Arguments', () => { + // WHEN + const task = new EmrContainersStartJobRun(stack, 'EMR Containers Start Job Run', { + ...defaultProps, + jobDriver: { + sparkSubmitJobDriver: { + entryPoint: sfn.TaskInput.fromText('entrypoint'), + entryPointArguments: sfn.TaskInput.fromJsonPathAt('$.entrypointArguments'), + }, + }, + }); + + // THEN + expect(stack.resolve(task.toStateJson())).toMatchObject({ + Parameters: { + JobDriver: { + SparkSubmitJobDriver: { + 'EntryPoint': 'entrypoint', + 'EntryPointArguments.$': '$.entrypointArguments', + }, + }, + }, + }); + }); test('Job Execution Role', () => { // WHEN @@ -281,7 +305,26 @@ describe('Invoke EMR Containers Start Job Run with ', () => { { Action: 'logs:DescribeLogGroups', Effect: 'Allow', - Resource: 'arn:aws:logs:*:*:*', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':logs:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':*', + ], + ], + }, }, ], Version: '2012-10-17', @@ -439,7 +482,26 @@ describe('Invoke EMR Containers Start Job Run with ', () => { { Action: 'logs:DescribeLogGroups', Effect: 'Allow', - Resource: 'arn:aws:logs:*:*:*', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':logs:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':*', + ], + ], + }, }, ], Version: '2012-10-17', @@ -589,7 +651,7 @@ describe('Invoke EMR Containers Start Job Run with ', () => { }).toThrow('Entry point must be between 1 and 256 characters in length. Received 0.'); }); - test('Entry Point Arguments is not an string array that is between 1 and 10280 entries in length', () => { + test('Entry Point Arguments is not a string array that is between 1 and 10280 entries in length', () => { // WHEN const entryPointArgs = sfn.TaskInput.fromObject(new Array(10281).fill('x', 10281)); const entryPointArgsNone = sfn.TaskInput.fromObject([]); @@ -607,7 +669,7 @@ describe('Invoke EMR Containers Start Job Run with ', () => { }, }, }); - }).toThrow('Entry point arguments must be a string array or encoded JSON path but received object'); + }).toThrow('Entry point arguments must be a string array or an encoded JSON path but received object'); // THEN expect(() => { @@ -620,7 +682,7 @@ describe('Invoke EMR Containers Start Job Run with ', () => { }, }, }); - }).toThrow('Entry point arguments must be a string array or encoded JSON path, but received a non JSON path string'); + }).toThrow('Entry point arguments must be a string array or an encoded JSON path, but received a non JSON path string'); // THEN expect(() => { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sns/publish.integ.snapshot/aws-stepfunctions-tasks-sns-publish-integ.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sns/publish.integ.snapshot/aws-stepfunctions-tasks-sns-publish-integ.template.json index 243b67ba89b15..8cca2d08cb99d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sns/publish.integ.snapshot/aws-stepfunctions-tasks-sns-publish-integ.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sns/publish.integ.snapshot/aws-stepfunctions-tasks-sns-publish-integ.template.json @@ -45,6 +45,7 @@ }, "showmethemessagesawsstepfunctionstaskssnspublishintegcooltopic8388C976F1D63091": { "Type": "AWS::SNS::Subscription", + "DependsOn": "showmethemessagesPolicyB08B04B0", "Properties": { "Protocol": "sqs", "TopicArn": { diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 45cff09aed9cd..966bd890efdff 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,365 @@ +# CloudFormation Resource Specification v91.0.0 + +## New Resource Types + +* AWS::CloudFront::MonitoringSubscription +* AWS::ConnectCampaigns::Campaign +* AWS::IoTFleetWise::Campaign +* AWS::IoTFleetWise::DecoderManifest +* AWS::IoTFleetWise::Fleet +* AWS::IoTFleetWise::ModelManifest +* AWS::IoTFleetWise::SignalCatalog +* AWS::IoTFleetWise::Vehicle +* AWS::RolesAnywhere::CRL +* AWS::RolesAnywhere::Profile +* AWS::RolesAnywhere::TrustAnchor +* AWS::SageMaker::ModelPackage + +## Attribute Changes + +* AWS::CloudWatch::Alarm Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html +* AWS::ElastiCache::SubnetGroup Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html +* AWS::ElasticBeanstalk::ApplicationVersion Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html +* AWS::ElasticBeanstalk::ApplicationVersion Id (__added__) +* AWS::RDS::DBClusterParameterGroup DBClusterParameterGroupName (__added__) + +## Property Changes + +* AWS::CloudWatch::Alarm ActionsEnabled.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-actionsenabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-actionsenabled +* AWS::CloudWatch::Alarm AlarmActions.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmactions + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmactions +* AWS::CloudWatch::Alarm AlarmDescription.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmdescription + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmdescription +* AWS::CloudWatch::Alarm AlarmName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmname +* AWS::CloudWatch::Alarm ComparisonOperator.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-comparisonoperator + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-comparisonoperator +* AWS::CloudWatch::Alarm DatapointsToAlarm.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarm-datapointstoalarm + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarm-datapointstoalarm +* AWS::CloudWatch::Alarm Dimensions.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-dimension + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-dimension +* AWS::CloudWatch::Alarm EvaluateLowSampleCountPercentile.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-evaluatelowsamplecountpercentile + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-evaluatelowsamplecountpercentile +* AWS::CloudWatch::Alarm EvaluationPeriods.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-evaluationperiods + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-evaluationperiods +* AWS::CloudWatch::Alarm ExtendedStatistic.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-extendedstatistic + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-extendedstatistic +* AWS::CloudWatch::Alarm InsufficientDataActions.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-insufficientdataactions + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-insufficientdataactions +* AWS::CloudWatch::Alarm MetricName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-metricname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-metricname +* AWS::CloudWatch::Alarm Metrics.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarm-metrics + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarm-metrics +* AWS::CloudWatch::Alarm Namespace.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-namespace + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-namespace +* AWS::CloudWatch::Alarm OKActions.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-okactions + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-okactions +* AWS::CloudWatch::Alarm Period.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-period + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-period +* AWS::CloudWatch::Alarm Statistic.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-statistic + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-statistic +* AWS::CloudWatch::Alarm Threshold.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-threshold + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-threshold +* AWS::CloudWatch::Alarm ThresholdMetricId.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-dynamic-threshold + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-dynamic-threshold +* AWS::CloudWatch::Alarm TreatMissingData.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-treatmissingdata + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-treatmissingdata +* AWS::CloudWatch::Alarm Unit.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-unit + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-unit +* AWS::DynamoDB::Table ImportSourceSpecification (__added__) +* AWS::DynamoDB::Table AttributeDefinitions.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedefinitions +* AWS::DynamoDB::Table AttributeDefinitions.DuplicatesAllowed (__changed__) + * Old: true + * New: false +* AWS::DynamoDB::Table AttributeDefinitions.UpdateType (__changed__) + * Old: Conditional + * New: Mutable +* AWS::DynamoDB::Table ContributorInsightsSpecification.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-contributorinsightsspecification-enabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-contributorinsightsspecification +* AWS::DynamoDB::Table GlobalSecondaryIndexes.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-globalsecondaryindexes +* AWS::DynamoDB::Table LocalSecondaryIndexes.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-localsecondaryindexes +* AWS::DynamoDB::Table LocalSecondaryIndexes.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::ElastiCache::CacheCluster TransitEncryptionEnabled (__added__) +* AWS::ElastiCache::SubnetGroup CacheSubnetGroupName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-cachesubnetgroupname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-cachesubnetgroupname +* AWS::ElastiCache::SubnetGroup Description.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-description + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-description +* AWS::ElastiCache::SubnetGroup SubnetIds.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-subnetids + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-subnetids +* AWS::ElastiCache::SubnetGroup Tags.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-tags + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-tags +* AWS::ElasticBeanstalk::ApplicationVersion ApplicationName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-applicationname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-applicationname +* AWS::ElasticBeanstalk::ApplicationVersion Description.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-description + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-description +* AWS::ElasticBeanstalk::ApplicationVersion SourceBundle.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-sourcebundle + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-sourcebundle +* AWS::RDS::DBCluster AllocatedStorage (__added__) +* AWS::RDS::DBCluster AutoMinorVersionUpgrade (__added__) +* AWS::RDS::DBCluster DBClusterInstanceClass (__added__) +* AWS::RDS::DBCluster DBInstanceParameterGroupName (__added__) +* AWS::RDS::DBCluster Iops (__added__) +* AWS::RDS::DBCluster MonitoringInterval (__added__) +* AWS::RDS::DBCluster MonitoringRoleArn (__added__) +* AWS::RDS::DBCluster PerformanceInsightsEnabled (__added__) +* AWS::RDS::DBCluster PerformanceInsightsKmsKeyId (__added__) +* AWS::RDS::DBCluster PerformanceInsightsRetentionPeriod (__added__) +* AWS::RDS::DBCluster PubliclyAccessible (__added__) +* AWS::RDS::DBCluster ServerlessV2ScalingConfiguration (__added__) +* AWS::RDS::DBCluster StorageType (__added__) +* AWS::RDS::DBCluster BacktrackWindow.PrimitiveType (__changed__) + * Old: Long + * New: Integer +* AWS::RDS::DBCluster BackupRetentionPeriod.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backuprententionperiod + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backupretentionperiod +* AWS::RDS::DBCluster MasterUsername.UpdateType (__changed__) + * Old: Immutable + * New: Conditional +* AWS::RDS::DBCluster Tags.DuplicatesAllowed (__changed__) + * Old: true + * New: false +* AWS::RDS::DBClusterParameterGroup Tags.DuplicatesAllowed (__deleted__) +* AWS::RDS::DBInstance CustomIAMInstanceProfile.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::SageMaker::DataQualityJobDefinition EndpointName (__added__) +* AWS::SageMaker::Device DeviceFleetName.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::SageMaker::ModelBiasJobDefinition EndpointName (__added__) +* AWS::SageMaker::ModelExplainabilityJobDefinition EndpointName (__added__) +* AWS::SageMaker::ModelQualityJobDefinition EndpointName (__added__) +* AWS::SageMaker::NotebookInstance InstanceMetadataServiceConfiguration (__added__) +* AWS::SageMaker::Workteam WorkforceName (__added__) + +## Property Type Changes + +* AWS::DLM::LifecyclePolicy.ArchiveRetainRule (__added__) +* AWS::DLM::LifecyclePolicy.ArchiveRule (__added__) +* AWS::DLM::LifecyclePolicy.RetentionArchiveTier (__added__) +* AWS::DynamoDB::Table.Csv (__added__) +* AWS::DynamoDB::Table.ImportSourceSpecification (__added__) +* AWS::DynamoDB::Table.InputFormatOptions (__added__) +* AWS::DynamoDB::Table.S3BucketSource (__added__) +* AWS::ImageBuilder::ContainerRecipe.ComponentParameter (__added__) +* AWS::Macie::AllowList.S3WordsList (__added__) +* AWS::RDS::DBCluster.ReadEndpoint (__added__) +* AWS::RDS::DBCluster.ServerlessV2ScalingConfiguration (__added__) +* AWS::Redshift::ScheduledAction.PauseClusterMessage (__added__) +* AWS::Redshift::ScheduledAction.ResizeClusterMessage (__added__) +* AWS::Redshift::ScheduledAction.ResumeClusterMessage (__added__) +* AWS::S3::StorageLens.SSEKMS (__added__) +* AWS::SageMaker::Domain.RSessionAppSettings (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyExplainerConfig (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyFeatureType (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyHeader (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyInferenceConfig (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyShapBaselineConfig (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyShapConfig (__added__) +* AWS::SageMaker::EndpointConfig.ClarifyTextConfig (__added__) +* AWS::SageMaker::NotebookInstance.InstanceMetadataServiceConfiguration (__added__) +* AWS::SageMaker::Workteam.OidcMemberDefinition (__added__) +* AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts Type.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts Value.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TimeBasedCanary CanaryInterval.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary-canaryinterval + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-codedeploy-deploymentconfig-timebasedcanary-canaryinterval +* AWS::CodeDeploy::DeploymentConfig.TimeBasedCanary CanaryInterval.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TimeBasedCanary CanaryPercentage.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary-canarypercentage + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-codedeploy-deploymentconfig-timebasedcanary-canarypercentage +* AWS::CodeDeploy::DeploymentConfig.TimeBasedCanary CanaryPercentage.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TimeBasedLinear LinearInterval.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear-linearinterval + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-codedeploy-deploymentconfig-timebasedlinear-linearinterval +* AWS::CodeDeploy::DeploymentConfig.TimeBasedLinear LinearInterval.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TimeBasedLinear LinearPercentage.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear-linearpercentage + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-codedeploy-deploymentconfig-timebasedlinear-linearpercentage +* AWS::CodeDeploy::DeploymentConfig.TimeBasedLinear LinearPercentage.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig TimeBasedCanary.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig TimeBasedCanary.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig TimeBasedLinear.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig TimeBasedLinear.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig Type.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-type + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-type +* AWS::CodeDeploy::DeploymentConfig.TrafficRoutingConfig Type.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::DLM::LifecyclePolicy.Schedule ArchiveRule (__added__) +* AWS::DynamoDB::Table.AttributeDefinition AttributeName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-attributedefinition.html#cfn-dynamodb-table-attributedefinition-attributename +* AWS::DynamoDB::Table.AttributeDefinition AttributeType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-attributedefinition.html#cfn-dynamodb-table-attributedefinition-attributetype +* AWS::DynamoDB::Table.ContributorInsightsSpecification Enabled.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-contributorinsightsspecification.html#cfn-dynamodb-contributorinsightsspecification-enabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-contributorinsightsspecification.html#cfn-dynamodb-table-contributorinsightsspecification-enabled +* AWS::DynamoDB::Table.GlobalSecondaryIndex ContributorInsightsSpecification.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-contributorinsightsspecification-enabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-contributorinsightsspecification +* AWS::DynamoDB::Table.GlobalSecondaryIndex IndexName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-indexname +* AWS::DynamoDB::Table.GlobalSecondaryIndex KeySchema.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-keyschema +* AWS::DynamoDB::Table.GlobalSecondaryIndex Projection.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-projection +* AWS::DynamoDB::Table.GlobalSecondaryIndex ProvisionedThroughput.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-provisionedthroughput +* AWS::DynamoDB::Table.KeySchema AttributeName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-keyschema.html#cfn-dynamodb-table-keyschema-attributename +* AWS::DynamoDB::Table.KeySchema KeyType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-keyschema.html#cfn-dynamodb-table-keyschema-keytype +* AWS::DynamoDB::Table.KinesisStreamSpecification StreamArn.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-kinesisstreamspecification.html#cfn-dynamodb-kinesisstreamspecification-streamarn + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-kinesisstreamspecification.html#cfn-dynamodb-table-kinesisstreamspecification-streamarn +* AWS::DynamoDB::Table.LocalSecondaryIndex IndexName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-indexname +* AWS::DynamoDB::Table.LocalSecondaryIndex KeySchema.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-keyschema +* AWS::DynamoDB::Table.LocalSecondaryIndex Projection.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-projection +* AWS::DynamoDB::Table.Projection NonKeyAttributes.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-projection.html#cfn-dynamodb-table-projection-nonkeyattributes +* AWS::DynamoDB::Table.Projection ProjectionType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-projection.html#cfn-dynamodb-table-projection-projectiontype +* AWS::DynamoDB::Table.ProvisionedThroughput ReadCapacityUnits.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html#cfn-dynamodb-table-provisionedthroughput-readcapacityunits +* AWS::DynamoDB::Table.ProvisionedThroughput ReadCapacityUnits.PrimitiveType (__changed__) + * Old: Long + * New: Integer +* AWS::DynamoDB::Table.ProvisionedThroughput WriteCapacityUnits.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html#cfn-dynamodb-table-provisionedthroughput-writecapacityunits +* AWS::DynamoDB::Table.ProvisionedThroughput WriteCapacityUnits.PrimitiveType (__changed__) + * Old: Long + * New: Integer +* AWS::DynamoDB::Table.StreamSpecification StreamViewType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-streamspecification.html#cfn-dynamodb-table-streamspecification-streamviewtype +* AWS::DynamoDB::Table.TimeToLiveSpecification AttributeName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html#cfn-dynamodb-table-timetolivespecification-attributename +* AWS::DynamoDB::Table.TimeToLiveSpecification Enabled.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html#cfn-dynamodb-table-timetolivespecification-enabled +* AWS::ElasticBeanstalk::ApplicationVersion.SourceBundle S3Bucket.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-sourcebundle.html#cfn-beanstalk-sourcebundle-s3bucket + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-applicationversion-sourcebundle.html#cfn-elasticbeanstalk-applicationversion-sourcebundle-s3bucket +* AWS::ElasticBeanstalk::ApplicationVersion.SourceBundle S3Bucket.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::ElasticBeanstalk::ApplicationVersion.SourceBundle S3Key.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-sourcebundle.html#cfn-beanstalk-sourcebundle-s3key + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-applicationversion-sourcebundle.html#cfn-elasticbeanstalk-applicationversion-sourcebundle-s3key +* AWS::ElasticBeanstalk::ApplicationVersion.SourceBundle S3Key.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration Parameters (__added__) +* AWS::IoTSiteWise::Asset.AssetProperty Unit (__added__) +* AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile FactoryPresetFreqsList (__added__) +* AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile RxDataRate2 (__added__) +* AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile RxDelay1 (__added__) +* AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile RxDrOffset1 (__added__) +* AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile RxFreq2 (__added__) +* AWS::SageMaker::Device.Device DeviceName.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::SageMaker::Domain.ResourceSpec LifecycleConfigArn (__added__) +* AWS::SageMaker::Domain.UserSettings RSessionAppSettings (__added__) +* AWS::SageMaker::EndpointConfig.ProductionVariant ContainerStartupHealthCheckTimeoutInSeconds (__added__) +* AWS::SageMaker::EndpointConfig.ProductionVariant ModelDataDownloadTimeoutInSeconds (__added__) +* AWS::SageMaker::EndpointConfig.ProductionVariant VolumeSizeInGB (__added__) +* AWS::SageMaker::Workteam.MemberDefinition OidcMemberDefinition (__added__) +* AWS::SageMaker::Workteam.MemberDefinition CognitoMemberDefinition.Required (__changed__) + * Old: true + * New: false + +## Unapplied changes + +* AWS::IdentityStore is at 0.0.0 +* AWS::M2 is at 89.0.0 +* AWS::Rekognition is at 68.0.0 + # CloudFormation Resource Specification v89.0.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index b6ce3ca5971f9..b313bdb501c80 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -89.0.0 +91.0.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_ConnectCampaigns.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_ConnectCampaigns.rejected.json deleted file mode 100644 index 51d8b204e0703..0000000000000 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_ConnectCampaigns.rejected.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "PropertyTypes": { - "AWS::ConnectCampaigns::Campaign.DialerConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-dialerconfig.html" - }, - "AWS::ConnectCampaigns::Campaign.OutboundCallConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html", - "Properties": { - "ConnectContactFlowArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectcontactflowarn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ConnectQueueArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectqueuearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ConnectSourcePhoneNumber": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectsourcephonenumber", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - } - }, - "ResourceSpecificationVersion": "89.0.0", - "ResourceTypes": { - "AWS::ConnectCampaigns::Campaign": { - "Attributes": { - "Arn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html", - "Properties": { - "ConnectInstanceArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-connectinstancearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "DialerConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-dialerconfig", - "Required": true, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-name", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "OutboundCallConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-outboundcallconfig", - "Required": true, - "Type": "OutboundCallConfig", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-tags", - "DuplicatesAllowed": false, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - } - } -} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_IdentityStore.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_IdentityStore.rejected.json new file mode 100644 index 0000000000000..89e52f76c9fd5 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_IdentityStore.rejected.json @@ -0,0 +1,65 @@ +{ + "PropertyTypes": { + "AWS::IdentityStore::GroupMembership.MemberId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-identitystore-groupmembership-memberid.html" + } + }, + "ResourceSpecificationVersion": "91.0.0", + "ResourceTypes": { + "AWS::IdentityStore::Group": { + "Attributes": { + "GroupId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-group.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-group.html#cfn-identitystore-group-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DisplayName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-group.html#cfn-identitystore-group-displayname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "IdentityStoreId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-group.html#cfn-identitystore-group-identitystoreid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::IdentityStore::GroupMembership": { + "Attributes": { + "MembershipId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-groupmembership.html", + "Properties": { + "GroupId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-groupmembership.html#cfn-identitystore-groupmembership-groupid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "IdentityStoreId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-groupmembership.html#cfn-identitystore-groupmembership-identitystoreid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "MemberId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-identitystore-groupmembership.html#cfn-identitystore-groupmembership-memberid", + "Required": false, + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_M2.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_M2.rejected.json new file mode 100644 index 0000000000000..4e166a1ccf38d --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_M2.rejected.json @@ -0,0 +1,204 @@ +{ + "PropertyTypes": { + "AWS::M2::Application.Definition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-application-definition.html" + }, + "AWS::M2::Environment.EfsStorageConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-efsstorageconfiguration.html", + "Properties": { + "FileSystemId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-efsstorageconfiguration.html#cfn-m2-environment-efsstorageconfiguration-filesystemid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "MountPoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-efsstorageconfiguration.html#cfn-m2-environment-efsstorageconfiguration-mountpoint", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::M2::Environment.FsxStorageConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-fsxstorageconfiguration.html", + "Properties": { + "FileSystemId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-fsxstorageconfiguration.html#cfn-m2-environment-fsxstorageconfiguration-filesystemid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "MountPoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-fsxstorageconfiguration.html#cfn-m2-environment-fsxstorageconfiguration-mountpoint", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::M2::Environment.HighAvailabilityConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-highavailabilityconfig.html", + "Properties": { + "DesiredCapacity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-highavailabilityconfig.html#cfn-m2-environment-highavailabilityconfig-desiredcapacity", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::M2::Environment.StorageConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-storageconfiguration.html", + "Properties": { + "Efs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-storageconfiguration.html#cfn-m2-environment-storageconfiguration-efs", + "Required": false, + "Type": "EfsStorageConfiguration", + "UpdateType": "Immutable" + }, + "Fsx": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-environment-storageconfiguration.html#cfn-m2-environment-storageconfiguration-fsx", + "Required": false, + "Type": "FsxStorageConfiguration", + "UpdateType": "Immutable" + } + } + } + }, + "ResourceSpecificationVersion": "91.0.0", + "ResourceTypes": { + "AWS::M2::Application": { + "Attributes": { + "ApplicationArn": { + "PrimitiveType": "String" + }, + "ApplicationId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html", + "Properties": { + "Definition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html#cfn-m2-application-definition", + "Required": true, + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html#cfn-m2-application-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "EngineType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html#cfn-m2-application-enginetype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html#cfn-m2-application-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-application.html#cfn-m2-application-tags", + "PrimitiveItemType": "String", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + } + } + }, + "AWS::M2::Environment": { + "Attributes": { + "EnvironmentArn": { + "PrimitiveType": "String" + }, + "EnvironmentId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "EngineType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-enginetype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "EngineVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-engineversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "HighAvailabilityConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-highavailabilityconfig", + "Required": false, + "Type": "HighAvailabilityConfig", + "UpdateType": "Mutable" + }, + "InstanceType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-instancetype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "PreferredMaintenanceWindow": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-preferredmaintenancewindow", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PubliclyAccessible": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-publiclyaccessible", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Immutable" + }, + "SecurityGroupIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-securitygroupids", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "StorageConfigurations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-storageconfigurations", + "ItemType": "StorageConfiguration", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "SubnetIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-subnetids", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-m2-environment.html#cfn-m2-environment-tags", + "PrimitiveItemType": "String", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_Rekognition.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_Rekognition.rejected.json index cbf7aa544bdc1..c98e82182b399 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_Rekognition.rejected.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_Rekognition.rejected.json @@ -143,7 +143,7 @@ } } }, - "ResourceSpecificationVersion": "89.0.0", + "ResourceSpecificationVersion": "91.0.0", "ResourceTypes": { "AWS::Rekognition::Collection": { "Attributes": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_RolesAnywhere.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_RolesAnywhere.rejected.json deleted file mode 100644 index 76a2104ebbe93..0000000000000 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_RolesAnywhere.rejected.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "PropertyTypes": { - "AWS::RolesAnywhere::TrustAnchor.Source": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html", - "Properties": { - "SourceData": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html#cfn-rolesanywhere-trustanchor-source-sourcedata", - "Required": false, - "UpdateType": "Mutable" - }, - "SourceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html#cfn-rolesanywhere-trustanchor-source-sourcetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::RolesAnywhere::TrustAnchor.SourceData": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-sourcedata.html" - } - }, - "ResourceSpecificationVersion": "89.0.0", - "ResourceTypes": { - "AWS::RolesAnywhere::CRL": { - "Attributes": { - "CrlId": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html", - "Properties": { - "CrlData": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-crldata", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Enabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-enabled", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-name", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "TrustAnchorArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-trustanchorarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::RolesAnywhere::Profile": { - "Attributes": { - "ProfileArn": { - "PrimitiveType": "String" - }, - "ProfileId": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html", - "Properties": { - "DurationSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-durationseconds", - "PrimitiveType": "Double", - "Required": false, - "UpdateType": "Mutable" - }, - "Enabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-enabled", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "ManagedPolicyArns": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-managedpolicyarns", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-name", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "RequireInstanceProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-requireinstanceproperties", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "RoleArns": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-rolearns", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SessionPolicy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-sessionpolicy", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::RolesAnywhere::TrustAnchor": { - "Attributes": { - "TrustAnchorArn": { - "PrimitiveType": "String" - }, - "TrustAnchorId": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html", - "Properties": { - "Enabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-enabled", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-name", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Source": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-source", - "Required": false, - "Type": "Source", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - } - } -} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_SageMaker.rejected.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_SageMaker.rejected.json deleted file mode 100644 index 6a483814692c7..0000000000000 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/.000_AWS_SageMaker.rejected.json +++ /dev/null @@ -1,5032 +0,0 @@ -{ - "PropertyTypes": { - "AWS::SageMaker::App.ResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html", - "Properties": { - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html#cfn-sagemaker-app-resourcespec-instancetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html#cfn-sagemaker-app-resourcespec-sagemakerimagearn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageVersionArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html#cfn-sagemaker-app-resourcespec-sagemakerimageversionarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::AppImageConfig.FileSystemConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-filesystemconfig.html", - "Properties": { - "DefaultGid": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-filesystemconfig.html#cfn-sagemaker-appimageconfig-filesystemconfig-defaultgid", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - }, - "DefaultUid": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-filesystemconfig.html#cfn-sagemaker-appimageconfig-filesystemconfig-defaultuid", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - }, - "MountPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-filesystemconfig.html#cfn-sagemaker-appimageconfig-filesystemconfig-mountpath", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::AppImageConfig.KernelGatewayImageConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelgatewayimageconfig.html", - "Properties": { - "FileSystemConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelgatewayimageconfig.html#cfn-sagemaker-appimageconfig-kernelgatewayimageconfig-filesystemconfig", - "Required": false, - "Type": "FileSystemConfig", - "UpdateType": "Mutable" - }, - "KernelSpecs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelgatewayimageconfig.html#cfn-sagemaker-appimageconfig-kernelgatewayimageconfig-kernelspecs", - "ItemType": "KernelSpec", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::AppImageConfig.KernelSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelspec.html", - "Properties": { - "DisplayName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelspec.html#cfn-sagemaker-appimageconfig-kernelspec-displayname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-appimageconfig-kernelspec.html#cfn-sagemaker-appimageconfig-kernelspec-name", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::CodeRepository.GitConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-coderepository-gitconfig.html", - "Properties": { - "Branch": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-coderepository-gitconfig.html#cfn-sagemaker-coderepository-gitconfig-branch", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "RepositoryUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-coderepository-gitconfig.html#cfn-sagemaker-coderepository-gitconfig-repositoryurl", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "SecretArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-coderepository-gitconfig.html#cfn-sagemaker-coderepository-gitconfig-secretarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-clusterconfig.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-clusterconfig.html#cfn-sagemaker-dataqualityjobdefinition-clusterconfig-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-clusterconfig.html#cfn-sagemaker-dataqualityjobdefinition-clusterconfig-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-clusterconfig.html#cfn-sagemaker-dataqualityjobdefinition-clusterconfig-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-clusterconfig.html#cfn-sagemaker-dataqualityjobdefinition-clusterconfig-volumesizeingb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-constraintsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-constraintsresource.html#cfn-sagemaker-dataqualityjobdefinition-constraintsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.DataQualityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html", - "Properties": { - "ContainerArguments": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-containerarguments", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "ContainerEntrypoint": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-containerentrypoint", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Immutable" - }, - "ImageUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-imageuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "PostAnalyticsProcessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-postanalyticsprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "RecordPreprocessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityappspecification.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification-recordpreprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.DataQualityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig.html", - "Properties": { - "BaseliningJobName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig.html#cfn-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig-baseliningjobname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig.html#cfn-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig-constraintsresource", - "Required": false, - "Type": "ConstraintsResource", - "UpdateType": "Immutable" - }, - "StatisticsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig.html#cfn-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig-statisticsresource", - "Required": false, - "Type": "StatisticsResource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.DataQualityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityjobinput.html", - "Properties": { - "EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-dataqualityjobinput.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityjobinput-endpointinput", - "Required": true, - "Type": "EndpointInput", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-endpointinput.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-endpointinput.html#cfn-sagemaker-dataqualityjobdefinition-endpointinput-endpointname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-endpointinput.html#cfn-sagemaker-dataqualityjobdefinition-endpointinput-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3DataDistributionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-endpointinput.html#cfn-sagemaker-dataqualityjobdefinition-endpointinput-s3datadistributiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3InputMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-endpointinput.html#cfn-sagemaker-dataqualityjobdefinition-endpointinput-s3inputmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.MonitoringOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringoutput.html", - "Properties": { - "S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringoutput.html#cfn-sagemaker-dataqualityjobdefinition-monitoringoutput-s3output", - "Required": true, - "Type": "S3Output", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-dataqualityjobdefinition-monitoringoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "MonitoringOutputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-dataqualityjobdefinition-monitoringoutputconfig-monitoringoutputs", - "ItemType": "MonitoringOutput", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-monitoringresources.html#cfn-sagemaker-dataqualityjobdefinition-monitoringresources-clusterconfig", - "Required": true, - "Type": "ClusterConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-networkconfig.html", - "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-networkconfig.html#cfn-sagemaker-dataqualityjobdefinition-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-networkconfig.html#cfn-sagemaker-dataqualityjobdefinition-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-networkconfig.html#cfn-sagemaker-dataqualityjobdefinition-networkconfig-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-s3output.html", - "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-s3output.html#cfn-sagemaker-dataqualityjobdefinition-s3output-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-s3output.html#cfn-sagemaker-dataqualityjobdefinition-s3output-s3uploadmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-s3output.html#cfn-sagemaker-dataqualityjobdefinition-s3output-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.StatisticsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-statisticsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-statisticsresource.html#cfn-sagemaker-dataqualityjobdefinition-statisticsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-stoppingcondition.html", - "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-stoppingcondition.html#cfn-sagemaker-dataqualityjobdefinition-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-vpcconfig.html#cfn-sagemaker-dataqualityjobdefinition-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-dataqualityjobdefinition-vpcconfig.html#cfn-sagemaker-dataqualityjobdefinition-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Device.Device": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html", - "Properties": { - "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html#cfn-sagemaker-device-device-description", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "DeviceName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html#cfn-sagemaker-device-device-devicename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "IotThingName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html#cfn-sagemaker-device-device-iotthingname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::DeviceFleet.EdgeOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-devicefleet-edgeoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-devicefleet-edgeoutputconfig.html#cfn-sagemaker-devicefleet-edgeoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3OutputLocation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-devicefleet-edgeoutputconfig.html#cfn-sagemaker-devicefleet-edgeoutputconfig-s3outputlocation", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.CustomImage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-customimage.html", - "Properties": { - "AppImageConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-customimage.html#cfn-sagemaker-domain-customimage-appimageconfigname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ImageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-customimage.html#cfn-sagemaker-domain-customimage-imagename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ImageVersionNumber": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-customimage.html#cfn-sagemaker-domain-customimage-imageversionnumber", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.DomainSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-domainsettings.html", - "Properties": { - "RStudioServerProDomainSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-domainsettings.html#cfn-sagemaker-domain-domainsettings-rstudioserverprodomainsettings", - "Required": false, - "Type": "RStudioServerProDomainSettings", - "UpdateType": "Mutable" - }, - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-domainsettings.html#cfn-sagemaker-domain-domainsettings-securitygroupids", - "DuplicatesAllowed": true, - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Domain.JupyterServerAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-jupyterserverappsettings.html", - "Properties": { - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-jupyterserverappsettings.html#cfn-sagemaker-domain-jupyterserverappsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.KernelGatewayAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-kernelgatewayappsettings.html", - "Properties": { - "CustomImages": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-kernelgatewayappsettings.html#cfn-sagemaker-domain-kernelgatewayappsettings-customimages", - "DuplicatesAllowed": true, - "ItemType": "CustomImage", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-kernelgatewayappsettings.html#cfn-sagemaker-domain-kernelgatewayappsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.RSessionAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html", - "Properties": { - "CustomImages": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html#cfn-sagemaker-domain-rsessionappsettings-customimages", - "DuplicatesAllowed": true, - "ItemType": "CustomImage", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html#cfn-sagemaker-domain-rsessionappsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.RStudioServerProAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverproappsettings.html", - "Properties": { - "AccessStatus": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverproappsettings.html#cfn-sagemaker-domain-rstudioserverproappsettings-accessstatus", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "UserGroup": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverproappsettings.html#cfn-sagemaker-domain-rstudioserverproappsettings-usergroup", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.RStudioServerProDomainSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverprodomainsettings.html", - "Properties": { - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverprodomainsettings.html#cfn-sagemaker-domain-rstudioserverprodomainsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Immutable" - }, - "DomainExecutionRoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverprodomainsettings.html#cfn-sagemaker-domain-rstudioserverprodomainsettings-domainexecutionrolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "RStudioConnectUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverprodomainsettings.html#cfn-sagemaker-domain-rstudioserverprodomainsettings-rstudioconnecturl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "RStudioPackageManagerUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverprodomainsettings.html#cfn-sagemaker-domain-rstudioserverprodomainsettings-rstudiopackagemanagerurl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.ResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html", - "Properties": { - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-instancetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "LifecycleConfigArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-lifecycleconfigarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-sagemakerimagearn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageVersionArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-sagemakerimageversionarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.SharingSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-sharingsettings.html", - "Properties": { - "NotebookOutputOption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-sharingsettings.html#cfn-sagemaker-domain-sharingsettings-notebookoutputoption", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-sharingsettings.html#cfn-sagemaker-domain-sharingsettings-s3kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3OutputPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-sharingsettings.html#cfn-sagemaker-domain-sharingsettings-s3outputpath", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain.UserSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html", - "Properties": { - "ExecutionRole": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-executionrole", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JupyterServerAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-jupyterserverappsettings", - "Required": false, - "Type": "JupyterServerAppSettings", - "UpdateType": "Mutable" - }, - "KernelGatewayAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-kernelgatewayappsettings", - "Required": false, - "Type": "KernelGatewayAppSettings", - "UpdateType": "Mutable" - }, - "RSessionAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-rsessionappsettings", - "Required": false, - "Type": "RSessionAppSettings", - "UpdateType": "Mutable" - }, - "RStudioServerProAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-rstudioserverproappsettings", - "Required": false, - "Type": "RStudioServerProAppSettings", - "UpdateType": "Mutable" - }, - "SecurityGroups": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-securitygroups", - "DuplicatesAllowed": true, - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SharingSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-sharingsettings", - "Required": false, - "Type": "SharingSettings", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.Alarm": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-alarm.html", - "Properties": { - "AlarmName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-alarm.html#cfn-sagemaker-endpoint-alarm-alarmname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.AutoRollbackConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-autorollbackconfig.html", - "Properties": { - "Alarms": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-autorollbackconfig.html#cfn-sagemaker-endpoint-autorollbackconfig-alarms", - "ItemType": "Alarm", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.BlueGreenUpdatePolicy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-bluegreenupdatepolicy.html", - "Properties": { - "MaximumExecutionTimeoutInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-bluegreenupdatepolicy.html#cfn-sagemaker-endpoint-bluegreenupdatepolicy-maximumexecutiontimeoutinseconds", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - }, - "TerminationWaitInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-bluegreenupdatepolicy.html#cfn-sagemaker-endpoint-bluegreenupdatepolicy-terminationwaitinseconds", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - }, - "TrafficRoutingConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-bluegreenupdatepolicy.html#cfn-sagemaker-endpoint-bluegreenupdatepolicy-trafficroutingconfiguration", - "Required": true, - "Type": "TrafficRoutingConfig", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.CapacitySize": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-capacitysize.html", - "Properties": { - "Type": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-capacitysize.html#cfn-sagemaker-endpoint-capacitysize-type", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Value": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-capacitysize.html#cfn-sagemaker-endpoint-capacitysize-value", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.DeploymentConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-deploymentconfig.html", - "Properties": { - "AutoRollbackConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-deploymentconfig.html#cfn-sagemaker-endpoint-deploymentconfig-autorollbackconfiguration", - "Required": false, - "Type": "AutoRollbackConfig", - "UpdateType": "Mutable" - }, - "BlueGreenUpdatePolicy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-deploymentconfig.html#cfn-sagemaker-endpoint-deploymentconfig-bluegreenupdatepolicy", - "Required": true, - "Type": "BlueGreenUpdatePolicy", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.TrafficRoutingConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-trafficroutingconfig.html", - "Properties": { - "CanarySize": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-trafficroutingconfig.html#cfn-sagemaker-endpoint-trafficroutingconfig-canarysize", - "Required": false, - "Type": "CapacitySize", - "UpdateType": "Mutable" - }, - "LinearStepSize": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-trafficroutingconfig.html#cfn-sagemaker-endpoint-trafficroutingconfig-linearstepsize", - "Required": false, - "Type": "CapacitySize", - "UpdateType": "Mutable" - }, - "Type": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-trafficroutingconfig.html#cfn-sagemaker-endpoint-trafficroutingconfig-type", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "WaitIntervalInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-trafficroutingconfig.html#cfn-sagemaker-endpoint-trafficroutingconfig-waitintervalinseconds", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Endpoint.VariantProperty": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-variantproperty.html", - "Properties": { - "VariantPropertyType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpoint-variantproperty.html#cfn-sagemaker-endpoint-variantproperty-variantpropertytype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.AsyncInferenceClientConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceclientconfig.html", - "Properties": { - "MaxConcurrentInvocationsPerInstance": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceclientconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceclientconfig-maxconcurrentinvocationsperinstance", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.AsyncInferenceConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html", - "Properties": { - "ClientConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig-clientconfig", - "Required": false, - "Type": "AsyncInferenceClientConfig", - "UpdateType": "Immutable" - }, - "OutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig-outputconfig", - "Required": true, - "Type": "AsyncInferenceOutputConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.AsyncInferenceNotificationConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html", - "Properties": { - "ErrorTopic": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html#cfn-sagemaker-endpointconfig-asyncinferencenotificationconfig-errortopic", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "SuccessTopic": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html#cfn-sagemaker-endpointconfig-asyncinferencenotificationconfig-successtopic", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.AsyncInferenceOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "NotificationConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-notificationconfig", - "Required": false, - "Type": "AsyncInferenceNotificationConfig", - "UpdateType": "Immutable" - }, - "S3OutputPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-s3outputpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.CaptureContentTypeHeader": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader.html", - "Properties": { - "CsvContentTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader.html#cfn-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader-csvcontenttypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "JsonContentTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader.html#cfn-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader-jsoncontenttypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.CaptureOption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-captureoption.html", - "Properties": { - "CaptureMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-captureoption.html#cfn-sagemaker-endpointconfig-captureoption-capturemode", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ClarifyExplainerConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html", - "Properties": { - "EnableExplanations": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-enableexplanations", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "InferenceConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-inferenceconfig", - "Required": false, - "Type": "ClarifyInferenceConfig", - "UpdateType": "Immutable" - }, - "ShapConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-shapconfig", - "Required": true, - "Type": "ClarifyShapConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ClarifyFeatureType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyfeaturetype.html", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "AWS::SageMaker::EndpointConfig.ClarifyHeader": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyheader.html", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "AWS::SageMaker::EndpointConfig.ClarifyInferenceConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html", - "Properties": { - "ContentTemplate": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-contenttemplate", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "FeatureHeaders": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featureheaders", - "ItemType": "ClarifyHeader", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "FeatureTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featuretypes", - "ItemType": "ClarifyFeatureType", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "FeaturesAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featuresattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LabelAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LabelHeaders": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelheaders", - "ItemType": "ClarifyHeader", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "LabelIndex": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelindex", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "MaxPayloadInMB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-maxpayloadinmb", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "MaxRecordCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-maxrecordcount", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "ProbabilityAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-probabilityattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProbabilityIndex": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-probabilityindex", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ClarifyShapBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html", - "Properties": { - "MimeType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-mimetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ShapBaseline": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-shapbaseline", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ShapBaselineUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-shapbaselineuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ClarifyShapConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html", - "Properties": { - "NumberOfSamples": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-numberofsamples", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "Seed": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-seed", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "ShapBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-shapbaselineconfig", - "Required": true, - "Type": "ClarifyShapBaselineConfig", - "UpdateType": "Immutable" - }, - "TextConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-textconfig", - "Required": false, - "Type": "ClarifyTextConfig", - "UpdateType": "Immutable" - }, - "UseLogit": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-uselogit", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ClarifyTextConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html", - "Properties": { - "Granularity": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html#cfn-sagemaker-endpointconfig-clarifytextconfig-granularity", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "Language": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html#cfn-sagemaker-endpointconfig-clarifytextconfig-language", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.DataCaptureConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html", - "Properties": { - "CaptureContentTypeHeader": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader", - "Required": false, - "Type": "CaptureContentTypeHeader", - "UpdateType": "Immutable" - }, - "CaptureOptions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-captureoptions", - "ItemType": "CaptureOption", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "DestinationS3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-destinations3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "EnableCapture": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-enablecapture", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "InitialSamplingPercentage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-initialsamplingpercentage", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ProductionVariant": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html", - "Properties": { - "AcceleratorType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-acceleratortype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "InitialInstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-initialinstancecount", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "InitialVariantWeight": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-initialvariantweight", - "PrimitiveType": "Double", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-instancetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-modelname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ServerlessConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-serverlessconfig", - "Required": false, - "Type": "ServerlessConfig", - "UpdateType": "Mutable" - }, - "VariantName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-variantname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::EndpointConfig.ServerlessConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant-serverlessconfig.html", - "Properties": { - "MaxConcurrency": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant-serverlessconfig.html#cfn-sagemaker-endpointconfig-productionvariant-serverlessconfig-maxconcurrency", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "MemorySizeInMB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant-serverlessconfig.html#cfn-sagemaker-endpointconfig-productionvariant-serverlessconfig-memorysizeinmb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::FeatureGroup.FeatureDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-featuregroup-featuredefinition.html", - "Properties": { - "FeatureName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-featuregroup-featuredefinition.html#cfn-sagemaker-featuregroup-featuredefinition-featurename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "FeatureType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-featuregroup-featuredefinition.html#cfn-sagemaker-featuregroup-featuredefinition-featuretype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.ContainerDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html", - "Properties": { - "ContainerHostname": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-containerhostname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-environment", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Immutable" - }, - "Image": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-image", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ImageConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-imageconfig", - "Required": false, - "Type": "ImageConfig", - "UpdateType": "Immutable" - }, - "InferenceSpecificationName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-inferencespecificationname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Mode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-mode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelDataUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-modeldataurl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelPackageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-modelpackagename", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "MultiModelConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition.html#cfn-sagemaker-model-containerdefinition-multimodelconfig", - "Required": false, - "Type": "MultiModelConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.ImageConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig.html", - "Properties": { - "RepositoryAccessMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig.html#cfn-sagemaker-model-containerdefinition-imageconfig-repositoryaccessmode", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "RepositoryAuthConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig.html#cfn-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig", - "Required": false, - "Type": "RepositoryAuthConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.InferenceExecutionConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-inferenceexecutionconfig.html", - "Properties": { - "Mode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-inferenceexecutionconfig.html#cfn-sagemaker-model-inferenceexecutionconfig-mode", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.MultiModelConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-multimodelconfig.html", - "Properties": { - "ModelCacheSetting": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-multimodelconfig.html#cfn-sagemaker-model-containerdefinition-multimodelconfig-modelcachesetting", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.RepositoryAuthConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig.html", - "Properties": { - "RepositoryCredentialsProviderArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig.html#cfn-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig-repositorycredentialsproviderarn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-vpcconfig.html#cfn-sagemaker-model-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-vpcconfig.html#cfn-sagemaker-model-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-clusterconfig.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-clusterconfig.html#cfn-sagemaker-modelbiasjobdefinition-clusterconfig-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-clusterconfig.html#cfn-sagemaker-modelbiasjobdefinition-clusterconfig-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-clusterconfig.html#cfn-sagemaker-modelbiasjobdefinition-clusterconfig-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-clusterconfig.html#cfn-sagemaker-modelbiasjobdefinition-clusterconfig-volumesizeingb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-constraintsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-constraintsresource.html#cfn-sagemaker-modelbiasjobdefinition-constraintsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html", - "Properties": { - "EndTimeOffset": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-endtimeoffset", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-endpointname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "FeaturesAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-featuresattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "InferenceAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-inferenceattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ProbabilityAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-probabilityattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProbabilityThresholdAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-probabilitythresholdattribute", - "PrimitiveType": "Double", - "Required": false, - "UpdateType": "Immutable" - }, - "S3DataDistributionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-s3datadistributiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3InputMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-s3inputmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "StartTimeOffset": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-endpointinput.html#cfn-sagemaker-modelbiasjobdefinition-endpointinput-starttimeoffset", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.ModelBiasAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasappspecification.html", - "Properties": { - "ConfigUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasappspecification.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasappspecification-configuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasappspecification.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasappspecification-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Immutable" - }, - "ImageUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasappspecification.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasappspecification-imageuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.ModelBiasBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig.html", - "Properties": { - "BaseliningJobName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig-baseliningjobname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig-constraintsresource", - "Required": false, - "Type": "ConstraintsResource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.ModelBiasJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasjobinput.html", - "Properties": { - "EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasjobinput.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasjobinput-endpointinput", - "Required": true, - "Type": "EndpointInput", - "UpdateType": "Immutable" - }, - "GroundTruthS3Input": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-modelbiasjobinput.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasjobinput-groundtruths3input", - "Required": true, - "Type": "MonitoringGroundTruthS3Input", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.MonitoringGroundTruthS3Input": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringgroundtruths3input.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringgroundtruths3input.html#cfn-sagemaker-modelbiasjobdefinition-monitoringgroundtruths3input-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.MonitoringOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringoutput.html", - "Properties": { - "S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringoutput.html#cfn-sagemaker-modelbiasjobdefinition-monitoringoutput-s3output", - "Required": true, - "Type": "S3Output", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelbiasjobdefinition-monitoringoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "MonitoringOutputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelbiasjobdefinition-monitoringoutputconfig-monitoringoutputs", - "ItemType": "MonitoringOutput", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-monitoringresources.html#cfn-sagemaker-modelbiasjobdefinition-monitoringresources-clusterconfig", - "Required": true, - "Type": "ClusterConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-networkconfig.html", - "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-networkconfig.html#cfn-sagemaker-modelbiasjobdefinition-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-networkconfig.html#cfn-sagemaker-modelbiasjobdefinition-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-networkconfig.html#cfn-sagemaker-modelbiasjobdefinition-networkconfig-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-s3output.html", - "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-s3output.html#cfn-sagemaker-modelbiasjobdefinition-s3output-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-s3output.html#cfn-sagemaker-modelbiasjobdefinition-s3output-s3uploadmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-s3output.html#cfn-sagemaker-modelbiasjobdefinition-s3output-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-stoppingcondition.html", - "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-stoppingcondition.html#cfn-sagemaker-modelbiasjobdefinition-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-vpcconfig.html#cfn-sagemaker-modelbiasjobdefinition-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelbiasjobdefinition-vpcconfig.html#cfn-sagemaker-modelbiasjobdefinition-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-clusterconfig.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-clusterconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-clusterconfig-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-clusterconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-clusterconfig-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-clusterconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-clusterconfig-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-clusterconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-clusterconfig-volumesizeingb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-constraintsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-constraintsresource.html#cfn-sagemaker-modelexplainabilityjobdefinition-constraintsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-endpointname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "FeaturesAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-featuresattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "InferenceAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-inferenceattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ProbabilityAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-probabilityattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3DataDistributionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-s3datadistributiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3InputMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-endpointinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointinput-s3inputmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.ModelExplainabilityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification.html", - "Properties": { - "ConfigUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification-configuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Immutable" - }, - "ImageUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification-imageuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.ModelExplainabilityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig.html", - "Properties": { - "BaseliningJobName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig-baseliningjobname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig-constraintsresource", - "Required": false, - "Type": "ConstraintsResource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.ModelExplainabilityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityjobinput.html", - "Properties": { - "EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityjobinput.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityjobinput-endpointinput", - "Required": true, - "Type": "EndpointInput", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.MonitoringOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutput.html", - "Properties": { - "S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutput.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringoutput-s3output", - "Required": true, - "Type": "S3Output", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "MonitoringOutputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig-monitoringoutputs", - "ItemType": "MonitoringOutput", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringresources-clusterconfig", - "Required": true, - "Type": "ClusterConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html", - "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html", - "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uploadmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html", - "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html#cfn-sagemaker-modelexplainabilityjobdefinition-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.AdditionalInferenceSpecificationDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html", - "Properties": { - "Containers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-containers", - "ItemType": "ModelPackageContainerDefinition", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - }, - "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-description", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-name", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "SupportedContentTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedcontenttypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SupportedRealtimeInferenceInstanceTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedrealtimeinferenceinstancetypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SupportedResponseMIMETypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedresponsemimetypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SupportedTransformInstanceTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedtransforminstancetypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ModelPackage.Bias": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html", - "Properties": { - "PostTrainingReport": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-posttrainingreport", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "PreTrainingReport": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-pretrainingreport", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "Report": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-report", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.CreatedBy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-createdby.html" - }, - "AWS::SageMaker::ModelPackage.DataSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-datasource.html", - "Properties": { - "S3DataSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-datasource.html#cfn-sagemaker-modelpackage-datasource-s3datasource", - "Required": true, - "Type": "S3DataSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.DriftCheckBaselines": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html", - "Properties": { - "Bias": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-bias", - "Required": false, - "Type": "DriftCheckBias", - "UpdateType": "Immutable" - }, - "Explainability": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-explainability", - "Required": false, - "Type": "DriftCheckExplainability", - "UpdateType": "Immutable" - }, - "ModelDataQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-modeldataquality", - "Required": false, - "Type": "DriftCheckModelDataQuality", - "UpdateType": "Immutable" - }, - "ModelQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-modelquality", - "Required": false, - "Type": "DriftCheckModelQuality", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.DriftCheckBias": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html", - "Properties": { - "ConfigFile": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-configfile", - "Required": false, - "Type": "FileSource", - "UpdateType": "Immutable" - }, - "PostTrainingConstraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-posttrainingconstraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "PreTrainingConstraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-pretrainingconstraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.DriftCheckExplainability": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html", - "Properties": { - "ConfigFile": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html#cfn-sagemaker-modelpackage-driftcheckexplainability-configfile", - "Required": false, - "Type": "FileSource", - "UpdateType": "Immutable" - }, - "Constraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html#cfn-sagemaker-modelpackage-driftcheckexplainability-constraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.DriftCheckModelDataQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html", - "Properties": { - "Constraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html#cfn-sagemaker-modelpackage-driftcheckmodeldataquality-constraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "Statistics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html#cfn-sagemaker-modelpackage-driftcheckmodeldataquality-statistics", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.DriftCheckModelQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html", - "Properties": { - "Constraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html#cfn-sagemaker-modelpackage-driftcheckmodelquality-constraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "Statistics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html#cfn-sagemaker-modelpackage-driftcheckmodelquality-statistics", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-environment.html", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" - }, - "AWS::SageMaker::ModelPackage.Explainability": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-explainability.html", - "Properties": { - "Report": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-explainability.html#cfn-sagemaker-modelpackage-explainability-report", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.FileSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html", - "Properties": { - "ContentDigest": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-contentdigest", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ContentType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-contenttype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.InferenceSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html", - "Properties": { - "Containers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-containers", - "DuplicatesAllowed": false, - "ItemType": "ModelPackageContainerDefinition", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "SupportedContentTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedcontenttypes", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "SupportedRealtimeInferenceInstanceTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedrealtimeinferenceinstancetypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "SupportedResponseMIMETypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedresponsemimetypes", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "SupportedTransformInstanceTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedtransforminstancetypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.LastModifiedBy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-lastmodifiedby.html" - }, - "AWS::SageMaker::ModelPackage.MetadataProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html", - "Properties": { - "CommitId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-commitid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "GeneratedBy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-generatedby", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProjectId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-projectid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Repository": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-repository", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.MetricsSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html", - "Properties": { - "ContentDigest": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-contentdigest", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ContentType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-contenttype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelDataQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html", - "Properties": { - "Constraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html#cfn-sagemaker-modelpackage-modeldataquality-constraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "Statistics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html#cfn-sagemaker-modelpackage-modeldataquality-statistics", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelMetrics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html", - "Properties": { - "Bias": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-bias", - "Required": false, - "Type": "Bias", - "UpdateType": "Immutable" - }, - "Explainability": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-explainability", - "Required": false, - "Type": "Explainability", - "UpdateType": "Immutable" - }, - "ModelDataQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-modeldataquality", - "Required": false, - "Type": "ModelDataQuality", - "UpdateType": "Immutable" - }, - "ModelQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-modelquality", - "Required": false, - "Type": "ModelQuality", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelPackageContainerDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html", - "Properties": { - "ContainerHostname": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-containerhostname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-environment", - "Required": false, - "Type": "Environment", - "UpdateType": "Mutable" - }, - "Framework": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-framework", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "FrameworkVersion": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-frameworkversion", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Image": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-image", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ImageDigest": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-imagedigest", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ModelDataUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-modeldataurl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ModelInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-modelinput", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" - }, - "NearestModelName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-nearestmodelname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ProductId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-productid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelPackageStatusDetails": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html", - "Properties": { - "ImageScanStatuses": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails-imagescanstatuses", - "ItemType": "ModelPackageStatusItem", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "ValidationStatuses": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails-validationstatuses", - "ItemType": "ModelPackageStatusItem", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelPackageStatusItem": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html", - "Properties": { - "FailureReason": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-failurereason", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Name": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-name", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Status": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-status", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ModelQuality": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html", - "Properties": { - "Constraints": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html#cfn-sagemaker-modelpackage-modelquality-constraints", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - }, - "Statistics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html#cfn-sagemaker-modelpackage-modelquality-statistics", - "Required": false, - "Type": "MetricsSource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.S3DataSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html", - "Properties": { - "S3DataType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html#cfn-sagemaker-modelpackage-s3datasource-s3datatype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html#cfn-sagemaker-modelpackage-s3datasource-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.SourceAlgorithm": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html", - "Properties": { - "AlgorithmName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html#cfn-sagemaker-modelpackage-sourcealgorithm-algorithmname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ModelDataUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html#cfn-sagemaker-modelpackage-sourcealgorithm-modeldataurl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.SourceAlgorithmSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithmspecification.html", - "Properties": { - "SourceAlgorithms": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithmspecification.html#cfn-sagemaker-modelpackage-sourcealgorithmspecification-sourcealgorithms", - "ItemType": "SourceAlgorithm", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.TransformInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html", - "Properties": { - "CompressionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-compressiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ContentType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-contenttype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "DataSource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-datasource", - "Required": true, - "Type": "DataSource", - "UpdateType": "Immutable" - }, - "SplitType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-splittype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.TransformJobDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html", - "Properties": { - "BatchStrategy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-batchstrategy", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-environment", - "Required": false, - "Type": "Environment", - "UpdateType": "Immutable" - }, - "MaxConcurrentTransforms": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-maxconcurrenttransforms", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "MaxPayloadInMB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-maxpayloadinmb", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Immutable" - }, - "TransformInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transforminput", - "Required": true, - "Type": "TransformInput", - "UpdateType": "Immutable" - }, - "TransformOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transformoutput", - "Required": true, - "Type": "TransformOutput", - "UpdateType": "Immutable" - }, - "TransformResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transformresources", - "Required": true, - "Type": "TransformResources", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.TransformOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html", - "Properties": { - "Accept": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-accept", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "AssembleWith": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-assemblewith", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3OutputPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-s3outputpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.TransformResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ValidationProfile": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html", - "Properties": { - "ProfileName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html#cfn-sagemaker-modelpackage-validationprofile-profilename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "TransformJobDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html#cfn-sagemaker-modelpackage-validationprofile-transformjobdefinition", - "Required": true, - "Type": "TransformJobDefinition", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage.ValidationSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html", - "Properties": { - "ValidationProfiles": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html#cfn-sagemaker-modelpackage-validationspecification-validationprofiles", - "ItemType": "ValidationProfile", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "ValidationRole": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html#cfn-sagemaker-modelpackage-validationspecification-validationrole", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-clusterconfig.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-clusterconfig.html#cfn-sagemaker-modelqualityjobdefinition-clusterconfig-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-clusterconfig.html#cfn-sagemaker-modelqualityjobdefinition-clusterconfig-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-clusterconfig.html#cfn-sagemaker-modelqualityjobdefinition-clusterconfig-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-clusterconfig.html#cfn-sagemaker-modelqualityjobdefinition-clusterconfig-volumesizeingb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-constraintsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-constraintsresource.html#cfn-sagemaker-modelqualityjobdefinition-constraintsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html", - "Properties": { - "EndTimeOffset": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-endtimeoffset", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-endpointname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "InferenceAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-inferenceattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ProbabilityAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-probabilityattribute", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProbabilityThresholdAttribute": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-probabilitythresholdattribute", - "PrimitiveType": "Double", - "Required": false, - "UpdateType": "Immutable" - }, - "S3DataDistributionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-s3datadistributiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3InputMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-s3inputmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "StartTimeOffset": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-endpointinput.html#cfn-sagemaker-modelqualityjobdefinition-endpointinput-starttimeoffset", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.ModelQualityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html", - "Properties": { - "ContainerArguments": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-containerarguments", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "ContainerEntrypoint": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-containerentrypoint", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Immutable" - }, - "ImageUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-imageuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "PostAnalyticsProcessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-postanalyticsprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProblemType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-problemtype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "RecordPreprocessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityappspecification.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification-recordpreprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.ModelQualityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig.html", - "Properties": { - "BaseliningJobName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig.html#cfn-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig-baseliningjobname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig.html#cfn-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig-constraintsresource", - "Required": false, - "Type": "ConstraintsResource", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.ModelQualityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityjobinput.html", - "Properties": { - "EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityjobinput.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityjobinput-endpointinput", - "Required": true, - "Type": "EndpointInput", - "UpdateType": "Immutable" - }, - "GroundTruthS3Input": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-modelqualityjobinput.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityjobinput-groundtruths3input", - "Required": true, - "Type": "MonitoringGroundTruthS3Input", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.MonitoringGroundTruthS3Input": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringgroundtruths3input.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringgroundtruths3input.html#cfn-sagemaker-modelqualityjobdefinition-monitoringgroundtruths3input-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.MonitoringOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringoutput.html", - "Properties": { - "S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringoutput.html#cfn-sagemaker-modelqualityjobdefinition-monitoringoutput-s3output", - "Required": true, - "Type": "S3Output", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelqualityjobdefinition-monitoringoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "MonitoringOutputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelqualityjobdefinition-monitoringoutputconfig-monitoringoutputs", - "ItemType": "MonitoringOutput", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-monitoringresources.html#cfn-sagemaker-modelqualityjobdefinition-monitoringresources-clusterconfig", - "Required": true, - "Type": "ClusterConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-networkconfig.html", - "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-networkconfig.html#cfn-sagemaker-modelqualityjobdefinition-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-networkconfig.html#cfn-sagemaker-modelqualityjobdefinition-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-networkconfig.html#cfn-sagemaker-modelqualityjobdefinition-networkconfig-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-s3output.html", - "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-s3output.html#cfn-sagemaker-modelqualityjobdefinition-s3output-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-s3output.html#cfn-sagemaker-modelqualityjobdefinition-s3output-s3uploadmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-s3output.html#cfn-sagemaker-modelqualityjobdefinition-s3output-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-stoppingcondition.html", - "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-stoppingcondition.html#cfn-sagemaker-modelqualityjobdefinition-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-vpcconfig.html#cfn-sagemaker-modelqualityjobdefinition-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelqualityjobdefinition-vpcconfig.html#cfn-sagemaker-modelqualityjobdefinition-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.BaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-baselineconfig.html", - "Properties": { - "ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-baselineconfig.html#cfn-sagemaker-monitoringschedule-baselineconfig-constraintsresource", - "Required": false, - "Type": "ConstraintsResource", - "UpdateType": "Mutable" - }, - "StatisticsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-baselineconfig.html#cfn-sagemaker-monitoringschedule-baselineconfig-statisticsresource", - "Required": false, - "Type": "StatisticsResource", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-clusterconfig.html", - "Properties": { - "InstanceCount": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-clusterconfig.html#cfn-sagemaker-monitoringschedule-clusterconfig-instancecount", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Mutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-clusterconfig.html#cfn-sagemaker-monitoringschedule-clusterconfig-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "VolumeKmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-clusterconfig.html#cfn-sagemaker-monitoringschedule-clusterconfig-volumekmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-clusterconfig.html#cfn-sagemaker-monitoringschedule-clusterconfig-volumesizeingb", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.ConstraintsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-constraintsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-constraintsresource.html#cfn-sagemaker-monitoringschedule-constraintsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-endpointinput.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-endpointinput.html#cfn-sagemaker-monitoringschedule-endpointinput-endpointname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-endpointinput.html#cfn-sagemaker-monitoringschedule-endpointinput-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "S3DataDistributionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-endpointinput.html#cfn-sagemaker-monitoringschedule-endpointinput-s3datadistributiontype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3InputMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-endpointinput.html#cfn-sagemaker-monitoringschedule-endpointinput-s3inputmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html", - "Properties": { - "ContainerArguments": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html#cfn-sagemaker-monitoringschedule-monitoringappspecification-containerarguments", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "ContainerEntrypoint": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html#cfn-sagemaker-monitoringschedule-monitoringappspecification-containerentrypoint", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "ImageUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html#cfn-sagemaker-monitoringschedule-monitoringappspecification-imageuri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "PostAnalyticsProcessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html#cfn-sagemaker-monitoringschedule-monitoringappspecification-postanalyticsprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "RecordPreprocessorSourceUri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringappspecification.html#cfn-sagemaker-monitoringschedule-monitoringappspecification-recordpreprocessorsourceuri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringExecutionSummary": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html", - "Properties": { - "CreationTime": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-creationtime", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "FailureReason": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-failurereason", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "LastModifiedTime": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-lastmodifiedtime", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "MonitoringExecutionStatus": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-monitoringexecutionstatus", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "MonitoringScheduleName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-monitoringschedulename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ProcessingJobArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-processingjobarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ScheduledTime": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringexecutionsummary.html#cfn-sagemaker-monitoringschedule-monitoringexecutionsummary-scheduledtime", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringinput.html", - "Properties": { - "EndpointInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringinput.html#cfn-sagemaker-monitoringschedule-monitoringinput-endpointinput", - "Required": true, - "Type": "EndpointInput", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringJobDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html", - "Properties": { - "BaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-baselineconfig", - "Required": false, - "Type": "BaselineConfig", - "UpdateType": "Mutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Mutable" - }, - "MonitoringAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-monitoringappspecification", - "Required": true, - "Type": "MonitoringAppSpecification", - "UpdateType": "Mutable" - }, - "MonitoringInputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-monitoringinputs", - "ItemType": "MonitoringInput", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - }, - "MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-monitoringoutputconfig", - "Required": true, - "Type": "MonitoringOutputConfig", - "UpdateType": "Mutable" - }, - "MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-monitoringresources", - "Required": true, - "Type": "MonitoringResources", - "UpdateType": "Mutable" - }, - "NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-networkconfig", - "Required": false, - "Type": "NetworkConfig", - "UpdateType": "Mutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringjobdefinition.html#cfn-sagemaker-monitoringschedule-monitoringjobdefinition-stoppingcondition", - "Required": false, - "Type": "StoppingCondition", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringOutput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringoutput.html", - "Properties": { - "S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringoutput.html#cfn-sagemaker-monitoringschedule-monitoringoutput-s3output", - "Required": true, - "Type": "S3Output", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringoutputconfig.html", - "Properties": { - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringoutputconfig.html#cfn-sagemaker-monitoringschedule-monitoringoutputconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "MonitoringOutputs": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringoutputconfig.html#cfn-sagemaker-monitoringschedule-monitoringoutputconfig-monitoringoutputs", - "ItemType": "MonitoringOutput", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringresources.html#cfn-sagemaker-monitoringschedule-monitoringresources-clusterconfig", - "Required": true, - "Type": "ClusterConfig", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.MonitoringScheduleConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringscheduleconfig.html", - "Properties": { - "MonitoringJobDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringscheduleconfig.html#cfn-sagemaker-monitoringschedule-monitoringscheduleconfig-monitoringjobdefinition", - "Required": false, - "Type": "MonitoringJobDefinition", - "UpdateType": "Mutable" - }, - "MonitoringJobDefinitionName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringscheduleconfig.html#cfn-sagemaker-monitoringschedule-monitoringscheduleconfig-monitoringjobdefinitionname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "MonitoringType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringscheduleconfig.html#cfn-sagemaker-monitoringschedule-monitoringscheduleconfig-monitoringtype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ScheduleConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-monitoringscheduleconfig.html#cfn-sagemaker-monitoringschedule-monitoringscheduleconfig-scheduleconfig", - "Required": false, - "Type": "ScheduleConfig", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-networkconfig.html", - "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-networkconfig.html#cfn-sagemaker-monitoringschedule-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-networkconfig.html#cfn-sagemaker-monitoringschedule-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-networkconfig.html#cfn-sagemaker-monitoringschedule-networkconfig-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-s3output.html", - "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-s3output.html#cfn-sagemaker-monitoringschedule-s3output-localpath", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-s3output.html#cfn-sagemaker-monitoringschedule-s3output-s3uploadmode", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-s3output.html#cfn-sagemaker-monitoringschedule-s3output-s3uri", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.ScheduleConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-scheduleconfig.html", - "Properties": { - "ScheduleExpression": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-scheduleconfig.html#cfn-sagemaker-monitoringschedule-scheduleconfig-scheduleexpression", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.StatisticsResource": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-statisticsresource.html", - "Properties": { - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-statisticsresource.html#cfn-sagemaker-monitoringschedule-statisticsresource-s3uri", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-stoppingcondition.html", - "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-stoppingcondition.html#cfn-sagemaker-monitoringschedule-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-vpcconfig.html", - "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-vpcconfig.html#cfn-sagemaker-monitoringschedule-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-monitoringschedule-vpcconfig.html#cfn-sagemaker-monitoringschedule-vpcconfig-subnets", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::NotebookInstance.InstanceMetadataServiceConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstance-instancemetadataserviceconfiguration.html", - "Properties": { - "MinimumInstanceMetadataServiceVersion": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstance-instancemetadataserviceconfiguration.html#cfn-sagemaker-notebookinstance-instancemetadataserviceconfiguration-minimuminstancemetadataserviceversion", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::NotebookInstanceLifecycleConfig.NotebookInstanceLifecycleHook": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstancelifecycleconfig-notebookinstancelifecyclehook.html", - "Properties": { - "Content": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstancelifecycleconfig-notebookinstancelifecyclehook.html#cfn-sagemaker-notebookinstancelifecycleconfig-notebookinstancelifecyclehook-content", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.CustomImage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-customimage.html", - "Properties": { - "AppImageConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-customimage.html#cfn-sagemaker-userprofile-customimage-appimageconfigname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ImageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-customimage.html#cfn-sagemaker-userprofile-customimage-imagename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "ImageVersionNumber": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-customimage.html#cfn-sagemaker-userprofile-customimage-imageversionnumber", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.JupyterServerAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-jupyterserverappsettings.html", - "Properties": { - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-jupyterserverappsettings.html#cfn-sagemaker-userprofile-jupyterserverappsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.KernelGatewayAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-kernelgatewayappsettings.html", - "Properties": { - "CustomImages": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-kernelgatewayappsettings.html#cfn-sagemaker-userprofile-kernelgatewayappsettings-customimages", - "DuplicatesAllowed": true, - "ItemType": "CustomImage", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "DefaultResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-kernelgatewayappsettings.html#cfn-sagemaker-userprofile-kernelgatewayappsettings-defaultresourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.RStudioServerProAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-rstudioserverproappsettings.html", - "Properties": { - "AccessStatus": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-rstudioserverproappsettings.html#cfn-sagemaker-userprofile-rstudioserverproappsettings-accessstatus", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "UserGroup": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-rstudioserverproappsettings.html#cfn-sagemaker-userprofile-rstudioserverproappsettings-usergroup", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::UserProfile.ResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-resourcespec.html", - "Properties": { - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-resourcespec.html#cfn-sagemaker-userprofile-resourcespec-instancetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-resourcespec.html#cfn-sagemaker-userprofile-resourcespec-sagemakerimagearn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SageMakerImageVersionArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-resourcespec.html#cfn-sagemaker-userprofile-resourcespec-sagemakerimageversionarn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.SharingSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-sharingsettings.html", - "Properties": { - "NotebookOutputOption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-sharingsettings.html#cfn-sagemaker-userprofile-sharingsettings-notebookoutputoption", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-sharingsettings.html#cfn-sagemaker-userprofile-sharingsettings-s3kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "S3OutputPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-sharingsettings.html#cfn-sagemaker-userprofile-sharingsettings-s3outputpath", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::UserProfile.UserSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html", - "Properties": { - "ExecutionRole": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-executionrole", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JupyterServerAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-jupyterserverappsettings", - "Required": false, - "Type": "JupyterServerAppSettings", - "UpdateType": "Mutable" - }, - "KernelGatewayAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-kernelgatewayappsettings", - "Required": false, - "Type": "KernelGatewayAppSettings", - "UpdateType": "Mutable" - }, - "RStudioServerProAppSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-rstudioserverproappsettings", - "Required": false, - "Type": "RStudioServerProAppSettings", - "UpdateType": "Mutable" - }, - "SecurityGroups": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-securitygroups", - "DuplicatesAllowed": true, - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "SharingSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-userprofile-usersettings.html#cfn-sagemaker-userprofile-usersettings-sharingsettings", - "Required": false, - "Type": "SharingSettings", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Workteam.CognitoMemberDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-cognitomemberdefinition.html", - "Properties": { - "CognitoClientId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-cognitomemberdefinition.html#cfn-sagemaker-workteam-cognitomemberdefinition-cognitoclientid", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "CognitoUserGroup": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-cognitomemberdefinition.html#cfn-sagemaker-workteam-cognitomemberdefinition-cognitousergroup", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "CognitoUserPool": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-cognitomemberdefinition.html#cfn-sagemaker-workteam-cognitomemberdefinition-cognitouserpool", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Workteam.MemberDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-memberdefinition.html", - "Properties": { - "CognitoMemberDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-memberdefinition.html#cfn-sagemaker-workteam-memberdefinition-cognitomemberdefinition", - "Required": false, - "Type": "CognitoMemberDefinition", - "UpdateType": "Mutable" - }, - "OidcMemberDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-memberdefinition.html#cfn-sagemaker-workteam-memberdefinition-oidcmemberdefinition", - "Required": false, - "Type": "OidcMemberDefinition", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Workteam.NotificationConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-notificationconfiguration.html", - "Properties": { - "NotificationTopicArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-notificationconfiguration.html#cfn-sagemaker-workteam-notificationconfiguration-notificationtopicarn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Workteam.OidcMemberDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-oidcmemberdefinition.html", - "Properties": { - "OidcGroups": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-oidcmemberdefinition.html#cfn-sagemaker-workteam-oidcmemberdefinition-oidcgroups", - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Mutable" - } - } - } - }, - "ResourceSpecificationVersion": "89.0.0", - "ResourceTypes": { - "AWS::SageMaker::App": { - "Attributes": { - "AppArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html", - "Properties": { - "AppName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-appname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "AppType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-apptype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "DomainId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-domainid", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ResourceSpec": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-resourcespec", - "Required": false, - "Type": "ResourceSpec", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "UserProfileName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-app.html#cfn-sagemaker-app-userprofilename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::AppImageConfig": { - "Attributes": { - "AppImageConfigArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-appimageconfig.html", - "Properties": { - "AppImageConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-appimageconfig.html#cfn-sagemaker-appimageconfig-appimageconfigname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "KernelGatewayImageConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-appimageconfig.html#cfn-sagemaker-appimageconfig-kernelgatewayimageconfig", - "Required": false, - "Type": "KernelGatewayImageConfig", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-appimageconfig.html#cfn-sagemaker-appimageconfig-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::CodeRepository": { - "Attributes": { - "CodeRepositoryName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-coderepository.html", - "Properties": { - "CodeRepositoryName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-coderepository.html#cfn-sagemaker-coderepository-coderepositoryname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "GitConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-coderepository.html#cfn-sagemaker-coderepository-gitconfig", - "Required": true, - "Type": "GitConfig", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-coderepository.html#cfn-sagemaker-coderepository-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::DataQualityJobDefinition": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "JobDefinitionArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html", - "Properties": { - "DataQualityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityappspecification", - "Required": true, - "Type": "DataQualityAppSpecification", - "UpdateType": "Immutable" - }, - "DataQualityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-dataqualitybaselineconfig", - "Required": false, - "Type": "DataQualityBaselineConfig", - "UpdateType": "Immutable" - }, - "DataQualityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityjobinput", - "Required": true, - "Type": "DataQualityJobInput", - "UpdateType": "Immutable" - }, - "DataQualityJobOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-dataqualityjoboutputconfig", - "Required": true, - "Type": "MonitoringOutputConfig", - "UpdateType": "Immutable" - }, - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JobDefinitionName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-jobdefinitionname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "JobResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-jobresources", - "Required": true, - "Type": "MonitoringResources", - "UpdateType": "Immutable" - }, - "NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-networkconfig", - "Required": false, - "Type": "NetworkConfig", - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-stoppingcondition", - "Required": false, - "Type": "StoppingCondition", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Device": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html", - "Properties": { - "Device": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-device", - "Required": false, - "Type": "Device", - "UpdateType": "Mutable" - }, - "DeviceFleetName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-devicefleetname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::DeviceFleet": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html", - "Properties": { - "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html#cfn-sagemaker-devicefleet-description", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "DeviceFleetName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html#cfn-sagemaker-devicefleet-devicefleetname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "OutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html#cfn-sagemaker-devicefleet-outputconfig", - "Required": true, - "Type": "EdgeOutputConfig", - "UpdateType": "Mutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html#cfn-sagemaker-devicefleet-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-devicefleet.html#cfn-sagemaker-devicefleet-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Domain": { - "Attributes": { - "DomainArn": { - "PrimitiveType": "String" - }, - "DomainId": { - "PrimitiveType": "String" - }, - "HomeEfsFileSystemId": { - "PrimitiveType": "String" - }, - "SecurityGroupIdForDomainBoundary": { - "PrimitiveType": "String" - }, - "SingleSignOnManagedApplicationInstanceId": { - "PrimitiveType": "String" - }, - "Url": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html", - "Properties": { - "AppNetworkAccessType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-appnetworkaccesstype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "AppSecurityGroupManagement": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-appsecuritygroupmanagement", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "AuthMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-authmode", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "DefaultUserSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-defaultusersettings", - "Required": true, - "Type": "UserSettings", - "UpdateType": "Mutable" - }, - "DomainName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-domainname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "DomainSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-domainsettings", - "Required": false, - "Type": "DomainSettings", - "UpdateType": "Mutable" - }, - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "SubnetIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-subnetids", - "DuplicatesAllowed": true, - "PrimitiveItemType": "String", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "VpcId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-domain.html#cfn-sagemaker-domain-vpcid", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Endpoint": { - "Attributes": { - "EndpointName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html", - "Properties": { - "DeploymentConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-deploymentconfig", - "Required": false, - "Type": "DeploymentConfig", - "UpdateType": "Mutable" - }, - "EndpointConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-endpointconfigname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ExcludeRetainedVariantProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-excluderetainedvariantproperties", - "ItemType": "VariantProperty", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "RetainAllVariantProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-retainallvariantproperties", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "RetainDeploymentConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-retaindeploymentconfig", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpoint.html#cfn-sagemaker-endpoint-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::EndpointConfig": { - "Attributes": { - "EndpointConfigName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html", - "Properties": { - "AsyncInferenceConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig", - "Required": false, - "Type": "AsyncInferenceConfig", - "UpdateType": "Immutable" - }, - "DataCaptureConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig", - "Required": false, - "Type": "DataCaptureConfig", - "UpdateType": "Immutable" - }, - "EndpointConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-endpointconfigname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProductionVariants": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-productionvariants", - "ItemType": "ProductionVariant", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::FeatureGroup": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html", - "Properties": { - "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-description", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "EventTimeFeatureName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-eventtimefeaturename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "FeatureDefinitions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-featuredefinitions", - "DuplicatesAllowed": true, - "ItemType": "FeatureDefinition", - "Required": true, - "Type": "List", - "UpdateType": "Immutable" - }, - "FeatureGroupName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-featuregroupname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "OfflineStoreConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-offlinestoreconfig", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Immutable" - }, - "OnlineStoreConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-onlinestoreconfig", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Immutable" - }, - "RecordIdentifierFeatureName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-recordidentifierfeaturename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-rolearn", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-featuregroup.html#cfn-sagemaker-featuregroup-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Image": { - "Attributes": { - "ImageArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html", - "Properties": { - "ImageDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html#cfn-sagemaker-image-imagedescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ImageDisplayName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html#cfn-sagemaker-image-imagedisplayname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ImageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html#cfn-sagemaker-image-imagename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ImageRoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html#cfn-sagemaker-image-imagerolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-image.html#cfn-sagemaker-image-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ImageVersion": { - "Attributes": { - "ContainerImage": { - "PrimitiveType": "String" - }, - "ImageArn": { - "PrimitiveType": "String" - }, - "ImageVersionArn": { - "PrimitiveType": "String" - }, - "Version": { - "PrimitiveType": "Integer" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-imageversion.html", - "Properties": { - "BaseImage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-imageversion.html#cfn-sagemaker-imageversion-baseimage", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ImageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-imageversion.html#cfn-sagemaker-imageversion-imagename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::Model": { - "Attributes": { - "ModelName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html", - "Properties": { - "Containers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-containers", - "ItemType": "ContainerDefinition", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-enablenetworkisolation", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Immutable" - }, - "ExecutionRoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-executionrolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "InferenceExecutionConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-inferenceexecutionconfig", - "Required": false, - "Type": "InferenceExecutionConfig", - "UpdateType": "Immutable" - }, - "ModelName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-modelname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "PrimaryContainer": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-primarycontainer", - "Required": false, - "Type": "ContainerDefinition", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-model.html#cfn-sagemaker-model-vpcconfig", - "Required": false, - "Type": "VpcConfig", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelBiasJobDefinition": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "JobDefinitionArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JobDefinitionName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-jobdefinitionname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "JobResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-jobresources", - "Required": true, - "Type": "MonitoringResources", - "UpdateType": "Immutable" - }, - "ModelBiasAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasappspecification", - "Required": true, - "Type": "ModelBiasAppSpecification", - "UpdateType": "Immutable" - }, - "ModelBiasBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasbaselineconfig", - "Required": false, - "Type": "ModelBiasBaselineConfig", - "UpdateType": "Immutable" - }, - "ModelBiasJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasjobinput", - "Required": true, - "Type": "ModelBiasJobInput", - "UpdateType": "Immutable" - }, - "ModelBiasJobOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-modelbiasjoboutputconfig", - "Required": true, - "Type": "MonitoringOutputConfig", - "UpdateType": "Immutable" - }, - "NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-networkconfig", - "Required": false, - "Type": "NetworkConfig", - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-stoppingcondition", - "Required": false, - "Type": "StoppingCondition", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "JobDefinitionArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JobDefinitionName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-jobdefinitionname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "JobResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-jobresources", - "Required": true, - "Type": "MonitoringResources", - "UpdateType": "Immutable" - }, - "ModelExplainabilityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityappspecification", - "Required": true, - "Type": "ModelExplainabilityAppSpecification", - "UpdateType": "Immutable" - }, - "ModelExplainabilityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilitybaselineconfig", - "Required": false, - "Type": "ModelExplainabilityBaselineConfig", - "UpdateType": "Immutable" - }, - "ModelExplainabilityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityjobinput", - "Required": true, - "Type": "ModelExplainabilityJobInput", - "UpdateType": "Immutable" - }, - "ModelExplainabilityJobOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-modelexplainabilityjoboutputconfig", - "Required": true, - "Type": "MonitoringOutputConfig", - "UpdateType": "Immutable" - }, - "NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig", - "Required": false, - "Type": "NetworkConfig", - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-stoppingcondition", - "Required": false, - "Type": "StoppingCondition", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackage": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "ModelPackageArn": { - "PrimitiveType": "String" - }, - "ModelPackageStatus": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html", - "Properties": { - "AdditionalInferenceSpecificationDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition", - "Required": false, - "Type": "AdditionalInferenceSpecificationDefinition", - "UpdateType": "Mutable" - }, - "AdditionalInferenceSpecifications": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecifications", - "ItemType": "AdditionalInferenceSpecificationDefinition", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "AdditionalInferenceSpecificationsToAdd": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecificationstoadd", - "ItemType": "AdditionalInferenceSpecificationDefinition", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "ApprovalDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-approvaldescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "CertifyForMarketplace": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-certifyformarketplace", - "PrimitiveType": "Boolean", - "Required": false, - "UpdateType": "Mutable" - }, - "ClientToken": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-clienttoken", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "CreatedBy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-createdby", - "Required": false, - "UpdateType": "Mutable" - }, - "CustomerMetadataProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-customermetadataproperties", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Mutable" - }, - "Domain": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-domain", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "DriftCheckBaselines": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-driftcheckbaselines", - "Required": false, - "Type": "DriftCheckBaselines", - "UpdateType": "Immutable" - }, - "Environment": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-environment", - "PrimitiveItemType": "String", - "Required": false, - "Type": "Map", - "UpdateType": "Mutable" - }, - "InferenceSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-inferencespecification", - "Required": false, - "Type": "InferenceSpecification", - "UpdateType": "Immutable" - }, - "LastModifiedBy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-lastmodifiedby", - "Required": false, - "UpdateType": "Mutable" - }, - "LastModifiedTime": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-lastmodifiedtime", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "MetadataProperties": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-metadataproperties", - "Required": false, - "Type": "MetadataProperties", - "UpdateType": "Immutable" - }, - "ModelApprovalStatus": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelapprovalstatus", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ModelMetrics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelmetrics", - "Required": false, - "Type": "ModelMetrics", - "UpdateType": "Immutable" - }, - "ModelPackageDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagedescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelPackageGroupName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagegroupname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelPackageName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagename", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "ModelPackageStatusDetails": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails", - "Required": false, - "Type": "ModelPackageStatusDetails", - "UpdateType": "Mutable" - }, - "ModelPackageStatusItem": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagestatusitem", - "Required": false, - "Type": "ModelPackageStatusItem", - "UpdateType": "Mutable" - }, - "ModelPackageVersion": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackageversion", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - }, - "SamplePayloadUrl": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-samplepayloadurl", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "SourceAlgorithmSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-sourcealgorithmspecification", - "Required": false, - "Type": "SourceAlgorithmSpecification", - "UpdateType": "Immutable" - }, - "Tag": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-tag", - "Required": false, - "Type": "Tag", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "Task": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-task", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ValidationSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-validationspecification", - "Required": false, - "Type": "ValidationSpecification", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelPackageGroup": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "ModelPackageGroupArn": { - "PrimitiveType": "String" - }, - "ModelPackageGroupStatus": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackagegroup.html", - "Properties": { - "ModelPackageGroupDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackagegroup.html#cfn-sagemaker-modelpackagegroup-modelpackagegroupdescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ModelPackageGroupName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackagegroup.html#cfn-sagemaker-modelpackagegroup-modelpackagegroupname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ModelPackageGroupPolicy": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackagegroup.html#cfn-sagemaker-modelpackagegroup-modelpackagegrouppolicy", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackagegroup.html#cfn-sagemaker-modelpackagegroup-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::ModelQualityJobDefinition": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "JobDefinitionArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "JobDefinitionName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-jobdefinitionname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "JobResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-jobresources", - "Required": true, - "Type": "MonitoringResources", - "UpdateType": "Immutable" - }, - "ModelQualityAppSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityappspecification", - "Required": true, - "Type": "ModelQualityAppSpecification", - "UpdateType": "Immutable" - }, - "ModelQualityBaselineConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-modelqualitybaselineconfig", - "Required": false, - "Type": "ModelQualityBaselineConfig", - "UpdateType": "Immutable" - }, - "ModelQualityJobInput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityjobinput", - "Required": true, - "Type": "ModelQualityJobInput", - "UpdateType": "Immutable" - }, - "ModelQualityJobOutputConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-modelqualityjoboutputconfig", - "Required": true, - "Type": "MonitoringOutputConfig", - "UpdateType": "Immutable" - }, - "NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-networkconfig", - "Required": false, - "Type": "NetworkConfig", - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-stoppingcondition", - "Required": false, - "Type": "StoppingCondition", - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::MonitoringSchedule": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "LastModifiedTime": { - "PrimitiveType": "String" - }, - "MonitoringScheduleArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html", - "Properties": { - "EndpointName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-endpointname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "FailureReason": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-failurereason", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "LastMonitoringExecutionSummary": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-lastmonitoringexecutionsummary", - "Required": false, - "Type": "MonitoringExecutionSummary", - "UpdateType": "Mutable" - }, - "MonitoringScheduleConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-monitoringscheduleconfig", - "Required": true, - "Type": "MonitoringScheduleConfig", - "UpdateType": "Mutable" - }, - "MonitoringScheduleName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-monitoringschedulename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "MonitoringScheduleStatus": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-monitoringschedulestatus", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-monitoringschedule.html#cfn-sagemaker-monitoringschedule-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::NotebookInstance": { - "Attributes": { - "NotebookInstanceName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html", - "Properties": { - "AcceleratorTypes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-acceleratortypes", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "AdditionalCodeRepositories": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-additionalcoderepositories", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "DefaultCodeRepository": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-defaultcoderepository", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "DirectInternetAccess": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-directinternetaccess", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "InstanceMetadataServiceConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-instancemetadataserviceconfiguration", - "Required": false, - "Type": "InstanceMetadataServiceConfiguration", - "UpdateType": "Mutable" - }, - "InstanceType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-instancetype", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-kmskeyid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "LifecycleConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-lifecycleconfigname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "NotebookInstanceName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-notebookinstancename", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "PlatformIdentifier": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-platformidentifier", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "RootAccess": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-rootaccess", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-securitygroupids", - "PrimitiveItemType": "String", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "SubnetId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-subnetid", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "VolumeSizeInGB": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-volumesizeingb", - "PrimitiveType": "Integer", - "Required": false, - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::NotebookInstanceLifecycleConfig": { - "Attributes": { - "NotebookInstanceLifecycleConfigName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstancelifecycleconfig.html", - "Properties": { - "NotebookInstanceLifecycleConfigName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstancelifecycleconfig.html#cfn-sagemaker-notebookinstancelifecycleconfig-notebookinstancelifecycleconfigname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "OnCreate": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstancelifecycleconfig.html#cfn-sagemaker-notebookinstancelifecycleconfig-oncreate", - "ItemType": "NotebookInstanceLifecycleHook", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "OnStart": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstancelifecycleconfig.html#cfn-sagemaker-notebookinstancelifecycleconfig-onstart", - "ItemType": "NotebookInstanceLifecycleHook", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Pipeline": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html", - "Properties": { - "ParallelismConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-parallelismconfiguration", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" - }, - "PipelineDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-pipelinedefinition", - "PrimitiveType": "Json", - "Required": true, - "UpdateType": "Mutable" - }, - "PipelineDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-pipelinedescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "PipelineDisplayName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-pipelinedisplayname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "PipelineName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-pipelinename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-rolearn", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-pipeline.html#cfn-sagemaker-pipeline-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Project": { - "Attributes": { - "CreationTime": { - "PrimitiveType": "String" - }, - "ProjectArn": { - "PrimitiveType": "String" - }, - "ProjectId": { - "PrimitiveType": "String" - }, - "ProjectStatus": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-project.html", - "Properties": { - "ProjectDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-project.html#cfn-sagemaker-project-projectdescription", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "ProjectName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-project.html#cfn-sagemaker-project-projectname", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "ServiceCatalogProvisioningDetails": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-project.html#cfn-sagemaker-project-servicecatalogprovisioningdetails", - "PrimitiveType": "Json", - "Required": true, - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-project.html#cfn-sagemaker-project-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::UserProfile": { - "Attributes": { - "UserProfileArn": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html", - "Properties": { - "DomainId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-domainid", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "SingleSignOnUserIdentifier": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-singlesignonuseridentifier", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "SingleSignOnUserValue": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-singlesignonuservalue", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-tags", - "DuplicatesAllowed": true, - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Immutable" - }, - "UserProfileName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-userprofilename", - "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" - }, - "UserSettings": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-userprofile.html#cfn-sagemaker-userprofile-usersettings", - "Required": false, - "Type": "UserSettings", - "UpdateType": "Mutable" - } - } - }, - "AWS::SageMaker::Workteam": { - "Attributes": { - "WorkteamName": { - "PrimitiveType": "String" - } - }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html", - "Properties": { - "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-description", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Mutable" - }, - "MemberDefinitions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-memberdefinitions", - "ItemType": "MemberDefinition", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "NotificationConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-notificationconfiguration", - "Required": false, - "Type": "NotificationConfiguration", - "UpdateType": "Mutable" - }, - "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-tags", - "ItemType": "Tag", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, - "WorkforceName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-workforcename", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, - "WorkteamName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-workteamname", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - } - } - } - } -} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json index e5f7cb9c11510..2e3ca0b71fdda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ACMPCA::Certificate.ApiPassthrough": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-acmpca-certificate-apipassthrough.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json index ce00c0d42e1da..4c24cc428e5c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::APS::Workspace.LoggingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-aps-workspace-loggingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json index e3e352a99525b..9d20217a90055 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AccessAnalyzer::Analyzer.ArchiveRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-accessanalyzer-analyzer-archiverule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json index decfff07c49d5..021b1d565a7e5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AmazonMQ::Broker.ConfigurationId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amazonmq-broker-configurationid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json index 5b4d85d049b99..3450af0a5ac65 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Amplify::App.AutoBranchCreationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplify-app-autobranchcreationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json index 0e8879c917ffd..277171327511d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AmplifyUIBuilder::Component.ActionParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json index fe69b14e0a0b1..945420cc6c6ac 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ApiGateway::ApiKey.StageKey": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-apikey-stagekey.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json index 33be55d8782b3..dc014483102e5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ApiGatewayV2::Api.BodyS3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-api-bodys3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json index 49845dbe62184..48c2df20cdcba 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppConfig::Application.Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appconfig-application-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json index bd5c263bcea3c..86ca9aa5cbadc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppFlow::ConnectorProfile.AmplitudeConnectorProfileCredentials": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-connectorprofile-amplitudeconnectorprofilecredentials.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json index 16bf9f245bc94..0ce61d49fb0e7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppIntegrations::DataIntegration.ScheduleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json index 59fcdd55e6078..84d10ddef0d8f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppMesh::GatewayRoute.GatewayRouteHostnameMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-gatewayroute-gatewayroutehostnamematch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json index 47dc740367f95..3a5d4e68f32aa 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppRunner::ObservabilityConfiguration.TraceConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-observabilityconfiguration-traceconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json index d13300fb4c1f7..65baa1d4b85b2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppStream::AppBlock.S3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-appblock-s3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json index 8085e98ee8695..33672b8c315c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AppSync::DataSource.AuthorizationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-authorizationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json index 5a373c7d332f4..29305f03dcf71 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ApplicationAutoScaling::ScalableTarget.ScalableTargetAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationautoscaling-scalabletarget-scalabletargetaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json index f45892884658a..58dfb5a54a436 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ApplicationInsights::Application.Alarm": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationinsights-application-alarm.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json index 601db5507c7ed..b615850c2ca2e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Athena::WorkGroup.EncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-athena-workgroup-encryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json index 56fc59a1976e7..84eb331cd18ab 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AuditManager::Assessment.AWSAccount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-auditmanager-assessment-awsaccount.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json index a476007db82df..6f5addd9f4b47 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AutoScaling::AutoScalingGroup.AcceleratorCountRequest": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-acceleratorcountrequest.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json index eb8ad8b24a3ba..2bbc5959c94a5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::AutoScalingPlans::ScalingPlan.ApplicationSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscalingplans-scalingplan-applicationsource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json index c93bafdfdcc70..dc4a715a8ca27 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Backup::BackupPlan.AdvancedBackupSettingResourceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-advancedbackupsettingresourcetype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json index 61a4454eb0610..ceaf17b072e4c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Batch::ComputeEnvironment.ComputeResources": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_BillingConductor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_BillingConductor.json index 40f2ba94fb66f..a433df4ba6bc1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_BillingConductor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_BillingConductor.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::BillingConductor::BillingGroup.AccountGrouping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-billingconductor-billinggroup-accountgrouping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json index a2bf1596252f0..6b44c19164046 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Budgets::Budget.BudgetData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-budgets-budget-budgetdata.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json index e1d5edf81e988..28f7e9dc7d04c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CE::AnomalyMonitor.ResourceTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalymonitor-resourcetag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json index 727b31c3d5690..257a93c3c53dc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CUR::ReportDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json index 7ff0ae09b2b24..2533d571e02c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Cassandra::Table.BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cassandra-table-billingmode.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json index 22222792bff71..6853384d418c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CertificateManager::Account.ExpiryEventsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json index dac5c40ea10d3..a91fce6d881f1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Chatbot::SlackChannelConfiguration": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json index 22dfd77224559..2ad357240c61b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Cloud9::EnvironmentEC2.Repository": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloud9-environmentec2-repository.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json index 754105d624ac3..5f30b331eaf48 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CloudFormation::HookVersion.LoggingConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-hookversion-loggingconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json index 4eb7e26638896..17efda6c52cd0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-cachepolicy-cachepolicyconfig.html", @@ -1115,6 +1115,28 @@ } } }, + "AWS::CloudFront::MonitoringSubscription.MonitoringSubscription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-monitoringsubscription-monitoringsubscription.html", + "Properties": { + "RealtimeMetricsSubscriptionConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-monitoringsubscription-monitoringsubscription.html#cfn-cloudfront-monitoringsubscription-monitoringsubscription-realtimemetricssubscriptionconfig", + "Required": false, + "Type": "RealtimeMetricsSubscriptionConfig", + "UpdateType": "Mutable" + } + } + }, + "AWS::CloudFront::MonitoringSubscription.RealtimeMetricsSubscriptionConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-monitoringsubscription-realtimemetricssubscriptionconfig.html", + "Properties": { + "RealtimeMetricsSubscriptionStatus": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-monitoringsubscription-realtimemetricssubscriptionconfig.html#cfn-cloudfront-monitoringsubscription-realtimemetricssubscriptionconfig-realtimemetricssubscriptionstatus", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::CloudFront::OriginAccessControl.OriginAccessControlConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-originaccesscontrol-originaccesscontrolconfig.html", "Properties": { @@ -1887,6 +1909,23 @@ } } }, + "AWS::CloudFront::MonitoringSubscription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-monitoringsubscription.html", + "Properties": { + "DistributionId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-monitoringsubscription.html#cfn-cloudfront-monitoringsubscription-distributionid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "MonitoringSubscription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-monitoringsubscription.html#cfn-cloudfront-monitoringsubscription-monitoringsubscription", + "Required": true, + "Type": "MonitoringSubscription", + "UpdateType": "Mutable" + } + } + }, "AWS::CloudFront::OriginAccessControl": { "Attributes": { "Id": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json index cbc48443a0e50..adf3fab0ebba6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CloudTrail::EventDataStore.AdvancedEventSelector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudtrail-eventdatastore-advancedeventselector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json index 505c54cc52acf..80a1b51b42157 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CloudWatch::Alarm.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html", @@ -384,16 +384,16 @@ "PrimitiveType": "String" } }, - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html", "Properties": { "ActionsEnabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-actionsenabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-actionsenabled", "PrimitiveType": "Boolean", "Required": false, "UpdateType": "Mutable" }, "AlarmActions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmactions", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmactions", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, @@ -401,31 +401,31 @@ "UpdateType": "Mutable" }, "AlarmDescription": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmdescription", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmdescription", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "AlarmName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-alarmname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-alarmname", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, "ComparisonOperator": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-comparisonoperator", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-comparisonoperator", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "DatapointsToAlarm": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarm-datapointstoalarm", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarm-datapointstoalarm", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "Dimensions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-dimension", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-dimension", "DuplicatesAllowed": true, "ItemType": "Dimension", "Required": false, @@ -433,25 +433,25 @@ "UpdateType": "Mutable" }, "EvaluateLowSampleCountPercentile": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-evaluatelowsamplecountpercentile", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-evaluatelowsamplecountpercentile", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "EvaluationPeriods": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-evaluationperiods", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-evaluationperiods", "PrimitiveType": "Integer", "Required": true, "UpdateType": "Mutable" }, "ExtendedStatistic": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-extendedstatistic", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-extendedstatistic", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "InsufficientDataActions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-insufficientdataactions", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-insufficientdataactions", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, @@ -459,13 +459,13 @@ "UpdateType": "Mutable" }, "MetricName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-metricname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-metricname", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "Metrics": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarm-metrics", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarm-metrics", "DuplicatesAllowed": false, "ItemType": "MetricDataQuery", "Required": false, @@ -473,13 +473,13 @@ "UpdateType": "Mutable" }, "Namespace": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-namespace", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-namespace", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "OKActions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-okactions", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-okactions", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, @@ -487,37 +487,37 @@ "UpdateType": "Mutable" }, "Period": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-period", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-period", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "Statistic": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-statistic", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-statistic", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "Threshold": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-threshold", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-threshold", "PrimitiveType": "Double", "Required": false, "UpdateType": "Mutable" }, "ThresholdMetricId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-dynamic-threshold", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-dynamic-threshold", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "TreatMissingData": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-treatmissingdata", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-treatmissingdata", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "Unit": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html#cfn-cloudwatch-alarms-unit", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarms-unit", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json index 5a69f318f3ae4..446cda3e23a9b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeArtifact::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json index 48c034a460564..561386370cca6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeBuild::Project.Artifacts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json index c04d13f79b4f5..58b67c80d5f29 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeCommit::Repository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codecommit-repository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json index cc98b3c18c9b0..7005faad95d76 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html", @@ -8,13 +8,13 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html#cfn-codedeploy-deploymentconfig-minimumhealthyhosts-type", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "Value": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html#cfn-codedeploy-deploymentconfig-minimumhealthyhosts-value", "PrimitiveType": "Integer", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } }, @@ -22,16 +22,16 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html", "Properties": { "CanaryInterval": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary-canaryinterval", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-codedeploy-deploymentconfig-timebasedcanary-canaryinterval", "PrimitiveType": "Integer", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "CanaryPercentage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary-canarypercentage", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedcanary.html#cfn-codedeploy-deploymentconfig-timebasedcanary-canarypercentage", "PrimitiveType": "Integer", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } }, @@ -39,16 +39,16 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html", "Properties": { "LinearInterval": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear-linearinterval", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-codedeploy-deploymentconfig-timebasedlinear-linearinterval", "PrimitiveType": "Integer", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "LinearPercentage": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear-linearpercentage", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-timebasedlinear.html#cfn-codedeploy-deploymentconfig-timebasedlinear-linearpercentage", "PrimitiveType": "Integer", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } }, @@ -56,22 +56,22 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html", "Properties": { "TimeBasedCanary": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-timebasedcanary", "Required": false, "Type": "TimeBasedCanary", - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "TimeBasedLinear": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-timebasedlinear", "Required": false, "Type": "TimeBasedLinear", - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "Type": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-properties-codedeploy-deploymentconfig-trafficroutingconfig-type", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-trafficroutingconfig.html#cfn-codedeploy-deploymentconfig-trafficroutingconfig-type", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } }, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json index a684cc5b02318..4f93ed584954d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeGuruProfiler::ProfilingGroup.Channel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codeguruprofiler-profilinggroup-channel.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json index e71b7ebe9e5ed..f9037af699ca6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeGuruReviewer::RepositoryAssociation": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json index 43d2a53e4ec80..71b3a9c3bd157 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodePipeline::CustomActionType.ArtifactDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-customactiontype-artifactdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json index e2803b9db1d37..8a98ad3cad12d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeStar::GitHubRepository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestar-githubrepository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json index 8f1a1b19ece8c..fa04ac1fbe796 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeStarConnections::Connection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json index 1df32855f90ea..42e480c86fc34 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CodeStarNotifications::NotificationRule.Target": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestarnotifications-notificationrule-target.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json index 48834ffa83a65..cf748f5818eda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Cognito::IdentityPool.CognitoIdentityProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypool-cognitoidentityprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json index b87fdbbe21af8..f9a03074ac39a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Config::ConfigRule.CustomPolicyDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-configrule-custompolicydetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json index 38e4305152b63..f6dd4c26876ef 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Connect::HoursOfOperation.HoursOfOperationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connect-hoursofoperation-hoursofoperationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ConnectCampaigns.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ConnectCampaigns.json index 9e81a8b9aec41..1a099592a4ca6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ConnectCampaigns.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ConnectCampaigns.json @@ -1,5 +1,111 @@ { - "$version": "0.0.0", - "PropertyTypes": {}, - "ResourceTypes": {} + "$version": "91.0.0", + "PropertyTypes": { + "AWS::ConnectCampaigns::Campaign.DialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-dialerconfig.html", + "Properties": { + "PredictiveDialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-dialerconfig.html#cfn-connectcampaigns-campaign-dialerconfig-predictivedialerconfig", + "Required": false, + "Type": "PredictiveDialerConfig", + "UpdateType": "Mutable" + }, + "ProgressiveDialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-dialerconfig.html#cfn-connectcampaigns-campaign-dialerconfig-progressivedialerconfig", + "Required": false, + "Type": "ProgressiveDialerConfig", + "UpdateType": "Mutable" + } + } + }, + "AWS::ConnectCampaigns::Campaign.OutboundCallConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html", + "Properties": { + "ConnectContactFlowArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectcontactflowarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ConnectQueueArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectqueuearn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ConnectSourcePhoneNumber": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-outboundcallconfig.html#cfn-connectcampaigns-campaign-outboundcallconfig-connectsourcephonenumber", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::ConnectCampaigns::Campaign.PredictiveDialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-predictivedialerconfig.html", + "Properties": { + "BandwidthAllocation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-predictivedialerconfig.html#cfn-connectcampaigns-campaign-predictivedialerconfig-bandwidthallocation", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::ConnectCampaigns::Campaign.ProgressiveDialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-progressivedialerconfig.html", + "Properties": { + "BandwidthAllocation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-progressivedialerconfig.html#cfn-connectcampaigns-campaign-progressivedialerconfig-bandwidthallocation", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + } + } + } + }, + "ResourceTypes": { + "AWS::ConnectCampaigns::Campaign": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html", + "Properties": { + "ConnectInstanceArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-connectinstancearn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "DialerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-dialerconfig", + "Required": true, + "Type": "DialerConfig", + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "OutboundCallConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-outboundcallconfig", + "Required": true, + "Type": "OutboundCallConfig", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-connectcampaigns-campaign.html#cfn-connectcampaigns-campaign-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + } + } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ControlTower.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ControlTower.json index b930e6ac4d7f3..3133c758d39d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ControlTower.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ControlTower.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::ControlTower::EnabledControl": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json index 0d9612e834e19..a400942a23436 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::CustomerProfiles::Integration.ConnectorOperator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-customerprofiles-integration-connectoroperator.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json index dce9768d7529a..47a10d3b3148d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DAX::Cluster.SSESpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dax-cluster-ssespecification.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json index 78061dbff5da7..0381c9d639cfe 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DLM::LifecyclePolicy.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-action.html", @@ -19,6 +19,28 @@ } } }, + "AWS::DLM::LifecyclePolicy.ArchiveRetainRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-archiveretainrule.html", + "Properties": { + "RetentionArchiveTier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-archiveretainrule.html#cfn-dlm-lifecyclepolicy-archiveretainrule-retentionarchivetier", + "Required": true, + "Type": "RetentionArchiveTier", + "UpdateType": "Mutable" + } + } + }, + "AWS::DLM::LifecyclePolicy.ArchiveRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-archiverule.html", + "Properties": { + "RetainRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-archiverule.html#cfn-dlm-lifecyclepolicy-archiverule-retainrule", + "Required": true, + "Type": "ArchiveRetainRule", + "UpdateType": "Mutable" + } + } + }, "AWS::DLM::LifecyclePolicy.CreateRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-createrule.html", "Properties": { @@ -375,9 +397,38 @@ } } }, + "AWS::DLM::LifecyclePolicy.RetentionArchiveTier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-retentionarchivetier.html", + "Properties": { + "Count": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-retentionarchivetier.html#cfn-dlm-lifecyclepolicy-retentionarchivetier-count", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "Interval": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-retentionarchivetier.html#cfn-dlm-lifecyclepolicy-retentionarchivetier-interval", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "IntervalUnit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-retentionarchivetier.html#cfn-dlm-lifecyclepolicy-retentionarchivetier-intervalunit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::DLM::LifecyclePolicy.Schedule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-schedule.html", "Properties": { + "ArchiveRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-schedule.html#cfn-dlm-lifecyclepolicy-schedule-archiverule", + "Required": false, + "Type": "ArchiveRule", + "UpdateType": "Mutable" + }, "CopyTags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-schedule.html#cfn-dlm-lifecyclepolicy-schedule-copytags", "PrimitiveType": "Boolean", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json index 5c8e837ae31fd..d0d3455a24ed9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DMS::Endpoint.DocDbSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dms-endpoint-docdbsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json index 2feb1455ecdcb..3c6c742d97092 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DataBrew::Dataset.CsvOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-dataset-csvoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json index e26520eb3162f..3cc648242eadd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DataPipeline::Pipeline.Field": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datapipeline-pipeline-pipelineobjects-fields.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json index e506efc74fdec..498d381cfb2f9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DataSync::LocationEFS.Ec2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationefs-ec2config.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json index 26b07efca4e4c..4efbccadcac25 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Detective::Graph": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json index 9d9005874487c..9a45e7d9c7e98 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DevOpsGuru::NotificationChannel.NotificationChannelConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-devopsguru-notificationchannel-notificationchannelconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json index c2bbb3971fc97..de2143574e2a8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DirectoryService::MicrosoftAD.VpcSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-microsoftad-vpcsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json index 2b0e1450c83db..707d13dcefbda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDB::DBCluster": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json index 2b6e02ba12f5b..60bfdc2a7e053 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::DynamoDB::GlobalTable.AttributeDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-globaltable-attributedefinition.html", @@ -355,16 +355,16 @@ } }, "AWS::DynamoDB::Table.AttributeDefinition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-attributedefinition.html", "Properties": { "AttributeName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-attributedefinition.html#cfn-dynamodb-table-attributedefinition-attributename", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "AttributeType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-attributedefinition.html#cfn-dynamodb-table-attributedefinition-attributetype", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" @@ -372,33 +372,52 @@ } }, "AWS::DynamoDB::Table.ContributorInsightsSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-contributorinsightsspecification.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-contributorinsightsspecification.html", "Properties": { "Enabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-contributorinsightsspecification.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-contributorinsightsspecification.html#cfn-dynamodb-table-contributorinsightsspecification-enabled", "PrimitiveType": "Boolean", "Required": true, "UpdateType": "Mutable" } } }, + "AWS::DynamoDB::Table.Csv": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-csv.html", + "Properties": { + "Delimiter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-csv.html#cfn-dynamodb-table-csv-delimiter", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "HeaderList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-csv.html#cfn-dynamodb-table-csv-headerlist", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, "AWS::DynamoDB::Table.GlobalSecondaryIndex": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html", "Properties": { "ContributorInsightsSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-contributorinsightsspecification", "Required": false, "Type": "ContributorInsightsSpecification", "UpdateType": "Mutable" }, "IndexName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-indexname", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "KeySchema": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-keyschema", "DuplicatesAllowed": false, "ItemType": "KeySchema", "Required": true, @@ -406,30 +425,70 @@ "UpdateType": "Mutable" }, "Projection": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-projection", "Required": true, "Type": "Projection", "UpdateType": "Mutable" }, "ProvisionedThroughput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-globalsecondaryindex.html#cfn-dynamodb-table-globalsecondaryindex-provisionedthroughput", "Required": false, "Type": "ProvisionedThroughput", "UpdateType": "Mutable" } } }, + "AWS::DynamoDB::Table.ImportSourceSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-importsourcespecification.html", + "Properties": { + "InputCompressionType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-importsourcespecification.html#cfn-dynamodb-table-importsourcespecification-inputcompressiontype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "InputFormat": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-importsourcespecification.html#cfn-dynamodb-table-importsourcespecification-inputformat", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "InputFormatOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-importsourcespecification.html#cfn-dynamodb-table-importsourcespecification-inputformatoptions", + "Required": false, + "Type": "InputFormatOptions", + "UpdateType": "Immutable" + }, + "S3BucketSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-importsourcespecification.html#cfn-dynamodb-table-importsourcespecification-s3bucketsource", + "Required": true, + "Type": "S3BucketSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::DynamoDB::Table.InputFormatOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-inputformatoptions.html", + "Properties": { + "Csv": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-inputformatoptions.html#cfn-dynamodb-table-inputformatoptions-csv", + "Required": false, + "Type": "Csv", + "UpdateType": "Immutable" + } + } + }, "AWS::DynamoDB::Table.KeySchema": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-keyschema.html", "Properties": { "AttributeName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-keyschema.html#cfn-dynamodb-table-keyschema-attributename", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "KeyType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-keyschema.html#cfn-dynamodb-table-keyschema-keytype", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" @@ -437,10 +496,10 @@ } }, "AWS::DynamoDB::Table.KinesisStreamSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-kinesisstreamspecification.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-kinesisstreamspecification.html", "Properties": { "StreamArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-kinesisstreamspecification.html#cfn-dynamodb-kinesisstreamspecification-streamarn", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-kinesisstreamspecification.html#cfn-dynamodb-table-kinesisstreamspecification-streamarn", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" @@ -448,16 +507,16 @@ } }, "AWS::DynamoDB::Table.LocalSecondaryIndex": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html", "Properties": { "IndexName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-indexname", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "KeySchema": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-keyschema", "DuplicatesAllowed": false, "ItemType": "KeySchema", "Required": true, @@ -465,7 +524,7 @@ "UpdateType": "Mutable" }, "Projection": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-localsecondaryindex.html#cfn-dynamodb-table-localsecondaryindex-projection", "Required": true, "Type": "Projection", "UpdateType": "Mutable" @@ -484,10 +543,10 @@ } }, "AWS::DynamoDB::Table.Projection": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-projection.html", "Properties": { "NonKeyAttributes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-projection.html#cfn-dynamodb-table-projection-nonkeyattributes", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, @@ -495,7 +554,7 @@ "UpdateType": "Mutable" }, "ProjectionType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-projection.html#cfn-dynamodb-table-projection-projectiontype", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" @@ -503,22 +562,45 @@ } }, "AWS::DynamoDB::Table.ProvisionedThroughput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html", "Properties": { "ReadCapacityUnits": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits", - "PrimitiveType": "Long", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html#cfn-dynamodb-table-provisionedthroughput-readcapacityunits", + "PrimitiveType": "Integer", "Required": true, "UpdateType": "Mutable" }, "WriteCapacityUnits": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits", - "PrimitiveType": "Long", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-provisionedthroughput.html#cfn-dynamodb-table-provisionedthroughput-writecapacityunits", + "PrimitiveType": "Integer", "Required": true, "UpdateType": "Mutable" } } }, + "AWS::DynamoDB::Table.S3BucketSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-s3bucketsource.html", + "Properties": { + "S3Bucket": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-s3bucketsource.html#cfn-dynamodb-table-s3bucketsource-s3bucket", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "S3BucketOwner": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-s3bucketsource.html#cfn-dynamodb-table-s3bucketsource-s3bucketowner", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "S3KeyPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-s3bucketsource.html#cfn-dynamodb-table-s3bucketsource-s3keyprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, "AWS::DynamoDB::Table.SSESpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html", "Properties": { @@ -543,10 +625,10 @@ } }, "AWS::DynamoDB::Table.StreamSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-streamspecification.html", "Properties": { "StreamViewType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-streamspecification.html#cfn-dynamodb-table-streamspecification-streamviewtype", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" @@ -554,16 +636,16 @@ } }, "AWS::DynamoDB::Table.TimeToLiveSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html", "Properties": { "AttributeName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html#cfn-dynamodb-table-timetolivespecification-attributename", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "Enabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html#cfn-dynamodb-table-timetolivespecification-enabled", "PrimitiveType": "Boolean", "Required": true, "UpdateType": "Mutable" @@ -676,12 +758,12 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html", "Properties": { "AttributeDefinitions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef", - "DuplicatesAllowed": true, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedefinitions", + "DuplicatesAllowed": false, "ItemType": "AttributeDefinition", "Required": false, "Type": "List", - "UpdateType": "Conditional" + "UpdateType": "Mutable" }, "BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode", @@ -690,19 +772,25 @@ "UpdateType": "Mutable" }, "ContributorInsightsSpecification": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-contributorinsightsspecification-enabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-contributorinsightsspecification", "Required": false, "Type": "ContributorInsightsSpecification", "UpdateType": "Mutable" }, "GlobalSecondaryIndexes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-globalsecondaryindexes", "DuplicatesAllowed": true, "ItemType": "GlobalSecondaryIndex", "Required": false, "Type": "List", "UpdateType": "Mutable" }, + "ImportSourceSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-importsourcespecification", + "Required": false, + "Type": "ImportSourceSpecification", + "UpdateType": "Immutable" + }, "KeySchema": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema", "DuplicatesAllowed": false, @@ -718,12 +806,12 @@ "UpdateType": "Mutable" }, "LocalSecondaryIndexes": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-localsecondaryindexes", "DuplicatesAllowed": true, "ItemType": "LocalSecondaryIndex", "Required": false, "Type": "List", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "PointInTimeRecoverySpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-pointintimerecoveryspecification", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json index 2dc18b0b50378..a8a23deb82bb8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EC2::CapacityReservation.TagSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-capacityreservation-tagspecification.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json index a72d7a9264093..318e3f8d67eae 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ECR::ReplicationConfiguration.ReplicationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecr-replicationconfiguration-replicationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json index 9e8a07a494f07..27ba52c95a0a2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ECS::CapacityProvider.AutoScalingGroupProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-autoscalinggroupprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json index 575f006936290..eabf9d190948b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EFS::AccessPoint.AccessPointTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-efs-accesspoint-accesspointtag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json index cdcb06c6fc02f..aac6f6feef97f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EKS::Cluster.ClusterLogging": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-clusterlogging.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json index b69abf10dbf4e..5eda7fcbe1080 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EMR::Cluster.Application": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticmapreduce-cluster-application.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json index 26d2d23c68f0f..319ab58cacd90 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EMRContainers::VirtualCluster.ContainerInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-emrcontainers-virtualcluster-containerinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRServerless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRServerless.json index 881a24105335c..0f7ca21d72f52 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRServerless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRServerless.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EMRServerless::Application.AutoStartConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-emrserverless-application-autostartconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json index c2865a34c3782..49854884068e0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ElastiCache::CacheCluster.CloudWatchLogsDestinationDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cachecluster-cloudwatchlogsdestinationdetails.html", @@ -396,6 +396,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "TransitEncryptionEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cache-cluster.html#cfn-elasticache-cachecluster-transitencryptionenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "VpcSecurityGroupIds": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cache-cluster.html#cfn-elasticache-cachecluster-vpcsecuritygroupids", "DuplicatesAllowed": true, @@ -818,22 +824,22 @@ } }, "AWS::ElastiCache::SubnetGroup": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html", "Properties": { "CacheSubnetGroupName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-cachesubnetgroupname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-cachesubnetgroupname", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-description", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-description", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "SubnetIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-subnetids", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-subnetids", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, @@ -841,7 +847,7 @@ "UpdateType": "Mutable" }, "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-tags", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-subnetgroup.html#cfn-elasticache-subnetgroup-tags", "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json index cb3623596fe64..82f14c8bd1ae8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ElasticBeanstalk::Application.ApplicationResourceLifecycleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-application-applicationresourcelifecycleconfig.html", @@ -82,19 +82,19 @@ } }, "AWS::ElasticBeanstalk::ApplicationVersion.SourceBundle": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-sourcebundle.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-applicationversion-sourcebundle.html", "Properties": { "S3Bucket": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-sourcebundle.html#cfn-beanstalk-sourcebundle-s3bucket", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-applicationversion-sourcebundle.html#cfn-elasticbeanstalk-applicationversion-sourcebundle-s3bucket", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "S3Key": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-sourcebundle.html#cfn-beanstalk-sourcebundle-s3key", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-applicationversion-sourcebundle.html#cfn-elasticbeanstalk-applicationversion-sourcebundle-s3key", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } }, @@ -222,22 +222,27 @@ } }, "AWS::ElasticBeanstalk::ApplicationVersion": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html", + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html", "Properties": { "ApplicationName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-applicationname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-applicationname", "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" }, "Description": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-description", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-description", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "SourceBundle": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-version.html#cfn-elasticbeanstalk-applicationversion-sourcebundle", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticbeanstalk-applicationversion.html#cfn-elasticbeanstalk-applicationversion-sourcebundle", "Required": true, "Type": "SourceBundle", "UpdateType": "Immutable" diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json index 302fbd3c20de8..aa5d77ee4d810 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancing::LoadBalancer.AccessLoggingPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb-accessloggingpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json index ef2a81e08cdd3..2251fefe23f0e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancingV2::Listener.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json index 6a4011b854902..cb1a1063d473a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Elasticsearch::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json index dba4aa6c6207d..92bcc00cd0ddd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::EventSchemas::Discoverer.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eventschemas-discoverer-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json index b7a154dd13b41..e1668c25acf92 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Events::Connection.ApiKeyAuthParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-apikeyauthparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json index 6a69bd49b2277..5a1d84d2db3a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Evidently::Experiment.MetricGoalObject": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json index 07eac859f0ff7..79bb9bdbc3f7a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::FIS::ExperimentTemplate.ExperimentTemplateAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fis-experimenttemplate-experimenttemplateaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json index 763ca9f47d275..c42bab375e016 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::FMS::Policy.IEMap": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fms-policy-iemap.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json index 4085a682b6188..4622ab6d988dc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::FSx::FileSystem.AuditLogConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json index e7275de4d439e..d7efc9adf3ed7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::FinSpace::Environment.FederationParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-finspace-environment-federationparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json index b06136d188044..823bbe4e7ce6c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Forecast::Dataset": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json index aad7e5d414e55..8f5270a610518 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::FraudDetector::Detector.EntityType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-frauddetector-detector-entitytype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json index 3e7cfa12cc248..3bb572edc25d0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::GameLift::Alias.RoutingStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json index 06a1ae0db291b..32b336172ed0c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::GlobalAccelerator::EndpointGroup.EndpointConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-globalaccelerator-endpointgroup-endpointconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json index 6a0dc8458ba5d..18e0ad0ea6845 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Glue::Classifier.CsvClassifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-classifier-csvclassifier.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json index 2a6d3f92e15c6..0ef25d4456b1b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Greengrass::ConnectorDefinition.Connector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-connectordefinition-connector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json index c199c82fc4157..639312a845413 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::GreengrassV2::ComponentVersion.ComponentDependencyRequirement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrassv2-componentversion-componentdependencyrequirement.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json index 2c97e9e670809..fa1a7f73b53bf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::GroundStation::Config.AntennaDownlinkConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-groundstation-config-antennadownlinkconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json index b3c586d230917..a0425852065bc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::GuardDuty::Detector.CFNDataSourceConfigurations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-guardduty-detector-cfndatasourceconfigurations.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json index 83113ea023afc..e5858e53cdbea 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::HealthLake::FHIRDatastore.KmsEncryptionConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-healthlake-fhirdatastore-kmsencryptionconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json index aff603c5a8ad0..7a7254b034c87 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IAM::Group.Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json index 77d9c91e5754e..f2965fbb00d58 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IVS::RecordingConfiguration.DestinationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-destinationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IdentityStore.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IdentityStore.json new file mode 100644 index 0000000000000..9e81a8b9aec41 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IdentityStore.json @@ -0,0 +1,5 @@ +{ + "$version": "0.0.0", + "PropertyTypes": {}, + "ResourceTypes": {} +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json index a4b1ab03f16ed..ac44f96acc73c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html", @@ -9,6 +9,31 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" + }, + "Parameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html#cfn-imagebuilder-containerrecipe-componentconfiguration-parameters", + "ItemType": "ComponentParameter", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::ImageBuilder::ContainerRecipe.ComponentParameter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentparameter.html", + "Properties": { + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentparameter.html#cfn-imagebuilder-containerrecipe-componentparameter-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentparameter.html#cfn-imagebuilder-containerrecipe-componentparameter-value", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" } } }, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json index 613908cc1b7b6..39290a1d78632 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Inspector::AssessmentTarget": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json index 5a8b263fbdb93..22b25200d53f6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::InspectorV2::Filter.DateFilter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json index 7b8b7b8077a39..93ec80269064b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoT::AccountAuditConfiguration.AuditCheckConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-accountauditconfiguration-auditcheckconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json index b76f9a08e57be..44e5cf90d8918 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoT1Click::Project.DeviceTemplate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot1click-project-devicetemplate.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json index 14015794c65eb..f9ef68b677c51 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTAnalytics::Channel.ChannelStorage": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-channelstorage.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json index ba114edd943f9..c783e81d773b8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTCoreDeviceAdvisor::SuiteDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json index 7be4b43aa08e5..9efe5be1fc1fc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTEvents::AlarmModel.AcknowledgeFlow": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-alarmmodel-acknowledgeflow.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json index eebf0f66de056..92dbd8cc62d09 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTFleetHub::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetWise.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetWise.json new file mode 100644 index 0000000000000..c4fdd6ed29650 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetWise.json @@ -0,0 +1,1009 @@ +{ + "$version": "91.0.0", + "PropertyTypes": { + "AWS::IoTFleetWise::Campaign.CollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-collectionscheme.html", + "Properties": { + "ConditionBasedCollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-collectionscheme.html#cfn-iotfleetwise-campaign-collectionscheme-conditionbasedcollectionscheme", + "Required": false, + "Type": "ConditionBasedCollectionScheme", + "UpdateType": "Immutable" + }, + "TimeBasedCollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-collectionscheme.html#cfn-iotfleetwise-campaign-collectionscheme-timebasedcollectionscheme", + "Required": false, + "Type": "TimeBasedCollectionScheme", + "UpdateType": "Immutable" + } + } + }, + "AWS::IoTFleetWise::Campaign.ConditionBasedCollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-conditionbasedcollectionscheme.html", + "Properties": { + "ConditionLanguageVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-conditionbasedcollectionscheme.html#cfn-iotfleetwise-campaign-conditionbasedcollectionscheme-conditionlanguageversion", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "Expression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-conditionbasedcollectionscheme.html#cfn-iotfleetwise-campaign-conditionbasedcollectionscheme-expression", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "MinimumTriggerIntervalMs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-conditionbasedcollectionscheme.html#cfn-iotfleetwise-campaign-conditionbasedcollectionscheme-minimumtriggerintervalms", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Immutable" + }, + "TriggerMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-conditionbasedcollectionscheme.html#cfn-iotfleetwise-campaign-conditionbasedcollectionscheme-triggermode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::IoTFleetWise::Campaign.SignalInformation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-signalinformation.html", + "Properties": { + "MaxSampleCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-signalinformation.html#cfn-iotfleetwise-campaign-signalinformation-maxsamplecount", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "MinimumSamplingIntervalMs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-signalinformation.html#cfn-iotfleetwise-campaign-signalinformation-minimumsamplingintervalms", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-signalinformation.html#cfn-iotfleetwise-campaign-signalinformation-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::Campaign.TimeBasedCollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-timebasedcollectionscheme.html", + "Properties": { + "PeriodMs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-timebasedcollectionscheme.html#cfn-iotfleetwise-campaign-timebasedcollectionscheme-periodms", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.CanInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-caninterface.html", + "Properties": { + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-caninterface.html#cfn-iotfleetwise-decodermanifest-caninterface-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ProtocolName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-caninterface.html#cfn-iotfleetwise-decodermanifest-caninterface-protocolname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ProtocolVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-caninterface.html#cfn-iotfleetwise-decodermanifest-caninterface-protocolversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.CanNetworkInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cannetworkinterface.html", + "Properties": { + "CanInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cannetworkinterface.html#cfn-iotfleetwise-decodermanifest-cannetworkinterface-caninterface", + "Required": true, + "Type": "CanInterface", + "UpdateType": "Mutable" + }, + "InterfaceId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cannetworkinterface.html#cfn-iotfleetwise-decodermanifest-cannetworkinterface-interfaceid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cannetworkinterface.html#cfn-iotfleetwise-decodermanifest-cannetworkinterface-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.CanSignal": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html", + "Properties": { + "Factor": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-factor", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "IsBigEndian": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-isbigendian", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "IsSigned": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-issigned", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Length": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-length", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "MessageId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-messageid", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Offset": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-offset", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "StartBit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignal.html#cfn-iotfleetwise-decodermanifest-cansignal-startbit", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.CanSignalDecoder": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignaldecoder.html", + "Properties": { + "CanSignal": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignaldecoder.html#cfn-iotfleetwise-decodermanifest-cansignaldecoder-cansignal", + "Required": true, + "Type": "CanSignal", + "UpdateType": "Mutable" + }, + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignaldecoder.html#cfn-iotfleetwise-decodermanifest-cansignaldecoder-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "InterfaceId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignaldecoder.html#cfn-iotfleetwise-decodermanifest-cansignaldecoder-interfaceid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-cansignaldecoder.html#cfn-iotfleetwise-decodermanifest-cansignaldecoder-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.ObdInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html", + "Properties": { + "DtcRequestIntervalSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-dtcrequestintervalseconds", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "HasTransmissionEcu": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-hastransmissionecu", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObdStandard": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-obdstandard", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PidRequestIntervalSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-pidrequestintervalseconds", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "RequestMessageId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-requestmessageid", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "UseExtendedIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdinterface.html#cfn-iotfleetwise-decodermanifest-obdinterface-useextendedids", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.ObdNetworkInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdnetworkinterface.html", + "Properties": { + "InterfaceId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdnetworkinterface.html#cfn-iotfleetwise-decodermanifest-obdnetworkinterface-interfaceid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObdInterface": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdnetworkinterface.html#cfn-iotfleetwise-decodermanifest-obdnetworkinterface-obdinterface", + "Required": true, + "Type": "ObdInterface", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdnetworkinterface.html#cfn-iotfleetwise-decodermanifest-obdnetworkinterface-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.ObdSignal": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html", + "Properties": { + "BitMaskLength": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-bitmasklength", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "BitRightShift": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-bitrightshift", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "ByteLength": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-bytelength", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Offset": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-offset", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Pid": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-pid", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "PidResponseLength": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-pidresponselength", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Scaling": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-scaling", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "ServiceMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-servicemode", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "StartByte": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignal.html#cfn-iotfleetwise-decodermanifest-obdsignal-startbyte", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest.ObdSignalDecoder": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignaldecoder.html", + "Properties": { + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignaldecoder.html#cfn-iotfleetwise-decodermanifest-obdsignaldecoder-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "InterfaceId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignaldecoder.html#cfn-iotfleetwise-decodermanifest-obdsignaldecoder-interfaceid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObdSignal": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignaldecoder.html#cfn-iotfleetwise-decodermanifest-obdsignaldecoder-obdsignal", + "Required": true, + "Type": "ObdSignal", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-decodermanifest-obdsignaldecoder.html#cfn-iotfleetwise-decodermanifest-obdsignaldecoder-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.Actuator": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html", + "Properties": { + "AllowedValues": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-allowedvalues", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AssignedValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-assignedvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DataType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-datatype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Max": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-max", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Min": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-min", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Unit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-actuator.html#cfn-iotfleetwise-signalcatalog-actuator-unit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.Attribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html", + "Properties": { + "AllowedValues": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-allowedvalues", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AssignedValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-assignedvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DataType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-datatype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "DefaultValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-defaultvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Max": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-max", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Min": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-min", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Unit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-attribute.html#cfn-iotfleetwise-signalcatalog-attribute-unit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.Branch": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-branch.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-branch.html#cfn-iotfleetwise-signalcatalog-branch-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-branch.html#cfn-iotfleetwise-signalcatalog-branch-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.Node": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-node.html", + "Properties": { + "Actuator": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-node.html#cfn-iotfleetwise-signalcatalog-node-actuator", + "Required": false, + "Type": "Actuator", + "UpdateType": "Mutable" + }, + "Attribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-node.html#cfn-iotfleetwise-signalcatalog-node-attribute", + "Required": false, + "Type": "Attribute", + "UpdateType": "Mutable" + }, + "Branch": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-node.html#cfn-iotfleetwise-signalcatalog-node-branch", + "Required": false, + "Type": "Branch", + "UpdateType": "Mutable" + }, + "Sensor": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-node.html#cfn-iotfleetwise-signalcatalog-node-sensor", + "Required": false, + "Type": "Sensor", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.NodeCounts": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html", + "Properties": { + "TotalActuators": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html#cfn-iotfleetwise-signalcatalog-nodecounts-totalactuators", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "TotalAttributes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html#cfn-iotfleetwise-signalcatalog-nodecounts-totalattributes", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "TotalBranches": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html#cfn-iotfleetwise-signalcatalog-nodecounts-totalbranches", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "TotalNodes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html#cfn-iotfleetwise-signalcatalog-nodecounts-totalnodes", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "TotalSensors": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-nodecounts.html#cfn-iotfleetwise-signalcatalog-nodecounts-totalsensors", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog.Sensor": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html", + "Properties": { + "AllowedValues": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-allowedvalues", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "DataType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-datatype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FullyQualifiedName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-fullyqualifiedname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Max": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-max", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Min": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-min", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Unit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-signalcatalog-sensor.html#cfn-iotfleetwise-signalcatalog-sensor-unit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + } + }, + "ResourceTypes": { + "AWS::IoTFleetWise::Campaign": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html", + "Properties": { + "Action": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-action", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "CollectionScheme": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-collectionscheme", + "Required": true, + "Type": "CollectionScheme", + "UpdateType": "Immutable" + }, + "Compression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-compression", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "DataExtraDimensions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-dataextradimensions", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DiagnosticsMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-diagnosticsmode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ExpiryTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-expirytime", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "PostTriggerCollectionDuration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-posttriggercollectionduration", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Immutable" + }, + "Priority": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-priority", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "SignalCatalogArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-signalcatalogarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SignalsToCollect": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-signalstocollect", + "ItemType": "SignalInformation", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SpoolingMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-spoolingmode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "StartTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-starttime", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "TargetArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-campaign.html#cfn-iotfleetwise-campaign-targetarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::IoTFleetWise::DecoderManifest": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ModelManifestArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-modelmanifestarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "NetworkInterfaces": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-networkinterfaces", + "PrimitiveItemType": "Json", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SignalDecoders": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-signaldecoders", + "PrimitiveItemType": "Json", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Status": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-status", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-decodermanifest.html#cfn-iotfleetwise-decodermanifest-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::Fleet": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-fleet.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-fleet.html#cfn-iotfleetwise-fleet-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Id": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-fleet.html#cfn-iotfleetwise-fleet-id", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SignalCatalogArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-fleet.html#cfn-iotfleetwise-fleet-signalcatalogarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-fleet.html#cfn-iotfleetwise-fleet-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::ModelManifest": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Nodes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-nodes", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SignalCatalogArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-signalcatalogarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Status": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-status", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-modelmanifest.html#cfn-iotfleetwise-modelmanifest-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::SignalCatalog": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + }, + "NodeCounts.TotalActuators": { + "PrimitiveType": "Double" + }, + "NodeCounts.TotalAttributes": { + "PrimitiveType": "Double" + }, + "NodeCounts.TotalBranches": { + "PrimitiveType": "Double" + }, + "NodeCounts.TotalNodes": { + "PrimitiveType": "Double" + }, + "NodeCounts.TotalSensors": { + "PrimitiveType": "Double" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-signalcatalog.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-signalcatalog.html#cfn-iotfleetwise-signalcatalog-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-signalcatalog.html#cfn-iotfleetwise-signalcatalog-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Nodes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-signalcatalog.html#cfn-iotfleetwise-signalcatalog-nodes", + "DuplicatesAllowed": false, + "ItemType": "Node", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-signalcatalog.html#cfn-iotfleetwise-signalcatalog-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTFleetWise::Vehicle": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "CreationTime": { + "PrimitiveType": "String" + }, + "LastModificationTime": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html", + "Properties": { + "AssociationBehavior": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-associationbehavior", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Attributes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-attributes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + }, + "DecoderManifestArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-decodermanifestarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ModelManifestArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-modelmanifestarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotfleetwise-vehicle.html#cfn-iotfleetwise-vehicle-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json index adb7f250a0202..51013b08d94b4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTSiteWise::AccessPolicy.AccessPolicyIdentity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-accesspolicy-accesspolicyidentity.html", @@ -133,6 +133,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "Unit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-asset-assetproperty.html#cfn-iotsitewise-asset-assetproperty-unit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json index 270dd48b5cb9c..693200f2ffdc9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTThingsGraph::FlowTemplate.DefinitionDocument": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotthingsgraph-flowtemplate-definitiondocument.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTTwinMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTTwinMaker.json index b6b87ef1ed858..982814a366180 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTTwinMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTTwinMaker.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTTwinMaker::ComponentType.DataConnector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iottwinmaker-componenttype-dataconnector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json index 1a85c5a5a2e0b..5460c3e34da0b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html", @@ -16,6 +16,13 @@ "Required": false, "UpdateType": "Mutable" }, + "FactoryPresetFreqsList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-factorypresetfreqslist", + "PrimitiveItemType": "Integer", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "MacVersion": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-macversion", "PrimitiveType": "String", @@ -64,6 +71,30 @@ "Required": false, "UpdateType": "Mutable" }, + "RxDataRate2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-rxdatarate2", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "RxDelay1": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-rxdelay1", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "RxDrOffset1": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-rxdroffset1", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "RxFreq2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-rxfreq2", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "Supports32BitFCnt": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html#cfn-iotwireless-deviceprofile-lorawandeviceprofile-supports32bitfcnt", "PrimitiveType": "Boolean", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json index 522aa90987b50..3212107df3f6d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KMS::Alias": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json index 647d98a13eda7..a12d72573416b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::KafkaConnect::Connector.ApacheKafkaCluster": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kafkaconnect-connector-apachekafkacluster.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json index 15b608a1fef30..304c9c876487d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Kendra::DataSource.AccessControlListConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-accesscontrollistconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json index 24610f9803e5b..c8bbc07733652 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Kinesis::Stream.StreamEncryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesis-stream-streamencryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json index 33661a96b1020..08899597a7b1c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::KinesisAnalytics::Application.CSVMappingParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalytics-application-csvmappingparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json index b9e8270258d1f..5d8e73de00355 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::KinesisAnalyticsV2::Application.ApplicationCodeConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-applicationcodeconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json index c5f66c8379304..78e4cc0446ebb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::KinesisFirehose::DeliveryStream.AmazonopensearchserviceBufferingHints": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisfirehose-deliverystream-amazonopensearchservicebufferinghints.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json index 705b050bd7c26..5e4286926c638 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KinesisVideo::SignalingChannel": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json index 6ae3e3091a572..e8e50133f5575 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::LakeFormation::DataCellsFilter.ColumnWildcard": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lakeformation-datacellsfilter-columnwildcard.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json index 8e2767b64b77d..476c35b23be3d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Lambda::Alias.AliasRoutingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-alias-aliasroutingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json index bf8aec7ef02e9..bf96689d89abb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Lex::Bot.AdvancedRecognitionSetting": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-bot-advancedrecognitionsetting.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json index ce0c28f455434..53f0aaf2c75a6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::LicenseManager::License.BorrowConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-licensemanager-license-borrowconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json index 86ae3c3f401ba..53fe4118aba8a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Lightsail::Bucket.AccessRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json index 08486f4b995b3..629a223d1c661 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Location::Map.MapConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-location-map-mapconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json index 5922e65a53fc8..dba61e6e24be4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Logs::MetricFilter.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-logs-metricfilter-dimension.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json index e31748cbf4c8d..2e6feb3f026bb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutEquipment::InferenceScheduler": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json index 4990be21fde0b..2b92ab71cd405 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::LookoutMetrics::Alert.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lookoutmetrics-alert-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json index b756c412666e0..2b7da1403af32 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutVision::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json index 69987f3afdee0..c39ed6fa45556 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MSK::Cluster.BrokerLogs": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokerlogs.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json index a46f4fc5f909c..66eba5021e3ff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MWAA::Environment.LoggingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mwaa-environment-loggingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json index b5ce85dce6381..952657ec4c8de 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json @@ -1,11 +1,39 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Macie::AllowList.Criteria": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-criteria.html", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" + "Properties": { + "Regex": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-criteria.html#cfn-macie-allowlist-criteria-regex", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "S3WordsList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-criteria.html#cfn-macie-allowlist-criteria-s3wordslist", + "Required": false, + "Type": "S3WordsList", + "UpdateType": "Mutable" + } + } + }, + "AWS::Macie::AllowList.S3WordsList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-s3wordslist.html", + "Properties": { + "BucketName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-s3wordslist.html#cfn-macie-allowlist-s3wordslist-bucketname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObjectKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-s3wordslist.html#cfn-macie-allowlist-s3wordslist-objectkey", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } }, "AWS::Macie::FindingsFilter.Criterion": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-findingsfilter-criterion.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json index e46d162bb6fa0..d68ef9398d0e7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ManagedBlockchain::Member.ApprovalThresholdPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-managedblockchain-member-approvalthresholdpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json index 7c84b2487649d..33d2c945e66d4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaConnect::Flow.Encryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconnect-flow-encryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json index 3eda41e28fa22..7ff282cdb9785 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaConvert::JobTemplate.AccelerationSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconvert-jobtemplate-accelerationsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json index c3d6528c5a0eb..ba6ccc077e024 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaLive::Channel.AacSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-aacsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json index 85b2e2aa5b992..e1532a0bb878c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaPackage::Asset.EgressEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediapackage-asset-egressendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json index fead4ae38eb0e..c846e9892e937 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaStore::Container.CorsRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-corsrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaTailor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaTailor.json index af0513a73f09e..4e09263cba14a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaTailor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaTailor.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MediaTailor::PlaybackConfiguration.AdMarkerPassthrough": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediatailor-playbackconfiguration-admarkerpassthrough.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json index 6539ffe26f8c9..3c914586cabba 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::MemoryDB::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-memorydb-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json index 87216ad2999a5..1cececcc3e07d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Neptune::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-neptune-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json index d10fc72ae36e6..05853d2f03d77 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::NetworkFirewall::Firewall.SubnetMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewall-subnetmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json index d7a7b8da1b03f..e9136af9ef6c3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::NetworkManager::ConnectAttachment.ConnectAttachmentOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-connectattachment-connectattachmentoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json index 33efdf030e643..99408868ac4c4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::NimbleStudio::LaunchProfile.StreamConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json index 9bdd01fe10e1c..9e0ea4e349517 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::OpenSearchService::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json index 65f706f650183..a3b179a368898 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::OpsWorks::App.DataSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworks-app-datasource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json index cd93b6234cfa1..4588b7221668b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::OpsWorksCM::Server.EngineAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworkscm-server-engineattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json index 1fd05d26aa0d1..af5fd6199c0c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Panorama::ApplicationInstance.ManifestOverridesPayload": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-panorama-applicationinstance-manifestoverridespayload.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Personalize.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Personalize.json index 1a6beca689eaa..458c394cd0d41 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Personalize.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Personalize.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Personalize::Dataset.DatasetImportJob": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-personalize-dataset-datasetimportjob.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json index 9699443e01d3e..824ad6a905e4e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Pinpoint::ApplicationSettings.CampaignHook": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpoint-applicationsettings-campaignhook.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json index b8086e9e0a024..a7dc6b5484201 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::PinpointEmail::ConfigurationSet.DeliveryOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpointemail-configurationset-deliveryoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json index 930ea7bf947e5..d2c230b00fb53 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::QLDB::Stream.KinesisConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qldb-stream-kinesisconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json index e226b5efd069c..8214a977c5ad2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::QuickSight::Analysis.AnalysisError": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-analysis-analysiserror.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json index 5c1c08dfdd162..ba91fba328faa 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::RAM::ResourceShare": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json index de32ef6a18914..34b20acb48867 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::RDS::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-dbclusterrole.html", @@ -18,6 +18,17 @@ } } }, + "AWS::RDS::DBCluster.ReadEndpoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-readendpoint.html", + "Properties": { + "Address": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-readendpoint.html#cfn-rds-dbcluster-readendpoint-address", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::RDS::DBCluster.ScalingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-scalingconfiguration.html", "Properties": { @@ -47,6 +58,23 @@ } } }, + "AWS::RDS::DBCluster.ServerlessV2ScalingConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-serverlessv2scalingconfiguration.html", + "Properties": { + "MaxCapacity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-serverlessv2scalingconfiguration.html#cfn-rds-dbcluster-serverlessv2scalingconfiguration-maxcapacity", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "MinCapacity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-serverlessv2scalingconfiguration.html#cfn-rds-dbcluster-serverlessv2scalingconfiguration-mincapacity", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::RDS::DBInstance.DBInstanceRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbinstance-dbinstancerole.html", "Properties": { @@ -317,6 +345,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html", "Properties": { + "AllocatedStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-allocatedstorage", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "AssociatedRoles": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-associatedroles", "DuplicatesAllowed": false, @@ -325,6 +359,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "AutoMinorVersionUpgrade": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-autominorversionupgrade", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "AvailabilityZones": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-availabilityzones", "DuplicatesAllowed": false, @@ -335,12 +375,12 @@ }, "BacktrackWindow": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backtrackwindow", - "PrimitiveType": "Long", + "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "BackupRetentionPeriod": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backuprententionperiod", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backupretentionperiod", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" @@ -357,12 +397,24 @@ "Required": false, "UpdateType": "Immutable" }, + "DBClusterInstanceClass": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-dbclusterinstanceclass", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "DBClusterParameterGroupName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-dbclusterparametergroupname", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, + "DBInstanceParameterGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-dbinstanceparametergroupname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "DBSubnetGroupName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-dbsubnetgroupname", "PrimitiveType": "String", @@ -425,6 +477,12 @@ "Required": false, "UpdateType": "Conditional" }, + "Iops": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-iops", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "KmsKeyId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-kmskeyid", "PrimitiveType": "String", @@ -441,7 +499,37 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-masterusername", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Conditional" + }, + "MonitoringInterval": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-monitoringinterval", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "MonitoringRoleArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-monitoringrolearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PerformanceInsightsEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-performanceinsightsenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "PerformanceInsightsKmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-performanceinsightskmskeyid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PerformanceInsightsRetentionPeriod": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-performanceinsightsretentionperiod", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" }, "Port": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-port", @@ -461,6 +549,12 @@ "Required": false, "UpdateType": "Mutable" }, + "PubliclyAccessible": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-publiclyaccessible", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Immutable" + }, "ReplicationSourceIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-replicationsourceidentifier", "PrimitiveType": "String", @@ -479,6 +573,12 @@ "Type": "ScalingConfiguration", "UpdateType": "Mutable" }, + "ServerlessV2ScalingConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-serverlessv2scalingconfiguration", + "Required": false, + "Type": "ServerlessV2ScalingConfiguration", + "UpdateType": "Mutable" + }, "SnapshotIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-snapshotidentifier", "PrimitiveType": "String", @@ -503,9 +603,15 @@ "Required": false, "UpdateType": "Immutable" }, + "StorageType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-storagetype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-tags", - "DuplicatesAllowed": true, + "DuplicatesAllowed": false, "ItemType": "Tag", "Required": false, "Type": "List", @@ -528,6 +634,11 @@ } }, "AWS::RDS::DBClusterParameterGroup": { + "Attributes": { + "DBClusterParameterGroupName": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbclusterparametergroup.html", "Properties": { "Description": { @@ -550,7 +661,6 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbclusterparametergroup.html#cfn-rds-dbclusterparametergroup-tags", - "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, "Type": "List", @@ -631,7 +741,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbinstance.html#cfn-rds-dbinstance-customiaminstanceprofile", "PrimitiveType": "String", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "DBClusterIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbinstance.html#cfn-rds-dbinstance-dbclusteridentifier", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json index c4fc71123cc3f..be1c2794a931e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::RUM::AppMonitor.AppMonitorConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rum-appmonitor-appmonitorconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json index b23081964e3ec..65be73a048775 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Redshift::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-cluster-endpoint.html", @@ -69,11 +69,85 @@ } } }, + "AWS::Redshift::ScheduledAction.PauseClusterMessage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-pauseclustermessage.html", + "Properties": { + "ClusterIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-pauseclustermessage.html#cfn-redshift-scheduledaction-pauseclustermessage-clusteridentifier", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Redshift::ScheduledAction.ResizeClusterMessage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html", + "Properties": { + "Classic": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html#cfn-redshift-scheduledaction-resizeclustermessage-classic", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "ClusterIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html#cfn-redshift-scheduledaction-resizeclustermessage-clusteridentifier", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ClusterType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html#cfn-redshift-scheduledaction-resizeclustermessage-clustertype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "NodeType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html#cfn-redshift-scheduledaction-resizeclustermessage-nodetype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "NumberOfNodes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resizeclustermessage.html#cfn-redshift-scheduledaction-resizeclustermessage-numberofnodes", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Redshift::ScheduledAction.ResumeClusterMessage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resumeclustermessage.html", + "Properties": { + "ClusterIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-resumeclustermessage.html#cfn-redshift-scheduledaction-resumeclustermessage-clusteridentifier", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::Redshift::ScheduledAction.ScheduledActionType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-scheduledactiontype.html", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" + "Properties": { + "PauseCluster": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-scheduledactiontype.html#cfn-redshift-scheduledaction-scheduledactiontype-pausecluster", + "Required": false, + "Type": "PauseClusterMessage", + "UpdateType": "Mutable" + }, + "ResizeCluster": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-scheduledactiontype.html#cfn-redshift-scheduledaction-scheduledactiontype-resizecluster", + "Required": false, + "Type": "ResizeClusterMessage", + "UpdateType": "Mutable" + }, + "ResumeCluster": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-scheduledaction-scheduledactiontype.html#cfn-redshift-scheduledaction-scheduledactiontype-resumecluster", + "Required": false, + "Type": "ResumeClusterMessage", + "UpdateType": "Mutable" + } + } } }, "ResourceTypes": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RedshiftServerless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RedshiftServerless.json index 7fbe1cc048214..1757adfa0a4f8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RedshiftServerless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RedshiftServerless.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::RedshiftServerless::Workgroup.ConfigParameter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshiftserverless-workgroup-configparameter.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json index 548cf4e2de81c..80c774d30512a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::RefactorSpaces::Application.ApiGatewayProxyInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-refactorspaces-application-apigatewayproxyinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json index b06b82f7ce204..3f85feaab9578 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ResilienceHub::App.PhysicalResourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resiliencehub-app-physicalresourceid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json index e59b41596a54a..4e0b44033307c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ResourceGroups::Group.ConfigurationItem": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resourcegroups-group-configurationitem.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json index b469785459f4a..edfb48c5917dd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::RoboMaker::RobotApplication.RobotSoftwareSuite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-robomaker-robotapplication-robotsoftwaresuite.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RolesAnywhere.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RolesAnywhere.json index 9e81a8b9aec41..a2d951be4fcb6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RolesAnywhere.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RolesAnywhere.json @@ -1,5 +1,184 @@ { - "$version": "0.0.0", - "PropertyTypes": {}, - "ResourceTypes": {} + "$version": "91.0.0", + "PropertyTypes": { + "AWS::RolesAnywhere::TrustAnchor.Source": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html", + "Properties": { + "SourceData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html#cfn-rolesanywhere-trustanchor-source-sourcedata", + "Required": false, + "Type": "SourceData", + "UpdateType": "Mutable" + }, + "SourceType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html#cfn-rolesanywhere-trustanchor-source-sourcetype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::RolesAnywhere::TrustAnchor.SourceData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-sourcedata.html", + "Properties": { + "AcmPcaArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-sourcedata.html#cfn-rolesanywhere-trustanchor-sourcedata-acmpcaarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "X509CertificateData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-sourcedata.html#cfn-rolesanywhere-trustanchor-sourcedata-x509certificatedata", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + } + }, + "ResourceTypes": { + "AWS::RolesAnywhere::CRL": { + "Attributes": { + "CrlId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html", + "Properties": { + "CrlData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-crldata", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-enabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "TrustAnchorArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-crl.html#cfn-rolesanywhere-crl-trustanchorarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::RolesAnywhere::Profile": { + "Attributes": { + "ProfileArn": { + "PrimitiveType": "String" + }, + "ProfileId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html", + "Properties": { + "DurationSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-durationseconds", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-enabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "ManagedPolicyArns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-managedpolicyarns", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RequireInstanceProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-requireinstanceproperties", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "RoleArns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-rolearns", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SessionPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-sessionpolicy", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-profile.html#cfn-rolesanywhere-profile-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::RolesAnywhere::TrustAnchor": { + "Attributes": { + "TrustAnchorArn": { + "PrimitiveType": "String" + }, + "TrustAnchorId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html", + "Properties": { + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-enabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Source": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-source", + "Required": false, + "Type": "Source", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rolesanywhere-trustanchor.html#cfn-rolesanywhere-trustanchor-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + } + } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json index e69abe6e18e52..0bdd39e257fa6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Route53::CidrCollection.Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-cidrcollection-location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json index ccabeb38e2e0d..24f5fb6c897dc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json index f271fbbb80063..0d77b959c1bfb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Route53RecoveryReadiness::ResourceSet.DNSTargetResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json index 3614dd36fae9c..c9f7609678a90 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Route53Resolver::FirewallRuleGroup.FirewallRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53resolver-firewallrulegroup-firewallrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json index 4d1d44ae0d764..f8f485ef14afb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::S3::AccessPoint.PublicAccessBlockConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-accesspoint-publicaccessblockconfiguration.html", @@ -1432,9 +1432,20 @@ }, "AWS::S3::StorageLens.Encryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-encryption.html", - "PrimitiveType": "Json", - "Required": false, - "UpdateType": "Mutable" + "Properties": { + "SSEKMS": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-encryption.html#cfn-s3-storagelens-encryption-ssekms", + "Required": false, + "Type": "SSEKMS", + "UpdateType": "Mutable" + }, + "SSES3": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-encryption.html#cfn-s3-storagelens-encryption-sses3", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + } + } }, "AWS::S3::StorageLens.PrefixLevel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-prefixlevel.html", @@ -1505,6 +1516,17 @@ } } }, + "AWS::S3::StorageLens.SSEKMS": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-ssekms.html", + "Properties": { + "KeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-ssekms.html#cfn-s3-storagelens-ssekms-keyid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::S3::StorageLens.SelectionCriteria": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-storagelens-selectioncriteria.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json index 7be101442dda5..edf91e1e1659d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::S3ObjectLambda::AccessPoint.ObjectLambdaConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3objectlambda-accesspoint-objectlambdaconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json index b098988af334b..2fc9c89241062 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::S3Outposts::AccessPoint.VpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3outposts-accesspoint-vpcconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json index bb9e98f4e606b..0f110fd13c53d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SDB::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json index 0339a254280ab..fa125b7751302 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SES::ConfigurationSet.DeliveryOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationset-deliveryoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json index ed6de7d792b45..a7c8d45efca6c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SNS::Topic.Subscription": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic-subscription.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json index 6b9f4f64da3d7..9dac20e6f7c9e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SQS::Queue": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json index 0bcdbf3ba5492..e4169230a66ec 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SSM::Association.InstanceAssociationOutputLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-association-instanceassociationoutputlocation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json index 881aa1fc0b369..67664c67d1695 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SSMContacts::Contact.ChannelTargetInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmcontacts-contact-channeltargetinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json index 1675e6c76d413..abe20e3a72693 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SSMIncidents::ReplicationSet.RegionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmincidents-replicationset-regionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json index 3652ccbfe27f0..a2e2091b59eb3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SSO::InstanceAccessControlAttributeConfiguration.AccessControlAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sso-instanceaccesscontrolattributeconfiguration-accesscontrolattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json index a6bf9215f89f1..4250729f423a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json @@ -1,5 +1,5 @@ { - "$version": "72.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SageMaker::App.ResourceSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html", @@ -392,7 +392,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html#cfn-sagemaker-device-device-devicename", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "IotThingName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-device-device.html#cfn-sagemaker-device-device-iotthingname", @@ -491,6 +491,25 @@ } } }, + "AWS::SageMaker::Domain.RSessionAppSettings": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html", + "Properties": { + "CustomImages": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html#cfn-sagemaker-domain-rsessionappsettings-customimages", + "DuplicatesAllowed": true, + "ItemType": "CustomImage", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "DefaultResourceSpec": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rsessionappsettings.html#cfn-sagemaker-domain-rsessionappsettings-defaultresourcespec", + "Required": false, + "Type": "ResourceSpec", + "UpdateType": "Mutable" + } + } + }, "AWS::SageMaker::Domain.RStudioServerProAppSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-rstudioserverproappsettings.html", "Properties": { @@ -546,6 +565,12 @@ "Required": false, "UpdateType": "Mutable" }, + "LifecycleConfigArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-lifecycleconfigarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "SageMakerImageArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-resourcespec.html#cfn-sagemaker-domain-resourcespec-sagemakerimagearn", "PrimitiveType": "String", @@ -604,6 +629,12 @@ "Type": "KernelGatewayAppSettings", "UpdateType": "Mutable" }, + "RSessionAppSettings": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-rsessionappsettings", + "Required": false, + "Type": "RSessionAppSettings", + "UpdateType": "Mutable" + }, "RStudioServerProAppSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-domain-usersettings.html#cfn-sagemaker-domain-usersettings-rstudioserverproappsettings", "Required": false, @@ -844,6 +875,190 @@ } } }, + "AWS::SageMaker::EndpointConfig.ClarifyExplainerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html", + "Properties": { + "EnableExplanations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-enableexplanations", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "InferenceConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-inferenceconfig", + "Required": false, + "Type": "ClarifyInferenceConfig", + "UpdateType": "Immutable" + }, + "ShapConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyexplainerconfig.html#cfn-sagemaker-endpointconfig-clarifyexplainerconfig-shapconfig", + "Required": true, + "Type": "ClarifyShapConfig", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.ClarifyFeatureType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyfeaturetype.html", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "AWS::SageMaker::EndpointConfig.ClarifyHeader": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyheader.html", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "AWS::SageMaker::EndpointConfig.ClarifyInferenceConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html", + "Properties": { + "ContentTemplate": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-contenttemplate", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "FeatureHeaders": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featureheaders", + "ItemType": "ClarifyHeader", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "FeatureTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featuretypes", + "ItemType": "ClarifyFeatureType", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "FeaturesAttribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-featuresattribute", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "LabelAttribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelattribute", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "LabelHeaders": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelheaders", + "ItemType": "ClarifyHeader", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "LabelIndex": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-labelindex", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "MaxPayloadInMB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-maxpayloadinmb", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "MaxRecordCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-maxrecordcount", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "ProbabilityAttribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-probabilityattribute", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ProbabilityIndex": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyinferenceconfig.html#cfn-sagemaker-endpointconfig-clarifyinferenceconfig-probabilityindex", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.ClarifyShapBaselineConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html", + "Properties": { + "MimeType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-mimetype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ShapBaseline": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-shapbaseline", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ShapBaselineUri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapbaselineconfig.html#cfn-sagemaker-endpointconfig-clarifyshapbaselineconfig-shapbaselineuri", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.ClarifyShapConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html", + "Properties": { + "NumberOfSamples": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-numberofsamples", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "Seed": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-seed", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "ShapBaselineConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-shapbaselineconfig", + "Required": true, + "Type": "ClarifyShapBaselineConfig", + "UpdateType": "Immutable" + }, + "TextConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-textconfig", + "Required": false, + "Type": "ClarifyTextConfig", + "UpdateType": "Immutable" + }, + "UseLogit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifyshapconfig.html#cfn-sagemaker-endpointconfig-clarifyshapconfig-uselogit", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.ClarifyTextConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html", + "Properties": { + "Granularity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html#cfn-sagemaker-endpointconfig-clarifytextconfig-granularity", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Language": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-clarifytextconfig.html#cfn-sagemaker-endpointconfig-clarifytextconfig-language", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::SageMaker::EndpointConfig.DataCaptureConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig.html", "Properties": { @@ -895,6 +1110,12 @@ "Required": false, "UpdateType": "Immutable" }, + "ContainerStartupHealthCheckTimeoutInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-containerstartuphealthchecktimeoutinseconds", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, "InitialInstanceCount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-initialinstancecount", "PrimitiveType": "Integer", @@ -913,6 +1134,12 @@ "Required": false, "UpdateType": "Immutable" }, + "ModelDataDownloadTimeoutInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-modeldatadownloadtimeoutinseconds", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, "ModelName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-modelname", "PrimitiveType": "String", @@ -930,6 +1157,12 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" + }, + "VolumeSizeInGB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-productionvariant.html#cfn-sagemaker-endpointconfig-productionvariant-volumesizeingb", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" } } }, @@ -1548,94 +1781,818 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringoutputconfig-monitoringoutputs", "ItemType": "MonitoringOutput", "Required": true, - "Type": "List", + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelExplainabilityJobDefinition.MonitoringResources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html", + "Properties": { + "ClusterConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringresources-clusterconfig", + "Required": true, + "Type": "ClusterConfig", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelExplainabilityJobDefinition.NetworkConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html", + "Properties": { + "EnableInterContainerTrafficEncryption": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enableintercontainertrafficencryption", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Immutable" + }, + "EnableNetworkIsolation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enablenetworkisolation", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Immutable" + }, + "VpcConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-vpcconfig", + "Required": false, + "Type": "VpcConfig", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelExplainabilityJobDefinition.S3Output": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html", + "Properties": { + "LocalPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-localpath", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "S3UploadMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uploadmode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "S3Uri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uri", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelExplainabilityJobDefinition.StoppingCondition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html", + "Properties": { + "MaxRuntimeInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html#cfn-sagemaker-modelexplainabilityjobdefinition-stoppingcondition-maxruntimeinseconds", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelExplainabilityJobDefinition.VpcConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html", + "Properties": { + "SecurityGroupIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-securitygroupids", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + }, + "Subnets": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-subnets", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.AdditionalInferenceSpecificationDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html", + "Properties": { + "Containers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-containers", + "ItemType": "ModelPackageContainerDefinition", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "SupportedContentTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedcontenttypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SupportedRealtimeInferenceInstanceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedrealtimeinferenceinstancetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SupportedResponseMIMETypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedresponsemimetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "SupportedTransformInstanceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-additionalinferencespecificationdefinition.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition-supportedtransforminstancetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::SageMaker::ModelPackage.Bias": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html", + "Properties": { + "PostTrainingReport": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-posttrainingreport", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "PreTrainingReport": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-pretrainingreport", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "Report": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-bias.html#cfn-sagemaker-modelpackage-bias-report", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DataSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-datasource.html", + "Properties": { + "S3DataSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-datasource.html#cfn-sagemaker-modelpackage-datasource-s3datasource", + "Required": true, + "Type": "S3DataSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DriftCheckBaselines": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html", + "Properties": { + "Bias": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-bias", + "Required": false, + "Type": "DriftCheckBias", + "UpdateType": "Immutable" + }, + "Explainability": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-explainability", + "Required": false, + "Type": "DriftCheckExplainability", + "UpdateType": "Immutable" + }, + "ModelDataQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-modeldataquality", + "Required": false, + "Type": "DriftCheckModelDataQuality", + "UpdateType": "Immutable" + }, + "ModelQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbaselines.html#cfn-sagemaker-modelpackage-driftcheckbaselines-modelquality", + "Required": false, + "Type": "DriftCheckModelQuality", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DriftCheckBias": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html", + "Properties": { + "ConfigFile": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-configfile", + "Required": false, + "Type": "FileSource", + "UpdateType": "Immutable" + }, + "PostTrainingConstraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-posttrainingconstraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "PreTrainingConstraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckbias.html#cfn-sagemaker-modelpackage-driftcheckbias-pretrainingconstraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DriftCheckExplainability": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html", + "Properties": { + "ConfigFile": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html#cfn-sagemaker-modelpackage-driftcheckexplainability-configfile", + "Required": false, + "Type": "FileSource", + "UpdateType": "Immutable" + }, + "Constraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckexplainability.html#cfn-sagemaker-modelpackage-driftcheckexplainability-constraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DriftCheckModelDataQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html", + "Properties": { + "Constraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html#cfn-sagemaker-modelpackage-driftcheckmodeldataquality-constraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "Statistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodeldataquality.html#cfn-sagemaker-modelpackage-driftcheckmodeldataquality-statistics", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.DriftCheckModelQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html", + "Properties": { + "Constraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html#cfn-sagemaker-modelpackage-driftcheckmodelquality-constraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "Statistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-driftcheckmodelquality.html#cfn-sagemaker-modelpackage-driftcheckmodelquality-statistics", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.Environment": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-environment.html", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "AWS::SageMaker::ModelPackage.Explainability": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-explainability.html", + "Properties": { + "Report": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-explainability.html#cfn-sagemaker-modelpackage-explainability-report", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.FileSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html", + "Properties": { + "ContentDigest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-contentdigest", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ContentType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-contenttype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "S3Uri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-filesource.html#cfn-sagemaker-modelpackage-filesource-s3uri", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.InferenceSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html", + "Properties": { + "Containers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-containers", + "DuplicatesAllowed": false, + "ItemType": "ModelPackageContainerDefinition", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + }, + "SupportedContentTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedcontenttypes", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + }, + "SupportedRealtimeInferenceInstanceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedrealtimeinferenceinstancetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "SupportedResponseMIMETypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedresponsemimetypes", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + }, + "SupportedTransformInstanceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-inferencespecification.html#cfn-sagemaker-modelpackage-inferencespecification-supportedtransforminstancetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.MetadataProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html", + "Properties": { + "CommitId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-commitid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "GeneratedBy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-generatedby", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ProjectId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-projectid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Repository": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metadataproperties.html#cfn-sagemaker-modelpackage-metadataproperties-repository", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.MetricsSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html", + "Properties": { + "ContentDigest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-contentdigest", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ContentType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-contenttype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "S3Uri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-metricssource.html#cfn-sagemaker-modelpackage-metricssource-s3uri", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelDataQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html", + "Properties": { + "Constraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html#cfn-sagemaker-modelpackage-modeldataquality-constraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "Statistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modeldataquality.html#cfn-sagemaker-modelpackage-modeldataquality-statistics", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelMetrics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html", + "Properties": { + "Bias": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-bias", + "Required": false, + "Type": "Bias", + "UpdateType": "Immutable" + }, + "Explainability": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-explainability", + "Required": false, + "Type": "Explainability", + "UpdateType": "Immutable" + }, + "ModelDataQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-modeldataquality", + "Required": false, + "Type": "ModelDataQuality", + "UpdateType": "Immutable" + }, + "ModelQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelmetrics.html#cfn-sagemaker-modelpackage-modelmetrics-modelquality", + "Required": false, + "Type": "ModelQuality", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelPackageContainerDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html", + "Properties": { + "ContainerHostname": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-containerhostname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Environment": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-environment", + "Required": false, + "Type": "Environment", + "UpdateType": "Mutable" + }, + "Framework": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-framework", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FrameworkVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-frameworkversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Image": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-image", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ImageDigest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-imagedigest", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ModelDataUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-modeldataurl", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ModelInput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-modelinput", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "NearestModelName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-nearestmodelname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ProductId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagecontainerdefinition.html#cfn-sagemaker-modelpackage-modelpackagecontainerdefinition-productid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelPackageStatusDetails": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html", + "Properties": { + "ImageScanStatuses": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails-imagescanstatuses", + "ItemType": "ModelPackageStatusItem", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ValidationStatuses": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusdetails.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails-validationstatuses", + "ItemType": "ModelPackageStatusItem", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelPackageStatusItem": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html", + "Properties": { + "FailureReason": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-failurereason", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Status": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelpackagestatusitem.html#cfn-sagemaker-modelpackage-modelpackagestatusitem-status", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::SageMaker::ModelPackage.ModelQuality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html", + "Properties": { + "Constraints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html#cfn-sagemaker-modelpackage-modelquality-constraints", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + }, + "Statistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-modelquality.html#cfn-sagemaker-modelpackage-modelquality-statistics", + "Required": false, + "Type": "MetricsSource", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.S3DataSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html", + "Properties": { + "S3DataType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html#cfn-sagemaker-modelpackage-s3datasource-s3datatype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "S3Uri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-s3datasource.html#cfn-sagemaker-modelpackage-s3datasource-s3uri", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.SourceAlgorithm": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html", + "Properties": { + "AlgorithmName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html#cfn-sagemaker-modelpackage-sourcealgorithm-algorithmname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "ModelDataUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithm.html#cfn-sagemaker-modelpackage-sourcealgorithm-modeldataurl", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.SourceAlgorithmSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithmspecification.html", + "Properties": { + "SourceAlgorithms": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-sourcealgorithmspecification.html#cfn-sagemaker-modelpackage-sourcealgorithmspecification-sourcealgorithms", + "ItemType": "SourceAlgorithm", + "Required": true, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.TransformInput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html", + "Properties": { + "CompressionType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-compressiontype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ContentType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-contenttype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "DataSource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-datasource", + "Required": true, + "Type": "DataSource", + "UpdateType": "Immutable" + }, + "SplitType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transforminput.html#cfn-sagemaker-modelpackage-transforminput-splittype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.TransformJobDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html", + "Properties": { + "BatchStrategy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-batchstrategy", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Environment": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-environment", + "Required": false, + "Type": "Environment", + "UpdateType": "Immutable" + }, + "MaxConcurrentTransforms": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-maxconcurrenttransforms", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "MaxPayloadInMB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-maxpayloadinmb", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + }, + "TransformInput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transforminput", + "Required": true, + "Type": "TransformInput", + "UpdateType": "Immutable" + }, + "TransformOutput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transformoutput", + "Required": true, + "Type": "TransformOutput", "UpdateType": "Immutable" - } - } - }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.MonitoringResources": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html", - "Properties": { - "ClusterConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-monitoringresources.html#cfn-sagemaker-modelexplainabilityjobdefinition-monitoringresources-clusterconfig", + }, + "TransformResources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformjobdefinition.html#cfn-sagemaker-modelpackage-transformjobdefinition-transformresources", "Required": true, - "Type": "ClusterConfig", + "Type": "TransformResources", "UpdateType": "Immutable" } } }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.NetworkConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html", + "AWS::SageMaker::ModelPackage.TransformOutput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html", "Properties": { - "EnableInterContainerTrafficEncryption": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enableintercontainertrafficencryption", - "PrimitiveType": "Boolean", + "Accept": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-accept", + "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, - "EnableNetworkIsolation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-enablenetworkisolation", - "PrimitiveType": "Boolean", + "AssembleWith": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-assemblewith", + "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, - "VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-networkconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-networkconfig-vpcconfig", + "KmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-kmskeyid", + "PrimitiveType": "String", "Required": false, - "Type": "VpcConfig", + "UpdateType": "Immutable" + }, + "S3OutputPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformoutput.html#cfn-sagemaker-modelpackage-transformoutput-s3outputpath", + "PrimitiveType": "String", + "Required": true, "UpdateType": "Immutable" } } }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.S3Output": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html", + "AWS::SageMaker::ModelPackage.TransformResources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html", "Properties": { - "LocalPath": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-localpath", + "InstanceCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-instancecount", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Immutable" + }, + "InstanceType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-instancetype", "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" }, - "S3UploadMode": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uploadmode", + "VolumeKmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-transformresources.html#cfn-sagemaker-modelpackage-transformresources-volumekmskeyid", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::ModelPackage.UserContext": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-usercontext.html", + "Properties": { + "DomainId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-usercontext.html#cfn-sagemaker-modelpackage-usercontext-domainid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" }, - "S3Uri": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-s3output.html#cfn-sagemaker-modelexplainabilityjobdefinition-s3output-s3uri", + "UserProfileArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-usercontext.html#cfn-sagemaker-modelpackage-usercontext-userprofilearn", "PrimitiveType": "String", - "Required": true, - "UpdateType": "Immutable" + "Required": false, + "UpdateType": "Mutable" + }, + "UserProfileName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-usercontext.html#cfn-sagemaker-modelpackage-usercontext-userprofilename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.StoppingCondition": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html", + "AWS::SageMaker::ModelPackage.ValidationProfile": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html", "Properties": { - "MaxRuntimeInSeconds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-stoppingcondition.html#cfn-sagemaker-modelexplainabilityjobdefinition-stoppingcondition-maxruntimeinseconds", - "PrimitiveType": "Integer", + "ProfileName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html#cfn-sagemaker-modelpackage-validationprofile-profilename", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "TransformJobDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationprofile.html#cfn-sagemaker-modelpackage-validationprofile-transformjobdefinition", "Required": true, + "Type": "TransformJobDefinition", "UpdateType": "Immutable" } } }, - "AWS::SageMaker::ModelExplainabilityJobDefinition.VpcConfig": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html", + "AWS::SageMaker::ModelPackage.ValidationSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html", "Properties": { - "SecurityGroupIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-securitygroupids", - "PrimitiveItemType": "String", + "ValidationProfiles": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html#cfn-sagemaker-modelpackage-validationspecification-validationprofiles", + "ItemType": "ValidationProfile", "Required": true, "Type": "List", "UpdateType": "Immutable" }, - "Subnets": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelexplainabilityjobdefinition-vpcconfig.html#cfn-sagemaker-modelexplainabilityjobdefinition-vpcconfig-subnets", - "PrimitiveItemType": "String", + "ValidationRole": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-modelpackage-validationspecification.html#cfn-sagemaker-modelpackage-validationspecification-validationrole", + "PrimitiveType": "String", "Required": true, - "Type": "List", "UpdateType": "Immutable" } } @@ -2365,6 +3322,17 @@ } } }, + "AWS::SageMaker::NotebookInstance.InstanceMetadataServiceConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstance-instancemetadataserviceconfiguration.html", + "Properties": { + "MinimumInstanceMetadataServiceVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstance-instancemetadataserviceconfiguration.html#cfn-sagemaker-notebookinstance-instancemetadataserviceconfiguration-minimuminstancemetadataserviceversion", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::SageMaker::NotebookInstanceLifecycleConfig.NotebookInstanceLifecycleHook": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-notebookinstancelifecycleconfig-notebookinstancelifecyclehook.html", "Properties": { @@ -2563,9 +3531,15 @@ "Properties": { "CognitoMemberDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-memberdefinition.html#cfn-sagemaker-workteam-memberdefinition-cognitomemberdefinition", - "Required": true, + "Required": false, "Type": "CognitoMemberDefinition", "UpdateType": "Mutable" + }, + "OidcMemberDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-memberdefinition.html#cfn-sagemaker-workteam-memberdefinition-oidcmemberdefinition", + "Required": false, + "Type": "OidcMemberDefinition", + "UpdateType": "Mutable" } } }, @@ -2579,6 +3553,18 @@ "UpdateType": "Mutable" } } + }, + "AWS::SageMaker::Workteam.OidcMemberDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-oidcmemberdefinition.html", + "Properties": { + "OidcGroups": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-workteam-oidcmemberdefinition.html#cfn-sagemaker-workteam-oidcmemberdefinition-oidcgroups", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + } + } } }, "ResourceTypes": { @@ -2724,6 +3710,12 @@ "Type": "MonitoringOutputConfig", "UpdateType": "Immutable" }, + "EndpointName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-endpointname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "JobDefinitionName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-dataqualityjobdefinition.html#cfn-sagemaker-dataqualityjobdefinition-jobdefinitionname", "PrimitiveType": "String", @@ -2776,7 +3768,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-devicefleetname", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-tags", @@ -3220,6 +4212,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html", "Properties": { + "EndpointName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-endpointname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "JobDefinitionName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelbiasjobdefinition.html#cfn-sagemaker-modelbiasjobdefinition-jobdefinitionname", "PrimitiveType": "String", @@ -3294,6 +4292,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html", "Properties": { + "EndpointName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-endpointname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "JobDefinitionName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelexplainabilityjobdefinition.html#cfn-sagemaker-modelexplainabilityjobdefinition-jobdefinitionname", "PrimitiveType": "String", @@ -3357,6 +4361,201 @@ } } }, + "AWS::SageMaker::ModelPackage": { + "Attributes": { + "CreationTime": { + "PrimitiveType": "String" + }, + "ModelPackageArn": { + "PrimitiveType": "String" + }, + "ModelPackageStatus": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html", + "Properties": { + "AdditionalInferenceSpecificationDefinition": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecificationdefinition", + "Required": false, + "Type": "AdditionalInferenceSpecificationDefinition", + "UpdateType": "Mutable" + }, + "AdditionalInferenceSpecifications": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecifications", + "ItemType": "AdditionalInferenceSpecificationDefinition", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AdditionalInferenceSpecificationsToAdd": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-additionalinferencespecificationstoadd", + "ItemType": "AdditionalInferenceSpecificationDefinition", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ApprovalDescription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-approvaldescription", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "CertifyForMarketplace": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-certifyformarketplace", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "ClientToken": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-clienttoken", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "CreatedBy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-createdby", + "Required": false, + "Type": "UserContext", + "UpdateType": "Mutable" + }, + "CustomerMetadataProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-customermetadataproperties", + "PrimitiveItemType": "String", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + }, + "Domain": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-domain", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "DriftCheckBaselines": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-driftcheckbaselines", + "Required": false, + "Type": "DriftCheckBaselines", + "UpdateType": "Immutable" + }, + "Environment": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-environment", + "PrimitiveItemType": "String", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + }, + "InferenceSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-inferencespecification", + "Required": false, + "Type": "InferenceSpecification", + "UpdateType": "Immutable" + }, + "LastModifiedBy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-lastmodifiedby", + "Required": false, + "Type": "UserContext", + "UpdateType": "Mutable" + }, + "LastModifiedTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-lastmodifiedtime", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "MetadataProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-metadataproperties", + "Required": false, + "Type": "MetadataProperties", + "UpdateType": "Immutable" + }, + "ModelApprovalStatus": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelapprovalstatus", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ModelMetrics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelmetrics", + "Required": false, + "Type": "ModelMetrics", + "UpdateType": "Immutable" + }, + "ModelPackageDescription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagedescription", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ModelPackageGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagegroupname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ModelPackageName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ModelPackageStatusDetails": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagestatusdetails", + "Required": false, + "Type": "ModelPackageStatusDetails", + "UpdateType": "Mutable" + }, + "ModelPackageStatusItem": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackagestatusitem", + "Required": false, + "Type": "ModelPackageStatusItem", + "UpdateType": "Mutable" + }, + "ModelPackageVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-modelpackageversion", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "SamplePayloadUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-samplepayloadurl", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "SourceAlgorithmSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-sourcealgorithmspecification", + "Required": false, + "Type": "SourceAlgorithmSpecification", + "UpdateType": "Immutable" + }, + "Tag": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-tag", + "Required": false, + "Type": "Tag", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Task": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-task", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ValidationSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelpackage.html#cfn-sagemaker-modelpackage-validationspecification", + "Required": false, + "Type": "ValidationSpecification", + "UpdateType": "Immutable" + } + } + }, "AWS::SageMaker::ModelPackageGroup": { "Attributes": { "CreationTime": { @@ -3409,6 +4608,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html", "Properties": { + "EndpointName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-endpointname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "JobDefinitionName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-modelqualityjobdefinition.html#cfn-sagemaker-modelqualityjobdefinition-jobdefinitionname", "PrimitiveType": "String", @@ -3565,6 +4770,12 @@ "Required": false, "UpdateType": "Immutable" }, + "InstanceMetadataServiceConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-instancemetadataserviceconfiguration", + "Required": false, + "Type": "InstanceMetadataServiceConfiguration", + "UpdateType": "Mutable" + }, "InstanceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html#cfn-sagemaker-notebookinstance-instancetype", "PrimitiveType": "String", @@ -3840,6 +5051,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "WorkforceName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-workforcename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "WorkteamName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-workteam.html#cfn-sagemaker-workteam-workteamname", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json index 96529b32d7b8f..66692451ca40c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::SecretsManager::RotationSchedule.HostedRotationLambda": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json index 42204264c59da..94a770c909ae1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SecurityHub::Hub": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json index df04e3454fed2..f014b703a938f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ServiceCatalog::CloudFormationProduct.ProvisioningArtifactProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicecatalog-cloudformationproduct-provisioningartifactproperties.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json index 23024fe77f0b1..51e7d77c989a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::ServiceCatalogAppRegistry::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json index eff465518b41e..f9fc035eee2a3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::ServiceDiscovery::PrivateDnsNamespace.PrivateDnsPropertiesMutable": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicediscovery-privatednsnamespace-privatednspropertiesmutable.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json index bcd005a2e718a..0503e5bc739b3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Signer::SigningProfile.SignatureValidityPeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-signer-signingprofile-signaturevalidityperiod.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json index c851d23612105..baeaa420193d1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::StepFunctions::Activity.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stepfunctions-activity-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SupportApp.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SupportApp.json index 3955796815123..e510279ba2cb2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SupportApp.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SupportApp.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SupportApp::AccountAlias": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json index bd37b2b6dfaa1..4551b1567e6a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Synthetics::Canary.ArtifactConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-artifactconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json index 412ac735f50d7..079ed4707c077 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Timestream::ScheduledQuery.DimensionMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-timestream-scheduledquery-dimensionmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json index 2f889646da23a..96fd123b7e607 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Transfer::Server.As2Transport": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-as2transport.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_VoiceID.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_VoiceID.json index 4a15ef91aa978..25fc5e4fb6d56 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_VoiceID.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_VoiceID.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::VoiceID::Domain.ServerSideEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-voiceid-domain-serversideencryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json index 52e60d25114e3..42e5dee577795 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::WAF::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waf-bytematchset-bytematchtuples.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json index c26aa39cfca58..933f80815db98 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::WAFRegional::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafregional-bytematchset-bytematchtuple.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json index 45d95832bde17..7b1f51768ce8b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json index dfe8d281b1eaf..7befea040da6e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::Wisdom::Assistant.ServerSideEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wisdom-assistant-serversideencryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json index 4e0821496ac6b..051ecc458a3a6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::WorkSpaces::ConnectionAlias.ConnectionAliasAssociation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-workspaces-connectionalias-connectionaliasassociation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json index 3030f5f4ef152..f59de500f72b7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "AWS::XRay::Group.InsightsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-xray-group-insightsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json index 9be6be366e7bd..3ccf87b002290 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "Alexa::ASK::Skill.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ask-skill-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json index 3423ffcbb70e4..8b70d3cde6ef8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json @@ -1,5 +1,5 @@ { - "$version": "89.0.0", + "$version": "91.0.0", "PropertyTypes": { "Tag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json index 4d3eac5e46b4d..2123f7f38135c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json @@ -1,3 +1,3 @@ { - "ResourceSpecificationVersion": "89.0.0" + "ResourceSpecificationVersion": "91.0.0" } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_SageMaker_ModelPackage_patch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_SageMaker_ModelPackage_patch.json new file mode 100644 index 0000000000000..5591ac0b29286 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_SageMaker_ModelPackage_patch.json @@ -0,0 +1,15 @@ +{ + "ResourceTypes": { + "AWS::SageMaker::ModelPackage": { + "patch": { + "description": "Drop unrecognized and unnecessary singular Tag parameter", + "operations": [ + { + "op": "remove", + "path": "/Properties/Tag" + } + ] + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/test/spec-validators.ts b/packages/@aws-cdk/cfnspec/test/spec-validators.ts index afa446ca567f1..d28058b630ded 100644 --- a/packages/@aws-cdk/cfnspec/test/spec-validators.ts +++ b/packages/@aws-cdk/cfnspec/test/spec-validators.ts @@ -89,8 +89,7 @@ function validateProperties( expectedKeys.push('Type'); expect(property.Type).toBeTruthy(); const fqn = `${typeName.split('.')[0]}.${property.Type}`; - const resolvedType = specification.PropertyTypes && specification.PropertyTypes[fqn]; - expect(resolvedType).toBeTruthy(); + expect(Object.keys(specification.PropertyTypes)).toContain(fqn); } else if (schema.isUnionProperty(property)) { expectedKeys.push('PrimitiveTypes', 'PrimitiveItemTypes', 'ItemTypes', 'Types', 'InclusivePrimitiveItemTypes', 'InclusiveItemTypes', 'InclusiveItemPattern'); diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/artifact-schema.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/artifact-schema.ts index 4d98b3a29bb32..66872401251aa 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/artifact-schema.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/artifact-schema.ts @@ -134,14 +134,9 @@ export interface AwsCloudFormationStackProperties { } /** - * Artifact properties for the Asset Manifest + * Configuration options for the Asset Manifest */ -export interface AssetManifestProperties { - /** - * Filename of the asset manifest - */ - readonly file: string; - +export interface AssetManifestOptions { /** * Version of bootstrap stack required to deploy this stack * @@ -163,6 +158,16 @@ export interface AssetManifestProperties { readonly bootstrapStackVersionSsmParameter?: string; } +/** + * Artifact properties for the Asset Manifest + */ +export interface AssetManifestProperties extends AssetManifestOptions { + /** + * Filename of the asset manifest + */ + readonly file: string; +} + /** * Artifact properties for the Construct Tree Artifact */ diff --git a/packages/@aws-cdk/cloudformation-include/README.md b/packages/@aws-cdk/cloudformation-include/README.md index 6e10d290a5c67..66e8f1e47e296 100644 --- a/packages/@aws-cdk/cloudformation-include/README.md +++ b/packages/@aws-cdk/cloudformation-include/README.md @@ -132,7 +132,9 @@ make sure to download the unprocessed template However, certain unprocessed templates can fail when used with the `CfnInclude` class. The most common reason for the failure is that the unprocessed template can contain cycles between resources, which get removed after the Transform is processed, -but is not allowed when being included (as pure CloudFormation does not permit cycles). +but is not allowed when being included (as pure CloudFormation does not permit cycles). To enable cycle processing behavior similar +to cloudformation, set `allowCyclicalReferences` of CfnIncludeProps to true. + When that happens, you should instead download the processed template from the CloudFormation AWS Console (make sure the "View processed template" checkbox is **checked** in that case): diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 778bd9a124152..d4b6b9877c126 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -57,6 +57,15 @@ export interface CfnIncludeProps { * @default - parameters will retain their original definitions */ readonly parameters?: { [parameterName: string]: any }; + + /** + * Specifies whether to allow cyclical references, effectively disregarding safeguards meant to avoid undeployable + * templates. This should only be set to true in the case of templates utilizing cloud transforms (e.g. SAM) that + * after processing the transform will no longer contain any circular references. + * + * @default - will throw an error on detecting any cyclical references + */ + readonly allowCyclicalReferences?: boolean; } /** @@ -99,10 +108,16 @@ export class CfnInclude extends core.CfnElement { private readonly nestedStacksToInclude: { [name: string]: CfnIncludeProps }; private readonly template: any; private readonly preserveLogicalIds: boolean; + private readonly allowCyclicalReferences: boolean; + private logicalIdToPlaceholderMap: Map; constructor(scope: Construct, id: string, props: CfnIncludeProps) { super(scope, id); + this.allowCyclicalReferences = props.allowCyclicalReferences ?? false; + + this.logicalIdToPlaceholderMap = new Map(); + this.parametersToReplace = props.parameters || {}; // read the template into a JS object @@ -584,10 +599,31 @@ export class CfnInclude extends core.CfnElement { return cfnCondition; } + private getPlaceholderID(): string { + return `Placeholder${this.logicalIdToPlaceholderMap.size}`; + } + private getOrCreateResource(logicalId: string, cycleChain: string[] = []): core.CfnResource { cycleChain = cycleChain.concat([logicalId]); if (cycleChain.length !== new Set(cycleChain).size) { - throw new Error(`Found a cycle between resources in the template: ${cycleChain.join(' depends on ')}`); + if (!this.allowCyclicalReferences) { + throw new Error(`Found a cycle between resources in the template: ${cycleChain.join(' depends on ')}`); + } + //only allow one placeholder per logical id + if (this.logicalIdToPlaceholderMap.get(logicalId)) { + return this.resources[this.logicalIdToPlaceholderMap.get(logicalId)!]; + } + let placeholderResourceAttributes: any = this.template.Resources[logicalId]; + let placeholderId: string = this.getPlaceholderID(); + this.logicalIdToPlaceholderMap.set(logicalId, placeholderId); + let placeholderInstance = new core.CfnResource(this, placeholderId, { + type: placeholderResourceAttributes.Type, + properties: {}, + }); + placeholderInstance.overrideLogicalId(placeholderId); + this.resources[placeholderId] = placeholderInstance; + + return placeholderInstance; } const ret = this.resources[logicalId]; @@ -652,6 +688,17 @@ export class CfnInclude extends core.CfnElement { } } + /* + 1. remove placeholder version of object created for cycle breaking + 2. override logical id before deletion so references to the placeholder instead reference the original + */ + if (this.logicalIdToPlaceholderMap.get(logicalId)) { + let placeholderId: string = this.logicalIdToPlaceholderMap.get(logicalId)!; + this.resources[placeholderId].overrideLogicalId(logicalId); + this.node.tryRemoveChild(placeholderId); + delete this.resources[placeholderId]; + } + this.overrideLogicalIdIfNeeded(l1Instance, logicalId); this.resources[logicalId] = l1Instance; diff --git a/packages/@aws-cdk/cloudformation-include/package.json b/packages/@aws-cdk/cloudformation-include/package.json index 885dd72171c4a..4477f943f5737 100644 --- a/packages/@aws-cdk/cloudformation-include/package.json +++ b/packages/@aws-cdk/cloudformation-include/package.json @@ -121,6 +121,7 @@ "@aws-cdk/aws-cognito": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", + "@aws-cdk/aws-connectcampaigns": "0.0.0", "@aws-cdk/aws-controltower": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", "@aws-cdk/aws-customerprofiles": "0.0.0", @@ -175,6 +176,7 @@ "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", "@aws-cdk/aws-iotevents": "0.0.0", "@aws-cdk/aws-iotfleethub": "0.0.0", + "@aws-cdk/aws-iotfleetwise": "0.0.0", "@aws-cdk/aws-iotsitewise": "0.0.0", "@aws-cdk/aws-iotthingsgraph": "0.0.0", "@aws-cdk/aws-iottwinmaker": "0.0.0", @@ -232,6 +234,7 @@ "@aws-cdk/aws-resiliencehub": "0.0.0", "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", + "@aws-cdk/aws-rolesanywhere": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53recoverycontrol": "0.0.0", "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", @@ -321,6 +324,7 @@ "@aws-cdk/aws-cognito": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", + "@aws-cdk/aws-connectcampaigns": "0.0.0", "@aws-cdk/aws-controltower": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", "@aws-cdk/aws-customerprofiles": "0.0.0", @@ -375,6 +379,7 @@ "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", "@aws-cdk/aws-iotevents": "0.0.0", "@aws-cdk/aws-iotfleethub": "0.0.0", + "@aws-cdk/aws-iotfleetwise": "0.0.0", "@aws-cdk/aws-iotsitewise": "0.0.0", "@aws-cdk/aws-iotthingsgraph": "0.0.0", "@aws-cdk/aws-iottwinmaker": "0.0.0", @@ -432,6 +437,7 @@ "@aws-cdk/aws-resiliencehub": "0.0.0", "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", + "@aws-cdk/aws-rolesanywhere": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53recoverycontrol": "0.0.0", "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", diff --git a/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts index 2fa4a3f4d1f6a..dcdade326cb62 100644 --- a/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts @@ -1,4 +1,5 @@ import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as core from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import * as constructs from 'constructs'; @@ -141,16 +142,120 @@ describe('CDK Include', () => { }).toThrow(/Short-form Fn::GetAtt must contain a '.' in its string argument, got: 'Bucket1Arn'/); }); - test('detects a cycle between resources in the template', () => { + /** + * A->B + * B->A + * simplified version of cycle-in-resources.json, an example of cyclical references + */ + test('by default does not accept a cycle between resources in the template', () => { expect(() => { includeTestTemplate(stack, 'cycle-in-resources.json'); }).toThrow(/Found a cycle between resources in the template: Bucket1 depends on Bucket2 depends on Bucket1/); }); + + /** + * A->B + * B->C + * C->{D,A} + * D->B + * simplified version of multi-cycle-in-resources.json, an example of multiple cyclical references + */ + test('by default does not accept multiple cycles between resources in the template', () => { + expect(() => { + includeTestTemplate(stack, 'multi-cycle-in-resources.json'); + }).toThrow(/Found a cycle between resources in the template: Bucket1 depends on Bucket2 depends on Bucket3 depends on Bucket4 depends on Bucket2/); + }); + + /** + * A->B + * B->{C,A} + * C->A + * simplified version of multi-cycle-multi-dest-in-resources.json, an example of multiple cyclical references that + * include visiting the same destination more than once + */ + test('by default does not accept multiple cycles and multiple destinations between resources in the template', () => { + expect(() => { + includeTestTemplate(stack, 'multi-cycle-multi-dest-in-resources.json'); + }).toThrow(/Found a cycle between resources in the template: Bucket1 depends on Bucket2 depends on Bucket3 depends on Bucket1/); + }); + + /** + * A->B + * B->A + * simplified version of cycle-in-resources.json, an example of cyclical references + */ + test('accepts a cycle between resources in the template if allowed', () => { + includeTestTemplate(stack, 'cycle-in-resources.json', { allowCyclicalReferences: true }); + Template.fromStack(stack, { skipCyclicalDependenciesCheck: true }).templateMatches( + { + Resources: { + Bucket2: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket1'] }, + Bucket1: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'Bucket2' } }, + }, + }, + }, + ); + }); + + /** + * A->B + * B->C + * C->{D,A} + * D->B + * simplified version of multi-cycle-in-resources.json, an example of multiple cyclical references + */ + test('accepts multiple cycles between resources in the template if allowed', () => { + includeTestTemplate(stack, 'multi-cycle-in-resources.json', { allowCyclicalReferences: true }); + Template.fromStack(stack, { skipCyclicalDependenciesCheck: true }).templateMatches( + { + Resources: { + Bucket2: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket3'] }, + Bucket3: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket4', 'Bucket1'] }, + Bucket4: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket2'] }, + Bucket1: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'Bucket2' } }, + }, + }, + }, + ); + }); + + /** + * A->B + * B->{C,A} + * C->A + * simplified version of multi-cycle-multi-dest-in-resources.json, an example of multiple cyclical references that + * include visiting the same destination more than once + */ + test('accepts multiple cycles and multiple destinations between resources in the template if allowed', () => { + includeTestTemplate(stack, 'multi-cycle-multi-dest-in-resources.json', { allowCyclicalReferences: true }); + Template.fromStack(stack, { skipCyclicalDependenciesCheck: true }).templateMatches( + { + Resources: { + Bucket2: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket3', 'Bucket1'] }, + Bucket3: { Type: 'AWS::S3::Bucket', DependsOn: ['Bucket1'] }, + Bucket1: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'Bucket2' } }, + }, + }, + }, + ); + }); }); -function includeTestTemplate(scope: constructs.Construct, testTemplate: string): inc.CfnInclude { +interface IncludeTestTemplateProps { + /** @default false */ + readonly allowCyclicalReferences?: boolean; +} + +function includeTestTemplate(scope: constructs.Construct, testTemplate: string, props: IncludeTestTemplateProps = {}): inc.CfnInclude { return new inc.CfnInclude(scope, 'MyScope', { templateFile: _testTemplateFilePath(testTemplate), + allowCyclicalReferences: props.allowCyclicalReferences, }); } diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-in-resources.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-in-resources.json new file mode 100644 index 0000000000000..06d96804f91c3 --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-in-resources.json @@ -0,0 +1,24 @@ +{ + "Resources": { + "Bucket1": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "Bucket2" + } + } + }, + "Bucket2": { + "Type": "AWS::S3::Bucket", + "DependsOn": "Bucket3" + }, + "Bucket3": { + "Type": "AWS::S3::Bucket", + "DependsOn": ["Bucket4", "Bucket1"] + }, + "Bucket4": { + "Type": "AWS::S3::Bucket", + "DependsOn": "Bucket2" + } + } +} diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-multi-dest-in-resources.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-multi-dest-in-resources.json new file mode 100644 index 0000000000000..d8ed03161b255 --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/multi-cycle-multi-dest-in-resources.json @@ -0,0 +1,20 @@ +{ + "Resources": { + "Bucket1": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "Bucket2" + } + } + }, + "Bucket2": { + "Type": "AWS::S3::Bucket", + "DependsOn": ["Bucket3", "Bucket1"] + }, + "Bucket3": { + "Type": "AWS::S3::Bucket", + "DependsOn": ["Bucket1"] + } + } +} diff --git a/packages/@aws-cdk/core/lib/app.ts b/packages/@aws-cdk/core/lib/app.ts index 5973445ab74b4..49359c4a94c35 100644 --- a/packages/@aws-cdk/core/lib/app.ts +++ b/packages/@aws-cdk/core/lib/app.ts @@ -1,5 +1,6 @@ import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; +import * as fs from 'fs-extra'; import { addCustomSynthesis, ICustomSynthesis } from './private/synthesis'; import { TreeMetadata } from './private/tree-metadata'; import { Stage } from './stage'; @@ -173,13 +174,13 @@ export class App extends Stage { this.node.setContext(k, v); } - // read from environment - const contextJson = process.env[cxapi.CONTEXT_ENV]; - const contextFromEnvironment = contextJson - ? JSON.parse(contextJson) - : { }; + // reconstructing the context from the two possible sources: + const context = { + ...this.readContextFromEnvironment(), + ...this.readContextFromTempFile(), + }; - for (const [k, v] of Object.entries(contextFromEnvironment)) { + for (const [k, v] of Object.entries(context)) { this.node.setContext(k, v); } @@ -188,6 +189,16 @@ export class App extends Stage { this.node.setContext(k, v); } } + + private readContextFromTempFile() { + const location = process.env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV]; + return location ? fs.readJSONSync(location) : {}; + } + + private readContextFromEnvironment() { + const contextJson = process.env[cxapi.CONTEXT_ENV]; + return contextJson ? JSON.parse(contextJson) : {}; + } } /** diff --git a/packages/@aws-cdk/core/lib/cfn-resource.ts b/packages/@aws-cdk/core/lib/cfn-resource.ts index 94ae9c506e5e0..9777268a7b328 100644 --- a/packages/@aws-cdk/core/lib/cfn-resource.ts +++ b/packages/@aws-cdk/core/lib/cfn-resource.ts @@ -609,6 +609,35 @@ function deepMerge(target: any, ...sources: any[]) { } } + /** + * There might also be the case where the source is an intrinsic + * + * target: { + * Type: 'MyResourceType', + * Properties: { + * prop1: { subprop: { name: { 'Fn::GetAtt': 'abc' } } } + * } + * } + * sources: [ { + * Properties: { + * prop1: { subprop: { 'Fn::If': ['SomeCondition', {...}, {...}] }} + * } + * } ] + * + * We end up in a place that is the reverse of the above check, the source + * becomes an intrinsic before the target + * + * target: { subprop: { name: { 'Fn::GetAtt': 'abc' } } } + * sources: [{ + * 'Fn::If': [ 'MyCondition', {...}, {...} ] + * }] + */ + if (Object.keys(value).length === 1) { + if (MERGE_EXCLUDE_KEYS.includes(Object.keys(value)[0])) { + target[key] = {}; + } + } + deepMerge(target[key], value); // if the result of the merge is an empty object, it's because the diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts deleted file mode 100644 index 74f96800e755a..0000000000000 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/_asset-manifest-builder.ts +++ /dev/null @@ -1,221 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import * as cxschema from '@aws-cdk/cloud-assembly-schema'; -import { FileAssetSource, FileAssetLocation, FileAssetPackaging, DockerImageAssetSource, DockerImageAssetLocation } from '../assets'; -import { Fn } from '../cfn-fn'; -import { Stack } from '../stack'; -import { resolvedOr } from './_shared'; -import { ISynthesisSession } from './types'; - -/** - * Build an manifest from assets added to a stack synthesizer - */ -export class AssetManifestBuilder { - private readonly files: NonNullable = {}; - private readonly dockerImages: NonNullable = {}; - - public addFileAssetDefault( - asset: FileAssetSource, - stack: Stack, - bucketName: string, - bucketPrefix: string, - role?: RoleOptions, - ): FileAssetLocation { - validateFileAssetSource(asset); - - const extension = - asset.fileName != undefined ? path.extname(asset.fileName) : ''; - const objectKey = - bucketPrefix + - asset.sourceHash + - (asset.packaging === FileAssetPackaging.ZIP_DIRECTORY - ? '.zip' - : extension); - - // Add to manifest - this.files[asset.sourceHash] = { - source: { - path: asset.fileName, - executable: asset.executable, - packaging: asset.packaging, - }, - destinations: { - [this.manifestEnvName(stack)]: { - bucketName: bucketName, - objectKey, - region: resolvedOr(stack.region, undefined), - assumeRoleArn: role?.assumeRoleArn, - assumeRoleExternalId: role?.assumeRoleExternalId, - }, - }, - }; - - const { region, urlSuffix } = stackLocationOrInstrinsics(stack); - const httpUrl = cfnify( - `https://s3.${region}.${urlSuffix}/${bucketName}/${objectKey}`, - ); - const s3ObjectUrlWithPlaceholders = `s3://${bucketName}/${objectKey}`; - - // Return CFN expression - // - // 's3ObjectUrlWithPlaceholders' is intended for the CLI. The CLI ultimately needs a - // 'https://s3.REGION.amazonaws.com[.cn]/name/hash' URL to give to CloudFormation. - // However, there's no way for us to actually know the URL_SUFFIX in the framework, so - // we can't construct that URL. Instead, we record the 's3://.../...' form, and the CLI - // transforms it to the correct 'https://.../' URL before calling CloudFormation. - return { - bucketName: cfnify(bucketName), - objectKey, - httpUrl, - s3ObjectUrl: cfnify(s3ObjectUrlWithPlaceholders), - s3ObjectUrlWithPlaceholders, - s3Url: httpUrl, - }; - } - - public addDockerImageAssetDefault( - asset: DockerImageAssetSource, - stack: Stack, - repositoryName: string, - dockerTagPrefix: string, - role?: RoleOptions, - ): DockerImageAssetLocation { - validateDockerImageAssetSource(asset); - const imageTag = `${dockerTagPrefix}${asset.sourceHash}`; - - // Add to manifest - this.dockerImages[asset.sourceHash] = { - source: { - executable: asset.executable, - directory: asset.directoryName, - dockerBuildArgs: asset.dockerBuildArgs, - dockerBuildTarget: asset.dockerBuildTarget, - dockerFile: asset.dockerFile, - networkMode: asset.networkMode, - platform: asset.platform, - }, - destinations: { - [this.manifestEnvName(stack)]: { - repositoryName: repositoryName, - imageTag, - region: resolvedOr(stack.region, undefined), - assumeRoleArn: role?.assumeRoleArn, - assumeRoleExternalId: role?.assumeRoleExternalId, - }, - }, - }; - - const { account, region, urlSuffix } = stackLocationOrInstrinsics(stack); - - // Return CFN expression - return { - repositoryName: cfnify(repositoryName), - imageUri: cfnify( - `${account}.dkr.ecr.${region}.${urlSuffix}/${repositoryName}:${imageTag}`, - ), - imageTag: cfnify(imageTag), - }; - } - - /** - * Write the manifest to disk, and add it to the synthesis session - * - * Reutrn the artifact Id - */ - public writeManifest( - stack: Stack, - session: ISynthesisSession, - additionalProps: Partial = {}, - ): string { - const artifactId = `${stack.artifactId}.assets`; - const manifestFile = `${artifactId}.json`; - const outPath = path.join(session.assembly.outdir, manifestFile); - - const manifest: cxschema.AssetManifest = { - version: cxschema.Manifest.version(), - files: this.files, - dockerImages: this.dockerImages, - }; - - fs.writeFileSync(outPath, JSON.stringify(manifest, undefined, 2)); - - session.assembly.addArtifact(artifactId, { - type: cxschema.ArtifactType.ASSET_MANIFEST, - properties: { - file: manifestFile, - ...additionalProps, - }, - }); - - return artifactId; - } - - private manifestEnvName(stack: Stack): string { - return [ - resolvedOr(stack.account, 'current_account'), - resolvedOr(stack.region, 'current_region'), - ].join('-'); - } -} - -export interface RoleOptions { - readonly assumeRoleArn?: string; - readonly assumeRoleExternalId?: string; -} - -function validateFileAssetSource(asset: FileAssetSource) { - if (!!asset.executable === !!asset.fileName) { - throw new Error(`Exactly one of 'fileName' or 'executable' is required, got: ${JSON.stringify(asset)}`); - } - - if (!!asset.packaging !== !!asset.fileName) { - throw new Error(`'packaging' is expected in combination with 'fileName', got: ${JSON.stringify(asset)}`); - } -} - -function validateDockerImageAssetSource(asset: DockerImageAssetSource) { - if (!!asset.executable === !!asset.directoryName) { - throw new Error(`Exactly one of 'directoryName' or 'executable' is required, got: ${JSON.stringify(asset)}`); - } - - check('dockerBuildArgs'); - check('dockerBuildTarget'); - check('dockerFile'); - - function check(key: K) { - if (asset[key] && !asset.directoryName) { - throw new Error(`'${key}' is only allowed in combination with 'directoryName', got: ${JSON.stringify(asset)}`); - } - } -} - -/** - * Return the stack locations if they're concrete, or the original CFN intrisics otherwise - * - * We need to return these instead of the tokenized versions of the strings, - * since we must accept those same ${AWS::AccountId}/${AWS::Region} placeholders - * in bucket names and role names (in order to allow environment-agnostic stacks). - * - * We'll wrap a single {Fn::Sub} around the final string in order to replace everything, - * but we can't have the token system render part of the string to {Fn::Join} because - * the CFN specification doesn't allow the {Fn::Sub} template string to be an arbitrary - * expression--it must be a string literal. - */ -function stackLocationOrInstrinsics(stack: Stack) { - return { - account: resolvedOr(stack.account, '${AWS::AccountId}'), - region: resolvedOr(stack.region, '${AWS::Region}'), - urlSuffix: resolvedOr(stack.urlSuffix, '${AWS::URLSuffix}'), - }; -} - -/** - * If the string still contains placeholders, wrap it in a Fn::Sub so they will be substituted at CFN deployment time - * - * (This happens to work because the placeholders we picked map directly onto CFN - * placeholders. If they didn't we'd have to do a transformation here). - */ -function cfnify(s: string): string { - return s.indexOf('${') > -1 ? Fn.sub(s) : s; -} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts index cae4195035c25..c4579949debe5 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/_shared.ts @@ -1,10 +1,7 @@ import * as crypto from 'crypto'; -import * as fs from 'fs'; -import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { Node, IConstruct } from 'constructs'; -import { FileAssetSource, FileAssetPackaging } from '../assets'; import { Stack } from '../stack'; import { Token } from '../token'; import { ISynthesisSession } from './types'; @@ -172,16 +169,3 @@ export class StringSpecializer { export function resolvedOr(x: string, def: A): string | A { return Token.isUnresolved(x) ? def : x; } - -export function stackTemplateFileAsset(stack: Stack, session: ISynthesisSession): FileAssetSource { - const templatePath = path.join(session.assembly.outdir, stack.templateFile); - const template = fs.readFileSync(templatePath, { encoding: 'utf-8' }); - - const sourceHash = contentHash(template); - - return { - fileName: stack.templateFile, - packaging: FileAssetPackaging.FILE, - sourceHash, - }; -} diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts new file mode 100644 index 0000000000000..73e23c330c9b1 --- /dev/null +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts @@ -0,0 +1,251 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import { FileAssetSource, FileAssetPackaging, DockerImageAssetSource } from '../assets'; +import { Stack } from '../stack'; +import { resolvedOr } from './_shared'; +import { ISynthesisSession } from './types'; + +/** + * Build an asset manifest from assets added to a stack + * + * This class does not need to be used by app builders; it is only nessary for building Stack Synthesizers. + */ +export class AssetManifestBuilder { + private readonly files: NonNullable = {}; + private readonly dockerImages: NonNullable = {}; + + /** + * Add a file asset to the manifest with default settings + * + * Derive the region from the stack, use the asset hash as the key, copy the + * file extension over, and set the prefix. + */ + public defaultAddFileAsset(stack: Stack, asset: FileAssetSource, target: AssetManifestFileDestination) { + validateFileAssetSource(asset); + + const extension = + asset.fileName != undefined ? path.extname(asset.fileName) : ''; + const objectKey = + (target.bucketPrefix ?? '') + + asset.sourceHash + + (asset.packaging === FileAssetPackaging.ZIP_DIRECTORY + ? '.zip' + : extension); + + // Add to manifest + return this.addFileAsset(stack, asset.sourceHash, { + path: asset.fileName, + executable: asset.executable, + packaging: asset.packaging, + }, { + bucketName: target.bucketName, + objectKey, + region: resolvedOr(stack.region, undefined), + assumeRoleArn: target.role?.assumeRoleArn, + assumeRoleExternalId: target.role?.assumeRoleExternalId, + }); + } + + /** + * Add a docker image asset to the manifest with default settings + * + * Derive the region from the stack, use the asset hash as the key, and set the prefix. + */ + public defaultAddDockerImageAsset( + stack: Stack, + asset: DockerImageAssetSource, + target: AssetManifestDockerImageDestination, + ) { + validateDockerImageAssetSource(asset); + const imageTag = `${target.dockerTagPrefix ?? ''}${asset.sourceHash}`; + + // Add to manifest + return this.addDockerImageAsset(stack, asset.sourceHash, { + executable: asset.executable, + directory: asset.directoryName, + dockerBuildArgs: asset.dockerBuildArgs, + dockerBuildTarget: asset.dockerBuildTarget, + dockerFile: asset.dockerFile, + networkMode: asset.networkMode, + platform: asset.platform, + }, { + repositoryName: target.repositoryName, + imageTag, + region: resolvedOr(stack.region, undefined), + assumeRoleArn: target.role?.assumeRoleArn, + assumeRoleExternalId: target.role?.assumeRoleExternalId, + }); + } + + /** + * Add a file asset source and destination to the manifest + * + * sourceHash should be unique for every source. + */ + public addFileAsset(stack: Stack, sourceHash: string, source: cxschema.FileSource, dest: cxschema.FileDestination) { + if (!this.files[sourceHash]) { + this.files[sourceHash] = { + source, + destinations: {}, + }; + } + this.files[sourceHash].destinations[this.manifestEnvName(stack)] = dest; + return dest; + } + + /** + * Add a docker asset source and destination to the manifest + * + * sourceHash should be unique for every source. + */ + public addDockerImageAsset(stack: Stack, sourceHash: string, source: cxschema.DockerImageSource, dest: cxschema.DockerImageDestination) { + if (!this.dockerImages[sourceHash]) { + this.dockerImages[sourceHash] = { + source, + destinations: {}, + }; + } + this.dockerImages[sourceHash].destinations[this.manifestEnvName(stack)] = dest; + return dest; + } + + /** + * Whether there are any assets registered in the manifest + */ + public get hasAssets() { + return Object.keys(this.files).length + Object.keys(this.dockerImages).length > 0; + } + + /** + * Write the manifest to disk, and add it to the synthesis session + * + * Return the artifact id, which should be added to the `additionalDependencies` + * field of the stack artifact. + */ + public emitManifest( + stack: Stack, + session: ISynthesisSession, + options: cxschema.AssetManifestOptions = {}, + ): string { + const artifactId = `${stack.artifactId}.assets`; + const manifestFile = `${artifactId}.json`; + const outPath = path.join(session.assembly.outdir, manifestFile); + + const manifest: cxschema.AssetManifest = { + version: cxschema.Manifest.version(), + files: this.files, + dockerImages: this.dockerImages, + }; + + fs.writeFileSync(outPath, JSON.stringify(manifest, undefined, 2)); + + session.assembly.addArtifact(artifactId, { + type: cxschema.ArtifactType.ASSET_MANIFEST, + properties: { + file: manifestFile, + ...options, + }, + }); + + return artifactId; + } + + private manifestEnvName(stack: Stack): string { + return [ + resolvedOr(stack.account, 'current_account'), + resolvedOr(stack.region, 'current_region'), + ].join('-'); + } +} + +/** + * The destination for a file asset, when it is given to the AssetManifestBuilder + */ +export interface AssetManifestFileDestination { + /** + * Bucket name where the file asset should be written + */ + readonly bucketName: string; + + /** + * Prefix to prepend to the asset hash + * + * @default '' + */ + readonly bucketPrefix?: string; + + /** + * Role to use for uploading + * + * @default - current role + */ + readonly role?: RoleOptions; +} + +/** + * The destination for a docker image asset, when it is given to the AssetManifestBuilder + */ +export interface AssetManifestDockerImageDestination { + /** + * Repository name where the docker image asset should be written + */ + readonly repositoryName: string; + + /** + * Prefix to add to the asset hash to make the Docker image tag + * + * @default '' + */ + readonly dockerTagPrefix?: string; + + /** + * Role to use to perform the upload + * + * @default - No role + */ + readonly role?: RoleOptions; +} + +/** + * Options for specifying a role + */ +export interface RoleOptions { + /** + * ARN of the role to assume + */ + readonly assumeRoleArn: string; + + /** + * External ID to use when assuming the role + * + * @default - No external ID + */ + readonly assumeRoleExternalId?: string; +} + +function validateFileAssetSource(asset: FileAssetSource) { + if (!!asset.executable === !!asset.fileName) { + throw new Error(`Exactly one of 'fileName' or 'executable' is required, got: ${JSON.stringify(asset)}`); + } + + if (!!asset.packaging !== !!asset.fileName) { + throw new Error(`'packaging' is expected in combination with 'fileName', got: ${JSON.stringify(asset)}`); + } +} + +function validateDockerImageAssetSource(asset: DockerImageAssetSource) { + if (!!asset.executable === !!asset.directoryName) { + throw new Error(`Exactly one of 'directoryName' or 'executable' is required, got: ${JSON.stringify(asset)}`); + } + + check('dockerBuildArgs'); + check('dockerBuildTarget'); + check('dockerFile'); + + function check(key: K) { + if (asset[key] && !asset.directoryName) { + throw new Error(`'${key}' is only allowed in combination with 'directoryName', got: ${JSON.stringify(asset)}`); + } + } +} diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts index f98c9925cdff0..1ecc74efd6126 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/bootstrapless-synthesizer.ts @@ -1,5 +1,4 @@ import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; -import { assertBound } from './_shared'; import { DefaultStackSynthesizer } from './default-synthesizer'; import { ISynthesisSession } from './types'; @@ -56,13 +55,11 @@ export class BootstraplessSynthesizer extends DefaultStackSynthesizer { } public synthesize(session: ISynthesisSession): void { - assertBound(this.stack); - - this.synthesizeStackTemplate(this.stack, session); + this.synthesizeStackTemplate(this.boundStack, session); // do _not_ treat the template as an asset, // because this synthesizer doesn't have a bootstrap bucket to put it in - this.emitStackArtifact(this.stack, session, { + this.emitArtifact(session, { assumeRoleArn: this.deployRoleArn, cloudFormationExecutionRoleArn: this.cloudFormationExecutionRoleArn, }); diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts index 20ba571e45f77..095098ec0022d 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/cli-credentials-synthesizer.ts @@ -2,8 +2,8 @@ import * as cxapi from '@aws-cdk/cx-api'; import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; import { Stack } from '../stack'; import { Token } from '../token'; -import { AssetManifestBuilder } from './_asset-manifest-builder'; -import { assertBound, StringSpecializer, stackTemplateFileAsset } from './_shared'; +import { assertBound, StringSpecializer } from './_shared'; +import { AssetManifestBuilder } from './asset-manifest-builder'; import { BOOTSTRAP_QUALIFIER_CONTEXT, DefaultStackSynthesizer } from './default-synthesizer'; import { StackSynthesizer } from './stack-synthesizer'; import { ISynthesisSession } from './types'; @@ -87,7 +87,6 @@ export interface CliCredentialsStackSynthesizerProps { * the default names using the synthesizer's construction properties. */ export class CliCredentialsStackSynthesizer extends StackSynthesizer { - private stack?: Stack; private qualifier?: string; private bucketName?: string; private repositoryName?: string; @@ -108,7 +107,7 @@ export class CliCredentialsStackSynthesizer extends StackSynthesizer { function validateNoToken(key: A) { const prop = props[key]; if (typeof prop === 'string' && Token.isUnresolved(prop)) { - throw new Error(`DefaultSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [ + throw new Error(`CliCredentialsStackSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [ '${Qualifier}', cxapi.EnvironmentPlaceholders.CURRENT_REGION, cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT, @@ -119,11 +118,7 @@ export class CliCredentialsStackSynthesizer extends StackSynthesizer { } public bind(stack: Stack): void { - if (this.stack !== undefined) { - throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); - } - - this.stack = stack; + super.bind(stack); const qualifier = this.props.qualifier ?? stack.node.tryGetContext(BOOTSTRAP_QUALIFIER_CONTEXT) ?? DefaultStackSynthesizer.DEFAULT_QUALIFIER; this.qualifier = qualifier; @@ -139,34 +134,37 @@ export class CliCredentialsStackSynthesizer extends StackSynthesizer { } public addFileAsset(asset: FileAssetSource): FileAssetLocation { - assertBound(this.stack); assertBound(this.bucketName); - assertBound(this.bucketPrefix); - return this.assetManifest.addFileAssetDefault(asset, this.stack, this.bucketName, this.bucketPrefix); + const location = this.assetManifest.defaultAddFileAsset(this.boundStack, asset, { + bucketName: this.bucketName, + bucketPrefix: this.bucketPrefix, + }); + return this.cloudFormationLocationFromFileAsset(location); } public addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { - assertBound(this.stack); assertBound(this.repositoryName); - assertBound(this.dockerTagPrefix); - return this.assetManifest.addDockerImageAssetDefault(asset, this.stack, this.repositoryName, this.dockerTagPrefix); + const location = this.assetManifest.defaultAddDockerImageAsset(this.boundStack, asset, { + repositoryName: this.repositoryName, + dockerTagPrefix: this.dockerTagPrefix, + }); + return this.cloudFormationLocationFromDockerImageAsset(location); } /** * Synthesize the associated stack to the session */ public synthesize(session: ISynthesisSession): void { - assertBound(this.stack); assertBound(this.qualifier); - this.synthesizeStackTemplate(this.stack, session); + const templateAssetSource = this.synthesizeTemplate(session); + const templateAsset = this.addFileAsset(templateAssetSource); - const templateAsset = this.addFileAsset(stackTemplateFileAsset(this.stack, session)); - const assetManifestId = this.assetManifest.writeManifest(this.stack, session); + const assetManifestId = this.assetManifest.emitManifest(this.boundStack, session); - this.emitStackArtifact(this.stack, session, { + this.emitArtifact(session, { stackTemplateAssetObjectUrl: templateAsset.s3ObjectUrlWithPlaceholders, additionalDependencies: [assetManifestId], }); diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts index 323dbf413a4d1..0118db4190955 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts @@ -1,12 +1,9 @@ import * as cxapi from '@aws-cdk/cx-api'; import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; -import { Fn } from '../cfn-fn'; -import { CfnParameter } from '../cfn-parameter'; -import { CfnRule } from '../cfn-rule'; import { Stack } from '../stack'; import { Token } from '../token'; -import { AssetManifestBuilder } from './_asset-manifest-builder'; -import { assertBound, StringSpecializer, stackTemplateFileAsset } from './_shared'; +import { assertBound, StringSpecializer } from './_shared'; +import { AssetManifestBuilder } from './asset-manifest-builder'; import { StackSynthesizer } from './stack-synthesizer'; import { ISynthesisSession } from './types'; @@ -290,7 +287,6 @@ export class DefaultStackSynthesizer extends StackSynthesizer { */ public static readonly DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER = '/cdk-bootstrap/${Qualifier}/version'; - private _stack?: Stack; private bucketName?: string; private repositoryName?: string; private _deployRoleArn?: string; @@ -303,7 +299,6 @@ export class DefaultStackSynthesizer extends StackSynthesizer { private bucketPrefix?: string; private dockerTagPrefix?: string; private bootstrapStackVersionSsmParameter?: string; - private assetManifest = new AssetManifestBuilder(); constructor(private readonly props: DefaultStackSynthesizerProps = {}) { @@ -319,7 +314,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { function validateNoToken(key: A) { const prop = props[key]; if (typeof prop === 'string' && Token.isUnresolved(prop)) { - throw new Error(`DefaultSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [ + throw new Error(`DefaultStackSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [ '${Qualifier}', cxapi.EnvironmentPlaceholders.CURRENT_REGION, cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT, @@ -330,11 +325,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { } public bind(stack: Stack): void { - if (this._stack !== undefined) { - throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); - } - - this._stack = stack; + super.bind(stack); const qualifier = this.props.qualifier ?? stack.node.tryGetContext(BOOTSTRAP_QUALIFIER_CONTEXT) ?? DefaultStackSynthesizer.DEFAULT_QUALIFIER; this.qualifier = qualifier; @@ -356,36 +347,53 @@ export class DefaultStackSynthesizer extends StackSynthesizer { } public addFileAsset(asset: FileAssetSource): FileAssetLocation { - assertBound(this.stack); assertBound(this.bucketName); - assertBound(this.bucketPrefix); - return this.assetManifest.addFileAssetDefault(asset, this.stack, this.bucketName, this.bucketPrefix, { - assumeRoleArn: this.fileAssetPublishingRoleArn, - assumeRoleExternalId: this.props.fileAssetPublishingExternalId, + const location = this.assetManifest.defaultAddFileAsset(this.boundStack, asset, { + bucketName: this.bucketName, + bucketPrefix: this.bucketPrefix, + role: this.fileAssetPublishingRoleArn ? { + assumeRoleArn: this.fileAssetPublishingRoleArn, + assumeRoleExternalId: this.props.fileAssetPublishingExternalId, + } : undefined, }); + return this.cloudFormationLocationFromFileAsset(location); } public addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { - assertBound(this.stack); assertBound(this.repositoryName); - assertBound(this.dockerTagPrefix); - return this.assetManifest.addDockerImageAssetDefault(asset, this.stack, this.repositoryName, this.dockerTagPrefix, { - assumeRoleArn: this.imageAssetPublishingRoleArn, - assumeRoleExternalId: this.props.imageAssetPublishingExternalId, + const location = this.assetManifest.defaultAddDockerImageAsset(this.boundStack, asset, { + repositoryName: this.repositoryName, + dockerTagPrefix: this.dockerTagPrefix, + role: this.imageAssetPublishingRoleArn ? { + assumeRoleArn: this.imageAssetPublishingRoleArn, + assumeRoleExternalId: this.props.imageAssetPublishingExternalId, + } : undefined, }); + return this.cloudFormationLocationFromDockerImageAsset(location); } + /** + * Synthesize the stack template to the given session, passing the configured lookup role ARN + */ protected synthesizeStackTemplate(stack: Stack, session: ISynthesisSession) { stack._synthesizeTemplate(session, this.lookupRoleArn); } + /** + * Return the currently bound stack + * + * @deprecated Use `boundStack` instead. + */ + protected get stack(): Stack | undefined { + return this.boundStack; + } + /** * Synthesize the associated stack to the session */ public synthesize(session: ISynthesisSession): void { - assertBound(this.stack); assertBound(this.qualifier); // Must be done here -- if it's done in bind() (called in the Stack's constructor) @@ -394,19 +402,18 @@ export class DefaultStackSynthesizer extends StackSynthesizer { // If it's done AFTER _synthesizeTemplate(), then the template won't contain the // right constructs. if (this.props.generateBootstrapVersionRule ?? true) { - addBootstrapVersionRule(this.stack, MIN_BOOTSTRAP_STACK_VERSION, this.bootstrapStackVersionSsmParameter); + this.addBootstrapVersionRule(MIN_BOOTSTRAP_STACK_VERSION, this.bootstrapStackVersionSsmParameter!); } - this.synthesizeStackTemplate(this.stack, session); + const templateAssetSource = this.synthesizeTemplate(session, this.lookupRoleArn); + const templateAsset = this.addFileAsset(templateAssetSource); - const templateAsset = this.addFileAsset(stackTemplateFileAsset(this.stack, session)); - - const assetManifestId = this.assetManifest.writeManifest(this.stack, session, { + const assetManifestId = this.assetManifest.emitManifest(this.boundStack, session, { requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION, bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter, }); - this.emitStackArtifact(this.stack, session, { + this.emitArtifact(session, { assumeRoleExternalId: this.props.deployRoleExternalId, assumeRoleArn: this._deployRoleArn, cloudFormationExecutionRoleArn: this._cloudFormationExecutionRoleArn, @@ -442,48 +449,4 @@ export class DefaultStackSynthesizer extends StackSynthesizer { } return this._cloudFormationExecutionRoleArn; } - - protected get stack(): Stack | undefined { - return this._stack; - } -} - -/** - * Add a CfnRule to the Stack which checks the current version of the bootstrap stack this template is targeting - * - * The CLI normally checks this, but in a pipeline the CLI is not involved - * so we encode this rule into the template in a way that CloudFormation will check it. - */ -function addBootstrapVersionRule(stack: Stack, requiredVersion: number, bootstrapStackVersionSsmParameter: string) { - // Because of https://github.com/aws/aws-cdk/blob/main/packages/assert-internal/lib/synth-utils.ts#L74 - // synthesize() may be called more than once on a stack in unit tests, and the below would break - // if we execute it a second time. Guard against the constructs already existing. - if (stack.node.tryFindChild('BootstrapVersion')) { return; } - - const param = new CfnParameter(stack, 'BootstrapVersion', { - type: 'AWS::SSM::Parameter::Value', - description: `Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. ${cxapi.SSMPARAM_NO_INVALIDATE}`, - default: bootstrapStackVersionSsmParameter, - }); - - // There is no >= check in CloudFormation, so we have to check the number - // is NOT in [1, 2, 3, ... - 1] - const oldVersions = range(1, requiredVersion).map(n => `${n}`); - - new CfnRule(stack, 'CheckBootstrapVersion', { - assertions: [ - { - assert: Fn.conditionNot(Fn.conditionContains(oldVersions, param.valueAsString)), - assertDescription: `CDK bootstrap stack version ${requiredVersion} required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.`, - }, - ], - }); -} - -function range(startIncl: number, endExcl: number) { - const ret = new Array(); - for (let i = startIncl; i < endExcl; i++) { - ret.push(i); - } - return ret; } diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts index 2a7a4060dcf53..6b16861016c99 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/index.ts @@ -5,3 +5,4 @@ export * from './bootstrapless-synthesizer'; export * from './nested'; export * from './stack-synthesizer'; export * from './cli-credentials-synthesizer'; +export * from './asset-manifest-builder'; diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts index c1652e462df41..c7c76ddc94819 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts @@ -4,7 +4,6 @@ import { Construct } from 'constructs'; import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; import { Fn } from '../cfn-fn'; import { FileAssetParameters } from '../private/asset-parameters'; -import { Stack } from '../stack'; import { assertBound } from './_shared'; import { StackSynthesizer } from './stack-synthesizer'; import { ISynthesisSession } from './types'; @@ -46,7 +45,6 @@ const ASSETS_ECR_REPOSITORY_NAME_OVERRIDE_CONTEXT_KEY = 'assets-ecr-repository-n * by overriding `Stack.addFileAsset()` and `Stack.addDockerImageAsset()`. */ export class LegacyStackSynthesizer extends StackSynthesizer { - private stack?: Stack; private cycle = false; /** @@ -60,16 +58,7 @@ export class LegacyStackSynthesizer extends StackSynthesizer { */ private readonly addedImageAssets = new Set(); - public bind(stack: Stack): void { - if (this.stack !== undefined) { - throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); - } - this.stack = stack; - } - public addFileAsset(asset: FileAssetSource): FileAssetLocation { - assertBound(this.stack); - // Backwards compatibility hack. We have a number of conflicting goals here: // // - We want put the actual logic in this class @@ -88,7 +77,7 @@ export class LegacyStackSynthesizer extends StackSynthesizer { } this.cycle = true; try { - const stack = this.stack; + const stack = this.boundStack; return withoutDeprecationWarnings(() => stack.addFileAsset(asset)); } finally { this.cycle = false; @@ -96,8 +85,6 @@ export class LegacyStackSynthesizer extends StackSynthesizer { } public addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { - assertBound(this.stack); - // See `addFileAsset` for explanation. // @deprecated: this can be removed for v2 if (this.cycle) { @@ -105,7 +92,7 @@ export class LegacyStackSynthesizer extends StackSynthesizer { } this.cycle = true; try { - const stack = this.stack; + const stack = this.boundStack; return withoutDeprecationWarnings(() => stack.addDockerImageAsset(asset)); } finally { this.cycle = false; @@ -116,19 +103,15 @@ export class LegacyStackSynthesizer extends StackSynthesizer { * Synthesize the associated stack to the session */ public synthesize(session: ISynthesisSession): void { - assertBound(this.stack); - - this.synthesizeStackTemplate(this.stack, session); + this.synthesizeTemplate(session); // Just do the default stuff, nothing special - this.emitStackArtifact(this.stack, session); + this.emitArtifact(session); } private doAddDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation { - assertBound(this.stack); - // check if we have an override from context - const repositoryNameOverride = this.stack.node.tryGetContext(ASSETS_ECR_REPOSITORY_NAME_OVERRIDE_CONTEXT_KEY); + const repositoryNameOverride = this.boundStack.node.tryGetContext(ASSETS_ECR_REPOSITORY_NAME_OVERRIDE_CONTEXT_KEY); const repositoryName = asset.repositoryName ?? repositoryNameOverride ?? ASSETS_ECR_REPOSITORY_NAME; const imageTag = asset.sourceHash; const assetId = asset.sourceHash; @@ -153,19 +136,17 @@ export class LegacyStackSynthesizer extends StackSynthesizer { platform: asset.platform, }; - this.stack.node.addMetadata(cxschema.ArtifactMetadataEntryType.ASSET, metadata); + this.boundStack.node.addMetadata(cxschema.ArtifactMetadataEntryType.ASSET, metadata); this.addedImageAssets.add(assetId); } return { - imageUri: `${this.stack.account}.dkr.ecr.${this.stack.region}.${this.stack.urlSuffix}/${repositoryName}:${imageTag}`, + imageUri: `${this.boundStack.account}.dkr.ecr.${this.boundStack.region}.${this.boundStack.urlSuffix}/${repositoryName}:${imageTag}`, repositoryName, }; } private doAddFileAsset(asset: FileAssetSource): FileAssetLocation { - assertBound(this.stack); - let params = this.assetParameters.node.tryFindChild(asset.sourceHash) as FileAssetParameters; if (!params) { params = new FileAssetParameters(this.assetParameters, asset.sourceHash); @@ -185,7 +166,7 @@ export class LegacyStackSynthesizer extends StackSynthesizer { artifactHashParameter: params.artifactHashParameter.logicalId, }; - this.stack.node.addMetadata(cxschema.ArtifactMetadataEntryType.ASSET, metadata); + this.boundStack.node.addMetadata(cxschema.ArtifactMetadataEntryType.ASSET, metadata); } const bucketName = params.bucketNameParameter.valueAsString; @@ -197,17 +178,17 @@ export class LegacyStackSynthesizer extends StackSynthesizer { const s3Filename = Fn.select(1, Fn.split(cxapi.ASSET_PREFIX_SEPARATOR, encodedKey)); const objectKey = `${s3Prefix}${s3Filename}`; - const httpUrl = `https://s3.${this.stack.region}.${this.stack.urlSuffix}/${bucketName}/${objectKey}`; + const httpUrl = `https://s3.${this.boundStack.region}.${this.boundStack.urlSuffix}/${bucketName}/${objectKey}`; const s3ObjectUrl = `s3://${bucketName}/${objectKey}`; return { bucketName, objectKey, httpUrl, s3ObjectUrl, s3Url: httpUrl }; } private get assetParameters() { - assertBound(this.stack); + assertBound(this.boundStack); if (!this._assetParameters) { - this._assetParameters = new Construct(this.stack, 'AssetParameters'); + this._assetParameters = new Construct(this.boundStack, 'AssetParameters'); } return this._assetParameters; } diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts index d9c86fc782745..c04867f86695c 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/nested.ts @@ -1,6 +1,4 @@ import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; -import { Stack } from '../stack'; -import { assertBound } from './_shared'; import { StackSynthesizer } from './stack-synthesizer'; import { IStackSynthesizer, ISynthesisSession } from './types'; @@ -13,19 +11,10 @@ import { IStackSynthesizer, ISynthesisSession } from './types'; * App builder do not need to use this class directly. */ export class NestedStackSynthesizer extends StackSynthesizer { - private stack?: Stack; - constructor(private readonly parentDeployment: IStackSynthesizer) { super(); } - public bind(stack: Stack): void { - if (this.stack !== undefined) { - throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); - } - this.stack = stack; - } - public addFileAsset(asset: FileAssetSource): FileAssetLocation { // Forward to parent deployment. By the magic of cross-stack references any parameter // returned and used will magically be forwarded to the nested stack. @@ -39,9 +28,8 @@ export class NestedStackSynthesizer extends StackSynthesizer { } public synthesize(session: ISynthesisSession): void { - assertBound(this.stack); // Synthesize the template, but don't emit as a cloud assembly artifact. // It will be registered as an S3 asset of its parent instead. - this.synthesizeStackTemplate(this.stack, session); + this.synthesizeTemplate(session); } } diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts index 6253df8caf0d8..624d22b173eea 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/stack-synthesizer.ts @@ -1,7 +1,13 @@ +import * as fs from 'fs'; +import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; -import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from '../assets'; +import * as cxapi from '@aws-cdk/cx-api'; +import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource, FileAssetPackaging } from '../assets'; +import { Fn } from '../cfn-fn'; +import { CfnParameter } from '../cfn-parameter'; +import { CfnRule } from '../cfn-rule'; import { Stack } from '../stack'; -import { addStackArtifactToAssembly } from './_shared'; +import { addStackArtifactToAssembly, contentHash, resolvedOr } from './_shared'; import { IStackSynthesizer, ISynthesisSession } from './types'; /** @@ -13,17 +19,31 @@ import { IStackSynthesizer, ISynthesisSession } from './types'; * and could not be accessed by external implementors. */ export abstract class StackSynthesizer implements IStackSynthesizer { + private _boundStack?: Stack; + /** * Bind to the stack this environment is going to be used on * * Must be called before any of the other methods are called. */ - public abstract bind(stack: Stack): void; + public bind(stack: Stack): void { + if (this._boundStack !== undefined) { + throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack'); + } + + this._boundStack = stack; + } /** * Register a File Asset * * Returns the parameters that can be used to refer to the asset inside the template. + * + * The synthesizer must rely on some out-of-band mechanism to make sure the given files + * are actually placed in the returned location before the deployment happens. This can + * be by writing the intructions to the asset manifest (for use by the `cdk-assets` tool), + * by relying on the CLI to upload files (legacy behavior), or some other operator controlled + * mechanism. */ public abstract addFileAsset(asset: FileAssetSource): FileAssetLocation; @@ -31,6 +51,12 @@ export abstract class StackSynthesizer implements IStackSynthesizer { * Register a Docker Image Asset * * Returns the parameters that can be used to refer to the asset inside the template. + * + * The synthesizer must rely on some out-of-band mechanism to make sure the given files + * are actually placed in the returned location before the deployment happens. This can + * be by writing the intructions to the asset manifest (for use by the `cdk-assets` tool), + * by relying on the CLI to upload files (legacy behavior), or some other operator controlled + * mechanism. */ public abstract addDockerImageAsset(asset: DockerImageAssetSource): DockerImageAssetLocation; @@ -41,20 +67,126 @@ export abstract class StackSynthesizer implements IStackSynthesizer { /** * Have the stack write out its template + * + * @deprecated Use `synthesizeTemplate` instead */ protected synthesizeStackTemplate(stack: Stack, session: ISynthesisSession): void { stack._synthesizeTemplate(session); } + /** + * Write the stack template to the given session + * + * Return a descriptor that represents the stack template as a file asset + * source, for adding to an asset manifest (if desired). This can be used to + * have the asset manifest system (`cdk-assets`) upload the template to S3 + * using the appropriate role, so that afterwards only a CloudFormation + * deployment is necessary. + * + * If the template is uploaded as an asset, the `stackTemplateAssetObjectUrl` + * property should be set when calling `emitArtifact.` + * + * If the template is *NOT* uploaded as an asset first and the template turns + * out to be >50KB, it will need to be uploaded to S3 anyway. At that point + * the credentials will be the same identity that is doing the `UpdateStack` + * call, which may not have the right permissions to write to S3. + */ + protected synthesizeTemplate(session: ISynthesisSession, lookupRoleArn?: string): FileAssetSource { + this.boundStack._synthesizeTemplate(session, lookupRoleArn); + return stackTemplateFileAsset(this.boundStack, session); + } + /** * Write the stack artifact to the session * * Use default settings to add a CloudFormationStackArtifact artifact to * the given synthesis session. + * + * @deprecated Use `emitArtifact` instead */ protected emitStackArtifact(stack: Stack, session: ISynthesisSession, options: SynthesizeStackArtifactOptions = {}) { addStackArtifactToAssembly(session, stack, options ?? {}, options.additionalDependencies ?? []); } + + /** + * Write the CloudFormation stack artifact to the session + * + * Use default settings to add a CloudFormationStackArtifact artifact to + * the given synthesis session. The Stack artifact will control the settings for the + * CloudFormation deployment. + */ + protected emitArtifact(session: ISynthesisSession, options: SynthesizeStackArtifactOptions = {}) { + addStackArtifactToAssembly(session, this.boundStack, options ?? {}, options.additionalDependencies ?? []); + } + + /** + * Add a CfnRule to the bound stack that checks whether an SSM parameter exceeds a given version + * + * This will modify the template, so must be called before the stack is synthesized. + */ + protected addBootstrapVersionRule(requiredVersion: number, bootstrapStackVersionSsmParameter: string) { + addBootstrapVersionRule(this.boundStack, requiredVersion, bootstrapStackVersionSsmParameter); + } + + /** + * Retrieve the bound stack + * + * Fails if the stack hasn't been bound yet. + */ + protected get boundStack(): Stack { + if (!this._boundStack) { + throw new Error('The StackSynthesizer must be bound to a Stack first before boundStack() can be called'); + } + return this._boundStack; + } + + /** + * Turn a file asset location into a CloudFormation representation of that location + * + * If any of the fields contain placeholders, the result will be wrapped in a `Fn.sub`. + */ + protected cloudFormationLocationFromFileAsset(location: cxschema.FileDestination): FileAssetLocation { + const { region, urlSuffix } = stackLocationOrInstrinsics(this.boundStack); + const httpUrl = cfnify( + `https://s3.${region}.${urlSuffix}/${location.bucketName}/${location.objectKey}`, + ); + const s3ObjectUrlWithPlaceholders = `s3://${location.bucketName}/${location.objectKey}`; + + // Return CFN expression + // + // 's3ObjectUrlWithPlaceholders' is intended for the CLI. The CLI ultimately needs a + // 'https://s3.REGION.amazonaws.com[.cn]/name/hash' URL to give to CloudFormation. + // However, there's no way for us to actually know the URL_SUFFIX in the framework, so + // we can't construct that URL. Instead, we record the 's3://.../...' form, and the CLI + // transforms it to the correct 'https://.../' URL before calling CloudFormation. + return { + bucketName: cfnify(location.bucketName), + objectKey: cfnify(location.objectKey), + httpUrl, + s3ObjectUrl: cfnify(s3ObjectUrlWithPlaceholders), + s3ObjectUrlWithPlaceholders, + s3Url: httpUrl, + }; + } + + /** + * Turn a docker asset location into a CloudFormation representation of that location + * + * If any of the fields contain placeholders, the result will be wrapped in a `Fn.sub`. + */ + protected cloudFormationLocationFromDockerImageAsset(dest: cxschema.DockerImageDestination): DockerImageAssetLocation { + const { account, region, urlSuffix } = stackLocationOrInstrinsics(this.boundStack); + + // Return CFN expression + return { + repositoryName: cfnify(dest.repositoryName), + imageUri: cfnify( + `${account}.dkr.ecr.${region}.${urlSuffix}/${dest.repositoryName}:${dest.imageTag}`, + ), + imageTag: cfnify(dest.imageTag), + }; + } + } /** @@ -135,3 +267,91 @@ export interface SynthesizeStackArtifactOptions { */ readonly bootstrapStackVersionSsmParameter?: string; } + +function stackTemplateFileAsset(stack: Stack, session: ISynthesisSession): FileAssetSource { + const templatePath = path.join(session.assembly.outdir, stack.templateFile); + + if (!fs.existsSync(templatePath)) { + throw new Error(`Stack template ${stack.stackName} not written yet: ${templatePath}`); + } + + const template = fs.readFileSync(templatePath, { encoding: 'utf-8' }); + + const sourceHash = contentHash(template); + + return { + fileName: stack.templateFile, + packaging: FileAssetPackaging.FILE, + sourceHash, + }; +} + +/** + * Add a CfnRule to the Stack which checks the current version of the bootstrap stack this template is targeting + * + * The CLI normally checks this, but in a pipeline the CLI is not involved + * so we encode this rule into the template in a way that CloudFormation will check it. + */ +function addBootstrapVersionRule(stack: Stack, requiredVersion: number, bootstrapStackVersionSsmParameter: string) { + // Because of https://github.com/aws/aws-cdk/blob/main/packages/assert-internal/lib/synth-utils.ts#L74 + // synthesize() may be called more than once on a stack in unit tests, and the below would break + // if we execute it a second time. Guard against the constructs already existing. + if (stack.node.tryFindChild('BootstrapVersion')) { return; } + + const param = new CfnParameter(stack, 'BootstrapVersion', { + type: 'AWS::SSM::Parameter::Value', + description: `Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. ${cxapi.SSMPARAM_NO_INVALIDATE}`, + default: bootstrapStackVersionSsmParameter, + }); + + // There is no >= check in CloudFormation, so we have to check the number + // is NOT in [1, 2, 3, ... - 1] + const oldVersions = range(1, requiredVersion).map(n => `${n}`); + + new CfnRule(stack, 'CheckBootstrapVersion', { + assertions: [ + { + assert: Fn.conditionNot(Fn.conditionContains(oldVersions, param.valueAsString)), + assertDescription: `CDK bootstrap stack version ${requiredVersion} required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.`, + }, + ], + }); +} + +function range(startIncl: number, endExcl: number) { + const ret = new Array(); + for (let i = startIncl; i < endExcl; i++) { + ret.push(i); + } + return ret; +} + +/** + * Return the stack locations if they're concrete, or the original CFN intrisics otherwise + * + * We need to return these instead of the tokenized versions of the strings, + * since we must accept those same ${AWS::AccountId}/${AWS::Region} placeholders + * in bucket names and role names (in order to allow environment-agnostic stacks). + * + * We'll wrap a single {Fn::Sub} around the final string in order to replace everything, + * but we can't have the token system render part of the string to {Fn::Join} because + * the CFN specification doesn't allow the {Fn::Sub} template string to be an arbitrary + * expression--it must be a string literal. + */ +function stackLocationOrInstrinsics(stack: Stack) { + return { + account: resolvedOr(stack.account, '${AWS::AccountId}'), + region: resolvedOr(stack.region, '${AWS::Region}'), + urlSuffix: resolvedOr(stack.urlSuffix, '${AWS::URLSuffix}'), + }; +} + +/** + * If the string still contains placeholders, wrap it in a Fn::Sub so they will be substituted at CFN deployment time + * + * (This happens to work because the placeholders we picked map directly onto CFN + * placeholders. If they didn't we'd have to do a transformation here). + */ +function cfnify(s: string): string { + return s.indexOf('${') > -1 ? Fn.sub(s) : s; +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index 8ca911b83b8aa..b56d13d4bf642 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -730,6 +730,19 @@ export class Stack extends Construct implements ITaggable { this.templateOptions.transforms.push(transform); } + /** + * Adds an arbitary key-value pair, with information you want to record about the stack. + * These get translated to the Metadata section of the generated template. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html + */ + public addMetadata(key: string, value: any) { + if (!this.templateOptions.metadata) { + this.templateOptions.metadata = {}; + } + this.templateOptions.metadata[key] = value; + } + /** * Called implicitly by the `addDependency` helper function in order to * realize a dependency between two top-level stacks at the assembly level. diff --git a/packages/@aws-cdk/core/lib/stage.ts b/packages/@aws-cdk/core/lib/stage.ts index 57aa97482b0a6..64df6a7f96bda 100644 --- a/packages/@aws-cdk/core/lib/stage.ts +++ b/packages/@aws-cdk/core/lib/stage.ts @@ -53,6 +53,13 @@ export interface StageProps { * temporary directory will be created. */ readonly outdir?: string; + + /** + * Name of this stage. + * + * @default - Derived from the id. + */ + readonly stageName?: string; } /** @@ -136,7 +143,7 @@ export class Stage extends Construct { this.account = props.env?.account ?? this.parentStage?.account; this._assemblyBuilder = this.createBuilder(props.outdir); - this.stageName = [this.parentStage?.stageName, id].filter(x => x).join('-'); + this.stageName = [this.parentStage?.stageName, props.stageName ?? id].filter(x => x).join('-'); } /** diff --git a/packages/@aws-cdk/core/test/app.test.ts b/packages/@aws-cdk/core/test/app.test.ts index d9ab8c0396f3d..ea9c58551d530 100644 --- a/packages/@aws-cdk/core/test/app.test.ts +++ b/packages/@aws-cdk/core/test/app.test.ts @@ -1,6 +1,9 @@ +import * as os from 'os'; +import * as path from 'path'; import { ContextProvider } from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; +import * as fs from 'fs-extra'; import { CfnResource, DefaultStackSynthesizer, Stack, StackProps } from '../lib'; import { Annotations } from '../lib/annotations'; import { App, AppProps } from '../lib/app'; @@ -101,29 +104,55 @@ describe('app', () => { }); }); - test('context can be passed through CDK_CONTEXT', () => { - process.env[cxapi.CONTEXT_ENV] = JSON.stringify({ + test('context can be passed through CONTEXT_OVERFLOW_LOCATION_ENV', async () => { + const contextDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-context')); + const overflow = path.join(contextDir, 'overflow.json'); + fs.writeJSONSync(overflow, { key1: 'val1', key2: 'val2', }); + process.env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV] = overflow; + const prog = new App(); expect(prog.node.tryGetContext('key1')).toEqual('val1'); expect(prog.node.tryGetContext('key2')).toEqual('val2'); }); - test('context passed through CDK_CONTEXT has precedence', () => { + test('context can be passed through CDK_CONTEXT', async () => { process.env[cxapi.CONTEXT_ENV] = JSON.stringify({ key1: 'val1', key2: 'val2', }); + + const prog = new App(); + expect(prog.node.tryGetContext('key1')).toEqual('val1'); + expect(prog.node.tryGetContext('key2')).toEqual('val2'); + }); + + test('context passed through CONTEXT_OVERFLOW_LOCATION_ENV is merged with the context passed through CONTEXT_ENV', async () => { + const contextDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-context')); + const contextLocation = path.join(contextDir, 'context-temp.json'); + fs.writeJSONSync(contextLocation, { + key1: 'val1', + key2: 'val2', + }); + process.env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV] = contextLocation; + + process.env[cxapi.CONTEXT_ENV] = JSON.stringify({ + key3: 'val3', + key4: 'val4', + }); + const prog = new App({ context: { - key1: 'val3', - key2: 'val4', + key1: 'val5', + key2: 'val6', }, }); expect(prog.node.tryGetContext('key1')).toEqual('val1'); expect(prog.node.tryGetContext('key2')).toEqual('val2'); + expect(prog.node.tryGetContext('key3')).toEqual('val3'); + expect(prog.node.tryGetContext('key4')).toEqual('val4'); }); test('context passed through finalContext prop has precedence', () => { diff --git a/packages/@aws-cdk/core/test/resource.test.ts b/packages/@aws-cdk/core/test/resource.test.ts index 32a273f76a663..fe247827bb3d6 100644 --- a/packages/@aws-cdk/core/test/resource.test.ts +++ b/packages/@aws-cdk/core/test/resource.test.ts @@ -726,6 +726,59 @@ describe('resource', () => { }); }); + test('Can override a an object with an intrinsic', () => { + // GIVEN + const stack = new Stack(); + + const condition = new CfnCondition(stack, 'MyCondition', { + expression: Fn.conditionEquals('us-east-1', 'us-east-1'), + }); + const resource = new CfnResource(stack, 'MyResource', { + type: 'MyResourceType', + properties: { + prop1: { + subprop: { + name: Fn.getAtt('resource', 'abc'), + }, + }, + }, + }); + const isEnabled = Fn.conditionIf(condition.logicalId, { + Ref: 'AWS::NoValue', + }, { + name: Fn.getAtt('resource', 'abc'), + }); + + // WHEN + resource.addPropertyOverride('prop1.subprop', isEnabled); + const cfn = toCloudFormation(stack); + + // THEN + expect(cfn.Resources.MyResource).toEqual({ + Type: 'MyResourceType', + Properties: { + prop1: { + subprop: { + 'Fn::If': [ + 'MyCondition', + { + Ref: 'AWS::NoValue', + }, + { + name: { + 'Fn::GetAtt': [ + 'resource', + 'abc', + ], + }, + }, + ], + }, + }, + }, + }); + }); + test('overrides allow overriding a nested intrinsic', () => { // GIVEN const stack = new Stack(); diff --git a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts index f7480265fdbc7..0208d01e42bb9 100644 --- a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts +++ b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts @@ -139,17 +139,14 @@ describe('new style synthesis', () => { * Synthesize the associated bootstrap stack to the session. */ public synthesize(session: ISynthesisSession): void { - if (!this.stack) { - throw new Error('You must call bind() with a stack instance first'); - } - this.synthesizeStackTemplate(this.stack, session); + this.synthesizeTemplate(session); session.assembly.addArtifact('FAKE_ARTIFACT_ID', { type: ArtifactType.ASSET_MANIFEST, properties: { file: 'FAKE_ARTIFACT_ID.json', }, }); - this.emitStackArtifact(this.stack, session, { + this.emitArtifact(session, { additionalDependencies: ['FAKE_ARTIFACT_ID'], }); } diff --git a/packages/@aws-cdk/core/test/stack.test.ts b/packages/@aws-cdk/core/test/stack.test.ts index b2fc01b337a87..b9692f8d77e3d 100644 --- a/packages/@aws-cdk/core/test/stack.test.ts +++ b/packages/@aws-cdk/core/test/stack.test.ts @@ -1263,6 +1263,21 @@ describe('regionalFact', () => { }, }); }); + + test('stack.addMetadata() adds metadata', () => { + const stack = new Stack(); + + stack.addMetadata('Instances', { Description: 'Information about the instances' }); + stack.addMetadata('Databases', { Description: 'Information about the databases' } ); + + expect(toCloudFormation(stack)).toEqual({ + Metadata: { + Instances: { Description: 'Information about the instances' }, + Databases: { Description: 'Information about the databases' }, + }, + }); + }); + }); class StackWithPostProcessor extends Stack { diff --git a/packages/@aws-cdk/core/test/stage.test.ts b/packages/@aws-cdk/core/test/stage.test.ts index 532515cea54ea..41e604a212182 100644 --- a/packages/@aws-cdk/core/test/stage.test.ts +++ b/packages/@aws-cdk/core/test/stage.test.ts @@ -92,6 +92,17 @@ describe('stage', () => { expect(stack.stackName).toEqual('MyStage-MyStack'); }); + test('can override the stage name', () => { + // WHEN + const app = new App(); + const stage = new Stage(app, 'NotMyStageName', { stageName: 'MyStage' }); + const stack = new BogusStack(stage, 'MyStack'); + + // THEN + expect(stage.stageName).toEqual('MyStage'); + expect(stack.stackName).toEqual('MyStage-MyStack'); + }); + test('Can not have dependencies to stacks outside the nested asm', () => { // GIVEN const app = new App(); diff --git a/packages/@aws-cdk/core/test/synthesis.test.ts b/packages/@aws-cdk/core/test/synthesis.test.ts index 70bfc05042a82..359601dac62f7 100644 --- a/packages/@aws-cdk/core/test/synthesis.test.ts +++ b/packages/@aws-cdk/core/test/synthesis.test.ts @@ -229,8 +229,10 @@ describe('synthesis', () => { const calls = new Array(); class SynthesizeMe extends cdk.Stack { + public readonly templateFile = 'hey.json'; + constructor() { - super(undefined as any, 'id', { + super(undefined as any, 'hey', { synthesizer: new cdk.LegacyStackSynthesizer(), }); this.node.addValidation({ diff --git a/packages/@aws-cdk/cx-api/lib/artifacts/asset-manifest-artifact.ts b/packages/@aws-cdk/cx-api/lib/artifacts/asset-manifest-artifact.ts index b3195847b2f92..ee79eb2c638d3 100644 --- a/packages/@aws-cdk/cx-api/lib/artifacts/asset-manifest-artifact.ts +++ b/packages/@aws-cdk/cx-api/lib/artifacts/asset-manifest-artifact.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs'; import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { CloudArtifact } from '../cloud-artifact'; @@ -47,6 +48,8 @@ export class AssetManifestArtifact extends CloudArtifact { */ public readonly bootstrapStackVersionSsmParameter?: string; + private _contents?: cxschema.AssetManifest; + constructor(assembly: CloudAssembly, name: string, artifact: cxschema.ArtifactManifest) { super(assembly, name, artifact); @@ -58,6 +61,19 @@ export class AssetManifestArtifact extends CloudArtifact { this.requiresBootstrapStackVersion = properties.requiresBootstrapStackVersion; this.bootstrapStackVersionSsmParameter = properties.bootstrapStackVersionSsmParameter; } + + /** + * The Asset Manifest contents + */ + public get contents(): cxschema.AssetManifest { + if (this._contents !== undefined) { + return this._contents; + } + + const contents = this._contents = JSON.parse(fs.readFileSync(this.file, 'utf-8')); + return contents; + } + } /** diff --git a/packages/@aws-cdk/cx-api/lib/cxapi.ts b/packages/@aws-cdk/cx-api/lib/cxapi.ts index 9b179e9a71b5f..8137dcf3907f6 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -4,6 +4,11 @@ export const OUTDIR_ENV = 'CDK_OUTDIR'; export const CONTEXT_ENV = 'CDK_CONTEXT_JSON'; +/** + * The name of the temporary file where the context is stored. + */ +export const CONTEXT_OVERFLOW_LOCATION_ENV = 'CONTEXT_OVERFLOW_LOCATION_ENV'; + /** * Environment variable set by the CDK CLI with the default AWS account ID. */ diff --git a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts index c8fc073d89918..9ddaf2e7e4de4 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts @@ -417,5 +417,8 @@ export const DEFAULT_SYNTH_OPTIONS = { env: { CDK_INTEG_ACCOUNT: '12345678', CDK_INTEG_REGION: 'test-region', + CDK_INTEG_HOSTED_ZONE_ID: 'Z23ABC4XYZL05B', + CDK_INTEG_HOSTED_ZONE_NAME: 'example.com', + CDK_INTEG_DOMAIN_NAME: '*.example.com', }, }; diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts b/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts index 08fd3885e61d8..a0b67ad587f39 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts @@ -83,7 +83,7 @@ export interface IApiCall extends IConstruct { * * message.assertAtPath('Messages.0.Body', ExpectedResult.stringLikeRegexp('hello')); */ - assertAtPath(path: string, expected: ExpectedResult): void; + assertAtPath(path: string, expected: ExpectedResult): IApiCall; /** * Allows you to chain IApiCalls. This adds an explicit dependency @@ -107,7 +107,6 @@ export abstract class ApiCallBase extends Construct implements IApiCall { protected abstract readonly apiCallResource: CustomResource; protected expectedResult?: string; protected flattenResponse: string = 'false'; - protected stateMachineArn?: string; public abstract readonly provider: AssertionsProvider; @@ -130,7 +129,7 @@ export abstract class ApiCallBase extends Construct implements IApiCall { this.expectedResult = expected.result; } - public abstract assertAtPath(path: string, expected: ExpectedResult): void; + public abstract assertAtPath(path: string, expected: ExpectedResult): IApiCall; public next(next: IApiCall): IApiCall { next.node.addDependency(this); diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/assertion.ts b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/assertion.ts index b8fba80266edb..9bea7f1da745d 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/assertion.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/assertion.ts @@ -16,7 +16,8 @@ export class AssertionHandler extends CustomResourceHandler { + public async handle(): Promise { try { - console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: '...' })}`); const response = await this.processEvent(this.event.ResourceProperties as unknown as Request); - console.log(`Event output : ${JSON.stringify(response)}`); - await this.respond({ - status: 'SUCCESS', - reason: 'OK', - data: response, - }); + return response; } catch (e) { console.log(e); - await this.respond({ - status: 'FAILED', - reason: e.message ?? 'Internal Error', - }); + throw e; } finally { clearTimeout(this.timeout); } @@ -50,7 +41,7 @@ export abstract class CustomResourceHandler; - private respond(response: HandlerResponse) { + public respond(response: HandlerResponse) { if (this.timedOut) { return; } diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/index.ts b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/index.ts index 72ca3544cb66d..8873d83b8981c 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/index.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/index.ts @@ -1,19 +1,76 @@ +/* eslint-disable no-console */ import { AssertionHandler } from './assertion'; import { AwsApiCallHandler } from './sdk'; import * as types from './types'; export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: '...' })}`); const provider = createResourceHandler(event, context); - await provider.handle(); + try { + // if we are deleting the custom resource, just respond + // with 'SUCCESS' since there is nothing to do. + if (event.RequestType === 'Delete') { + await provider.respond({ + status: 'SUCCESS', + reason: 'OK', + }); + return; + } + const result = await provider.handle(); + const actualPath = event.ResourceProperties.actualPath; + // if we are providing a path to make the assertion at, that means that we have + // flattened the response, otherwise the path to assert against in the entire response + const actual = actualPath ? (result as { [key: string]: string })[`apiCallResponse.${actualPath}`] : (result as types.AwsApiCallResult).apiCallResponse; + if ('expected' in event.ResourceProperties) { + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected, + }, + }, context); + try { + const assertionResult = await assertion.handle(); + await provider.respond({ + status: 'SUCCESS', + reason: 'OK', + // return both the result of the API call _and_ the assertion results + data: { + ...assertionResult, + ...result, + }, + }); + return; + } catch (e) { + await provider.respond({ + status: 'FAILED', + reason: e.message ?? 'Internal Error', + }); + return; + } + } + await provider.respond({ + status: 'SUCCESS', + reason: 'OK', + data: result, + }); + } catch (e) { + await provider.respond({ + status: 'FAILED', + reason: e.message ?? 'Internal Error', + }); + return; + } + return; } function createResourceHandler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) { if (event.ResourceType.startsWith(types.SDK_RESOURCE_TYPE_PREFIX)) { return new AwsApiCallHandler(event, context); - } - switch (event.ResourceType) { - case types.ASSERT_RESOURCE_TYPE: return new AssertionHandler(event, context); - default: - throw new Error(`Unsupported resource type "${event.ResourceType}`); + } else if (event.ResourceType.startsWith(types.ASSERT_RESOURCE_TYPE)) { + return new AssertionHandler(event, context); + } else { + throw new Error(`Unsupported resource type "${event.ResourceType}`); } } diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/sdk.ts b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/sdk.ts index 5d53df2f5b38e..51d677b81084c 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/sdk.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/sdk.ts @@ -15,7 +15,12 @@ export function flatten(object: object): { [key: string]: any } { ...function _flatten(child: any, path: string[] = []): any { return [].concat(...Object.keys(child) .map(key => { - const childKey = Buffer.isBuffer(child[key]) ? child[key].toString('utf8') : child[key]; + let childKey = Buffer.isBuffer(child[key]) ? child[key].toString('utf8') : child[key]; + // if the value is a json string then treat it as an object + // and keep recursing. This allows for easier assertions against complex json strings + if (typeof childKey === 'string') { + childKey = isJsonString(childKey); + } return typeof childKey === 'object' && childKey !== null ? _flatten(childKey, path.concat([key])) : ({ [path.concat([key]).join('.')]: childKey }); @@ -31,7 +36,12 @@ export class AwsApiCallHandler extends CustomResourceHandler this.expectedResult }), + actualPath: Lazy.string({ produce: () => this._assertAtPath }), parameters: this.provider.encode(props.parameters), flattenResponse: Lazy.string({ produce: () => this.flattenResponse }), salt: Date.now().toString(), @@ -63,30 +65,29 @@ export class AwsApiCall extends ApiCallBase { // Needed so that all the policies set up by the provider should be available before the custom resource is provisioned. this.apiCallResource.node.addDependency(this.provider); - } - - public getAtt(attributeName: string): Reference { - this.flattenResponse = 'true'; - return this.apiCallResource.getAtt(`apiCallResponse.${attributeName}`); - } - - public getAttString(attributeName: string): string { - this.flattenResponse = 'true'; - return this.apiCallResource.getAttString(`apiCallResponse.${attributeName}`); - } - public expect(expected: ExpectedResult): void { - new EqualsAssertion(this, `AssertEquals${this.name}`, { - expected, - actual: ActualResult.fromCustomResource(this.apiCallResource, 'apiCallResponse'), + // if expectedResult has been configured then that means + // we are making assertions and we should output the results + Aspects.of(this).add({ + visit(node: IConstruct) { + if (node instanceof AwsApiCall) { + if (node.expectedResult) { + const result = node.apiCallResource.getAttString('assertion'); + + new CfnOutput(node, 'AssertionResults', { + value: result, + }).overrideLogicalId(`AssertionResults${id}`); + } + } + }, }); } - public assertAtPath(path: string, expected: ExpectedResult): void { - new EqualsAssertion(this, `AssertEquals${this.name}`, { - expected, - actual: ActualResult.fromAwsApiCall(this, path), - }); + public assertAtPath(path: string, expected: ExpectedResult): IApiCall { + this._assertAtPath = path; + this.expectedResult = expected.result; + this.flattenResponse = 'true'; + return this; } } diff --git a/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/assertion.test.ts b/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/assertion.test.ts index 0abda7d477de7..5f928892a312b 100644 --- a/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/assertion.test.ts +++ b/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/assertion.test.ts @@ -50,7 +50,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(response.data).toEqual('{"status":"success"}'); + expect(response.assertion).toEqual('{"status":"success"}'); }); test('fail', async () => { @@ -65,7 +65,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(JSON.parse(response.data)).toEqual({ + expect(JSON.parse(response.assertion)).toEqual({ status: 'fail', message: expect.stringMatching(/String 'this is the actual results' did not match pattern 'abcd' (using stringLikeRegexp matcher)*/), }); @@ -95,7 +95,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(response.data).toEqual('{"status":"success"}'); + expect(response.assertion).toEqual('{"status":"success"}'); }); test('fail', async () => { @@ -121,7 +121,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(JSON.parse(response.data)).toEqual({ + expect(JSON.parse(response.assertion)).toEqual({ status: 'fail', message: expect.stringMatching(/Missing element at pattern index 0 (using arrayWith matcher)*/), }); @@ -159,7 +159,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(response.data).toEqual('{"status":"success"}'); + expect(response.assertion).toEqual('{"status":"success"}'); }); test('fail', async () => { @@ -180,7 +180,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(JSON.parse(response.data)).toEqual({ + expect(JSON.parse(response.assertion)).toEqual({ status: 'fail', message: 'Expected bar but received foo at /stringParam (using objectLike matcher)\n' + '{\n \"stringParam\": \"foo\",\n \"numberParam\": 3,\n \"booleanParam\": true\n}', @@ -209,7 +209,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(response.data).toEqual('{"status":"success"}'); + expect(response.assertion).toEqual('{"status":"success"}'); }); test('string equals pass', async () => { @@ -224,7 +224,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(response.data).toEqual('{"status":"success"}'); + expect(response.assertion).toEqual('{"status":"success"}'); }); test('fail', async () => { @@ -243,7 +243,7 @@ describe('AssertionHandler', () => { const response: AssertionResult = await handler.processEvent(request); // THEN - expect(JSON.parse(response.data)).toEqual({ + expect(JSON.parse(response.assertion)).toEqual({ status: 'fail', message: 'Expected bar but received foo at /stringParam (using exact matcher)\n{\n \"stringParam\": \"foo\"\n}', }); diff --git a/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/base.test.ts b/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/base.test.ts index d30f20a5678f3..8722eea5e3837 100644 --- a/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/base.test.ts +++ b/packages/@aws-cdk/integ-tests/test/assertions/providers/lambda-handler/base.test.ts @@ -1,4 +1,8 @@ +import * as SDK from 'aws-sdk'; +import * as AWS from 'aws-sdk-mock'; import * as nock from 'nock'; +import * as sinon from 'sinon'; +import { handler as lambda_handler } from '../../../../lib/assertions/providers/lambda-handler'; import { CustomResourceHandler } from '../../../../lib/assertions/providers/lambda-handler/base'; interface MyHandlerRequest { @@ -6,71 +10,102 @@ interface MyHandlerRequest { } interface MyHandlerResponse { - readonly output: string; + readonly apiCallResponse: any; } interface CloudFormationResponse extends Omit { - readonly Data: MyHandlerResponse; + readonly Data: any; } + +let mockMyApi: sinon.SinonSpy; +let mockStartExecution: sinon.SinonSpy; describe('CustomResourceHandler', () => { beforeEach(() => { + AWS.setSDK(require.resolve('aws-sdk')); + mockMyApi = sinon.fake.resolves({ + Buckets: [{ + Name: 'somebucket', + }], + } as SDK.S3.ListBucketsOutput); + mockStartExecution = sinon.fake.resolves({}); + AWS.mock('S3', 'listBuckets', mockMyApi); + AWS.mock('StepFunctions', 'startExecution', mockStartExecution); jest.spyOn(console, 'log').mockImplementation(() => { return true; }); }); afterEach(() => { jest.restoreAllMocks(); + jest.resetAllMocks(); nock.cleanAll(); + AWS.restore(); }); - test('default', async () => { - // GIVEN - class MyHandler extends CustomResourceHandler { - protected async processEvent(request: MyHandlerRequest): Promise { - return { output: `MyResponseTo${request.input}` }; - } - } - - const nocked = nockUp((body) => { - return body.Status === 'SUCCESS' - && body.Reason === 'OK' - && body.Data.output === 'MyResponseToYourRequest' - && body.StackId === 'MyStackId' - && body.RequestId === 'MyRequestId' - && body.NoEcho === false; - }); + describe('lambda handler', () => { + test('create sync request', async () => { + const nocked = nockUp((body) => { + return body.Status === 'SUCCESS' + && body.Reason === 'OK' + && body.Data.apiCallResponse.Buckets[0].Name === 'somebucket' + && body.StackId === 'MyStackId' + && body.RequestId === 'MyRequestId' + && body.NoEcho === false; + }); + const event = createEvent({ + service: 'S3', + api: 'listBuckets', + }, 'Custom::DeployAssert@SdkCall'); + await lambda_handler(event, standardContext); + sinon.assert.calledOnce(mockMyApi); + sinon.assert.notCalled(mockStartExecution); - // WHEN - const handler = new MyHandler(createEvent({ input: 'YourRequest' }), standardContext); - - await handler.handle(); + // THEN + expect(nocked.isDone()).toEqual(true); + }); - // THEN - expect(nocked.isDone()).toEqual(true); - }); + test('create request with assertions', async () => { + const nocked = nockUp((body) => { + return body.Status === 'SUCCESS' + && body.Reason === 'OK' + && body.Data.assertion === '{"status":"success"}' + && body.Data.apiCallResponse.Buckets[0].Name === 'somebucket' + && body.StackId === 'MyStackId' + && body.RequestId === 'MyRequestId' + && body.NoEcho === false; + }); + const event = createEvent({ + service: 'S3', + api: 'listBuckets', + expected: JSON.stringify({ $ObjectLike: { Buckets: [{ Name: 'somebucket' }] } }), + }, 'Custom::DeployAssert@SdkCall'); + await lambda_handler(event, standardContext); - test('processEvent fails', async () => { - // GIVEN - class MyHandler extends CustomResourceHandler { - protected async processEvent(_: MyHandlerRequest): Promise { - throw new Error('FooFAIL'); - } - } + sinon.assert.calledOnce(mockMyApi); + sinon.assert.notCalled(mockStartExecution); - const nocked = nockUp((body) => { - return body.Status === 'FAILED' - && body.Reason === 'FooFAIL'; + // THEN + expect(nocked.isDone()).toEqual(true); }); + test('create request with assertions fails', async () => { + const nocked = nockUp((body) => { + return body.Status === 'FAILED' + && (body.Reason?.match(/Expected someotherbucket/) ?? []).length === 1; + }); + const event = createEvent({ + service: 'S3', + api: 'listBuckets', + expected: JSON.stringify({ $ObjectLike: { Buckets: [{ Name: 'someotherbucket' }] } }), + }, 'Custom::DeployAssert@SdkCall'); + await lambda_handler(event, standardContext); - // WHEN - const handler = new MyHandler(createEvent({ input: 'YourRequest' }), standardContext); - - await handler.handle(); + sinon.assert.calledOnce(mockMyApi); + sinon.assert.notCalled(mockStartExecution); - // THEN - expect(nocked.isDone()).toEqual(true); + // THEN + expect(nocked.isDone()).toEqual(true); + }); }); test('timeout kicks in', async () => { @@ -95,60 +130,12 @@ describe('CustomResourceHandler', () => { getRemainingTimeInMillis: () => 1300, }); - // WHEN await handler.handle(); - // THEN expect(nocked.isDone()).toEqual(true); }); - - describe('physicalResourceId', () => { - test('create event', async () => { - // GIVEN - class MyHandler extends CustomResourceHandler { - protected async processEvent(request: MyHandlerRequest): Promise { - return { output: `MyResponseTo${request.input}` }; - } - } - - const nocked = nockUp((body) => { - return body.PhysicalResourceId === 'MyLogicalResourceId'; - }); - - - // WHEN - const handler = new MyHandler(createEvent({ input: 'YourRequest' }), standardContext); - - await handler.handle(); - - // THEN - expect(nocked.isDone()).toEqual(true); - }); - - test('update event', async () => { - // GIVEN - class MyHandler extends CustomResourceHandler { - protected async processEvent(request: MyHandlerRequest): Promise { - return { output: `MyResponseTo${request.input}` }; - } - } - - const nocked = nockUp((body) => { - return body.PhysicalResourceId === 'MyPhysicalResourceId'; - }); - - - // WHEN - const handler = new MyHandler(updateEvent({ input: 'YourRequest' }), standardContext); - - await handler.handle(); - - // THEN - expect(nocked.isDone()).toEqual(true); - }); - }); }); function nockUp(predicate: (body: CloudFormationResponse) => boolean) { @@ -161,33 +148,12 @@ const standardContext: any = { // keeping this as any so as to not have to fill getRemainingTimeInMillis: () => 5000, }; -function createEvent(data?: MyHandlerRequest): AWSLambda.CloudFormationCustomResourceCreateEvent { +function createEvent(data?: any, resourceType: string = 'MyResourceType'): AWSLambda.CloudFormationCustomResourceCreateEvent { return { LogicalResourceId: 'MyLogicalResourceId', RequestId: 'MyRequestId', RequestType: 'Create', - ResourceType: 'MyResourceType', - ResourceProperties: { - ...data, - ServiceToken: 'MyServiceToken', - }, - ResponseURL: 'https://someurl.com', - ServiceToken: 'MyServiceToken', - StackId: 'MyStackId', - }; -} - -function updateEvent(data?: MyHandlerRequest): AWSLambda.CloudFormationCustomResourceUpdateEvent { - return { - LogicalResourceId: 'MyLogicalResourceId', - OldResourceProperties: { - ...data, - ServiceToken: 'MyServiceToken', - }, - PhysicalResourceId: 'MyPhysicalResourceId', - RequestId: 'MyRequestId', - RequestType: 'Update', - ResourceType: 'MyResourceType', + ResourceType: resourceType, ResourceProperties: { ...data, ServiceToken: 'MyServiceToken', diff --git a/packages/@aws-cdk/integ-tests/test/assertions/providers/provider.test.ts b/packages/@aws-cdk/integ-tests/test/assertions/providers/provider.test.ts index f27d61189e72f..bac228258751a 100644 --- a/packages/@aws-cdk/integ-tests/test/assertions/providers/provider.test.ts +++ b/packages/@aws-cdk/integ-tests/test/assertions/providers/provider.test.ts @@ -2,11 +2,13 @@ import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { AssertionsProvider } from '../../../lib/assertions'; +let stack: Stack; +beforeEach(() => { + stack = new Stack(); +}); + describe('AssertionProvider', () => { test('default', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionProvider'); @@ -20,9 +22,6 @@ describe('AssertionProvider', () => { describe('addPolicyStatementForSdkCall', () => { test('default', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); provider.addPolicyStatementFromSdkCall('MyService', 'myApi'); @@ -47,9 +46,6 @@ describe('AssertionProvider', () => { }); test('multiple calls', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); provider.addPolicyStatementFromSdkCall('MyService', 'myApi'); @@ -80,8 +76,6 @@ describe('AssertionProvider', () => { }); test('multiple providers, 1 resource', () => { - // GIVEN - const stack = new Stack(); // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); @@ -114,9 +108,6 @@ describe('AssertionProvider', () => { }); test('prefix different from service name', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); provider.addPolicyStatementFromSdkCall('applicationautoscaling', 'myApi'); @@ -143,9 +134,6 @@ describe('AssertionProvider', () => { describe('encode', () => { test('booleans', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); const encoded = provider.encode({ @@ -161,9 +149,6 @@ describe('AssertionProvider', () => { }); test('all other values return as usual', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); const encoded = provider.encode({ @@ -181,9 +166,6 @@ describe('AssertionProvider', () => { }); test('nullish', () => { - // GIVEN - const stack = new Stack(); - // WHEN const provider = new AssertionsProvider(stack, 'AssertionsProvider'); diff --git a/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts b/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts index 3a03487425c5c..672888f937892 100644 --- a/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts +++ b/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts @@ -22,35 +22,6 @@ describe('AwsApiCall', () => { }); }); - test('then', () => { - // GIVEN - const app = new App(); - const deplossert = new DeployAssert(app); - - // WHEN - const first = deplossert.awsApiCall('MyService', 'MyApi'); - first.next(deplossert.awsApiCall('MyOtherService', 'MyOtherApi')); - - // THEN - const template = Template.fromStack(deplossert.scope); - template.resourceCountIs('AWS::Lambda::Function', 1); - template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', { - service: 'MyService', - api: 'MyApi', - parameters: Match.absent(), - }); - template.hasResource('Custom::DeployAssert@SdkCallMyOtherServiceMyOtherApi', { - Properties: { - service: 'MyOtherService', - api: 'MyOtherApi', - parameters: Match.absent(), - }, - DependsOn: [ - 'AwsApiCallMyServiceMyApi', - ], - }); - }); - test('parameters', () => { // GIVEN const app = new App(); @@ -198,14 +169,8 @@ describe('AwsApiCall', () => { // THEN const template = Template.fromStack(deplossert.scope); - template.hasResourceProperties('Custom::DeployAssert@AssertEquals', { + template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', { expected: JSON.stringify({ $Exact: { foo: 'bar' } }), - actual: { - 'Fn::GetAtt': [ - 'AwsApiCallMyServiceMyApi', - 'apiCallResponse', - ], - }, }); }); @@ -220,14 +185,8 @@ describe('AwsApiCall', () => { // THEN const template = Template.fromStack(deplossert.scope); - template.hasResourceProperties('Custom::DeployAssert@AssertEquals', { + template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', { expected: JSON.stringify({ $ObjectLike: { foo: 'bar' } }), - actual: { - 'Fn::GetAtt': [ - 'AwsApiCallMyServiceMyApi', - 'apiCallResponse', - ], - }, }); }); @@ -242,14 +201,8 @@ describe('AwsApiCall', () => { // THEN const template = Template.fromStack(deplossert.scope); - template.hasResourceProperties('Custom::DeployAssert@AssertEquals', { + template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', { expected: JSON.stringify({ $Exact: 'bar' }), - actual: { - 'Fn::GetAtt': [ - 'AwsApiCallMyServiceMyApi', - 'apiCallResponse', - ], - }, }); }); }); diff --git a/packages/@aws-cdk/region-info/lib/aws-entities.ts b/packages/@aws-cdk/region-info/lib/aws-entities.ts index 0c28399449434..d91e34848c73f 100644 --- a/packages/@aws-cdk/region-info/lib/aws-entities.ts +++ b/packages/@aws-cdk/region-info/lib/aws-entities.ts @@ -1,8 +1,3 @@ -/** - * After this point, SSM only creates regional principals - */ -export const RULE_SSM_PRINCIPALS_ARE_REGIONAL = Symbol('SSM_PRINCIPALS_ARE_REGIONAL'); - /** * After this point, S3 website domains look like `s3-website.REGION.s3.amazonaws.com` * @@ -49,7 +44,6 @@ export const AWS_REGIONS_AND_RULES: readonly (string | symbol)[] = [ 'ap-northeast-3', // Asia Pacific (Osaka) 'us-gov-east-1', // AWS GovCloud (US-East) 'eu-north-1', // Europe (Stockholm) - RULE_SSM_PRINCIPALS_ARE_REGIONAL, 'ap-east-1', // Asia Pacific (Hong Kong) 'me-south-1', // Middle East (Bahrain) 'eu-south-1', // Europe (Milan) diff --git a/packages/@aws-cdk/region-info/lib/default.ts b/packages/@aws-cdk/region-info/lib/default.ts index 39a8db5ddedc9..c240c55ec1068 100644 --- a/packages/@aws-cdk/region-info/lib/default.ts +++ b/packages/@aws-cdk/region-info/lib/default.ts @@ -1,5 +1,3 @@ -import { before, RULE_SSM_PRINCIPALS_ARE_REGIONAL } from './aws-entities'; - /** * Provides default values for certain regional information points. */ @@ -81,12 +79,6 @@ export class Default { } switch (service) { - // SSM turned from global to regional at some point - case 'ssm': - return before(region, RULE_SSM_PRINCIPALS_ARE_REGIONAL) - ? universal - : regional; - // CodeDeploy is regional+partitional in CN, only regional everywhere else case 'codedeploy': return region.startsWith('cn-') diff --git a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap index dae9b4dda9d16..2ce71cae5df83 100644 --- a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap +++ b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap @@ -30,7 +30,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.af-south-1.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.af-south-1.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -63,7 +63,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.ap-east-1.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.ap-east-1.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -294,7 +294,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.ap-southeast-3.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.ap-southeast-3.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -492,7 +492,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.eu-south-1.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.eu-south-1.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -525,7 +525,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.eu-south-2.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.eu-south-2.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -657,7 +657,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.me-south-1.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.me-south-1.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "com.amazonaws.vpce", @@ -888,7 +888,7 @@ Object { "s3": "s3.amazonaws.com", "sns": "sns.amazonaws.com", "sqs": "sqs.amazonaws.com", - "ssm": "ssm.us-iso-west-1.amazonaws.com", + "ssm": "ssm.amazonaws.com", "states": "states.amazonaws.com", }, "vpcEndPointServiceNamePrefix": "gov.ic.c2s.vpce", diff --git a/packages/@aws-cdk/region-info/test/default.test.ts b/packages/@aws-cdk/region-info/test/default.test.ts index b9c7a4375f8fd..10651a4788070 100644 --- a/packages/@aws-cdk/region-info/test/default.test.ts +++ b/packages/@aws-cdk/region-info/test/default.test.ts @@ -5,7 +5,7 @@ const urlSuffix = '.nowhere.null'; describe('servicePrincipal', () => { for (const suffix of ['', '.amazonaws.com', '.amazonaws.com.cn']) { - for (const service of ['codedeploy', 'states', 'ssm']) { + for (const service of ['codedeploy', 'states']) { test(`${service}${suffix}`, () => { expect(Default.servicePrincipal(`${service}${suffix}`, region, urlSuffix)).toBe(`${service}.${region}.amazonaws.com`); }); @@ -58,11 +58,15 @@ describe('servicePrincipal', () => { describe('spot-check some service principals', () => { test('ssm', () => { + // SSM has advertised in its documentation that it is regional after a certain point, but that + // documentation only applies to SSM Inventory, not SSM Automation. Plus, there is no need for + // a different service principal, as all accounts are (at least currently) included in the global + // one. expectServicePrincipals('ssm.amazonaws.com', { 'us-east-1': 'ssm.amazonaws.com', 'eu-north-1': 'ssm.amazonaws.com', - 'ap-east-1': 'ssm.ap-east-1.amazonaws.com', - 'eu-south-1': 'ssm.eu-south-1.amazonaws.com', + 'ap-east-1': 'ssm.amazonaws.com', + 'eu-south-1': 'ssm.amazonaws.com', }); }); diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 5ded6c593fb1f..a6e0e6931dc18 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -175,6 +175,7 @@ "@aws-cdk/aws-cognito-identitypool": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", + "@aws-cdk/aws-connectcampaigns": "0.0.0", "@aws-cdk/aws-controltower": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", "@aws-cdk/aws-customerprofiles": "0.0.0", @@ -237,6 +238,7 @@ "@aws-cdk/aws-iotevents": "0.0.0", "@aws-cdk/aws-iotevents-actions": "0.0.0", "@aws-cdk/aws-iotfleethub": "0.0.0", + "@aws-cdk/aws-iotfleetwise": "0.0.0", "@aws-cdk/aws-iotsitewise": "0.0.0", "@aws-cdk/aws-iotthingsgraph": "0.0.0", "@aws-cdk/aws-iottwinmaker": "0.0.0", @@ -302,6 +304,7 @@ "@aws-cdk/aws-resiliencehub": "0.0.0", "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", + "@aws-cdk/aws-rolesanywhere": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53-patterns": "0.0.0", "@aws-cdk/aws-route53-targets": "0.0.0", diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index 4b4a03656fe9d..57356153cf7b2 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -336,19 +336,19 @@ The `progress` key can also be specified as a user setting (`~/.cdk.json`) #### CloudFormation Change Sets vs direct stack updates -By default CDK will create a CloudFormation change with the changes that will -be deployed, and then executes it. This behavior can be controlled with the +By default, CDK creates a CloudFormation change set with the changes that will +be deployed and then executes it. This behavior can be controlled with the `--method` parameter: - `--method=change-set` (default): create and execute the change set. -- `--method=prepare-change-set`: create teh change set but don't execute it. +- `--method=prepare-change-set`: create the change set but don't execute it. This is useful if you have external tools that will inspect the change set or you have an approval process for change sets. - `--method=direct`: do not create a change set but apply the change immediately. This is typically a bit faster than creating a change set, but it loses the progress information. -To have deploy faster without using change sets: +To deploy faster without using change sets: ```console $ cdk deploy --method=direct @@ -410,6 +410,8 @@ For this reason, only use it for development purposes. **⚠ Note #2**: This command is considered experimental, and might have breaking changes in the future. +**⚠ Note #3**: Expected defaults for certain parameters may be different with the hotswap parameter. For example, an ECS service's minimum healthy percentage will currently be set to 0. Please review the source accordingly if this occurs. + ### `cdk watch` The `watch` command is similar to `deploy`, diff --git a/packages/aws-cdk/lib/api/cxapp/exec.ts b/packages/aws-cdk/lib/api/cxapp/exec.ts index 34fae3c59c4c6..01259f7a11763 100644 --- a/packages/aws-cdk/lib/api/cxapp/exec.ts +++ b/packages/aws-cdk/lib/api/cxapp/exec.ts @@ -1,10 +1,14 @@ import * as childProcess from 'child_process'; +import * as os from 'os'; import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; -import { debug } from '../../logging'; +import * as semver from 'semver'; +import { debug, warning } from '../../logging'; import { Configuration, PROJECT_CONFIG, USER_DEFAULTS } from '../../settings'; +import { loadTree, some } from '../../tree'; +import { splitBySize } from '../../util/objects'; import { versionNumber } from '../../version'; import { SdkProvider } from '../aws-auth'; @@ -44,7 +48,6 @@ export async function execProgram(aws: SdkProvider, config: Configuration): Prom context[cxapi.BUNDLING_STACKS] = bundlingStacks; debug('context:', context); - env[cxapi.CONTEXT_ENV] = JSON.stringify(context); const build = config.settings.get(['build']); if (build) { @@ -83,9 +86,28 @@ export async function execProgram(aws: SdkProvider, config: Configuration): Prom debug('env:', env); + const envVariableSizeLimit = os.platform() === 'win32' ? 32760 : 131072; + const [smallContext, overflow] = splitBySize(context, spaceAvailableForContext(env, envVariableSizeLimit)); + + // Store the safe part in the environment variable + env[cxapi.CONTEXT_ENV] = JSON.stringify(smallContext); + + // If there was any overflow, write it to a temporary file + let contextOverflowLocation; + if (Object.keys(overflow ?? {}).length > 0) { + const contextDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-context')); + contextOverflowLocation = path.join(contextDir, 'context-overflow.json'); + fs.writeJSONSync(contextOverflowLocation, overflow); + env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV] = contextOverflowLocation; + } + await exec(commandLine.join(' ')); - return createAssembly(outdir); + const assembly = createAssembly(outdir); + + contextOverflowCleanup(contextOverflowLocation, assembly); + + return assembly; function createAssembly(appDir: string) { try { @@ -215,3 +237,33 @@ async function guessExecutable(commandLine: string[]) { } return commandLine; } + +function contextOverflowCleanup(location: string | undefined, assembly: cxapi.CloudAssembly) { + if (location) { + fs.removeSync(path.dirname(location)); + + const tree = loadTree(assembly); + const frameworkDoesNotSupportContextOverflow = some(tree, node => { + const fqn = node.constructInfo?.fqn; + const version = node.constructInfo?.version; + return (fqn === 'aws-cdk-lib.App' && version != null && semver.lte(version, '2.38.0')) + || fqn === '@aws-cdk/core.App'; // v1 + }); + + // We're dealing with an old version of the framework here. It is unaware of the temporary + // file, which means that it will ignore the context overflow. + if (frameworkDoesNotSupportContextOverflow) { + warning('Part of the context could not be sent to the application. Please update the AWS CDK library to the latest version.'); + } + } +} + +function spaceAvailableForContext(env: { [key: string]: string }, limit: number) { + const size = (value: string) => value != null ? Buffer.byteLength(value) : 0; + + const usedSpace = Object.entries(env) + .map(([k, v]) => k === cxapi.CONTEXT_ENV ? size(k) : size(k) + size(v)) + .reduce((a, b) => a + b, 0); + + return Math.max(0, limit - usedSpace); +} \ No newline at end of file diff --git a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts index baa7383fd3d62..47bba75413e8a 100644 --- a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts +++ b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts @@ -126,7 +126,8 @@ class EcsServiceHotswapOperation implements HotswapOperation { clusterPromises = []; servicePerClusterUpdates[clusterName] = clusterPromises; } - + // Forcing New Deployment and setting Minimum Healthy Percent to 0. + // As CDK HotSwap is development only, this seems the most efficient way to ensure all tasks are replaced immediately, regardless of original amount. clusterPromises.push({ promise: sdk.ecs().updateService({ service: ecsService.serviceArn, diff --git a/packages/aws-cdk/lib/commands/doctor.ts b/packages/aws-cdk/lib/commands/doctor.ts index e1942bbd06b2b..5ea4ddc6367eb 100644 --- a/packages/aws-cdk/lib/commands/doctor.ts +++ b/packages/aws-cdk/lib/commands/doctor.ts @@ -51,7 +51,7 @@ function displayCdkEnvironmentVariables() { print('ℹ️ CDK environment variables:'); let healthy = true; for (const key of keys.sort()) { - if (key === cxapi.CONTEXT_ENV || key === cxapi.OUTDIR_ENV) { + if (key === cxapi.CONTEXT_ENV || key === cxapi.CONTEXT_OVERFLOW_LOCATION_ENV || key === cxapi.OUTDIR_ENV) { print(` - ${chalk.red(key)} = ${chalk.green(process.env[key]!)} (⚠️ reserved for use by the CDK toolkit)`); healthy = false; } else { diff --git a/packages/aws-cdk/lib/init-templates/app/go/%name%.template.go b/packages/aws-cdk/lib/init-templates/app/go/%name%.template.go index 1cbe6d66b615c..8c966fa48359d 100644 --- a/packages/aws-cdk/lib/init-templates/app/go/%name%.template.go +++ b/packages/aws-cdk/lib/init-templates/app/go/%name%.template.go @@ -4,7 +4,7 @@ import ( "github.com/aws/aws-cdk-go/awscdk/v2" // "github.com/aws/aws-cdk-go/awscdk/v2/awssqs" "github.com/aws/constructs-go/constructs/v10" - // "github.com/aws/jsii-runtime-go" + "github.com/aws/jsii-runtime-go" ) type %name.PascalCased%StackProps struct { diff --git a/packages/aws-cdk/lib/notices.ts b/packages/aws-cdk/lib/notices.ts index 3d4b48a7154b5..7370b84a36f9f 100644 --- a/packages/aws-cdk/lib/notices.ts +++ b/packages/aws-cdk/lib/notices.ts @@ -3,7 +3,8 @@ import * as https from 'https'; import * as path from 'path'; import * as fs from 'fs-extra'; import * as semver from 'semver'; -import { debug, print, trace } from './logging'; +import { debug, print } from './logging'; +import { some, ConstructTreeNode, loadTreeFromDir } from './tree'; import { flatMap } from './util'; import { cdkCacheDir } from './util/directories'; import { versionNumber } from './version'; @@ -79,7 +80,7 @@ export function filterNotices(data: Notice[], options: FilterNoticeOptions): Not const filter = new NoticeFilter({ cliVersion: options.cliVersion ?? versionNumber(), acknowledgedIssueNumbers: options.acknowledgedIssueNumbers ?? new Set(), - tree: loadTree(options.outdir ?? 'cdk.out').tree, + tree: loadTreeFromDir(options.outdir ?? 'cdk.out'), }); return data.filter(notice => filter.apply(notice)); } @@ -336,51 +337,3 @@ function match(query: Component[], tree: ConstructTreeNode): boolean { return semver.satisfies(target ?? '', pattern); } } - -function loadTree(outdir: string) { - try { - return fs.readJSONSync(path.join(outdir, 'tree.json')); - } catch (e) { - trace(`Failed to get tree.json file: ${e}. Proceeding with empty tree.`); - return {}; - } -} - -/** - * Source information on a construct (class fqn and version) - */ -interface ConstructInfo { - readonly fqn: string; - readonly version: string; -} - -/** - * A node in the construct tree. - * @internal - */ -interface ConstructTreeNode { - readonly id: string; - readonly path: string; - readonly children?: { [key: string]: ConstructTreeNode }; - readonly attributes?: { [key: string]: any }; - - /** - * Information on the construct class that led to this node, if available - */ - readonly constructInfo?: ConstructInfo; -} - -function some(node: ConstructTreeNode, predicate: (n: ConstructTreeNode) => boolean): boolean { - return node != null && (predicate(node) || findInChildren()); - - function findInChildren(): boolean { - if (node.children == null) { return false; } - - for (const name in node.children) { - if (some(node.children[name], predicate)) { - return true; - } - } - return false; - } -} diff --git a/packages/aws-cdk/lib/tree.ts b/packages/aws-cdk/lib/tree.ts new file mode 100644 index 0000000000000..57ae5685ae17c --- /dev/null +++ b/packages/aws-cdk/lib/tree.ts @@ -0,0 +1,58 @@ +import * as path from 'path'; +import { CloudAssembly } from '@aws-cdk/cx-api'; +import * as fs from 'fs-extra'; +import { trace } from './logging'; + +/** + * Source information on a construct (class fqn and version) + */ +export interface ConstructInfo { + readonly fqn: string; + readonly version: string; +} + +/** + * A node in the construct tree. + */ +export interface ConstructTreeNode { + readonly id: string; + readonly path: string; + readonly children?: { [key: string]: ConstructTreeNode }; + readonly attributes?: { [key: string]: any }; + + /** + * Information on the construct class that led to this node, if available + */ + readonly constructInfo?: ConstructInfo; +} + +/** + * Whether the provided predicate is true for at least one element in the construct (sub-)tree. + */ +export function some(node: ConstructTreeNode, predicate: (n: ConstructTreeNode) => boolean): boolean { + return node != null && (predicate(node) || findInChildren()); + + function findInChildren(): boolean { + return Object.values(node.children ?? {}).some(child => some(child, predicate)); + } +} + +export function loadTree(assembly: CloudAssembly) { + try { + const outdir = assembly.directory; + const fileName = assembly.tree()?.file; + return fileName ? fs.readJSONSync(path.join(outdir, fileName)).tree : {}; + } catch (e) { + trace(`Failed to get tree.json file: ${e}. Proceeding with empty tree.`); + return {}; + } +} + +export function loadTreeFromDir(outdir: string) { + try { + return fs.readJSONSync(path.join(outdir, 'tree.json')).tree; + } catch (e) { + trace(`Failed to get tree.json file: ${e}. Proceeding with empty tree.`); + return {}; + } +} diff --git a/packages/aws-cdk/lib/util/objects.ts b/packages/aws-cdk/lib/util/objects.ts index 7fb660525687c..c372152a2cc5f 100644 --- a/packages/aws-cdk/lib/util/objects.ts +++ b/packages/aws-cdk/lib/util/objects.ts @@ -134,3 +134,39 @@ export function deepMerge(...objects: Array | undefined>) { others.forEach(other => mergeOne(into, other)); return into; } + +/** + * Splits the given object into two, such that: + * + * 1. The size of the first object (after stringified in UTF-8) is less than or equal to the provided size limit. + * 2. Merging the two objects results in the original one. + */ +export function splitBySize(data: any, maxSizeBytes: number): [any, any] { + if (maxSizeBytes < 2) { + // It's impossible to fit anything in the first object + return [undefined, data]; + } + const entries = Object.entries(data); + return recurse(0, 0); + + function recurse(index: number, runningTotalSize: number): [any, any] { + if (index >= entries.length) { + // Everything fits in the first object + return [data, undefined]; + } + + const size = runningTotalSize + entrySize(entries[index]); + return (size > maxSizeBytes) ? cutAt(index) : recurse(index + 1, size); + } + + function entrySize(entry: [string, unknown]) { + return Buffer.byteLength(JSON.stringify(Object.fromEntries([entry]))); + } + + function cutAt(index: number): [any, any] { + return [ + Object.fromEntries(entries.slice(0, index)), + Object.fromEntries(entries.slice(index)), + ]; + } +} \ No newline at end of file diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index dcd2f52dd01df..ba1c5ec0179d8 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -88,7 +88,8 @@ "ts-jest": "^27.1.5", "ts-mock-imports": "^1.3.8", "xml-js": "^1.6.11", - "axios": "^0.27.2" + "axios": "^0.27.2", + "fast-check": "^2.25.0" }, "dependencies": { "@aws-cdk/cloud-assembly-schema": "0.0.0", diff --git a/packages/aws-cdk/test/integ/common/jest-test.bash b/packages/aws-cdk/test/integ/common/jest-test.bash index b29ca90036d38..7a96a9f845155 100755 --- a/packages/aws-cdk/test/integ/common/jest-test.bash +++ b/packages/aws-cdk/test/integ/common/jest-test.bash @@ -5,7 +5,7 @@ function invokeJest() { # package.json. if ! npx --no-install jest --version; then echo 'Looks like we need to install jest first. Hold on.' >& 2 - npm install --prefix .. jest jest-junit aws-sdk axios + npm install --prefix .. jest@^27 jest-junit@^14 aws-sdk@^2 axios@^0.27.2 fi # This must --runInBand because parallelism is arranged for inside the tests diff --git a/packages/aws-cdk/test/tree.test.ts b/packages/aws-cdk/test/tree.test.ts new file mode 100644 index 0000000000000..0feb5725c21df --- /dev/null +++ b/packages/aws-cdk/test/tree.test.ts @@ -0,0 +1,114 @@ +import * as path from 'path'; +import { ConstructTreeNode, loadTreeFromDir, some } from '../lib/tree'; + +describe('some', () => { + const tree: ConstructTreeNode = { + id: 'App', + path: '', + children: { + Tree: { + id: 'Tree', + path: 'Tree', + constructInfo: { + fqn: '@aws-cdk/core.Construct', + version: '1.162.0', + }, + }, + stack: { + id: 'stack', + path: 'stack', + children: { + bucket: { + id: 'bucket', + path: 'stack/bucket', + children: { + Resource: { + id: 'Resource', + path: 'stack/bucket/Resource', + attributes: { + 'aws:cdk:cloudformation:type': 'AWS::S3::Bucket', + 'aws:cdk:cloudformation:props': {}, + }, + constructInfo: { + fqn: '@aws-cdk/aws-s3.CfnBucket', + version: '1.162.0', + }, + }, + }, + constructInfo: { + fqn: '@aws-cdk/aws-s3.Bucket', + version: '1.162.0', + }, + }, + CDKMetadata: { + id: 'CDKMetadata', + path: 'stack/CDKMetadata', + children: { + Default: { + id: 'Default', + path: 'stack/CDKMetadata/Default', + constructInfo: { + fqn: '@aws-cdk/core.CfnResource', + version: '1.162.0', + }, + }, + Condition: { + id: 'Condition', + path: 'stack/CDKMetadata/Condition', + constructInfo: { + fqn: '@aws-cdk/core.CfnCondition', + version: '1.162.0', + }, + }, + }, + constructInfo: { + fqn: '@aws-cdk/core.Construct', + version: '1.162.0', + }, + }, + }, + constructInfo: { + fqn: '@aws-cdk/core.Stack', + version: '1.162.0', + }, + }, + }, + constructInfo: { + fqn: '@aws-cdk/core.App', + version: '1.162.0', + }, + }; + + test('tree matches predicate', () => { + expect(some(tree, node => node.constructInfo?.fqn === '@aws-cdk/aws-s3.Bucket')).toBe(true); + }); + + test('tree does not match predicate', () => { + expect(some(tree, node => node.constructInfo?.fqn === '@aws-cdk/aws-lambda.Function')).toBe(false); + }); + + test('childless tree', () => { + const childless = { + id: 'App', + path: '', + constructInfo: { + fqn: '@aws-cdk/core.App', + version: '1.162.0', + }, + }; + + expect(some(childless, node => node.path.length > 0)).toBe(false); + }); +}); + +describe('loadTreeFromDir', () => { + test('can find tree', () => { + const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees/built-with-1_144_0')); + expect(tree.id).toEqual('App'); + }); + + test('cannot find tree', () => { + const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees/foo')); + expect(tree).toEqual({}); + }); +}); \ No newline at end of file diff --git a/packages/aws-cdk/test/util/objects.test.ts b/packages/aws-cdk/test/util/objects.test.ts index ad8db09e09002..ef9b23d2e4aed 100644 --- a/packages/aws-cdk/test/util/objects.test.ts +++ b/packages/aws-cdk/test/util/objects.test.ts @@ -1,4 +1,5 @@ -import { deepClone, deepGet, deepMerge, deepSet } from '../../lib/util'; +import * as fc from 'fast-check'; +import { deepClone, deepGet, deepMerge, deepSet, splitBySize } from '../../lib/util'; test('deepSet can set deeply', () => { const obj = {}; @@ -44,3 +45,20 @@ test('deepMerge does not overwrite if rightmost is "undefined"', () => { expect(original).toEqual({ a: 1 }); }); + +describe('splitBySize', () => { + test('objects are split at the right place', () => { + fc.assert( + fc.property(fc.object(), fc.integer({ min: 2 }), (data, size) => { + const [first, second] = splitBySize(data, size); + + expect(Buffer.from(JSON.stringify(first)).length).toBeLessThanOrEqual(size); + expect(merge(first, second)).toEqual(data); + }), + ); + + function merge(fst: any, snd: any) { + return { ...(fst ?? {}), ...(snd ?? {}) }; + } + }); +}); \ No newline at end of file diff --git a/packages/monocdk/package.json b/packages/monocdk/package.json index ca03edcce0d69..3575417985300 100644 --- a/packages/monocdk/package.json +++ b/packages/monocdk/package.json @@ -173,6 +173,7 @@ "@aws-cdk/aws-cognito-identitypool": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", + "@aws-cdk/aws-connectcampaigns": "0.0.0", "@aws-cdk/aws-controltower": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", "@aws-cdk/aws-customerprofiles": "0.0.0", @@ -235,6 +236,7 @@ "@aws-cdk/aws-iotevents": "0.0.0", "@aws-cdk/aws-iotevents-actions": "0.0.0", "@aws-cdk/aws-iotfleethub": "0.0.0", + "@aws-cdk/aws-iotfleetwise": "0.0.0", "@aws-cdk/aws-iotsitewise": "0.0.0", "@aws-cdk/aws-iotthingsgraph": "0.0.0", "@aws-cdk/aws-iottwinmaker": "0.0.0", @@ -300,6 +302,7 @@ "@aws-cdk/aws-resiliencehub": "0.0.0", "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", + "@aws-cdk/aws-rolesanywhere": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53-patterns": "0.0.0", "@aws-cdk/aws-route53-targets": "0.0.0", diff --git a/tools/@aws-cdk/prlint/lint.ts b/tools/@aws-cdk/prlint/lint.ts index 425be04d6f8e4..d01c3f2121126 100644 --- a/tools/@aws-cdk/prlint/lint.ts +++ b/tools/@aws-cdk/prlint/lint.ts @@ -29,6 +29,19 @@ export interface GitHubFile { readonly filename: string; } +export interface Review { + id: number; + user: { + login: string + }; + body: string; + state: string; +} + +export interface Comment { + id: number; +} + class LinterError extends Error { constructor(message: string) { super(message); @@ -158,37 +171,97 @@ export interface PullRequestLinterProps { export class PullRequestLinter { private readonly client: Octokit; private readonly prParams: { owner: string, repo: string, pull_number: number }; + private readonly issueParams: { owner: string, repo: string, issue_number: number }; constructor(private readonly props: PullRequestLinterProps) { this.client = props.client; this.prParams = { owner: props.owner, repo: props.repo, pull_number: props.number }; + this.issueParams = { owner: props.owner, repo: props.repo, issue_number: props.number }; } /** - * Dismisses previous reviews by aws-cdk-automation when changes have been made to the pull request. + * Deletes the previous linter comment if it exists. */ - private async dismissPreviousPRLinterReviews(): Promise { - const reviews = await this.client.pulls.listReviews(this.prParams); - reviews.data.forEach(async (review: any) => { - if (review.user?.login === 'aws-cdk-automation' && review.state !== 'DISMISSED') { - await this.client.pulls.dismissReview({ - ...this.prParams, - review_id: review.id, - message: 'Pull Request updated. Dissmissing previous PRLinter Review.', - }) - } + private async deletePRLinterComment(): Promise { + // Since previous versions of this pr linter didn't add comments, we need to do this check first. + const comment = await this.findExistingComment(); + if (comment) { + await this.client.issues.deleteComment({ + ...this.issueParams, + comment_id: comment.id, + }); + }; + }; + + /** + * Dismisses previous reviews by aws-cdk-automation when the pull request succeeds the linter. + * @param existingReview The review created by a previous run of the linter + */ + private async dismissPRLinterReview(existingReview?: Review): Promise { + if (existingReview) { + await this.client.pulls.dismissReview({ + ...this.prParams, + review_id: existingReview.id, + message: '✅ Updated pull request passes all PRLinter validations. Dissmissing previous PRLinter review.' + }) + } + } + + /** + * Creates a new review and comment for first run with failure or creates a new comment with new failures for existing reviews. + * @param failureMessages The failures received by the pr linter validation checks. + * @param existingReview The review created by a previous run of the linter. + */ + private async createOrUpdatePRLinterReview(failureMessages: string[], existingReview?: Review): Promise { + const body = `The pull request linter fails with the following errors:${this.formatErrors(failureMessages)}PRs must pass status checks before we can provide a meaningful review.`; + if (!existingReview) { + await this.client.pulls.createReview({ + ...this.prParams, + body: 'The pull request linter has failed. See the aws-cdk-automation comment below for failure reasons.' + + ' If you believe this pull request should receive an exemption, please comment and provide a justification.', + event: 'REQUEST_CHANGES', + }) + } + + await this.client.issues.createComment({ + ...this.issueParams, + body, }) + + throw new LinterError(body); + } + + /** + * Finds existing review, if present + * @returns Existing review, if present + */ + private async findExistingReview(): Promise { + const reviews = await this.client.pulls.listReviews(this.prParams); + return reviews.data.find((review) => review.user?.login === 'aws-cdk-automation' && review.state !== 'DISMISSED') as Review; + } + + /** + * Finds existing comment from previous review, if present + * @returns Existing comment, if present + */ + private async findExistingComment(): Promise { + const comments = await this.client.issues.listComments(this.issueParams); + return comments.data.find((comment) => comment.user?.login === 'aws-cdk-automation' && comment.body?.startsWith('The pull request linter fails with the following errors:')) as Comment; } /** * Creates a new review, requesting changes, with the reasons that the linter did not pass. - * @param failureReasons The list of reasons why the linter failed + * @param result The result of the PR Linter run. */ - private async communicateResult(failureReasons: string[]): Promise { - const body = `The Pull Request Linter fails with the following errors:${this.formatErrors(failureReasons)}PRs must pass status checks before we can provide a meaningful review.`; - await this.client.pulls.createReview({ ...this.prParams, body, event: 'REQUEST_CHANGES', }); - throw new LinterError(body); + private async communicateResult(result: ValidationCollector): Promise { + const existingReview = await this.findExistingReview(); + if (result.isValid()) { + console.log("✅ Success"); + await this.dismissPRLinterReview(existingReview); + } else { + await this.createOrUpdatePRLinterReview(result.errors, existingReview); + } } /** @@ -245,8 +318,8 @@ export class PullRequestLinter { testRuleSet: [ { test: noCliChanges } ], }); - await this.dismissPreviousPRLinterReviews(); - validationCollector.isValid() ? console.log("✅ Success") : await this.communicateResult(validationCollector.errors); + await this.deletePRLinterComment(); + await this.communicateResult(validationCollector); } private formatErrors(errors: string[]) { diff --git a/tools/@aws-cdk/prlint/test/lint.test.ts b/tools/@aws-cdk/prlint/test/lint.test.ts index 5cd298eb65a49..9a22289c7589d 100644 --- a/tools/@aws-cdk/prlint/test/lint.test.ts +++ b/tools/@aws-cdk/prlint/test/lint.test.ts @@ -168,7 +168,7 @@ describe('integration tests required on features', () => { ]; const prLinter = configureMock(issue, files); await expect(prLinter.validate()).rejects.toThrow( - 'The Pull Request Linter fails with the following errors:' + + 'The pull request linter fails with the following errors:' + '\n\n\t❌ Features must contain a change to an integration test file and the resulting snapshot.' + '\n\nPRs must pass status checks before we can provide a meaningful review.' ); @@ -198,7 +198,7 @@ describe('integration tests required on features', () => { ]; const prLinter = configureMock(issue, files); await expect(prLinter.validate()).rejects.toThrow( - 'The Pull Request Linter fails with the following errors:' + + 'The pull request linter fails with the following errors:' + '\n\n\t❌ Features must contain a change to an integration test file and the resulting snapshot.' + '\n\nPRs must pass status checks before we can provide a meaningful review.' ); @@ -228,7 +228,7 @@ describe('integration tests required on features', () => { ]; const prLinter = configureMock(issue, files); await expect(prLinter.validate()).rejects.toThrow( - 'The Pull Request Linter fails with the following errors:' + + 'The pull request linter fails with the following errors:' + '\n\n\t❌ Fixes must contain a change to an integration test file and the resulting snapshot.' + '\n\nPRs must pass status checks before we can provide a meaningful review.' ); @@ -258,7 +258,7 @@ describe('integration tests required on features', () => { ]; const prLinter = configureMock(issue, files); await expect(prLinter.validate()).rejects.toThrow( - 'The Pull Request Linter fails with the following errors:' + + 'The pull request linter fails with the following errors:' + '\n\n\t❌ Fixes must contain a change to an integration test file and the resulting snapshot.' + '\n\nPRs must pass status checks before we can provide a meaningful review.' ); @@ -355,12 +355,21 @@ function configureMock(pr: linter.GitHubPr, prFiles?: linter.GitHubFile[]): lint }, listReviews(_props: { _owner: string, _repo: string, _pull_number: number }) { - return { data: [{ id: 1111122222, user: { login: 'aws-cdk-automation' }, state: 'CHANGES_REQUESTED' }] }; + return { data: [{ id: 1111122222, user: { login: 'aws-cdk-automation' }, state: 'CHANGES_REQUESTED' }] }; }, dismissReview() {}, + }; - } + const issuesClient = { + createComment() {}, + + deleteComment() {}, + + listComments() { + return { data: [{ id: 1212121212, user: { login: 'aws-cdk-automation' }, body: 'The pull request linter fails with the following errors:' }] } + } + }; return new linter.PullRequestLinter({ owner: 'aws', repo: 'aws-cdk', @@ -369,6 +378,7 @@ function configureMock(pr: linter.GitHubPr, prFiles?: linter.GitHubFile[]): lint // hax hax client: { pulls: pullsClient as any, + issues: issuesClient as any, } as any, }) } diff --git a/version.v2.json b/version.v2.json index d48962f88e81c..14e2015ff2321 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.44.0", - "alphaVersion": "2.44.0-alpha.0" + "version": "2.45.0", + "alphaVersion": "2.45.0-alpha.0" } \ No newline at end of file