diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index 405ffd52e59eb..5c0234bdf43a5 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.56.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.56.0-alpha.0...v2.56.1-alpha.0) (2022-12-23) + +## [2.56.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.55.1-alpha.0...v2.56.0-alpha.0) (2022-12-21) + + +### Features + +* **integ-tests:** add serializedJson on match utility ([#23218](https://github.com/aws/aws-cdk/issues/23218)) ([1a62dc4](https://github.com/aws/aws-cdk/commit/1a62dc4590d725d3c03861af434a24789eaa0a2e)) +* **servicecatalogappregistry:** Cross region warning and default application tag ([#23412](https://github.com/aws/aws-cdk/issues/23412)) ([8d359ae](https://github.com/aws/aws-cdk/commit/8d359ae35877ce066e419f7e2e7da2b0deb587e6)) + ## [2.55.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.55.0-alpha.0...v2.55.1-alpha.0) (2022-12-16) ## [2.55.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.54.0-alpha.0...v2.55.0-alpha.0) (2022-12-14) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index edce65d28bb01..627dbdbf84728 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -2,6 +2,36 @@ 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.56.1](https://github.com/aws/aws-cdk/compare/v2.56.0...v2.56.1) (2022-12-23) + + +### Bug Fixes + +* **cfnspec:** v101.0.0 introduced specific types on several types that previously were typed as json ([#23448](https://github.com/aws/aws-cdk/issues/23448)) ([1b4e3a4](https://github.com/aws/aws-cdk/commit/1b4e3a4b503d5d08e976ccf245c20f4430bcba46)) + +## [2.56.0](https://github.com/aws/aws-cdk/compare/v2.55.1...v2.56.0) (2022-12-21) + + +### Features + +* **aws-cognito:** add AuthSessionValidity property on a UserPoolClient ([#23040](https://github.com/aws/aws-cdk/issues/23040)) ([8896fb9](https://github.com/aws/aws-cdk/commit/8896fb902ad9c8d91a5ddb63df64963186bd09e1)), closes [#22854](https://github.com/aws/aws-cdk/issues/22854) +* **cfnspec:** cloudformation spec v102.0.0 ([#23372](https://github.com/aws/aws-cdk/issues/23372)) ([480b0a5](https://github.com/aws/aws-cdk/commit/480b0a5098e51248bbf36ebf2bcec57cc791c2b0)) +* **core:** CfnResource dependency methods ([#23383](https://github.com/aws/aws-cdk/issues/23383)) ([ecedb00](https://github.com/aws/aws-cdk/commit/ecedb00ee3a3cfcaa2564a679fa635aff38f32d8)), closes [#20419](https://github.com/aws/aws-cdk/issues/20419) [#20418](https://github.com/aws/aws-cdk/issues/20418) +* **lambda:** expose all docker run options to container bundling of all lambda variants ([#23318](https://github.com/aws/aws-cdk/issues/23318)) ([02d0876](https://github.com/aws/aws-cdk/commit/02d0876bbb196e9fbeb32d977e7cf65229c8559d)), closes [#22829](https://github.com/aws/aws-cdk/issues/22829) +* **trigger:** Allow trigger to work with Lambda functions with long timeouts ([#23062](https://github.com/aws/aws-cdk/issues/23062)) ([9fd3811](https://github.com/aws/aws-cdk/commit/9fd3811b3213a227b84d79348e635a520fc537c7)), closes [#23058](https://github.com/aws/aws-cdk/issues/23058) + + +### Bug Fixes + +* **apigateway:** allow multi-level base path mapping ([#23362](https://github.com/aws/aws-cdk/issues/23362)) ([86b6c6f](https://github.com/aws/aws-cdk/commit/86b6c6f796cbd15b7c53a4c0482a2b189d45300f)), closes [#23347](https://github.com/aws/aws-cdk/issues/23347) +* **autoscaling:** Allow adding AutoScalingGroup to multiple target groups ([#23044](https://github.com/aws/aws-cdk/issues/23044)) ([07acd18](https://github.com/aws/aws-cdk/commit/07acd180d778b7084d8519234cfc3570bb8846ba)), closes [/github.com/aws/aws-cdk/issues/5667#issuecomment-636657482](https://github.com/aws//github.com/aws/aws-cdk/issues/5667/issues/issuecomment-636657482) [#5667](https://github.com/aws/aws-cdk/issues/5667) +* **aws-eks:** fail to update both logging and access at the same time ([#22957](https://github.com/aws/aws-cdk/issues/22957)) ([606837d](https://github.com/aws/aws-cdk/commit/606837d3de5d048e3fb1674c30a3048e918f680a)) +* **cognito:** quote or mime-encode `fromName` to comply RFC 5322 ([#23227](https://github.com/aws/aws-cdk/issues/23227)) ([78d474a](https://github.com/aws/aws-cdk/commit/78d474a12bce7805f88be96df926149c130bf513)), closes [#18903](https://github.com/aws/aws-cdk/issues/18903) [/www.rfc-editor.org/rfc/rfc5322#section-3](https://github.com/aws//www.rfc-editor.org/rfc/rfc5322/issues/section-3) +* **core:** cross region ssm writer update ([#23356](https://github.com/aws/aws-cdk/issues/23356)) ([87bd42d](https://github.com/aws/aws-cdk/commit/87bd42d41f11667aef673d9087c28cecedb87f66)) +* **dynamodb:** add kms permissions to grantStreamRead ([#23400](https://github.com/aws/aws-cdk/issues/23400)) ([fcf1bfa](https://github.com/aws/aws-cdk/commit/fcf1bfaab173ee57bbf64d95be62bf10cbb1b851)), closes [40aws-cdk/aws-dynamodb/lib/table.ts#L1025-L1061](https://github.com/40aws-cdk/aws-dynamodb/lib/table.ts/issues/L1025-L1061) +* **s3-deployment:** source markers missing when there are multiple sources ([#23364](https://github.com/aws/aws-cdk/issues/23364)) ([8a7ec37](https://github.com/aws/aws-cdk/commit/8a7ec37e0085e952b59bebab1ecc880167a0691f)), closes [#23321](https://github.com/aws/aws-cdk/issues/23321) [40aws-cdk/aws-s3-deployment/lib/lambda/index.py#L64](https://github.com/40aws-cdk/aws-s3-deployment/lib/lambda/index.py/issues/L64) [40aws-cdk/aws-s3-deployment/lib/lambda/index.py#L137](https://github.com/40aws-cdk/aws-s3-deployment/lib/lambda/index.py/issues/L137) +* **timestream:** magneticStoreWriteProperties and retentionProperties not working as Json ([#23425](https://github.com/aws/aws-cdk/issues/23425)) ([b705224](https://github.com/aws/aws-cdk/commit/b7052242fb699ba89603ae718ae2d6b0ab9efa6f)), closes [#23404](https://github.com/aws/aws-cdk/issues/23404) + ## [2.55.1](https://github.com/aws/aws-cdk/compare/v2.55.0...v2.55.1) (2022-12-16) 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 066ec229b832f..0df48fcb89e3b 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/base-path-mapping.ts @@ -56,8 +56,14 @@ export class BasePathMapping extends Resource { super(scope, id); if (props.basePath && !Token.isUnresolved(props.basePath)) { - if (!props.basePath.match(/^[a-zA-Z0-9$_.+!*'()-]+$/)) { - throw new Error(`A base path may only contain letters, numbers, and one of "$-_.+!*'()", received: ${props.basePath}`); + if (props.basePath.startsWith('/') || props.basePath.endsWith('/')) { + throw new Error(`A base path cannot start or end with /", received: ${props.basePath}`); + } + if (props.basePath.match(/\/{2,}/)) { + throw new Error(`A base path cannot have more than one consecutive /", received: ${props.basePath}`); + } + if (!props.basePath.match(/^[a-zA-Z0-9$_.+!*'()-/]+$/)) { + throw new Error(`A base path may only contain letters, numbers, and one of "$-_.+!*'()/", received: ${props.basePath}`); } } 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 c3da93e83ba26..69e7e98d9146f 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 @@ -8,7 +8,7 @@ describe('BasePathMapping', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigw.RestApi(stack, 'MyApi'); - api.root.addMethod('GET'); // api must have atleast one method. + api.root.addMethod('GET'); // api must have at least 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'), @@ -33,7 +33,7 @@ describe('BasePathMapping', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigw.RestApi(stack, 'MyApi'); - api.root.addMethod('GET'); // api must have atleast one method. + api.root.addMethod('GET'); // api must have at least 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'), @@ -53,11 +53,11 @@ describe('BasePathMapping', () => { }); }); - test('throw error for invalid basePath property', () => { + test('specify multi-level basePath property', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigw.RestApi(stack, 'MyApi'); - api.root.addMethod('GET'); // api must have atleast one method. + api.root.addMethod('GET'); // api must have at least 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'), @@ -65,7 +65,31 @@ describe('BasePathMapping', () => { }); // WHEN - const invalidBasePath = '/invalid-/base-path'; + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: 'api/v1/example', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::BasePathMapping', { + BasePath: 'api/v1/example', + }); + }); + + test('throws when basePath contains an invalid character', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have at least 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 + const invalidBasePath = 'invalid-/base-path?'; // THEN expect(() => { @@ -77,11 +101,83 @@ describe('BasePathMapping', () => { }).toThrowError(/base path may only contain/); }); + test('throw error for basePath starting with /', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have at least 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 + const invalidBasePath = '/invalid-base-path'; + + // THEN + expect(() => { + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: invalidBasePath, + }); + }).toThrowError(/A base path cannot start or end with/); + }); + + test('throw error for basePath ending with /', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have at least 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 + const invalidBasePath = 'invalid-base-path/'; + + // THEN + expect(() => { + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: invalidBasePath, + }); + }).toThrowError(/A base path cannot start or end with/); + }); + + test('throw error for basePath containing more than one consecutive /', () => { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigw.RestApi(stack, 'MyApi'); + api.root.addMethod('GET'); // api must have at least 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 + const invalidBasePath = 'in//valid-base-path'; + + // THEN + expect(() => { + new apigw.BasePathMapping(stack, 'MyBasePath', { + restApi: api, + domainName: domain, + basePath: invalidBasePath, + }); + }).toThrowError(/A base path cannot have more than one consecutive \//); + }); + test('specify stage property', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigw.RestApi(stack, 'MyApi'); - api.root.addMethod('GET'); // api must have atleast one method. + api.root.addMethod('GET'); // api must have at least 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'), @@ -111,7 +207,7 @@ describe('BasePathMapping', () => { // GIVEN const stack = new cdk.Stack(); const api = new apigw.RestApi(stack, 'MyApi'); - api.root.addMethod('GET'); // api must have atleast one method. + api.root.addMethod('GET'); // api must have at least 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'), diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/manifest.json b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/manifest.json index a57c7ce4a9fcd..0049bafae7b8e 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/manifest.json @@ -81,6 +81,12 @@ "data": "MappingTwo551C79ED" } ], + "/test-stack/MappingThree/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MappingThree36BBA1B6" + } + ], "/test-stack/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/test-stack.template.json b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/test-stack.template.json index 52d687e8b3f2d..022e83846fdab 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/test-stack.template.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/test-stack.template.json @@ -70,6 +70,16 @@ "Ref": "ApiF70053CD" } } + }, + "MappingThree36BBA1B6": { + "Type": "AWS::ApiGateway::BasePathMapping", + "Properties": { + "DomainName": "domainName", + "BasePath": "api/v1/multi-level-path", + "RestApiId": { + "Ref": "ApiF70053CD" + } + } } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/tree.json b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/tree.json index 2a9baa7dc204d..814e1397b0795 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.js.snapshot/tree.json @@ -217,6 +217,34 @@ "fqn": "@aws-cdk/aws-apigateway.BasePathMapping", "version": "0.0.0" } + }, + "MappingThree": { + "id": "MappingThree", + "path": "test-stack/MappingThree", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/MappingThree/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": { 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 index 9d3a31a3a205e..f25b572545f49 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integ.base-path-mapping.ts @@ -27,6 +27,13 @@ export class TestStack extends cdk.Stack { basePath: 'path', attachToStage: false, }); + + new apigateway.BasePathMapping(this, 'MappingThree', { + domainName, + restApi, + basePath: 'api/v1/multi-level-path', + attachToStage: false, + }); } } diff --git a/packages/@aws-cdk/aws-appsync/lib/appsync-function.ts b/packages/@aws-cdk/aws-appsync/lib/appsync-function.ts index 7423317d0fa3e..46019afe6c2a9 100644 --- a/packages/@aws-cdk/aws-appsync/lib/appsync-function.ts +++ b/packages/@aws-cdk/aws-appsync/lib/appsync-function.ts @@ -142,7 +142,7 @@ export class AppsyncFunction extends Resource implements IAppsyncFunction { this.functionId = this.function.attrFunctionId; this.dataSource = props.dataSource; - this.function.addDependsOn(this.dataSource.ds); + this.function.addDependency(this.dataSource.ds); props.api.addSchemaDependency(this.function); } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts index 83027eafd5603..0f7f16a37f0ab 100644 --- a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts +++ b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts @@ -518,7 +518,7 @@ export class GraphqlApi extends GraphqlApiBase { apiId: this.apiId, }); - domainNameAssociation.addDependsOn(this.domainNameResource); + domainNameAssociation.addDependency(this.domainNameResource); } if (modes.some((mode) => mode.authorizationType === AuthorizationType.API_KEY)) { @@ -526,7 +526,7 @@ export class GraphqlApi extends GraphqlApiBase { return mode.authorizationType === AuthorizationType.API_KEY && mode.apiKeyConfig; })?.apiKeyConfig; this.apiKeyResource = this.createAPIKey(config); - this.apiKeyResource.addDependsOn(this.schemaResource); + this.apiKeyResource.addDependency(this.schemaResource); this.apiKey = this.apiKeyResource.attrApiKey; } @@ -631,7 +631,7 @@ export class GraphqlApi extends GraphqlApiBase { * @param construct the dependee */ public addSchemaDependency(construct: CfnResource): boolean { - construct.addDependsOn(this.schemaResource); + construct.addDependency(this.schemaResource); return true; } diff --git a/packages/@aws-cdk/aws-appsync/lib/resolver.ts b/packages/@aws-cdk/aws-appsync/lib/resolver.ts index 3df7f44a068c5..72818cb59b966 100644 --- a/packages/@aws-cdk/aws-appsync/lib/resolver.ts +++ b/packages/@aws-cdk/aws-appsync/lib/resolver.ts @@ -122,7 +122,7 @@ export class Resolver extends Construct { }); props.api.addSchemaDependency(this.resolver); if (props.dataSource) { - this.resolver.addDependsOn(props.dataSource.ds); + this.resolver.addDependency(props.dataSource.ds); } this.arn = this.resolver.attrResolverArn; } diff --git a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts index c70c32271c331..9226cd703f6bf 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts @@ -985,6 +985,7 @@ abstract class AutoScalingGroupBase extends Resource implements IAutoScalingGrou public abstract readonly osType: ec2.OperatingSystemType; protected albTargetGroup?: elbv2.ApplicationTargetGroup; public readonly grantPrincipal: iam.IPrincipal = new iam.UnknownPrincipal({ resource: this }); + protected hasCalledScaleOnRequestCount: boolean = false; /** * Send a message to either an SQS queue or SNS topic when instances launch or terminate @@ -1088,6 +1089,7 @@ abstract class AutoScalingGroupBase extends Resource implements IAutoScalingGrou }); policy.node.addDependency(this.albTargetGroup.loadBalancerAttached); + this.hasCalledScaleOnRequestCount = true; return policy; } @@ -1388,6 +1390,8 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements if (props.requireImdsv2) { Aspects.of(this).add(new AutoScalingGroupRequireImdsv2Aspect()); } + + this.node.addValidation({ validate: () => this.validateTargetGroup() }); } /** @@ -1415,10 +1419,6 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements * Attach to ELBv2 Application Target Group */ public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps { - if (this.albTargetGroup !== undefined) { - throw new Error('Cannot add AutoScalingGroup to 2nd Target Group'); - } - this.targetGroupArns.push(targetGroup.targetGroupArn); if (targetGroup instanceof elbv2.ApplicationTargetGroup) { // Copy onto self if it's a concrete type. We need this for autoscaling @@ -1765,6 +1765,16 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements }; } } + + + private validateTargetGroup(): string[] { + const errors = new Array(); + if (this.hasCalledScaleOnRequestCount && this.targetGroupArns.length > 1) { + errors.push('Cannon use multiple target groups if `scaleOnRequestCount()` is being used.'); + } + + return errors; + } } /** diff --git a/packages/@aws-cdk/aws-autoscaling/package.json b/packages/@aws-cdk/aws-autoscaling/package.json index 24a847e983fb2..91cbf8992ccd5 100644 --- a/packages/@aws-cdk/aws-autoscaling/package.json +++ b/packages/@aws-cdk/aws-autoscaling/package.json @@ -82,10 +82,11 @@ "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/cloud-assembly-schema": "0.0.0", "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", "jest": "^27.5.1" diff --git a/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts b/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts index 553ed50b81dc4..ca1b88e2f2722 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts +++ b/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts @@ -2,6 +2,7 @@ import { Annotations, Match, Template } from '@aws-cdk/assertions'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import { AmazonLinuxCpuType, AmazonLinuxGeneration, AmazonLinuxImage, InstanceType, LaunchTemplate } from '@aws-cdk/aws-ec2'; +import { ApplicationListener, ApplicationLoadBalancer, ApplicationTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; import * as iam from '@aws-cdk/aws-iam'; import * as sns from '@aws-cdk/aws-sns'; import { testDeprecated } from '@aws-cdk/cdk-build-tools'; @@ -1864,6 +1865,61 @@ describe('auto scaling group', () => { })).not.toThrow(); }); + + describe('multiple target groups', () => { + let asg: autoscaling.AutoScalingGroup; + let stack: cdk.Stack; + let vpc: ec2.IVpc; + let alb: ApplicationLoadBalancer; + let listener: ApplicationListener; + + beforeEach(() => { + stack = new cdk.Stack(undefined, 'MyStack', { env: { region: 'us-east-1', account: '1234' } }); + vpc = mockVpc(stack); + alb = new ApplicationLoadBalancer(stack, 'alb', { + vpc, + internetFacing: true, + }); + + listener = alb.addListener('Listener', { + port: 80, + open: true, + }); + + asg = new autoscaling.AutoScalingGroup(stack, 'MyFleet', { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.MICRO), + machineImage: new ec2.AmazonLinuxImage(), + vpc, + }); + }); + + test('Adding two application target groups should succeed validation', () => { + const atg1 = new ApplicationTargetGroup(stack, 'ATG1', { port: 443 }); + const atg2 = new ApplicationTargetGroup(stack, 'ATG2', { port: 443 }); + + listener.addTargetGroups('tgs', { targetGroups: [atg1, atg2] }); + + asg.attachToApplicationTargetGroup(atg1); + asg.attachToApplicationTargetGroup(atg2); + + expect(asg.node.validate()).toEqual([]); + }); + + test('Adding two application target groups should fail validation validate if `scaleOnRequestCount()` has been called', () => { + const atg1 = new ApplicationTargetGroup(stack, 'ATG1', { port: 443 }); + const atg2 = new ApplicationTargetGroup(stack, 'ATG2', { port: 443 }); + + listener.addTargetGroups('tgs', { targetGroups: [atg1, atg2] }); + + asg.attachToApplicationTargetGroup(atg1); + asg.attachToApplicationTargetGroup(atg2); + + asg.scaleOnRequestCount('requests-per-minute', { targetRequestsPerMinute: 60 }); + + expect(asg.node.validate()).toContainEqual('Cannon use multiple target groups if `scaleOnRequestCount()` is being used.'); + }); + }); + }); function mockVpc(stack: cdk.Stack) { diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json new file mode 100644 index 0000000000000..57e75754f5e88 --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "LambdaTestDefaultTestDeployAssert1AF2B360.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-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.template.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.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-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.assets.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.assets.json similarity index 62% rename from packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.assets.json rename to packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.assets.json index ecc9fe25929b4..2f0cf30035fc5 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.assets.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.assets.json @@ -1,15 +1,15 @@ { - "version": "20.0.0", + "version": "22.0.0", "files": { - "3294a2beef1e4a711276251bf311cdf22b70152f30241f0d155898e2ab9ad091": { + "6e4ba6d1c10cb8a0be78abd30ef94d231f8913f1cd4b02c0b62b8626f3425c00": { "source": { - "path": "integ-user-pool-signup-code.template.json", + "path": "aws-cdk-asg-atg-integ.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3294a2beef1e4a711276251bf311cdf22b70152f30241f0d155898e2ab9ad091.json", + "objectKey": "6e4ba6d1c10cb8a0be78abd30ef94d231f8913f1cd4b02c0b62b8626f3425c00.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-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.template.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.template.json new file mode 100644 index 0000000000000..e05bb77369716 --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-atg-integ.template.json @@ -0,0 +1,710 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC" + ] + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet2EIP4947BC00": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2NATGateway3C070193": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet2EIP4947BC00", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ] + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "VPCPrivateSubnet2SubnetCFCDAA7A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTable0A19E10E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTableAssociation0C73D413": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "VPCPrivateSubnet2DefaultRouteF4F5CFD2": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "alb8A8B13C2": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ], + "Type": "application" + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC", + "VPCPublicSubnet2DefaultRouteB7481BBA", + "VPCPublicSubnet2RouteTableAssociation5A808732" + ] + }, + "albSecurityGroup49866104": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB awscdkasgatgintegalbAE8C693C", + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "albSecurityGrouptoawscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C443B02D0421": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + }, + "FromPort": 443, + "ToPort": 443 + } + }, + "albListener3EA0B2EF": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "ForwardConfig": { + "TargetGroups": [ + { + "TargetGroupArn": { + "Ref": "ATG17CFF5455" + }, + "Weight": 1 + }, + { + "TargetGroupArn": { + "Ref": "ATG2A54F3827" + }, + "Weight": 1 + } + ] + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "alb8A8B13C2" + }, + "Port": 80, + "Protocol": "HTTP" + } + }, + "AsgInstanceSecurityGroupC53F1492": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/Asg" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "AsgInstanceSecurityGroupfromawscdkasgatgintegalbSecurityGroup3EC708D0443E9585EF6": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "FromPort": 443, + "GroupId": { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + }, + "ToPort": 443 + } + }, + "AsgInstanceRole7946982D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-asg-atg-integ/Asg" + } + ] + } + }, + "AsgInstanceProfileBCEDB827": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "AsgInstanceRole7946982D" + } + ] + } + }, + "AsgLaunchConfig6D4F96BB": { + "Type": "AWS::AutoScaling::LaunchConfiguration", + "Properties": { + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.micro", + "IamInstanceProfile": { + "Ref": "AsgInstanceProfileBCEDB827" + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "DependsOn": [ + "AsgInstanceRole7946982D" + ] + }, + "AsgASGD1D7B4E2": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "MaxSize": "1", + "MinSize": "1", + "LaunchConfigurationName": { + "Ref": "AsgLaunchConfig6D4F96BB" + }, + "Tags": [ + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "aws-cdk-asg-atg-integ/Asg" + } + ], + "TargetGroupARNs": [ + { + "Ref": "ATG17CFF5455" + }, + { + "Ref": "ATG2A54F3827" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ] + }, + "UpdatePolicy": { + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "ATG17CFF5455": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 443, + "Protocol": "HTTPS", + "TargetGroupAttributes": [ + { + "Key": "stickiness.enabled", + "Value": "false" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "ATG2A54F3827": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 443, + "Protocol": "HTTPS", + "TargetGroupAttributes": [ + { + "Key": "stickiness.enabled", + "Value": "false" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-integ.assets.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-integ.assets.json index 9ac85f9ce2ba2..6265dba737ebc 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-integ.assets.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/aws-cdk-asg-integ.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { "66b1b9cec9c1b972779161099a4b8310affc4106b7e751a3032a397c09e1c9f0": { "source": { diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/cdk.out b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/cdk.out index 8ecc185e9dbee..145739f539580 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/integ.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/integ.json index a5777c505cdc6..40b3938d6a745 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/integ.json @@ -1,14 +1,13 @@ { - "version": "21.0.0", + "version": "22.0.0", "testCases": { - "integ.asg-w-elbv2": { + "LambdaTest/DefaultTest": { "stacks": [ - "aws-cdk-asg-integ" + "aws-cdk-asg-integ", + "aws-cdk-asg-atg-integ" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "LambdaTest/DefaultTest/DeployAssert", + "assertionStackName": "LambdaTestDefaultTestDeployAssert1AF2B360" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/manifest.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/manifest.json index 0f9edacc60c14..14f2cddea1732 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-asg-integ.assets": { "type": "cdk:asset-manifest", "properties": { @@ -269,6 +263,334 @@ ] }, "displayName": "aws-cdk-asg-integ" + }, + "aws-cdk-asg-atg-integ.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-asg-atg-integ.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-asg-atg-integ": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-asg-atg-integ.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}/6e4ba6d1c10cb8a0be78abd30ef94d231f8913f1cd4b02c0b62b8626f3425c00.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-asg-atg-integ.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-asg-atg-integ.assets" + ], + "metadata": { + "/aws-cdk-asg-atg-integ/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1SubnetB4246D30" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableFEE4B781" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableAssociation0B0896DC" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1DefaultRoute91CEF279" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1EIP6AD938E8" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1NATGatewayE0556630" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2Subnet74179F39" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTable6F1A15F1" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2RouteTableAssociation5A808732" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2DefaultRouteB7481BBA" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2EIP4947BC00" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet2NATGateway3C070193" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableBE8A6027" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableAssociation347902D1" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1DefaultRouteAE1D6490" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTable0A19E10E" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2RouteTableAssociation0C73D413" + } + ], + "/aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet2DefaultRouteF4F5CFD2" + } + ], + "/aws-cdk-asg-atg-integ/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/aws-cdk-asg-atg-integ/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/aws-cdk-asg-atg-integ/alb/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "alb8A8B13C2" + } + ], + "/aws-cdk-asg-atg-integ/alb/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "albSecurityGroup49866104" + } + ], + "/aws-cdk-asg-atg-integ/alb/SecurityGroup/to awscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C:443": [ + { + "type": "aws:cdk:logicalId", + "data": "albSecurityGrouptoawscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C443B02D0421" + } + ], + "/aws-cdk-asg-atg-integ/alb/Listener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "albListener3EA0B2EF" + } + ], + "/aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgInstanceSecurityGroupC53F1492" + } + ], + "/aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup/from awscdkasgatgintegalbSecurityGroup3EC708D0:443": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgInstanceSecurityGroupfromawscdkasgatgintegalbSecurityGroup3EC708D0443E9585EF6" + } + ], + "/aws-cdk-asg-atg-integ/Asg/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgInstanceRole7946982D" + } + ], + "/aws-cdk-asg-atg-integ/Asg/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgInstanceProfileBCEDB827" + } + ], + "/aws-cdk-asg-atg-integ/Asg/LaunchConfig": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgLaunchConfig6D4F96BB" + } + ], + "/aws-cdk-asg-atg-integ/Asg/ASG": [ + { + "type": "aws:cdk:logicalId", + "data": "AsgASGD1D7B4E2" + } + ], + "/aws-cdk-asg-atg-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/aws-cdk-asg-atg-integ/ATG1": [ + { + "type": "aws:cdk:warning", + "data": "When creating an empty TargetGroup, you should specify a 'targetType' (this warning may become an error in the future)." + } + ], + "/aws-cdk-asg-atg-integ/ATG1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ATG17CFF5455" + } + ], + "/aws-cdk-asg-atg-integ/ATG2": [ + { + "type": "aws:cdk:warning", + "data": "When creating an empty TargetGroup, you should specify a 'targetType' (this warning may become an error in the future)." + } + ], + "/aws-cdk-asg-atg-integ/ATG2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ATG2A54F3827" + } + ], + "/aws-cdk-asg-atg-integ/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-asg-atg-integ/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-asg-atg-integ" + }, + "LambdaTestDefaultTestDeployAssert1AF2B360.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "LambdaTestDefaultTestDeployAssert1AF2B360.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "LambdaTestDefaultTestDeployAssert1AF2B360": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "LambdaTestDefaultTestDeployAssert1AF2B360.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": [ + "LambdaTestDefaultTestDeployAssert1AF2B360.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": [ + "LambdaTestDefaultTestDeployAssert1AF2B360.assets" + ], + "metadata": { + "/LambdaTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/LambdaTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "LambdaTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/tree.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/tree.json index 1f1936c2e188d..d9026b2de3166 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.140" - } - }, "aws-cdk-asg-integ": { "id": "aws-cdk-asg-integ", "path": "aws-cdk-asg-integ", @@ -736,6 +728,14 @@ "id": "InstanceRole", "path": "aws-cdk-asg-integ/Fleet/InstanceRole", "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-asg-integ/Fleet/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-asg-integ/Fleet/InstanceRole/Resource", @@ -1152,12 +1152,1222 @@ "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationLoadBalancer", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-asg-integ/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-asg-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" } + }, + "aws-cdk-asg-atg-integ": { + "id": "aws-cdk-asg-atg-integ", + "path": "aws-cdk-asg-atg-integ", + "children": { + "VPC": { + "id": "VPC", + "path": "aws-cdk-asg-atg-integ/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "allocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "subnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, + "allocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet2EIP4947BC00", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-asg-atg-integ/VPC/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet2NATGateway3C070193" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-cdk-asg-atg-integ/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-cdk-asg-atg-integ/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.Vpc", + "version": "0.0.0" + } + }, + "alb": { + "id": "alb", + "path": "aws-cdk-asg-atg-integ/alb", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/alb/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "aws:cdk:cloudformation:props": { + "loadBalancerAttributes": [ + { + "key": "deletion_protection.enabled", + "value": "false" + } + ], + "scheme": "internet-facing", + "securityGroups": [ + { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + ], + "type": "application" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnLoadBalancer", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-cdk-asg-atg-integ/alb/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/alb/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "Automatically created Security Group for ELB awscdkasgatgintegalbAE8C693C", + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "tcp", + "fromPort": 80, + "toPort": 80, + "description": "Allow from anyone on port 80" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "to awscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C:443": { + "id": "to awscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C:443", + "path": "aws-cdk-asg-atg-integ/alb/SecurityGroup/to awscdkasgatgintegAsgInstanceSecurityGroupE6EC7F0C:443", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupEgress", + "aws:cdk:cloudformation:props": { + "groupId": { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + }, + "ipProtocol": "tcp", + "description": "Load balancer to target", + "destinationSecurityGroupId": { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + }, + "fromPort": 443, + "toPort": 443 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupEgress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Listener": { + "id": "Listener", + "path": "aws-cdk-asg-atg-integ/alb/Listener", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/alb/Listener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "defaultActions": [ + { + "type": "forward", + "forwardConfig": { + "targetGroups": [ + { + "targetGroupArn": { + "Ref": "ATG17CFF5455" + }, + "weight": 1 + }, + { + "targetGroupArn": { + "Ref": "ATG2A54F3827" + }, + "weight": 1 + } + ] + } + } + ], + "loadBalancerArn": { + "Ref": "alb8A8B13C2" + }, + "port": 80, + "protocol": "HTTP" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnListener", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationListener", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationLoadBalancer", + "version": "0.0.0" + } + }, + "Asg": { + "id": "Asg", + "path": "aws-cdk-asg-atg-integ/Asg", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/Asg" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "from awscdkasgatgintegalbSecurityGroup3EC708D0:443": { + "id": "from awscdkasgatgintegalbSecurityGroup3EC708D0:443", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceSecurityGroup/from awscdkasgatgintegalbSecurityGroup3EC708D0:443", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupIngress", + "aws:cdk:cloudformation:props": { + "ipProtocol": "tcp", + "description": "Load balancer to target", + "fromPort": 443, + "groupId": { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + }, + "sourceSecurityGroupId": { + "Fn::GetAtt": [ + "albSecurityGroup49866104", + "GroupId" + ] + }, + "toPort": 443 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/Asg" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "aws-cdk-asg-atg-integ/Asg/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "AsgInstanceRole7946982D" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "LaunchConfig": { + "id": "LaunchConfig", + "path": "aws-cdk-asg-atg-integ/Asg/LaunchConfig", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::LaunchConfiguration", + "aws:cdk:cloudformation:props": { + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.micro", + "iamInstanceProfile": { + "Ref": "AsgInstanceProfileBCEDB827" + }, + "securityGroups": [ + { + "Fn::GetAtt": [ + "AsgInstanceSecurityGroupC53F1492", + "GroupId" + ] + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-autoscaling.CfnLaunchConfiguration", + "version": "0.0.0" + } + }, + "ASG": { + "id": "ASG", + "path": "aws-cdk-asg-atg-integ/Asg/ASG", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::AutoScalingGroup", + "aws:cdk:cloudformation:props": { + "maxSize": "1", + "minSize": "1", + "launchConfigurationName": { + "Ref": "AsgLaunchConfig6D4F96BB" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-asg-atg-integ/Asg", + "propagateAtLaunch": true + } + ], + "targetGroupArns": [ + { + "Ref": "ATG17CFF5455" + }, + { + "Ref": "ATG2A54F3827" + } + ], + "vpcZoneIdentifier": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-autoscaling.CfnAutoScalingGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-autoscaling.AutoScalingGroup", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "aws-cdk-asg-atg-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "aws-cdk-asg-atg-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "ATG1": { + "id": "ATG1", + "path": "aws-cdk-asg-atg-integ/ATG1", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/ATG1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "port": 443, + "protocol": "HTTPS", + "targetGroupAttributes": [ + { + "key": "stickiness.enabled", + "value": "false" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnTargetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationTargetGroup", + "version": "0.0.0" + } + }, + "ATG2": { + "id": "ATG2", + "path": "aws-cdk-asg-atg-integ/ATG2", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-asg-atg-integ/ATG2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "aws:cdk:cloudformation:props": { + "port": 443, + "protocol": "HTTPS", + "targetGroupAttributes": [ + { + "key": "stickiness.enabled", + "value": "false" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnTargetGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationTargetGroup", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-asg-atg-integ/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-asg-atg-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "LambdaTest": { + "id": "LambdaTest", + "path": "LambdaTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "LambdaTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "LambdaTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.168" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "LambdaTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "LambdaTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "LambdaTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "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" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.168" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.ts b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.ts index 71f484df99b49..e949b58b17f84 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.ts +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.ts @@ -1,40 +1,97 @@ #!/usr/bin/env node import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; +import { ListenerAction } from '@aws-cdk/aws-elasticloadbalancingv2'; import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { Construct } from 'constructs'; import * as autoscaling from '../lib'; -const app = new cdk.App(); -const stack = new cdk.Stack(app, 'aws-cdk-asg-integ'); +class ElbV2AsgStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); -const vpc = new ec2.Vpc(stack, 'VPC', { - maxAzs: 2, -}); + const vpc = new ec2.Vpc(this, 'VPC', { + maxAzs: 2, + }); -const asg = new autoscaling.AutoScalingGroup(stack, 'Fleet', { - vpc, - instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), - machineImage: new ec2.AmazonLinuxImage(), -}); + const asg = new autoscaling.AutoScalingGroup(this, 'Fleet', { + vpc, + instanceType: ec2.InstanceType.of( + ec2.InstanceClass.BURSTABLE2, + ec2.InstanceSize.MICRO, + ), + machineImage: new ec2.AmazonLinuxImage(), + }); -const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { - vpc, - internetFacing: true, -}); + const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { + vpc, + internetFacing: true, + }); -const listener = lb.addListener('Listener', { - port: 80, -}); + const listener = lb.addListener('Listener', { + port: 80, + }); -listener.addTargets('Target', { - port: 80, - targets: [asg], -}); + listener.addTargets('Target', { + port: 80, + targets: [asg], + }); -listener.connections.allowDefaultPortFromAnyIpv4('Open to the world'); + listener.connections.allowDefaultPortFromAnyIpv4('Open to the world'); -asg.scaleOnRequestCount('AModestLoad', { - targetRequestsPerSecond: 1, -}); + asg.scaleOnRequestCount('AModestLoad', { + targetRequestsPerSecond: 1, + }); + } +} -app.synth(); +class ElbV2AsgAtgStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + const vpc = new ec2.Vpc(this, 'VPC', { + maxAzs: 2, + }); + const alb = new elbv2.ApplicationLoadBalancer(this, 'alb', { + vpc, + internetFacing: true, + }); + const listener = alb.addListener('Listener', { + port: 80, + open: true, + }); + + const asg = new autoscaling.AutoScalingGroup(this, 'Asg', { + vpc, + instanceType: new ec2.InstanceType('t3.micro'), + machineImage: new ec2.AmazonLinuxImage(), + }); + + const atg1 = new elbv2.ApplicationTargetGroup(this, 'ATG1', { + port: 443, + vpc, + }); + const atg2 = new elbv2.ApplicationTargetGroup(this, 'ATG2', { + port: 443, + vpc, + }); + + listener.addAction('tgs', { + action: ListenerAction.weightedForward([ + { targetGroup: atg1, weight: 1 }, + { targetGroup: atg2, weight: 1 }, + ]), + }); + + asg.attachToApplicationTargetGroup(atg1); + asg.attachToApplicationTargetGroup(atg2); + } +} +const app = new cdk.App(); + +new integ.IntegTest(app, 'LambdaTest', { + testCases: [ + new ElbV2AsgStack(app, 'aws-cdk-asg-integ'), + new ElbV2AsgAtgStack(app, 'aws-cdk-asg-atg-integ'), + ], +}); diff --git a/packages/@aws-cdk/aws-cloudformation/package.json b/packages/@aws-cdk/aws-cloudformation/package.json index e77fc63a8af4a..ebeda6f56846a 100644 --- a/packages/@aws-cdk/aws-cloudformation/package.json +++ b/packages/@aws-cdk/aws-cloudformation/package.json @@ -78,6 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json new file mode 100644 index 0000000000000..a513dc6283811 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "DependsOnTestDefaultTestDeployAssert3B3B50E2.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-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.template.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.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-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts new file mode 100644 index 0000000000000..9bbf5854684b6 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.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-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js new file mode 100644 index 0000000000000..d8d501f248a23 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.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-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts new file mode 100644 index 0000000000000..1bb38a9f3d774 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.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-cloudformation/test/core-deps.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/integ.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/integ.json new file mode 100644 index 0000000000000..46d61a98f2f47 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "21.0.0", + "testCases": { + "DependsOnTest/DefaultTest": { + "stacks": [ + "replace-depends-on-test", + "nested-stack-depends-test" + ], + "assertionStack": "DependsOnTest/DefaultTest/DeployAssert", + "assertionStackName": "DependsOnTestDefaultTestDeployAssert3B3B50E2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..158178cf68b01 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/manifest.json @@ -0,0 +1,224 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "replace-depends-on-test.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "replace-depends-on-test.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "replace-depends-on-test": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "replace-depends-on-test.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}/57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "replace-depends-on-test.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": [ + "replace-depends-on-test.assets" + ], + "metadata": { + "/replace-depends-on-test/MyLambda/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaServiceRole4539ECB6" + } + ], + "/replace-depends-on-test/MyLambda/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaCCE802FB" + } + ], + "/replace-depends-on-test/MyLambda/LogRetention/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaLogRetention48BA931C" + } + ], + "/replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ], + "/replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A" + } + ], + "/replace-depends-on-test/CustomPolicy": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomPolicy" + } + ], + "/replace-depends-on-test/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/replace-depends-on-test/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "replace-depends-on-test" + }, + "nested-stack-depends-test.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "nested-stack-depends-test.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "nested-stack-depends-test": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "nested-stack-depends-test.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}/c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "nested-stack-depends-test.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": [ + "nested-stack-depends-test.assets" + ], + "metadata": { + "/nested-stack-depends-test/Stack1/Lambda1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda1ServiceRoleF188C4B8" + } + ], + "/nested-stack-depends-test/Stack1/Lambda1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda1DB8E9965" + } + ], + "/nested-stack-depends-test/Stack1.NestedStack/Stack1.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack1NestedStackStack1NestedStackResource256CB8C4" + } + ], + "/nested-stack-depends-test/Stack2/Lambda2/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda2ServiceRole31A072E1" + } + ], + "/nested-stack-depends-test/Stack2/Lambda2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda217CFB423" + } + ], + "/nested-stack-depends-test/Stack2.NestedStack/Stack2.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack2NestedStackStack2NestedStackResource9F0678CF" + } + ], + "/nested-stack-depends-test/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/nested-stack-depends-test/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "nested-stack-depends-test" + }, + "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "DependsOnTestDefaultTestDeployAssert3B3B50E2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "DependsOnTestDefaultTestDeployAssert3B3B50E2.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": [ + "DependsOnTestDefaultTestDeployAssert3B3B50E2.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": [ + "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets" + ], + "metadata": { + "/DependsOnTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/DependsOnTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "DependsOnTest/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.assets.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.assets.json new file mode 100644 index 0000000000000..7f73a85d9077c --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.assets.json @@ -0,0 +1,45 @@ +{ + "version": "21.0.0", + "files": { + "d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2": { + "source": { + "path": "nestedstackdependstestStack1DE6783D8.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431": { + "source": { + "path": "nestedstackdependstestStack2A36722CF.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a": { + "source": { + "path": "nested-stack-depends-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a.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-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.template.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.template.json new file mode 100644 index 0000000000000..cf6d4b0d46cee --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nested-stack-depends-test.template.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "Stack1NestedStackStack1NestedStackResource256CB8C4": { + "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}" + }, + "/d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json" + ] + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Stack2NestedStackStack2NestedStackResource9F0678CF": { + "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}" + }, + "/caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json" + ] + ] + } + }, + "DependsOn": [ + "Stack1NestedStackStack1NestedStackResource256CB8C4" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json new file mode 100644 index 0000000000000..8b39a08a02151 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "Lambda1ServiceRoleF188C4B8": { + "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" + ] + ] + } + ] + } + }, + "Lambda1DB8E9965": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "Lambda1ServiceRoleF188C4B8", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "Lambda1ServiceRoleF188C4B8" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json new file mode 100644 index 0000000000000..d1b0202b0afc1 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "Lambda2ServiceRole31A072E1": { + "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" + ] + ] + } + ] + } + }, + "Lambda217CFB423": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "Lambda2ServiceRole31A072E1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "Lambda2ServiceRole31A072E1" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.assets.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.assets.json new file mode 100644 index 0000000000000..e2083cbfc507f --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "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}" + } + } + }, + "57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af": { + "source": { + "path": "replace-depends-on-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af.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-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.template.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.template.json new file mode 100644 index 0000000000000..5574a9b261d30 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/replace-depends-on-test.template.json @@ -0,0 +1,188 @@ +{ + "Resources": { + "MyLambdaServiceRole4539ECB6": { + "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" + ] + ] + } + ] + } + }, + "MyLambdaCCE802FB": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyLambdaServiceRole4539ECB6" + ] + }, + "MyLambdaLogRetention48BA931C": { + "Type": "Custom::LogRetention", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn" + ] + }, + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "MyLambdaCCE802FB" + } + ] + ] + }, + "RetentionInDays": 1 + } + }, + "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" + ] + ] + } + ] + } + }, + "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": [ + "CustomPolicy", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + ] + }, + "CustomPolicy": { + "Type": "AWS::IAM::ManagedPolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + } + }, + "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-cloudformation/test/core-deps.integ.snapshot/tree.json b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/tree.json new file mode 100644 index 0000000000000..9b65fee29f707 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-deps.integ.snapshot/tree.json @@ -0,0 +1,582 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + }, + "replace-depends-on-test": { + "id": "replace-depends-on-test", + "path": "replace-depends-on-test", + "children": { + "MyLambda": { + "id": "MyLambda", + "path": "replace-depends-on-test/MyLambda", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "replace-depends-on-test/MyLambda/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "LogRetention": { + "id": "LogRetention", + "path": "replace-depends-on-test/MyLambda/LogRetention", + "children": { + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/LogRetention/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-logs.LogRetention", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "replace-depends-on-test/MyLambda/LogGroup", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a": { + "id": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "children": { + "Code": { + "id": "Code", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "replace-depends-on-test/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": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + }, + "CustomPolicy": { + "id": "CustomPolicy", + "path": "replace-depends-on-test/CustomPolicy", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::ManagedPolicy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnManagedPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "nested-stack-depends-test": { + "id": "nested-stack-depends-test", + "path": "nested-stack-depends-test", + "children": { + "Stack1": { + "id": "Stack1", + "path": "nested-stack-depends-test/Stack1", + "children": { + "Lambda1": { + "id": "Lambda1", + "path": "nested-stack-depends-test/Stack1/Lambda1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "nested-stack-depends-test/Stack1/Lambda1/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack1/Lambda1/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack1/Lambda1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "Lambda1ServiceRoleF188C4B8", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "Stack1.NestedStack": { + "id": "Stack1.NestedStack", + "path": "nested-stack-depends-test/Stack1.NestedStack", + "children": { + "Stack1.NestedStackResource": { + "id": "Stack1.NestedStackResource", + "path": "nested-stack-depends-test/Stack1.NestedStack/Stack1.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + }, + "Stack2": { + "id": "Stack2", + "path": "nested-stack-depends-test/Stack2", + "children": { + "Lambda2": { + "id": "Lambda2", + "path": "nested-stack-depends-test/Stack2/Lambda2", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "nested-stack-depends-test/Stack2/Lambda2/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack2/Lambda2/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack2/Lambda2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "Lambda2ServiceRole31A072E1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "Stack2.NestedStack": { + "id": "Stack2.NestedStack", + "path": "nested-stack-depends-test/Stack2.NestedStack", + "children": { + "Stack2.NestedStackResource": { + "id": "Stack2.NestedStackResource", + "path": "nested-stack-depends-test/Stack2.NestedStack/Stack2.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "DependsOnTest": { + "id": "DependsOnTest", + "path": "DependsOnTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "DependsOnTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "DependsOnTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "DependsOnTest/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-cloudformation/test/deps.test.ts b/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts index 980f17ef6fcb9..0dbb1a9c5ec1b 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts @@ -15,7 +15,7 @@ describe('resource dependencies', () => { const r2 = new CfnResource(stack, 'r2', { type: 'r2' }); // WHEN - r1.addDependsOn(r2); + r1.addDependency(r2); // THEN expect(app.synth().getStackArtifact(stack.artifactId).template?.Resources).toEqual({ @@ -304,7 +304,7 @@ describe('stack dependencies', () => { * Given a test function which sets the stage and verifies a dependency scenario * between two CloudFormation resources, returns two tests which exercise both * "construct dependency" (i.e. node.addDependency) and "resource dependency" - * (i.e. resource.addDependsOn). + * (i.e. resource.addDependency). * * @param testFunction The test function */ @@ -314,7 +314,7 @@ function matrixForResourceDependencyTest(testFunction: (addDep: (source: CfnReso testFunction((source, target) => source.node.addDependency(target)); }); test('resource dependency', () => { - testFunction((source, target) => source.addDependsOn(target)); + testFunction((source, target) => source.addDependency(target)); }); }; } diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json new file mode 100644 index 0000000000000..a513dc6283811 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "DependsOnTestDefaultTestDeployAssert3B3B50E2.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-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.template.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/DependsOnTestDefaultTestDeployAssert3B3B50E2.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-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.d.ts new file mode 100644 index 0000000000000..9bbf5854684b6 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.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-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.js new file mode 100644 index 0000000000000..d8d501f248a23 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.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-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/asset.d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347/index.ts new file mode 100644 index 0000000000000..1bb38a9f3d774 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.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-cloudformation/test/integ.core-deps.js.snapshot/cdk.out b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/integ.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/integ.json new file mode 100644 index 0000000000000..46d61a98f2f47 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "21.0.0", + "testCases": { + "DependsOnTest/DefaultTest": { + "stacks": [ + "replace-depends-on-test", + "nested-stack-depends-test" + ], + "assertionStack": "DependsOnTest/DefaultTest/DeployAssert", + "assertionStackName": "DependsOnTestDefaultTestDeployAssert3B3B50E2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/manifest.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/manifest.json new file mode 100644 index 0000000000000..f546ab43d55c3 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/manifest.json @@ -0,0 +1,224 @@ +{ + "version": "21.0.0", + "artifacts": { + "replace-depends-on-test.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "replace-depends-on-test.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "replace-depends-on-test": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "replace-depends-on-test.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}/57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "replace-depends-on-test.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": [ + "replace-depends-on-test.assets" + ], + "metadata": { + "/replace-depends-on-test/MyLambda/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaServiceRole4539ECB6" + } + ], + "/replace-depends-on-test/MyLambda/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaCCE802FB" + } + ], + "/replace-depends-on-test/MyLambda/LogRetention/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaLogRetention48BA931C" + } + ], + "/replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ], + "/replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A" + } + ], + "/replace-depends-on-test/CustomPolicy": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomPolicy" + } + ], + "/replace-depends-on-test/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/replace-depends-on-test/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "replace-depends-on-test" + }, + "nested-stack-depends-test.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "nested-stack-depends-test.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "nested-stack-depends-test": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "nested-stack-depends-test.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}/c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "nested-stack-depends-test.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": [ + "nested-stack-depends-test.assets" + ], + "metadata": { + "/nested-stack-depends-test/Stack1/Lambda1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda1ServiceRoleF188C4B8" + } + ], + "/nested-stack-depends-test/Stack1/Lambda1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda1DB8E9965" + } + ], + "/nested-stack-depends-test/Stack1.NestedStack/Stack1.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack1NestedStackStack1NestedStackResource256CB8C4" + } + ], + "/nested-stack-depends-test/Stack2/Lambda2/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda2ServiceRole31A072E1" + } + ], + "/nested-stack-depends-test/Stack2/Lambda2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Lambda217CFB423" + } + ], + "/nested-stack-depends-test/Stack2.NestedStack/Stack2.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack2NestedStackStack2NestedStackResource9F0678CF" + } + ], + "/nested-stack-depends-test/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/nested-stack-depends-test/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "nested-stack-depends-test" + }, + "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "DependsOnTestDefaultTestDeployAssert3B3B50E2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "DependsOnTestDefaultTestDeployAssert3B3B50E2.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": [ + "DependsOnTestDefaultTestDeployAssert3B3B50E2.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": [ + "DependsOnTestDefaultTestDeployAssert3B3B50E2.assets" + ], + "metadata": { + "/DependsOnTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/DependsOnTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "DependsOnTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.assets.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.assets.json new file mode 100644 index 0000000000000..7f73a85d9077c --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.assets.json @@ -0,0 +1,45 @@ +{ + "version": "21.0.0", + "files": { + "d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2": { + "source": { + "path": "nestedstackdependstestStack1DE6783D8.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431": { + "source": { + "path": "nestedstackdependstestStack2A36722CF.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a": { + "source": { + "path": "nested-stack-depends-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c4e1a28f651cf56ff9d696ef9e4ce1c771896e999777d763e55f06b089b7c81a.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-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.template.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.template.json new file mode 100644 index 0000000000000..cf6d4b0d46cee --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nested-stack-depends-test.template.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "Stack1NestedStackStack1NestedStackResource256CB8C4": { + "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}" + }, + "/d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json" + ] + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Stack2NestedStackStack2NestedStackResource9F0678CF": { + "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}" + }, + "/caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json" + ] + ] + } + }, + "DependsOn": [ + "Stack1NestedStackStack1NestedStackResource256CB8C4" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json new file mode 100644 index 0000000000000..8b39a08a02151 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack1DE6783D8.nested.template.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "Lambda1ServiceRoleF188C4B8": { + "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" + ] + ] + } + ] + } + }, + "Lambda1DB8E9965": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "Lambda1ServiceRoleF188C4B8", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "Lambda1ServiceRoleF188C4B8" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json new file mode 100644 index 0000000000000..d1b0202b0afc1 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/nestedstackdependstestStack2A36722CF.nested.template.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "Lambda2ServiceRole31A072E1": { + "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" + ] + ] + } + ] + } + }, + "Lambda217CFB423": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "Lambda2ServiceRole31A072E1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "Lambda2ServiceRole31A072E1" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.assets.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.assets.json new file mode 100644 index 0000000000000..e2083cbfc507f --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "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}" + } + } + }, + "57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af": { + "source": { + "path": "replace-depends-on-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "57d6494f80ed197e8ed81877d3521488a65bc202ee15ffb64f4e58eabff000af.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-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.template.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.template.json new file mode 100644 index 0000000000000..5574a9b261d30 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/replace-depends-on-test.template.json @@ -0,0 +1,188 @@ +{ + "Resources": { + "MyLambdaServiceRole4539ECB6": { + "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" + ] + ] + } + ] + } + }, + "MyLambdaCCE802FB": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyLambdaServiceRole4539ECB6" + ] + }, + "MyLambdaLogRetention48BA931C": { + "Type": "Custom::LogRetention", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn" + ] + }, + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "MyLambdaCCE802FB" + } + ] + ] + }, + "RetentionInDays": 1 + } + }, + "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" + ] + ] + } + ] + } + }, + "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": [ + "CustomPolicy", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + ] + }, + "CustomPolicy": { + "Type": "AWS::IAM::ManagedPolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + } + }, + "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-cloudformation/test/integ.core-deps.js.snapshot/tree.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/tree.json new file mode 100644 index 0000000000000..45159d69f419f --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.js.snapshot/tree.json @@ -0,0 +1,664 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "replace-depends-on-test": { + "id": "replace-depends-on-test", + "path": "replace-depends-on-test", + "children": { + "MyLambda": { + "id": "MyLambda", + "path": "replace-depends-on-test/MyLambda", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "replace-depends-on-test/MyLambda/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "replace-depends-on-test/MyLambda/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "LogRetention": { + "id": "LogRetention", + "path": "replace-depends-on-test/MyLambda/LogRetention", + "children": { + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/MyLambda/LogRetention/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-logs.LogRetention", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "replace-depends-on-test/MyLambda/LogGroup", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a": { + "id": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a", + "children": { + "Code": { + "id": "Code", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "replace-depends-on-test/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": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "replace-depends-on-test/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "CustomPolicy": { + "id": "CustomPolicy", + "path": "replace-depends-on-test/CustomPolicy", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::ManagedPolicy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:DeleteRetentionPolicy", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnManagedPolicy", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "replace-depends-on-test/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "replace-depends-on-test/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "nested-stack-depends-test": { + "id": "nested-stack-depends-test", + "path": "nested-stack-depends-test", + "children": { + "Stack1": { + "id": "Stack1", + "path": "nested-stack-depends-test/Stack1", + "children": { + "Lambda1": { + "id": "Lambda1", + "path": "nested-stack-depends-test/Stack1/Lambda1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "nested-stack-depends-test/Stack1/Lambda1/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "nested-stack-depends-test/Stack1/Lambda1/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack1/Lambda1/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack1/Lambda1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "Lambda1ServiceRoleF188C4B8", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "Stack1.NestedStack": { + "id": "Stack1.NestedStack", + "path": "nested-stack-depends-test/Stack1.NestedStack", + "children": { + "Stack1.NestedStackResource": { + "id": "Stack1.NestedStackResource", + "path": "nested-stack-depends-test/Stack1.NestedStack/Stack1.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/d80f241007964c163f30b1e491fb22d85422a376901bdf57f34ef94d71dcf4a2.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "Stack2": { + "id": "Stack2", + "path": "nested-stack-depends-test/Stack2", + "children": { + "Lambda2": { + "id": "Lambda2", + "path": "nested-stack-depends-test/Stack2/Lambda2", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "nested-stack-depends-test/Stack2/Lambda2/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "nested-stack-depends-test/Stack2/Lambda2/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack2/Lambda2/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" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "nested-stack-depends-test/Stack2/Lambda2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "Lambda2ServiceRole31A072E1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "Stack2.NestedStack": { + "id": "Stack2.NestedStack", + "path": "nested-stack-depends-test/Stack2.NestedStack", + "children": { + "Stack2.NestedStackResource": { + "id": "Stack2.NestedStackResource", + "path": "nested-stack-depends-test/Stack2.NestedStack/Stack2.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/caff9f6719171b7d0611de54f70e0ef42e8e4f56432babf0d4beae6cb8bba431.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "nested-stack-depends-test/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "nested-stack-depends-test/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "DependsOnTest": { + "id": "DependsOnTest", + "path": "DependsOnTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "DependsOnTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "DependsOnTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "DependsOnTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "DependsOnTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "DependsOnTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "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" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.ts b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.ts new file mode 100644 index 0000000000000..b8ea66419e9cc --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-deps.ts @@ -0,0 +1,74 @@ +/* + * Real replaceDependency use case to test + * + * TestStack verification steps: + * - Deploy with `--no-clean` + * - Verify that the CloudFormation stack LogRetention CfnResource dependencies list CustomPolicy, not DefaultPolicy + * + * TestNestedStack verification steps: + * - Deploy with `--no-clean` + * - Verify that Stack2 lists Stack1 in DependsOn + */ +import * as iam from '@aws-cdk/aws-iam'; +import * as lambda from '@aws-cdk/aws-lambda'; +import { RetentionDays } from '@aws-cdk/aws-logs'; +import { App, Stack, CfnResource, NestedStack } from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { Construct } from 'constructs'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + new lambda.Function(this, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + logRetention: RetentionDays.ONE_DAY, + }); + const logRetentionFunction = this.node.tryFindChild('LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a')!; + const serviceRole = logRetentionFunction.node.tryFindChild('ServiceRole') as iam.Role; + const defaultPolicy = serviceRole.node.tryFindChild('DefaultPolicy')!.node.defaultChild! as iam.CfnPolicy; + const customPolicy = new iam.CfnManagedPolicy(this, 'CustomPolicy', { + policyDocument: defaultPolicy.policyDocument, + roles: defaultPolicy.roles, + }); + const logRetentionResource = logRetentionFunction.node.tryFindChild('Resource') as CfnResource; + // Without replacing the dependency, Cfn will reject the template because it references this non-existent logical id + logRetentionResource.replaceDependency(defaultPolicy, customPolicy); + serviceRole.node.tryRemoveChild('DefaultPolicy'); + } +} + +class TestNestedStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + const stack1 = new NestedStack(this, 'Stack1'); + const stack2 = new NestedStack(this, 'Stack2'); + const resource1 = new lambda.Function(stack1, 'Lambda1', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + }).node.defaultChild! as CfnResource; + const resource2 = new lambda.Function(stack2, 'Lambda2', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + }).node.defaultChild! as CfnResource; + + // The following two statements should cancel each other out + resource1.addDependency(resource2); + resource1.removeDependency(resource2); + + resource2.addDependency(resource1); + } +} + +const app = new App(); +const stack = new TestStack(app, 'replace-depends-on-test'); +const nestedStack = new TestNestedStack(app, 'nested-stack-depends-test'); + +new integ.IntegTest(app, 'DependsOnTest', { + testCases: [stack, nestedStack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-cloudfront/lib/origin-request-policy.ts b/packages/@aws-cdk/aws-cloudfront/lib/origin-request-policy.ts index 2a72736e95e5f..d8a87ffaade7d 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/origin-request-policy.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/origin-request-policy.ts @@ -66,6 +66,8 @@ export class OriginRequestPolicy extends Resource implements IOriginRequestPolic public static readonly ALL_VIEWER = OriginRequestPolicy.fromManagedOriginRequestPolicy('216adef6-5c7f-47e4-b989-5492eafa07d3'); /** This policy is designed for use with an origin that is an AWS Elemental MediaTailor endpoint. */ public static readonly ELEMENTAL_MEDIA_TAILOR = OriginRequestPolicy.fromManagedOriginRequestPolicy('775133bc-15f2-49f9-abea-afb2e0bf67d2'); + /** This policy includes all values (headers, cookies, and query strings) in the viewer request, and all CloudFront headers that were released through June 2022 (CloudFront headers released after June 2022 are not included). */ + public static readonly ALL_VIEWER_AND_CLOUDFRONT_2022 = OriginRequestPolicy.fromManagedOriginRequestPolicy('33f36d7e-f396-46d9-90e0-52428a34d9dc'); /** Imports a Origin Request Policy from its id. */ public static fromOriginRequestPolicyId(scope: Construct, id: string, originRequestPolicyId: string): IOriginRequestPolicy { diff --git a/packages/@aws-cdk/aws-cloudfront/test/origin-request-policy.test.ts b/packages/@aws-cdk/aws-cloudfront/test/origin-request-policy.test.ts index bda5a09058e67..b0fbbd93539c8 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/origin-request-policy.test.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/origin-request-policy.test.ts @@ -108,6 +108,7 @@ test('managed policies are provided', () => { expect(OriginRequestPolicy.CORS_S3_ORIGIN.originRequestPolicyId).toEqual('88a5eaf4-2fd4-4709-b370-b4c650ea3fcf'); expect(OriginRequestPolicy.ALL_VIEWER.originRequestPolicyId).toEqual('216adef6-5c7f-47e4-b989-5492eafa07d3'); expect(OriginRequestPolicy.ELEMENTAL_MEDIA_TAILOR.originRequestPolicyId).toEqual('775133bc-15f2-49f9-abea-afb2e0bf67d2'); + expect(OriginRequestPolicy.ALL_VIEWER_AND_CLOUDFRONT_2022.originRequestPolicyId).toEqual('33f36d7e-f396-46d9-90e0-52428a34d9dc'); }); // OriginRequestCookieBehavior and OriginRequestQueryStringBehavior have identical behavior diff --git a/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts b/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts index 35c0c453cc7c2..0df406088fdb1 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/base-deployment-config.ts @@ -2,8 +2,8 @@ import { ArnFormat, Resource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnDeploymentConfig } from './codedeploy.generated'; import { MinimumHealthyHosts } from './host-health-config'; +import { arnForDeploymentConfig, validateName } from './private/utils'; import { TrafficRouting } from './traffic-routing-config'; -import { arnForDeploymentConfig, validateName } from './utils'; /** * The base class for ServerDeploymentConfig, EcsDeploymentConfig, diff --git a/packages/@aws-cdk/aws-codedeploy/lib/ecs/application.ts b/packages/@aws-cdk/aws-codedeploy/lib/ecs/application.ts index 289a6660c8c4f..9b9173a7d17c0 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/ecs/application.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/ecs/application.ts @@ -1,7 +1,7 @@ -import { ArnFormat, IResource, Resource } from '@aws-cdk/core'; +import { ArnFormat, IResource, Resource, Stack, Arn } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnApplication } from '../codedeploy.generated'; -import { arnForApplication, validateName } from '../utils'; +import { arnForApplication, validateName } from '../private/utils'; /** * Represents a reference to a CodeDeploy Application deploying to Amazon ECS. @@ -42,6 +42,9 @@ export class EcsApplication extends Resource implements IEcsApplication { /** * Import an Application defined either outside the CDK, or in a different CDK Stack. * + * The Application's account and region are assumed to be the same as the stack it is being imported + * into. If not, use `fromEcsApplicationArn`. + * * @param scope the parent Construct for this new Construct * @param id the logical ID of this new Construct * @param ecsApplicationName the name of the application to import @@ -49,13 +52,28 @@ export class EcsApplication extends Resource implements IEcsApplication { */ public static fromEcsApplicationName(scope: Construct, id: string, ecsApplicationName: string): IEcsApplication { class Import extends Resource implements IEcsApplication { - public applicationArn = arnForApplication(ecsApplicationName); + public applicationArn = arnForApplication(Stack.of(scope), ecsApplicationName); public applicationName = ecsApplicationName; } return new Import(scope, id); } + /** + * Import an Application defined either outside the CDK, or in a different CDK Stack, by ARN. + * + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct + * @param ecsApplicationArn the ARN of the application to import + * @returns a Construct representing a reference to an existing Application + */ + public static fromEcsApplicationArn(scope: Construct, id: string, ecsApplicationArn: string): IEcsApplication { + return new class extends Resource implements IEcsApplication { + public applicationArn = ecsApplicationArn; + public applicationName = Arn.split(ecsApplicationArn, ArnFormat.COLON_RESOURCE_NAME).resourceName ?? ''; + } (scope, id, { environmentFromArn: ecsApplicationArn }); + } + public readonly applicationArn: string; public readonly applicationName: string; @@ -70,7 +88,7 @@ export class EcsApplication extends Resource implements IEcsApplication { }); this.applicationName = this.getResourceNameAttribute(resource.ref); - this.applicationArn = this.getResourceArnAttribute(arnForApplication(resource.ref), { + this.applicationArn = this.getResourceArnAttribute(arnForApplication(Stack.of(scope), resource.ref), { service: 'codedeploy', resource: 'application', resourceName: this.physicalName, 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 be6204b4b10ad..32a5552834e3a 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-config.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { BaseDeploymentConfig, BaseDeploymentConfigOptions, ComputePlatform, IBaseDeploymentConfig } from '../base-deployment-config'; +import { deploymentConfig } from '../private/utils'; import { TrafficRouting } from '../traffic-routing-config'; -import { deploymentConfig } from '../utils'; /** * The Deployment Configuration of an ECS Deployment Group. diff --git a/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-group.ts index 762f6210e51c3..02c7e809b4275 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/ecs/deployment-group.ts @@ -5,8 +5,9 @@ import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnDeploymentGroup } from '../codedeploy.generated'; +import { ImportedDeploymentGroupBase, DeploymentGroupBase } from '../private/base-deployment-group'; +import { renderAlarmConfiguration, renderAutoRollbackConfiguration } from '../private/utils'; import { AutoRollbackConfig } from '../rollback-config'; -import { arnForDeploymentGroup, renderAlarmConfiguration, renderAutoRollbackConfiguration, validateName } from '../utils'; import { IEcsApplication, EcsApplication } from './application'; import { EcsDeploymentConfig, IEcsDeploymentConfig } from './deployment-config'; @@ -182,9 +183,11 @@ export interface EcsDeploymentGroupProps { * A CodeDeploy deployment group that orchestrates ECS blue-green deployments. * @resource AWS::CodeDeploy::DeploymentGroup */ -export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGroup { +export class EcsDeploymentGroup extends DeploymentGroupBase implements IEcsDeploymentGroup { /** - * Import an ECS Deployment Group defined outside the CDK app. + * Reference an ECS Deployment Group defined outside the CDK app. + * + * Account and region for the DeploymentGroup are taken from the application. * * @param scope the parent Construct for this new Construct * @param id the logical ID of this new Construct @@ -199,8 +202,6 @@ export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGr } public readonly application: IEcsApplication; - public readonly deploymentGroupName: string; - public readonly deploymentGroupArn: string; public readonly deploymentConfig: IEcsDeploymentConfig; /** * The service Role of this Deployment Group. @@ -211,16 +212,15 @@ export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGr constructor(scope: Construct, id: string, props: EcsDeploymentGroupProps) { super(scope, id, { - physicalName: props.deploymentGroupName, + deploymentGroupName: props.deploymentGroupName, + role: props.role, + roleConstructId: 'ServiceRole', }); + this.role = this._role; this.application = props.application || new EcsApplication(this, 'Application'); this.alarms = props.alarms || []; - this.role = props.role || new iam.Role(this, 'ServiceRole', { - assumedBy: new iam.ServicePrincipal('codedeploy.amazonaws.com'), - }); - this.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeDeployRoleForECS')); this.deploymentConfig = props.deploymentConfig || EcsDeploymentConfig.ALL_AT_ONCE; @@ -261,21 +261,13 @@ export class EcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGr autoRollbackConfiguration: cdk.Lazy.any({ produce: () => renderAutoRollbackConfiguration(this.alarms, props.autoRollback) }), }); - this.deploymentGroupName = this.getResourceNameAttribute(resource.ref); - this.deploymentGroupArn = this.getResourceArnAttribute(arnForDeploymentGroup(this.application.applicationName, resource.ref), { - service: 'codedeploy', - resource: 'deploymentgroup', - resourceName: `${this.application.applicationName}/${this.physicalName}`, - arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, - }); + this._setNameAndArn(resource, this.application); // If the deployment config is a construct, add a dependency to ensure the deployment config // is created before the deployment group is. if (Construct.isConstruct(this.deploymentConfig)) { this.node.addDependency(this.deploymentConfig); } - - this.node.addValidation({ validate: () => validateName('Deployment group', this.physicalName) }); } /** @@ -355,17 +347,17 @@ export interface EcsDeploymentGroupAttributes { readonly deploymentConfig?: IEcsDeploymentConfig; } -class ImportedEcsDeploymentGroup extends cdk.Resource implements IEcsDeploymentGroup { +class ImportedEcsDeploymentGroup extends ImportedDeploymentGroupBase implements IEcsDeploymentGroup { public readonly application: IEcsApplication; - public readonly deploymentGroupName: string; - public readonly deploymentGroupArn: string; public readonly deploymentConfig: IEcsDeploymentConfig; - constructor(scope:Construct, id: string, props: EcsDeploymentGroupAttributes) { - super(scope, id); + constructor(scope: Construct, id: string, props: EcsDeploymentGroupAttributes) { + super(scope, id, { + application: props.application, + deploymentGroupName: props.deploymentGroupName, + }); + this.application = props.application; - this.deploymentGroupName = props.deploymentGroupName; - this.deploymentGroupArn = arnForDeploymentGroup(props.application.applicationName, props.deploymentGroupName); this.deploymentConfig = props.deploymentConfig || EcsDeploymentConfig.ALL_AT_ONCE; } } diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/application.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/application.ts index e0d27f8dabc34..c3c20a5afb2d9 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/application.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/application.ts @@ -1,7 +1,7 @@ -import { ArnFormat, IResource, Resource } from '@aws-cdk/core'; +import { ArnFormat, IResource, Resource, Stack, Arn } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnApplication } from '../codedeploy.generated'; -import { arnForApplication, validateName } from '../utils'; +import { arnForApplication, validateName } from '../private/utils'; /** * Represents a reference to a CodeDeploy Application deploying to AWS Lambda. @@ -42,6 +42,9 @@ export class LambdaApplication extends Resource implements ILambdaApplication { /** * Import an Application defined either outside the CDK, or in a different CDK Stack. * + * The Application's account and region are assumed to be the same as the stack it is being imported + * into. If not, use `fromLambdaApplicationArn`. + * * @param scope the parent Construct for this new Construct * @param id the logical ID of this new Construct * @param lambdaApplicationName the name of the application to import @@ -49,13 +52,28 @@ export class LambdaApplication extends Resource implements ILambdaApplication { */ public static fromLambdaApplicationName(scope: Construct, id: string, lambdaApplicationName: string): ILambdaApplication { class Import extends Resource implements ILambdaApplication { - public applicationArn = arnForApplication(lambdaApplicationName); + public applicationArn = arnForApplication(Stack.of(scope), lambdaApplicationName); public applicationName = lambdaApplicationName; } return new Import(scope, id); } + /** + * Import an Application defined either outside the CDK, or in a different CDK Stack, by ARN. + * + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct + * @param lambdaApplicationArn the ARN of the application to import + * @returns a Construct representing a reference to an existing Application + */ + public static fromLambdaApplicationArn(scope: Construct, id: string, lambdaApplicationArn: string): ILambdaApplication { + return new class extends Resource implements ILambdaApplication { + public applicationArn = lambdaApplicationArn; + public applicationName = Arn.split(lambdaApplicationArn, ArnFormat.COLON_RESOURCE_NAME).resourceName ?? ''; + }(scope, id, { environmentFromArn: lambdaApplicationArn }); + } + public readonly applicationArn: string; public readonly applicationName: string; @@ -70,7 +88,7 @@ export class LambdaApplication extends Resource implements ILambdaApplication { }); this.applicationName = this.getResourceNameAttribute(resource.ref); - this.applicationArn = this.getResourceArnAttribute(arnForApplication(resource.ref), { + this.applicationArn = this.getResourceArnAttribute(arnForApplication(Stack.of(this), resource.ref), { service: 'codedeploy', resource: 'application', resourceName: this.physicalName, 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 fe4ceeb249af2..4a9a6d09e426d 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 @@ -1,7 +1,7 @@ import { Duration, Names, Resource } from '@aws-cdk/core'; import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from '@aws-cdk/custom-resources'; import { Construct } from 'constructs'; -import { arnForDeploymentConfig, validateName } from '../utils'; +import { arnForDeploymentConfig, validateName } from '../private/utils'; import { ILambdaDeploymentConfig } from './deployment-config'; /** 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 a86da3222b5f1..e049ecbe08887 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-config.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { BaseDeploymentConfig, BaseDeploymentConfigOptions, ComputePlatform, IBaseDeploymentConfig } from '../base-deployment-config'; +import { deploymentConfig } from '../private/utils'; import { TrafficRouting } from '../traffic-routing-config'; -import { deploymentConfig } from '../utils'; /** * The Deployment Configuration of a Lambda Deployment Group. diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts index 5968402efdd1f..44f1cd01eded7 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts @@ -4,8 +4,9 @@ import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnDeploymentGroup } from '../codedeploy.generated'; +import { ImportedDeploymentGroupBase, DeploymentGroupBase } from '../private/base-deployment-group'; +import { renderAlarmConfiguration, renderAutoRollbackConfiguration } from '../private/utils'; import { AutoRollbackConfig } from '../rollback-config'; -import { arnForDeploymentGroup, renderAlarmConfiguration, renderAutoRollbackConfiguration, validateName } from '../utils'; import { ILambdaApplication, LambdaApplication } from './application'; import { ILambdaDeploymentConfig, LambdaDeploymentConfig } from './deployment-config'; @@ -120,10 +121,12 @@ export interface LambdaDeploymentGroupProps { /** * @resource AWS::CodeDeploy::DeploymentGroup */ -export class LambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploymentGroup { +export class LambdaDeploymentGroup extends DeploymentGroupBase implements ILambdaDeploymentGroup { /** * Import an Lambda Deployment Group defined either outside the CDK app, or in a different AWS region. * + * Account and region for the DeploymentGroup are taken from the application. + * * @param scope the parent Construct for this new Construct * @param id the logical ID of this new Construct * @param attrs the properties of the referenced Deployment Group @@ -137,9 +140,10 @@ export class LambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploy } public readonly application: ILambdaApplication; - public readonly deploymentGroupName: string; - public readonly deploymentGroupArn: string; public readonly deploymentConfig: ILambdaDeploymentConfig; + /** + * The service Role of this Deployment Group. + */ public readonly role: iam.IRole; private readonly alarms: cloudwatch.IAlarm[]; @@ -148,16 +152,15 @@ export class LambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploy constructor(scope: Construct, id: string, props: LambdaDeploymentGroupProps) { super(scope, id, { - physicalName: props.deploymentGroupName, + deploymentGroupName: props.deploymentGroupName, + role: props.role, + roleConstructId: 'ServiceRole', }); + this.role = this._role; this.application = props.application || new LambdaApplication(this, 'Application'); this.alarms = props.alarms || []; - this.role = props.role || new iam.Role(this, 'ServiceRole', { - assumedBy: new iam.ServicePrincipal('codedeploy.amazonaws.com'), - }); - this.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCodeDeployRoleForLambdaLimited')); this.deploymentConfig = props.deploymentConfig || LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES; @@ -174,13 +177,7 @@ export class LambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploy autoRollbackConfiguration: cdk.Lazy.any({ produce: () => renderAutoRollbackConfiguration(this.alarms, props.autoRollback) }), }); - this.deploymentGroupName = this.getResourceNameAttribute(resource.ref); - this.deploymentGroupArn = this.getResourceArnAttribute(arnForDeploymentGroup(this.application.applicationName, resource.ref), { - service: 'codedeploy', - resource: 'deploymentgroup', - resourceName: `${this.application.applicationName}/${this.physicalName}`, - arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, - }); + this._setNameAndArn(resource, this.application); if (props.preHook) { this.addPreHook(props.preHook); @@ -203,8 +200,6 @@ export class LambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploy if (this.deploymentConfig instanceof Construct) { this.node.addDependency(this.deploymentConfig); } - - this.node.addValidation({ validate: () => validateName('Deployment group', this.physicalName) }); } /** @@ -284,17 +279,17 @@ export interface LambdaDeploymentGroupAttributes { readonly deploymentConfig?: ILambdaDeploymentConfig; } -class ImportedLambdaDeploymentGroup extends cdk.Resource implements ILambdaDeploymentGroup { +class ImportedLambdaDeploymentGroup extends ImportedDeploymentGroupBase implements ILambdaDeploymentGroup { public readonly application: ILambdaApplication; - public readonly deploymentGroupName: string; - public readonly deploymentGroupArn: string; public readonly deploymentConfig: ILambdaDeploymentConfig; - constructor(scope:Construct, id: string, props: LambdaDeploymentGroupAttributes) { - super(scope, id); + constructor(scope: Construct, id: string, props: LambdaDeploymentGroupAttributes) { + super(scope, id, { + application: props.application, + deploymentGroupName: props.deploymentGroupName, + }); + this.application = props.application; - this.deploymentGroupName = props.deploymentGroupName; - this.deploymentGroupArn = arnForDeploymentGroup(props.application.applicationName, props.deploymentGroupName); this.deploymentConfig = props.deploymentConfig || LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES; } } diff --git a/packages/@aws-cdk/aws-codedeploy/lib/private/base-deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/private/base-deployment-group.ts new file mode 100644 index 0000000000000..3ea12aa50d702 --- /dev/null +++ b/packages/@aws-cdk/aws-codedeploy/lib/private/base-deployment-group.ts @@ -0,0 +1,138 @@ +import * as iam from '@aws-cdk/aws-iam'; +import { Resource, IResource, ArnFormat, Arn, Aws } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { CfnDeploymentGroup } from '../codedeploy.generated'; +import { validateName } from './utils'; + +/** + * Structural typing, not jsii compatible but doesn't need to be + */ +interface IApplicationLike extends IResource { + readonly applicationArn: string; + readonly applicationName: string; +} + +/** + */ +export interface ImportedDeploymentGroupBaseProps { + /** + * The reference to the CodeDeploy Application that this Deployment Group belongs to. + */ + readonly application: IApplicationLike; + + /** + * The physical, human-readable name of the CodeDeploy Deployment Group + * that we are referencing. + * + * @default Either deploymentGroupName or deploymentGroupArn is required + */ + readonly deploymentGroupName: string; +} + +/** + * @internal + */ +export class ImportedDeploymentGroupBase extends Resource { + public readonly deploymentGroupName: string; + public readonly deploymentGroupArn: string; + + constructor(scope: Construct, id: string, props: ImportedDeploymentGroupBaseProps) { + const deploymentGroupName = props.deploymentGroupName; + const deploymentGroupArn = Arn.format({ + partition: Aws.PARTITION, + account: props.application.env.account, + region: props.application.env.region, + service: 'codedeploy', + resource: 'deploymentgroup', + resourceName: `${props.application.applicationName}/${deploymentGroupName}`, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); + + super(scope, id, { environmentFromArn: deploymentGroupArn }); + this.deploymentGroupName = deploymentGroupName; + this.deploymentGroupArn = deploymentGroupArn; + } +} + +export interface DeploymentGroupBaseProps { + /** + * The physical, human-readable name of the CodeDeploy Deployment Group. + * + * @default An auto-generated name will be used. + */ + readonly deploymentGroupName?: string; + + /** + * The service Role of this Deployment Group. + * + * @default A new Role will be created. + */ + readonly role?: iam.IRole; + + /** + * Id of the role construct, if created by this construct + * + * Exists because when we factored this out, there was a difference between the + * 3 deployment groups. + */ + readonly roleConstructId: string; +} + +/** + * @internal + */ +export class DeploymentGroupBase extends Resource { + /** + * The name of the Deployment Group. + */ + public readonly deploymentGroupName!: string; + + /** + * The ARN of the Deployment Group. + */ + public readonly deploymentGroupArn!: string; + + /** + * The service Role of this Deployment Group. + * + * (Can't make `role` properly public here, as it's typed as optional in one + * interface and typing it here as definitely set interferes with that.) + * + * @internal + */ + public readonly _role: iam.IRole; + + constructor(scope: Construct, id: string, props: DeploymentGroupBaseProps) { + super(scope, id, { + physicalName: props.deploymentGroupName, + }); + + this._role = props.role || new iam.Role(this, props.roleConstructId, { + assumedBy: new iam.ServicePrincipal('codedeploy.amazonaws.com'), + }); + + this.node.addValidation({ validate: () => validateName('Deployment group', this.physicalName) }); + } + + /** + * Set name and ARN properties. + * + * Must be called in the child constructor. + * + * @internal + */ + protected _setNameAndArn(resource: CfnDeploymentGroup, application: IApplicationLike) { + (this as any).deploymentGroupName = this.getResourceNameAttribute(resource.ref); + (this as any).deploymentGroupArn = this.getResourceArnAttribute(this.stack.formatArn({ + service: 'codedeploy', + resource: 'deploymentgroup', + resourceName: `${application.applicationName}/${resource.ref}`, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }), { + service: 'codedeploy', + resource: 'deploymentgroup', + resourceName: `${application.applicationName}/${this.physicalName}`, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/lib/utils.ts b/packages/@aws-cdk/aws-codedeploy/lib/private/utils.ts similarity index 74% rename from packages/@aws-cdk/aws-codedeploy/lib/utils.ts rename to packages/@aws-cdk/aws-codedeploy/lib/private/utils.ts index 137998a23eb37..9dccb367d8578 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/utils.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/private/utils.ts @@ -1,19 +1,33 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; -import { Aws, Token } from '@aws-cdk/core'; -import { IBaseDeploymentConfig } from './base-deployment-config'; -import { CfnDeploymentGroup } from './codedeploy.generated'; -import { AutoRollbackConfig } from './rollback-config'; +import { Token, Stack, ArnFormat, Arn, Fn, Aws } from '@aws-cdk/core'; +import { IBaseDeploymentConfig } from '../base-deployment-config'; +import { CfnDeploymentGroup } from '../codedeploy.generated'; +import { AutoRollbackConfig } from '../rollback-config'; -export function arnForApplication(applicationName: string): string { - return `arn:${Aws.PARTITION}:codedeploy:${Aws.REGION}:${Aws.ACCOUNT_ID}:application:${applicationName}`; +export function arnForApplication(stack: Stack, applicationName: string): string { + return stack.formatArn({ + service: 'codedeploy', + resource: 'application', + resourceName: applicationName, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); } -export function arnForDeploymentGroup(applicationName: string, deploymentGroupName: string): string { - return `arn:${Aws.PARTITION}:codedeploy:${Aws.REGION}:${Aws.ACCOUNT_ID}:deploymentgroup:${applicationName}/${deploymentGroupName}`; +export function nameFromDeploymentGroupArn(deploymentGroupArn: string): string { + const components = Arn.split(deploymentGroupArn, ArnFormat.COLON_RESOURCE_NAME); + return Fn.select(1, Fn.split('/', components.resourceName ?? '')); } export function arnForDeploymentConfig(name: string): string { - return `arn:${Aws.PARTITION}:codedeploy:${Aws.REGION}:${Aws.ACCOUNT_ID}:deploymentconfig:${name}`; + return Arn.format({ + partition: Aws.PARTITION, + account: Aws.ACCOUNT_ID, + region: Aws.REGION, + service: 'codedeploy', + resource: 'deploymentconfig', + resourceName: name, + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }); } export function renderAlarmConfiguration(alarms: cloudwatch.IAlarm[], ignorePollAlarmFailure?: boolean): diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/application.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/application.ts index a04d789fce566..16addfd0537ae 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/application.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/application.ts @@ -1,7 +1,7 @@ -import { ArnFormat, IResource, Resource } from '@aws-cdk/core'; +import { ArnFormat, IResource, Resource, Stack, Arn } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnApplication } from '../codedeploy.generated'; -import { arnForApplication, validateName } from '../utils'; +import { arnForApplication, validateName } from '../private/utils'; /** * Represents a reference to a CodeDeploy Application deploying to EC2/on-premise instances. @@ -42,6 +42,9 @@ export class ServerApplication extends Resource implements IServerApplication { /** * Import an Application defined either outside the CDK app, or in a different region. * + * The Application's account and region are assumed to be the same as the stack it is being imported + * into. If not, use `fromServerApplicationArn`. + * * @param scope the parent Construct for this new Construct * @param id the logical ID of this new Construct * @param serverApplicationName the name of the application to import @@ -49,12 +52,26 @@ export class ServerApplication extends Resource implements IServerApplication { */ public static fromServerApplicationName(scope: Construct, id: string, serverApplicationName: string): IServerApplication { class Import extends Resource implements IServerApplication { - public readonly applicationArn = arnForApplication(serverApplicationName); + public readonly applicationArn = arnForApplication(Stack.of(scope), serverApplicationName); public readonly applicationName = serverApplicationName; } return new Import(scope, id); + } + /** + * Import an Application defined either outside the CDK, or in a different CDK Stack, by ARN. + * + * @param scope the parent Construct for this new Construct + * @param id the logical ID of this new Construct + * @param serverApplicationArn the ARN of the application to import + * @returns a Construct representing a reference to an existing Application + */ + public static fromServerApplicationArn(scope: Construct, id: string, serverApplicationArn: string): IServerApplication { + return new class extends Resource implements IServerApplication { + public applicationArn = serverApplicationArn; + public applicationName = Arn.split(serverApplicationArn, ArnFormat.COLON_RESOURCE_NAME).resourceName ?? ''; + }(scope, id, { environmentFromArn: serverApplicationArn }); } public readonly applicationArn: string; @@ -71,7 +88,7 @@ export class ServerApplication extends Resource implements IServerApplication { }); this.applicationName = this.getResourceNameAttribute(resource.ref); - this.applicationArn = this.getResourceArnAttribute(arnForApplication(resource.ref), { + this.applicationArn = this.getResourceArnAttribute(arnForApplication(Stack.of(scope), resource.ref), { service: 'codedeploy', resource: 'application', resourceName: this.physicalName, 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 c3ae4a75ffb59..d09af03cf2fa5 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,7 @@ import { Construct } from 'constructs'; import { BaseDeploymentConfig, BaseDeploymentConfigOptions, IBaseDeploymentConfig } from '../base-deployment-config'; import { MinimumHealthyHosts } from '../host-health-config'; -import { deploymentConfig } from '../utils'; +import { deploymentConfig } from '../private/utils'; /** * The Deployment Configuration of an EC2/on-premise Deployment Group. diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts index afb6aee8545e0..448d4f9dde5e8 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts @@ -4,11 +4,11 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; -import { ArnFormat } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnDeploymentGroup } from '../codedeploy.generated'; +import { ImportedDeploymentGroupBase, DeploymentGroupBase } from '../private/base-deployment-group'; +import { renderAlarmConfiguration, renderAutoRollbackConfiguration } from '../private/utils'; import { AutoRollbackConfig } from '../rollback-config'; -import { arnForDeploymentGroup, renderAlarmConfiguration, renderAutoRollbackConfiguration, validateName } from '../utils'; import { IServerApplication, ServerApplication } from './application'; import { IServerDeploymentConfig, ServerDeploymentConfig } from './deployment-config'; import { LoadBalancer, LoadBalancerGeneration } from './load-balancer'; @@ -55,43 +55,20 @@ export interface ServerDeploymentGroupAttributes { readonly deploymentConfig?: IServerDeploymentConfig; } -/** - * Represents a reference to a CodeDeploy EC2/on-premise Deployment Group. - * - * If you're managing the Deployment Group alongside the rest of your CDK resources, - * use the {@link ServerDeploymentGroup} class. - * - * If you want to reference an already existing Deployment Group, - * or one defined in a different CDK Stack, - * use the {@link #import} method. - */ -abstract class ServerDeploymentGroupBase extends cdk.Resource implements IServerDeploymentGroup { - public abstract readonly application: IServerApplication; - public abstract readonly role?: iam.IRole; - public abstract readonly deploymentGroupName: string; - public abstract readonly deploymentGroupArn: string; - public readonly deploymentConfig: IServerDeploymentConfig; - public abstract readonly autoScalingGroups?: autoscaling.IAutoScalingGroup[]; - - constructor(scope: Construct, id: string, deploymentConfig?: IServerDeploymentConfig, props?: cdk.ResourceProps) { - super(scope, id, props); - this.deploymentConfig = deploymentConfig || ServerDeploymentConfig.ONE_AT_A_TIME; - } -} - -class ImportedServerDeploymentGroup extends ServerDeploymentGroupBase { +class ImportedServerDeploymentGroup extends ImportedDeploymentGroupBase implements IServerDeploymentGroup { public readonly application: IServerApplication; public readonly role?: iam.Role = undefined; - public readonly deploymentGroupName: string; - public readonly deploymentGroupArn: string; public readonly autoScalingGroups?: autoscaling.AutoScalingGroup[] = undefined; + public readonly deploymentConfig: IServerDeploymentConfig; constructor(scope: Construct, id: string, props: ServerDeploymentGroupAttributes) { - super(scope, id, props.deploymentConfig); + super(scope, id, { + application: props.application, + deploymentGroupName: props.deploymentGroupName, + }); this.application = props.application; - this.deploymentGroupName = props.deploymentGroupName; - this.deploymentGroupArn = arnForDeploymentGroup(props.application.applicationName, props.deploymentGroupName); + this.deploymentConfig = props.deploymentConfig || ServerDeploymentConfig.ONE_AT_A_TIME; } } @@ -238,7 +215,7 @@ export interface ServerDeploymentGroupProps { * A CodeDeploy Deployment Group that deploys to EC2/on-premise instances. * @resource AWS::CodeDeploy::DeploymentGroup */ -export class ServerDeploymentGroup extends ServerDeploymentGroupBase { +export class ServerDeploymentGroup extends DeploymentGroupBase implements IServerDeploymentGroup { /** * Import an EC2/on-premise Deployment Group defined either outside the CDK app, * or in a different region. @@ -256,9 +233,11 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupBase { } public readonly application: IServerApplication; + public readonly deploymentConfig: IServerDeploymentConfig; + /** + * The service Role of this Deployment Group. + */ public readonly role?: iam.IRole; - public readonly deploymentGroupArn: string; - public readonly deploymentGroupName: string; private readonly _autoScalingGroups: autoscaling.IAutoScalingGroup[]; private readonly installAgent: boolean; @@ -266,19 +245,19 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupBase { private readonly alarms: cloudwatch.IAlarm[]; constructor(scope: Construct, id: string, props: ServerDeploymentGroupProps = {}) { - super(scope, id, props.deploymentConfig, { - physicalName: props.deploymentGroupName, + super(scope, id, { + deploymentGroupName: props.deploymentGroupName, + role: props.role, + roleConstructId: 'Role', }); + this.role = this._role; this.application = props.application || new ServerApplication(this, 'Application', { applicationName: props.deploymentGroupName === cdk.PhysicalName.GENERATE_IF_NEEDED ? cdk.PhysicalName.GENERATE_IF_NEEDED : undefined, }); + this.deploymentConfig = props.deploymentConfig || ServerDeploymentConfig.ONE_AT_A_TIME; - this.role = props.role || new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('codedeploy.amazonaws.com'), - managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCodeDeployRole')], - }); - + this.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCodeDeployRole')); this._autoScalingGroups = props.autoScalingGroups || []; this.installAgent = props.installAgent ?? true; this.codeDeployBucket = s3.Bucket.fromBucketName(this, 'Bucket', `aws-codedeploy-${cdk.Stack.of(this).region}`); @@ -307,15 +286,7 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupBase { autoRollbackConfiguration: cdk.Lazy.any({ produce: () => renderAutoRollbackConfiguration(this.alarms, props.autoRollback) }), }); - this.deploymentGroupName = this.getResourceNameAttribute(resource.ref); - this.deploymentGroupArn = this.getResourceArnAttribute(arnForDeploymentGroup(this.application.applicationName, resource.ref), { - service: 'codedeploy', - resource: 'deploymentgroup', - resourceName: `${this.application.applicationName}/${this.physicalName}`, - arnFormat: ArnFormat.COLON_RESOURCE_NAME, - }); - - this.node.addValidation({ validate: () => validateName('Deployment group', this.physicalName) }); + this._setNameAndArn(resource, this.application); } /** diff --git a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-group.test.ts b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-group.test.ts index 62f2b4402c009..aed7b8655516e 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-group.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/ecs/deployment-group.test.ts @@ -848,4 +848,26 @@ describe('CodeDeploy ECS DeploymentGroup', () => { }, }); }); + + test('deploymentGroup from Arn knows its account and region', () => { + // GIVEN + const stack = new cdk.Stack(undefined, 'Stack', { env: { account: '111111111111', region: 'blabla-1' } }); + + // WHEN + const application = codedeploy.EcsApplication.fromEcsApplicationArn(stack, 'Application', 'arn:aws:codedeploy:theregion-1:222222222222:application:MyApplication'); + const group = codedeploy.EcsDeploymentGroup.fromEcsDeploymentGroupAttributes(stack, 'Group', { + application, + deploymentGroupName: 'DeploymentGroup', + }); + + // THEN + expect(application.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + expect(group.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + }); }); 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 959c98bbce139..9eae61c7a4e4f 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 @@ -615,6 +615,28 @@ describe('CodeDeploy Lambda DeploymentGroup', () => { }, }); }); + + test('deploymentGroup from Arn knows its account and region', () => { + // GIVEN + const stack = new cdk.Stack(undefined, 'Stack', { env: { account: '111111111111', region: 'blabla-1' } }); + + // WHEN + const application = codedeploy.LambdaApplication.fromLambdaApplicationArn(stack, 'Application', 'arn:aws:codedeploy:theregion-1:222222222222:application:MyApplication'); + const group = codedeploy.LambdaDeploymentGroup.fromLambdaDeploymentGroupAttributes(stack, 'Group', { + application, + deploymentGroupName: 'DeploymentGroup', + }); + + // THEN + expect(application.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + expect(group.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + }); }); describe('imported with fromLambdaDeploymentGroupAttributes', () => { diff --git a/packages/@aws-cdk/aws-codedeploy/test/server/deployment-group.test.ts b/packages/@aws-cdk/aws-codedeploy/test/server/deployment-group.test.ts index 6b22a90cbeedb..4f360aa9cb9c2 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/server/deployment-group.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/server/deployment-group.test.ts @@ -494,4 +494,25 @@ describe('CodeDeploy Server Deployment Group', () => { expect(() => app.synth()).toThrow('Deployment group 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('deploymentGroup from Arn knows its account and region', () => { + // GIVEN + const stack = new cdk.Stack(undefined, 'Stack', { env: { account: '111111111111', region: 'blabla-1' } }); + + // WHEN + const application = codedeploy.ServerApplication.fromServerApplicationArn(stack, 'Application', 'arn:aws:codedeploy:theregion-1:222222222222:application:MyApplication'); + const group = codedeploy.ServerDeploymentGroup.fromServerDeploymentGroupAttributes(stack, 'Group', { + application, + deploymentGroupName: 'DeploymentGroup', + }); + + // THEN + expect(application.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + expect(group.env).toEqual(expect.objectContaining({ + account: '222222222222', + region: 'theregion-1', + })); + }); }); 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 index 631c3d6f84c26..c5239f88f3f9f 100644 --- 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 @@ -103,8 +103,8 @@ const beanstalkEnv = new elasticbeanstalk.CfnEnvironment(stack, 'beanstlk-env', ], }); -beanstalkEnv.addDependsOn(instanceProfile); -beanstalkEnv.addDependsOn(beanstalkApp); +beanstalkEnv.addDependency(instanceProfile); +beanstalkEnv.addDependency(beanstalkApp); const pipeline = new codepipeline.Pipeline(stack, 'Pipeline', { artifactBucket: bucket, @@ -144,4 +144,4 @@ new integ.IntegTest(app, 'codepipeline-elastic-beanstalk-deploy', { stackUpdateWorkflow: false, }); -app.synth(); \ No newline at end of file +app.synth(); diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index f01f8646a4d1f..3e0e035a13318 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -431,6 +431,18 @@ new cognito.UserPool(this, 'myuserpool', { }); ``` +If `fromName` does not comply RFC 5322 atom or quoted-string, it will be quoted or mime-encoded. + +```ts +new cognito.UserPool(this, 'myuserpool', { + email: cognito.UserPoolEmail.withSES({ + fromEmail: 'noreply@myawesomeapp.com', + fromName: 'myname@mycompany.com', + }), +}); +// => From: "myname@mycompany.com" +``` + ### Device Tracking User pools can be configured to track devices that users have logged in to. @@ -708,6 +720,17 @@ const client = pool.addClient('app-client', { client.node.addDependency(provider); ``` +The property `authSessionValidity` is the session token for each API request in the authentication flow. +Valid duration is from 3 to 15 minutes. + +```ts +const pool = new cognito.UserPool(this, 'Pool'); +pool.addClient('app-client', { + // ... + authSessionValidity: Duration.minutes(15), +}); +``` + In accordance with the OIDC open standard, Cognito user pool clients provide access tokens, ID tokens and refresh tokens. More information is available at [Using Tokens with User Pools](https://docs.aws.amazon.com/en_us/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html). The expiration time for these tokens can be configured as shown below. diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts index cabcae64a2c8f..a36f113b37b3e 100644 --- a/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts @@ -239,6 +239,15 @@ export interface UserPoolClientOptions { */ readonly oAuth?: OAuthSettings; + /** + * Cognito creates a session token for each API request in an authentication flow. + * AuthSessionValidity is the duration, in minutes, of that session token. + * see defaults in `AuthSessionValidity`. Valid duration is from 3 to 15 minutes. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html#cfn-cognito-userpoolclient-authsessionvalidity + * @default - Duration.minutes(3) + */ + readonly authSessionValidity?: Duration; + /** * Whether Cognito returns a UserNotFoundException exception when the * user does not exist in the user pool (false), or whether it returns @@ -409,6 +418,7 @@ export class UserPoolClient extends Resource implements IUserPoolClient { writeAttributes: props.writeAttributes?.attributes(), enableTokenRevocation: props.enableTokenRevocation, }); + this.configureAuthSessionValidity(resource, props); this.configureTokenValidity(resource, props); this.userPoolClientId = resource.ref; @@ -522,6 +532,11 @@ export class UserPoolClient extends Resource implements IUserPoolClient { return Array.from(providers); } + private configureAuthSessionValidity(resource: CfnUserPoolClient, props: UserPoolClientProps) { + this.validateDuration('authSessionValidity', Duration.minutes(3), Duration.minutes(15), props.authSessionValidity); + resource.authSessionValidity = props.authSessionValidity ? props.authSessionValidity.toMinutes() : undefined; + } + private configureTokenValidity(resource: CfnUserPoolClient, props: UserPoolClientProps) { this.validateDuration('idTokenValidity', Duration.minutes(5), Duration.days(1), props.idTokenValidity); this.validateDuration('accessTokenValidity', Duration.minutes(5), Duration.days(1), props.accessTokenValidity); diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-email.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-email.ts index 27eb3f8c240d3..d275c4d3a5dd2 100644 --- a/packages/@aws-cdk/aws-cognito/lib/user-pool-email.ts +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-email.ts @@ -164,9 +164,10 @@ class SESEmail extends UserPoolEmail { throw new Error('Your stack region cannot be determined so "sesRegion" is required in SESOptions'); } - let from = this.options.fromEmail; + let from = encodeAndTest(this.options.fromEmail); if (this.options.fromName) { - from = `${this.options.fromName} <${this.options.fromEmail}>`; + const fromName = formatFromName(this.options.fromName); + from = `${fromName} <${from}>`; } if (this.options.sesVerifiedDomain) { @@ -177,7 +178,7 @@ class SESEmail extends UserPoolEmail { } return { - from: encodeAndTest(from), + from, replyToEmailAddress: encodeAndTest(this.options.replyTo), configurationSet: this.options.configurationSetName, emailSendingAccount: 'DEVELOPER', @@ -202,3 +203,59 @@ function encodeAndTest(input: string | undefined): string | undefined { return undefined; } } + +/** + * Formats `fromName` to comply RFC 5322 + * + * @see https://www.rfc-editor.org/rfc/rfc5322#section-3.4 + */ +function formatFromName(fromName: string): string { + // mime encode for non US-ASCII characters + // see RFC 2047 for details https://www.rfc-editor.org/rfc/rfc2047 + if (!isAscii(fromName)) { + const base64Name = Buffer.from(fromName, 'utf-8').toString('base64'); + return `=?UTF-8?B?${base64Name}?=`; + } + + // makes a quoted-string unless fromName is a phrase (only atext and space) + // or a quoted-string already + if (!(isSimplePhrase(fromName) || isQuotedString(fromName))) { + // in quoted-string, `\` and `"` should be escaped by `\` + // e.g. `"foo \"bar\" \\baz"` + const quotedName = fromName.replace(/[\\"]/g, (ch) => `\\${ch}`); + return `"${quotedName}"`; + } + + // otherwise, returns as is + return fromName; +} + +/** + * Returns whether the input is a printable US-ASCII string + */ +function isAscii(input: string): boolean { + // U+0020 (space) - U+007E (`~`) + return /^[\u0020-\u007E]+$/u.test(input); +} + +/** + * Returns whether the input is a phrase excluding quoted-string + * + * @see https://www.rfc-editor.org/rfc/rfc5322#section-3.2 + */ +function isSimplePhrase(input: string): boolean { + return /^[\w !#$%&'*+-\/=?^_`{|}~]+$/.test(input); +} + +/** + * Returns whether the input is already a quoted-string + * + * @see https://www.rfc-editor.org/rfc/rfc5322#section-3.2.4 + */ +function isQuotedString(input: string): boolean { + // in quoted-string, `\` and `"` should be esacaped by `\` + // + // match: `"foo.bar"` / `"foo \"bar\""` / `"foo \\ bar"` + // not match: `"bare " dquote"` / `"unclosed escape \"` / `"unclosed dquote` + return /^"(?:[^\\"]|\\.)*"$/.test(input); +} diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286/index.js b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286/index.js deleted file mode 100644 index 7bae87b06d44d..0000000000000 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286/index.js +++ /dev/null @@ -1,252 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handler = exports.forceSdkInstallation = exports.flatten = exports.PHYSICAL_RESOURCE_ID_REFERENCE = void 0; -/* eslint-disable no-console */ -const child_process_1 = require("child_process"); -const fs = require("fs"); -const path_1 = require("path"); -/** - * Serialized form of the physical resource id for use in the operation parameters - */ -exports.PHYSICAL_RESOURCE_ID_REFERENCE = 'PHYSICAL:RESOURCEID:'; -/** - * Flattens a nested object - * - * @param object the object to be flattened - * @returns a flat object with path as keys - */ -function flatten(object) { - return Object.assign({}, ...function _flatten(child, path = []) { - return [].concat(...Object.keys(child) - .map(key => { - const childKey = Buffer.isBuffer(child[key]) ? child[key].toString('utf8') : child[key]; - return typeof childKey === 'object' && childKey !== null - ? _flatten(childKey, path.concat([key])) - : ({ [path.concat([key]).join('.')]: childKey }); - })); - }(object)); -} -exports.flatten = flatten; -/** - * Decodes encoded special values (physicalResourceId) - */ -function decodeSpecialValues(object, physicalResourceId) { - return JSON.parse(JSON.stringify(object), (_k, v) => { - switch (v) { - case exports.PHYSICAL_RESOURCE_ID_REFERENCE: - return physicalResourceId; - default: - return v; - } - }); -} -/** - * Filters the keys of an object. - */ -function filterKeys(object, pred) { - return Object.entries(object) - .reduce((acc, [k, v]) => pred(k) - ? { ...acc, [k]: v } - : acc, {}); -} -let latestSdkInstalled = false; -function forceSdkInstallation() { - latestSdkInstalled = false; -} -exports.forceSdkInstallation = forceSdkInstallation; -/** - * Installs latest AWS SDK v2 - */ -function installLatestSdk() { - console.log('Installing latest AWS SDK v2'); - // Both HOME and --prefix are needed here because /tmp is the only writable location - child_process_1.execSync('HOME=/tmp npm install aws-sdk@2 --production --no-package-lock --no-save --prefix /tmp'); - latestSdkInstalled = true; -} -// no currently patched services -const patchedServices = []; -/** - * Patches the AWS SDK by loading service models in the same manner as the actual SDK - */ -function patchSdk(awsSdk) { - const apiLoader = awsSdk.apiLoader; - patchedServices.forEach(({ serviceName, apiVersions }) => { - const lowerServiceName = serviceName.toLowerCase(); - if (!awsSdk.Service.hasService(lowerServiceName)) { - apiLoader.services[lowerServiceName] = {}; - awsSdk[serviceName] = awsSdk.Service.defineService(lowerServiceName, apiVersions); - } - else { - awsSdk.Service.addVersions(awsSdk[serviceName], apiVersions); - } - apiVersions.forEach(apiVersion => { - Object.defineProperty(apiLoader.services[lowerServiceName], apiVersion, { - get: function get() { - const modelFilePrefix = `aws-sdk-patch/${lowerServiceName}-${apiVersion}`; - const model = JSON.parse(fs.readFileSync(path_1.join(__dirname, `${modelFilePrefix}.service.json`), 'utf-8')); - model.paginators = JSON.parse(fs.readFileSync(path_1.join(__dirname, `${modelFilePrefix}.paginators.json`), 'utf-8')).pagination; - return model; - }, - enumerable: true, - configurable: true, - }); - }); - }); - return awsSdk; -} -/* eslint-disable @typescript-eslint/no-require-imports, import/no-extraneous-dependencies */ -async function handler(event, context) { - try { - let AWS; - if (!latestSdkInstalled && event.ResourceProperties.InstallLatestAwsSdk === 'true') { - try { - installLatestSdk(); - AWS = require('/tmp/node_modules/aws-sdk'); - } - catch (e) { - console.log(`Failed to install latest AWS SDK v2: ${e}`); - AWS = require('aws-sdk'); // Fallback to pre-installed version - } - } - else if (latestSdkInstalled) { - AWS = require('/tmp/node_modules/aws-sdk'); - } - else { - AWS = require('aws-sdk'); - } - try { - AWS = patchSdk(AWS); - } - catch (e) { - console.log(`Failed to patch AWS SDK: ${e}. Proceeding with the installed copy.`); - } - console.log(JSON.stringify({ ...event, ResponseURL: '...' })); - console.log('AWS SDK VERSION: ' + AWS.VERSION); - event.ResourceProperties.Create = decodeCall(event.ResourceProperties.Create); - event.ResourceProperties.Update = decodeCall(event.ResourceProperties.Update); - event.ResourceProperties.Delete = decodeCall(event.ResourceProperties.Delete); - // Default physical resource id - let physicalResourceId; - switch (event.RequestType) { - case 'Create': - physicalResourceId = event.ResourceProperties.Create?.physicalResourceId?.id ?? - event.ResourceProperties.Update?.physicalResourceId?.id ?? - event.ResourceProperties.Delete?.physicalResourceId?.id ?? - event.LogicalResourceId; - break; - case 'Update': - case 'Delete': - physicalResourceId = event.ResourceProperties[event.RequestType]?.physicalResourceId?.id ?? event.PhysicalResourceId; - break; - } - let flatData = {}; - let data = {}; - const call = event.ResourceProperties[event.RequestType]; - if (call) { - let credentials; - if (call.assumedRoleArn) { - const timestamp = (new Date()).getTime(); - const params = { - RoleArn: call.assumedRoleArn, - RoleSessionName: `${timestamp}-${physicalResourceId}`.substring(0, 64), - }; - credentials = new AWS.ChainableTemporaryCredentials({ - params: params, - }); - } - if (!Object.prototype.hasOwnProperty.call(AWS, call.service)) { - throw Error(`Service ${call.service} does not exist in AWS SDK version ${AWS.VERSION}.`); - } - const awsService = new AWS[call.service]({ - apiVersion: call.apiVersion, - credentials: credentials, - region: call.region, - }); - try { - const response = await awsService[call.action](call.parameters && decodeSpecialValues(call.parameters, physicalResourceId)).promise(); - flatData = { - apiVersion: awsService.config.apiVersion, - region: awsService.config.region, - ...flatten(response), - }; - let outputPaths; - if (call.outputPath) { - outputPaths = [call.outputPath]; - } - else if (call.outputPaths) { - outputPaths = call.outputPaths; - } - if (outputPaths) { - data = filterKeys(flatData, startsWithOneOf(outputPaths)); - } - else { - data = flatData; - } - } - catch (e) { - if (!call.ignoreErrorCodesMatching || !new RegExp(call.ignoreErrorCodesMatching).test(e.code)) { - throw e; - } - } - if (call.physicalResourceId?.responsePath) { - physicalResourceId = flatData[call.physicalResourceId.responsePath]; - } - } - await respond('SUCCESS', 'OK', physicalResourceId, data); - } - catch (e) { - console.log(e); - await respond('FAILED', e.message || 'Internal Error', context.logStreamName, {}); - } - function respond(responseStatus, reason, physicalResourceId, data) { - const responseBody = JSON.stringify({ - Status: responseStatus, - Reason: reason, - PhysicalResourceId: physicalResourceId, - StackId: event.StackId, - RequestId: event.RequestId, - LogicalResourceId: event.LogicalResourceId, - NoEcho: false, - Data: data, - }); - 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); - } - }); - } -} -exports.handler = handler; -function decodeCall(call) { - if (!call) { - return undefined; - } - return JSON.parse(call); -} -function startsWithOneOf(searchStrings) { - return function (string) { - for (const searchString of searchStrings) { - if (string.startsWith(searchString)) { - return true; - } - } - return false; - }; -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsaURBQXlDO0FBQ3pDLHlCQUF5QjtBQUN6QiwrQkFBNEI7QUFTNUI7O0dBRUc7QUFDVSxRQUFBLDhCQUE4QixHQUFHLHNCQUFzQixDQUFDO0FBRXJFOzs7OztHQUtHO0FBQ0gsU0FBZ0IsT0FBTyxDQUFDLE1BQWM7SUFDcEMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUNsQixFQUFFLEVBQ0YsR0FBRyxTQUFTLFFBQVEsQ0FBQyxLQUFVLEVBQUUsT0FBaUIsRUFBRTtRQUNsRCxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQzthQUNuQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDVCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEYsT0FBTyxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxLQUFLLElBQUk7Z0JBQ3RELENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUN4QyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUNWLENBQUM7QUFDSixDQUFDO0FBYkQsMEJBYUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsTUFBYyxFQUFFLGtCQUEwQjtJQUNyRSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNsRCxRQUFRLENBQUMsRUFBRTtZQUNULEtBQUssc0NBQThCO2dCQUNqQyxPQUFPLGtCQUFrQixDQUFDO1lBQzVCO2dCQUNFLE9BQU8sQ0FBQyxDQUFDO1NBQ1o7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsVUFBVSxDQUFDLE1BQWMsRUFBRSxJQUE4QjtJQUNoRSxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1NBQzFCLE1BQU0sQ0FDTCxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtRQUNwQixDQUFDLENBQUMsR0FBRyxFQUNQLEVBQUUsQ0FDSCxDQUFDO0FBQ04sQ0FBQztBQUVELElBQUksa0JBQWtCLEdBQUcsS0FBSyxDQUFDO0FBRS9CLFNBQWdCLG9CQUFvQjtJQUNsQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7QUFDN0IsQ0FBQztBQUZELG9EQUVDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQjtJQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDNUMsb0ZBQW9GO0lBQ3BGLHdCQUFRLENBQUMsd0ZBQXdGLENBQUMsQ0FBQztJQUNuRyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7QUFDNUIsQ0FBQztBQUVELGdDQUFnQztBQUNoQyxNQUFNLGVBQWUsR0FBcUQsRUFBRSxDQUFDO0FBQzdFOztHQUVHO0FBQ0gsU0FBUyxRQUFRLENBQUMsTUFBVztJQUMzQixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO0lBQ25DLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFO1FBQ3ZELE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFO1lBQ2hELFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDMUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDO1NBQ25GO2FBQU07WUFDTCxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDOUQ7UUFDRCxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQy9CLE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFVBQVUsRUFBRTtnQkFDdEUsR0FBRyxFQUFFLFNBQVMsR0FBRztvQkFDZixNQUFNLGVBQWUsR0FBRyxpQkFBaUIsZ0JBQWdCLElBQUksVUFBVSxFQUFFLENBQUM7b0JBQzFFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsZUFBZSxlQUFlLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUN2RyxLQUFLLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsZUFBZSxrQkFBa0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO29CQUMxSCxPQUFPLEtBQUssQ0FBQztnQkFDZixDQUFDO2dCQUNELFVBQVUsRUFBRSxJQUFJO2dCQUNoQixZQUFZLEVBQUUsSUFBSTthQUNuQixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVELDZGQUE2RjtBQUN0RixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsSUFBSTtRQUNGLElBQUksR0FBUSxDQUFDO1FBQ2IsSUFBSSxDQUFDLGtCQUFrQixJQUFJLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsS0FBSyxNQUFNLEVBQUU7WUFDbEYsSUFBSTtnQkFDRixnQkFBZ0IsRUFBRSxDQUFDO2dCQUNuQixHQUFHLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBQUM7YUFDNUM7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixPQUFPLENBQUMsR0FBRyxDQUFDLHdDQUF3QyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6RCxHQUFHLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsb0NBQW9DO2FBQy9EO1NBQ0Y7YUFBTSxJQUFJLGtCQUFrQixFQUFFO1lBQzdCLEdBQUcsR0FBRyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQztTQUM1QzthQUFNO1lBQ0wsR0FBRyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMxQjtRQUNELElBQUk7WUFDRixHQUFHLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3JCO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLDRCQUE0QixDQUFDLHVDQUF1QyxDQUFDLENBQUM7U0FDbkY7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9DLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5RSxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlFLCtCQUErQjtRQUMvQixJQUFJLGtCQUEwQixDQUFDO1FBQy9CLFFBQVEsS0FBSyxDQUFDLFdBQVcsRUFBRTtZQUN6QixLQUFLLFFBQVE7Z0JBQ1gsa0JBQWtCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxFQUFFO29CQUN2RCxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxFQUFFLGtCQUFrQixFQUFFLEVBQUU7b0JBQ3ZELEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsRUFBRTtvQkFDdkQsS0FBSyxDQUFDLGlCQUFpQixDQUFDO2dCQUM3QyxNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUM7WUFDZCxLQUFLLFFBQVE7Z0JBQ1gsa0JBQWtCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxFQUFFLElBQUksS0FBSyxDQUFDLGtCQUFrQixDQUFDO2dCQUNySCxNQUFNO1NBQ1Q7UUFFRCxJQUFJLFFBQVEsR0FBOEIsRUFBRSxDQUFDO1FBQzdDLElBQUksSUFBSSxHQUE4QixFQUFFLENBQUM7UUFDekMsTUFBTSxJQUFJLEdBQTJCLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFakYsSUFBSSxJQUFJLEVBQUU7WUFFUixJQUFJLFdBQVcsQ0FBQztZQUNoQixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3ZCLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUV6QyxNQUFNLE1BQU0sR0FBRztvQkFDYixPQUFPLEVBQUUsSUFBSSxDQUFDLGNBQWM7b0JBQzVCLGVBQWUsRUFBRSxHQUFHLFNBQVMsSUFBSSxrQkFBa0IsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO2lCQUN2RSxDQUFDO2dCQUVGLFdBQVcsR0FBRyxJQUFJLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQztvQkFDbEQsTUFBTSxFQUFFLE1BQU07aUJBQ2YsQ0FBQyxDQUFDO2FBQ0o7WUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQzVELE1BQU0sS0FBSyxDQUFDLFdBQVcsSUFBSSxDQUFDLE9BQU8sc0NBQXNDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO2FBQzFGO1lBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSyxHQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNoRCxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7Z0JBQzNCLFdBQVcsRUFBRSxXQUFXO2dCQUN4QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07YUFDcEIsQ0FBQyxDQUFDO1lBRUgsSUFBSTtnQkFDRixNQUFNLFFBQVEsR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQzVDLElBQUksQ0FBQyxVQUFVLElBQUksbUJBQW1CLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3pGLFFBQVEsR0FBRztvQkFDVCxVQUFVLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxVQUFVO29CQUN4QyxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNO29CQUNoQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7aUJBQ3JCLENBQUM7Z0JBRUYsSUFBSSxXQUFpQyxDQUFDO2dCQUN0QyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7b0JBQ25CLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztpQkFDakM7cUJBQU0sSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO29CQUMzQixXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztpQkFDaEM7Z0JBRUQsSUFBSSxXQUFXLEVBQUU7b0JBQ2YsSUFBSSxHQUFHLFVBQVUsQ0FBQyxRQUFRLEVBQUUsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7aUJBQzNEO3FCQUFNO29CQUNMLElBQUksR0FBRyxRQUFRLENBQUM7aUJBQ2pCO2FBQ0Y7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDN0YsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7YUFDRjtZQUVELElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksRUFBRTtnQkFDekMsa0JBQWtCLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUNyRTtTQUNGO1FBRUQsTUFBTSxPQUFPLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRSxJQUFJLENBQUMsQ0FBQztLQUMxRDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNmLE1BQU0sT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsT0FBTyxJQUFJLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDbkY7SUFFRCxTQUFTLE9BQU8sQ0FBQyxjQUFzQixFQUFFLE1BQWMsRUFBRSxrQkFBMEIsRUFBRSxJQUFTO1FBQzVGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDbEMsTUFBTSxFQUFFLGNBQWM7WUFDdEIsTUFBTSxFQUFFLE1BQU07WUFDZCxrQkFBa0IsRUFBRSxrQkFBa0I7WUFDdEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztZQUMxQixpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1lBQzFDLE1BQU0sRUFBRSxLQUFLO1lBQ2IsSUFBSSxFQUFFLElBQUk7U0FDWCxDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztRQUV4QyxpRUFBaUU7UUFDakUsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDMUQsTUFBTSxjQUFjLEdBQUc7WUFDckIsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1lBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtZQUNwQixNQUFNLEVBQUUsS0FBSztZQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtTQUN2RSxDQUFDO1FBRUYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJO2dCQUNGLGlFQUFpRTtnQkFDakUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ2xFLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUM1QixPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7YUFDZjtZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNYO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQztBQWpKRCwwQkFpSkM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxJQUF3QjtJQUMxQyxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQUUsT0FBTyxTQUFTLENBQUM7S0FBRTtJQUNoQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUIsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLGFBQXVCO0lBQzlDLE9BQU8sVUFBUyxNQUFjO1FBQzVCLEtBQUssTUFBTSxZQUFZLElBQUksYUFBYSxFQUFFO1lBQ3hDLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDbkMsT0FBTyxJQUFJLENBQUM7YUFDYjtTQUNGO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCB7IGpvaW4gfSBmcm9tICdwYXRoJztcbi8vIGltcG9ydCB0aGUgQVdTTGFtYmRhIHBhY2thZ2UgZXhwbGljaXRseSxcbi8vIHdoaWNoIGlzIGdsb2JhbGx5IGF2YWlsYWJsZSBpbiB0aGUgTGFtYmRhIHJ1bnRpbWUsXG4vLyBhcyBvdGhlcndpc2UgbGlua2luZyB0aGlzIHJlcG9zaXRvcnkgd2l0aCBsaW5rLWFsbC5zaFxuLy8gZmFpbHMgaW4gdGhlIENESyBhcHAgZXhlY3V0ZWQgd2l0aCB0cy1ub2RlXG4vKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzLGltcG9ydC9uby11bnJlc29sdmVkICovXG5pbXBvcnQgKiBhcyBBV1NMYW1iZGEgZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBBd3NTZGtDYWxsIH0gZnJvbSAnLi4vYXdzLWN1c3RvbS1yZXNvdXJjZSc7XG5cbi8qKlxuICogU2VyaWFsaXplZCBmb3JtIG9mIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBpZCBmb3IgdXNlIGluIHRoZSBvcGVyYXRpb24gcGFyYW1ldGVyc1xuICovXG5leHBvcnQgY29uc3QgUEhZU0lDQUxfUkVTT1VSQ0VfSURfUkVGRVJFTkNFID0gJ1BIWVNJQ0FMOlJFU09VUkNFSUQ6JztcblxuLyoqXG4gKiBGbGF0dGVucyBhIG5lc3RlZCBvYmplY3RcbiAqXG4gKiBAcGFyYW0gb2JqZWN0IHRoZSBvYmplY3QgdG8gYmUgZmxhdHRlbmVkXG4gKiBAcmV0dXJucyBhIGZsYXQgb2JqZWN0IHdpdGggcGF0aCBhcyBrZXlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKG9iamVjdDogb2JqZWN0KTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSB7XG4gIHJldHVybiBPYmplY3QuYXNzaWduKFxuICAgIHt9LFxuICAgIC4uLmZ1bmN0aW9uIF9mbGF0dGVuKGNoaWxkOiBhbnksIHBhdGg6IHN0cmluZ1tdID0gW10pOiBhbnkge1xuICAgICAgcmV0dXJuIFtdLmNvbmNhdCguLi5PYmplY3Qua2V5cyhjaGlsZClcbiAgICAgICAgLm1hcChrZXkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNoaWxkS2V5ID0gQnVmZmVyLmlzQnVmZmVyKGNoaWxkW2tleV0pID8gY2hpbGRba2V5XS50b1N0cmluZygndXRmOCcpIDogY2hpbGRba2V5XTtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIGNoaWxkS2V5ID09PSAnb2JqZWN0JyAmJiBjaGlsZEtleSAhPT0gbnVsbFxuICAgICAgICAgICAgPyBfZmxhdHRlbihjaGlsZEtleSwgcGF0aC5jb25jYXQoW2tleV0pKVxuICAgICAgICAgICAgOiAoeyBbcGF0aC5jb25jYXQoW2tleV0pLmpvaW4oJy4nKV06IGNoaWxkS2V5IH0pO1xuICAgICAgICB9KSk7XG4gICAgfShvYmplY3QpLFxuICApO1xufVxuXG4vKipcbiAqIERlY29kZXMgZW5jb2RlZCBzcGVjaWFsIHZhbHVlcyAocGh5c2ljYWxSZXNvdXJjZUlkKVxuICovXG5mdW5jdGlvbiBkZWNvZGVTcGVjaWFsVmFsdWVzKG9iamVjdDogb2JqZWN0LCBwaHlzaWNhbFJlc291cmNlSWQ6IHN0cmluZykge1xuICByZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShvYmplY3QpLCAoX2ssIHYpID0+IHtcbiAgICBzd2l0Y2ggKHYpIHtcbiAgICAgIGNhc2UgUEhZU0lDQUxfUkVTT1VSQ0VfSURfUkVGRVJFTkNFOlxuICAgICAgICByZXR1cm4gcGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKiBGaWx0ZXJzIHRoZSBrZXlzIG9mIGFuIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gZmlsdGVyS2V5cyhvYmplY3Q6IG9iamVjdCwgcHJlZDogKGtleTogc3RyaW5nKSA9PiBib29sZWFuKSB7XG4gIHJldHVybiBPYmplY3QuZW50cmllcyhvYmplY3QpXG4gICAgLnJlZHVjZShcbiAgICAgIChhY2MsIFtrLCB2XSkgPT4gcHJlZChrKVxuICAgICAgICA/IHsgLi4uYWNjLCBba106IHYgfVxuICAgICAgICA6IGFjYyxcbiAgICAgIHt9LFxuICAgICk7XG59XG5cbmxldCBsYXRlc3RTZGtJbnN0YWxsZWQgPSBmYWxzZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZvcmNlU2RrSW5zdGFsbGF0aW9uKCkge1xuICBsYXRlc3RTZGtJbnN0YWxsZWQgPSBmYWxzZTtcbn1cblxuLyoqXG4gKiBJbnN0YWxscyBsYXRlc3QgQVdTIFNESyB2MlxuICovXG5mdW5jdGlvbiBpbnN0YWxsTGF0ZXN0U2RrKCk6IHZvaWQge1xuICBjb25zb2xlLmxvZygnSW5zdGFsbGluZyBsYXRlc3QgQVdTIFNESyB2MicpO1xuICAvLyBCb3RoIEhPTUUgYW5kIC0tcHJlZml4IGFyZSBuZWVkZWQgaGVyZSBiZWNhdXNlIC90bXAgaXMgdGhlIG9ubHkgd3JpdGFibGUgbG9jYXRpb25cbiAgZXhlY1N5bmMoJ0hPTUU9L3RtcCBucG0gaW5zdGFsbCBhd3Mtc2RrQDIgLS1wcm9kdWN0aW9uIC0tbm8tcGFja2FnZS1sb2NrIC0tbm8tc2F2ZSAtLXByZWZpeCAvdG1wJyk7XG4gIGxhdGVzdFNka0luc3RhbGxlZCA9IHRydWU7XG59XG5cbi8vIG5vIGN1cnJlbnRseSBwYXRjaGVkIHNlcnZpY2VzXG5jb25zdCBwYXRjaGVkU2VydmljZXM6IHsgc2VydmljZU5hbWU6IHN0cmluZzsgYXBpVmVyc2lvbnM6IHN0cmluZ1tdIH1bXSA9IFtdO1xuLyoqXG4gKiBQYXRjaGVzIHRoZSBBV1MgU0RLIGJ5IGxvYWRpbmcgc2VydmljZSBtb2RlbHMgaW4gdGhlIHNhbWUgbWFubmVyIGFzIHRoZSBhY3R1YWwgU0RLXG4gKi9cbmZ1bmN0aW9uIHBhdGNoU2RrKGF3c1NkazogYW55KTogYW55IHtcbiAgY29uc3QgYXBpTG9hZGVyID0gYXdzU2RrLmFwaUxvYWRlcjtcbiAgcGF0Y2hlZFNlcnZpY2VzLmZvckVhY2goKHsgc2VydmljZU5hbWUsIGFwaVZlcnNpb25zIH0pID0+IHtcbiAgICBjb25zdCBsb3dlclNlcnZpY2VOYW1lID0gc2VydmljZU5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAoIWF3c1Nkay5TZXJ2aWNlLmhhc1NlcnZpY2UobG93ZXJTZXJ2aWNlTmFtZSkpIHtcbiAgICAgIGFwaUxvYWRlci5zZXJ2aWNlc1tsb3dlclNlcnZpY2VOYW1lXSA9IHt9O1xuICAgICAgYXdzU2RrW3NlcnZpY2VOYW1lXSA9IGF3c1Nkay5TZXJ2aWNlLmRlZmluZVNlcnZpY2UobG93ZXJTZXJ2aWNlTmFtZSwgYXBpVmVyc2lvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd3NTZGsuU2VydmljZS5hZGRWZXJzaW9ucyhhd3NTZGtbc2VydmljZU5hbWVdLCBhcGlWZXJzaW9ucyk7XG4gICAgfVxuICAgIGFwaVZlcnNpb25zLmZvckVhY2goYXBpVmVyc2lvbiA9PiB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoYXBpTG9hZGVyLnNlcnZpY2VzW2xvd2VyU2VydmljZU5hbWVdLCBhcGlWZXJzaW9uLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIGNvbnN0IG1vZGVsRmlsZVByZWZpeCA9IGBhd3Mtc2RrLXBhdGNoLyR7bG93ZXJTZXJ2aWNlTmFtZX0tJHthcGlWZXJzaW9ufWA7XG4gICAgICAgICAgY29uc3QgbW9kZWwgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhqb2luKF9fZGlybmFtZSwgYCR7bW9kZWxGaWxlUHJlZml4fS5zZXJ2aWNlLmpzb25gKSwgJ3V0Zi04JykpO1xuICAgICAgICAgIG1vZGVsLnBhZ2luYXRvcnMgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhqb2luKF9fZGlybmFtZSwgYCR7bW9kZWxGaWxlUHJlZml4fS5wYWdpbmF0b3JzLmpzb25gKSwgJ3V0Zi04JykpLnBhZ2luYXRpb247XG4gICAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBhd3NTZGs7XG59XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIHRyeSB7XG4gICAgbGV0IEFXUzogYW55O1xuICAgIGlmICghbGF0ZXN0U2RrSW5zdGFsbGVkICYmIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5JbnN0YWxsTGF0ZXN0QXdzU2RrID09PSAndHJ1ZScpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGluc3RhbGxMYXRlc3RTZGsoKTtcbiAgICAgICAgQVdTID0gcmVxdWlyZSgnL3RtcC9ub2RlX21vZHVsZXMvYXdzLXNkaycpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgRmFpbGVkIHRvIGluc3RhbGwgbGF0ZXN0IEFXUyBTREsgdjI6ICR7ZX1gKTtcbiAgICAgICAgQVdTID0gcmVxdWlyZSgnYXdzLXNkaycpOyAvLyBGYWxsYmFjayB0byBwcmUtaW5zdGFsbGVkIHZlcnNpb25cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGxhdGVzdFNka0luc3RhbGxlZCkge1xuICAgICAgQVdTID0gcmVxdWlyZSgnL3RtcC9ub2RlX21vZHVsZXMvYXdzLXNkaycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBBV1MgPSByZXF1aXJlKCdhd3Mtc2RrJyk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBBV1MgPSBwYXRjaFNkayhBV1MpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBGYWlsZWQgdG8gcGF0Y2ggQVdTIFNESzogJHtlfS4gUHJvY2VlZGluZyB3aXRoIHRoZSBpbnN0YWxsZWQgY29weS5gKTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7IC4uLmV2ZW50LCBSZXNwb25zZVVSTDogJy4uLicgfSkpO1xuICAgIGNvbnNvbGUubG9nKCdBV1MgU0RLIFZFUlNJT046ICcgKyBBV1MuVkVSU0lPTik7XG5cbiAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuQ3JlYXRlID0gZGVjb2RlQ2FsbChldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuQ3JlYXRlKTtcbiAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVXBkYXRlID0gZGVjb2RlQ2FsbChldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVXBkYXRlKTtcbiAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuRGVsZXRlID0gZGVjb2RlQ2FsbChldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuRGVsZXRlKTtcbiAgICAvLyBEZWZhdWx0IHBoeXNpY2FsIHJlc291cmNlIGlkXG4gICAgbGV0IHBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICAgIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICAgIGNhc2UgJ0NyZWF0ZSc6XG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZCA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DcmVhdGU/LnBoeXNpY2FsUmVzb3VyY2VJZD8uaWQgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlVwZGF0ZT8ucGh5c2ljYWxSZXNvdXJjZUlkPy5pZCA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuRGVsZXRlPy5waHlzaWNhbFJlc291cmNlSWQ/LmlkID8/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1VwZGF0ZSc6XG4gICAgICBjYXNlICdEZWxldGUnOlxuICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXNbZXZlbnQuUmVxdWVzdFR5cGVdPy5waHlzaWNhbFJlc291cmNlSWQ/LmlkID8/IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZDtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgbGV0IGZsYXREYXRhOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gICAgbGV0IGRhdGE6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBjb25zdCBjYWxsOiBBd3NTZGtDYWxsIHwgdW5kZWZpbmVkID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzW2V2ZW50LlJlcXVlc3RUeXBlXTtcblxuICAgIGlmIChjYWxsKSB7XG5cbiAgICAgIGxldCBjcmVkZW50aWFscztcbiAgICAgIGlmIChjYWxsLmFzc3VtZWRSb2xlQXJuKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIFJvbGVBcm46IGNhbGwuYXNzdW1lZFJvbGVBcm4sXG4gICAgICAgICAgUm9sZVNlc3Npb25OYW1lOiBgJHt0aW1lc3RhbXB9LSR7cGh5c2ljYWxSZXNvdXJjZUlkfWAuc3Vic3RyaW5nKDAsIDY0KSxcbiAgICAgICAgfTtcblxuICAgICAgICBjcmVkZW50aWFscyA9IG5ldyBBV1MuQ2hhaW5hYmxlVGVtcG9yYXJ5Q3JlZGVudGlhbHMoe1xuICAgICAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoQVdTLCBjYWxsLnNlcnZpY2UpKSB7XG4gICAgICAgIHRocm93IEVycm9yKGBTZXJ2aWNlICR7Y2FsbC5zZXJ2aWNlfSBkb2VzIG5vdCBleGlzdCBpbiBBV1MgU0RLIHZlcnNpb24gJHtBV1MuVkVSU0lPTn0uYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBhd3NTZXJ2aWNlID0gbmV3IChBV1MgYXMgYW55KVtjYWxsLnNlcnZpY2VdKHtcbiAgICAgICAgYXBpVmVyc2lvbjogY2FsbC5hcGlWZXJzaW9uLFxuICAgICAgICBjcmVkZW50aWFsczogY3JlZGVudGlhbHMsXG4gICAgICAgIHJlZ2lvbjogY2FsbC5yZWdpb24sXG4gICAgICB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhd3NTZXJ2aWNlW2NhbGwuYWN0aW9uXShcbiAgICAgICAgICBjYWxsLnBhcmFtZXRlcnMgJiYgZGVjb2RlU3BlY2lhbFZhbHVlcyhjYWxsLnBhcmFtZXRlcnMsIHBoeXNpY2FsUmVzb3VyY2VJZCkpLnByb21pc2UoKTtcbiAgICAgICAgZmxhdERhdGEgPSB7XG4gICAgICAgICAgYXBpVmVyc2lvbjogYXdzU2VydmljZS5jb25maWcuYXBpVmVyc2lvbiwgLy8gRm9yIHRlc3QgcHVycG9zZXM6IGNoZWNrIGlmIGFwaVZlcnNpb24gd2FzIGNvcnJlY3RseSBwYXNzZWQuXG4gICAgICAgICAgcmVnaW9uOiBhd3NTZXJ2aWNlLmNvbmZpZy5yZWdpb24sIC8vIEZvciB0ZXN0IHB1cnBvc2VzOiBjaGVjayBpZiByZWdpb24gd2FzIGNvcnJlY3RseSBwYXNzZWQuXG4gICAgICAgICAgLi4uZmxhdHRlbihyZXNwb25zZSksXG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IG91dHB1dFBhdGhzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGNhbGwub3V0cHV0UGF0aCkge1xuICAgICAgICAgIG91dHB1dFBhdGhzID0gW2NhbGwub3V0cHV0UGF0aF07XG4gICAgICAgIH0gZWxzZSBpZiAoY2FsbC5vdXRwdXRQYXRocykge1xuICAgICAgICAgIG91dHB1dFBhdGhzID0gY2FsbC5vdXRwdXRQYXRocztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvdXRwdXRQYXRocykge1xuICAgICAgICAgIGRhdGEgPSBmaWx0ZXJLZXlzKGZsYXREYXRhLCBzdGFydHNXaXRoT25lT2Yob3V0cHV0UGF0aHMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRhID0gZmxhdERhdGE7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCFjYWxsLmlnbm9yZUVycm9yQ29kZXNNYXRjaGluZyB8fCAhbmV3IFJlZ0V4cChjYWxsLmlnbm9yZUVycm9yQ29kZXNNYXRjaGluZykudGVzdChlLmNvZGUpKSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2FsbC5waHlzaWNhbFJlc291cmNlSWQ/LnJlc3BvbnNlUGF0aCkge1xuICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQgPSBmbGF0RGF0YVtjYWxsLnBoeXNpY2FsUmVzb3VyY2VJZC5yZXNwb25zZVBhdGhdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGF3YWl0IHJlc3BvbmQoJ1NVQ0NFU1MnLCAnT0snLCBwaHlzaWNhbFJlc291cmNlSWQsIGRhdGEpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc29sZS5sb2coZSk7XG4gICAgYXdhaXQgcmVzcG9uZCgnRkFJTEVEJywgZS5tZXNzYWdlIHx8ICdJbnRlcm5hbCBFcnJvcicsIGNvbnRleHQubG9nU3RyZWFtTmFtZSwge30pO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzcG9uZChyZXNwb25zZVN0YXR1czogc3RyaW5nLCByZWFzb246IHN0cmluZywgcGh5c2ljYWxSZXNvdXJjZUlkOiBzdHJpbmcsIGRhdGE6IGFueSkge1xuICAgIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIFN0YXR1czogcmVzcG9uc2VTdGF0dXMsXG4gICAgICBSZWFzb246IHJlYXNvbixcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgICAgTm9FY2hvOiBmYWxzZSxcbiAgICAgIERhdGE6IGRhdGEsXG4gICAgfSk7XG5cbiAgICBjb25zb2xlLmxvZygnUmVzcG9uZGluZycsIHJlc3BvbnNlQm9keSk7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHBhcnNlZFVybCA9IHJlcXVpcmUoJ3VybCcpLnBhcnNlKGV2ZW50LlJlc3BvbnNlVVJMKTtcbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgIGhvc3RuYW1lOiBwYXJzZWRVcmwuaG9zdG5hbWUsXG4gICAgICBwYXRoOiBwYXJzZWRVcmwucGF0aCxcbiAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICBoZWFkZXJzOiB7ICdjb250ZW50LXR5cGUnOiAnJywgJ2NvbnRlbnQtbGVuZ3RoJzogcmVzcG9uc2VCb2R5Lmxlbmd0aCB9LFxuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVpcmUoJ2h0dHBzJykucmVxdWVzdChyZXF1ZXN0T3B0aW9ucywgcmVzb2x2ZSk7XG4gICAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgICByZXF1ZXN0LmVuZCgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGVjb2RlQ2FsbChjYWxsOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgaWYgKCFjYWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgcmV0dXJuIEpTT04ucGFyc2UoY2FsbCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGhPbmVPZihzZWFyY2hTdHJpbmdzOiBzdHJpbmdbXSk6IChzdHJpbmc6IHN0cmluZykgPT4gYm9vbGVhbiB7XG4gIHJldHVybiBmdW5jdGlvbihzdHJpbmc6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGZvciAoY29uc3Qgc2VhcmNoU3RyaW5nIG9mIHNlYXJjaFN0cmluZ3MpIHtcbiAgICAgIGlmIChzdHJpbmcuc3RhcnRzV2l0aChzZWFyY2hTdHJpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476/index.js b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476/index.js new file mode 100644 index 0000000000000..d913ab9defaa1 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/asset.a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476/index.js @@ -0,0 +1,253 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.handler = exports.forceSdkInstallation = exports.flatten = exports.PHYSICAL_RESOURCE_ID_REFERENCE = void 0; +/* eslint-disable no-console */ +const child_process_1 = require("child_process"); +const fs = require("fs"); +const path_1 = require("path"); +/** + * Serialized form of the physical resource id for use in the operation parameters + */ +exports.PHYSICAL_RESOURCE_ID_REFERENCE = 'PHYSICAL:RESOURCEID:'; +/** + * Flattens a nested object + * + * @param object the object to be flattened + * @returns a flat object with path as keys + */ +function flatten(object) { + return Object.assign({}, ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child) + .map(key => { + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString('utf8') : child[key]; + return typeof childKey === 'object' && childKey !== null + ? _flatten(childKey, path.concat([key])) + : ({ [path.concat([key]).join('.')]: childKey }); + })); + }(object)); +} +exports.flatten = flatten; +/** + * Decodes encoded special values (physicalResourceId) + */ +function decodeSpecialValues(object, physicalResourceId) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case exports.PHYSICAL_RESOURCE_ID_REFERENCE: + return physicalResourceId; + default: + return v; + } + }); +} +/** + * Filters the keys of an object. + */ +function filterKeys(object, pred) { + return Object.entries(object) + .reduce((acc, [k, v]) => pred(k) + ? { ...acc, [k]: v } + : acc, {}); +} +let latestSdkInstalled = false; +function forceSdkInstallation() { + latestSdkInstalled = false; +} +exports.forceSdkInstallation = forceSdkInstallation; +/** + * Installs latest AWS SDK v2 + */ +function installLatestSdk() { + console.log('Installing latest AWS SDK v2'); + // Both HOME and --prefix are needed here because /tmp is the only writable location + child_process_1.execSync('HOME=/tmp npm install aws-sdk@2 --production --no-package-lock --no-save --prefix /tmp'); + latestSdkInstalled = true; +} +// no currently patched services +const patchedServices = []; +/** + * Patches the AWS SDK by loading service models in the same manner as the actual SDK + */ +function patchSdk(awsSdk) { + const apiLoader = awsSdk.apiLoader; + patchedServices.forEach(({ serviceName, apiVersions }) => { + const lowerServiceName = serviceName.toLowerCase(); + if (!awsSdk.Service.hasService(lowerServiceName)) { + apiLoader.services[lowerServiceName] = {}; + awsSdk[serviceName] = awsSdk.Service.defineService(lowerServiceName, apiVersions); + } + else { + awsSdk.Service.addVersions(awsSdk[serviceName], apiVersions); + } + apiVersions.forEach(apiVersion => { + Object.defineProperty(apiLoader.services[lowerServiceName], apiVersion, { + get: function get() { + const modelFilePrefix = `aws-sdk-patch/${lowerServiceName}-${apiVersion}`; + const model = JSON.parse(fs.readFileSync(path_1.join(__dirname, `${modelFilePrefix}.service.json`), 'utf-8')); + model.paginators = JSON.parse(fs.readFileSync(path_1.join(__dirname, `${modelFilePrefix}.paginators.json`), 'utf-8')).pagination; + return model; + }, + enumerable: true, + configurable: true, + }); + }); + }); + return awsSdk; +} +/* eslint-disable @typescript-eslint/no-require-imports, import/no-extraneous-dependencies */ +async function handler(event, context) { + try { + let AWS; + if (!latestSdkInstalled && event.ResourceProperties.InstallLatestAwsSdk === 'true') { + try { + installLatestSdk(); + AWS = require('/tmp/node_modules/aws-sdk'); + } + catch (e) { + console.log(`Failed to install latest AWS SDK v2: ${e}`); + AWS = require('aws-sdk'); // Fallback to pre-installed version + } + } + else if (latestSdkInstalled) { + AWS = require('/tmp/node_modules/aws-sdk'); + } + else { + AWS = require('aws-sdk'); + } + try { + AWS = patchSdk(AWS); + } + catch (e) { + console.log(`Failed to patch AWS SDK: ${e}. Proceeding with the installed copy.`); + } + console.log(JSON.stringify({ ...event, ResponseURL: '...' })); + console.log('AWS SDK VERSION: ' + AWS.VERSION); + event.ResourceProperties.Create = decodeCall(event.ResourceProperties.Create); + event.ResourceProperties.Update = decodeCall(event.ResourceProperties.Update); + event.ResourceProperties.Delete = decodeCall(event.ResourceProperties.Delete); + // Default physical resource id + let physicalResourceId; + switch (event.RequestType) { + case 'Create': + physicalResourceId = event.ResourceProperties.Create?.physicalResourceId?.id ?? + event.ResourceProperties.Update?.physicalResourceId?.id ?? + event.ResourceProperties.Delete?.physicalResourceId?.id ?? + event.LogicalResourceId; + break; + case 'Update': + case 'Delete': + physicalResourceId = event.ResourceProperties[event.RequestType]?.physicalResourceId?.id ?? event.PhysicalResourceId; + break; + } + let flatData = {}; + let data = {}; + const call = event.ResourceProperties[event.RequestType]; + if (call) { + let credentials; + if (call.assumedRoleArn) { + const timestamp = (new Date()).getTime(); + const params = { + RoleArn: call.assumedRoleArn, + RoleSessionName: `${timestamp}-${physicalResourceId}`.substring(0, 64), + }; + credentials = new AWS.ChainableTemporaryCredentials({ + params: params, + stsConfig: { stsRegionalEndpoints: 'regional' }, + }); + } + if (!Object.prototype.hasOwnProperty.call(AWS, call.service)) { + throw Error(`Service ${call.service} does not exist in AWS SDK version ${AWS.VERSION}.`); + } + const awsService = new AWS[call.service]({ + apiVersion: call.apiVersion, + credentials: credentials, + region: call.region, + }); + try { + const response = await awsService[call.action](call.parameters && decodeSpecialValues(call.parameters, physicalResourceId)).promise(); + flatData = { + apiVersion: awsService.config.apiVersion, + region: awsService.config.region, + ...flatten(response), + }; + let outputPaths; + if (call.outputPath) { + outputPaths = [call.outputPath]; + } + else if (call.outputPaths) { + outputPaths = call.outputPaths; + } + if (outputPaths) { + data = filterKeys(flatData, startsWithOneOf(outputPaths)); + } + else { + data = flatData; + } + } + catch (e) { + if (!call.ignoreErrorCodesMatching || !new RegExp(call.ignoreErrorCodesMatching).test(e.code)) { + throw e; + } + } + if (call.physicalResourceId?.responsePath) { + physicalResourceId = flatData[call.physicalResourceId.responsePath]; + } + } + await respond('SUCCESS', 'OK', physicalResourceId, data); + } + catch (e) { + console.log(e); + await respond('FAILED', e.message || 'Internal Error', context.logStreamName, {}); + } + function respond(responseStatus, reason, physicalResourceId, data) { + const responseBody = JSON.stringify({ + Status: responseStatus, + Reason: reason, + PhysicalResourceId: physicalResourceId, + StackId: event.StackId, + RequestId: event.RequestId, + LogicalResourceId: event.LogicalResourceId, + NoEcho: false, + Data: data, + }); + 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); + } + }); + } +} +exports.handler = handler; +function decodeCall(call) { + if (!call) { + return undefined; + } + return JSON.parse(call); +} +function startsWithOneOf(searchStrings) { + return function (string) { + for (const searchString of searchStrings) { + if (string.startsWith(searchString)) { + return true; + } + } + return false; + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsaURBQXlDO0FBQ3pDLHlCQUF5QjtBQUN6QiwrQkFBNEI7QUFTNUI7O0dBRUc7QUFDVSxRQUFBLDhCQUE4QixHQUFHLHNCQUFzQixDQUFDO0FBRXJFOzs7OztHQUtHO0FBQ0gsU0FBZ0IsT0FBTyxDQUFDLE1BQWM7SUFDcEMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUNsQixFQUFFLEVBQ0YsR0FBRyxTQUFTLFFBQVEsQ0FBQyxLQUFVLEVBQUUsT0FBaUIsRUFBRTtRQUNsRCxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQzthQUNuQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDVCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEYsT0FBTyxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxLQUFLLElBQUk7Z0JBQ3RELENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUN4QyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUNWLENBQUM7QUFDSixDQUFDO0FBYkQsMEJBYUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsTUFBYyxFQUFFLGtCQUEwQjtJQUNyRSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNsRCxRQUFRLENBQUMsRUFBRTtZQUNULEtBQUssc0NBQThCO2dCQUNqQyxPQUFPLGtCQUFrQixDQUFDO1lBQzVCO2dCQUNFLE9BQU8sQ0FBQyxDQUFDO1NBQ1o7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsVUFBVSxDQUFDLE1BQWMsRUFBRSxJQUE4QjtJQUNoRSxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1NBQzFCLE1BQU0sQ0FDTCxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtRQUNwQixDQUFDLENBQUMsR0FBRyxFQUNQLEVBQUUsQ0FDSCxDQUFDO0FBQ04sQ0FBQztBQUVELElBQUksa0JBQWtCLEdBQUcsS0FBSyxDQUFDO0FBRS9CLFNBQWdCLG9CQUFvQjtJQUNsQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7QUFDN0IsQ0FBQztBQUZELG9EQUVDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQjtJQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDNUMsb0ZBQW9GO0lBQ3BGLHdCQUFRLENBQUMsd0ZBQXdGLENBQUMsQ0FBQztJQUNuRyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7QUFDNUIsQ0FBQztBQUVELGdDQUFnQztBQUNoQyxNQUFNLGVBQWUsR0FBcUQsRUFBRSxDQUFDO0FBQzdFOztHQUVHO0FBQ0gsU0FBUyxRQUFRLENBQUMsTUFBVztJQUMzQixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO0lBQ25DLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFO1FBQ3ZELE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFO1lBQ2hELFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDMUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDO1NBQ25GO2FBQU07WUFDTCxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDOUQ7UUFDRCxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQy9CLE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFVBQVUsRUFBRTtnQkFDdEUsR0FBRyxFQUFFLFNBQVMsR0FBRztvQkFDZixNQUFNLGVBQWUsR0FBRyxpQkFBaUIsZ0JBQWdCLElBQUksVUFBVSxFQUFFLENBQUM7b0JBQzFFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsZUFBZSxlQUFlLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUN2RyxLQUFLLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsZUFBZSxrQkFBa0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO29CQUMxSCxPQUFPLEtBQUssQ0FBQztnQkFDZixDQUFDO2dCQUNELFVBQVUsRUFBRSxJQUFJO2dCQUNoQixZQUFZLEVBQUUsSUFBSTthQUNuQixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVELDZGQUE2RjtBQUN0RixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsSUFBSTtRQUNGLElBQUksR0FBUSxDQUFDO1FBQ2IsSUFBSSxDQUFDLGtCQUFrQixJQUFJLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsS0FBSyxNQUFNLEVBQUU7WUFDbEYsSUFBSTtnQkFDRixnQkFBZ0IsRUFBRSxDQUFDO2dCQUNuQixHQUFHLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBQUM7YUFDNUM7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixPQUFPLENBQUMsR0FBRyxDQUFDLHdDQUF3QyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6RCxHQUFHLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsb0NBQW9DO2FBQy9EO1NBQ0Y7YUFBTSxJQUFJLGtCQUFrQixFQUFFO1lBQzdCLEdBQUcsR0FBRyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQztTQUM1QzthQUFNO1lBQ0wsR0FBRyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMxQjtRQUNELElBQUk7WUFDRixHQUFHLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3JCO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLDRCQUE0QixDQUFDLHVDQUF1QyxDQUFDLENBQUM7U0FDbkY7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9DLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5RSxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlFLCtCQUErQjtRQUMvQixJQUFJLGtCQUEwQixDQUFDO1FBQy9CLFFBQVEsS0FBSyxDQUFDLFdBQVcsRUFBRTtZQUN6QixLQUFLLFFBQVE7Z0JBQ1gsa0JBQWtCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxFQUFFO29CQUN2RCxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxFQUFFLGtCQUFrQixFQUFFLEVBQUU7b0JBQ3ZELEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsRUFBRTtvQkFDdkQsS0FBSyxDQUFDLGlCQUFpQixDQUFDO2dCQUM3QyxNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUM7WUFDZCxLQUFLLFFBQVE7Z0JBQ1gsa0JBQWtCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxFQUFFLElBQUksS0FBSyxDQUFDLGtCQUFrQixDQUFDO2dCQUNySCxNQUFNO1NBQ1Q7UUFFRCxJQUFJLFFBQVEsR0FBOEIsRUFBRSxDQUFDO1FBQzdDLElBQUksSUFBSSxHQUE4QixFQUFFLENBQUM7UUFDekMsTUFBTSxJQUFJLEdBQTJCLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFakYsSUFBSSxJQUFJLEVBQUU7WUFFUixJQUFJLFdBQVcsQ0FBQztZQUNoQixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3ZCLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUV6QyxNQUFNLE1BQU0sR0FBRztvQkFDYixPQUFPLEVBQUUsSUFBSSxDQUFDLGNBQWM7b0JBQzVCLGVBQWUsRUFBRSxHQUFHLFNBQVMsSUFBSSxrQkFBa0IsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO2lCQUN2RSxDQUFDO2dCQUVGLFdBQVcsR0FBRyxJQUFJLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQztvQkFDbEQsTUFBTSxFQUFFLE1BQU07b0JBQ2QsU0FBUyxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsVUFBVSxFQUFFO2lCQUNoRCxDQUFDLENBQUM7YUFDSjtZQUVELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDNUQsTUFBTSxLQUFLLENBQUMsV0FBVyxJQUFJLENBQUMsT0FBTyxzQ0FBc0MsR0FBRyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7YUFDMUY7WUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFLLEdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2hELFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDM0IsV0FBVyxFQUFFLFdBQVc7Z0JBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTthQUNwQixDQUFDLENBQUM7WUFFSCxJQUFJO2dCQUNGLE1BQU0sUUFBUSxHQUFHLE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FDNUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDekYsUUFBUSxHQUFHO29CQUNULFVBQVUsRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVU7b0JBQ3hDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU07b0JBQ2hDLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztpQkFDckIsQ0FBQztnQkFFRixJQUFJLFdBQWlDLENBQUM7Z0JBQ3RDLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtvQkFDbkIsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUNqQztxQkFBTSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7b0JBQzNCLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2lCQUNoQztnQkFFRCxJQUFJLFdBQVcsRUFBRTtvQkFDZixJQUFJLEdBQUcsVUFBVSxDQUFDLFFBQVEsRUFBRSxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztpQkFDM0Q7cUJBQU07b0JBQ0wsSUFBSSxHQUFHLFFBQVEsQ0FBQztpQkFDakI7YUFDRjtZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNWLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFO29CQUM3RixNQUFNLENBQUMsQ0FBQztpQkFDVDthQUNGO1lBRUQsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsWUFBWSxFQUFFO2dCQUN6QyxrQkFBa0IsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQ3JFO1NBQ0Y7UUFFRCxNQUFNLE9BQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLElBQUksQ0FBQyxDQUFDO0tBQzFEO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2YsTUFBTSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxPQUFPLElBQUksZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztLQUNuRjtJQUVELFNBQVMsT0FBTyxDQUFDLGNBQXNCLEVBQUUsTUFBYyxFQUFFLGtCQUEwQixFQUFFLElBQVM7UUFDNUYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNsQyxNQUFNLEVBQUUsY0FBYztZQUN0QixNQUFNLEVBQUUsTUFBTTtZQUNkLGtCQUFrQixFQUFFLGtCQUFrQjtZQUN0QyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1lBQzFCLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxpQkFBaUI7WUFDMUMsTUFBTSxFQUFFLEtBQUs7WUFDYixJQUFJLEVBQUUsSUFBSTtTQUNYLENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBRXhDLGlFQUFpRTtRQUNqRSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxNQUFNLGNBQWMsR0FBRztZQUNyQixRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7WUFDNUIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO1lBQ3BCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsTUFBTSxFQUFFO1NBQ3ZFLENBQUM7UUFFRixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUk7Z0JBQ0YsaUVBQWlFO2dCQUNqRSxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDbEUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQzthQUNmO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ1g7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7QUFDSCxDQUFDO0FBbEpELDBCQWtKQztBQUVELFNBQVMsVUFBVSxDQUFDLElBQXdCO0lBQzFDLElBQUksQ0FBQyxJQUFJLEVBQUU7UUFBRSxPQUFPLFNBQVMsQ0FBQztLQUFFO0lBQ2hDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsYUFBdUI7SUFDOUMsT0FBTyxVQUFTLE1BQWM7UUFDNUIsS0FBSyxNQUFNLFlBQVksSUFBSSxhQUFhLEVBQUU7WUFDeEMsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFO2dCQUNuQyxPQUFPLElBQUksQ0FBQzthQUNiO1NBQ0Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgeyBleGVjU3luYyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ3BhdGgnO1xuLy8gaW1wb3J0IHRoZSBBV1NMYW1iZGEgcGFja2FnZSBleHBsaWNpdGx5LFxuLy8gd2hpY2ggaXMgZ2xvYmFsbHkgYXZhaWxhYmxlIGluIHRoZSBMYW1iZGEgcnVudGltZSxcbi8vIGFzIG90aGVyd2lzZSBsaW5raW5nIHRoaXMgcmVwb3NpdG9yeSB3aXRoIGxpbmstYWxsLnNoXG4vLyBmYWlscyBpbiB0aGUgQ0RLIGFwcCBleGVjdXRlZCB3aXRoIHRzLW5vZGVcbi8qIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMsaW1wb3J0L25vLXVucmVzb2x2ZWQgKi9cbmltcG9ydCAqIGFzIEFXU0xhbWJkYSBmcm9tICdhd3MtbGFtYmRhJztcbmltcG9ydCB7IEF3c1Nka0NhbGwgfSBmcm9tICcuLi9hd3MtY3VzdG9tLXJlc291cmNlJztcblxuLyoqXG4gKiBTZXJpYWxpemVkIGZvcm0gb2YgdGhlIHBoeXNpY2FsIHJlc291cmNlIGlkIGZvciB1c2UgaW4gdGhlIG9wZXJhdGlvbiBwYXJhbWV0ZXJzXG4gKi9cbmV4cG9ydCBjb25zdCBQSFlTSUNBTF9SRVNPVVJDRV9JRF9SRUZFUkVOQ0UgPSAnUEhZU0lDQUw6UkVTT1VSQ0VJRDonO1xuXG4vKipcbiAqIEZsYXR0ZW5zIGEgbmVzdGVkIG9iamVjdFxuICpcbiAqIEBwYXJhbSBvYmplY3QgdGhlIG9iamVjdCB0byBiZSBmbGF0dGVuZWRcbiAqIEByZXR1cm5zIGEgZmxhdCBvYmplY3Qgd2l0aCBwYXRoIGFzIGtleXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW4ob2JqZWN0OiBvYmplY3QpOiB7IFtrZXk6IHN0cmluZ106IGFueSB9IHtcbiAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXG4gICAge30sXG4gICAgLi4uZnVuY3Rpb24gX2ZsYXR0ZW4oY2hpbGQ6IGFueSwgcGF0aDogc3RyaW5nW10gPSBbXSk6IGFueSB7XG4gICAgICByZXR1cm4gW10uY29uY2F0KC4uLk9iamVjdC5rZXlzKGNoaWxkKVxuICAgICAgICAubWFwKGtleSA9PiB7XG4gICAgICAgICAgY29uc3QgY2hpbGRLZXkgPSBCdWZmZXIuaXNCdWZmZXIoY2hpbGRba2V5XSkgPyBjaGlsZFtrZXldLnRvU3RyaW5nKCd1dGY4JykgOiBjaGlsZFtrZXldO1xuICAgICAgICAgIHJldHVybiB0eXBlb2YgY2hpbGRLZXkgPT09ICdvYmplY3QnICYmIGNoaWxkS2V5ICE9PSBudWxsXG4gICAgICAgICAgICA/IF9mbGF0dGVuKGNoaWxkS2V5LCBwYXRoLmNvbmNhdChba2V5XSkpXG4gICAgICAgICAgICA6ICh7IFtwYXRoLmNvbmNhdChba2V5XSkuam9pbignLicpXTogY2hpbGRLZXkgfSk7XG4gICAgICAgIH0pKTtcbiAgICB9KG9iamVjdCksXG4gICk7XG59XG5cbi8qKlxuICogRGVjb2RlcyBlbmNvZGVkIHNwZWNpYWwgdmFsdWVzIChwaHlzaWNhbFJlc291cmNlSWQpXG4gKi9cbmZ1bmN0aW9uIGRlY29kZVNwZWNpYWxWYWx1ZXMob2JqZWN0OiBvYmplY3QsIHBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nKSB7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iamVjdCksIChfaywgdikgPT4ge1xuICAgIHN3aXRjaCAodikge1xuICAgICAgY2FzZSBQSFlTSUNBTF9SRVNPVVJDRV9JRF9SRUZFUkVOQ0U6XG4gICAgICAgIHJldHVybiBwaHlzaWNhbFJlc291cmNlSWQ7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdjtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIEZpbHRlcnMgdGhlIGtleXMgb2YgYW4gb2JqZWN0LlxuICovXG5mdW5jdGlvbiBmaWx0ZXJLZXlzKG9iamVjdDogb2JqZWN0LCBwcmVkOiAoa2V5OiBzdHJpbmcpID0+IGJvb2xlYW4pIHtcbiAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKG9iamVjdClcbiAgICAucmVkdWNlKFxuICAgICAgKGFjYywgW2ssIHZdKSA9PiBwcmVkKGspXG4gICAgICAgID8geyAuLi5hY2MsIFtrXTogdiB9XG4gICAgICAgIDogYWNjLFxuICAgICAge30sXG4gICAgKTtcbn1cblxubGV0IGxhdGVzdFNka0luc3RhbGxlZCA9IGZhbHNlO1xuXG5leHBvcnQgZnVuY3Rpb24gZm9yY2VTZGtJbnN0YWxsYXRpb24oKSB7XG4gIGxhdGVzdFNka0luc3RhbGxlZCA9IGZhbHNlO1xufVxuXG4vKipcbiAqIEluc3RhbGxzIGxhdGVzdCBBV1MgU0RLIHYyXG4gKi9cbmZ1bmN0aW9uIGluc3RhbGxMYXRlc3RTZGsoKTogdm9pZCB7XG4gIGNvbnNvbGUubG9nKCdJbnN0YWxsaW5nIGxhdGVzdCBBV1MgU0RLIHYyJyk7XG4gIC8vIEJvdGggSE9NRSBhbmQgLS1wcmVmaXggYXJlIG5lZWRlZCBoZXJlIGJlY2F1c2UgL3RtcCBpcyB0aGUgb25seSB3cml0YWJsZSBsb2NhdGlvblxuICBleGVjU3luYygnSE9NRT0vdG1wIG5wbSBpbnN0YWxsIGF3cy1zZGtAMiAtLXByb2R1Y3Rpb24gLS1uby1wYWNrYWdlLWxvY2sgLS1uby1zYXZlIC0tcHJlZml4IC90bXAnKTtcbiAgbGF0ZXN0U2RrSW5zdGFsbGVkID0gdHJ1ZTtcbn1cblxuLy8gbm8gY3VycmVudGx5IHBhdGNoZWQgc2VydmljZXNcbmNvbnN0IHBhdGNoZWRTZXJ2aWNlczogeyBzZXJ2aWNlTmFtZTogc3RyaW5nOyBhcGlWZXJzaW9uczogc3RyaW5nW10gfVtdID0gW107XG4vKipcbiAqIFBhdGNoZXMgdGhlIEFXUyBTREsgYnkgbG9hZGluZyBzZXJ2aWNlIG1vZGVscyBpbiB0aGUgc2FtZSBtYW5uZXIgYXMgdGhlIGFjdHVhbCBTREtcbiAqL1xuZnVuY3Rpb24gcGF0Y2hTZGsoYXdzU2RrOiBhbnkpOiBhbnkge1xuICBjb25zdCBhcGlMb2FkZXIgPSBhd3NTZGsuYXBpTG9hZGVyO1xuICBwYXRjaGVkU2VydmljZXMuZm9yRWFjaCgoeyBzZXJ2aWNlTmFtZSwgYXBpVmVyc2lvbnMgfSkgPT4ge1xuICAgIGNvbnN0IGxvd2VyU2VydmljZU5hbWUgPSBzZXJ2aWNlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghYXdzU2RrLlNlcnZpY2UuaGFzU2VydmljZShsb3dlclNlcnZpY2VOYW1lKSkge1xuICAgICAgYXBpTG9hZGVyLnNlcnZpY2VzW2xvd2VyU2VydmljZU5hbWVdID0ge307XG4gICAgICBhd3NTZGtbc2VydmljZU5hbWVdID0gYXdzU2RrLlNlcnZpY2UuZGVmaW5lU2VydmljZShsb3dlclNlcnZpY2VOYW1lLCBhcGlWZXJzaW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3c1Nkay5TZXJ2aWNlLmFkZFZlcnNpb25zKGF3c1Nka1tzZXJ2aWNlTmFtZV0sIGFwaVZlcnNpb25zKTtcbiAgICB9XG4gICAgYXBpVmVyc2lvbnMuZm9yRWFjaChhcGlWZXJzaW9uID0+IHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcGlMb2FkZXIuc2VydmljZXNbbG93ZXJTZXJ2aWNlTmFtZV0sIGFwaVZlcnNpb24sIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgY29uc3QgbW9kZWxGaWxlUHJlZml4ID0gYGF3cy1zZGstcGF0Y2gvJHtsb3dlclNlcnZpY2VOYW1lfS0ke2FwaVZlcnNpb259YDtcbiAgICAgICAgICBjb25zdCBtb2RlbCA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGpvaW4oX19kaXJuYW1lLCBgJHttb2RlbEZpbGVQcmVmaXh9LnNlcnZpY2UuanNvbmApLCAndXRmLTgnKSk7XG4gICAgICAgICAgbW9kZWwucGFnaW5hdG9ycyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGpvaW4oX19kaXJuYW1lLCBgJHttb2RlbEZpbGVQcmVmaXh9LnBhZ2luYXRvcnMuanNvbmApLCAndXRmLTgnKSkucGFnaW5hdGlvbjtcbiAgICAgICAgICByZXR1cm4gbW9kZWw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGF3c1Nkaztcbn1cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpIHtcbiAgdHJ5IHtcbiAgICBsZXQgQVdTOiBhbnk7XG4gICAgaWYgKCFsYXRlc3RTZGtJbnN0YWxsZWQgJiYgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkluc3RhbGxMYXRlc3RBd3NTZGsgPT09ICd0cnVlJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaW5zdGFsbExhdGVzdFNkaygpO1xuICAgICAgICBBV1MgPSByZXF1aXJlKCcvdG1wL25vZGVfbW9kdWxlcy9hd3Mtc2RrJyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBGYWlsZWQgdG8gaW5zdGFsbCBsYXRlc3QgQVdTIFNESyB2MjogJHtlfWApO1xuICAgICAgICBBV1MgPSByZXF1aXJlKCdhd3Mtc2RrJyk7IC8vIEZhbGxiYWNrIHRvIHByZS1pbnN0YWxsZWQgdmVyc2lvblxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobGF0ZXN0U2RrSW5zdGFsbGVkKSB7XG4gICAgICBBV1MgPSByZXF1aXJlKCcvdG1wL25vZGVfbW9kdWxlcy9hd3Mtc2RrJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIEFXUyA9IHJlcXVpcmUoJ2F3cy1zZGsnKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIEFXUyA9IHBhdGNoU2RrKEFXUyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5sb2coYEZhaWxlZCB0byBwYXRjaCBBV1MgU0RLOiAke2V9LiBQcm9jZWVkaW5nIHdpdGggdGhlIGluc3RhbGxlZCBjb3B5LmApO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHsgLi4uZXZlbnQsIFJlc3BvbnNlVVJMOiAnLi4uJyB9KSk7XG4gICAgY29uc29sZS5sb2coJ0FXUyBTREsgVkVSU0lPTjogJyArIEFXUy5WRVJTSU9OKTtcblxuICAgIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DcmVhdGUgPSBkZWNvZGVDYWxsKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DcmVhdGUpO1xuICAgIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5VcGRhdGUgPSBkZWNvZGVDYWxsKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5VcGRhdGUpO1xuICAgIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5EZWxldGUgPSBkZWNvZGVDYWxsKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5EZWxldGUpO1xuICAgIC8vIERlZmF1bHQgcGh5c2ljYWwgcmVzb3VyY2UgaWRcbiAgICBsZXQgcGh5c2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gICAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgICAgY2FzZSAnQ3JlYXRlJzpcbiAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNyZWF0ZT8ucGh5c2ljYWxSZXNvdXJjZUlkPy5pZCA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVXBkYXRlPy5waHlzaWNhbFJlc291cmNlSWQ/LmlkID8/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5EZWxldGU/LnBoeXNpY2FsUmVzb3VyY2VJZD8uaWQgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuTG9naWNhbFJlc291cmNlSWQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6XG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZCA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllc1tldmVudC5SZXF1ZXN0VHlwZV0/LnBoeXNpY2FsUmVzb3VyY2VJZD8uaWQgPz8gZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBsZXQgZmxhdERhdGE6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBsZXQgZGF0YTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGNvbnN0IGNhbGw6IEF3c1Nka0NhbGwgfCB1bmRlZmluZWQgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXNbZXZlbnQuUmVxdWVzdFR5cGVdO1xuXG4gICAgaWYgKGNhbGwpIHtcblxuICAgICAgbGV0IGNyZWRlbnRpYWxzO1xuICAgICAgaWYgKGNhbGwuYXNzdW1lZFJvbGVBcm4pIHtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgUm9sZUFybjogY2FsbC5hc3N1bWVkUm9sZUFybixcbiAgICAgICAgICBSb2xlU2Vzc2lvbk5hbWU6IGAke3RpbWVzdGFtcH0tJHtwaHlzaWNhbFJlc291cmNlSWR9YC5zdWJzdHJpbmcoMCwgNjQpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNyZWRlbnRpYWxzID0gbmV3IEFXUy5DaGFpbmFibGVUZW1wb3JhcnlDcmVkZW50aWFscyh7XG4gICAgICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICAgICAgc3RzQ29uZmlnOiB7IHN0c1JlZ2lvbmFsRW5kcG9pbnRzOiAncmVnaW9uYWwnIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChBV1MsIGNhbGwuc2VydmljZSkpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoYFNlcnZpY2UgJHtjYWxsLnNlcnZpY2V9IGRvZXMgbm90IGV4aXN0IGluIEFXUyBTREsgdmVyc2lvbiAke0FXUy5WRVJTSU9OfS5gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF3c1NlcnZpY2UgPSBuZXcgKEFXUyBhcyBhbnkpW2NhbGwuc2VydmljZV0oe1xuICAgICAgICBhcGlWZXJzaW9uOiBjYWxsLmFwaVZlcnNpb24sXG4gICAgICAgIGNyZWRlbnRpYWxzOiBjcmVkZW50aWFscyxcbiAgICAgICAgcmVnaW9uOiBjYWxsLnJlZ2lvbixcbiAgICAgIH0pO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF3c1NlcnZpY2VbY2FsbC5hY3Rpb25dKFxuICAgICAgICAgIGNhbGwucGFyYW1ldGVycyAmJiBkZWNvZGVTcGVjaWFsVmFsdWVzKGNhbGwucGFyYW1ldGVycywgcGh5c2ljYWxSZXNvdXJjZUlkKSkucHJvbWlzZSgpO1xuICAgICAgICBmbGF0RGF0YSA9IHtcbiAgICAgICAgICBhcGlWZXJzaW9uOiBhd3NTZXJ2aWNlLmNvbmZpZy5hcGlWZXJzaW9uLCAvLyBGb3IgdGVzdCBwdXJwb3NlczogY2hlY2sgaWYgYXBpVmVyc2lvbiB3YXMgY29ycmVjdGx5IHBhc3NlZC5cbiAgICAgICAgICByZWdpb246IGF3c1NlcnZpY2UuY29uZmlnLnJlZ2lvbiwgLy8gRm9yIHRlc3QgcHVycG9zZXM6IGNoZWNrIGlmIHJlZ2lvbiB3YXMgY29ycmVjdGx5IHBhc3NlZC5cbiAgICAgICAgICAuLi5mbGF0dGVuKHJlc3BvbnNlKSxcbiAgICAgICAgfTtcblxuICAgICAgICBsZXQgb3V0cHV0UGF0aHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY2FsbC5vdXRwdXRQYXRoKSB7XG4gICAgICAgICAgb3V0cHV0UGF0aHMgPSBbY2FsbC5vdXRwdXRQYXRoXTtcbiAgICAgICAgfSBlbHNlIGlmIChjYWxsLm91dHB1dFBhdGhzKSB7XG4gICAgICAgICAgb3V0cHV0UGF0aHMgPSBjYWxsLm91dHB1dFBhdGhzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG91dHB1dFBhdGhzKSB7XG4gICAgICAgICAgZGF0YSA9IGZpbHRlcktleXMoZmxhdERhdGEsIHN0YXJ0c1dpdGhPbmVPZihvdXRwdXRQYXRocykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGEgPSBmbGF0RGF0YTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIWNhbGwuaWdub3JlRXJyb3JDb2Rlc01hdGNoaW5nIHx8ICFuZXcgUmVnRXhwKGNhbGwuaWdub3JlRXJyb3JDb2Rlc01hdGNoaW5nKS50ZXN0KGUuY29kZSkpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYWxsLnBoeXNpY2FsUmVzb3VyY2VJZD8ucmVzcG9uc2VQYXRoKSB7XG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZCA9IGZsYXREYXRhW2NhbGwucGh5c2ljYWxSZXNvdXJjZUlkLnJlc3BvbnNlUGF0aF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgcmVzcG9uZCgnU1VDQ0VTUycsICdPSycsIHBoeXNpY2FsUmVzb3VyY2VJZCwgZGF0YSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmxvZyhlKTtcbiAgICBhd2FpdCByZXNwb25kKCdGQUlMRUQnLCBlLm1lc3NhZ2UgfHwgJ0ludGVybmFsIEVycm9yJywgY29udGV4dC5sb2dTdHJlYW1OYW1lLCB7fSk7XG4gIH1cblxuICBmdW5jdGlvbiByZXNwb25kKHJlc3BvbnNlU3RhdHVzOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nLCBwaHlzaWNhbFJlc291cmNlSWQ6IHN0cmluZywgZGF0YTogYW55KSB7XG4gICAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgU3RhdHVzOiByZXNwb25zZVN0YXR1cyxcbiAgICAgIFJlYXNvbjogcmVhc29uLFxuICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gICAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgICBMb2dpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgICBOb0VjaG86IGZhbHNlLFxuICAgICAgRGF0YTogZGF0YSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKCdSZXNwb25kaW5nJywgcmVzcG9uc2VCb2R5KTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgcGFyc2VkVXJsID0gcmVxdWlyZSgndXJsJykucGFyc2UoZXZlbnQuUmVzcG9uc2VVUkwpO1xuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiByZXNwb25zZUJvZHkubGVuZ3RoIH0sXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgICAgICBjb25zdCByZXF1ZXN0ID0gcmVxdWlyZSgnaHR0cHMnKS5yZXF1ZXN0KHJlcXVlc3RPcHRpb25zLCByZXNvbHZlKTtcbiAgICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkZWNvZGVDYWxsKGNhbGw6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICBpZiAoIWNhbGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuICByZXR1cm4gSlNPTi5wYXJzZShjYWxsKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aE9uZU9mKHNlYXJjaFN0cmluZ3M6IHN0cmluZ1tdKTogKHN0cmluZzogc3RyaW5nKSA9PiBib29sZWFuIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZzogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgZm9yIChjb25zdCBzZWFyY2hTdHJpbmcgb2Ygc2VhcmNoU3RyaW5ncykge1xuICAgICAgaWYgKHN0cmluZy5zdGFydHNXaXRoKHNlYXJjaFN0cmluZykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/cdk.out b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/cdk.out index 588d7b269d34f..8ecc185e9dbee 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.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-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.assets.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.assets.json index 969d21c874896..f85aabe27e77e 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.assets.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.assets.json @@ -1,20 +1,20 @@ { - "version": "20.0.0", + "version": "21.0.0", "files": { - "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286": { + "a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476": { "source": { - "path": "asset.105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286", + "path": "asset.a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286.zip", + "objectKey": "a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "800ae0e8612e8f6d8cb727c55cf20dc51d4cbcc37c1e1701560675517ff5134a": { + "c2d925005ce1ea0db47e73cb0e76cc9f0f9347ede3ba8abe8f0768effe102872": { "source": { "path": "integ-user-pool-client-explicit-props.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "800ae0e8612e8f6d8cb727c55cf20dc51d4cbcc37c1e1701560675517ff5134a.json", + "objectKey": "c2d925005ce1ea0db47e73cb0e76cc9f0f9347ede3ba8abe8f0768effe102872.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-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json index da5a9d5a2388d..f76f3ff409e22 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json @@ -59,6 +59,7 @@ "profile", "aws.cognito.signin.user.admin" ], + "AuthSessionValidity": 3, "CallbackURLs": [ "https://redirect-here.myapp.com" ], @@ -203,7 +204,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286.zip" + "S3Key": "a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ.json index 9a94e157d7d16..556572edaf738 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "21.0.0", "testCases": { "integ.user-pool-client-explicit-props": { "stacks": [ diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/manifest.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/manifest.json index e46124e0f630a..50556b9c7f614 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "21.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "integ-user-pool-client-explicit-props.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,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}/800ae0e8612e8f6d8cb727c55cf20dc51d4cbcc37c1e1701560675517ff5134a.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c2d925005ce1ea0db47e73cb0e76cc9f0f9347ede3ba8abe8f0768effe102872.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -95,6 +89,12 @@ ] }, "displayName": "integ-user-pool-client-explicit-props" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json index cee7825f705ba..350f08f329fe5 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "integ-user-pool-client-explicit-props": { "id": "integ-user-pool-client-explicit-props", "path": "integ-user-pool-client-explicit-props", @@ -92,6 +84,7 @@ "profile", "aws.cognito.signin.user.admin" ], + "authSessionValidity": 3, "callbackUrLs": [ "https://redirect-here.myapp.com" ], @@ -156,14 +149,14 @@ "id": "Default", "path": "integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Resource/Default", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" } }, "CustomResourcePolicy": { @@ -236,6 +229,14 @@ "id": "ServiceRole", "path": "integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/Resource", @@ -289,8 +290,8 @@ "id": "Stage", "path": "integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -317,7 +318,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "105b4f39ae68785e705640aa91919e412fcba2dd454aca53412747be8d955286.zip" + "s3Key": "a268caa53756f51bda8ad5f499be4ed8484a81b314811806fbb66f874837c476.zip" }, "role": { "Fn::GetAtt": [ @@ -369,17 +370,41 @@ "fqn": "@aws-cdk/aws-secretsmanager.Secret", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-user-pool-client-explicit-props/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-user-pool-client-explicit-props/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.161" } } }, "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-cognito/test/integ.user-pool-client-explicit-props.ts b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.ts index 26f715f29180d..1c12e2104a4ba 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.ts +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-client-explicit-props.ts @@ -1,5 +1,5 @@ import { Secret } from '@aws-cdk/aws-secretsmanager'; -import { App, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { App, Duration, RemovalPolicy, Stack } from '@aws-cdk/core'; import { ClientAttributes, OAuthScope, StringAttribute, UserPool } from '../lib'; const app = new App(); @@ -37,6 +37,7 @@ const client = userpool.addClient('myuserpoolclient', { callbackUrls: ['https://redirect-here.myapp.com'], }, preventUserExistenceErrors: true, + authSessionValidity: Duration.minutes(3), writeAttributes: (new ClientAttributes()).withStandardAttributes( { address: true, diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json new file mode 100644 index 0000000000000..ab8ca0bd4a1f2 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "IntegTestDefaultTestDeployAssertE3E7D2A4.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-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.template.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.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-cognito/test/integ.user-pool-ses-email.js.snapshot/cdk.out b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/cdk.out index 588d7b269d34f..145739f539580 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.assets.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.assets.json new file mode 100644 index 0000000000000..f41ed844f36e1 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "55384e618066ba251d0576ca224e2109d90f1e97e067d2d9bfb1476d43fff838": { + "source": { + "path": "integ-user-ses-email.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "55384e618066ba251d0576ca224e2109d90f1e97e067d2d9bfb1476d43fff838.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-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.template.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.template.json similarity index 97% rename from packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.template.json rename to packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.template.json index 76d04227ceaed..06d48aad9d5dd 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-pool-signup-code.template.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ-user-ses-email.template.json @@ -20,7 +20,7 @@ }, "EmailConfiguration": { "EmailSendingAccount": "DEVELOPER", - "From": "noreply@example.com", + "From": "\"myname@mycompany.com\" ", "ReplyToEmailAddress": "support@example.com", "SourceArn": { "Fn::Join": [ diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ.json index b0fa49a1c72f9..7719605f8486c 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "22.0.0", "testCases": { - "integ.user-pool-ses-email": { + "IntegTest/DefaultTest": { "stacks": [ - "integ-user-pool-signup-code" + "integ-user-ses-email" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "IntegTest/DefaultTest/DeployAssert", + "assertionStackName": "IntegTestDefaultTestDeployAssertE3E7D2A4" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/manifest.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/manifest.json index d04a7ad4df06b..4f837b695cd65 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/manifest.json @@ -1,33 +1,27 @@ { - "version": "20.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, - "integ-user-pool-signup-code.assets": { + "integ-user-ses-email.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "integ-user-pool-signup-code.assets.json", + "file": "integ-user-ses-email.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "integ-user-pool-signup-code": { + "integ-user-ses-email": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "integ-user-pool-signup-code.template.json", + "templateFile": "integ-user-ses-email.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}/3294a2beef1e4a711276251bf311cdf22b70152f30241f0d155898e2ab9ad091.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/55384e618066ba251d0576ca224e2109d90f1e97e067d2d9bfb1476d43fff838.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "integ-user-pool-signup-code.assets" + "integ-user-ses-email.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,35 +30,88 @@ } }, "dependencies": [ - "integ-user-pool-signup-code.assets" + "integ-user-ses-email.assets" ], "metadata": { - "/integ-user-pool-signup-code/myuserpool/Resource": [ + "/integ-user-ses-email/myuserpool/Resource": [ { "type": "aws:cdk:logicalId", "data": "myuserpool01998219" } ], - "/integ-user-pool-signup-code/user-pool-id": [ + "/integ-user-ses-email/user-pool-id": [ { "type": "aws:cdk:logicalId", "data": "userpoolid" } ], - "/integ-user-pool-signup-code/BootstrapVersion": [ + "/integ-user-ses-email/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/integ-user-pool-signup-code/CheckBootstrapVersion": [ + "/integ-user-ses-email/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "integ-user-pool-signup-code" + "displayName": "integ-user-ses-email" + }, + "IntegTestDefaultTestDeployAssertE3E7D2A4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "IntegTestDefaultTestDeployAssertE3E7D2A4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "IntegTestDefaultTestDeployAssertE3E7D2A4.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": [ + "IntegTestDefaultTestDeployAssertE3E7D2A4.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": [ + "IntegTestDefaultTestDeployAssertE3E7D2A4.assets" + ], + "metadata": { + "/IntegTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/IntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "IntegTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/tree.json b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/tree.json index fb6d64ba764b1..df43736a6cf7d 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.js.snapshot/tree.json @@ -4,25 +4,17 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "integ-user-pool-signup-code": { - "id": "integ-user-pool-signup-code", - "path": "integ-user-pool-signup-code", + "integ-user-ses-email": { + "id": "integ-user-ses-email", + "path": "integ-user-ses-email", "children": { "myuserpool": { "id": "myuserpool", - "path": "integ-user-pool-signup-code/myuserpool", + "path": "integ-user-ses-email/myuserpool", "children": { "Resource": { "id": "Resource", - "path": "integ-user-pool-signup-code/myuserpool/Resource", + "path": "integ-user-ses-email/myuserpool/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Cognito::UserPool", "aws:cdk:cloudformation:props": { @@ -42,7 +34,7 @@ "allowAdminCreateUserOnly": true }, "emailConfiguration": { - "from": "noreply@example.com", + "from": "\"myname@mycompany.com\" ", "replyToEmailAddress": "support@example.com", "emailSendingAccount": "DEVELOPER", "sourceArn": { @@ -87,22 +79,100 @@ }, "user-pool-id": { "id": "user-pool-id", - "path": "integ-user-pool-signup-code/user-pool-id", + "path": "integ-user-ses-email/user-pool-id", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-user-ses-email/BootstrapVersion", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-user-ses-email/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "IntegTest": { + "id": "IntegTest", + "path": "IntegTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "IntegTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "IntegTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.168" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "IntegTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "IntegTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "IntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "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" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.168" } } }, "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-cognito/test/integ.user-pool-ses-email.ts b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.ts index 8278649d12f7f..d4064158ff784 100644 --- a/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.ts +++ b/packages/@aws-cdk/aws-cognito/test/integ.user-pool-ses-email.ts @@ -1,9 +1,9 @@ import { App, CfnOutput, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import { UserPool, UserPoolEmail } from '../lib'; - const app = new App(); -const stack = new Stack(app, 'integ-user-pool-signup-code'); +const stack = new Stack(app, 'integ-user-ses-email'); const userpool = new UserPool(stack, 'myuserpool', { removalPolicy: RemovalPolicy.DESTROY, @@ -11,6 +11,7 @@ const userpool = new UserPool(stack, 'myuserpool', { email: UserPoolEmail.withSES({ sesRegion: 'us-east-1', fromEmail: 'noreply@example.com', + fromName: 'myname@mycompany.com', replyTo: 'support@example.com', sesVerifiedDomain: 'example.com', }), @@ -20,4 +21,4 @@ new CfnOutput(stack, 'user-pool-id', { value: userpool.userPoolId, }); -app.synth(); +new IntegTest(app, 'IntegTest', { testCases: [stack] }); diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts b/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts index 8d4f54c88ccba..e285a10f24480 100644 --- a/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts @@ -777,6 +777,86 @@ describe('User Pool Client', () => { }); }); + describe('auth session validity', () => { + test('default', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client1', { + userPoolClientName: 'Client1', + authSessionValidity: Duration.minutes(3), + }); + pool.addClient('Client2', { + userPoolClientName: 'Client2', + authSessionValidity: Duration.minutes(9), + }); + pool.addClient('Client3', { + userPoolClientName: 'Client3', + authSessionValidity: Duration.minutes(15), + }); + pool.addClient('Client5', { + userPoolClientName: 'Client4', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client1', + AuthSessionValidity: 3, + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client2', + AuthSessionValidity: 9, + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client3', + AuthSessionValidity: 15, + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client4', + }); + }); + + test.each([ + Duration.minutes(0), + Duration.minutes(1), + Duration.minutes(3).minus(Duration.minutes(1)), + Duration.minutes(15).plus(Duration.minutes(1)), + Duration.minutes(100), + ])('validates authSessionValidity is a duration between 3 and 15 minutes', (validity) => { + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + expect(() => { + pool.addClient('Client1', { + userPoolClientName: 'Client1', + authSessionValidity: validity, + }); + }).toThrow(`authSessionValidity: Must be a duration between 3 minutes and 15 minutes (inclusive); received ${validity.toHumanString()}.`); + }); + + test.each([ + Duration.minutes(3), + Duration.minutes(9), + Duration.minutes(15), + ])('validates authSessionValidity is a duration between 3 and 15 minutes (valid)', (validity) => { + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client1', { + userPoolClientName: 'Client1', + authSessionValidity: validity, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client1', + AuthSessionValidity: validity.toMinutes(), + }); + }); + }); + describe('token validity', () => { test('default', () => { // GIVEN diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts b/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts index 9cc1cfc5fb4a8..edec04ad26fb5 100644 --- a/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts +++ b/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts @@ -1708,7 +1708,158 @@ describe('User Pool', () => { }, }, }); + }); + + test('email withSES with name as quoted-string', () => { + // GIVEN + const stack = new Stack(undefined, undefined, { + env: { + region: 'us-east-1', + account: '11111111111', + }, + }); + + // WHEN + new UserPool(stack, 'Pool', { + email: UserPoolEmail.withSES({ + fromEmail: 'mycustomemail@example.com', + fromName: '"My Custom Email"', + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPool', { + EmailConfiguration: { + EmailSendingAccount: 'DEVELOPER', + From: '"My Custom Email" ', + SourceArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':ses:us-east-1:11111111111:identity/mycustomemail@example.com', + ], + ], + }, + }, + }); + }); + + test('email withSES with name with non atom characters', () => { + // GIVEN + const stack = new Stack(undefined, undefined, { + env: { + region: 'us-east-1', + account: '11111111111', + }, + }); + // WHEN + new UserPool(stack, 'Pool', { + email: UserPoolEmail.withSES({ + fromEmail: 'mycustomemail@example.com', + fromName: 'mycustomname@example.com', + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPool', { + EmailConfiguration: { + EmailSendingAccount: 'DEVELOPER', + From: '"mycustomname@example.com" ', + SourceArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':ses:us-east-1:11111111111:identity/mycustomemail@example.com', + ], + ], + }, + }, + }); + }); + + test('email withSES with name with quotes', () => { + // GIVEN + const stack = new Stack(undefined, undefined, { + env: { + region: 'us-east-1', + account: '11111111111', + }, + }); + + // WHEN + new UserPool(stack, 'Pool', { + email: UserPoolEmail.withSES({ + fromEmail: 'mycustomemail@example.com', + fromName: 'Foo "Bar" \\Baz', + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPool', { + EmailConfiguration: { + EmailSendingAccount: 'DEVELOPER', + From: '"Foo \\"Bar\\" \\\\Baz" ', + SourceArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':ses:us-east-1:11111111111:identity/mycustomemail@example.com', + ], + ], + }, + }, + }); + }); + + test('email withSES with name with non US-ASCII characters', () => { + // GIVEN + const stack = new Stack(undefined, undefined, { + env: { + region: 'us-east-1', + account: '11111111111', + }, + }); + + // WHEN + new UserPool(stack, 'Pool', { + email: UserPoolEmail.withSES({ + fromEmail: 'mycustomemail@example.com', + fromName: 'あいう', + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPool', { + EmailConfiguration: { + EmailSendingAccount: 'DEVELOPER', + From: '=?UTF-8?B?44GC44GE44GG?= ', + SourceArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':ses:us-east-1:11111111111:identity/mycustomemail@example.com', + ], + ], + }, + }, + }); }); test('email withSES with valid region', () => { diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 539761ba96032..122820039d038 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -1026,6 +1026,9 @@ abstract class TableBase extends Resource implements ITable { grantee: iam.IGrantable, opts: { keyActions?: string[], tableActions?: string[], streamActions?: string[] }, ): iam.Grant { + if (this.encryptionKey && opts.keyActions) { + this.encryptionKey.grant(grantee, ...opts.keyActions); + } if (opts.tableActions) { const resources = [this.tableArn, Lazy.string({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : Aws.NO_VALUE }), @@ -1039,9 +1042,6 @@ abstract class TableBase extends Resource implements ITable { resourceArns: resources, scope: this, }); - if (this.encryptionKey && opts.keyActions) { - this.encryptionKey.grant(grantee, ...opts.keyActions); - } return ret; } if (opts.streamActions) { diff --git a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts index 35145edd0d57c..02ccd0b1540d6 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts @@ -2264,6 +2264,60 @@ describe('import', () => { }); }); + test('if an encryption key is included, encrypt/decrypt permissions are added to the principal for grantStreamRead', () => { + const stack = new Stack(); + + const tableName = 'MyTable'; + const tableStreamArn = 'arn:foo:bar:baz:TrustMeThisIsATableStream'; + const encryptionKey = new kms.Key(stack, 'Key', { + enableKeyRotation: true, + }); + + const table = Table.fromTableAttributes(stack, 'ImportedTable', { tableName, tableStreamArn, encryptionKey }); + + const role = new iam.Role(stack, 'NewRole', { + assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), + }); + + expect(table.grantStreamRead(role)).toBeDefined(); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + 'Action': 'dynamodb:ListStreams', + 'Effect': 'Allow', + 'Resource': '*', + }, + { + 'Action': [ + 'kms:Decrypt', + 'kms:DescribeKey', + ], + 'Effect': 'Allow', + 'Resource': { + 'Fn::GetAtt': [ + 'Key961B73FD', + 'Arn', + ], + }, + }, + { + 'Action': [ + 'dynamodb:DescribeStream', + 'dynamodb:GetRecords', + 'dynamodb:GetShardIterator', + ], + 'Effect': 'Allow', + 'Resource': 'arn:foo:bar:baz:TrustMeThisIsATableStream', + }, + ], + Version: '2012-10-17', + }, + Roles: [stack.resolve(role.roleName)], + }); + }); + test('creates the correct index grant if indexes have been provided when importing', () => { const stack = new Stack(); diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.assets.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.assets.json index aa3256624691c..8f13a49bbff39 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.assets.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "22.0.0", "files": { - "28f29dc1ca8be205ffc54093c72bcd51a45a56b3375537b6cfa7e2b132bbdc9e": { + "aaaac6e8f3f1ffa9992cbb900021f1d1b5ec67af132595b4b296680991a0d152": { "source": { "path": "aws-cdk-dynamodb.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "28f29dc1ca8be205ffc54093c72bcd51a45a56b3375537b6cfa7e2b132bbdc9e.json", + "objectKey": "aaaac6e8f3f1ffa9992cbb900021f1d1b5ec67af132595b4b296680991a0d152.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-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.template.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.template.json index b4c641169a41e..5c90ea1dde1a9 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.template.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/aws-cdk-dynamodb.template.json @@ -371,6 +371,143 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "Key961B73FD": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "EnableKeyRotation": true + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "TableWithCustomerManagedKeyD5C58807": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "KeySchema": [ + { + "AttributeName": "hashKey", + "KeyType": "HASH" + } + ], + "AttributeDefinitions": [ + { + "AttributeName": "hashKey", + "AttributeType": "S" + } + ], + "ProvisionedThroughput": { + "ReadCapacityUnits": 5, + "WriteCapacityUnits": 5 + }, + "SSESpecification": { + "KMSMasterKeyId": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + }, + "SSEEnabled": true, + "SSEType": "KMS" + }, + "StreamSpecification": { + "StreamViewType": "NEW_AND_OLD_IMAGES" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Role1ABCC5F0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "sqs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "RoleDefaultPolicy5FFB7DAB": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + } + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TableWithCustomerManagedKeyD5C58807", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "RoleDefaultPolicy5FFB7DAB", + "Roles": [ + { + "Ref": "Role1ABCC5F0" + } + ] + } + }, "User00B015A1": { "Type": "AWS::IAM::User" }, diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/cdk.out b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/cdk.out index 588d7b269d34f..145739f539580 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/integ.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/integ.json index 6de1a0399c7a2..45afa8d3160a6 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "22.0.0", "testCases": { "integ.dynamodb": { "stacks": [ diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/manifest.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/manifest.json index 293f1e74490ca..5f09227f142a1 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-dynamodb.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,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}/28f29dc1ca8be205ffc54093c72bcd51a45a56b3375537b6cfa7e2b132bbdc9e.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/aaaac6e8f3f1ffa9992cbb900021f1d1b5ec67af132595b4b296680991a0d152.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -63,6 +57,30 @@ "data": "TableWithLocalSecondaryIndex4DA3D08F" } ], + "/aws-cdk-dynamodb/Key/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Key961B73FD" + } + ], + "/aws-cdk-dynamodb/TableWithCustomerManagedKey/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TableWithCustomerManagedKeyD5C58807" + } + ], + "/aws-cdk-dynamodb/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Role1ABCC5F0" + } + ], + "/aws-cdk-dynamodb/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RoleDefaultPolicy5FFB7DAB" + } + ], "/aws-cdk-dynamodb/User/Resource": [ { "type": "aws:cdk:logicalId", @@ -89,6 +107,12 @@ ] }, "displayName": "aws-cdk-dynamodb" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/tree.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/tree.json index 202cabc0f7115..4db3749ed870a 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-dynamodb": { "id": "aws-cdk-dynamodb", "path": "aws-cdk-dynamodb", @@ -53,8 +45,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/Table/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -327,8 +319,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalAndLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -396,8 +388,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -473,8 +465,120 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.Table", + "version": "0.0.0" + } + }, + "Key": { + "id": "Key", + "path": "aws-cdk-dynamodb/Key", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-dynamodb/Key/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "enableKeyRotation": true + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-kms.Key", + "version": "0.0.0" + } + }, + "TableWithCustomerManagedKey": { + "id": "TableWithCustomerManagedKey", + "path": "aws-cdk-dynamodb/TableWithCustomerManagedKey", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-dynamodb/TableWithCustomerManagedKey/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", + "aws:cdk:cloudformation:props": { + "keySchema": [ + { + "attributeName": "hashKey", + "keyType": "HASH" + } + ], + "attributeDefinitions": [ + { + "attributeName": "hashKey", + "attributeType": "S" + } + ], + "provisionedThroughput": { + "readCapacityUnits": 5, + "writeCapacityUnits": 5 + }, + "sseSpecification": { + "sseEnabled": true, + "kmsMasterKeyId": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + }, + "sseType": "KMS" + }, + "streamSpecification": { + "streamViewType": "NEW_AND_OLD_IMAGES" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "version": "0.0.0" + } + }, + "ScalingRole": { + "id": "ScalingRole", + "path": "aws-cdk-dynamodb/TableWithCustomerManagedKey/ScalingRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -483,6 +587,115 @@ "version": "0.0.0" } }, + "Role": { + "id": "Role", + "path": "aws-cdk-dynamodb/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "aws-cdk-dynamodb/Role/ImportRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-dynamodb/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "sqs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-dynamodb/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-dynamodb/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Key961B73FD", + "Arn" + ] + } + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TableWithCustomerManagedKeyD5C58807", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "RoleDefaultPolicy5FFB7DAB", + "roles": [ + { + "Ref": "Role1ABCC5F0" + } + ] + } + }, + "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" + } + }, "User": { "id": "User", "path": "aws-cdk-dynamodb/User", @@ -582,17 +795,41 @@ "fqn": "@aws-cdk/aws-iam.User", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-dynamodb/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-dynamodb/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.189" } } }, "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-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.assets.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.assets.json index 7f8b8258d7abc..90f3a7d2343f5 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.assets.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "22.0.0", "files": { - "449ab31c53e48708bdc4d899497ed3129e2565e94bbdf22cd8704751fc73fcb5": { + "67bada7a8e782ac86bb16bf47c61bc2039c780e5e42eaae93c8bc65e9b3e7cbb": { "source": { "path": "aws-cdk-dynamodb.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "449ab31c53e48708bdc4d899497ed3129e2565e94bbdf22cd8704751fc73fcb5.json", + "objectKey": "67bada7a8e782ac86bb16bf47c61bc2039c780e5e42eaae93c8bc65e9b3e7cbb.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-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.template.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.template.json index fdcaf307d248c..6cd6ef9769f51 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.template.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/aws-cdk-dynamodb.template.json @@ -489,6 +489,19 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TableKey25666F95", + "Arn" + ] + } + }, { "Action": [ "dynamodb:BatchGetItem", @@ -532,19 +545,6 @@ "Ref": "AWS::NoValue" } ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "TableKey25666F95", - "Arn" - ] - } } ], "Version": "2012-10-17" diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/cdk.out b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/cdk.out index 588d7b269d34f..145739f539580 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/integ.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/integ.json index 14c805d5166f4..85acd063c33d2 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "22.0.0", "testCases": { "integ.dynamodb.sse": { "stacks": [ diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/manifest.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/manifest.json index 8460159e46960..487bca37f7c43 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-dynamodb.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,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}/449ab31c53e48708bdc4d899497ed3129e2565e94bbdf22cd8704751fc73fcb5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/67bada7a8e782ac86bb16bf47c61bc2039c780e5e42eaae93c8bc65e9b3e7cbb.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -101,6 +95,12 @@ ] }, "displayName": "aws-cdk-dynamodb" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/tree.json b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/tree.json index 4d9a73bb877d9..15241edf76fe3 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.sse.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-dynamodb": { "id": "aws-cdk-dynamodb", "path": "aws-cdk-dynamodb", @@ -116,8 +108,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/Table/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -390,8 +382,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalAndLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -521,8 +513,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithGlobalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -601,8 +593,8 @@ "id": "ScalingRole", "path": "aws-cdk-dynamodb/TableWithLocalSecondaryIndex/ScalingRole", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } } }, @@ -615,6 +607,14 @@ "id": "Role", "path": "aws-cdk-dynamodb/Role", "children": { + "ImportRole": { + "id": "ImportRole", + "path": "aws-cdk-dynamodb/Role/ImportRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-dynamodb/Role/Resource", @@ -652,6 +652,19 @@ "aws:cdk:cloudformation:props": { "policyDocument": { "Statement": [ + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TableKey25666F95", + "Arn" + ] + } + }, { "Action": [ "dynamodb:BatchGetItem", @@ -695,19 +708,6 @@ "Ref": "AWS::NoValue" } ] - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey" - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "TableKey25666F95", - "Arn" - ] - } } ], "Version": "2012-10-17" @@ -736,17 +736,41 @@ "fqn": "@aws-cdk/aws-iam.Role", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-dynamodb/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-dynamodb/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.189" } } }, "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-dynamodb/test/integ.dynamodb.ts b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.ts index f016561c441db..762e513df1cd1 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/integ.dynamodb.ts @@ -1,4 +1,5 @@ import * as iam from '@aws-cdk/aws-iam'; +import * as kms from '@aws-cdk/aws-kms'; import { App, RemovalPolicy, Stack, Tags } from '@aws-cdk/core'; import { Attribute, AttributeType, ProjectionType, StreamViewType, Table, TableEncryption } from '../lib'; @@ -7,6 +8,7 @@ const STACK_NAME = 'aws-cdk-dynamodb'; // DynamoDB table parameters const TABLE = 'Table'; +const TABLE_WITH_CMK = 'TableWithCustomerManagedKey'; const TABLE_WITH_GLOBAL_AND_LOCAL_SECONDARY_INDEX = 'TableWithGlobalAndLocalSecondaryIndex'; const TABLE_WITH_GLOBAL_SECONDARY_INDEX = 'TableWithGlobalSecondaryIndex'; const TABLE_WITH_LOCAL_SECONDARY_INDEX = 'TableWithLocalSecondaryIndex'; @@ -127,6 +129,22 @@ tableWithLocalSecondaryIndex.addLocalSecondaryIndex({ sortKey: LSI_SORT_KEY, }); +const encryptionKey = new kms.Key(stack, 'Key', { + enableKeyRotation: true, +}); + +const tableWithCMK = new Table(stack, TABLE_WITH_CMK, { + partitionKey: TABLE_PARTITION_KEY, + removalPolicy: RemovalPolicy.DESTROY, + stream: StreamViewType.NEW_AND_OLD_IMAGES, + encryptionKey: encryptionKey, +}); + +const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('sqs.amazonaws.com'), +}); +tableWithCMK.grantStreamRead(role); + const user = new iam.User(stack, 'User'); table.grantReadData(user); tableWithGlobalAndLocalSecondaryIndex.grantReadData(user); diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-flow-logs.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-flow-logs.ts index 30cd9fe7d7e0d..d43f9f9aac26c 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-flow-logs.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-flow-logs.ts @@ -676,7 +676,7 @@ export class FlowLog extends FlowLogBase { } const flowLog = new CfnFlowLog(this, 'FlowLog', { - destinationOptions: renderDestinationOptions(destinationConfig.destinationOptions), + destinationOptions: destinationConfig.destinationOptions, deliverLogsPermissionArn: this.iamRole ? this.iamRole.roleArn : undefined, logDestinationType: destinationConfig.logDestinationType, logGroupName: this.logGroup ? this.logGroup.logGroupName : undefined, @@ -694,13 +694,3 @@ export class FlowLog extends FlowLogBase { this.node.defaultChild = flowLog; } } - -function renderDestinationOptions(opts: DestinationOptions | undefined): CfnFlowLog.DestinationOptionsProperty | undefined { - if (opts === undefined) { return undefined; } - - return { - fileFormat: opts.fileFormat ?? 'plain-text', - hiveCompatiblePartitions: opts.hiveCompatiblePartitions ?? false, - perHourPartition: opts.perHourPartition ?? false, - }; -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.assets.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.assets.json index 7b8f6b3c685fc..297a68239d9a3 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.assets.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.assets.json @@ -1,20 +1,20 @@ { "version": "21.0.0", "files": { - "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac": { + "b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b": { "source": { - "path": "asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle", + "path": "asset.b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.bundle", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.zip", + "objectKey": "b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "dd951509b1e22484b40a66a661cb8cebce3087b8cb381e3dcf02e641e5eb08cd": { + "1dcf759cd2c8928f5b1acfbf439f1751e25367a5ac61ba5e640ff8b78fdf89f7": { "source": { "path": "FlowLogsDefaultTestDeployAssert6AFD1854.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "dd951509b1e22484b40a66a661cb8cebce3087b8cb381e3dcf02e641e5eb08cd.json", + "objectKey": "1dcf759cd2c8928f5b1acfbf439f1751e25367a5ac61ba5e640ff8b78fdf89f7.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-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.template.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.template.json index d8bc055b720ef..e8cb5fe5ffe8f 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.template.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsDefaultTestDeployAssert6AFD1854.template.json @@ -31,7 +31,7 @@ } }, "flattenResponse": "false", - "salt": "1668693953813" + "salt": "1666810703150" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -115,7 +115,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.zip" + "S3Key": "b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.zip" }, "Timeout": 120, "Handler": "index.handler", diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.assets.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.assets.json index ff70a68b4bce9..fa5105def2d15 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.assets.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.assets.json @@ -1,7 +1,7 @@ { "version": "21.0.0", "files": { - "8f4f8db3ea3ad2d5f5678275c75dce7d9b67b46d8df7d92c62913bdc5a03cd3f": { + "2db53e096625b4b167fb15dd7bdc246692b381f45e28c509614fef7d41c20bc9": { "source": { "path": "FlowLogsFeatureFlag.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8f4f8db3ea3ad2d5f5678275c75dce7d9b67b46d8df7d92c62913bdc5a03cd3f.json", + "objectKey": "2db53e096625b4b167fb15dd7bdc246692b381f45e28c509614fef7d41c20bc9.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-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.template.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.template.json index 9f63324d697a3..0c55b91df3207 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.template.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsFeatureFlag.template.json @@ -524,6 +524,7 @@ "Ref": "VPCB9E5F0B4" }, "ResourceType": "VPC", + "TrafficType": "ALL", "LogDestination": { "Fn::GetAtt": [ "VPCFlowLogsS3BucketFB7DC2BE", @@ -536,8 +537,7 @@ "Key": "Name", "Value": "FlowLogsFeatureFlag/VPC" } - ], - "TrafficType": "ALL" + ] } }, "VPCFlowLogsS3WithDestinationOptionsBucket1B7AC456": { @@ -673,10 +673,11 @@ "Ref": "VPCB9E5F0B4" }, "ResourceType": "VPC", + "TrafficType": "ALL", "DestinationOptions": { - "FileFormat": "plain-text", - "HiveCompatiblePartitions": true, - "PerHourPartition": false + "fileFormat": "plain-text", + "perHourPartition": false, + "hiveCompatiblePartitions": true }, "LogDestination": { "Fn::GetAtt": [ @@ -690,8 +691,7 @@ "Key": "Name", "Value": "FlowLogsFeatureFlag/VPC" } - ], - "TrafficType": "ALL" + ] } }, "FlowLogsInstanceInstanceSecurityGroupF61782E0": { diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.assets.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.assets.json index d99b980527565..310bb5c387339 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.assets.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.assets.json @@ -1,20 +1,20 @@ { "version": "21.0.0", "files": { - "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": { + "bb426cfb5fed5237e5928f871893b243ddf86a591a592b558bd29f60e28bad9d": { "source": { - "path": "asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c", + "path": "asset.bb426cfb5fed5237e5928f871893b243ddf86a591a592b558bd29f60e28bad9d", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c.zip", + "objectKey": "bb426cfb5fed5237e5928f871893b243ddf86a591a592b558bd29f60e28bad9d.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "23955aa16c5d59106d93ecce9cedd43aa5782fbf23bb2ef8549b2119345a6f79": { + "2090a74d484bc155b48d7511b99e4921b8f55e488c3fe1500cffede0cdfd33b7": { "source": { "path": "FlowLogsTestStack.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "23955aa16c5d59106d93ecce9cedd43aa5782fbf23bb2ef8549b2119345a6f79.json", + "objectKey": "2090a74d484bc155b48d7511b99e4921b8f55e488c3fe1500cffede0cdfd33b7.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-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.template.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.template.json index c368f02a02265..43b56bfee9517 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.template.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/FlowLogsTestStack.template.json @@ -524,6 +524,7 @@ "Ref": "VPCB9E5F0B4" }, "ResourceType": "VPC", + "TrafficType": "ALL", "LogDestination": { "Fn::GetAtt": [ "VPCFlowLogsS3BucketFB7DC2BE", @@ -536,8 +537,7 @@ "Key": "Name", "Value": "FlowLogsTestStack/VPC" } - ], - "TrafficType": "ALL" + ] } }, "VPCFlowLogsS3KeyPrefixFlowLogB57F1746": { @@ -547,6 +547,7 @@ "Ref": "VPCB9E5F0B4" }, "ResourceType": "VPC", + "TrafficType": "ALL", "LogDestination": { "Fn::Join": [ "", @@ -567,8 +568,7 @@ "Key": "Name", "Value": "FlowLogsTestStack/VPC" } - ], - "TrafficType": "ALL" + ] } }, "FlowLogsCWIAMRole017AD736": { @@ -643,6 +643,7 @@ "Ref": "VPCB9E5F0B4" }, "ResourceType": "VPC", + "TrafficType": "ALL", "DeliverLogsPermissionArn": { "Fn::GetAtt": [ "FlowLogsCWIAMRole017AD736", @@ -652,8 +653,7 @@ "LogDestinationType": "cloud-watch-logs", "LogGroupName": { "Ref": "FlowLogsCWLogGroup0398E8F8" - }, - "TrafficType": "ALL" + } } }, "Bucket83908E77": { @@ -888,7 +888,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c.zip" + "S3Key": "bb426cfb5fed5237e5928f871893b243ddf86a591a592b558bd29f60e28bad9d.zip" }, "Timeout": 900, "MemorySize": 128, diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js deleted file mode 100644 index 1e3a3093c1706..0000000000000 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js +++ /dev/null @@ -1,144 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.withRetries = exports.handler = exports.external = void 0; -const https = require("https"); -const url = require("url"); -// for unit tests -exports.external = { - sendHttpRequest: defaultSendHttpRequest, - log: defaultLog, - includeStackTraces: true, - userHandlerIndex: './index', -}; -const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; -const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; -async function handler(event, context) { - const sanitizedEvent = { ...event, ResponseURL: '...' }; - exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); - // ignore DELETE event when the physical resource ID is the marker that - // indicates that this DELETE is a subsequent DELETE to a failed CREATE - // operation. - if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { - exports.external.log('ignoring DELETE event caused by a failed CREATE event'); - await submitResponse('SUCCESS', event); - return; - } - try { - // invoke the user handler. this is intentionally inside the try-catch to - // ensure that if there is an error it's reported as a failure to - // cloudformation (otherwise cfn waits). - // eslint-disable-next-line @typescript-eslint/no-require-imports - const userHandler = require(exports.external.userHandlerIndex).handler; - const result = await userHandler(sanitizedEvent, context); - // validate user response and create the combined event - const responseEvent = renderResponse(event, result); - // submit to cfn as success - await submitResponse('SUCCESS', responseEvent); - } - catch (e) { - const resp = { - ...event, - Reason: exports.external.includeStackTraces ? e.stack : e.message, - }; - if (!resp.PhysicalResourceId) { - // special case: if CREATE fails, which usually implies, we usually don't - // have a physical resource id. in this case, the subsequent DELETE - // operation does not have any meaning, and will likely fail as well. to - // address this, we use a marker so the provider framework can simply - // ignore the subsequent DELETE. - if (event.RequestType === 'Create') { - exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); - resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; - } - else { - // otherwise, if PhysicalResourceId is not specified, something is - // terribly wrong because all other events should have an ID. - exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); - } - } - // this is an actual error, fail the activity altogether and exist. - await submitResponse('FAILED', resp); - } -} -exports.handler = handler; -function renderResponse(cfnRequest, handlerResponse = {}) { - // if physical ID is not returned, we have some defaults for you based - // on the request type. - const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; - // if we are in DELETE and physical ID was changed, it's an error. - if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { - throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); - } - // merge request event and result event (result prevails). - return { - ...cfnRequest, - ...handlerResponse, - PhysicalResourceId: physicalResourceId, - }; -} -async function submitResponse(status, event) { - const json = { - Status: status, - Reason: event.Reason ?? status, - StackId: event.StackId, - RequestId: event.RequestId, - PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, - LogicalResourceId: event.LogicalResourceId, - NoEcho: event.NoEcho, - Data: event.Data, - }; - exports.external.log('submit response to cloudformation', json); - const responseBody = JSON.stringify(json); - const parsedUrl = url.parse(event.ResponseURL); - const req = { - hostname: parsedUrl.hostname, - path: parsedUrl.path, - method: 'PUT', - headers: { 'content-type': '', 'content-length': responseBody.length }, - }; - const retryOptions = { - attempts: 5, - sleep: 1000, - }; - await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); -} -async function defaultSendHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, _ => resolve()); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -function defaultLog(fmt, ...params) { - // eslint-disable-next-line no-console - console.log(fmt, ...params); -} -function withRetries(options, fn) { - return async (...xs) => { - let attempts = options.attempts; - let ms = options.sleep; - while (true) { - try { - return await fn(...xs); - } - catch (e) { - if (attempts-- <= 0) { - throw e; - } - await sleep(Math.floor(Math.random() * ms)); - ms *= 2; - } - } - }; -} -exports.withRetries = withRetries; -async function sleep(ms) { - return new Promise((ok) => setTimeout(ok, ms)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtLQUN2RSxDQUFDO0lBRUYsTUFBTSxZQUFZLEdBQUc7UUFDbkIsUUFBUSxFQUFFLENBQUM7UUFDWCxLQUFLLEVBQUUsSUFBSTtLQUNaLENBQUM7SUFDRixNQUFNLFdBQVcsQ0FBQyxZQUFZLEVBQUUsZ0JBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDL0UsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ3ZGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWDtJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxHQUFHLE1BQWE7SUFDL0Msc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQVNELFNBQWdCLFdBQVcsQ0FBMEIsT0FBcUIsRUFBRSxFQUE0QjtJQUN0RyxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUssRUFBRSxFQUFFO1FBQ3hCLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDaEMsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUN2QixPQUFPLElBQUksRUFBRTtZQUNYLElBQUk7Z0JBQ0YsT0FBTyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2FBQ3hCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsSUFBSSxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUU7b0JBQ25CLE1BQU0sQ0FBQyxDQUFDO2lCQUNUO2dCQUNELE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDVDtTQUNGO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQWhCRCxrQ0FnQkM7QUFFRCxLQUFLLFVBQVUsS0FBSyxDQUFDLEVBQVU7SUFDN0IsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBodHRwcyBmcm9tICdodHRwcyc7XG5pbXBvcnQgKiBhcyB1cmwgZnJvbSAndXJsJztcblxuLy8gZm9yIHVuaXQgdGVzdHNcbmV4cG9ydCBjb25zdCBleHRlcm5hbCA9IHtcbiAgc2VuZEh0dHBSZXF1ZXN0OiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0LFxuICBsb2c6IGRlZmF1bHRMb2csXG4gIGluY2x1ZGVTdGFja1RyYWNlczogdHJ1ZSxcbiAgdXNlckhhbmRsZXJJbmRleDogJy4vaW5kZXgnLFxufTtcblxuY29uc3QgQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpDUkVBVEVfRkFJTEVEJztcbmNvbnN0IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSID0gJ0FXU0NESzo6Q3VzdG9tUmVzb3VyY2VQcm92aWRlckZyYW1ld29yazo6TUlTU0lOR19QSFlTSUNBTF9JRCc7XG5cbmV4cG9ydCB0eXBlIFJlc3BvbnNlID0gQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIEhhbmRsZXJSZXNwb25zZTtcbmV4cG9ydCB0eXBlIEhhbmRsZXIgPSAoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSA9PiBQcm9taXNlPEhhbmRsZXJSZXNwb25zZSB8IHZvaWQ+O1xuZXhwb3J0IHR5cGUgSGFuZGxlclJlc3BvbnNlID0gdW5kZWZpbmVkIHwge1xuICBEYXRhPzogYW55O1xuICBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmc7XG4gIFJlYXNvbj86IHN0cmluZztcbiAgTm9FY2hvPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkge1xuICBjb25zdCBzYW5pdGl6ZWRFdmVudCA9IHsgLi4uZXZlbnQsIFJlc3BvbnNlVVJMOiAnLi4uJyB9O1xuICBleHRlcm5hbC5sb2coSlNPTi5zdHJpbmdpZnkoc2FuaXRpemVkRXZlbnQsIHVuZGVmaW5lZCwgMikpO1xuXG4gIC8vIGlnbm9yZSBERUxFVEUgZXZlbnQgd2hlbiB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgaXMgdGhlIG1hcmtlciB0aGF0XG4gIC8vIGluZGljYXRlcyB0aGF0IHRoaXMgREVMRVRFIGlzIGEgc3Vic2VxdWVudCBERUxFVEUgdG8gYSBmYWlsZWQgQ1JFQVRFXG4gIC8vIG9wZXJhdGlvbi5cbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgPT09IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSKSB7XG4gICAgZXh0ZXJuYWwubG9nKCdpZ25vcmluZyBERUxFVEUgZXZlbnQgY2F1c2VkIGJ5IGEgZmFpbGVkIENSRUFURSBldmVudCcpO1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgZXZlbnQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLy8gaW52b2tlIHRoZSB1c2VyIGhhbmRsZXIuIHRoaXMgaXMgaW50ZW50aW9uYWxseSBpbnNpZGUgdGhlIHRyeS1jYXRjaCB0b1xuICAgIC8vIGVuc3VyZSB0aGF0IGlmIHRoZXJlIGlzIGFuIGVycm9yIGl0J3MgcmVwb3J0ZWQgYXMgYSBmYWlsdXJlIHRvXG4gICAgLy8gY2xvdWRmb3JtYXRpb24gKG90aGVyd2lzZSBjZm4gd2FpdHMpLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgdXNlckhhbmRsZXI6IEhhbmRsZXIgPSByZXF1aXJlKGV4dGVybmFsLnVzZXJIYW5kbGVySW5kZXgpLmhhbmRsZXI7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdXNlckhhbmRsZXIoc2FuaXRpemVkRXZlbnQsIGNvbnRleHQpO1xuXG4gICAgLy8gdmFsaWRhdGUgdXNlciByZXNwb25zZSBhbmQgY3JlYXRlIHRoZSBjb21iaW5lZCBldmVudFxuICAgIGNvbnN0IHJlc3BvbnNlRXZlbnQgPSByZW5kZXJSZXNwb25zZShldmVudCwgcmVzdWx0KTtcblxuICAgIC8vIHN1Ym1pdCB0byBjZm4gYXMgc3VjY2Vzc1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgcmVzcG9uc2VFdmVudCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zdCByZXNwOiBSZXNwb25zZSA9IHtcbiAgICAgIC4uLmV2ZW50LFxuICAgICAgUmVhc29uOiBleHRlcm5hbC5pbmNsdWRlU3RhY2tUcmFjZXMgPyBlLnN0YWNrIDogZS5tZXNzYWdlLFxuICAgIH07XG5cbiAgICBpZiAoIXJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICAvLyBzcGVjaWFsIGNhc2U6IGlmIENSRUFURSBmYWlscywgd2hpY2ggdXN1YWxseSBpbXBsaWVzLCB3ZSB1c3VhbGx5IGRvbid0XG4gICAgICAvLyBoYXZlIGEgcGh5c2ljYWwgcmVzb3VyY2UgaWQuIGluIHRoaXMgY2FzZSwgdGhlIHN1YnNlcXVlbnQgREVMRVRFXG4gICAgICAvLyBvcGVyYXRpb24gZG9lcyBub3QgaGF2ZSBhbnkgbWVhbmluZywgYW5kIHdpbGwgbGlrZWx5IGZhaWwgYXMgd2VsbC4gdG9cbiAgICAgIC8vIGFkZHJlc3MgdGhpcywgd2UgdXNlIGEgbWFya2VyIHNvIHRoZSBwcm92aWRlciBmcmFtZXdvcmsgY2FuIHNpbXBseVxuICAgICAgLy8gaWdub3JlIHRoZSBzdWJzZXF1ZW50IERFTEVURS5cbiAgICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScpIHtcbiAgICAgICAgZXh0ZXJuYWwubG9nKCdDUkVBVEUgZmFpbGVkLCByZXNwb25kaW5nIHdpdGggYSBtYXJrZXIgcGh5c2ljYWwgcmVzb3VyY2UgaWQgc28gdGhhdCB0aGUgc3Vic2VxdWVudCBERUxFVEUgd2lsbCBiZSBpZ25vcmVkJyk7XG4gICAgICAgIHJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkID0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBvdGhlcndpc2UsIGlmIFBoeXNpY2FsUmVzb3VyY2VJZCBpcyBub3Qgc3BlY2lmaWVkLCBzb21ldGhpbmcgaXNcbiAgICAgICAgLy8gdGVycmlibHkgd3JvbmcgYmVjYXVzZSBhbGwgb3RoZXIgZXZlbnRzIHNob3VsZCBoYXZlIGFuIElELlxuICAgICAgICBleHRlcm5hbC5sb2coYEVSUk9SOiBNYWxmb3JtZWQgZXZlbnQuIFwiUGh5c2ljYWxSZXNvdXJjZUlkXCIgaXMgcmVxdWlyZWQ6ICR7SlNPTi5zdHJpbmdpZnkoZXZlbnQpfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRoaXMgaXMgYW4gYWN0dWFsIGVycm9yLCBmYWlsIHRoZSBhY3Rpdml0eSBhbHRvZ2V0aGVyIGFuZCBleGlzdC5cbiAgICBhd2FpdCBzdWJtaXRSZXNwb25zZSgnRkFJTEVEJywgcmVzcCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVzcG9uc2UoXG4gIGNmblJlcXVlc3Q6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiB7IFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZyB9LFxuICBoYW5kbGVyUmVzcG9uc2U6IHZvaWQgfCBIYW5kbGVyUmVzcG9uc2UgPSB7IH0pOiBSZXNwb25zZSB7XG5cbiAgLy8gaWYgcGh5c2ljYWwgSUQgaXMgbm90IHJldHVybmVkLCB3ZSBoYXZlIHNvbWUgZGVmYXVsdHMgZm9yIHlvdSBiYXNlZFxuICAvLyBvbiB0aGUgcmVxdWVzdCB0eXBlLlxuICBjb25zdCBwaHlzaWNhbFJlc291cmNlSWQgPSBoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUmVxdWVzdElkO1xuXG4gIC8vIGlmIHdlIGFyZSBpbiBERUxFVEUgYW5kIHBoeXNpY2FsIElEIHdhcyBjaGFuZ2VkLCBpdCdzIGFuIGVycm9yLlxuICBpZiAoY2ZuUmVxdWVzdC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScgJiYgcGh5c2ljYWxSZXNvdXJjZUlkICE9PSBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgREVMRVRFOiBjYW5ub3QgY2hhbmdlIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBmcm9tIFwiJHtjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZH1cIiB0byBcIiR7aGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZH1cIiBkdXJpbmcgZGVsZXRpb25gKTtcbiAgfVxuXG4gIC8vIG1lcmdlIHJlcXVlc3QgZXZlbnQgYW5kIHJlc3VsdCBldmVudCAocmVzdWx0IHByZXZhaWxzKS5cbiAgcmV0dXJuIHtcbiAgICAuLi5jZm5SZXF1ZXN0LFxuICAgIC4uLmhhbmRsZXJSZXNwb25zZSxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3VibWl0UmVzcG9uc2Uoc3RhdHVzOiAnU1VDQ0VTUycgfCAnRkFJTEVEJywgZXZlbnQ6IFJlc3BvbnNlKSB7XG4gIGNvbnN0IGpzb246IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2UgPSB7XG4gICAgU3RhdHVzOiBzdGF0dXMsXG4gICAgUmVhc29uOiBldmVudC5SZWFzb24gPz8gc3RhdHVzLFxuICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgfHwgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIsXG4gICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIE5vRWNobzogZXZlbnQuTm9FY2hvLFxuICAgIERhdGE6IGV2ZW50LkRhdGEsXG4gIH07XG5cbiAgZXh0ZXJuYWwubG9nKCdzdWJtaXQgcmVzcG9uc2UgdG8gY2xvdWRmb3JtYXRpb24nLCBqc29uKTtcblxuICBjb25zdCByZXNwb25zZUJvZHkgPSBKU09OLnN0cmluZ2lmeShqc29uKTtcbiAgY29uc3QgcGFyc2VkVXJsID0gdXJsLnBhcnNlKGV2ZW50LlJlc3BvbnNlVVJMKTtcbiAgY29uc3QgcmVxID0ge1xuICAgIGhvc3RuYW1lOiBwYXJzZWRVcmwuaG9zdG5hbWUsXG4gICAgcGF0aDogcGFyc2VkVXJsLnBhdGgsXG4gICAgbWV0aG9kOiAnUFVUJyxcbiAgICBoZWFkZXJzOiB7ICdjb250ZW50LXR5cGUnOiAnJywgJ2NvbnRlbnQtbGVuZ3RoJzogcmVzcG9uc2VCb2R5Lmxlbmd0aCB9LFxuICB9O1xuXG4gIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHtcbiAgICBhdHRlbXB0czogNSxcbiAgICBzbGVlcDogMTAwMCxcbiAgfTtcbiAgYXdhaXQgd2l0aFJldHJpZXMocmV0cnlPcHRpb25zLCBleHRlcm5hbC5zZW5kSHR0cFJlcXVlc3QpKHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlPcHRpb25zIHtcbiAgLyoqIEhvdyBtYW55IHJldHJpZXMgKHdpbGwgYXQgbGVhc3QgdHJ5IG9uY2UpICovXG4gIHJlYWRvbmx5IGF0dGVtcHRzOiBudW1iZXI7XG4gIC8qKiBTbGVlcCBiYXNlLCBpbiBtcyAqL1xuICByZWFkb25seSBzbGVlcDogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aFJldHJpZXM8QSBleHRlbmRzIEFycmF5PGFueT4sIEI+KG9wdGlvbnM6IFJldHJ5T3B0aW9ucywgZm46ICguLi54czogQSkgPT4gUHJvbWlzZTxCPik6ICguLi54czogQSkgPT4gUHJvbWlzZTxCPiB7XG4gIHJldHVybiBhc3luYyAoLi4ueHM6IEEpID0+IHtcbiAgICBsZXQgYXR0ZW1wdHMgPSBvcHRpb25zLmF0dGVtcHRzO1xuICAgIGxldCBtcyA9IG9wdGlvbnMuc2xlZXA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmbiguLi54cyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChhdHRlbXB0cy0tIDw9IDApIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIG1zKSk7XG4gICAgICAgIG1zICo9IDI7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgob2spID0+IHNldFRpbWVvdXQob2ssIG1zKSk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js new file mode 100644 index 0000000000000..9df94382cc74e --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js @@ -0,0 +1,118 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + await exports.external.sendHttpRequest(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtLQUN2RSxDQUFDO0lBRUYsTUFBTSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ3ZGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWDtJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxHQUFHLE1BQWE7SUFDL0Msc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnN0IHJlc3A6IFJlc3BvbnNlID0ge1xuICAgICAgLi4uZXZlbnQsXG4gICAgICBSZWFzb246IGV4dGVybmFsLmluY2x1ZGVTdGFja1RyYWNlcyA/IGUuc3RhY2sgOiBlLm1lc3NhZ2UsXG4gICAgfTtcblxuICAgIGlmICghcmVzcC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICAgIC8vIHNwZWNpYWwgY2FzZTogaWYgQ1JFQVRFIGZhaWxzLCB3aGljaCB1c3VhbGx5IGltcGxpZXMsIHdlIHVzdWFsbHkgZG9uJ3RcbiAgICAgIC8vIGhhdmUgYSBwaHlzaWNhbCByZXNvdXJjZSBpZC4gaW4gdGhpcyBjYXNlLCB0aGUgc3Vic2VxdWVudCBERUxFVEVcbiAgICAgIC8vIG9wZXJhdGlvbiBkb2VzIG5vdCBoYXZlIGFueSBtZWFuaW5nLCBhbmQgd2lsbCBsaWtlbHkgZmFpbCBhcyB3ZWxsLiB0b1xuICAgICAgLy8gYWRkcmVzcyB0aGlzLCB3ZSB1c2UgYSBtYXJrZXIgc28gdGhlIHByb3ZpZGVyIGZyYW1ld29yayBjYW4gc2ltcGx5XG4gICAgICAvLyBpZ25vcmUgdGhlIHN1YnNlcXVlbnQgREVMRVRFLlxuICAgICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJykge1xuICAgICAgICBleHRlcm5hbC5sb2coJ0NSRUFURSBmYWlsZWQsIHJlc3BvbmRpbmcgd2l0aCBhIG1hcmtlciBwaHlzaWNhbCByZXNvdXJjZSBpZCBzbyB0aGF0IHRoZSBzdWJzZXF1ZW50IERFTEVURSB3aWxsIGJlIGlnbm9yZWQnKTtcbiAgICAgICAgcmVzcC5QaHlzaWNhbFJlc291cmNlSWQgPSBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgaWYgUGh5c2ljYWxSZXNvdXJjZUlkIGlzIG5vdCBzcGVjaWZpZWQsIHNvbWV0aGluZyBpc1xuICAgICAgICAvLyB0ZXJyaWJseSB3cm9uZyBiZWNhdXNlIGFsbCBvdGhlciBldmVudHMgc2hvdWxkIGhhdmUgYW4gSUQuXG4gICAgICAgIGV4dGVybmFsLmxvZyhgRVJST1I6IE1hbGZvcm1lZCBldmVudC4gXCJQaHlzaWNhbFJlc291cmNlSWRcIiBpcyByZXF1aXJlZDogJHtKU09OLnN0cmluZ2lmeShldmVudCl9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBpcyBhbiBhY3R1YWwgZXJyb3IsIGZhaWwgdGhlIGFjdGl2aXR5IGFsdG9nZXRoZXIgYW5kIGV4aXN0LlxuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdGQUlMRUQnLCByZXNwKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW5kZXJSZXNwb25zZShcbiAgY2ZuUmVxdWVzdDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIHsgUGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nIH0sXG4gIGhhbmRsZXJSZXNwb25zZTogdm9pZCB8IEhhbmRsZXJSZXNwb25zZSA9IHsgfSk6IFJlc3BvbnNlIHtcblxuICAvLyBpZiBwaHlzaWNhbCBJRCBpcyBub3QgcmV0dXJuZWQsIHdlIGhhdmUgc29tZSBkZWZhdWx0cyBmb3IgeW91IGJhc2VkXG4gIC8vIG9uIHRoZSByZXF1ZXN0IHR5cGUuXG4gIGNvbnN0IHBoeXNpY2FsUmVzb3VyY2VJZCA9IGhhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5SZXF1ZXN0SWQ7XG5cbiAgLy8gaWYgd2UgYXJlIGluIERFTEVURSBhbmQgcGh5c2ljYWwgSUQgd2FzIGNoYW5nZWQsIGl0J3MgYW4gZXJyb3IuXG4gIGlmIChjZm5SZXF1ZXN0LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBwaHlzaWNhbFJlc291cmNlSWQgIT09IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBERUxFVEU6IGNhbm5vdCBjaGFuZ2UgdGhlIHBoeXNpY2FsIHJlc291cmNlIElEIGZyb20gXCIke2NmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIHRvIFwiJHtoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIGR1cmluZyBkZWxldGlvbmApO1xuICB9XG5cbiAgLy8gbWVyZ2UgcmVxdWVzdCBldmVudCBhbmQgcmVzdWx0IGV2ZW50IChyZXN1bHQgcHJldmFpbHMpLlxuICByZXR1cm4ge1xuICAgIC4uLmNmblJlcXVlc3QsXG4gICAgLi4uaGFuZGxlclJlc3BvbnNlLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdWJtaXRSZXNwb25zZShzdGF0dXM6ICdTVUNDRVNTJyB8ICdGQUlMRUQnLCBldmVudDogUmVzcG9uc2UpIHtcbiAgY29uc3QganNvbjogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VSZXNwb25zZSA9IHtcbiAgICBTdGF0dXM6IHN0YXR1cyxcbiAgICBSZWFzb246IGV2ZW50LlJlYXNvbiA/PyBzdGF0dXMsXG4gICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICBSZXF1ZXN0SWQ6IGV2ZW50LlJlcXVlc3RJZCxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCB8fCBNSVNTSU5HX1BIWVNJQ0FMX0lEX01BUktFUixcbiAgICBMb2dpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgTm9FY2hvOiBldmVudC5Ob0VjaG8sXG4gICAgRGF0YTogZXZlbnQuRGF0YSxcbiAgfTtcblxuICBleHRlcm5hbC5sb2coJ3N1Ym1pdCByZXNwb25zZSB0byBjbG91ZGZvcm1hdGlvbicsIGpzb24pO1xuXG4gIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KGpzb24pO1xuICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2UoZXZlbnQuUmVzcG9uc2VVUkwpO1xuICBjb25zdCByZXEgPSB7XG4gICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICBwYXRoOiBwYXJzZWRVcmwucGF0aCxcbiAgICBtZXRob2Q6ICdQVVQnLFxuICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiByZXNwb25zZUJvZHkubGVuZ3RoIH0sXG4gIH07XG5cbiAgYXdhaXQgZXh0ZXJuYWwuc2VuZEh0dHBSZXF1ZXN0KHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts new file mode 100644 index 0000000000000..3554dc94d4617 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts @@ -0,0 +1 @@ +export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent): Promise; diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/index.js b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.js similarity index 100% rename from packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/index.js rename to packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.js diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts new file mode 100644 index 0000000000000..2459d44ab1d18 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts @@ -0,0 +1,82 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { S3 } from 'aws-sdk'; + +const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; + +const s3 = new S3(); + +export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { + switch (event.RequestType) { + case 'Create': + return; + case 'Update': + return onUpdate(event); + case 'Delete': + return onDelete(event.ResourceProperties?.BucketName); + } +} + +async function onUpdate(event: AWSLambda.CloudFormationCustomResourceEvent) { + const updateEvent = event as AWSLambda.CloudFormationCustomResourceUpdateEvent; + const oldBucketName = updateEvent.OldResourceProperties?.BucketName; + const newBucketName = updateEvent.ResourceProperties?.BucketName; + const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; + + /* If the name of the bucket has changed, CloudFormation will try to delete the bucket + and create a new one with the new name. So we have to delete the contents of the + bucket so that this operation does not fail. */ + if (bucketNameHasChanged) { + return onDelete(oldBucketName); + } +} + +/** + * Recursively delete all items in the bucket + * + * @param bucketName the bucket name + */ +async function emptyBucket(bucketName: string) { + const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); + const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; + if (contents.length === 0) { + return; + } + + const records = contents.map((record: any) => ({ Key: record.Key, VersionId: record.VersionId })); + await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); + + if (listedObjects?.IsTruncated) { + await emptyBucket(bucketName); + } +} + +async function onDelete(bucketName?: string) { + if (!bucketName) { + throw new Error('No BucketName was provided.'); + } + if (!await isBucketTaggedForDeletion(bucketName)) { + process.stdout.write(`Bucket does not have '${AUTO_DELETE_OBJECTS_TAG}' tag, skipping cleaning.\n`); + return; + } + try { + await emptyBucket(bucketName); + } catch (e) { + if (e.code !== 'NoSuchBucket') { + throw e; + } + // Bucket doesn't exist. Ignoring + } +} + +/** + * The bucket will only be tagged for deletion if it's being deleted in the same + * deployment as this Custom Resource. + * + * If the Custom Resource is every deleted before the bucket, it must be because + * `autoDeleteObjects` has been switched to false, in which case the tag would have + * been removed before we get to this Delete event. + */ +async function isBucketTaggedForDeletion(bucketName: string) { + const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); + return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js similarity index 75% rename from packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js rename to packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js index 6bee1ced2a9b7..ba956d47f51fe 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/asset.84802aa01d2d2c9e7d8d69705ee832c97f1ebad2d73c72be5c32d53f16cf90a7.bundle/index.js @@ -1,3 +1,4 @@ +"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; @@ -25,9 +26,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru // lib/assertions/providers/lambda-handler/index.ts var lambda_handler_exports = {}; __export(lambda_handler_exports, { - handler: () => handler, - isComplete: () => isComplete, - onTimeout: () => onTimeout + handler: () => handler }); module.exports = __toCommonJS(lambda_handler_exports); @@ -387,7 +386,6 @@ var StringLikeRegexpMatch = class extends Matcher { // lib/assertions/providers/lambda-handler/base.ts var https = __toESM(require("https")); var url = __toESM(require("url")); -var AWS = __toESM(require("aws-sdk")); var CustomResourceHandler = class { constructor(event, context) { this.event = event; @@ -406,40 +404,20 @@ var CustomResourceHandler = class { } async handle() { try { - if ("stateMachineArn" in this.event.ResourceProperties) { - const req = { - stateMachineArn: this.event.ResourceProperties.stateMachineArn, - name: this.event.RequestId, - input: JSON.stringify(this.event) - }; - await this.startExecution(req); - return; - } else { - const response = await this.processEvent(this.event.ResourceProperties); - return response; - } - } catch (e) { - console.log(e); - throw e; - } finally { - clearTimeout(this.timeout); - } - } - async handleIsComplete() { - try { - const result = await this.processEvent(this.event.ResourceProperties); - return result; + 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 + }); } catch (e) { console.log(e); - return; - } finally { - clearTimeout(this.timeout); - } - } - async startExecution(req) { - try { - const sfn = new AWS.StepFunctions(); - await sfn.startExecution(req).promise(); + await this.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); } finally { clearTimeout(this.timeout); } @@ -475,8 +453,6 @@ var CustomResourceHandler = class { request2.end(); } catch (e) { reject(e); - } finally { - clearTimeout(this.timeout); } }); } @@ -503,8 +479,7 @@ var AssertionHandler = class extends CustomResourceHandler { matchResult.finished(); if (matchResult.hasFailed()) { result = { - failed: true, - assertion: JSON.stringify({ + data: JSON.stringify({ status: "fail", message: [ ...matchResult.toHumanStrings(), @@ -513,11 +488,11 @@ var AssertionHandler = class extends CustomResourceHandler { }) }; if (request2.failDeployment) { - throw new Error(result.assertion); + throw new Error(result.data); } } else { result = { - assertion: JSON.stringify({ + data: JSON.stringify({ status: "success" }) }; @@ -587,10 +562,7 @@ function flatten(object) { {}, ...function _flatten(child, path = []) { return [].concat(...Object.keys(child).map((key) => { - let childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; - if (typeof childKey === "string") { - childKey = isJsonString(childKey); - } + const childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; })); }(object) @@ -598,12 +570,9 @@ function flatten(object) { } var AwsApiCallHandler = class extends CustomResourceHandler { async processEvent(request2) { - const AWS2 = require("aws-sdk"); - console.log(`AWS SDK VERSION: ${AWS2.VERSION}`); - if (!Object.prototype.hasOwnProperty.call(AWS2, request2.service)) { - throw Error(`Service ${request2.service} does not exist in AWS SDK version ${AWS2.VERSION}.`); - } - const service = new AWS2[request2.service](); + const AWS = require("aws-sdk"); + console.log(`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)}`); delete response.ResponseMetadata; @@ -613,18 +582,9 @@ var AwsApiCallHandler = class extends CustomResourceHandler { const flatData = { ...flatten(respond) }; - const resp = request2.flattenResponse === "true" ? flatData : respond; - console.log(`Returning result ${JSON.stringify(resp)}`); - return resp; + return request2.flattenResponse === "true" ? flatData : respond; } }; -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"; @@ -632,136 +592,21 @@ 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); - try { - if (event.RequestType === "Delete") { - await provider.respond({ - status: "SUCCESS", - reason: "OK" - }); - return; - } - const result = await provider.handle(); - if ("stateMachineArn" in event.ResourceProperties) { - console.info('Found "stateMachineArn", waiter statemachine started'); - return; - } else if ("expected" in event.ResourceProperties) { - console.info('Found "expected", testing assertions'); - const actualPath = event.ResourceProperties.actualPath; - const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; - 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; -} -async function onTimeout(timeoutEvent) { - const isCompleteRequest = JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage); - const provider = createResourceHandler(isCompleteRequest, standardContext); - await provider.respond({ - status: "FAILED", - reason: "Operation timed out: " + JSON.stringify(isCompleteRequest) - }); -} -async function isComplete(event, context) { - console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); const provider = createResourceHandler(event, context); - try { - const result = await provider.handleIsComplete(); - const actualPath = event.ResourceProperties.actualPath; - if (result) { - 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); - const assertionResult = await assertion.handleIsComplete(); - if (!(assertionResult == null ? void 0 : assertionResult.failed)) { - await provider.respond({ - status: "SUCCESS", - reason: "OK", - data: { - ...assertionResult, - ...result - } - }); - return; - } else { - console.log(`Assertion Failed: ${JSON.stringify(assertionResult)}`); - throw new Error(JSON.stringify(event)); - } - } - await provider.respond({ - status: "SUCCESS", - reason: "OK", - data: result - }); - } else { - console.log("No result"); - throw new Error(JSON.stringify(event)); - } - return; - } catch (e) { - console.log(e); - throw new Error(JSON.stringify(event)); - } + await provider.handle(); } function createResourceHandler(event, context) { if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { return new AwsApiCallHandler(event, context); - } else if (event.ResourceType.startsWith(ASSERT_RESOURCE_TYPE)) { - return new AssertionHandler(event, context); - } else { - throw new Error(`Unsupported resource type "${event.ResourceType}`); + } + switch (event.ResourceType) { + case ASSERT_RESOURCE_TYPE: + return new AssertionHandler(event, context); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); } } -var standardContext = { - getRemainingTimeInMillis: () => 9e4 -}; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { - handler, - isComplete, - onTimeout + handler }); diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/manifest.json index 773077597be42..a114baf10c235 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/manifest.json @@ -1,6 +1,12 @@ { "version": "21.0.0", "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, "FlowLogsFeatureFlag.assets": { "type": "cdk:asset-manifest", "properties": { @@ -17,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}/8f4f8db3ea3ad2d5f5678275c75dce7d9b67b46d8df7d92c62913bdc5a03cd3f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2db53e096625b4b167fb15dd7bdc246692b381f45e28c509614fef7d41c20bc9.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -204,10 +210,7 @@ "/FlowLogsFeatureFlag/VPC/FlowLogsS3WithDestinationOptions/FlowLog": [ { "type": "aws:cdk:logicalId", - "data": "VPCFlowLogsS3WithDestinationOptionsFlowLog030C15B2", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "VPCFlowLogsS3WithDestinationOptionsFlowLog030C15B2" } ], "/FlowLogsFeatureFlag/Exports/Output{\"Fn::GetAtt\":[\"VPCFlowLogsS3BucketFB7DC2BE\",\"Arn\"]}": [ @@ -283,7 +286,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}/23955aa16c5d59106d93ecce9cedd43aa5782fbf23bb2ef8549b2119345a6f79.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2090a74d484bc155b48d7511b99e4921b8f55e488c3fe1500cffede0cdfd33b7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -546,7 +549,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}/dd951509b1e22484b40a66a661cb8cebce3087b8cb381e3dcf02e641e5eb08cd.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1dcf759cd2c8928f5b1acfbf439f1751e25367a5ac61ba5e640ff8b78fdf89f7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -601,12 +604,6 @@ ] }, "displayName": "FlowLogs/DefaultTest/DeployAssert" - }, - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/tree.json index f6e0ef7c83ea9..9a0ff6b79a4b7 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc-flow-logs.js.snapshot/tree.json @@ -4,6 +4,14 @@ "id": "App", "path": "", "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.123" + } + }, "FlowLogsFeatureFlag": { "id": "FlowLogsFeatureFlag", "path": "FlowLogsFeatureFlag", @@ -819,6 +827,7 @@ "Ref": "VPCB9E5F0B4" }, "resourceType": "VPC", + "trafficType": "ALL", "logDestination": { "Fn::GetAtt": [ "VPCFlowLogsS3BucketFB7DC2BE", @@ -831,8 +840,7 @@ "key": "Name", "value": "FlowLogsFeatureFlag/VPC" } - ], - "trafficType": "ALL" + ] } }, "constructInfo": { @@ -1020,10 +1028,11 @@ "Ref": "VPCB9E5F0B4" }, "resourceType": "VPC", + "trafficType": "ALL", "destinationOptions": { "fileFormat": "plain-text", - "hiveCompatiblePartitions": true, - "perHourPartition": false + "perHourPartition": false, + "hiveCompatiblePartitions": true }, "logDestination": { "Fn::GetAtt": [ @@ -1037,8 +1046,7 @@ "key": "Name", "value": "FlowLogsFeatureFlag/VPC" } - ], - "trafficType": "ALL" + ] } }, "constructInfo": { @@ -1081,7 +1089,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.123" } }, "FlowLogsInstance": { @@ -1132,14 +1140,6 @@ "id": "InstanceRole", "path": "FlowLogsFeatureFlag/FlowLogsInstance/InstanceRole", "children": { - "ImportInstanceRole": { - "id": "ImportInstanceRole", - "path": "FlowLogsFeatureFlag/FlowLogsInstance/InstanceRole/ImportInstanceRole", - "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" - } - }, "Resource": { "id": "Resource", "path": "FlowLogsFeatureFlag/FlowLogsInstance/InstanceRole/Resource", @@ -1264,22 +1264,6 @@ "fqn": "@aws-cdk/core.Resource", "version": "0.0.0" } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "FlowLogsFeatureFlag/BootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "FlowLogsFeatureFlag/CheckBootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" - } } }, "constructInfo": { @@ -2102,6 +2086,7 @@ "Ref": "VPCB9E5F0B4" }, "resourceType": "VPC", + "trafficType": "ALL", "logDestination": { "Fn::GetAtt": [ "VPCFlowLogsS3BucketFB7DC2BE", @@ -2114,8 +2099,7 @@ "key": "Name", "value": "FlowLogsTestStack/VPC" } - ], - "trafficType": "ALL" + ] } }, "constructInfo": { @@ -2143,6 +2127,7 @@ "Ref": "VPCB9E5F0B4" }, "resourceType": "VPC", + "trafficType": "ALL", "logDestination": { "Fn::Join": [ "", @@ -2163,8 +2148,7 @@ "key": "Name", "value": "FlowLogsTestStack/VPC" } - ], - "trafficType": "ALL" + ] } }, "constructInfo": { @@ -2192,14 +2176,6 @@ "id": "IAMRole", "path": "FlowLogsTestStack/FlowLogsCW/IAMRole", "children": { - "ImportIAMRole": { - "id": "ImportIAMRole", - "path": "FlowLogsTestStack/FlowLogsCW/IAMRole/ImportIAMRole", - "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" - } - }, "Resource": { "id": "Resource", "path": "FlowLogsTestStack/FlowLogsCW/IAMRole/Resource", @@ -2323,6 +2299,7 @@ "Ref": "VPCB9E5F0B4" }, "resourceType": "VPC", + "trafficType": "ALL", "deliverLogsPermissionArn": { "Fn::GetAtt": [ "FlowLogsCWIAMRole017AD736", @@ -2332,8 +2309,7 @@ "logDestinationType": "cloud-watch-logs", "logGroupName": { "Ref": "FlowLogsCWLogGroup0398E8F8" - }, - "trafficType": "ALL" + } } }, "constructInfo": { @@ -2616,22 +2592,6 @@ "fqn": "@aws-cdk/core.CustomResourceProvider", "version": "0.0.0" } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "FlowLogsTestStack/BootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "FlowLogsTestStack/CheckBootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" - } } }, "constructInfo": { @@ -2652,7 +2612,7 @@ "path": "FlowLogs/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.123" } }, "DeployAssert": { @@ -2672,7 +2632,7 @@ "path": "FlowLogs/DefaultTest/DeployAssert/AwsApiCallS3listObjectsV2/SdkProvider/AssertionsProvider", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.123" } } }, @@ -2744,23 +2704,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "FlowLogs/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "FlowLogs/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" + "version": "10.1.123" } } }, @@ -2780,14 +2724,6 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.161" - } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts index 7a068377feffb..5b16d80caf50d 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts @@ -93,9 +93,9 @@ describe('vpc flow logs', () => { TrafficType: 'ALL', ResourceId: 'eni-123456', DestinationOptions: { - HiveCompatiblePartitions: true, - FileFormat: 'plain-text', - PerHourPartition: false, + hiveCompatiblePartitions: true, + fileFormat: 'plain-text', + perHourPartition: false, }, LogDestination: { 'Fn::GetAtt': [ diff --git a/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts index 0177a7e21b695..e6930b7844d32 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts @@ -136,10 +136,16 @@ export class ClusterResourceHandler extends ResourceHandler { return this.updateClusterVersion(this.newProps.version); } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { const config: aws.EKS.UpdateClusterConfigRequest = { name: this.clusterName, - logging: this.newProps.logging, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; }; if (updates.updateAccess) { // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: @@ -334,5 +340,5 @@ function analyzeUpdate(oldProps: Partial, newProps } function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); + return first.size === second.size && [...first].every((e: string) => second.has(e)); } diff --git a/packages/@aws-cdk/aws-eks/test/cluster-resource-provider.test.ts b/packages/@aws-cdk/aws-eks/test/cluster-resource-provider.test.ts index 5bec15aaed2d8..f1ad11b562838 100644 --- a/packages/@aws-cdk/aws-eks/test/cluster-resource-provider.test.ts +++ b/packages/@aws-cdk/aws-eks/test/cluster-resource-provider.test.ts @@ -588,11 +588,16 @@ describe('cluster resource provider', () => { logging: undefined, resourcesVpcConfig: undefined, })); - - const resp = await handler.onEvent(); - expect(resp).toEqual({ EksUpdateId: mocks.MOCK_UPDATE_STATUS_ID }); - expect(mocks.actualRequest.updateClusterConfigRequest!).toEqual({ - name: 'physical-resource-id', + let error: any; + try { + await handler.onEvent(); + } catch (e) { + error = e; + } + expect(error.message).toEqual('Cannot update logging and access at the same time'); + }); + test('both logging and access defined and modify both of them', async () => { + const handler = new ClusterResourceHandler(mocks.client, mocks.newRequest('Update', { logging: { clusterLogging: [ { @@ -601,13 +606,99 @@ describe('cluster resource provider', () => { }, ], }, + resourcesVpcConfig: { + endpointPrivateAccess: true, + endpointPublicAccess: false, + publicAccessCidrs: ['0.0.0.0/0'], + }, + }, { + logging: { + clusterLogging: [ + { + types: ['api', 'audit', 'authenticator', 'controllerManager'], + enabled: true, + }, + ], + }, resourcesVpcConfig: { endpointPrivateAccess: true, endpointPublicAccess: true, publicAccessCidrs: ['0.0.0.0/0'], }, - }); - expect(mocks.actualRequest.createClusterRequest).toEqual(undefined); + })); + let error: any; + try { + await handler.onEvent(); + } catch (e) { + error = e; + } + expect(error.message).toEqual('Cannot update logging and access at the same time'); + }); + test('Given logging enabled and unchanged, updating the only publicAccessCidrs is allowed ', async () => { + const handler = new ClusterResourceHandler(mocks.client, mocks.newRequest('Update', { + logging: { + clusterLogging: [ + { + types: ['api', 'audit', 'authenticator', 'controllerManager', 'scheduler'], + enabled: true, + }, + ], + }, + resourcesVpcConfig: { + endpointPrivateAccess: true, + endpointPublicAccess: true, + publicAccessCidrs: ['1.2.3.4/32'], + }, + }, { + logging: { + clusterLogging: [ + { + types: ['api', 'audit', 'authenticator', 'controllerManager', 'scheduler'], + enabled: true, + }, + ], + }, + resourcesVpcConfig: { + endpointPrivateAccess: true, + endpointPublicAccess: true, + publicAccessCidrs: ['0.0.0.0/0'], + }, + })); + const resp = await handler.onEvent(); + expect(resp).toEqual({ EksUpdateId: 'MockEksUpdateStatusId' }); + }); + test('Given logging enabled and unchanged, updating publicAccessCidrs from one to multiple entries is allowed ', async () => { + const handler = new ClusterResourceHandler(mocks.client, mocks.newRequest('Update', { + logging: { + clusterLogging: [ + { + types: ['api', 'audit', 'authenticator', 'controllerManager', 'scheduler'], + enabled: true, + }, + ], + }, + resourcesVpcConfig: { + endpointPrivateAccess: true, + endpointPublicAccess: true, + publicAccessCidrs: ['2.4.6.0/24', '1.2.3.4/32', '3.3.3.3/32'], + }, + }, { + logging: { + clusterLogging: [ + { + types: ['api', 'audit', 'authenticator', 'controllerManager', 'scheduler'], + enabled: true, + }, + ], + }, + resourcesVpcConfig: { + endpointPrivateAccess: true, + endpointPublicAccess: true, + publicAccessCidrs: ['2.4.6.0/24'], + }, + })); + const resp = await handler.onEvent(); + expect(resp).toEqual({ EksUpdateId: 'MockEksUpdateStatusId' }); }); }); }); diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.ts index f19c0d7cbaa70..40034ed72c1c8 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.ts @@ -94,7 +94,7 @@ vpc.publicSubnets.forEach((subnet, idx) => { cfnSubnet.ipv6CidrBlock = cdk.Fn.select(idx, ipv6Cidrs); // The subnet depends on the ipv6 cidr being allocated. - cfnSubnet.addDependsOn(ipv6Block); + cfnSubnet.addDependency(ipv6Block); group1.node.addDependency(subnet); group2.node.addDependency(subnet); diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index c611fa6152255..0056f000db052 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -24,6 +24,13 @@ export interface CommonGrantOptions { * The resource ARNs to grant to */ readonly resourceArns: string[]; + + /** + * Any conditions to attach to the grant + * + * @default - No conditions + */ + readonly conditions?: Record>; } /** @@ -160,6 +167,7 @@ export class Grant implements IDependable { const statement = new PolicyStatement({ actions: options.actions, resources: options.resourceArns, + conditions: options.conditions, }); const addedToPrincipal = options.grantee.grantPrincipal.addToPrincipalPolicy(statement); @@ -224,17 +232,27 @@ export class Grant implements IDependable { /** * The statement that was added to the principal's policy * - * Can be accessed to (e.g.) add additional conditions to the statement. + * @deprecated Use `principalStatements` instead */ public readonly principalStatement?: PolicyStatement; + /** + * The statements that were added to the principal's policy + */ + public readonly principalStatements = new Array(); + /** * The statement that was added to the resource policy * - * Can be accessed to (e.g.) add additional conditions to the statement. + * @deprecated Use `resourceStatements` instead */ public readonly resourceStatement?: PolicyStatement; + /** + * The statements that were added to the principal's policy + */ + public readonly resourceStatements = new Array(); + /** * The options originally used to set this result * @@ -243,14 +261,26 @@ export class Grant implements IDependable { */ private readonly options: CommonGrantOptions; + private readonly dependables = new Array(); + private constructor(props: GrantProps) { this.options = props.options; this.principalStatement = props.principalStatement; this.resourceStatement = props.resourceStatement; + if (this.principalStatement) { + this.principalStatements.push(this.principalStatement); + } + if (this.resourceStatement) { + this.resourceStatements.push(this.resourceStatement); + } + if (props.policyDependable) { + this.dependables.push(props.policyDependable); + } + const self = this; Dependable.implement(this, { get dependencyRoots() { - return props.policyDependable ? Dependable.of(props.policyDependable).dependencyRoots : []; + return Array.from(new Set(self.dependables.flatMap(d => Dependable.of(d).dependencyRoots))); }, }); } @@ -282,6 +312,24 @@ export class Grant implements IDependable { construct.node.addDependency(this); } } + + /** + * Combine two grants into a new one + */ + public combine(rhs: Grant) { + const combinedPrinc = [...this.principalStatements, ...rhs.principalStatements]; + const combinedRes = [...this.resourceStatements, ...rhs.resourceStatements]; + + const ret = new Grant({ + options: this.options, + principalStatement: combinedPrinc[0], + resourceStatement: combinedRes[0], + }); + ret.principalStatements.splice(0, ret.principalStatements.length, ...combinedPrinc); + ret.resourceStatements.splice(0, ret.resourceStatements.length, ...combinedRes); + ret.dependables.push(...this.dependables, ...rhs.dependables); + return ret; + } } function describeGrant(options: CommonGrantOptions) { diff --git a/packages/@aws-cdk/aws-iam/test/grant.test.ts b/packages/@aws-cdk/aws-iam/test/grant.test.ts index 1a4ca30016d6c..8e02c82da8596 100644 --- a/packages/@aws-cdk/aws-iam/test/grant.test.ts +++ b/packages/@aws-cdk/aws-iam/test/grant.test.ts @@ -1,4 +1,4 @@ -import { Template } from '@aws-cdk/assertions'; +import { Template, Match } from '@aws-cdk/assertions'; import { CfnResource, Resource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import * as iam from '../lib'; @@ -97,6 +97,34 @@ describe('Grant dependencies', () => { expectDependencyOn('RoleDefaultPolicy5FFB7DAB'); expectDependencyOn('BuckarooPolicy74174DA4'); }); + + test('can combine two grants', () => { + // GIVEN + const role1 = new iam.Role(stack, 'Role1', { + assumedBy: new iam.ServicePrincipal('bla.amazonaws.com'), + }); + const role2 = new iam.Role(stack, 'Role2', { + assumedBy: new iam.ServicePrincipal('bla.amazonaws.com'), + }); + + // WHEN + const g1 = iam.Grant.addToPrincipal({ + actions: ['service:DoAThing'], + grantee: role1, + resourceArns: ['*'], + }); + const g2 = iam.Grant.addToPrincipal({ + actions: ['service:DoAThing'], + grantee: role2, + resourceArns: ['*'], + }); + + (g1.combine(g2)).applyBefore(resource); + + // THEN + expectDependencyOn('Role1DefaultPolicyD3EF4D0A'); + expectDependencyOn('Role2DefaultPolicy3A7A0A1B'); + }); }); function applyGrantWithDependencyTo(principal: iam.IPrincipal) { @@ -108,8 +136,8 @@ function applyGrantWithDependencyTo(principal: iam.IPrincipal) { } function expectDependencyOn(id: string) { - Template.fromStack(stack).hasResource('CDK::Test::SomeResource', (props: any) => { - return (props?.DependsOn ?? []).includes(id); + Template.fromStack(stack).hasResource('CDK::Test::SomeResource', { + DependsOn: Match.arrayWith([id]), }); } diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 419425f44f6a5..b3e118e4f1b10 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -764,6 +764,55 @@ const fn = new lambda.Function(this, 'MyFunction', { See [the AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html) to learn more about AWS Lambda's X-Ray support. +## Lambda with AWS Distro for OpenTelemetry layer + +To have automatic integration with XRay without having to add dependencies or change your code, you can use the +[AWS Distro for OpenTelemetry Lambda (ADOT) layer](https://aws-otel.github.io/docs/getting-started/lambda). +Consuming the latest ADOT layer can be done with the following snippet: + +```ts +import { + AdotLambdaExecWrapper, + AdotLayerVersion, + AdotLambdaLayerJavaScriptSdkVersion, +} from 'aws-cdk-lib/aws-lambda'; + +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_18_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromJavaScriptSdkLayerVersion(AdotLambdaLayerJavaScriptSdkVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, +}); +``` + +To use a different layer version, use one of the following helper functions for the `layerVersion` prop: + +* `AdotLayerVersion.fromJavaScriptSdkLayerVersion` +* `AdotLayerVersion.fromPythonSdkLayerVersion` +* `AdotLayerVersion.fromJavaSdkLayerVersion` +* `AdotLayerVersion.fromJavaAutoInstrumentationSdkLayerVersion` +* `AdotLayerVersion.fromGenericSdkLayerVersion` + +Each helper function expects a version value from a corresponding enum-like class as below: + +* `AdotLambdaLayerJavaScriptSdkVersion` +* `AdotLambdaLayerPythonSdkVersion` +* `AdotLambdaLayerJavaSdkVersion` +* `AdotLambdaLayerJavaAutoInstrumentationSdkVersion` +* `AdotLambdaLayerGenericSdkVersion` + +For more examples, see our [the integration test](test/integ.lambda-adot.ts). + +If you want to retrieve the ARN of the ADOT Lambda layer without enabling ADOT in a Lambda function: + +```ts +declare const fn: lambda.Function; +const layerArn = lambda.AdotLambdaLayerJavaSdkVersion.V1_19_0.layerArn(fn.stack, fn.architecture); +``` + ## Lambda with Profiling The following code configures the lambda function with CodeGuru profiling. By default, this creates a new CodeGuru diff --git a/packages/@aws-cdk/aws-lambda/lib/adot-layers.ts b/packages/@aws-cdk/aws-lambda/lib/adot-layers.ts new file mode 100644 index 0000000000000..401830082e4fb --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/lib/adot-layers.ts @@ -0,0 +1,301 @@ +import { RegionInfo } from '@aws-cdk/region-info'; +import { IConstruct } from 'constructs'; +import { Stack } from '../../core/lib/stack'; +import { Token } from '../../core/lib/token'; +import { FactName } from '../../region-info/lib/fact'; +import { Architecture } from './architecture'; +import { IFunction } from './function-base'; + +/** + * The type of ADOT Lambda layer + */ +enum AdotLambdaLayerType { + /** + * The Lambda layer for ADOT Java instrumentation library. This layer only auto-instruments AWS + * SDK libraries. + */ + JAVA_SDK = 'JAVA_SDK', + + /** + * The Lambda layer for ADOT Java Auto-Instrumentation Agent. This layer automatically instruments + * a large number of libraries and frameworks out of the box and has notable impact on startup + * performance. + */ + JAVA_AUTO_INSTRUMENTATION = 'JAVA_AUTO_INSTRUMENTATION', + + /** + * The Lambda layer for ADOT Collector, OpenTelemetry for JavaScript and supported libraries. + */ + JAVASCRIPT_SDK = 'JAVASCRIPT_SDK', + + /** + * The Lambda layer for ADOT Collector, OpenTelemetry for Python and supported libraries. + */ + PYTHON_SDK = 'PYTHON_SDK', + + /** + * The generic Lambda layer that contains only ADOT Collector, used for manual instrumentation + * use cases (such as Go or DotNet runtimes). + */ + GENERIC = 'GENERIC', +} + +/** + * Config returned from {@link AdotLambdaLayerVersion._bind} + */ +interface AdotLambdaLayerBindConfig { + /** + * ARN of the ADOT Lambda layer version + */ + readonly arn: string; +} + +/** + * Return the ARN of an ADOT Lambda layer given its properties. If the region name is unknown + * at synthesis time, it will generate a map in the CloudFormation template and perform the look + * up at deployment time. + * + * @param scope the parent Construct that will use the imported layer. + * @param type the type of the ADOT Lambda layer + * @param version The version of the ADOT Lambda layer + * @param architecture the architecture of the Lambda layer ('amd64' or 'arm64') + */ +function getLayerArn(scope: IConstruct, type: string, version: string, architecture: string): string { + const scopeStack = Stack.of(scope); + const region = scopeStack.region; + + // Region is defined, look up the arn, or throw an error if the version isn't supported by a region + if (region !== undefined && !Token.isUnresolved(region)) { + const arn = RegionInfo.get(region).adotLambdaLayerArn(type, version, architecture); + if (arn === undefined) { + throw new Error( + `Could not find the ARN information for the ADOT Lambda Layer of type ${type} and version ${version} in ${region}`, + ); + } + return arn; + } + + // Otherwise, need to add a mapping to be looked up at deployment time + return scopeStack.regionalFact(FactName.adotLambdaLayer(type, version, architecture)); +} + +/** + * Properties for an ADOT instrumentation in Lambda + */ +export interface AdotInstrumentationConfig { + /** + * The ADOT Lambda layer. + */ + readonly layerVersion: AdotLayerVersion; + + /** + * The startup script to run, see ADOT documentation to pick the right script for your use case: https://aws-otel.github.io/docs/getting-started/lambda + */ + readonly execWrapper: AdotLambdaExecWrapper; +} + +/** + * An ADOT Lambda layer version that's specific to a lambda layer type and an architecture. + */ +export abstract class AdotLayerVersion { + /** + * The ADOT Lambda layer for Java SDK + * + * @param version The version of the Lambda layer to use + */ + public static fromJavaSdkLayerVersion(version: AdotLambdaLayerJavaSdkVersion): AdotLayerVersion { + return AdotLayerVersion.fromAdotVersion(version); + } + + /** + * The ADOT Lambda layer for Java auto instrumentation + * + * @param version The version of the Lambda layer to use + */ + public static fromJavaAutoInstrumentationLayerVersion( + version: AdotLambdaLayerJavaAutoInstrumentationVersion, + ): AdotLayerVersion { + return AdotLayerVersion.fromAdotVersion(version); + } + + /** + * The ADOT Lambda layer for JavaScript SDK + * + * @param version The version of the Lambda layer to use + */ + public static fromJavaScriptSdkLayerVersion(version: AdotLambdaLayerJavaScriptSdkVersion): AdotLayerVersion { + return AdotLayerVersion.fromAdotVersion(version); + } + + /** + * The ADOT Lambda layer for Python SDK + * + * @param version The version of the Lambda layer to use + */ + public static fromPythonSdkLayerVersion(version: AdotLambdaLayerPythonSdkVersion): AdotLayerVersion { + return AdotLayerVersion.fromAdotVersion(version); + } + + /** + * The ADOT Lambda layer for generic use cases + * + * @param version The version of the Lambda layer to use + */ + public static fromGenericLayerVersion(version: AdotLambdaLayerGenericVersion): AdotLayerVersion { + return AdotLayerVersion.fromAdotVersion(version); + } + + private static fromAdotVersion(adotVersion: AdotLambdaLayerVersion): AdotLayerVersion { + return new (class extends AdotLayerVersion { + _bind(_function: IFunction): AdotLambdaLayerBindConfig { + return { + arn: adotVersion.layerArn(_function.stack, _function.architecture), + }; + } + })(); + } + + /** + * Produce a `AdotLambdaLayerBindConfig` instance from this `AdotLayerVersion` instance. + * + * @internal + */ + public abstract _bind(_function: IFunction): AdotLambdaLayerBindConfig; +} + +/** + * The wrapper script to be used for the Lambda function in order to enable auto instrumentation + * with ADOT. + */ +export enum AdotLambdaExecWrapper { + /** + * Wrapping regular Lambda handlers. + */ + REGULAR_HANDLER = '/opt/otel-handler', + + /** + * Wrapping regular handlers (implementing RequestHandler) proxied through API Gateway, enabling + * HTTP context propagation. + */ + PROXY_HANDLER = '/opt/otel-proxy-handler', + + /** + * Wrapping streaming handlers (implementing RequestStreamHandler), enabling HTTP context + * propagation for HTTP requests. + */ + STREAM_HANDLER = '/opt/otel-stream-handler', +} + +abstract class AdotLambdaLayerVersion { + protected constructor(protected readonly type: AdotLambdaLayerType, protected readonly version: string) {} + + /** + * The ARN of the Lambda layer + * + * @param scope The binding scope. Usually this is the stack where the Lambda layer is bound to + * @param architecture The architecture of the Lambda layer (either X86_64 or ARM_64) + */ + public layerArn(scope: IConstruct, architecture: Architecture): string { + return getLayerArn(scope, this.type, this.version, architecture.name); + } +} + +/** + * The collection of versions of the ADOT Lambda Layer for Java SDK + */ +export class AdotLambdaLayerJavaSdkVersion extends AdotLambdaLayerVersion { + /** + * The latest layer version available in this CDK version. New versions could + * introduce incompatible changes. Make sure to test them before deploying to production. + */ + public static readonly LATEST = new AdotLambdaLayerJavaSdkVersion('1.19.0'); + + /** + * Version 1.19.0 + */ + public static readonly V1_19_0 = new AdotLambdaLayerJavaSdkVersion('1.19.0'); + + private constructor(protected readonly layerVersion: string) { + super(AdotLambdaLayerType.JAVA_SDK, layerVersion); + } +} + +/** + * The collection of versions of the ADOT Lambda Layer for Java auto-instrumentation + */ +export class AdotLambdaLayerJavaAutoInstrumentationVersion extends AdotLambdaLayerVersion { + /** + * The latest layer version available in this CDK version. New versions could + * introduce incompatible changes. Make sure to test them before deploying to production. + */ + public static readonly LATEST = new AdotLambdaLayerJavaAutoInstrumentationVersion('1.19.2'); + + /** + * Version 1.19.2 + */ + public static readonly V1_19_2 = new AdotLambdaLayerJavaAutoInstrumentationVersion('1.19.2'); + + private constructor(protected readonly layerVersion: string) { + super(AdotLambdaLayerType.JAVA_AUTO_INSTRUMENTATION, layerVersion); + } +} + +/** + * The collection of versions of the ADOT Lambda Layer for Python SDK + */ +export class AdotLambdaLayerPythonSdkVersion extends AdotLambdaLayerVersion { + /** + * The latest layer version available in this CDK version. New versions could + * introduce incompatible changes. Make sure to test them before deploying to production. + */ + public static readonly LATEST = new AdotLambdaLayerPythonSdkVersion('1.13.0'); + + /** + * Version 1.13.0 + */ + public static readonly V1_13_0 = new AdotLambdaLayerPythonSdkVersion('1.13.0'); + + private constructor(protected readonly layerVersion: string) { + super(AdotLambdaLayerType.PYTHON_SDK, layerVersion); + } +} + +/** + * The collection of versions of the ADOT Lambda Layer for JavaScript SDK + */ +export class AdotLambdaLayerJavaScriptSdkVersion extends AdotLambdaLayerVersion { + /** + * The latest layer version available in this CDK version. New versions could + * introduce incompatible changes. Make sure to test them before deploying to production. + */ + public static readonly LATEST = new AdotLambdaLayerJavaScriptSdkVersion('1.7.0'); + + /** + * Version 1.7.0 + */ + public static readonly V1_7_0 = new AdotLambdaLayerJavaScriptSdkVersion('1.7.0'); + + private constructor(protected readonly layerVersion: string) { + super(AdotLambdaLayerType.JAVASCRIPT_SDK, layerVersion); + } +} + +/** + * The collection of versions of the ADOT Lambda Layer for generic purpose + */ +export class AdotLambdaLayerGenericVersion extends AdotLambdaLayerVersion { + /** + * The latest layer version available in this CDK version. New versions could + * introduce incompatible changes. Make sure to test them before deploying to production. + */ + public static readonly LATEST = new AdotLambdaLayerGenericVersion('0.62.1'); + + /** + * Version 0.62.1 + */ + public static readonly V0_62_1 = new AdotLambdaLayerGenericVersion('0.62.1'); + + private constructor(protected readonly layerVersion: string) { + super(AdotLambdaLayerType.GENERIC, layerVersion); + } +} diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 0976b2962e7cf..a39a8fe7a9ea5 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -9,6 +9,7 @@ import * as sqs from '@aws-cdk/aws-sqs'; import { Annotations, ArnFormat, CfnResource, Duration, FeatureFlags, Fn, IAspect, Lazy, Names, Size, Stack, Token } from '@aws-cdk/core'; import { LAMBDA_RECOGNIZE_LAYER_VERSION } from '@aws-cdk/cx-api'; import { Construct, IConstruct } from 'constructs'; +import { AdotInstrumentationConfig } from './adot-layers'; import { AliasOptions, Alias } from './alias'; import { Architecture } from './architecture'; import { Code, CodeConfig } from './code'; @@ -250,6 +251,14 @@ export interface FunctionOptions extends EventInvokeConfigOptions { */ readonly insightsVersion?: LambdaInsightsVersion; + /** + * Specify the configuration of AWS Distro for OpenTelemetry (ADOT) instrumentation + * @see https://aws-otel.github.io/docs/getting-started/lambda + * + * @default - No ADOT instrumentation + */ + readonly adotInstrumentation?: AdotInstrumentationConfig; + /** * A list of layers to add to the function's execution environment. You can configure your Lambda function to pull in * additional code during initialization in the form of layers. Layers are packages of libraries or other dependencies @@ -794,7 +803,6 @@ export class Function extends FunctionBase { } : undefined, vpcConfig: this.configureVpc(props), deadLetterConfig: this.buildDeadLetterConfig(dlqTopicOrQueue), - tracingConfig: this.buildTracingConfig(props), reservedConcurrentExecutions: props.reservedConcurrentExecutions, imageConfig: undefinedIfNoKeys({ command: code.image?.cmd, @@ -807,6 +815,10 @@ export class Function extends FunctionBase { architectures: this._architecture ? [this._architecture.name] : undefined, }); + if ((props.tracing !== undefined) || (props.adotInstrumentation !== undefined)) { + resource.tracingConfig = this.buildTracingConfig(props.tracing ?? Tracing.ACTIVE); + } + resource.node.addDependency(this.role); this.functionName = this.getResourceNameAttribute(resource.ref); @@ -891,6 +903,8 @@ export class Function extends FunctionBase { // Configure Lambda insights this.configureLambdaInsights(props); + + this.configureAdotInstrumentation(props); } /** @@ -1079,6 +1093,31 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett this.role?.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy')); } + /** + * Add an AWS Distro for OpenTelemetry Lambda layer. + * + * @param props properties for the ADOT instrumentation + */ + private configureAdotInstrumentation(props: FunctionProps): void { + + if (props.adotInstrumentation === undefined) { + return; + } + + if (props.runtime === Runtime.FROM_IMAGE) { + throw new Error("ADOT Lambda layer can't be configured with container image package type"); + } + + // This is not the complete list of incompatible runtimes and layer types. We are only + // checking for common mistakes on a best-effort basis. + if (this.runtime === Runtime.GO_1_X) { + throw new Error('Runtime go1.x is not supported by the ADOT Lambda Go SDK'); + } + + this.addLayers(LayerVersion.fromLayerVersionArn(this, 'AdotLayer', props.adotInstrumentation.layerVersion._bind(this).arn)); + this.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', props.adotInstrumentation.execWrapper); + } + private renderLayers() { if (!this._layers || this._layers.length === 0) { return undefined; @@ -1228,8 +1267,8 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett } } - private buildTracingConfig(props: FunctionProps) { - if (props.tracing === undefined || props.tracing === Tracing.DISABLED) { + private buildTracingConfig(tracing: Tracing) { + if (tracing === undefined || tracing === Tracing.DISABLED) { return undefined; } @@ -1239,7 +1278,7 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett })); return { - mode: props.tracing, + mode: tracing, }; } diff --git a/packages/@aws-cdk/aws-lambda/lib/index.ts b/packages/@aws-cdk/aws-lambda/lib/index.ts index 104afa76627a0..e317a58bee4bf 100644 --- a/packages/@aws-cdk/aws-lambda/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/index.ts @@ -1,3 +1,4 @@ +export * from './adot-layers'; export * from './alias'; export * from './dlq'; export * from './function-base'; diff --git a/packages/@aws-cdk/aws-lambda/test/adot.test.ts b/packages/@aws-cdk/aws-lambda/test/adot.test.ts new file mode 100644 index 0000000000000..93ff30eb9cf49 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/adot.test.ts @@ -0,0 +1,89 @@ +import { Template } from '@aws-cdk/assertions'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as lambda from '../lib'; + +describe('ADOT Lambda Layer', () => { + + describe('when the stack region is specified and supported', () => { + + let fn: lambda.Function; + + beforeEach(() => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'stack', { env: { region: 'us-west-2' } }); + const bucket = new s3.Bucket(stack, 'CodeBucket'); + fn = new lambda.Function(stack, 'Function', { + code: lambda.Code.fromBucket(bucket, 'mock_key'), + handler: 'index.handler', + runtime: lambda.Runtime.JAVA_11, + }); + }); + + test('is added properly when the region information is available at synthesis time', () => { + const layerArn = lambda.AdotLambdaLayerJavaSdkVersion.V1_19_0.layerArn(fn.stack, fn.architecture); + + expect(layerArn).toEqual( + 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + ); + }); + + test('is added properly when using "LATEST" version', () => { + const layerArn = lambda.AdotLambdaLayerJavaSdkVersion.LATEST.layerArn(fn.stack, fn.architecture); + + expect(layerArn).toEqual( + 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + ); + }); + }); + + describe('when the stack region is not supported', () => { + test('throws error if the region is not supported', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'stack', { env: { region: 'neverland' } }); + const bucket = new s3.Bucket(stack, 'CodeBucket'); + const fn = new lambda.Function(stack, 'Function', { + code: lambda.Code.fromBucket(bucket, 'mock_key'), + handler: 'index.handler', + runtime: lambda.Runtime.JAVA_11, + }); + + expect(() => { + lambda.AdotLayerVersion.fromJavaSdkLayerVersion( + lambda.AdotLambdaLayerJavaSdkVersion.LATEST, + )._bind(fn).arn; + }).toThrow(/Could not find the ARN information for the ADOT Lambda Layer/); + }); + }); + + describe('when the stack is region agnostic', () => { + test('is added properly', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'region-agnostic-stack'); + const fn = new lambda.Function(stack, 'Function', { + code: new lambda.InlineCode('FooBar'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + architecture: lambda.Architecture.ARM_64, + }); + + const layerArn = lambda.AdotLambdaLayerJavaSdkVersion.LATEST.layerArn(stack, fn.architecture); + fn.stack.exportValue(layerArn, { + name: 'LayerArn', + }); + + // THEN + Template.fromStack(fn.stack).hasOutput('ExportLayerArn', { + Value: { + 'Fn::FindInMap': [ + 'AdotlambdalayerMap', + { + Ref: 'AWS::Region', + }, + 'JAVAxSDKx1x19x0xarm64', + ], + }, + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-lambda/test/function.test.ts b/packages/@aws-cdk/aws-lambda/test/function.test.ts index cd128a5050193..e16e17198bbf3 100644 --- a/packages/@aws-cdk/aws-lambda/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/function.test.ts @@ -17,6 +17,7 @@ import * as cxapi from '@aws-cdk/cx-api'; import * as constructs from 'constructs'; import * as _ from 'lodash'; import * as lambda from '../lib'; +import { AdotLambdaLayerJavaSdkVersion } from '../lib/adot-layers'; import { calculateFunctionHash } from '../lib/function-hash'; describe('function', () => { @@ -3070,6 +3071,55 @@ describe('function', () => { Runtime: 'nodejs14.x', }); }); + + test('adds ADOT instrumentation to a ZIP Lambda function', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Base', { + env: { account: '111111111111', region: 'us-west-2' }, + }); + + // WHEN + new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + adotInstrumentation: { + layerVersion: lambda.AdotLayerVersion.fromJavaSdkLayerVersion(AdotLambdaLayerJavaSdkVersion.V1_19_0), + execWrapper: lambda.AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Layers: ['arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1'], + Environment: { + Variables: { + AWS_LAMBDA_EXEC_WRAPPER: '/opt/otel-handler', + }, + }, + }); + }); + + test('adds ADOT instrumentation to a container image Lambda function', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Base', { + env: { account: '111111111111', region: 'us-west-2' }, + }); + + // WHEN + expect( + () => + new lambda.DockerImageFunction(stack, 'MyLambda', { + code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, 'docker-lambda-handler')), + adotInstrumentation: { + layerVersion: lambda.AdotLayerVersion.fromJavaSdkLayerVersion(AdotLambdaLayerJavaSdkVersion.V1_19_0), + execWrapper: lambda.AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }), + ).toThrow(/ADOT Lambda layer can't be configured with container image package type/); + }); }); test('throws if ephemeral storage size is out of bound', () => { diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json new file mode 100644 index 0000000000000..ab8ca0bd4a1f2 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "IntegTestDefaultTestDeployAssertE3E7D2A4.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-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.template.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.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-lambda/test/integ.lambda-adot.js.snapshot/Stack1.assets.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack1.assets.json new file mode 100644 index 0000000000000..a0e1449cea6ee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack1.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "47696196003068eea2528656bebb8f11e163f75e8635d774b801bbc06a0e57e2": { + "source": { + "path": "Stack1.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "47696196003068eea2528656bebb8f11e163f75e8635d774b801bbc06a0e57e2.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-lambda/test/integ.lambda-adot.js.snapshot/Stack1.template.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack1.template.json new file mode 100644 index 0000000000000..7c14bc7d09da1 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack1.template.json @@ -0,0 +1,575 @@ +{ + "Resources": { + "MyFunc1ServiceRoleF96C5B5C": { + "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" + ] + ] + } + ] + } + }, + "MyFunc1ServiceRoleDefaultPolicy3C5E9573": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "Roles": [ + { + "Ref": "MyFunc1ServiceRoleF96C5B5C" + } + ] + } + }, + "MyFunc11BE70A62": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc1ServiceRoleF96C5B5C", + "Arn" + ] + }, + "Architectures": [ + "arm64" + ], + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::FindInMap": [ + "AdotlambdalayerMap", + { + "Ref": "AWS::Region" + }, + "JAVASCRIPTxSDKx1x7x0xarm64" + ] + } + ], + "Runtime": "nodejs14.x", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "MyFunc1ServiceRoleF96C5B5C" + ] + }, + "MyFunc2ServiceRole68E50443": { + "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" + ] + ] + } + ] + } + }, + "MyFunc2ServiceRoleDefaultPolicyEF3319F6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "Roles": [ + { + "Ref": "MyFunc2ServiceRole68E50443" + } + ] + } + }, + "MyFunc242557A97": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc2ServiceRole68E50443", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "MyFunc2ServiceRole68E50443" + ] + }, + "MyFunc3ServiceRoleA69795ED": { + "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" + ] + ] + } + ] + } + }, + "MyFunc3ServiceRoleDefaultPolicy449C4CBA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "Roles": [ + { + "Ref": "MyFunc3ServiceRoleA69795ED" + } + ] + } + }, + "MyFunc3666B7A2F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc3ServiceRoleA69795ED", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "MyFunc3ServiceRoleA69795ED" + ] + }, + "MyFunc4ServiceRole93C4DEFF": { + "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" + ] + ] + } + ] + } + }, + "MyFunc4ServiceRoleDefaultPolicy68C57CB2": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "Roles": [ + { + "Ref": "MyFunc4ServiceRole93C4DEFF" + } + ] + } + }, + "MyFunc4B88F85C6": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc4ServiceRole93C4DEFF", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "MyFunc4ServiceRole93C4DEFF" + ] + }, + "MyFunc5ServiceRoleFE4CE92B": { + "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" + ] + ] + } + ] + } + }, + "MyFunc5ServiceRoleDefaultPolicy96ABEA66": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "Roles": [ + { + "Ref": "MyFunc5ServiceRoleFE4CE92B" + } + ] + } + }, + "MyFunc586573B53": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc5ServiceRoleFE4CE92B", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "MyFunc5ServiceRoleFE4CE92B" + ] + } + }, + "Mappings": { + "AdotlambdalayerMap": { + "ap-northeast-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "ap-northeast-2": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "ap-south-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "ap-southeast-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "ap-southeast-2": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "ca-central-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "eu-central-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "eu-north-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "eu-west-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "eu-west-2": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "eu-west-3": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "sa-east-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "us-east-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "us-east-2": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + }, + "us-west-1": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1" + }, + "us-west-2": { + "JAVASCRIPTxSDKx1x7x0xarm64": "arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2" + } + } + }, + "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-lambda/test/integ.lambda-adot.js.snapshot/Stack2.assets.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack2.assets.json new file mode 100644 index 0000000000000..48c0af9610b9d --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "a4926065bd63dad984b7b214cd689e14b56eeec5afba89f078cd5134f8304bd8": { + "source": { + "path": "Stack2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "a4926065bd63dad984b7b214cd689e14b56eeec5afba89f078cd5134f8304bd8.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-lambda/test/integ.lambda-adot.js.snapshot/Stack2.template.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack2.template.json new file mode 100644 index 0000000000000..d268d79b5f964 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/Stack2.template.json @@ -0,0 +1,526 @@ +{ + "Resources": { + "MyFunc1ServiceRoleF96C5B5C": { + "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" + ] + ] + } + ] + } + }, + "MyFunc1ServiceRoleDefaultPolicy3C5E9573": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "Roles": [ + { + "Ref": "MyFunc1ServiceRoleF96C5B5C" + } + ] + } + }, + "MyFunc11BE70A62": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc1ServiceRoleF96C5B5C", + "Arn" + ] + }, + "Architectures": [ + "x86_64" + ], + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2" + ] + ] + } + ], + "Runtime": "nodejs14.x", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "MyFunc1ServiceRoleF96C5B5C" + ] + }, + "MyFunc2ServiceRole68E50443": { + "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" + ] + ] + } + ] + } + }, + "MyFunc2ServiceRoleDefaultPolicyEF3319F6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "Roles": [ + { + "Ref": "MyFunc2ServiceRole68E50443" + } + ] + } + }, + "MyFunc242557A97": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc2ServiceRole68E50443", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "MyFunc2ServiceRole68E50443" + ] + }, + "MyFunc3ServiceRoleA69795ED": { + "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" + ] + ] + } + ] + } + }, + "MyFunc3ServiceRoleDefaultPolicy449C4CBA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "Roles": [ + { + "Ref": "MyFunc3ServiceRoleA69795ED" + } + ] + } + }, + "MyFunc3666B7A2F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc3ServiceRoleA69795ED", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "MyFunc3ServiceRoleA69795ED" + ] + }, + "MyFunc4ServiceRole93C4DEFF": { + "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" + ] + ] + } + ] + } + }, + "MyFunc4ServiceRoleDefaultPolicy68C57CB2": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "Roles": [ + { + "Ref": "MyFunc4ServiceRole93C4DEFF" + } + ] + } + }, + "MyFunc4B88F85C6": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc4ServiceRole93C4DEFF", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "MyFunc4ServiceRole93C4DEFF" + ] + }, + "MyFunc5ServiceRoleFE4CE92B": { + "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" + ] + ] + } + ] + } + }, + "MyFunc5ServiceRoleDefaultPolicy96ABEA66": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "Roles": [ + { + "Ref": "MyFunc5ServiceRoleFE4CE92B" + } + ] + } + }, + "MyFunc586573B53": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): pass" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc5ServiceRoleFE4CE92B", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1" + ] + ] + } + ], + "Runtime": "python3.9", + "TracingConfig": { + "Mode": "Active" + } + }, + "DependsOn": [ + "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "MyFunc5ServiceRoleFE4CE92B" + ] + } + }, + "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-lambda/test/integ.lambda-adot.js.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/cdk.out new file mode 100644 index 0000000000000..145739f539580 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/integ.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/integ.json new file mode 100644 index 0000000000000..48b2c710d1101 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "22.0.0", + "testCases": { + "IntegTest/DefaultTest": { + "stacks": [ + "Stack1", + "Stack2" + ], + "assertionStack": "IntegTest/DefaultTest/DeployAssert", + "assertionStackName": "IntegTestDefaultTestDeployAssertE3E7D2A4" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/manifest.json new file mode 100644 index 0000000000000..0c1767cb8ed9c --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/manifest.json @@ -0,0 +1,338 @@ +{ + "version": "22.0.0", + "artifacts": { + "Stack1.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "Stack1.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "Stack1": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "Stack1.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}/47696196003068eea2528656bebb8f11e163f75e8635d774b801bbc06a0e57e2.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "Stack1.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": [ + "Stack1.assets" + ], + "metadata": { + "/Stack1/MyFunc1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc1ServiceRoleF96C5B5C" + } + ], + "/Stack1/MyFunc1/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc1ServiceRoleDefaultPolicy3C5E9573" + } + ], + "/Stack1/MyFunc1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc11BE70A62" + } + ], + "/Stack1/Adot-lambda-layerMap": [ + { + "type": "aws:cdk:logicalId", + "data": "AdotlambdalayerMap" + } + ], + "/Stack1/MyFunc2/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc2ServiceRole68E50443" + } + ], + "/Stack1/MyFunc2/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc2ServiceRoleDefaultPolicyEF3319F6" + } + ], + "/Stack1/MyFunc2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc242557A97" + } + ], + "/Stack1/MyFunc3/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3ServiceRoleA69795ED" + } + ], + "/Stack1/MyFunc3/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3ServiceRoleDefaultPolicy449C4CBA" + } + ], + "/Stack1/MyFunc3/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3666B7A2F" + } + ], + "/Stack1/MyFunc4/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4ServiceRole93C4DEFF" + } + ], + "/Stack1/MyFunc4/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4ServiceRoleDefaultPolicy68C57CB2" + } + ], + "/Stack1/MyFunc4/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4B88F85C6" + } + ], + "/Stack1/MyFunc5/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc5ServiceRoleFE4CE92B" + } + ], + "/Stack1/MyFunc5/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc5ServiceRoleDefaultPolicy96ABEA66" + } + ], + "/Stack1/MyFunc5/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc586573B53" + } + ], + "/Stack1/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/Stack1/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "Stack1" + }, + "Stack2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "Stack2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "Stack2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "Stack2.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}/a4926065bd63dad984b7b214cd689e14b56eeec5afba89f078cd5134f8304bd8.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "Stack2.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": [ + "Stack2.assets" + ], + "metadata": { + "/Stack2/MyFunc1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc1ServiceRoleF96C5B5C" + } + ], + "/Stack2/MyFunc1/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc1ServiceRoleDefaultPolicy3C5E9573" + } + ], + "/Stack2/MyFunc1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc11BE70A62" + } + ], + "/Stack2/MyFunc2/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc2ServiceRole68E50443" + } + ], + "/Stack2/MyFunc2/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc2ServiceRoleDefaultPolicyEF3319F6" + } + ], + "/Stack2/MyFunc2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc242557A97" + } + ], + "/Stack2/MyFunc3/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3ServiceRoleA69795ED" + } + ], + "/Stack2/MyFunc3/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3ServiceRoleDefaultPolicy449C4CBA" + } + ], + "/Stack2/MyFunc3/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc3666B7A2F" + } + ], + "/Stack2/MyFunc4/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4ServiceRole93C4DEFF" + } + ], + "/Stack2/MyFunc4/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4ServiceRoleDefaultPolicy68C57CB2" + } + ], + "/Stack2/MyFunc4/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc4B88F85C6" + } + ], + "/Stack2/MyFunc5/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc5ServiceRoleFE4CE92B" + } + ], + "/Stack2/MyFunc5/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc5ServiceRoleDefaultPolicy96ABEA66" + } + ], + "/Stack2/MyFunc5/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunc586573B53" + } + ], + "/Stack2/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/Stack2/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "Stack2" + }, + "IntegTestDefaultTestDeployAssertE3E7D2A4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "IntegTestDefaultTestDeployAssertE3E7D2A4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "IntegTestDefaultTestDeployAssertE3E7D2A4.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": [ + "IntegTestDefaultTestDeployAssertE3E7D2A4.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": [ + "IntegTestDefaultTestDeployAssertE3E7D2A4.assets" + ], + "metadata": { + "/IntegTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/IntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "IntegTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/tree.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/tree.json new file mode 100644 index 0000000000000..9f2eb419a99ba --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.js.snapshot/tree.json @@ -0,0 +1,1768 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Stack1": { + "id": "Stack1", + "path": "Stack1", + "children": { + "MyFunc1": { + "id": "MyFunc1", + "path": "Stack1/MyFunc1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack1/MyFunc1/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack1/MyFunc1/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc1/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": "Stack1/MyFunc1/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc1/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "roles": [ + { + "Ref": "MyFunc1ServiceRoleF96C5B5C" + } + ] + } + }, + "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": "Stack1/MyFunc1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc1ServiceRoleF96C5B5C", + "Arn" + ] + }, + "architectures": [ + "arm64" + ], + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::FindInMap": [ + "AdotlambdalayerMap", + { + "Ref": "AWS::Region" + }, + "JAVASCRIPTxSDKx1x7x0xarm64" + ] + } + ], + "runtime": "nodejs14.x", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "Adot-lambda-layerMap": { + "id": "Adot-lambda-layerMap", + "path": "Stack1/Adot-lambda-layerMap", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnMapping", + "version": "0.0.0" + } + }, + "AdotLayer1": { + "id": "AdotLayer1", + "path": "Stack1/AdotLayer1", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc2": { + "id": "MyFunc2", + "path": "Stack1/MyFunc2", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack1/MyFunc2/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack1/MyFunc2/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc2/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": "Stack1/MyFunc2/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc2/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "roles": [ + { + "Ref": "MyFunc2ServiceRole68E50443" + } + ] + } + }, + "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": "Stack1/MyFunc2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc2ServiceRole68E50443", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer2": { + "id": "AdotLayer2", + "path": "Stack1/AdotLayer2", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc3": { + "id": "MyFunc3", + "path": "Stack1/MyFunc3", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack1/MyFunc3/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack1/MyFunc3/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc3/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": "Stack1/MyFunc3/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc3/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "roles": [ + { + "Ref": "MyFunc3ServiceRoleA69795ED" + } + ] + } + }, + "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": "Stack1/MyFunc3/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc3ServiceRoleA69795ED", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer3": { + "id": "AdotLayer3", + "path": "Stack1/AdotLayer3", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc4": { + "id": "MyFunc4", + "path": "Stack1/MyFunc4", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack1/MyFunc4/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack1/MyFunc4/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc4/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": "Stack1/MyFunc4/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc4/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "roles": [ + { + "Ref": "MyFunc4ServiceRole93C4DEFF" + } + ] + } + }, + "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": "Stack1/MyFunc4/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc4ServiceRole93C4DEFF", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer4": { + "id": "AdotLayer4", + "path": "Stack1/AdotLayer4", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc5": { + "id": "MyFunc5", + "path": "Stack1/MyFunc5", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack1/MyFunc5/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack1/MyFunc5/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc5/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": "Stack1/MyFunc5/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack1/MyFunc5/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "roles": [ + { + "Ref": "MyFunc5ServiceRoleFE4CE92B" + } + ] + } + }, + "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": "Stack1/MyFunc5/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc5ServiceRoleFE4CE92B", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer5": { + "id": "AdotLayer5", + "path": "Stack1/AdotLayer5", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "Stack1/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "Stack1/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Stack2": { + "id": "Stack2", + "path": "Stack2", + "children": { + "MyFunc1": { + "id": "MyFunc1", + "path": "Stack2/MyFunc1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack2/MyFunc1/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack2/MyFunc1/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc1/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": "Stack2/MyFunc1/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc1/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc1ServiceRoleDefaultPolicy3C5E9573", + "roles": [ + { + "Ref": "MyFunc1ServiceRoleF96C5B5C" + } + ] + } + }, + "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": "Stack2/MyFunc1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc1ServiceRoleF96C5B5C", + "Arn" + ] + }, + "architectures": [ + "x86_64" + ], + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2" + ] + ] + } + ], + "runtime": "nodejs14.x", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer1": { + "id": "AdotLayer1", + "path": "Stack2/AdotLayer1", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc2": { + "id": "MyFunc2", + "path": "Stack2/MyFunc2", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack2/MyFunc2/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack2/MyFunc2/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc2/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": "Stack2/MyFunc2/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc2/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc2ServiceRoleDefaultPolicyEF3319F6", + "roles": [ + { + "Ref": "MyFunc2ServiceRole68E50443" + } + ] + } + }, + "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": "Stack2/MyFunc2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc2ServiceRole68E50443", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer2": { + "id": "AdotLayer2", + "path": "Stack2/AdotLayer2", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc3": { + "id": "MyFunc3", + "path": "Stack2/MyFunc3", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack2/MyFunc3/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack2/MyFunc3/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc3/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": "Stack2/MyFunc3/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc3/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc3ServiceRoleDefaultPolicy449C4CBA", + "roles": [ + { + "Ref": "MyFunc3ServiceRoleA69795ED" + } + ] + } + }, + "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": "Stack2/MyFunc3/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc3ServiceRoleA69795ED", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer3": { + "id": "AdotLayer3", + "path": "Stack2/AdotLayer3", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc4": { + "id": "MyFunc4", + "path": "Stack2/MyFunc4", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack2/MyFunc4/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack2/MyFunc4/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc4/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": "Stack2/MyFunc4/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc4/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc4ServiceRoleDefaultPolicy68C57CB2", + "roles": [ + { + "Ref": "MyFunc4ServiceRole93C4DEFF" + } + ] + } + }, + "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": "Stack2/MyFunc4/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc4ServiceRole93C4DEFF", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer4": { + "id": "AdotLayer4", + "path": "Stack2/AdotLayer4", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "MyFunc5": { + "id": "MyFunc5", + "path": "Stack2/MyFunc5", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "Stack2/MyFunc5/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "Stack2/MyFunc5/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc5/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": "Stack2/MyFunc5/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack2/MyFunc5/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyFunc5ServiceRoleDefaultPolicy96ABEA66", + "roles": [ + { + "Ref": "MyFunc5ServiceRoleFE4CE92B" + } + ] + } + }, + "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": "Stack2/MyFunc5/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "def handler(event, context): pass" + }, + "role": { + "Fn::GetAtt": [ + "MyFunc5ServiceRoleFE4CE92B", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_LAMBDA_EXEC_WRAPPER": "/opt/otel-handler" + } + }, + "handler": "index.handler", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1" + ] + ] + } + ], + "runtime": "python3.9", + "tracingConfig": { + "mode": "Active" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "AdotLayer5": { + "id": "AdotLayer5", + "path": "Stack2/AdotLayer5", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "Stack2/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "Stack2/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "IntegTest": { + "id": "IntegTest", + "path": "IntegTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "IntegTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "IntegTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.168" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "IntegTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "IntegTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "IntegTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "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" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.168" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.ts b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.ts new file mode 100644 index 0000000000000..0dad219ddf1d5 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-adot.ts @@ -0,0 +1,97 @@ +import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import { Construct } from 'constructs'; +import { StackProps, Stack } from '../../core/lib/stack'; +import { + AdotLambdaLayerPythonSdkVersion, + AdotLambdaLayerJavaSdkVersion, + AdotLambdaExecWrapper, + AdotLambdaLayerJavaScriptSdkVersion, + AdotLambdaLayerJavaAutoInstrumentationVersion, + AdotLambdaLayerGenericVersion, + Code, + Architecture, + Function, + Runtime, + AdotLayerVersion, +} from '../lib'; + +const app = new cdk.App(); + +interface StackUnderTestProps extends StackProps { + architecture?: Architecture; +} + +class StackUnderTest extends Stack { + constructor(scope: Construct, id: string, props: StackUnderTestProps) { + super(scope, id, props); + + new Function(this, 'MyFunc1', { + runtime: Runtime.NODEJS_14_X, + handler: 'index.handler', + code: Code.fromInline(`exports.handler = ${handler.toString()}`), + architecture: props.architecture, + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromJavaScriptSdkLayerVersion(AdotLambdaLayerJavaScriptSdkVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + + new Function(this, 'MyFunc2', { + runtime: Runtime.PYTHON_3_9, + handler: 'index.handler', + code: Code.fromInline('def handler(event, context): pass'), + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromPythonSdkLayerVersion(AdotLambdaLayerPythonSdkVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + + new Function(this, 'MyFunc3', { + runtime: Runtime.PYTHON_3_9, + handler: 'index.handler', + code: Code.fromInline('def handler(event, context): pass'), + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromJavaSdkLayerVersion(AdotLambdaLayerJavaSdkVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + + new Function(this, 'MyFunc4', { + runtime: Runtime.PYTHON_3_9, + handler: 'index.handler', + code: Code.fromInline('def handler(event, context): pass'), + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromJavaAutoInstrumentationLayerVersion(AdotLambdaLayerJavaAutoInstrumentationVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + + new Function(this, 'MyFunc5', { + runtime: Runtime.PYTHON_3_9, + handler: 'index.handler', + code: Code.fromInline('def handler(event, context): pass'), + adotInstrumentation: { + layerVersion: AdotLayerVersion.fromGenericLayerVersion(AdotLambdaLayerGenericVersion.LATEST), + execWrapper: AdotLambdaExecWrapper.REGULAR_HANDLER, + }, + }); + } +} + +/* eslint-disable no-console */ +function handler(event: any, _context: any, callback: any) { + console.log(JSON.stringify(event, undefined, 2)); + return callback(); +} + +new IntegTest(app, 'IntegTest', { + testCases: [ + new StackUnderTest(app, 'Stack1', { + architecture: Architecture.ARM_64, + }), + new StackUnderTest(app, 'Stack2', { + architecture: Architecture.X86_64, + }), + ], +}); diff --git a/packages/@aws-cdk/aws-logs/lib/log-retention.ts b/packages/@aws-cdk/aws-logs/lib/log-retention.ts index 0f1c8ebcd8902..7350d089488c3 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-retention.ts @@ -186,10 +186,10 @@ class LogRetentionFunction extends Construct implements cdk.ITaggable { // Function dependencies role.node.children.forEach((child) => { if (cdk.CfnResource.isCfnResource(child)) { - resource.addDependsOn(child); + resource.addDependency(child); } if (Construct.isConstruct(child) && child.node.defaultChild && cdk.CfnResource.isCfnResource(child.node.defaultChild)) { - resource.addDependsOn(child.node.defaultChild); + resource.addDependency(child.node.defaultChild); } }); } diff --git a/packages/@aws-cdk/aws-route53/README.md b/packages/@aws-cdk/aws-route53/README.md index 44099031c986c..a98bf93f65495 100644 --- a/packages/@aws-cdk/aws-route53/README.md +++ b/packages/@aws-cdk/aws-route53/README.md @@ -152,16 +152,23 @@ new route53.ARecord(this, 'ARecord', { ### Cross Account Zone Delegation -To add a NS record to a HostedZone in different account you can do the following: +If you want to have your root domain hosted zone in one account and your subdomain hosted +zone in a diferent one, you can use `CrossAccountZoneDelegationRecord` to set up delegation +between them. In the account containing the parent hosted zone: ```ts const parentZone = new route53.PublicHostedZone(this, 'HostedZone', { zoneName: 'someexample.com', - crossAccountZoneDelegationPrincipal: new iam.AccountPrincipal('12345678901'), - crossAccountZoneDelegationRoleName: 'MyDelegationRole', }); +const crossAccountRole = new iam.Role(this, 'CrossAccountRole', { + // The role name must be predictable + roleName: 'MyDelegationRole', + // The other account + assumedBy: new iam.AccountPrincipal('12345678901'), +}); +parentZone.grantDelegation(crossAccountRole); ``` In the account containing the child zone to be delegated: diff --git a/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts b/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts index fc04c3f91077f..c3238dd7e3172 100644 --- a/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts +++ b/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts @@ -213,6 +213,7 @@ export interface PublicHostedZoneProps extends CommonHostedZoneProps { * with appropriate permissions for every opt-in region instead. * * @default - No delegation configuration + * @deprecated Create the Role yourself and call `hostedZone.grantDelegation()`. */ readonly crossAccountZoneDelegationPrincipal?: iam.IPrincipal; @@ -220,6 +221,7 @@ export interface PublicHostedZoneProps extends CommonHostedZoneProps { * The name of the role created for cross account delegation * * @default - A role name is generated automatically + * @deprecated Create the Role yourself and call `hostedZone.grantDelegation()`. */ readonly crossAccountZoneDelegationRoleName?: string; } @@ -342,6 +344,30 @@ export class PublicHostedZone extends HostedZone implements IPublicHostedZone { ttl: opts.ttl, }); } + + /** + * Grant permissions to add delegation records to this zone + */ + public grantDelegation(grantee: iam.IGrantable) { + const g1 = iam.Grant.addToPrincipal({ + grantee, + actions: ['route53:ChangeResourceRecordSets'], + resourceArns: [this.hostedZoneArn], + conditions: { + 'ForAllValues:StringEquals': { + 'route53:ChangeResourceRecordSetsRecordTypes': ['NS'], + 'route53:ChangeResourceRecordSetsActions': ['UPSERT', 'DELETE'], + }, + }, + }); + const g2 = iam.Grant.addToPrincipal({ + grantee, + actions: ['route53:ListHostedZonesByName'], + resourceArns: ['*'], + }); + + return g1.combine(g2); + } } /** diff --git a/packages/@aws-cdk/aws-route53/test/hosted-zone.test.ts b/packages/@aws-cdk/aws-route53/test/hosted-zone.test.ts index 94dddf9b0568a..8cd31471bad05 100644 --- a/packages/@aws-cdk/aws-route53/test/hosted-zone.test.ts +++ b/packages/@aws-cdk/aws-route53/test/hosted-zone.test.ts @@ -1,6 +1,7 @@ import { Match, Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; +import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import * as cdk from '@aws-cdk/core'; import { HostedZone, PrivateHostedZone, PublicHostedZone } from '../lib'; @@ -59,7 +60,7 @@ describe('hosted zone', () => { }); }); - test('with crossAccountZoneDelegationPrincipal', () => { + testDeprecated('with crossAccountZoneDelegationPrincipal', () => { // GIVEN const stack = new cdk.Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-east-1' }, @@ -154,7 +155,7 @@ describe('hosted zone', () => { }); }); - test('with crossAccountZoneDelegationPrincipal, throws if name provided without principal', () => { + testDeprecated('with crossAccountZoneDelegationPrincipal, throws if name provided without principal', () => { // GIVEN const stack = new cdk.Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-east-1' }, @@ -229,3 +230,60 @@ describe('Vpc', () => { }); }); }); + +test('grantDelegation', () => { + // GIVEN + const stack = new cdk.Stack(undefined, 'TestStack', { + env: { account: '123456789012', region: 'us-east-1' }, + }); + + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.AccountPrincipal('22222222222222'), + }); + + const zone = new PublicHostedZone(stack, 'Zone', { + zoneName: 'banana.com', + }); + + // WHEN + zone.grantDelegation(role); + + // THEN + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'route53:ChangeResourceRecordSets', + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':route53:::hostedzone/', + { + Ref: 'ZoneA5DE4B68', + }, + ], + ], + }, + Condition: { + 'ForAllValues:StringEquals': { + 'route53:ChangeResourceRecordSetsRecordTypes': ['NS'], + 'route53:ChangeResourceRecordSetsActions': ['UPSERT', 'DELETE'], + }, + }, + }, + { + Action: 'route53:ListHostedZonesByName', + Effect: 'Allow', + Resource: '*', + }, + ], + }, + }); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-route53/test/record-set.test.ts b/packages/@aws-cdk/aws-route53/test/record-set.test.ts index c444cb3059e07..78c5f7884446e 100644 --- a/packages/@aws-cdk/aws-route53/test/record-set.test.ts +++ b/packages/@aws-cdk/aws-route53/test/record-set.test.ts @@ -1,5 +1,6 @@ import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; +import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import { Duration, RemovalPolicy, Stack } from '@aws-cdk/core'; import * as route53 from '../lib'; @@ -578,7 +579,7 @@ describe('record set', () => { }); }); - test('Cross account zone delegation record with parentHostedZoneId', () => { + testDeprecated('Cross account zone delegation record with parentHostedZoneId', () => { // GIVEN const stack = new Stack(); const parentZone = new route53.PublicHostedZone(stack, 'ParentHostedZone', { @@ -630,7 +631,7 @@ describe('record set', () => { }); }); - test('Cross account zone delegation record with parentHostedZoneName', () => { + testDeprecated('Cross account zone delegation record with parentHostedZoneName', () => { // GIVEN const stack = new Stack(); const parentZone = new route53.PublicHostedZone(stack, 'ParentHostedZone', { @@ -675,7 +676,7 @@ describe('record set', () => { }); }); - test('Cross account zone delegation record throws when parent id and name both/nither are supplied', () => { + testDeprecated('Cross account zone delegation record throws when parent id and name both/nither are supplied', () => { // GIVEN const stack = new Stack(); const parentZone = new route53.PublicHostedZone(stack, 'ParentHostedZone', { @@ -707,7 +708,7 @@ describe('record set', () => { }).toThrow(/Only one of parentHostedZoneName and parentHostedZoneId is supported/); }); - test('Multiple cross account zone delegation records', () => { + testDeprecated('Multiple cross account zone delegation records', () => { // GIVEN const stack = new Stack(); const parentZone = new route53.PublicHostedZone(stack, 'ParentHostedZone', { @@ -773,7 +774,7 @@ describe('record set', () => { } }); - test('Cross account zone delegation policies', () => { + testDeprecated('Cross account zone delegation policies', () => { // GIVEN const stack = new Stack(); const parentZone = new route53.PublicHostedZone(stack, 'ParentHostedZone', { @@ -845,7 +846,7 @@ describe('record set', () => { } }); - test('Cross account zone context flag', () => { + testDeprecated('Cross account zone context flag', () => { // GIVEN const stack = new Stack(); stack.node.setContext('@aws-cdk/aws-route53:useRegionalStsEndpoint', true); diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index c910d93eeff0a..0a7b7c029e63b 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -2044,6 +2044,17 @@ export class Bucket extends BucketBase { if (!props.serverAccessLogsBucket && !props.serverAccessLogsPrefix) { return undefined; } + if ( + // The current bucket is being used and is configured for default SSE-KMS + !props.serverAccessLogsBucket && ( + props.encryptionKey || + props.encryption === BucketEncryption.KMS || + props.encryption === BucketEncryption.KMS_MANAGED) || + // Another bucket is being used that is configured for default SSE-KMS + props.serverAccessLogsBucket?.encryptionKey + ) { + throw new Error('SSE-S3 is the only supported default bucket encryption for Server Access Logging target buckets'); + } return { destinationBucketName: props.serverAccessLogsBucket?.bucketName, diff --git a/packages/@aws-cdk/aws-s3/test/bucket.test.ts b/packages/@aws-cdk/aws-s3/test/bucket.test.ts index ed727d615578a..e412ceb2bc6ad 100644 --- a/packages/@aws-cdk/aws-s3/test/bucket.test.ts +++ b/packages/@aws-cdk/aws-s3/test/bucket.test.ts @@ -337,6 +337,28 @@ describe('bucket', () => { }); + test('throws error if using KMS-Managed key and server access logging to self', () => { + const stack = new cdk.Stack(); + expect(() => { + new s3.Bucket(stack, 'MyBucket', { encryption: s3.BucketEncryption.KMS_MANAGED, serverAccessLogsPrefix: 'test' }); + }).toThrow('SSE-S3 is the only supported default bucket encryption for Server Access Logging target buckets'); + }); + test('throws error if using KMS CMK and server access logging to self', () => { + const stack = new cdk.Stack(); + const key = new kms.Key(stack, 'TestKey'); + expect(() => { + new s3.Bucket(stack, 'MyBucket', { encryptionKey: key, serverAccessLogsPrefix: 'test' }); + }).toThrow('SSE-S3 is the only supported default bucket encryption for Server Access Logging target buckets'); + }); + test('throws error if enabling server access logging to bucket with SSE-KMS', () => { + const stack = new cdk.Stack(); + const key = new kms.Key(stack, 'TestKey'); + const targetBucket = new s3.Bucket(stack, 'TargetBucket', { encryptionKey: key } ); + expect(() => { + new s3.Bucket(stack, 'MyBucket', { serverAccessLogsBucket: targetBucket }); + }).toThrow('SSE-S3 is the only supported default bucket encryption for Server Access Logging target buckets'); + }); + test('bucket with versioning turned on', () => { const stack = new cdk.Stack(); new s3.Bucket(stack, 'MyBucket', { diff --git a/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts index 7136bd3d267a7..7d0804aa3367a 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts @@ -232,9 +232,9 @@ export class AccessPoint extends AccessPointBase { { actions: ['GetObject'], contentTransformation: { - awsLambda: { - functionArn: props.handler.functionArn, - functionPayload: props.payload ? JSON.stringify(props.payload) : undefined, + AwsLambda: { + FunctionArn: props.handler.functionArn, + FunctionPayload: props.payload ? JSON.stringify(props.payload) : undefined, }, }, }, diff --git a/packages/@aws-cdk/aws-servicecatalog/lib/private/association-manager.ts b/packages/@aws-cdk/aws-servicecatalog/lib/private/association-manager.ts index dd44ef0f022fc..d9bd1e68475d8 100644 --- a/packages/@aws-cdk/aws-servicecatalog/lib/private/association-manager.ts +++ b/packages/@aws-cdk/aws-servicecatalog/lib/private/association-manager.ts @@ -50,7 +50,7 @@ export class AssociationManager { }); // Add dependsOn to force proper order in deployment. - constraint.addDependsOn(association.cfnPortfolioProductAssociation); + constraint.addDependency(association.cfnPortfolioProductAssociation); } else { throw new Error(`Cannot have multiple tag update constraints for association ${this.prettyPrintAssociation(portfolio, product)}`); } @@ -70,7 +70,7 @@ export class AssociationManager { }); // Add dependsOn to force proper order in deployment. - constraint.addDependsOn(association.cfnPortfolioProductAssociation); + constraint.addDependency(association.cfnPortfolioProductAssociation); } else { throw new Error(`Topic ${topic.node.path} is already subscribed to association ${this.prettyPrintAssociation(portfolio, product)}`); } @@ -93,7 +93,7 @@ export class AssociationManager { }); // Add dependsOn to force proper order in deployment. - constraint.addDependsOn(association.cfnPortfolioProductAssociation); + constraint.addDependency(association.cfnPortfolioProductAssociation); } else { throw new Error(`Provisioning rule ${options.rule.ruleName} already configured on association ${this.prettyPrintAssociation(portfolio, product)}`); } @@ -133,7 +133,7 @@ export class AssociationManager { }); // Add dependsOn to force proper order in deployment. - constraint.addDependsOn(association.cfnPortfolioProductAssociation); + constraint.addDependency(association.cfnPortfolioProductAssociation); } else { throw new Error(`Cannot configure multiple StackSet deployment constraints for association ${this.prettyPrintAssociation(portfolio, product)}`); } @@ -173,7 +173,7 @@ export class AssociationManager { }); // Add dependsOn to force proper order in deployment. - constraint.addDependsOn(association.cfnPortfolioProductAssociation); + constraint.addDependency(association.cfnPortfolioProductAssociation); } else { throw new Error(`Cannot set multiple launch roles for association ${this.prettyPrintAssociation(portfolio, product)}`); } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/README.md b/packages/@aws-cdk/aws-servicecatalogappregistry/README.md index 10985d4839557..be09aef037fae 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/README.md +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/README.md @@ -84,6 +84,8 @@ const associatedApp = new appreg.ApplicationAssociator(app, 'AssociatedApplicati }); ``` +This will create an application `MyAssociatedApplication` with the `TagKey` as `managedBy` and `TagValue` as `CDK_Application_Associator`. + 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: diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts index 7694a519802b4..982085a6b9cf3 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/aspects/stack-associator.ts @@ -80,7 +80,7 @@ abstract class StackAssociatorBase implements IAspect { } if (node.region != this.application.env.region) { - this.error(node, 'AppRegistry does not support cross region associations. Application region ' + this.warning(node, 'AppRegistry does not support cross region associations, deployment might fail if there is cross region stacks in the app. Application region ' + this.application.env.region + ', stack region ' + node.region); } } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/target-application.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/target-application.ts index 7745c0d99a02c..0452ea6ac4095 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/lib/target-application.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/lib/target-application.ts @@ -100,6 +100,7 @@ class CreateTargetApplication extends TargetApplication { applicationName: this.applicationOptions.applicationName, description: this.applicationOptions.applicationDescription || 'Application containing stacks deployed via CDK.', }); + cdk.Tags.of(appRegApplication).add('managedBy', 'CDK_Application_Associator'); return { application: appRegApplication, @@ -123,4 +124,4 @@ class ExistingTargetApplication extends TargetApplication { application: appRegApplication, }; } -} \ 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 index 0d0cf74062e29..fe6bf236b28ae 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application-associator.test.ts @@ -15,13 +15,19 @@ describe('Scope based Associations with Application within Same Account', () => }); }); test('ApplicationAssociator will associate allStacks created inside cdkApp', () => { - new appreg.ApplicationAssociator(app, 'MyApplication', { + const appAssociator = new appreg.ApplicationAssociator(app, 'MyApplication', { applications: [appreg.TargetApplication.createApplicationStack({ applicationName: 'MyAssociatedApplication', stackName: 'MyAssociatedApplicationStack', })], }); + const anotherStack = new AppRegistrySampleStack(app, 'SampleStack'); + Template.fromStack(appAssociator.appRegistryApplication().stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::Application', 1); + Template.fromStack(appAssociator.appRegistryApplication().stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::Application', { + Name: 'MyAssociatedApplication', + Tags: { managedBy: 'CDK_Application_Associator' }, + }); Template.fromStack(anotherStack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); Template.fromStack(anotherStack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { Application: 'MyAssociatedApplication', @@ -103,7 +109,8 @@ describe('Scope based Associations with Application with Cross Region/Account', 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'); + Annotations.fromStack(crossRegionStack).hasWarning('*', 'AppRegistry does not support cross region associations, deployment might fail if there is cross region stacks in the app.' + + ' Application region region2, stack region region'); }); test('Environment Agnostic ApplicationAssociator with cross region stacks inside cdkApp gives warning', () => { diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts index 7a14cda920d28..04349d3d33bd5 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts @@ -443,8 +443,9 @@ describe('Scope based Associations with Application with Cross Region/Account', }); 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'); + Annotations.fromStack(stageStack).hasWarning('*', + 'AppRegistry does not support cross region associations, deployment might fail if there is cross region stacks in the app.' + + ' Application region region, stack region region1'); }); }); diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.assets.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.assets.json index 225ef80716295..0f728aa69a648 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.assets.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.assets.json @@ -1,7 +1,7 @@ { "version": "22.0.0", "files": { - "806ae543572346400832fe865c1bdfa243ef2c1f07c3ce10aa0bd27ed4613a42": { + "225f3d7f7d17bfb53aa17ae8a44119a756f2fc51682bfd5ee27b84ea25f994eb": { "source": { "path": "integ-servicecatalogappregistry-application.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "806ae543572346400832fe865c1bdfa243ef2c1f07c3ce10aa0bd27ed4613a42.json", + "objectKey": "225f3d7f7d17bfb53aa17ae8a44119a756f2fc51682bfd5ee27b84ea25f994eb.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-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.template.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.template.json index 33f4f2a1912fb..d569907291d49 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.template.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/integ-servicecatalogappregistry-application.template.json @@ -3,7 +3,7 @@ "TestApplication2FBC585F": { "Type": "AWS::ServiceCatalogAppRegistry::Application", "Properties": { - "Name": "myCdkApplication", + "Name": "myApplication", "Description": "my application description" } }, @@ -84,7 +84,7 @@ "release": "go time" } }, - "Name": "myCdkAttributeGroup", + "Name": "myAttributeGroup", "Description": "my attribute group description" } }, @@ -123,7 +123,7 @@ }, "Outputs": { "TestApplicationApplicationManagerUrlE1058321": { - "Description": "Application manager url for application myCdkApplication", + "Description": "Application manager url for application myApplication", "Value": { "Fn::Join": [ "", @@ -132,7 +132,7 @@ { "Ref": "AWS::Region" }, - ".console.aws.amazon.com/systems-manager/appmanager/application/AWS_AppRegistry_Application-myCdkApplication" + ".console.aws.amazon.com/systems-manager/appmanager/application/AWS_AppRegistry_Application-myApplication" ] ] } diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/manifest.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/manifest.json index a8cd9a83688d7..6a0143a97aaf2 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/manifest.json @@ -17,7 +17,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}/806ae543572346400832fe865c1bdfa243ef2c1f07c3ce10aa0bd27ed4613a42.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/225f3d7f7d17bfb53aa17ae8a44119a756f2fc51682bfd5ee27b84ea25f994eb.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/tree.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/tree.json index da9f344585ed2..5e4d14f15093e 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.js.snapshot/tree.json @@ -18,7 +18,7 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::ServiceCatalogAppRegistry::Application", "aws:cdk:cloudformation:props": { - "name": "myCdkApplication", + "name": "myApplication", "description": "my application description" } }, @@ -149,7 +149,7 @@ "release": "go time" } }, - "name": "myCdkAttributeGroup", + "name": "myAttributeGroup", "description": "my attribute group description" } }, @@ -249,7 +249,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.189" } } }, diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.ts index 30f5e2bb88829..06c0395e31bfa 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.application.ts @@ -6,12 +6,12 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'integ-servicecatalogappregistry-application'); const application = new appreg.Application(stack, 'TestApplication', { - applicationName: 'myCdkApplication', + applicationName: 'myApplication', description: 'my application description', }); const attributeGroup = new appreg.AttributeGroup(stack, 'TestAttributeGroup', { - attributeGroupName: 'myCdkAttributeGroup', + attributeGroupName: 'myAttributeGroup', description: 'my attribute group description', attributes: { stage: 'alpha', diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/cdk.out b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/cdk.out index 8ecc185e9dbee..145739f539580 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ-servicecatalogappregistry-attribute-group.assets.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ-servicecatalogappregistry-attribute-group.assets.json index f3f8d64d86ef0..1aebd71d38d63 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ-servicecatalogappregistry-attribute-group.assets.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ-servicecatalogappregistry-attribute-group.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "22.0.0", "files": { "3dece22dad73361a79cb380f2880362a20ffc5c0cc75ddc6707e26b5a88cf93f": { "source": { diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ.json index c0763c76bc8aa..a50a65615f05b 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "22.0.0", "testCases": { "integ.attribute-group": { "stacks": [ diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/manifest.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/manifest.json index 29a8ab0c7ec2a..edce9703115a8 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "integ-servicecatalogappregistry-attribute-group.assets": { "type": "cdk:asset-manifest", "properties": { @@ -77,6 +71,12 @@ ] }, "displayName": "integ-servicecatalogappregistry-attribute-group" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/tree.json b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/tree.json index 1bbf2fd35bb5a..83ac3d2034037 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/integ.attribute-group.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "integ-servicecatalogappregistry-attribute-group": { "id": "integ-servicecatalogappregistry-attribute-group", "path": "integ-servicecatalogappregistry-attribute-group", @@ -97,6 +89,14 @@ "id": "MyRole", "path": "integ-servicecatalogappregistry-attribute-group/MyRole", "children": { + "ImportMyRole": { + "id": "ImportMyRole", + "path": "integ-servicecatalogappregistry-attribute-group/MyRole/ImportMyRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "integ-servicecatalogappregistry-attribute-group/MyRole/Resource", @@ -147,6 +147,14 @@ "id": "MySecondRole", "path": "integ-servicecatalogappregistry-attribute-group/MySecondRole", "children": { + "ImportMySecondRole": { + "id": "ImportMySecondRole", + "path": "integ-servicecatalogappregistry-attribute-group/MySecondRole/ImportMySecondRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "integ-servicecatalogappregistry-attribute-group/MySecondRole/Resource", @@ -192,17 +200,41 @@ "fqn": "@aws-cdk/aws-iam.Role", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-servicecatalogappregistry-attribute-group/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-servicecatalogappregistry-attribute-group/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.189" } } }, "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-stepfunctions-tasks/test/databrew/integ.start-job-run.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts index 973f405880c2c..056d97535a81e 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts @@ -86,8 +86,8 @@ class GlueDataBrewJobStack extends cdk.Stack { datasetName: dataset.name, recipeName: recipe.name, }); - project.addDependsOn(dataset); - project.addDependsOn(recipe); + project.addDependency(dataset); + project.addDependency(recipe); const job = new databrew.CfnJob(this, 'DataBrew Job', { name: 'job-1', @@ -100,7 +100,7 @@ class GlueDataBrewJobStack extends cdk.Stack { }, }], }); - job.addDependsOn(project); + job.addDependency(project); const startGlueDataBrewJob = new GlueDataBrewStartJobRun(this, 'Start DataBrew Job run', { name: job.name, diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index ad827b101d380..428bf0d218060 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,136 @@ +# CloudFormation Resource Specification v103.0.0 + +## New Resource Types + + +## Attribute Changes + +* AWS::ApiGateway::RestApi RestApiId (__deleted__) +* AWS::DirectoryService::SimpleAD DirectoryId (__added__) +* AWS::EC2::Volume Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html +* AWS::EC2::Volume VolumeId (__added__) +* AWS::FSx::FileSystem ResourceARN (__added__) +* AWS::GameLift::Build BuildId (__added__) +* AWS::IoT::Thing Arn (__added__) +* AWS::IoT::Thing Id (__added__) +* AWS::Logs::SubscriptionFilter FilterName (__deleted__) +* AWS::RDS::DBInstance DBSystemId (__added__) +* AWS::RedshiftServerless::Namespace Namespace (__deleted__) +* AWS::RedshiftServerless::Workgroup Workgroup (__deleted__) +* AWS::RedshiftServerless::Workgroup Workgroup.ConfigParameters (__deleted__) +* AWS::RedshiftServerless::Workgroup Workgroup.Endpoint (__deleted__) +* AWS::RedshiftServerless::Workgroup Workgroup.Endpoint.VpcEndpoints (__deleted__) +* AWS::Route53RecoveryControl::Cluster ClusterEndpoints (__deleted__) + +## Property Changes + +* AWS::ApiGateway::RestApi Parameters.DuplicatesAllowed (__added__) +* AWS::CloudFront::Function FunctionCode.Required (__changed__) + * Old: false + * New: true +* AWS::CloudFront::Function FunctionConfig.Required (__changed__) + * Old: false + * New: true +* AWS::DataSync::LocationEFS EfsFilesystemArn.Required (__changed__) + * Old: true + * New: false +* AWS::DirectoryService::SimpleAD Password.Required (__changed__) + * Old: true + * New: false +* AWS::EC2::Volume AutoEnableIO.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-autoenableio + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-autoenableio +* AWS::EC2::Volume AvailabilityZone.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-availabilityzone + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-availabilityzone +* AWS::EC2::Volume Encrypted.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-encrypted + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-encrypted +* AWS::EC2::Volume Iops.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-iops + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-iops +* AWS::EC2::Volume KmsKeyId.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-kmskeyid + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-kmskeyid +* AWS::EC2::Volume MultiAttachEnabled.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-multiattachenabled + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-multiattachenabled +* AWS::EC2::Volume OutpostArn.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-outpostarn + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-outpostarn +* AWS::EC2::Volume Size.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-size + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-size +* AWS::EC2::Volume SnapshotId.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-snapshotid + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-snapshotid +* AWS::EC2::Volume Tags.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-tags + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-tags +* AWS::EC2::Volume Throughput.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-throughput + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-throughput +* AWS::EC2::Volume VolumeType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-volumetype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-volumetype +* AWS::EKS::Nodegroup Labels.PrimitiveType (__deleted__) +* AWS::EKS::Nodegroup Labels.PrimitiveItemType (__added__) +* AWS::EKS::Nodegroup Labels.Type (__added__) +* AWS::EKS::Nodegroup Tags.PrimitiveType (__deleted__) +* AWS::EKS::Nodegroup Tags.PrimitiveItemType (__added__) +* AWS::EKS::Nodegroup Tags.Type (__added__) +* AWS::GameLift::Build StorageLocation.Type (__changed__) + * Old: S3Location + * New: StorageLocation +* AWS::Grafana::Workspace VpcConfiguration (__added__) +* AWS::Logs::SubscriptionFilter Distribution (__added__) +* AWS::Logs::SubscriptionFilter FilterName (__added__) +* AWS::RedshiftServerless::Namespace Namespace (__added__) +* AWS::RedshiftServerless::Workgroup Workgroup (__added__) +* AWS::Route53RecoveryControl::Cluster ClusterEndpoints (__added__) + +## Property Type Changes + +* AWS::GameLift::Build.S3Location (__removed__) +* AWS::GameLift::Build.StorageLocation (__added__) +* AWS::Grafana::Workspace.VpcConfiguration (__added__) +* AWS::NetworkFirewall::RuleGroup.IPSetReference (__added__) +* AWS::NetworkFirewall::RuleGroup.ReferenceSets (__added__) +* AWS::QuickSight::DataSource.DatabricksParameters (__added__) +* AWS::DirectoryService::SimpleAD.VpcSettings SubnetIds.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::DirectoryService::SimpleAD.VpcSettings VpcId.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::Evidently::Experiment.MetricGoalObject EventPattern.Required (__changed__) + * Old: true + * New: false +* AWS::Evidently::Launch.MetricDefinitionObject EventPattern.Required (__changed__) + * Old: true + * New: false +* AWS::FSx::FileSystem.OntapConfiguration RouteTableIds.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::FSx::Volume.OntapConfiguration CopyTagsToBackups (__added__) +* AWS::FSx::Volume.OntapConfiguration OntapVolumeType (__added__) +* AWS::FSx::Volume.OntapConfiguration SnapshotPolicy (__added__) +* AWS::FSx::Volume.OntapConfiguration JunctionPath.Required (__changed__) + * Old: true + * New: false +* AWS::FSx::Volume.OntapConfiguration StorageEfficiencyEnabled.Required (__changed__) + * Old: true + * New: false +* AWS::IoT::Thing.AttributePayload Attributes.DuplicatesAllowed (__deleted__) +* AWS::NetworkFirewall::FirewallPolicy.StatefulEngineOptions StreamExceptionPolicy (__added__) +* AWS::NetworkFirewall::RuleGroup.RuleGroup ReferenceSets (__added__) +* AWS::NetworkManager::VpcAttachment.VpcOptions ApplianceModeSupport (__added__) +* AWS::QuickSight::DataSource.DataSourceParameters DatabricksParameters (__added__) +* AWS::RDS::DBProxy.AuthFormat ClientPasswordAuthType (__added__) + + # CloudFormation Resource Specification v102.0.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index d4641b132dc0a..9dd4f066910f1 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -102.0.0 +103.0.0 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 495198b81cce8..8aa43d81a67ea 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": "102.0.0", + "$version": "103.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 bd88dc39b958b..03a83ccffc2c1 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": "102.0.0", + "$version": "103.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 d6b46239f1555..a87eee0496f92 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": "102.0.0", + "$version": "103.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 cb11b3177ff69..28739d8ccbab6 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": "102.0.0", + "$version": "103.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 73625ed7e741c..2c29a2594777e 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": "102.0.0", + "$version": "103.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 d9696fe11b06e..8a6171ba631c6 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": "102.0.0", + "$version": "103.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 fa966ec28645c..adc6240388026 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ApiGateway::ApiKey.StageKey": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-apikey-stagekey.html", @@ -1329,9 +1329,6 @@ }, "AWS::ApiGateway::RestApi": { "Attributes": { - "RestApiId": { - "PrimitiveType": "String" - }, "RootResourceId": { "PrimitiveType": "String" } @@ -1414,6 +1411,7 @@ }, "Parameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-parameters", + "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Required": false, "Type": "Map", 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 e15eb6be06e30..12f43e0316869 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": "102.0.0", + "$version": "103.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 1eb502b7fd350..c94c58f59eed0 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": "102.0.0", + "$version": "103.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 a1a66463b2082..751681ead7b24 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::AppFlow::Connector.ConnectorProvisioningConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-connector-connectorprovisioningconfig.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 027ecd1b3c764..e53efeb941a2b 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": "102.0.0", + "$version": "103.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 059466450e6b9..b341dd3fbae7f 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": "102.0.0", + "$version": "103.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 cf506f6249348..99cc20143150b 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": "102.0.0", + "$version": "103.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 72d49f0f6da5c..6e0ed270155b6 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": "102.0.0", + "$version": "103.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 4a331128e1b17..3004adc67e7e3 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": "102.0.0", + "$version": "103.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 8af17fdf1fbbb..b7d7014945789 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": "102.0.0", + "$version": "103.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 c824ebe11f80d..be9a65e00b777 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": "102.0.0", + "$version": "103.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 8e2067e0d6b90..2aa1cdce455a8 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": "102.0.0", + "$version": "103.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 d7d52dff90a83..59beebcbcd166 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": "102.0.0", + "$version": "103.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 43abb93cb57bc..c2715e59a84f1 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": "102.0.0", + "$version": "103.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 c0f6190243428..fde218a526415 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": "102.0.0", + "$version": "103.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 f06b394389473..8b394406e8abe 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": "102.0.0", + "$version": "103.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 89a5527fa1bf6..bb97eb6806daa 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": "102.0.0", + "$version": "103.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 d394247ae25cd..0bb1ab2c53791 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": "102.0.0", + "$version": "103.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 1ddc94074be12..2eb5108f5f1c7 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Budgets::Budget.AutoAdjustData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-budgets-budget-autoadjustdata.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 cd2d07433642c..d888a8ed0b9e4 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": "102.0.0", + "$version": "103.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 c120e6687e736..6b16b71246739 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": "102.0.0", + "$version": "103.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 760e154313376..9e8dda6f4f67d 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": "102.0.0", + "$version": "103.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 ea86972f64310..79054d722f8be 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": "102.0.0", + "$version": "103.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 3a2e09d0c4d24..b2595215db678 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": "102.0.0", + "$version": "103.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 2fc526c95d4bc..d078e60612ca5 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": "102.0.0", + "$version": "103.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 ed6f5c6e655e9..f4c4adc7c9940 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": "102.0.0", + "$version": "103.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 d168bf50c81ee..7c765f014eeda 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-cachepolicy-cachepolicyconfig.html", @@ -2007,12 +2007,12 @@ "FunctionCode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-function.html#cfn-cloudfront-function-functioncode", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "FunctionConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-function.html#cfn-cloudfront-function-functionconfig", - "Required": false, + "Required": true, "Type": "FunctionConfig", "UpdateType": "Mutable" }, 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 1d20fb37a7594..d90847e11590b 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": "102.0.0", + "$version": "103.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 7b2a32dc35436..d70d364a42352 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::CloudWatch::Alarm.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html", 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 ce029a74c3e6f..1e1bd521878e4 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": "102.0.0", + "$version": "103.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 a03c4bfeab626..1fa1c4dc98ac9 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": "102.0.0", + "$version": "103.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 87a55fdc019f8..6d47212d5c487 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": "102.0.0", + "$version": "103.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 bc7a4e35262b0..0d9623784b5ef 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html", 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 a3e3da3382ae2..ff3c0ee93927e 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::CodeGuruProfiler::ProfilingGroup.AgentPermissions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codeguruprofiler-profilinggroup-agentpermissions.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 122a16b4d5acd..89520e2134c53 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": "102.0.0", + "$version": "103.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 488bcb0ce11df..85ac6cfc40e09 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": "102.0.0", + "$version": "103.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 37727ec635096..777435b7d6f62 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": "102.0.0", + "$version": "103.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 b1904e5e37e86..9ad68b9965457 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": "102.0.0", + "$version": "103.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 e36c0219ef4be..e173e62cbe844 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": "102.0.0", + "$version": "103.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 c3cb24ccb6551..429b1a76a7d1b 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": "102.0.0", + "$version": "103.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 304082e86e56e..aaa204c502748 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": "102.0.0", + "$version": "103.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 cd6c40693b212..f5c5eec94e9a4 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": "102.0.0", + "$version": "103.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 7e6edd775683d..835f3f41542fe 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,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ConnectCampaigns::Campaign.DialerConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connectcampaigns-campaign-dialerconfig.html", 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 793aaa010a562..e4cca6809effa 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": "102.0.0", + "$version": "103.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 9d6570fbdf433..081ee9446bba1 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": "102.0.0", + "$version": "103.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 206c1f5cfbd01..74da6498e2f30 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": "102.0.0", + "$version": "103.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 4f759606d7022..5c48070d4ce33 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::DLM::LifecyclePolicy.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-action.html", 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 ceab8acf0d34e..6878b4b6d8b38 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": "102.0.0", + "$version": "103.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 26561725875fe..70df3dd9f0bff 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": "102.0.0", + "$version": "103.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 85d8baf104b05..2692fbc2b59c9 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::DataPipeline::Pipeline.Field": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datapipeline-pipeline-field.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 b82d37cd21920..ce74baaf863c9 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::DataSync::LocationEFS.Ec2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationefs-ec2config.html", @@ -418,7 +418,7 @@ "EfsFilesystemArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationefs.html#cfn-datasync-locationefs-efsfilesystemarn", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Immutable" }, "FileSystemAccessRoleArn": { 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 8838b4d066f5d..febfa9f77b824 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": "102.0.0", + "$version": "103.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 d2258eafed286..c5cb4ef15592f 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": "102.0.0", + "$version": "103.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 7bc0591d605ee..e39f6437074d8 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::DirectoryService::MicrosoftAD.VpcSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-microsoftad-vpcsettings.html", @@ -29,13 +29,13 @@ "PrimitiveItemType": "String", "Required": true, "Type": "List", - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "VpcId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-simplead-vpcsettings.html#cfn-directoryservice-simplead-vpcsettings-vpcid", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" } } } @@ -102,6 +102,9 @@ "Alias": { "PrimitiveType": "String" }, + "DirectoryId": { + "PrimitiveType": "String" + }, "DnsIpAddresses": { "PrimitiveItemType": "String", "Type": "List" @@ -136,7 +139,7 @@ "Password": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-directoryservice-simplead.html#cfn-directoryservice-simplead-password", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Immutable" }, "ShortName": { 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 7c885cab5f378..da464ae0ff981 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDB::DBCluster": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDBElastic.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDBElastic.json index 2258455b2d62a..f63a29a4f8770 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDBElastic.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDBElastic.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDBElastic::Cluster": { 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 3bef6cecb389b..a3ed76361ee71 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::DynamoDB::GlobalTable.AttributeDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-globaltable-attributedefinition.html", 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 65921cacd8f1d..f5cf9c63c2377 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::EC2::CapacityReservation.TagSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-capacityreservation-tagspecification.html", @@ -8567,64 +8567,69 @@ } }, "AWS::EC2::Volume": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html", + "Attributes": { + "VolumeId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html", "Properties": { "AutoEnableIO": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-autoenableio", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-autoenableio", "PrimitiveType": "Boolean", "Required": false, "UpdateType": "Mutable" }, "AvailabilityZone": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-availabilityzone", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-availabilityzone", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" }, "Encrypted": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-encrypted", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-encrypted", "PrimitiveType": "Boolean", "Required": false, "UpdateType": "Mutable" }, "Iops": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-iops", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-iops", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "KmsKeyId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-kmskeyid", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-kmskeyid", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "MultiAttachEnabled": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-multiattachenabled", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-multiattachenabled", "PrimitiveType": "Boolean", "Required": false, "UpdateType": "Mutable" }, "OutpostArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-outpostarn", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-outpostarn", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "Size": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-size", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-size", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "SnapshotId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-snapshotid", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-snapshotid", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" }, "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-tags", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-tags", "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, @@ -8632,13 +8637,13 @@ "UpdateType": "Mutable" }, "Throughput": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-throughput", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-throughput", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Mutable" }, "VolumeType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html#cfn-ec2-ebs-volume-volumetype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html#cfn-ec2-volume-volumetype", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" 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 65cc1f50de994..2b5df8a61f819 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ECR::PublicRepository.RepositoryCatalogData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecr-publicrepository-repositorycatalogdata.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 9cde5994e03cf..296b508c39256 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": "102.0.0", + "$version": "103.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 4a14e2b2116bc..5857388f4b0fb 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": "102.0.0", + "$version": "103.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 ea0c1c1cb1033..081eb611d2e3c 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::EKS::Cluster.ClusterLogging": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-clusterlogging.html", @@ -669,8 +669,9 @@ }, "Labels": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-labels", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Mutable" }, "LaunchTemplate": { @@ -719,8 +720,9 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Mutable" }, "Taints": { 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 a1ac97e1b2c6c..026524bc2c549 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": "102.0.0", + "$version": "103.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 5a8353d32ba38..15d1efcd5d695 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": "102.0.0", + "$version": "103.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 c299ec03fda96..1d9789fccb913 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": "102.0.0", + "$version": "103.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 2c67755069dd4..394632496ef61 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ElastiCache::CacheCluster.CloudWatchLogsDestinationDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cachecluster-cloudwatchlogsdestinationdetails.html", 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 33b5947060b51..5d34ac59be6c5 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ElasticBeanstalk::Application.ApplicationResourceLifecycleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-application-applicationresourcelifecycleconfig.html", 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 71f905d7184c5..8c8d08f06e875 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": "102.0.0", + "$version": "103.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 676fb68d33bce..ccba1f228d5d1 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": "102.0.0", + "$version": "103.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 f8fd092855a18..cef74af2e2418 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": "102.0.0", + "$version": "103.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 8a1c50962794a..2597ef7747758 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": "102.0.0", + "$version": "103.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 1f00c2794425c..7b3c7cb1da3e1 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": "102.0.0", + "$version": "103.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 125bbedf94ba9..5322e4cb1c972 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Evidently::Experiment.MetricGoalObject": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html", @@ -19,7 +19,7 @@ "EventPattern": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html#cfn-evidently-experiment-metricgoalobject-eventpattern", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "MetricName": { @@ -269,7 +269,7 @@ "EventPattern": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-launch-metricdefinitionobject.html#cfn-evidently-launch-metricdefinitionobject-eventpattern", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "MetricName": { 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 d9f8252c29650..be2fbc3888bb3 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::FIS::ExperimentTemplate.CloudWatchLogsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fis-experimenttemplate-cloudwatchlogsconfiguration.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 2016dde806ea3..b497d8c686d3f 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": "102.0.0", + "$version": "103.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 293ae8e34cbe1..dba25cfa81016 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::FSx::DataRepositoryAssociation.AutoExportPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-datarepositoryassociation-autoexportpolicy.html", @@ -241,7 +241,7 @@ "PrimitiveItemType": "String", "Required": false, "Type": "List", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ThroughputCapacity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-ontapconfiguration.html#cfn-fsx-filesystem-ontapconfiguration-throughputcapacity", @@ -595,12 +595,24 @@ "AWS::FSx::Volume.OntapConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html", "Properties": { + "CopyTagsToBackups": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-copytagstobackups", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "JunctionPath": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-junctionpath", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, + "OntapVolumeType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-ontapvolumetype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "SecurityStyle": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-securitystyle", "PrimitiveType": "String", @@ -613,10 +625,16 @@ "Required": true, "UpdateType": "Mutable" }, + "SnapshotPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-snapshotpolicy", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "StorageEfficiencyEnabled": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-volume-ontapconfiguration.html#cfn-fsx-volume-ontapconfiguration-storageefficiencyenabled", "PrimitiveType": "String", - "Required": true, + "Required": false, "UpdateType": "Mutable" }, "StorageVirtualMachineId": { @@ -831,6 +849,9 @@ "LustreMountName": { "PrimitiveType": "String" }, + "ResourceARN": { + "PrimitiveType": "String" + }, "RootVolumeId": { "PrimitiveType": "String" } 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 891376dbe3458..1fc7bf4741d17 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": "102.0.0", + "$version": "103.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 9e1c83ad51958..b70365fef6dfc 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Forecast::Dataset.AttributesItems": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-forecast-dataset-attributesitems.html", 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 23d0927b1773d..cc373cc1861ab 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": "102.0.0", + "$version": "103.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 6d486ca65991f..4fcb718e32fc2 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::GameLift::Alias.RoutingStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html", @@ -24,29 +24,29 @@ } } }, - "AWS::GameLift::Build.S3Location": { + "AWS::GameLift::Build.StorageLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html", "Properties": { "Bucket": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storage-bucket", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storagelocation-bucket", "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" }, "Key": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storage-key", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storagelocation-key", "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" }, "ObjectVersion": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-object-verison", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storagelocation-objectversion", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, "RoleArn": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storage-rolearn", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-build-storagelocation.html#cfn-gamelift-build-storagelocation-rolearn", "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" @@ -413,6 +413,11 @@ } }, "AWS::GameLift::Build": { + "Attributes": { + "BuildId": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-build.html", "Properties": { "Name": { @@ -430,7 +435,7 @@ "StorageLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-build.html#cfn-gamelift-build-storagelocation", "Required": false, - "Type": "S3Location", + "Type": "StorageLocation", "UpdateType": "Immutable" }, "Version": { 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 07b2ffe939ad3..0a5de7bcbe1be 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": "102.0.0", + "$version": "103.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 a6f9020945541..e6dae1331c246 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": "102.0.0", + "$version": "103.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_Grafana.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Grafana.json index 50536b043680c..3500629539aa7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Grafana.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Grafana.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Grafana::Workspace.AssertionAttributes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-grafana-workspace-assertionattributes.html", @@ -116,6 +116,27 @@ "UpdateType": "Mutable" } } + }, + "AWS::Grafana::Workspace.VpcConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-grafana-workspace-vpcconfiguration.html", + "Properties": { + "SecurityGroupIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-grafana-workspace-vpcconfiguration.html#cfn-grafana-workspace-vpcconfiguration-securitygroupids", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "SubnetIds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-grafana-workspace-vpcconfiguration.html#cfn-grafana-workspace-vpcconfiguration-subnetids", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + } + } } }, "ResourceTypes": { @@ -233,6 +254,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "VpcConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-grafana-workspace.html#cfn-grafana-workspace-vpcconfiguration", + "Required": false, + "Type": "VpcConfiguration", + "UpdateType": "Mutable" } } } 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 22a75783fdb6d..5e8aad77d88d6 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": "102.0.0", + "$version": "103.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 ab8871f159ab9..23e8ef567cdbf 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": "102.0.0", + "$version": "103.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 389771971f167..9d21141dc2bc9 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": "102.0.0", + "$version": "103.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 f02d0521de78c..bdf5348f461e2 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": "102.0.0", + "$version": "103.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 9480dcbfeb01a..3468a50e255b6 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::HealthLake::FHIRDatastore.CreatedAt": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-healthlake-fhirdatastore-createdat.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 e0e77f694ee52..9dc0e2aabe4af 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": "102.0.0", + "$version": "103.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 6540a7c1bdce3..6250dd07f73b7 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": "102.0.0", + "$version": "103.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 index 5449a20352e5d..c78c00d9f9121 100644 --- 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 @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IdentityStore::GroupMembership.MemberId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-identitystore-groupmembership-memberid.html", 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 6888835e9eedd..b5a893e1de365 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html", 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 82d24c9b6c96f..1a05a96aedf8d 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": "102.0.0", + "$version": "103.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 5e4e6c31c81b1..f0b26b5c1eb76 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": "102.0.0", + "$version": "103.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 d55f6d12fd700..3996bc42021b2 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IoT::AccountAuditConfiguration.AuditCheckConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-accountauditconfiguration-auditcheckconfiguration.html", @@ -703,7 +703,6 @@ "Properties": { "Attributes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-thing-attributepayload.html#cfn-iot-thing-attributepayload-attributes", - "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Required": false, "Type": "Map", @@ -2687,6 +2686,14 @@ } }, "AWS::IoT::Thing": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + }, + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iot-thing.html", "Properties": { "AttributePayload": { 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 b9e26744addb7..a62eb420dfb7a 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": "102.0.0", + "$version": "103.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 4b31a548c2dce..131e789238597 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": "102.0.0", + "$version": "103.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 eb30139331dc5..891c6a8253d47 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IoTCoreDeviceAdvisor::SuiteDefinition.DeviceUnderTest": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotcoredeviceadvisor-suitedefinition-deviceundertest.html", 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 cd42b586ef7cd..362598335c5b8 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": "102.0.0", + "$version": "103.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 261b1f6a78e77..1b3743272db45 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": "102.0.0", + "$version": "103.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 index 73d59025c84c7..96a825a24af02 100644 --- 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 @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IoTFleetWise::Campaign.CollectionScheme": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotfleetwise-campaign-collectionscheme.html", 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 32580c8e31e07..5d835f1a8c6fe 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IoTSiteWise::AccessPolicy.AccessPolicyIdentity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-accesspolicy-accesspolicyidentity.html", 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 f9310d73c0ab3..438629f38f5ec 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": "102.0.0", + "$version": "103.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 ad50b93f0fc9b..4e77cdbd21eb3 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": "102.0.0", + "$version": "103.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 79c3a30a0d2f3..422aa6722f32d 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html", 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 ca50ddd35f040..cdb68780acc1b 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": "102.0.0", + "$version": "103.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 4e6d336173dd3..f0a485fb5e52e 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": "102.0.0", + "$version": "103.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 faef350628853..63653809f67fd 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": "102.0.0", + "$version": "103.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 49f5bd99970c4..568836522e9b3 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": "102.0.0", + "$version": "103.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 8b4cb389100c0..d334efd64d2bf 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": "102.0.0", + "$version": "103.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 0756c17a4b45c..b58e76fb08700 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": "102.0.0", + "$version": "103.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 574f9c3f2edbf..852f462b97e75 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::KinesisFirehose::DeliveryStream.AmazonOpenSearchServerlessBufferingHints": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisfirehose-deliverystream-amazonopensearchserverlessbufferinghints.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 f7b8297fe2580..5633a26383301 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": "102.0.0", + "$version": "103.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 493bf72272008..9f45f7b1bb7ee 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": "102.0.0", + "$version": "103.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 7b3d474e94ed0..27a87e71cdb03 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": "102.0.0", + "$version": "103.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 ece003e14b3ca..76dcf2ef908a1 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": "102.0.0", + "$version": "103.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 5dc8ff73a0041..af34d7b144808 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": "102.0.0", + "$version": "103.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 3a669904bf8d6..6458d7e3063e1 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": "102.0.0", + "$version": "103.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 4af7a6252d49e..46c4282c52b6c 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": "102.0.0", + "$version": "103.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 a662921633460..61922d51fb9c4 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Logs::MetricFilter.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-logs-metricfilter-dimension.html", @@ -235,11 +235,6 @@ } }, "AWS::Logs::SubscriptionFilter": { - "Attributes": { - "FilterName": { - "PrimitiveType": "String" - } - }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-subscriptionfilter.html", "Properties": { "DestinationArn": { @@ -248,6 +243,18 @@ "Required": true, "UpdateType": "Immutable" }, + "Distribution": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-subscriptionfilter.html#cfn-logs-subscriptionfilter-distribution", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "FilterName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-subscriptionfilter.html#cfn-logs-subscriptionfilter-filtername", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "FilterPattern": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-subscriptionfilter.html#cfn-logs-subscriptionfilter-filterpattern", "PrimitiveType": "String", 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 8201b128bb0a5..d921dc4f42cda 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::LookoutEquipment::InferenceScheduler.DataInputConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lookoutequipment-inferencescheduler-datainputconfiguration.html", 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 ebc91409f3a97..07b1323e9b927 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": "102.0.0", + "$version": "103.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 7e898ad122139..0de2f6ac97344 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutVision::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_M2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_M2.json index 80808f3bbcc77..5a31c5893defc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_M2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_M2.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::M2::Application.Definition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-m2-application-definition.html", 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 1f7a03628cbef..f078247efee80 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": "102.0.0", + "$version": "103.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 89569d6daec84..9b5c34ec1c4e6 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": "102.0.0", + "$version": "103.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 031dc7eda0e1f..a11fdab015fca 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,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Macie::AllowList.Criteria": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-allowlist-criteria.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 3e3d842d9bc51..cb936a463cf3a 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": "102.0.0", + "$version": "103.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 10e5dc2bd65e2..294b2f5cc541c 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": "102.0.0", + "$version": "103.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 c75b342069803..3c3e9f5fd54b0 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": "102.0.0", + "$version": "103.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 73b0f96c0d74d..04ba2b5148be0 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": "102.0.0", + "$version": "103.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 296728921f025..4103a3ef8674d 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": "102.0.0", + "$version": "103.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 c931e337443fc..2105f05321b8c 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": "102.0.0", + "$version": "103.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 bcfe2ec7084a8..28e7526797fca 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": "102.0.0", + "$version": "103.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 c975e4abab5c3..4531ff12bcbd2 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": "102.0.0", + "$version": "103.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 6cd82b8d18e66..9bc4f04c13bb7 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": "102.0.0", + "$version": "103.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 2161f35e64c79..b58417b40e695 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::NetworkFirewall::Firewall.SubnetMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewall-subnetmapping.html", @@ -131,6 +131,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "StreamExceptionPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewallpolicy-statefulengineoptions.html#cfn-networkfirewall-firewallpolicy-statefulengineoptions-streamexceptionpolicy", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, @@ -326,6 +332,17 @@ } } }, + "AWS::NetworkFirewall::RuleGroup.IPSetReference": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ipsetreference.html", + "Properties": { + "ReferenceArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ipsetreference.html#cfn-networkfirewall-rulegroup-ipsetreference-referencearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::NetworkFirewall::RuleGroup.MatchAttributes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-matchattributes.html", "Properties": { @@ -422,6 +439,18 @@ } } }, + "AWS::NetworkFirewall::RuleGroup.ReferenceSets": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-referencesets.html", + "Properties": { + "IPSetReferences": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-referencesets.html#cfn-networkfirewall-rulegroup-referencesets-ipsetreferences", + "ItemType": "IPSetReference", + "Required": false, + "Type": "Map", + "UpdateType": "Mutable" + } + } + }, "AWS::NetworkFirewall::RuleGroup.RuleDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-ruledefinition.html", "Properties": { @@ -444,6 +473,12 @@ "AWS::NetworkFirewall::RuleGroup.RuleGroup": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulegroup.html", "Properties": { + "ReferenceSets": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulegroup.html#cfn-networkfirewall-rulegroup-rulegroup-referencesets", + "Required": false, + "Type": "ReferenceSets", + "UpdateType": "Mutable" + }, "RuleVariables": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-rulegroup-rulegroup.html#cfn-networkfirewall-rulegroup-rulegroup-rulevariables", "Required": false, 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 73a420054d924..157a27be0adca 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::NetworkManager::ConnectAttachment.ConnectAttachmentOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-connectattachment-connectattachmentoptions.html", @@ -284,6 +284,12 @@ "AWS::NetworkManager::VpcAttachment.VpcOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-vpcattachment-vpcoptions.html", "Properties": { + "ApplianceModeSupport": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-vpcattachment-vpcoptions.html#cfn-networkmanager-vpcattachment-vpcoptions-appliancemodesupport", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "Ipv6Support": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-vpcattachment-vpcoptions.html#cfn-networkmanager-vpcattachment-vpcoptions-ipv6support", "PrimitiveType": "Boolean", 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 a67852cda1a5a..b3461c4b5599b 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": "102.0.0", + "$version": "103.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_Oam.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Oam.json index d40e6a1794561..f3e07e546bc9b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Oam.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Oam.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Oam::Link": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchServerless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchServerless.json index 0159a4d6a62a0..f9c25c584333b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchServerless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchServerless.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::OpenSearchServerless::SecurityConfig.SamlConfigOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchserverless-securityconfig-samlconfigoptions.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 91a43ddb9f5e9..e5f70f333f55d 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": "102.0.0", + "$version": "103.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 8c1a8eba8b7d2..400e24eed4480 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": "102.0.0", + "$version": "103.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 4f7d71e05d5ef..42db784075d72 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": "102.0.0", + "$version": "103.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_Organizations.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Organizations.json index dbe5396d4c204..6f36e7e06f647 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Organizations.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Organizations.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Organizations::Account": { 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 cf3c0b36236af..684ab0405669b 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": "102.0.0", + "$version": "103.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 1195b150caf9d..147e44a422ea8 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Personalize::Dataset.DataSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-personalize-dataset-datasource.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 20585a9d520a6..5141c4336e2de 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": "102.0.0", + "$version": "103.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 8d0a4b6eae55b..ab6770cc9d97d 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": "102.0.0", + "$version": "103.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_Pipes.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pipes.json index 9284f2cb98aa3..71c6748710811 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pipes.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pipes.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Pipes::Pipe.AwsVpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-awsvpcconfiguration.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 6ce461abc892d..75db3fc9b58a9 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": "102.0.0", + "$version": "103.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 2080bc64aecc7..cc57a673c4d80 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::QuickSight::Analysis.AnalysisError": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-analysis-analysiserror.html", @@ -1368,6 +1368,12 @@ "Type": "AuroraPostgreSqlParameters", "UpdateType": "Mutable" }, + "DatabricksParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-datasourceparameters.html#cfn-quicksight-datasource-datasourceparameters-databricksparameters", + "Required": false, + "Type": "DatabricksParameters", + "UpdateType": "Mutable" + }, "MariaDbParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-datasourceparameters.html#cfn-quicksight-datasource-datasourceparameters-mariadbparameters", "Required": false, @@ -1442,6 +1448,29 @@ } } }, + "AWS::QuickSight::DataSource.DatabricksParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-databricksparameters.html", + "Properties": { + "Host": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-databricksparameters.html#cfn-quicksight-datasource-databricksparameters-host", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Port": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-databricksparameters.html#cfn-quicksight-datasource-databricksparameters-port", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + }, + "SqlEndpointPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-databricksparameters.html#cfn-quicksight-datasource-databricksparameters-sqlendpointpath", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::QuickSight::DataSource.ManifestFileLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-datasource-manifestfilelocation.html", "Properties": { 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 8bbd32c082692..792ff30972b50 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": "102.0.0", + "$version": "103.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 3879c272803d3..55ebdce7ac47c 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::RDS::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-dbclusterrole.html", @@ -170,6 +170,12 @@ "Required": false, "UpdateType": "Mutable" }, + "ClientPasswordAuthType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxy-authformat.html#cfn-rds-dbproxy-authformat-clientpasswordauthtype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Description": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbproxy-authformat.html#cfn-rds-dbproxy-authformat-description", "PrimitiveType": "String", @@ -739,6 +745,9 @@ "DBInstanceArn": { "PrimitiveType": "String" }, + "DBSystemId": { + "PrimitiveType": "String" + }, "DbiResourceId": { "PrimitiveType": "String" }, 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 85f87f6a0af6e..b34a971f23311 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": "102.0.0", + "$version": "103.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 4e54dcf2961af..28c159860ae45 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Redshift::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-cluster-endpoint.html", 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 8fcbc496e7683..9be1bdb8ba10e 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::RedshiftServerless::Namespace.Namespace": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshiftserverless-namespace-namespace.html", @@ -265,9 +265,6 @@ "ResourceTypes": { "AWS::RedshiftServerless::Namespace": { "Attributes": { - "Namespace": { - "Type": "Namespace" - }, "Namespace.AdminUsername": { "PrimitiveType": "String" }, @@ -364,6 +361,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "Namespace": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshiftserverless-namespace.html#cfn-redshiftserverless-namespace-namespace", + "Required": false, + "Type": "Namespace", + "UpdateType": "Mutable" + }, "NamespaceName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshiftserverless-namespace.html#cfn-redshiftserverless-namespace-namespacename", "PrimitiveType": "String", @@ -382,32 +385,18 @@ }, "AWS::RedshiftServerless::Workgroup": { "Attributes": { - "Workgroup": { - "Type": "Workgroup" - }, "Workgroup.BaseCapacity": { "PrimitiveType": "Integer" }, - "Workgroup.ConfigParameters": { - "ItemType": "ConfigParameter", - "Type": "List" - }, "Workgroup.CreationDate": { "PrimitiveType": "String" }, - "Workgroup.Endpoint": { - "Type": "Endpoint" - }, "Workgroup.Endpoint.Address": { "PrimitiveType": "String" }, "Workgroup.Endpoint.Port": { "PrimitiveType": "Integer" }, - "Workgroup.Endpoint.VpcEndpoints": { - "ItemType": "VpcEndpoint", - "Type": "List" - }, "Workgroup.EnhancedVpcRouting": { "PrimitiveType": "Boolean" }, @@ -496,6 +485,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "Workgroup": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshiftserverless-workgroup.html#cfn-redshiftserverless-workgroup-workgroup", + "Required": false, + "Type": "Workgroup", + "UpdateType": "Mutable" + }, "WorkgroupName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshiftserverless-workgroup.html#cfn-redshiftserverless-workgroup-workgroupname", "PrimitiveType": "String", 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 8cb938f78da8d..e8c2d142852a8 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": "102.0.0", + "$version": "103.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_Rekognition.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json index 12df724345cd7..412777ddb850e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Rekognition::StreamProcessor.BoundingBox": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rekognition-streamprocessor-boundingbox.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 d5f4d23be9c68..943ad9a298338 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": "102.0.0", + "$version": "103.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_ResourceExplorer2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceExplorer2.json index f4af7ae6c36dc..90b1403bc5793 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceExplorer2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceExplorer2.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::ResourceExplorer2::View.Filters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resourceexplorer2-view-filters.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 835032d710efb..ad009ea391660 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": "102.0.0", + "$version": "103.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 2340465891ef3..a1818371a32f2 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": "102.0.0", + "$version": "103.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 b78b5159f5fde..f0c3de65b2877 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,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::RolesAnywhere::TrustAnchor.Source": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rolesanywhere-trustanchor-source.html", 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 2ec57e5dadce8..29c07d5102132 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": "102.0.0", + "$version": "103.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 783f7c0b214e4..93de509e3c9f7 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", @@ -94,16 +94,20 @@ "ClusterArn": { "PrimitiveType": "String" }, - "ClusterEndpoints": { - "ItemType": "ClusterEndpoint", - "Type": "List" - }, "Status": { "PrimitiveType": "String" } }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-cluster.html", "Properties": { + "ClusterEndpoints": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-cluster.html#cfn-route53recoverycontrol-cluster-clusterendpoints", + "DuplicatesAllowed": true, + "ItemType": "ClusterEndpoint", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-cluster.html#cfn-route53recoverycontrol-cluster-name", "PrimitiveType": "String", 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 0e0c365e97c7a..dd2dcd3ca17e2 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": "102.0.0", + "$version": "103.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 01fb39df3e6c2..7d703776c8eb4 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": "102.0.0", + "$version": "103.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 335b05efb4075..1d5c96c01fc50 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::S3::AccessPoint.PolicyStatus": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-accesspoint-policystatus.html", 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 15f9000b09b6b..9571f5150baee 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::S3ObjectLambda::AccessPoint.AwsLambda": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3objectlambda-accesspoint-awslambda.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 b74bd755a1468..2dd589b04a80e 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": "102.0.0", + "$version": "103.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 d0afd28c72c59..b21be2487f72b 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": "102.0.0", + "$version": "103.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 babc5705f015b..37f78d23bbbd4 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::SES::ConfigurationSet.DashboardOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationset-dashboardoptions.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 0248453e8714a..7f4965a499f4b 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": "102.0.0", + "$version": "103.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 56e141d127bc1..71befad404eef 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": "102.0.0", + "$version": "103.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 f6176a01a54d8..92743638c17a0 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": "102.0.0", + "$version": "103.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 a439535f4f239..cbbceb5545cd9 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": "102.0.0", + "$version": "103.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 dffae3c29508c..828a7b816d096 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": "102.0.0", + "$version": "103.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 2b8bdb5384eea..792dd51f1a21e 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": "102.0.0", + "$version": "103.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 a9430ea9899ff..21b02a1b61ac0 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::SageMaker::App.ResourceSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Scheduler.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Scheduler.json index 044288c8564ba..943e3cd944dba 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Scheduler.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Scheduler.json @@ -1,5 +1,5 @@ { - "$version": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Scheduler::Schedule.AwsVpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-scheduler-schedule-awsvpcconfiguration.html", 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 08c3a9089c7ab..cf19d8bd07c98 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": "102.0.0", + "$version": "103.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 96bca182fa484..8fd56ef627c15 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": "102.0.0", + "$version": "103.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 8dee94fe651ab..4751f02b62de4 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": "102.0.0", + "$version": "103.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 21d9c1f5358ff..880fb0e979516 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": "102.0.0", + "$version": "103.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 c025de406f112..aeae3e3b5455b 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": "102.0.0", + "$version": "103.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 d95df93fd0798..8cce435fd6d6b 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": "102.0.0", + "$version": "103.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 e634f8c42f6d3..49fcc9bdcaa69 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": "102.0.0", + "$version": "103.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 eed21a95d79e0..9b79a989ab2c0 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": "102.0.0", + "$version": "103.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 286b06872fb4e..5926453a51c28 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": "102.0.0", + "$version": "103.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 930f438b30dd6..a1c57c7a1210e 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": "102.0.0", + "$version": "103.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 c5e477066b698..71f3befd2054f 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::Transfer::Connector.As2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-connector-as2config.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 28380d47ec205..104e2b2ece6da 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": "102.0.0", + "$version": "103.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 a8259a45ee9b4..4b6542f8abdcc 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": "102.0.0", + "$version": "103.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 2edfd0bc9f86f..f05b1f3520a5d 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": "102.0.0", + "$version": "103.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 1fc22e658c3c2..395c4b64d3ab3 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": "102.0.0", + "$version": "103.0.0", "PropertyTypes": { "AWS::WAFv2::LoggingConfiguration.ActionCondition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-actioncondition.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 0ccf18cc965ba..08bf0ca6553ad 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": "102.0.0", + "$version": "103.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 153a52f427cc8..c56971dddf272 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": "102.0.0", + "$version": "103.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 3e4a2f05b610e..9c11c2ed9beca 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": "102.0.0", + "$version": "103.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 85cbcac5383a3..ebe0ead3be9e1 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": "102.0.0", + "$version": "103.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 cc83f20d574dc..625b99fd72406 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": "102.0.0", + "$version": "103.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 d45bd749bfcdc..15232a850766d 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": "102.0.0" + "ResourceSpecificationVersion": "103.0.0" } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_Revert_To_Json_Types_patch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_Revert_To_Json_Types_patch.json new file mode 100644 index 0000000000000..237e302807756 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/500_Revert_To_Json_Types_patch.json @@ -0,0 +1,961 @@ +{ + "ResourceTypes": { + "AWS::Backup::ReportPlan": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ReportDeliveryChannel/Type" + }, + { + "op": "add", + "path": "/Properties/ReportDeliveryChannel/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/ReportSetting/Type" + }, + { + "op": "add", + "path": "/Properties/ReportSetting/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::CloudFormation::StackSet": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ManagedExecution/Type" + }, + { + "op": "add", + "path": "/Properties/ManagedExecution/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::CodeGuruProfiler::ProfilingGroup": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/AgentPermissions/Type" + }, + { + "op": "add", + "path": "/Properties/AgentPermissions/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Config::ConformancePack": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/TemplateSSMDocumentDetails/Type" + }, + { + "op": "add", + "path": "/Properties/TemplateSSMDocumentDetails/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Connect::TaskTemplate": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Constraints/Type" + }, + { + "op": "add", + "path": "/Properties/Constraints/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::EC2::FlowLog": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/DestinationOptions/Type" + }, + { + "op": "add", + "path": "/Properties/DestinationOptions/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::EC2::Subnet": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/PrivateDnsNameOptionsOnLaunch/Type" + }, + { + "op": "add", + "path": "/Properties/PrivateDnsNameOptionsOnLaunch/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::EC2::TransitGatewayAttachment": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Options/Type" + }, + { + "op": "add", + "path": "/Properties/Options/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::EC2::TransitGatewayMulticastDomain": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Options/Type" + }, + { + "op": "add", + "path": "/Properties/Options/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::EC2::TransitGatewayVpcAttachment": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Options/Type" + }, + { + "op": "add", + "path": "/Properties/Options/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::ECR::PublicRepository": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/RepositoryCatalogData/Type" + }, + { + "op": "add", + "path": "/Properties/RepositoryCatalogData/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::ElastiCache::User": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/AuthenticationMode/Type" + }, + { + "op": "add", + "path": "/Properties/AuthenticationMode/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Forecast::Dataset": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/EncryptionConfig/Type" + }, + { + "op": "add", + "path": "/Properties/EncryptionConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/Schema/Type" + }, + { + "op": "add", + "path": "/Properties/Schema/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoT::JobTemplate": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/AbortConfig/Type" + }, + { + "op": "add", + "path": "/Properties/AbortConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/JobExecutionsRolloutConfig/Type" + }, + { + "op": "add", + "path": "/Properties/JobExecutionsRolloutConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/PresignedUrlConfig/Type" + }, + { + "op": "add", + "path": "/Properties/PresignedUrlConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/TimeoutConfig/Type" + }, + { + "op": "add", + "path": "/Properties/TimeoutConfig/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTCoreDeviceAdvisor::SuiteDefinition": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/SuiteDefinitionConfiguration/Type" + }, + { + "op": "add", + "path": "/Properties/SuiteDefinitionConfiguration/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTSiteWise::Portal": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Alarms/Type" + }, + { + "op": "add", + "path": "/Properties/Alarms/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTWireless::NetworkAnalyzerConfiguration": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/TraceContent/Type" + }, + { + "op": "add", + "path": "/Properties/TraceContent/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Lex::Bot": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/DataPrivacy/Type" + }, + { + "op": "add", + "path": "/Properties/DataPrivacy/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Lex::BotAlias": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/SentimentAnalysisSettings/Type" + }, + { + "op": "add", + "path": "/Properties/SentimentAnalysisSettings/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::LookoutEquipment::InferenceScheduler": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/DataInputConfiguration/Type" + }, + { + "op": "add", + "path": "/Properties/DataInputConfiguration/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/DataOutputConfiguration/Type" + }, + { + "op": "add", + "path": "/Properties/DataOutputConfiguration/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::MemoryDB::User": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/AuthenticationMode/Type" + }, + { + "op": "add", + "path": "/Properties/AuthenticationMode/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Redshift::EndpointAccess": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/VpcEndpoint/Type" + }, + { + "op": "add", + "path": "/Properties/VpcEndpoint/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Route53::HealthCheck": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/HealthCheckConfig/Type" + }, + { + "op": "add", + "path": "/Properties/HealthCheckConfig/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::S3::AccessPoint": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/PolicyStatus/Type" + }, + { + "op": "add", + "path": "/Properties/PolicyStatus/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::SageMaker::FeatureGroup": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/OfflineStoreConfig/Type" + }, + { + "op": "add", + "path": "/Properties/OfflineStoreConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/OnlineStoreConfig/Type" + }, + { + "op": "add", + "path": "/Properties/OnlineStoreConfig/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::SageMaker::Pipeline": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ParallelismConfiguration/Type" + }, + { + "op": "add", + "path": "/Properties/ParallelismConfiguration/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/PipelineDefinition/Type" + }, + { + "op": "add", + "path": "/Properties/PipelineDefinition/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::SageMaker::Project": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ServiceCatalogProvisioningDetails/Type" + }, + { + "op": "add", + "path": "/Properties/ServiceCatalogProvisioningDetails/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Transfer::Connector": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/As2Config/Type" + }, + { + "op": "add", + "path": "/Properties/As2Config/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::WAFv2::LoggingConfiguration": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/LoggingFilter/Type" + }, + { + "op": "add", + "path": "/Properties/LoggingFilter/PrimitiveType", + "value": "Json" + } + ] + } + } + }, + "PropertyTypes": { + "AWS::Backup::BackupSelection.BackupSelectionResourceType": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Conditions/Type" + }, + { + "op": "add", + "path": "/Properties/Conditions/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Backup::Framework.FrameworkControl": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ControlScope/Type" + }, + { + "op": "add", + "path": "/Properties/ControlScope/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::DataBrew::Recipe.RecipeParameters": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Input/Type" + }, + { + "op": "add", + "path": "/Properties/Input/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::FIS::ExperimentTemplate.ExperimentTemplateLogConfiguration": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/CloudWatchLogsConfiguration/Type" + }, + { + "op": "add", + "path": "/Properties/CloudWatchLogsConfiguration/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/S3Configuration/Type" + }, + { + "op": "add", + "path": "/Properties/S3Configuration/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::GreengrassV2::Deployment.IoTJobRateIncreaseCriteria": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties" + }, + { + "op": "add", + "path": "/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTTwinMaker::ComponentType.DataValue": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/RelationshipValue/Type" + }, + { + "op": "add", + "path": "/Properties/RelationshipValue/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTTwinMaker::Entity.DataValue": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/RelationshipValue/Type" + }, + { + "op": "add", + "path": "/Properties/RelationshipValue/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTTwinMaker::Entity.Property": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Definition/Type" + }, + { + "op": "add", + "path": "/Properties/Definition/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::IoTTwinMaker::Entity.Status": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Error/Type" + }, + { + "op": "add", + "path": "/Properties/Error/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Lex::Bot.TestBotAliasSettings": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/SentimentAnalysisSettings/Type" + }, + { + "op": "add", + "path": "/Properties/SentimentAnalysisSettings/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Personalize::Dataset.DatasetImportJob": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/DataSource/Type" + }, + { + "op": "add", + "path": "/Properties/DataSource/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Personalize::Solution.SolutionConfig": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/AutoMLConfig/Type" + }, + { + "op": "add", + "path": "/Properties/AutoMLConfig/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/HpoConfig/Type" + }, + { + "op": "add", + "path": "/Properties/HpoConfig/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::S3ObjectLambda::AccessPoint.TransformationConfiguration": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ContentTransformation/Type" + }, + { + "op": "add", + "path": "/Properties/ContentTransformation/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::S3Outposts::Bucket.Rule": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Filter/Type" + }, + { + "op": "add", + "path": "/Properties/Filter/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::SageMaker::ModelPackage.ModelPackageContainerDefinition": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/ModelInput/Type" + }, + { + "op": "add", + "path": "/Properties/ModelInput/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::Transfer::Workflow.WorkflowStep": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/CopyStepDetails/Type" + }, + { + "op": "add", + "path": "/Properties/CopyStepDetails/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/CustomStepDetails/Type" + }, + { + "op": "add", + "path": "/Properties/CustomStepDetails/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/DeleteStepDetails/Type" + }, + { + "op": "add", + "path": "/Properties/DeleteStepDetails/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/TagStepDetails/Type" + }, + { + "op": "add", + "path": "/Properties/TagStepDetails/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/JsonBody/Type" + }, + { + "op": "add", + "path": "/Properties/JsonBody/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/SingleHeader/Type" + }, + { + "op": "add", + "path": "/Properties/SingleHeader/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::WAFv2::RuleGroup.FieldToMatch": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/SingleQueryArgument/Type" + }, + { + "op": "add", + "path": "/Properties/SingleQueryArgument/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/SingleHeader/Type" + }, + { + "op": "add", + "path": "/Properties/SingleHeader/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::WAFv2::RuleGroup.RuleAction": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/Allow/Type" + }, + { + "op": "add", + "path": "/Properties/Allow/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/Block/Type" + }, + { + "op": "add", + "path": "/Properties/Block/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/Captcha/Type" + }, + { + "op": "add", + "path": "/Properties/Captcha/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/Count/Type" + }, + { + "op": "add", + "path": "/Properties/Count/PrimitiveType", + "value": "Json" + } + ] + } + }, + "AWS::WAFv2::WebACL.FieldToMatch": { + "patch": { + "description": "This patch fixes all types that were previously typed as Json, and CfnSpec v101.0.0 added types to them, which is a breaking change.", + "operations": [ + { + "op": "remove", + "path": "/Properties/SingleQueryArgument/Type" + }, + { + "op": "add", + "path": "/Properties/SingleQueryArgument/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/SingleHeader/Type" + }, + { + "op": "add", + "path": "/Properties/SingleHeader/PrimitiveType", + "value": "Json" + } + ] + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/906_TimeStream_JsonTypes_patch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/906_TimeStream_JsonTypes_patch.json new file mode 100644 index 0000000000000..01c5d038c050c --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/906_TimeStream_JsonTypes_patch.json @@ -0,0 +1,29 @@ +{ + "ResourceTypes": { + "AWS::Timestream::Table": { + "patch": { + "description": "These types were once typed as Json, and adding types now is a breaking change. Keep them as Json forever.", + "operations": [ + { + "op": "remove", + "path": "/Properties/MagneticStoreWriteProperties/Type" + }, + { + "op": "add", + "path": "/Properties/MagneticStoreWriteProperties/PrimitiveType", + "value": "Json" + }, + { + "op": "remove", + "path": "/Properties/RetentionProperties/Type" + }, + { + "op": "add", + "path": "/Properties/RetentionProperties/PrimitiveType", + "value": "Json" + } + ] + } + } + } +} diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index da983bbf62ca5..c9a97272cf271 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -460,6 +460,10 @@ A stack dependency has the following implications: automatically deploy `stackB`. - `stackB`'s deployment will be performed *before* `stackA`'s deployment. +### CfnResource Dependencies + +To make declaring dependencies between `CfnResource` objects easier, you can declare dependencies from one `CfnResource` object on another by using the `cfnResource1.addDependency(cfnResource2)` method. This method will work for resources both within the same stack and across stacks as it detects the relative location of the two resources and adds the dependency either to the resource or between the relevant stacks, as appropriate. If more complex logic is in needed, you can similarly remove, replace, or view dependencies between `CfnResource` objects with the `CfnResource` `removeDependency`, `replaceDependency`, and `obtainDependencies` methods, respectively. + ## Custom Resources Custom Resources are CloudFormation resources that are implemented by arbitrary @@ -885,13 +889,13 @@ rawBucket.cfnOptions.metadata = { ``` Resource dependencies (the `DependsOn` attribute) is modified using the -`cfnResource.addDependsOn` method: +`cfnResource.addDependency` method: ```ts const resourceA = new CfnResource(this, 'ResourceA', resourceProps); const resourceB = new CfnResource(this, 'ResourceB', resourceProps); -resourceB.addDependsOn(resourceA); +resourceB.addDependency(resourceA); ``` [cfn-resource-attributes]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-product-attribute-reference.html diff --git a/packages/@aws-cdk/core/lib/cfn-resource.ts b/packages/@aws-cdk/core/lib/cfn-resource.ts index ebd6e0825fdb8..b99053c40665c 100644 --- a/packages/@aws-cdk/core/lib/cfn-resource.ts +++ b/packages/@aws-cdk/core/lib/cfn-resource.ts @@ -6,7 +6,7 @@ import { CfnCondition } from './cfn-condition'; import { CfnRefElement } from './cfn-element'; import { CfnCreationPolicy, CfnDeletionPolicy, CfnUpdatePolicy } from './cfn-resource-policy'; import { Construct, IConstruct, Node } from 'constructs'; -import { addDependency } from './deps'; +import { addDependency, obtainDependencies, removeDependency } from './deps'; import { CfnReference } from './private/cfn-reference'; import { CLOUDFORMATION_TOKEN_RESOLVER } from './private/cloudformation-lang'; import { Reference } from './reference'; @@ -274,6 +274,16 @@ export class CfnResource extends CfnRefElement { this.addPropertyOverride(propertyPath, undefined); } + /** + * Indicates that this resource depends on another resource and cannot be + * provisioned unless the other resource has been successfully provisioned. + * + * @deprecated use addDependency + */ + public addDependsOn(target: CfnResource) { + return this.addDependency(target); + } + /** * Indicates that this resource depends on another resource and cannot be * provisioned unless the other resource has been successfully provisioned. @@ -281,13 +291,52 @@ export class CfnResource extends CfnRefElement { * This can be used for resources across stacks (or nested stack) boundaries * and the dependency will automatically be transferred to the relevant scope. */ - public addDependsOn(target: CfnResource) { + public addDependency(target: CfnResource) { + // skip this dependency if the target is not part of the output + if (!target.shouldSynthesize()) { + return; + } + + addDependency(this, target); + } + + /** + * Indicates that this resource no longer depends on another resource. + * + * This can be used for resources across stacks (including nested stacks) + * and the dependency will automatically be removed from the relevant scope. + */ + public removeDependency(target: CfnResource) : void { // skip this dependency if the target is not part of the output if (!target.shouldSynthesize()) { return; } - addDependency(this, target, `"${Node.of(this).path}" depends on "${Node.of(target).path}"`); + removeDependency(this, target); + } + + /** + * Retrieves an array of resources this resource depends on. + * + * This assembles dependencies on resources across stacks (including nested stacks) + * automatically. + */ + public obtainDependencies() { + return obtainDependencies(this); + } + + /** + * Replaces one dependency with another. + * @param target The dependency to replace + * @param newTarget The new dependency to add + */ + public replaceDependency(target: CfnResource, newTarget: CfnResource) : void { + if (this.obtainDependencies().includes(target)) { + this.removeDependency(target); + this.addDependency(newTarget); + } else { + throw new Error(`"${Node.of(this).path}" does not depend on "${Node.of(target).path}"`); + } } /** @@ -330,7 +379,7 @@ export class CfnResource extends CfnRefElement { * dependency between two resources that are directly defined in the same * stacks. * - * Use `resource.addDependsOn` to define the dependency between two resources, + * Use `resource.addDependency` to define the dependency between two resources, * which also takes stack boundaries into account. * * @internal @@ -339,6 +388,24 @@ export class CfnResource extends CfnRefElement { this.dependsOn.add(target); } + /** + * Get a shallow copy of dependencies between this resource and other resources + * in the same stack. + */ + public obtainResourceDependencies() { + return Array.from(this.dependsOn.values()); + } + + /** + * Remove a dependency between this resource and other resources in the same + * stack. + * + * @internal + */ + public _removeResourceDependency(target: CfnResource) { + this.dependsOn.delete(target); + } + /** * Emits CloudFormation for this resource. * @internal diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/cross-region-export-providers/cross-region-ssm-writer-handler/index.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/cross-region-export-providers/cross-region-ssm-writer-handler/index.ts index 84d0e4fe679b1..9f1f2d62d7b99 100644 --- a/packages/@aws-cdk/core/lib/custom-resource-provider/cross-region-export-providers/cross-region-ssm-writer-handler/index.ts +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/cross-region-export-providers/cross-region-ssm-writer-handler/index.ts @@ -30,9 +30,13 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent const removedExports = except(oldExports, exports); await throwIfAnyInUse(ssm, removedExports); // if the ones we are removing are not in use then delete them - await ssm.deleteParameters({ - Names: Object.keys(removedExports), - }).promise(); + // skip if no export names are to be deleted + const removedExportsNames = Object.keys(removedExports); + if (removedExportsNames.length > 0) { + await ssm.deleteParameters({ + Names: removedExportsNames, + }).promise(); + } // also throw an error if we are creating a new export that already exists for some reason await throwIfAnyInUse(ssm, newExports); diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts index aa39ffb609f27..593a88caf3d93 100644 --- a/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts @@ -305,7 +305,7 @@ export class CustomResourceProvider extends Construct { }); if (this._role) { - handler.addDependsOn(this._role); + handler.addDependency(this._role); } if (this.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) { diff --git a/packages/@aws-cdk/core/lib/deps.ts b/packages/@aws-cdk/core/lib/deps.ts index e0ef970b6e359..23579a7a8a734 100644 --- a/packages/@aws-cdk/core/lib/deps.ts +++ b/packages/@aws-cdk/core/lib/deps.ts @@ -3,7 +3,7 @@ import { Stack } from './stack'; import { Stage } from './stage'; import { findLastCommonElement, pathToTopLevelStack as pathToRoot } from './util'; -type Element = CfnResource | Stack; +export type Element = CfnResource | Stack; /** * Adds a dependency between two resources or stacks, across stack and nested @@ -13,18 +13,53 @@ type Element = CfnResource | Stack; * - Try to find the deepest common stack between the two elements * - If there isn't a common stack, it means the elements belong to two * disjoined stack-trees and therefore we apply the dependency at the - * assembly/app level between the two topl-level stacks. + * assembly/app level between the two top-level stacks. * - If we did find a common stack, we apply the dependency as a CloudFormation * "DependsOn" between the resources that "represent" our source and target * either directly or through the AWS::CloudFormation::Stack resources that * "lead" to them. * - * @param source The source resource/stack (the depedent) + * @param source The source resource/stack (the dependent) * @param target The target resource/stack (the dependency) - * @param reason Optional resource to associate with the dependency for + */ +export function addDependency(source: Element, target: Element, reason?: string) { + operateOnDependency(DependencyOperation.ADD, source, target, reason); +} + +/** + * Removes a dependency between two resources or stacks, across stack and nested + * stack boundaries. + * + * The algorithm consists of: + * - Try to find the deepest common stack between the two elements + * - If there isn't a common stack, it means the elements belong to two + * disjoined stack-trees and therefore we applied the dependency at the + * assembly/app level between the two top-level stacks; remove it there. + * - If we did find a common stack, we applied the dependency as a CloudFormation + * "DependsOn" between the resources that "represent" our source and target + * either directly or through the AWS::CloudFormation::Stack resources that + * "lead" to them and must remove it there. + * + * @param source The source resource/stack (the dependent) + * @param target The target resource/stack (the dependency) + * @param reason Optional description to associate with the dependency for * diagnostics */ -export function addDependency(source: T, target: T, reason?: string) { +export function removeDependency(source: Element, target: Element) { + operateOnDependency(DependencyOperation.REMOVE, source, target); +} + +enum DependencyOperation { + ADD, + REMOVE +} + +/** + * Find the appropriate location for a dependency and add or remove it + * + * @internal + */ +function operateOnDependency(operation: DependencyOperation, source: Element, target: Element, description?: string) { if (source === target) { return; } @@ -36,7 +71,7 @@ export function addDependency(source: T, target: T, reason?: const targetStage = Stage.of(targetStack); if (sourceStage !== targetStage) { // eslint-disable-next-line max-len - throw new Error(`You cannot add a dependency from '${source.node.path}' (in ${describeStage(sourceStage)}) to '${target.node.path}' (in ${describeStage(targetStage)}): dependency cannot cross stage boundaries`); + throw new Error(`You cannot have a dependency from '${source.node.path}' (in ${describeStage(sourceStage)}) to '${target.node.path}' (in ${describeStage(targetStage)}): dependency cannot cross stage boundaries`); } // find the deepest common stack between the two elements @@ -44,12 +79,25 @@ export function addDependency(source: T, target: T, reason?: const targetPath = pathToRoot(targetStack); const commonStack = findLastCommonElement(sourcePath, targetPath); - // if there is no common stack, then define a assembly-level dependency + // if there is no common stack, then look for an assembly-level dependency // between the two top-level stacks if (!commonStack) { const topLevelSource = sourcePath[0]; // first path element is the top-level stack const topLevelTarget = targetPath[0]; - topLevelSource._addAssemblyDependency(topLevelTarget, reason); + const reason = { source, target, description }; + switch (operation) { + case DependencyOperation.ADD: { + topLevelSource._addAssemblyDependency(topLevelTarget, reason); + break; + } + case DependencyOperation.REMOVE: { + topLevelSource._removeAssemblyDependency(topLevelTarget, reason); + break; + } + default: { + throw new Error(`Unsupported dependency operation: ${operation}`); + } + } return; } @@ -70,31 +118,67 @@ export function addDependency(source: T, target: T, reason?: // `source` is a direct or indirect nested stack of `target`, and this is not // possible (nested stacks cannot depend on their parents). if (commonStack === target) { - throw new Error(`Nested stack '${sourceStack.node.path}' cannot depend on a parent stack '${targetStack.node.path}': ${reason}`); + throw new Error(`Nested stack '${sourceStack.node.path}' cannot depend on a parent stack '${targetStack.node.path}'`); } // we have a common stack from which we can reach both `source` and `target` // now we need to find two resources which are defined directly in this stack // and which can "lead us" to the source/target. - const sourceResource = resourceInCommonStackFor(source); - const targetResource = resourceInCommonStackFor(target); - sourceResource._addResourceDependency(targetResource); - - function resourceInCommonStackFor(element: CfnResource | Stack): CfnResource { - const resource = Stack.isStack(element) ? element.nestedStackResource : element; - if (!resource) { - throw new Error('assertion failure'); // see "assertion" above + const sourceResource = resourceInCommonStackFor(source, commonStack); + const targetResource = resourceInCommonStackFor(target, commonStack); + switch (operation) { + case DependencyOperation.ADD: { + sourceResource._addResourceDependency(targetResource); + break; + } + case DependencyOperation.REMOVE: { + sourceResource._removeResourceDependency(targetResource); + break; } + default: { + throw new Error(`Unsupported dependency operation: ${operation}`); + } + } +} - const resourceStack = Stack.of(resource); +/** + * Get a list of all resource-to-resource dependencies assembled from this Element, Stack or assembly-dependencies + * @param source The source resource/stack (the dependent) + */ +export function obtainDependencies(source: Element) { + let dependencies: Element[] = []; + if (source instanceof CfnResource) { + dependencies = source.obtainResourceDependencies(); + } - // we reached a resource defined in the common stack - if (commonStack === resourceStack) { - return resource; - } + let stacks = pathToRoot(Stack.of(source)); + stacks.forEach((stack) => { + dependencies = [...dependencies, ...stack._obtainAssemblyDependencies({ source: source })]; + }); - return resourceInCommonStackFor(resourceStack); + return dependencies; +} + +/** + * Find the resource in a common stack that 'points' to the given element + * + * @internal + */ +function resourceInCommonStackFor(element: Element, commonStack: Stack): CfnResource { + const resource: CfnResource = (Stack.isStack(element) ? element.nestedStackResource : element) as CfnResource; + if (!resource) { + // see "assertion" in operateOnDependency above + throw new Error(`Unexpected value for resource when looking at ${element}!`); } + + const resourceStack = Stack.of(resource); + + // we reached a resource defined in the common stack + if (commonStack === resourceStack) { + return resource; + } + + return resourceInCommonStackFor(resourceStack, commonStack); } /** diff --git a/packages/@aws-cdk/core/lib/index.ts b/packages/@aws-cdk/core/lib/index.ts index 378017a1fdefb..11a30ae57a65e 100644 --- a/packages/@aws-cdk/core/lib/index.ts +++ b/packages/@aws-cdk/core/lib/index.ts @@ -34,6 +34,7 @@ export * from './duration'; export * from './expiration'; export * from './size'; export * from './stack-trace'; +export { Element } from './deps'; export * from './app'; export * from './context-provider'; diff --git a/packages/@aws-cdk/core/lib/private/prepare-app.ts b/packages/@aws-cdk/core/lib/private/prepare-app.ts index 7e1959b4a4293..e7d73ee631cb2 100644 --- a/packages/@aws-cdk/core/lib/private/prepare-app.ts +++ b/packages/@aws-cdk/core/lib/private/prepare-app.ts @@ -22,7 +22,7 @@ export function prepareApp(root: IConstruct) { for (const target of targetCfnResources) { for (const source of sourceCfnResources) { - source.addDependsOn(target); + source.addDependency(target); } } } diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index e1e71d06ebdf3..660f841aead19 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -859,32 +859,137 @@ export class Stack extends Construct implements ITaggable { * * @internal */ - public _addAssemblyDependency(target: Stack, reason?: string) { + public _addAssemblyDependency(target: Stack, reason: StackDependencyReason = {}) { // defensive: we should never get here for nested stacks if (this.nested || target.nested) { throw new Error('Cannot add assembly-level dependencies for nested stacks'); } + // Fill in reason details if not provided + if (!reason.source) { + reason.source = this; + } + if (!reason.target) { + reason.target = target; + } + if (!reason.description) { + reason.description = 'no description provided'; + } - reason = reason || 'dependency added using stack.addDependency()'; const cycle = target.stackDependencyReasons(this); if (cycle !== undefined) { + const cycleDescription = cycle.map((cycleReason) => { + return cycleReason.description; + }).join(', '); // eslint-disable-next-line max-len - throw new Error(`'${target.node.path}' depends on '${this.node.path}' (${cycle.join(', ')}). Adding this dependency (${reason}) would create a cyclic reference.`); + throw new Error(`'${target.node.path}' depends on '${this.node.path}' (${cycleDescription}). Adding this dependency (${reason.description}) would create a cyclic reference.`); } let dep = this._stackDependencies[Names.uniqueId(target)]; if (!dep) { - dep = this._stackDependencies[Names.uniqueId(target)] = { - stack: target, - reasons: [], - }; + dep = this._stackDependencies[Names.uniqueId(target)] = { stack: target, reasons: [] }; + } + // Check for a duplicate reason already existing + let existingReasons: Set = new Set(); + dep.reasons.forEach((existingReason) => { + if (existingReason.source == reason.source && existingReason.target == reason.target) { + existingReasons.add(existingReason); + } + }); + if (existingReasons.size > 0) { + // Dependency already exists and for the provided reason + return; } - dep.reasons.push(reason); if (process.env.CDK_DEBUG_DEPS) { // eslint-disable-next-line no-console - console.error(`[CDK_DEBUG_DEPS] stack "${this.node.path}" depends on "${target.node.path}" because: ${reason}`); + console.error(`[CDK_DEBUG_DEPS] stack "${reason.source.node.path}" depends on "${reason.target.node.path}"`); + } + } + + /** + * Called implicitly by the `obtainDependencies` helper function in order to + * collect resource dependencies across two top-level stacks at the assembly level. + * + * Use `stack.obtainDependencies` to see the dependencies between any two stacks. + * + * @internal + */ + public _obtainAssemblyDependencies(reasonFilter: StackDependencyReason): Element[] { + if (!reasonFilter.source) { + throw new Error('reasonFilter.source must be defined!'); + } + // Assume reasonFilter has only source defined + let dependencies: Set = new Set(); + Object.values(this._stackDependencies).forEach((dep) => { + dep.reasons.forEach((reason) => { + if (reasonFilter.source == reason.source) { + if (!reason.target) { + throw new Error(`Encountered an invalid dependency target from source '${reasonFilter.source!.node.path}'`); + } + dependencies.add(reason.target); + } + }); + }); + return Array.from(dependencies); + } + + /** + * Called implicitly by the `removeDependency` helper function in order to + * remove a dependency between two top-level stacks at the assembly level. + * + * Use `stack.addDependency` to define the dependency between any two stacks, + * and take into account nested stack relationships. + * + * @internal + */ + public _removeAssemblyDependency(target: Stack, reasonFilter: StackDependencyReason={}) { + // defensive: we should never get here for nested stacks + if (this.nested || target.nested) { + throw new Error('There cannot be assembly-level dependencies for nested stacks'); + } + // No need to check for a dependency cycle when removing one + + // Fill in reason details if not provided + if (!reasonFilter.source) { + reasonFilter.source = this; + } + if (!reasonFilter.target) { + reasonFilter.target = target; + } + + let dep = this._stackDependencies[Names.uniqueId(target)]; + if (!dep) { + // Dependency doesn't exist - return now + return; + } + + // Find and remove the specified reason from the dependency + let matchedReasons: Set = new Set(); + dep.reasons.forEach((reason) => { + if (reasonFilter.source == reason.source && reasonFilter.target == reason.target) { + matchedReasons.add(reason); + } + }); + if (matchedReasons.size > 1) { + throw new Error(`There cannot be more than one reason for dependency removal, found: ${matchedReasons}`); + } + if (matchedReasons.size == 0) { + // Reason is already not there - return now + return; + } + let matchedReason = Array.from(matchedReasons)[0]; + + let index = dep.reasons.indexOf(matchedReason, 0); + dep.reasons.splice(index, 1); + // If that was the last reason, remove the dependency + if (dep.reasons.length == 0) { + delete this._stackDependencies[Names.uniqueId(target)]; + } + + if (process.env.CDK_DEBUG_DEPS) { + // eslint-disable-next-line no-console + console.log(`[CDK_DEBUG_DEPS] stack "${this.node.path}" no longer depends on "${target.node.path}" because: ${reasonFilter}`); } } @@ -1063,7 +1168,7 @@ export class Stack extends Construct implements ITaggable { * remove the reference from the consuming stack. After that, you can remove * the resource and the manual export. * - * # See `exportValue` for an example of this process. + * See `exportValue` for an example of this process. */ public exportStringListValue(exportedValue: any, options: ExportValueOptions = {}): string[] { if (options.name) { @@ -1261,7 +1366,7 @@ export class Stack extends Construct implements ITaggable { * Returns the list of reasons on the dependency path, or undefined * if there is no dependency. */ - private stackDependencyReasons(other: Stack): string[] | undefined { + private stackDependencyReasons(other: Stack): StackDependencyReason[] | undefined { if (this === other) { return []; } for (const dep of Object.values(this._stackDependencies)) { const ret = dep.stack.stackDependencyReasons(other); @@ -1537,9 +1642,15 @@ function generateExportName(stackExports: Construct, id: string) { return prefix + localPart.slice(Math.max(0, localPart.length - maxLength + prefix.length)); } +interface StackDependencyReason { + source?: Element; + target?: Element; + description?: string; +} + interface StackDependency { stack: Stack; - reasons: string[]; + reasons: StackDependencyReason[]; } interface ResolvedExport { @@ -1575,7 +1686,7 @@ function count(xs: string[]): Record { // These imports have to be at the end to prevent circular imports import { CfnOutput } from './cfn-output'; -import { addDependency } from './deps'; +import { addDependency, Element } from './deps'; import { FileSystem } from './fs'; import { Names } from './names'; import { Reference } from './reference'; @@ -1589,4 +1700,3 @@ import { getExportable } from './private/refs'; import { Fact, RegionInfo } from '@aws-cdk/region-info'; import { deployTimeLookup } from './private/region-lookup'; import { makeUniqueResourceName } from './private/unique-resource-name'; - diff --git a/packages/@aws-cdk/core/test/cfn-resource.test.ts b/packages/@aws-cdk/core/test/cfn-resource.test.ts index 4bc11c5ea43a4..8ab282f10c5ac 100644 --- a/packages/@aws-cdk/core/test/cfn-resource.test.ts +++ b/packages/@aws-cdk/core/test/cfn-resource.test.ts @@ -3,6 +3,7 @@ import { VALIDATE_SNAPSHOT_REMOVAL_POLICY } from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import * as core from '../lib'; import { getWarnings } from './util'; +import { Names } from '../lib'; describe('cfn resource', () => { describe('._toCloudFormation', () => { @@ -136,6 +137,142 @@ describe('cfn resource', () => { }); }); + describe('dependency methods', () => { + test('can explicitly add a dependency between resources', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + resource1.addDependency(resource2); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + DependsOn: [ + 'Resource2', + ], + }, + Resource2: { + Type: 'Test::Resource::Fake2', + }, + }); + }); + + test('can explicitly remove a dependency between resources', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + resource1.addDependency(resource2); + resource1.removeDependency(resource2); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + }, + Resource2: { + Type: 'Test::Resource::Fake2', + }, + }); + }); + + test('can explicitly add, obtain, and remove dependencies across stacks', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + // Use a really long construct id to identify issues between Names.uniqueId and Names.uniqueResourceName + const reallyLongConstructId = 'A'.repeat(247); + const stack2 = new core.Stack(app, reallyLongConstructId, { stackName: 'TestStack2' }); + // Sanity check since this test depends on the discrepancy + expect(Names.uniqueId(stack2)).not.toBe(Names.uniqueResourceName(stack2, {})); + const resource1 = new core.CfnResource(stack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack2, 'Resource2', { type: 'Test::Resource::Fake2' }); + const resource3 = new core.CfnResource(stack1, 'Resource3', { type: 'Test::Resource::Fake3' }); + + resource1.addDependency(resource2); + // Adding the same resource dependency twice should be a no-op + resource1.addDependency(resource2); + resource1.addDependency(resource3); + expect(stack1.dependencies.length).toEqual(1); + expect(stack1.dependencies[0].node.id).toEqual(stack2.node.id); + // obtainDependencies should assemble and flatten resource-to-resource dependencies even across stacks + expect(resource1.obtainDependencies().map(x => x.node.path)).toEqual([resource3.node.path, resource2.node.path]); + + resource1.removeDependency(resource2); + // For symmetry, removing a dependency that doesn't exist should be a no-op + resource1.removeDependency(resource2); + expect(stack1.dependencies.length).toEqual(0); + }); + + test('can explicitly add, then replace dependencies across stacks', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + const stack2 = new core.Stack(app, 'TestStack2'); + const stack3 = new core.Stack(app, 'TestStack3'); + const resource1 = new core.CfnResource(stack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack2, 'Resource2', { type: 'Test::Resource::Fake2' }); + const resource3 = new core.CfnResource(stack3, 'Resource3', { type: 'Test::Resource::Fake3' }); + + resource1.addDependency(resource2); + // Adding the same resource dependency twice should be a no-op + resource1.replaceDependency(resource2, resource3); + expect(stack1.dependencies).toEqual([stack3]); + // obtainDependencies should assemble and flatten resource-to-resource dependencies even across stacks + expect(resource1.obtainDependencies().map(x => x.node.path)).toEqual([resource3.node.path]); + + // Replacing a dependency that doesn't exist should raise an exception + expect(() => { + resource1.replaceDependency(resource2, resource3); + }).toThrow(/ does not depend on /); + }); + + test('do nothing if source is target', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + resource1.addDependency(resource1); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + }, + }); + }); + + test('do nothing if target does not synth', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + + class NoSynthResource extends core.CfnResource { + protected shouldSynthesize(): boolean { + return false; + } + } + + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new NoSynthResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + resource1.removeDependency(resource2); + resource1.addDependency(resource2); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + }, + }); + }); + + test('replace throws an error if oldTarget is not depended on', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + const resource3 = new core.CfnResource(stack, 'Resource3', { type: 'Test::Resource::Fake3' }); + expect(() => { + resource1.replaceDependency(resource2, resource3); + }).toThrow(/does not depend on/); + }); + }); + test('applyRemovalPolicy default includes Update policy', () => { // GIVEN const app = new core.App(); diff --git a/packages/@aws-cdk/core/test/custom-resource-provider/cross-region-ssm-writer-handler.test.ts b/packages/@aws-cdk/core/test/custom-resource-provider/cross-region-ssm-writer-handler.test.ts index 17ee6b3c26a31..e5079668b3b8c 100644 --- a/packages/@aws-cdk/core/test/custom-resource-provider/cross-region-ssm-writer-handler.test.ts +++ b/packages/@aws-cdk/core/test/custom-resource-provider/cross-region-ssm-writer-handler.test.ts @@ -177,6 +177,7 @@ describe('cross-region-ssm-writer entrypoint', () => { }); expect(mockPutParameter).toHaveBeenCalledTimes(1); expect(mocklistTagsForResource).toHaveBeenCalledTimes(1); + expect(mockDeleteParameters).toHaveBeenCalledTimes(0); }); test('removed exports are deleted', async () => { diff --git a/packages/@aws-cdk/core/test/deps.test.ts b/packages/@aws-cdk/core/test/deps.test.ts new file mode 100644 index 0000000000000..5a6eb0a40a8d9 --- /dev/null +++ b/packages/@aws-cdk/core/test/deps.test.ts @@ -0,0 +1,128 @@ +import * as core from '../lib'; +import { Names } from '../lib'; +import { addDependency, obtainDependencies, removeDependency } from '../lib/deps'; +import { Construct } from 'constructs'; + +describe('deps', () => { + describe('dependency methods', () => { + test('can explicitly add a dependency between resources', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + addDependency(resource1, resource2); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + DependsOn: [ + 'Resource2', + ], + }, + Resource2: { + Type: 'Test::Resource::Fake2', + }, + }); + }); + + test('can explicitly remove a dependency between resources', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack, 'Resource2', { type: 'Test::Resource::Fake2' }); + addDependency(resource1, resource2); + removeDependency(resource1, resource2); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + }, + Resource2: { + Type: 'Test::Resource::Fake2', + }, + }); + }); + + test('can explicitly add, obtain, and remove dependencies across stacks', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + // Use a really long construct id to identify issues between Names.uniqueId and Names.uniqueResourceName + const reallyLongConstructId = 'A'.repeat(247); + const stack2 = new core.Stack(app, reallyLongConstructId, { stackName: 'TestStack2' }); + // Sanity check since this test depends on the discrepancy + expect(Names.uniqueId(stack2)).not.toBe(Names.uniqueResourceName(stack2, {})); + const resource1 = new core.CfnResource(stack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(stack2, 'Resource2', { type: 'Test::Resource::Fake2' }); + const resource3 = new core.CfnResource(stack1, 'Resource3', { type: 'Test::Resource::Fake3' }); + + addDependency(resource1, resource2); + // Adding the same resource dependency twice should be a no-op + addDependency(resource1, resource2); + addDependency(resource1, resource3); + expect(stack1.dependencies.length).toEqual(1); + expect(stack1.dependencies[0].node.id).toEqual(stack2.node.id); + // obtainDependencies should assemble and flatten resource-to-resource dependencies even across stacks + expect(obtainDependencies(resource1).map(x => x.node.path)).toEqual([resource3.node.path, resource2.node.path]); + + removeDependency(resource1, resource2); + // For symmetry, removing a dependency that doesn't exist should be a no-op + removeDependency(resource1, resource2); + expect(stack1.dependencies.length).toEqual(0); + }); + + test('do nothing if source is target', () => { + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource1 = new core.CfnResource(stack, 'Resource1', { type: 'Test::Resource::Fake1' }); + addDependency(resource1, resource1); + + expect(app.synth().getStackByName(stack.stackName).template.Resources).toEqual({ + Resource1: { + Type: 'Test::Resource::Fake1', + }, + }); + }); + + test('handle source being common stack', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + const resource1 = new core.CfnResource(stack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + + // If source is the common stack, this should be a noop + addDependency(stack1, resource1); + expect(stack1.dependencies.length).toEqual(0); + }); + + test('throws error if target is common stack', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + const resource1 = new core.CfnResource(stack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + + expect(() => { + addDependency(resource1, stack1); + }).toThrow(/cannot depend on /); + }); + + test('can explicitly add, obtain, and remove dependencies across nested stacks', () => { + const app = new core.App(); + const stack1 = new core.Stack(app, 'TestStack1'); + const construct1 = new Construct(stack1, 'CommonConstruct'); + // Use a really long construct id to identify issues between Names.uniqueId and Names.uniqueResourceName + const nestedStack1 = new core.Stack(construct1, 'TestNestedStack1'); + const nestedStack2 = new core.Stack(construct1, 'TestNestedStack2'); + const resource1 = new core.CfnResource(nestedStack1, 'Resource1', { type: 'Test::Resource::Fake1' }); + const resource2 = new core.CfnResource(nestedStack2, 'Resource2', { type: 'Test::Resource::Fake2' }); + + addDependency(resource1, resource2); + // Adding the same resource dependency twice should be a no-op + addDependency(resource1, resource2); + expect(nestedStack1.dependencies.length).toEqual(1); + expect(nestedStack1.dependencies[0].node.id).toEqual(nestedStack2.node.id); + + removeDependency(resource1, resource2); + // For symmetry, removing a dependency that doesn't exist should be a no-op + removeDependency(resource1, resource2); + expect(stack1.dependencies.length).toEqual(0); + }); + }); +}); diff --git a/packages/@aws-cdk/core/test/integration.deps.readme b/packages/@aws-cdk/core/test/integration.deps.readme new file mode 100644 index 0000000000000..4797f34bca848 --- /dev/null +++ b/packages/@aws-cdk/core/test/integration.deps.readme @@ -0,0 +1,5 @@ ++--------------------------------------------------------------------------+ +| Since cdk-integ depends on cdk which depends on @aws-cdk/core (as a "dev | +| dependency"), this integration test has been added to the package | +| @aws-cdk/aws-cloudformation under `test/integ.core-deps.ts` | ++--------------------------------------------------------------------------+ diff --git a/packages/@aws-cdk/core/test/resource.test.ts b/packages/@aws-cdk/core/test/resource.test.ts index fe247827bb3d6..07f53d3e8fe66 100644 --- a/packages/@aws-cdk/core/test/resource.test.ts +++ b/packages/@aws-cdk/core/test/resource.test.ts @@ -151,11 +151,11 @@ describe('resource', () => { const dependent = new CfnResource(stack, 'Dependent', { type: 'R' }); // WHEN - dependent.addDependsOn(r1); - dependent.addDependsOn(r1); - dependent.addDependsOn(r1); - dependent.addDependsOn(r1); - dependent.addDependsOn(r1); + dependent.addDependency(r1); + dependent.addDependency(r1); + dependent.addDependency(r1); + dependent.addDependency(r1); + dependent.addDependency(r1); // THEN expect(toCloudFormation(stack)).toEqual({ diff --git a/packages/@aws-cdk/core/test/stack.test.ts b/packages/@aws-cdk/core/test/stack.test.ts index 8a7da057a9def..ee1a12412d3ca 100644 --- a/packages/@aws-cdk/core/test/stack.test.ts +++ b/packages/@aws-cdk/core/test/stack.test.ts @@ -1080,7 +1080,7 @@ describe('stack', () => { RefToResource1: resourceA.ref, }, }); - resource2.addDependsOn(resourceB); + resource2.addDependency(resourceB); // THEN const assembly = app.synth(); @@ -1116,6 +1116,206 @@ describe('stack', () => { expect(assembly.getStackArtifact(child2.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual(['ParentChild18FAEF419']); }); + test('_addAssemblyDependency adds to _stackDependencies', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'ChildA'); + const resource1 = new CfnResource(child1, 'Resource1', { type: 'R1' }); + const resource2 = new CfnResource(child1, 'Resource2', { type: 'R2' }); + const resourceA = new CfnResource(childA, 'ResourceA', { type: 'RA' }); + + childA._addAssemblyDependency(child1, { source: resourceA, target: resource1 }); + childA._addAssemblyDependency(child1, { source: resourceA, target: resource2 }); + + expect(childA._obtainAssemblyDependencies({ source: resourceA })) + .toEqual([resource1, resource2]); + + const assembly = app.synth(); + + expect(assembly.getStackArtifact(child1.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + expect(assembly.getStackArtifact(childA.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual(['ParentChild18FAEF419']); + }); + + test('_addAssemblyDependency adds one StackDependencyReason with defaults', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'ChildA'); + + childA._addAssemblyDependency(child1); + + expect(childA._obtainAssemblyDependencies({ source: childA })) + .toEqual([child1]); + + const assembly = app.synth(); + + expect(assembly.getStackArtifact(child1.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + expect(assembly.getStackArtifact(childA.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual(['ParentChild18FAEF419']); + }); + + test('_addAssemblyDependency raises error on cycle', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const child2 = new Stack(parent, 'Child2'); + + child2._addAssemblyDependency(child1); + expect(() => child1._addAssemblyDependency(child2)).toThrow("'Parent/Child2' depends on"); + }); + + test('_addAssemblyDependency raises error for nested stacks', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new NestedStack(parent, 'Child1'); + const child2 = new NestedStack(parent, 'Child2'); + + expect(() => child1._addAssemblyDependency(child2)).toThrow('Cannot add assembly-level'); + }); + + test('_addAssemblyDependency handles duplicate dependency reasons', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const child2 = new Stack(parent, 'Child2'); + + child2._addAssemblyDependency(child1); + const depsBefore = child2._obtainAssemblyDependencies({ source: child2 }); + child2._addAssemblyDependency(child1); + expect(depsBefore).toEqual(child2._obtainAssemblyDependencies({ source: child2 })); + }); + + test('_removeAssemblyDependency removes one StackDependencyReason of two from _stackDependencies', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'ChildA'); + const resource1 = new CfnResource(child1, 'Resource1', { type: 'R1' }); + const resource2 = new CfnResource(child1, 'Resource2', { type: 'R2' }); + const resourceA = new CfnResource(childA, 'ResourceA', { type: 'RA' }); + + childA._addAssemblyDependency(child1, { source: resourceA, target: resource1 }); + childA._addAssemblyDependency(child1, { source: resourceA, target: resource2 }); + childA._removeAssemblyDependency(child1, { source: resourceA, target: resource1 }); + + expect(childA._obtainAssemblyDependencies({ source: resourceA })).toEqual([resource2]); + + const assembly = app.synth(); + + expect(assembly.getStackArtifact(child1.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + expect(assembly.getStackArtifact(childA.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual(['ParentChild18FAEF419']); + }); + + test('_removeAssemblyDependency removes a StackDependency from _stackDependencies with the last reason', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'Child2'); + const resource1 = new CfnResource(child1, 'Resource1', { type: 'R1' }); + const resource2 = new CfnResource(child1, 'Resource2', { type: 'R2' }); + const resourceA = new CfnResource(childA, 'ResourceA', { type: 'RA' }); + + childA._addAssemblyDependency(child1, { source: resourceA, target: resource1 }); + childA._addAssemblyDependency(child1, { source: resourceA, target: resource2 }); + childA._removeAssemblyDependency(child1, { source: resourceA, target: resource1 }); + childA._removeAssemblyDependency(child1, { source: resourceA, target: resource2 }); + + expect(childA._obtainAssemblyDependencies({ source: childA })).toEqual([]); + + const assembly = app.synth(); + + expect(assembly.getStackArtifact(child1.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + expect(assembly.getStackArtifact(childA.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + }); + + test('_removeAssemblyDependency removes a StackDependency with default reason', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'Child2'); + + childA._addAssemblyDependency(child1); + childA._removeAssemblyDependency(child1); + + expect(childA._obtainAssemblyDependencies({ source: childA })).toEqual([]); + + const assembly = app.synth(); + + expect(assembly.getStackArtifact(child1.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + expect(assembly.getStackArtifact(childA.artifactId).dependencies.map((x: { id: any; }) => x.id)).toEqual([]); + }); + + test('_removeAssemblyDependency raises an error for nested stacks', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new NestedStack(parent, 'Child1'); + const childA = new NestedStack(parent, 'Child2'); + + expect(() => childA._removeAssemblyDependency(child1)).toThrow('There cannot be assembly-level'); + }); + + test('_removeAssemblyDependency handles a non-matching dependency reason', () => { + const app = new App({ + context: { + '@aws-cdk/core:stackRelativeExports': true, + [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false, + }, + }); + const parent = new Stack(app, 'Parent'); + const child1 = new Stack(parent, 'Child1'); + const childA = new Stack(parent, 'Child2'); + const resource1 = new CfnResource(child1, 'Resource1', { type: 'R1' }); + const resourceA = new CfnResource(childA, 'ResourceA', { type: 'RA' }); + + childA._addAssemblyDependency(child1); + childA._removeAssemblyDependency(child1, { source: resourceA, target: resource1 }); + }); + test('automatic cross-stack references and manual exports look the same', () => { // GIVEN: automatic const appA = new App({ context: { '@aws-cdk/core:stackRelativeExports': true } }); diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts index 8392932e8d5c2..1eb700f733e1e 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -505,3 +505,218 @@ export const FIREHOSE_CIDR_BLOCKS: { [region: string]: string } = { 'us-west-1': '13.57.135.192', 'us-west-2': '52.89.255.224', }; + +const ADOT_LAMBDA_LAYER_JAVA_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.19.0': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-19-0:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:2', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-19-0:1', + }, + }, +}; + +const ADOT_LAMBDA_LAYER_JAVA_AUTO_INSTRUMENTATION_ARNS: { + [version: string]: { [arch: string]: { [region: string]: string } }; +} = { + '1.19.2': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-19-2:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-19-2:1', + }, + }, +}; + +const ADOT_LAMBDA_LAYER_JAVASCRIPT_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.7.0': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-7-0:2', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-7-0:2', + }, + }, +}; + +const ADOT_LAMBDA_LAYER_PYTHON_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.13.0': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-python-amd64-ver-1-13-0:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-python-arm64-ver-1-13-0:1', + }, + }, +}; + +const ADOT_LAMBDA_LAYER_GENERIC_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '0.62.1': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-collector-amd64-ver-0-62-1:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-collector-arm64-ver-0-62-1:1', + }, + }, +}; + +export const ADOT_LAMBDA_LAYER_ARNS: { [key: string]: any } = { + JAVA_SDK: ADOT_LAMBDA_LAYER_JAVA_SDK_ARNS, + JAVA_AUTO_INSTRUMENTATION: ADOT_LAMBDA_LAYER_JAVA_AUTO_INSTRUMENTATION_ARNS, + JAVASCRIPT_SDK: ADOT_LAMBDA_LAYER_JAVASCRIPT_SDK_ARNS, + PYTHON_SDK: ADOT_LAMBDA_LAYER_PYTHON_SDK_ARNS, + GENERIC: ADOT_LAMBDA_LAYER_GENERIC_ARNS, +}; diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts index 042ff376796a3..3c272acf601c2 100644 --- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts +++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts @@ -10,7 +10,7 @@ import { import { Default } from '../lib/default'; import { APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, DLC_REPOSITORY_ACCOUNTS, - ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, EBS_ENV_ENDPOINT_HOSTED_ZONE_IDS, + ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, EBS_ENV_ENDPOINT_HOSTED_ZONE_IDS, ADOT_LAMBDA_LAYER_ARNS, } from './fact-tables'; async function main(): Promise { @@ -91,6 +91,18 @@ async function main(): Promise { } } + + for (const type in ADOT_LAMBDA_LAYER_ARNS) { + for (const version in ADOT_LAMBDA_LAYER_ARNS[type]) { + for (const arch in ADOT_LAMBDA_LAYER_ARNS[type][version]) { + registerFact( + region, + ['adotLambdaLayer', type, version, arch], + ADOT_LAMBDA_LAYER_ARNS[type][version][arch][region], + ); + } + } + } } lines.push(' }'); lines.push(''); diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index 4d918872ff4f0..efd9932e31908 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -191,4 +191,16 @@ export class FactName { public static servicePrincipal(service: string): string { return `service-principal:${service.replace(/\.amazonaws\.com(\.cn)?$/, '')}`; } + + /** + * The ARN of Amazon Distro for OpenTelemetry (ADOT) Lambda layer for a given lambda type, version and architecture. + * + * @param type the type of the ADOT lambda layer + * @param version the layer version. + * @param architecture the Lambda Function architecture (e.g. 'x86_64' or 'arm64') + */ + public static adotLambdaLayer(type: string, version: string, architecture: string): string { + const suffix = type + '_' + version.split('.').join('_') + '_' + architecture; + return `adot-lambda-layer:${suffix}`; + } } diff --git a/packages/@aws-cdk/region-info/lib/region-info.ts b/packages/@aws-cdk/region-info/lib/region-info.ts index 2b767c540679e..099218434c2c7 100644 --- a/packages/@aws-cdk/region-info/lib/region-info.ts +++ b/packages/@aws-cdk/region-info/lib/region-info.ts @@ -61,7 +61,7 @@ export class RegionInfo { return new RegionInfo(name); } - private constructor(public readonly name: string) { } + private constructor(public readonly name: string) {} /** * Whether the `AWS::CDK::Metadata` CloudFormation Resource is available in this region or not. @@ -106,8 +106,8 @@ export class RegionInfo { } /** - * The hosted zone ID used by Route 53 to alias a EBS environment endpoint in this region (e.g: Z2O1EMRO9K5GLX) - */ + * The hosted zone ID used by Route 53 to alias a EBS environment endpoint in this region (e.g: Z2O1EMRO9K5GLX) + */ public get ebsEnvEndpointHostedZoneId(): string | undefined { return Fact.find(this.name, FactName.EBS_ENV_ENDPOINT_HOSTED_ZONE_ID); } @@ -167,4 +167,15 @@ export class RegionInfo { public get firehoseCidrBlock(): string | undefined { return Fact.find(this.name, FactName.FIREHOSE_CIDR_BLOCK); } + + /** + * The ARN of the ADOT Lambda layer, for the given layer type, version and architecture. + * + * @param type the type of the ADOT lambda layer + * @param version the layer version. + * @param architecture the Lambda Function architecture (e.g. 'x86_64' or 'arm64') + */ + public adotLambdaLayerArn(type: string, version: string, architecture: string): string | undefined { + return Fact.find(this.name, FactName.adotLambdaLayer(type, version, architecture)); + } } diff --git a/packages/aws-cdk-lib/README.md b/packages/aws-cdk-lib/README.md index da983bbf62ca5..c9a97272cf271 100644 --- a/packages/aws-cdk-lib/README.md +++ b/packages/aws-cdk-lib/README.md @@ -460,6 +460,10 @@ A stack dependency has the following implications: automatically deploy `stackB`. - `stackB`'s deployment will be performed *before* `stackA`'s deployment. +### CfnResource Dependencies + +To make declaring dependencies between `CfnResource` objects easier, you can declare dependencies from one `CfnResource` object on another by using the `cfnResource1.addDependency(cfnResource2)` method. This method will work for resources both within the same stack and across stacks as it detects the relative location of the two resources and adds the dependency either to the resource or between the relevant stacks, as appropriate. If more complex logic is in needed, you can similarly remove, replace, or view dependencies between `CfnResource` objects with the `CfnResource` `removeDependency`, `replaceDependency`, and `obtainDependencies` methods, respectively. + ## Custom Resources Custom Resources are CloudFormation resources that are implemented by arbitrary @@ -885,13 +889,13 @@ rawBucket.cfnOptions.metadata = { ``` Resource dependencies (the `DependsOn` attribute) is modified using the -`cfnResource.addDependsOn` method: +`cfnResource.addDependency` method: ```ts const resourceA = new CfnResource(this, 'ResourceA', resourceProps); const resourceB = new CfnResource(this, 'ResourceB', resourceProps); -resourceB.addDependsOn(resourceA); +resourceB.addDependency(resourceA); ``` [cfn-resource-attributes]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-product-attribute-reference.html diff --git a/packages/aws-cdk/test/integ/init/test-typescript-versions.sh b/packages/aws-cdk/test/integ/init/test-typescript-versions.sh index 8df00129a7bff..da5793661a97e 100755 --- a/packages/aws-cdk/test/integ/init/test-typescript-versions.sh +++ b/packages/aws-cdk/test/integ/init/test-typescript-versions.sh @@ -15,15 +15,22 @@ MIN_SUPPORTED_TS_VERSION=${1:-"3.9"} SUPPORTED_TS_VERSIONS=$(node ${integdir}/typescript-versions.js ${MIN_SUPPORTED_TS_VERSION}) for version in $SUPPORTED_TS_VERSIONS; do - echo "Testing against TypeScript v$version" + header TypeScript v$version setup + set -x + node --version + npm --version + cdk init -l typescript sample-app --generate-only - npm pkg delete devDependencies + sed '/\"devDependencies\"/,/}/ d; /^$/d' package.json > package.json.new && rm package.json && mv package.json.new package.json npm install --save-dev typescript@$version + npm install # Older versions of npm require this to be a separate step from the one above npm prune && npm ls rm test/* npm run build cdk synth + + set +x done diff --git a/packages/awslint/lib/rules/resource.ts b/packages/awslint/lib/rules/resource.ts index 95894c847f71d..e7478a811fa57 100644 --- a/packages/awslint/lib/rules/resource.ts +++ b/packages/awslint/lib/rules/resource.ts @@ -189,7 +189,6 @@ resourceLinter.add({ // This rule is the worst resourceLinter.add({ code: 'resource-attribute', - warning: true, message: 'resources must represent all cloudformation attributes as attribute properties. ' + '"@attribute ATTR[,ATTR]" can be used to tag non-standard attribute names. ' + diff --git a/version.v2.json b/version.v2.json index 5b85393422f62..1484929ef453e 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.55.1", - "alphaVersion": "2.55.1-alpha.0" + "version": "2.56.1", + "alphaVersion": "2.56.1-alpha.0" } \ No newline at end of file