From 9f33dfa678bf5f8b06fcc4c054378aa8f840396c Mon Sep 17 00:00:00 2001 From: AWS CDK Team Date: Wed, 3 Jan 2024 17:15:42 +0000 Subject: [PATCH 01/12] chore(release): 2.118.0 --- CHANGELOG.v2.alpha.md | 13 +++++++++++++ CHANGELOG.v2.md | 30 ++++++++++++++++++++++++++++++ version.v2.json | 4 ++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index 433670e7ec04c..b06628880c00e 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -2,6 +2,19 @@ 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.118.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.117.0-alpha.0...v2.118.0-alpha.0) (2024-01-03) + + +### Features + +* **glue:** database description property ([#27744](https://github.com/aws/aws-cdk/issues/27744)) ([cbac240](https://github.com/aws/aws-cdk/commit/cbac24041db7dbc39b4ae1d6da4902b3443528cb)), closes [#27740](https://github.com/aws/aws-cdk/issues/27740) +* **glue-alpha:** add `cfn-glue-table-tableinput-parameters` to Glue table construct ([#27643](https://github.com/aws/aws-cdk/issues/27643)) ([8e15482](https://github.com/aws/aws-cdk/commit/8e15482295c1324eefea020faeb11e4c686357c6)) + + +### Bug Fixes + +* **lambda-go:** path with space breaks go build ([#28554](https://github.com/aws/aws-cdk/issues/28554)) ([a8a639e](https://github.com/aws/aws-cdk/commit/a8a639e2a2114162db240361c32c40a596a7a19e)), closes [#28555](https://github.com/aws/aws-cdk/issues/28555) + ## [2.117.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.116.1-alpha.0...v2.117.0-alpha.0) (2023-12-26) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index b9ddd965bf06c..a8d8af671f837 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.118.0](https://github.com/aws/aws-cdk/compare/v2.117.0...v2.118.0) (2024-01-03) + + +### Features + +* **appsync:** IntrospectionConfig property ([#28500](https://github.com/aws/aws-cdk/issues/28500)) ([98ed6b3](https://github.com/aws/aws-cdk/commit/98ed6b3346e4afd423592296bb1620d20544acad)), closes [#28429](https://github.com/aws/aws-cdk/issues/28429) +* **autoscaling:** add support for `InstanceRequirements` property ([#28464](https://github.com/aws/aws-cdk/issues/28464)) ([276e3a6](https://github.com/aws/aws-cdk/commit/276e3a66febf32afc65a93d7296ec6be8f6e2126)), closes [#28393](https://github.com/aws/aws-cdk/issues/28393) +* **cloudfront:** CloudFront Function runtime property ([#28099](https://github.com/aws/aws-cdk/issues/28099)) ([9b466ae](https://github.com/aws/aws-cdk/commit/9b466ae136910d07d4297a31f1010fa26ce864d0)), closes [#28163](https://github.com/aws/aws-cdk/issues/28163) +* **cloudfront:** Key Value Store L2 ([#28473](https://github.com/aws/aws-cdk/issues/28473)) ([030db42](https://github.com/aws/aws-cdk/commit/030db42ad06a471af3833665cb80dceee034aa02)), closes [#28377](https://github.com/aws/aws-cdk/issues/28377) +* **codepipeline-actions:** more convenient methods to `CacheControl` ([#28491](https://github.com/aws/aws-cdk/issues/28491)) ([a59dc0c](https://github.com/aws/aws-cdk/commit/a59dc0cb79af98ee601f352a7cf1b5fa9cc4d365)), closes [#25477](https://github.com/aws/aws-cdk/issues/25477) +* **ecs:** `interactive` option in `ContainerDefinitionOptions` ([#28536](https://github.com/aws/aws-cdk/issues/28536)) ([1f9788f](https://github.com/aws/aws-cdk/commit/1f9788f8ad45c0f159c9b7e6bafb76763e9b0bea)), closes [#24326](https://github.com/aws/aws-cdk/issues/24326) +* **ecs:** enable cluster to grant task protection API permissions to IAM entities ([#28486](https://github.com/aws/aws-cdk/issues/28486)) ([9bc972b](https://github.com/aws/aws-cdk/commit/9bc972b923b66248fb8392e9cba1b2b5829c6e1b)), closes [#26233](https://github.com/aws/aws-cdk/issues/26233) +* **ecs:** nvidia support to BottlerocketEcsVariant enum for gpu-accelerated tasks ([#28488](https://github.com/aws/aws-cdk/issues/28488)) ([832e29a](https://github.com/aws/aws-cdk/commit/832e29a47c2cb67558c0148a3bf1fa22e4d5cb82)), closes [#25980](https://github.com/aws/aws-cdk/issues/25980) +* **iam:** validate roleName ([#28509](https://github.com/aws/aws-cdk/issues/28509)) ([999c01a](https://github.com/aws/aws-cdk/commit/999c01a1250308b482fe33e651d7ee8da1f96956)), closes [#28502](https://github.com/aws/aws-cdk/issues/28502) +* **opensearchservice:** ip address type for domain ([#28497](https://github.com/aws/aws-cdk/issues/28497)) ([6b80338](https://github.com/aws/aws-cdk/commit/6b80338be59bdfa1d14d81fa1ae79f2eda889b37)), closes [#28436](https://github.com/aws/aws-cdk/issues/28436) +* **rds:** `timeout` and `timeoutAction` properties to ServerlessCluster ([#28534](https://github.com/aws/aws-cdk/issues/28534)) ([508825b](https://github.com/aws/aws-cdk/commit/508825b14d6ccae7274afc08487329162182e887)), closes [#27183](https://github.com/aws/aws-cdk/issues/27183) +* **rds:** ClientPasswordAuthType property on DatabaseProxy ([#28540](https://github.com/aws/aws-cdk/issues/28540)) ([669e6ff](https://github.com/aws/aws-cdk/commit/669e6ffc6e9d8c7b06cb0f62348635f933b6f823)), closes [#28415](https://github.com/aws/aws-cdk/issues/28415) +* **rds:** new Aurora Postgres engine versions ([#28508](https://github.com/aws/aws-cdk/issues/28508)) ([9d8b06f](https://github.com/aws/aws-cdk/commit/9d8b06f6478a98e01e3aaa86c1dbf22d6e861f05)) +* **stepfunctions-tasks:** add `timeout` parameter for EmrCreateCluster ([#28532](https://github.com/aws/aws-cdk/issues/28532)) ([ca91626](https://github.com/aws/aws-cdk/commit/ca91626327ac4a138adc16026d951f21fadf86a3)), closes [/github.com/aws/aws-cdk/pull/28529#discussion_r1438587964](https://github.com/aws//github.com/aws/aws-cdk/pull/28529/issues/discussion_r1438587964) +* **stepfunctions-tasks:** add validations for EmrCreateCluster ([#28529](https://github.com/aws/aws-cdk/issues/28529)) ([e0b725c](https://github.com/aws/aws-cdk/commit/e0b725cd39a01a8387dcf28921e0912552eb7fce)) +* **stepfunctions-tasks:** additional allocation strategies for spot instance fleets in EmrCreateCluster ([#28525](https://github.com/aws/aws-cdk/issues/28525)) ([94003ec](https://github.com/aws/aws-cdk/commit/94003ecb056e56623aa6621a2d013c1a7e3dcebe)) + + +### Bug Fixes + +* **cli:** direct deploy method fails when there are no updates ([#28523](https://github.com/aws/aws-cdk/issues/28523)) ([dde5975](https://github.com/aws/aws-cdk/commit/dde59755cb71aee73a58f3b2c2068f2ae01e9b72)), closes [/github.com/aws/aws-cdk/blob/9d8b06f6478a98e01e3aaa86c1dbf22d6e861f05/packages/aws-cdk/lib/api/util/cloudformation.ts#L290-L296](https://github.com/aws//github.com/aws/aws-cdk/blob/9d8b06f6478a98e01e3aaa86c1dbf22d6e861f05/packages/aws-cdk/lib/api/util/cloudformation.ts/issues/L290-L296) +* **events:** event bus fails with duplicate policy resource ([#28521](https://github.com/aws/aws-cdk/issues/28521)) ([166967f](https://github.com/aws/aws-cdk/commit/166967f11727a28fc11b9af5de0fad6da2a4ad64)), closes [#27340](https://github.com/aws/aws-cdk/issues/27340) [#28520](https://github.com/aws/aws-cdk/issues/28520) +* **iam:** withConditions overrides Principal actions ([#28510](https://github.com/aws/aws-cdk/issues/28510)) ([0b345c5](https://github.com/aws/aws-cdk/commit/0b345c5a98a61ae7a587e5578ffdfc69885bb676)), closes [#28426](https://github.com/aws/aws-cdk/issues/28426) +* **rds:** circular dependencies when creating multiple DatabaseProxies ([#28471](https://github.com/aws/aws-cdk/issues/28471)) ([a12d9eb](https://github.com/aws/aws-cdk/commit/a12d9eb75cc110657a73c6cb82399d572696d36e)), closes [/github.com/aws/aws-cdk/blob/cd54c4239ec29182e30fd91634505df560d6e5f8/packages/aws-cdk-lib/aws-rds/lib/cluster.ts#L446](https://github.com/aws//github.com/aws/aws-cdk/blob/cd54c4239ec29182e30fd91634505df560d6e5f8/packages/aws-cdk-lib/aws-rds/lib/cluster.ts/issues/L446) [#25633](https://github.com/aws/aws-cdk/issues/25633) + ## [2.117.0](https://github.com/aws/aws-cdk/compare/v2.116.1...v2.117.0) (2023-12-26) diff --git a/version.v2.json b/version.v2.json index 7698dd0cd52c0..87664eadc5654 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.117.0", - "alphaVersion": "2.117.0-alpha.0" + "version": "2.118.0", + "alphaVersion": "2.118.0-alpha.0" } \ No newline at end of file From a74aacfb362fac08ced4ebc3e176f89a71b57dd7 Mon Sep 17 00:00:00 2001 From: Thorsten Hoeger Date: Thu, 4 Jan 2024 02:51:39 +0100 Subject: [PATCH 02/12] fix(core): single-file bundling breaks due to left over temp dir (#28566) This change fixes a bad behavior of the asset bundling if we use the SINGLE_FILE asset type with the OUTPUT hash type. Because only the created file is moved and the temporary bundle dir is left over, subsequent bundling runs fail and create empty asset files. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-lib/core/lib/asset-staging.ts | 9 ++++-- .../aws-cdk-lib/core/test/staging.test.ts | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/asset-staging.ts b/packages/aws-cdk-lib/core/lib/asset-staging.ts index 91ec93914a2f0..8991dfbe18634 100644 --- a/packages/aws-cdk-lib/core/lib/asset-staging.ts +++ b/packages/aws-cdk-lib/core/lib/asset-staging.ts @@ -343,11 +343,16 @@ export class AssetStaging extends Construct { this.stageAsset(bundledAsset.path, stagedPath, 'move'); // If bundling produced a single archive file we "touch" this file in the bundling - // directory after it has been moved to the staging directory. This way if bundling + // directory after it has been moved to the staging directory if the hash is known before bundling. This way if bundling // is skipped because the bundling directory already exists we can still determine // the correct packaging type. + // If the hash is calculated after bundling we remove the temporary directory now. if (bundledAsset.packaging === FileAssetPackaging.FILE) { - fs.closeSync(fs.openSync(bundledAsset.path, 'w')); + if (this.hashType === AssetHashType.OUTPUT || this.hashType === AssetHashType.BUNDLE) { + fs.removeSync(path.dirname(bundledAsset.path)); + } else { + fs.closeSync(fs.openSync(bundledAsset.path, 'w')); + } } return { diff --git a/packages/aws-cdk-lib/core/test/staging.test.ts b/packages/aws-cdk-lib/core/test/staging.test.ts index 6f3d904b4ed6e..dff63c09a76f8 100644 --- a/packages/aws-cdk-lib/core/test/staging.test.ts +++ b/packages/aws-cdk-lib/core/test/staging.test.ts @@ -1419,6 +1419,37 @@ describe('staging', () => { expect(staging.isArchive).toEqual(false); }); + test('bundling that produces a single file with SINGLE_FILE and hash type OUTPUT', () => { + // GIVEN + const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + const stack = new Stack(app, 'stack'); + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1', 'subdir'); + + // WHEN + const staging = new AssetStaging(stack, 'Asset', { + sourcePath: directory, + assetHashType: AssetHashType.OUTPUT, + bundling: { + image: DockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_FILE], + outputType: BundlingOutput.SINGLE_FILE, + }, + }); + + // THEN + const assembly = app.synth(); + expect(fs.readdirSync(assembly.directory)).toEqual([ + // 'bundling-temp-0e346bd27baa32f4f2d15d1d73c8972db3293080f6c2836328b7bf77747683db', this directory gets removed and does no longer exist + 'asset.95c924c84f5d023be4edee540cb2cb401a49f115d01ed403b288f6cb412771df.txt', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + expect(staging.packaging).toEqual(FileAssetPackaging.FILE); + expect(staging.isArchive).toEqual(false); + }); + }); describe('staging with docker cp', () => { From 10ed1948beb0f83c1b978da9c0a656aa01a382cb Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Thu, 4 Jan 2024 02:07:38 -0800 Subject: [PATCH 03/12] fix(cli): `cdk diff` falsely reports resource replacements on trivial template changes (#28336) Adds a new flag to diff, `--change-set`, that creates a new changeset and uses it to determine resource replacement. This new flag is on by default. When the flag is set, the following happens: * Resource metadata changes are obscured * Resource changes that do not appear in the changeset are obscured from the diff When the flag is unset, yaml Fn::GetAtt short-form uses are considered equivalent to their long-form counterpart. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cloudformation-diff/lib/diff-template.ts | 118 ++- .../cloudformation-diff/lib/diff/types.ts | 29 +- .../@aws-cdk/cloudformation-diff/package.json | 1 + .../test/diff-template.test.ts | 685 ++++++++++++++---- .../test/iam/broadening.test.ts | 18 +- .../test/iam/detect-changes.test.ts | 30 +- .../test/network/detect-changes.test.ts | 4 +- .../lib/runner/snapshot-test-runner.ts | 4 +- packages/aws-cdk/README.md | 4 + .../lib/api/bootstrap/bootstrap-template.yaml | 3 +- packages/aws-cdk/lib/api/deploy-stack.ts | 141 +--- packages/aws-cdk/lib/api/deployments.ts | 7 +- .../aws-cdk/lib/api/hotswap-deployments.ts | 4 +- .../aws-cdk/lib/api/util/cloudformation.ts | 113 +++ .../lib/api/util/template-body-parameter.ts | 146 ++++ packages/aws-cdk/lib/cdk-toolkit.ts | 82 ++- packages/aws-cdk/lib/cli.ts | 4 +- packages/aws-cdk/lib/diff.ts | 15 +- packages/aws-cdk/lib/import.ts | 2 +- packages/aws-cdk/test/diff.test.ts | 41 ++ tools/@aws-cdk/pkglint/bin/pkglint.ts | 5 +- yarn.lock | 16 + 22 files changed, 1137 insertions(+), 335 deletions(-) create mode 100644 packages/aws-cdk/lib/api/util/template-body-parameter.ts diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts index 6e06e56f90af1..055bc3be8248b 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts @@ -1,3 +1,7 @@ +// The SDK is only used to reference `DescribeChangeSetOutput`, so the SDK is added as a devDependency. +// The SDK should not make network calls here +// eslint-disable-next-line import/no-extraneous-dependencies +import { CloudFormation } from 'aws-sdk'; import * as impl from './diff'; import * as types from './diff/types'; import { deepEqual, diffKeyedEntities, unionOf } from './diff/util'; @@ -33,12 +37,33 @@ const DIFF_HANDLERS: HandlerRegistry = { * * @param currentTemplate the current state of the stack. * @param newTemplate the target state of the stack. + * @param changeSet the change set for this stack. * * @returns a +types.TemplateDiff+ object that represents the changes that will happen if * a stack which current state is described by +currentTemplate+ is updated with * the template +newTemplate+. */ -export function diffTemplate(currentTemplate: { [key: string]: any }, newTemplate: { [key: string]: any }): types.TemplateDiff { +export function fullDiff( + currentTemplate: { [key: string]: any }, + newTemplate: { [key: string]: any }, + changeSet?: CloudFormation.DescribeChangeSetOutput, +): types.TemplateDiff { + + normalize(currentTemplate); + normalize(newTemplate); + const theDiff = diffTemplate(currentTemplate, newTemplate); + if (changeSet) { + filterFalsePositivies(theDiff, changeSet); + } + + return theDiff; +} + +function diffTemplate( + currentTemplate: { [key: string]: any }, + newTemplate: { [key: string]: any }, +): types.TemplateDiff { + // Base diff const theDiff = calculateTemplateDiff(currentTemplate, newTemplate); @@ -105,7 +130,6 @@ function calculateTemplateDiff(currentTemplate: { [key: string]: any }, newTempl const handler: DiffHandler = DIFF_HANDLERS[key] || ((_diff, oldV, newV) => unknown[key] = impl.diffUnknown(oldV, newV)); handler(differences, oldValue, newValue); - } if (Object.keys(unknown).length > 0) { differences.unknown = new types.DifferenceCollection(unknown); @@ -184,3 +208,93 @@ function deepCopy(x: any): any { return x; } + +function filterFalsePositivies(diff: types.TemplateDiff, changeSet: CloudFormation.DescribeChangeSetOutput) { + const replacements = findResourceReplacements(changeSet); + diff.resources.forEachDifference((logicalId: string, change: types.ResourceDifference) => { + change.forEachDifference((type: 'Property' | 'Other', name: string, value: types.Difference | types.PropertyDifference) => { + if (type === 'Property') { + if (!replacements[logicalId]) { + (value as types.PropertyDifference).changeImpact = types.ResourceImpact.NO_CHANGE; + (value as types.PropertyDifference).isDifferent = false; + return; + } + switch (replacements[logicalId].propertiesReplaced[name]) { + case 'Always': + (value as types.PropertyDifference).changeImpact = types.ResourceImpact.WILL_REPLACE; + break; + case 'Never': + (value as types.PropertyDifference).changeImpact = types.ResourceImpact.WILL_UPDATE; + break; + case 'Conditionally': + (value as types.PropertyDifference).changeImpact = types.ResourceImpact.MAY_REPLACE; + break; + case undefined: + (value as types.PropertyDifference).changeImpact = types.ResourceImpact.NO_CHANGE; + (value as types.PropertyDifference).isDifferent = false; + break; + // otherwise, defer to the changeImpact from `diffTemplate` + } + } else if (type === 'Other') { + switch (name) { + case 'Metadata': + change.setOtherChange('Metadata', new types.Difference(value.newValue, value.newValue)); + break; + } + } + }); + }); +} + +function findResourceReplacements(changeSet: CloudFormation.DescribeChangeSetOutput): types.ResourceReplacements { + const replacements: types.ResourceReplacements = {}; + for (const resourceChange of changeSet.Changes ?? []) { + const propertiesReplaced: { [propName: string]: types.ChangeSetReplacement } = {}; + for (const propertyChange of resourceChange.ResourceChange?.Details ?? []) { + if (propertyChange.Target?.Attribute === 'Properties') { + const requiresReplacement = propertyChange.Target.RequiresRecreation === 'Always'; + if (requiresReplacement && propertyChange.Evaluation === 'Static') { + propertiesReplaced[propertyChange.Target.Name!] = 'Always'; + } else if (requiresReplacement && propertyChange.Evaluation === 'Dynamic') { + // If Evaluation is 'Dynamic', then this may cause replacement, or it may not. + // see 'Replacement': https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ResourceChange.html + propertiesReplaced[propertyChange.Target.Name!] = 'Conditionally'; + } else { + propertiesReplaced[propertyChange.Target.Name!] = propertyChange.Target.RequiresRecreation as types.ChangeSetReplacement; + } + } + } + replacements[resourceChange.ResourceChange?.LogicalResourceId!] = { + resourceReplaced: resourceChange.ResourceChange?.Replacement === 'True', + propertiesReplaced, + }; + } + + return replacements; +} + +function normalize(template: any) { + if (typeof template === 'object') { + for (const key of (Object.keys(template ?? {}))) { + if (key === 'Fn::GetAtt' && typeof template[key] === 'string') { + template[key] = template[key].split('.'); + continue; + } else if (key === 'DependsOn') { + if (typeof template[key] === 'string') { + template[key] = [template[key]]; + } else if (Array.isArray(template[key])) { + template[key] = template[key].sort(); + } + continue; + } + + if (Array.isArray(template[key])) { + for (const element of (template[key])) { + normalize(element); + } + } else { + normalize(template[key]); + } + } + } +} diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts index 7bd91b58f6ee4..e85265bf99c1f 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts @@ -6,6 +6,15 @@ import { SecurityGroupChanges } from '../network/security-group-changes'; export type PropertyMap = {[key: string]: any }; +export type ResourceReplacements = { [logicalId: string]: ResourceReplacement }; + +export interface ResourceReplacement { + resourceReplaced: boolean, + propertiesReplaced: { [propertyName: string]: ChangeSetReplacement }; +} + +export type ChangeSetReplacement = 'Always' | 'Never' | 'Conditionally'; + /** Semantic differences between two CloudFormation templates. */ export class TemplateDiff implements ITemplateDiff { public awsTemplateFormatVersion?: Difference; @@ -296,7 +305,7 @@ export class Difference implements IDifference { * * isDifferent => (isUpdate | isRemoved | isUpdate) */ - public readonly isDifferent: boolean; + public isDifferent: boolean; /** * @param oldValue the old value, cannot be equal (to the sense of +deepEqual+) to +newValue+. @@ -327,7 +336,7 @@ export class Difference implements IDifference { } export class PropertyDifference extends Difference { - public readonly changeImpact?: ResourceImpact; + public changeImpact?: ResourceImpact; constructor(oldValue: ValueType | undefined, newValue: ValueType | undefined, args: { changeImpact?: ResourceImpact }) { super(oldValue, newValue); @@ -352,6 +361,10 @@ export class DifferenceCollection> { return ret; } + public remove(logicalId: string): void { + delete this.diffs[logicalId]; + } + public get logicalIds(): string[] { return Object.keys(this.changes); } @@ -621,6 +634,18 @@ export class ResourceDifference implements IDifference { this.propertyDiffs[propertyName] = change; } + /** + * Replace a OtherChange in this object + * + * This affects the property diff as it is summarized to users, but it DOES + * NOT affect either the "oldValue" or "newValue" values; those still contain + * the actual template values as provided by the user (they might still be + * used for downstream processing). + */ + public setOtherChange(otherName: string, change: PropertyDifference) { + this.otherDiffs[otherName] = change; + } + public get changeImpact(): ResourceImpact { // Check the Type first if (this.resourceTypes.oldType !== this.resourceTypes.newType) { diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 0afbb125805c8..2e502090932d3 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -38,6 +38,7 @@ "@types/string-width": "^4.0.1", "fast-check": "^3.14.0", "jest": "^29.7.0", + "aws-sdk": "2.1516.0", "ts-jest": "^29.1.1" }, "repository": { diff --git a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts index 5c755339fd737..b211c1d17c085 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts @@ -1,6 +1,6 @@ import * as fc from 'fast-check'; import { arbitraryTemplate } from './test-arbitraries'; -import { diffTemplate, ResourceImpact } from '../lib/diff-template'; +import { fullDiff, ResourceImpact } from '../lib/diff-template'; const POLICY_DOCUMENT = { foo: 'Bar' }; // Obviously a fake one! const BUCKET_POLICY_RESOURCE = { @@ -27,7 +27,7 @@ test('when there is no difference', () => { // Making a JSON-clone, because === is cheating! const newTemplate = JSON.parse(JSON.stringify(currentTemplate)); - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(0); }); @@ -36,7 +36,7 @@ test('when a resource is created', () => { const newTemplate = { Resources: { BucketResource: { Type: 'AWS::S3::Bucket' } } }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; @@ -60,7 +60,7 @@ test('when a resource is deleted (no DeletionPolicy)', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketPolicyResource; @@ -89,7 +89,7 @@ test('when a resource is deleted (DeletionPolicy=Retain)', () => { Resources: { BucketResource: { Type: 'AWS::S3::Bucket' } }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketPolicyResource; @@ -130,7 +130,7 @@ test('when a property changes', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; @@ -161,7 +161,7 @@ test('change in dependencies counts as a simple update', () => { }, }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); // THEN expect(differences.differenceCount).toBe(1); @@ -196,7 +196,7 @@ test('when a property is deleted', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; @@ -234,7 +234,7 @@ test('when a property is added', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; @@ -268,7 +268,7 @@ test('when a resource type changed', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; @@ -318,7 +318,7 @@ test('resource replacement is tracked through references', () => { }, }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); // THEN expect(differences.resources.differenceCount).toBe(3); @@ -370,10 +370,10 @@ test('adding and removing quotes from a numeric property causes no changes', () }, }, }; - let differences = diffTemplate(currentTemplate, newTemplate); + let differences = fullDiff(currentTemplate, newTemplate); expect(differences.resources.differenceCount).toBe(0); - differences = diffTemplate(newTemplate, currentTemplate); + differences = fullDiff(newTemplate, currentTemplate); expect(differences.resources.differenceCount).toBe(0); }); @@ -401,122 +401,9 @@ test('versions are correctly detected as not numbers', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.resources.differenceCount).toBe(1); }); - -test('single element arrays are equivalent to the single element in DependsOn expressions', () => { - // GIVEN - const currentTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: ['SomeResource'], - }, - }, - }; - - // WHEN - const newTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: 'SomeResource', - }, - }, - }; - - let differences = diffTemplate(currentTemplate, newTemplate); - expect(differences.resources.differenceCount).toBe(0); - - differences = diffTemplate(newTemplate, currentTemplate); - expect(differences.resources.differenceCount).toBe(0); -}); - -test('array equivalence is independent of element order in DependsOn expressions', () => { - // GIVEN - const currentTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: ['SomeResource', 'AnotherResource'], - }, - }, - }; - - // WHEN - const newTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: ['AnotherResource', 'SomeResource'], - }, - }, - }; - - let differences = diffTemplate(currentTemplate, newTemplate); - expect(differences.resources.differenceCount).toBe(0); - - differences = diffTemplate(newTemplate, currentTemplate); - expect(differences.resources.differenceCount).toBe(0); -}); - -test('arrays of different length are considered unequal in DependsOn expressions', () => { - // GIVEN - const currentTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: ['SomeResource', 'AnotherResource', 'LastResource'], - }, - }, - }; - - // WHEN - const newTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - DependsOn: ['AnotherResource', 'SomeResource'], - }, - }, - }; - - let differences = diffTemplate(currentTemplate, newTemplate); - expect(differences.resources.differenceCount).toBe(1); - - differences = diffTemplate(newTemplate, currentTemplate); - expect(differences.resources.differenceCount).toBe(1); -}); - -test('arrays that differ only in element order are considered unequal outside of DependsOn expressions', () => { - // GIVEN - const currentTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - BucketName: { 'Fn::Select': [0, ['name1', 'name2']] }, - }, - }, - }; - - // WHEN - const newTemplate = { - Resources: { - BucketResource: { - Type: 'AWS::S3::Bucket', - BucketName: { 'Fn::Select': [0, ['name2', 'name1']] }, - }, - }, - }; - - let differences = diffTemplate(currentTemplate, newTemplate); - expect(differences.resources.differenceCount).toBe(1); - - differences = diffTemplate(newTemplate, currentTemplate); - expect(differences.resources.differenceCount).toBe(1); -}); - test('boolean properties are considered equal with their stringified counterparts', () => { // GIVEN const currentTemplate = { @@ -545,7 +432,7 @@ test('boolean properties are considered equal with their stringified counterpart }; // WHEN - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); // THEN expect(differences.differenceCount).toBe(0); @@ -577,10 +464,10 @@ test('when a property changes including equivalent DependsOn', () => { }; // THEN - let differences = diffTemplate(currentTemplate, newTemplate); + let differences = fullDiff(currentTemplate, newTemplate); expect(differences.resources.differenceCount).toBe(1); - differences = diffTemplate(newTemplate, currentTemplate); + differences = fullDiff(newTemplate, currentTemplate); expect(differences.resources.differenceCount).toBe(1); }); @@ -615,7 +502,7 @@ test.each([ }, }; // WHEN - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); // THEN expect(differences.differenceCount).toBe(1); @@ -651,7 +538,7 @@ test('when a property with a number-like format doesn\'t change', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(0); expect(differences.resources.differenceCount).toBe(0); const difference = differences.resources.changes.BucketResource; @@ -677,7 +564,7 @@ test('handles a resource changing its Type', () => { }, }; - const differences = diffTemplate(currentTemplate, newTemplate); + const differences = fullDiff(currentTemplate, newTemplate); expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.FunctionApi; @@ -696,8 +583,538 @@ test('diffing any two arbitrary templates should not crash', () => { // We're not interested in making sure we find the right differences here -- just // that we're not crashing. fc.assert(fc.property(arbitraryTemplate, arbitraryTemplate, (t1, t2) => { - diffTemplate(t1, t2); + fullDiff(t1, t2); }), { // path: '1:0:0:0:3:0:1:1:1:1:1:1:1:1:1:1:1:1:1:2:1:1:1', }); }); + +test('metadata changes are rendered in the diff', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: 'magic-bucket', + Metadata: { + 'aws:cdk:path': '/foo/BucketResource', + }, + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: 'magic-bucket', + Metadata: { + 'aws:cdk:path': '/bar/BucketResource', + }, + }, + }, + }; + + // THEN + let differences = fullDiff(currentTemplate, newTemplate); + expect(differences.differenceCount).toBe(1); + + differences = fullDiff(newTemplate, currentTemplate); + expect(differences.resources.differenceCount).toBe(1); +}); + +describe('changeset', () => { + test('changeset overrides spec replacements', () => { + // GIVEN + const currentTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'Name1' }, // Immutable prop + }, + }, + }; + const newTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'BucketName' } }, // No change + }, + }, + }; + + // WHEN + const differences = fullDiff(currentTemplate, newTemplate, { + Parameters: [ + { + ParameterKey: 'BucketName', + ParameterValue: 'Name1', + }, + ], + Changes: [], + }); + + // THEN + expect(differences.differenceCount).toBe(0); + }); + + test('changeset does not overrides spec additions or deletions', () => { + // GIVEN + const currentTemplate = { + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'MagicBucket' }, + }, + }, + }; + const newTemplate = { + Resources: { + Queue: { + Type: 'AWS::SQS::Queue', + Properties: { QueueName: 'MagicQueue' }, + }, + }, + }; + + // WHEN + const differences = fullDiff(currentTemplate, newTemplate, { + Changes: [ + { + ResourceChange: { + Action: 'Remove', + LogicalResourceId: 'Bucket', + ResourceType: 'AWS::S3::Bucket', + Details: [], + }, + }, + { + ResourceChange: { + Action: 'Add', + LogicalResourceId: 'Queue', + ResourceType: 'AWS::SQS::Queue', + Details: [], + }, + }, + ], + }); + + // A realistic changeset will include Additions and Removals, but this shows that we don't use the changeset to determine additions or removals + const emptyChangeSetDifferences = fullDiff(currentTemplate, newTemplate, { + Changes: [], + }); + + // THEN + expect(differences.differenceCount).toBe(2); + expect(emptyChangeSetDifferences.differenceCount).toBe(2); + }); + + test('changeset replacements are respected', () => { + // GIVEN + const currentTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'Name1' }, // Immutable prop + }, + }, + }; + const newTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'BucketName' } }, // 'Name1' -> 'Name2' + }, + }, + }; + + // WHEN + const differences = fullDiff(currentTemplate, newTemplate, { + Parameters: [ + { + ParameterKey: 'BucketName', + ParameterValue: 'Name2', + }, + ], + Changes: [ + { + Type: 'Resource', + ResourceChange: { + Action: 'Modify', + LogicalResourceId: 'Bucket', + ResourceType: 'AWS::S3::Bucket', + Replacement: 'True', + Details: [ + { + Target: { + Attribute: 'Properties', + Name: 'BucketName', + RequiresRecreation: 'Always', + }, + Evaluation: 'Static', + ChangeSource: 'DirectModification', + }, + ], + }, + }, + ], + }); + + // THEN + expect(differences.differenceCount).toBe(1); + }); + + // This is directly in-line with changeset behavior, + // see 'Replacement': https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ResourceChange.html + test('dynamic changeset replacements are considered conditional replacements', () => { + // GIVEN + const currentTemplate = { + Resources: { + Instance: { + Type: 'AWS::EC2::Instance', + Properties: { + ImageId: 'ami-79fd7eee', + KeyName: 'rsa-is-fun', + }, + }, + }, + }; + const newTemplate = { + Resources: { + Instance: { + Type: 'AWS::EC2::Instance', + Properties: { + ImageId: 'ami-79fd7eee', + KeyName: 'but-sha-is-cool', + }, + }, + }, + }; + + // WHEN + const differences = fullDiff(currentTemplate, newTemplate, { + Changes: [ + { + Type: 'Resource', + ResourceChange: { + Action: 'Modify', + LogicalResourceId: 'Instance', + ResourceType: 'AWS::EC2::Instance', + Replacement: 'Conditional', + Details: [ + { + Target: { + Attribute: 'Properties', + Name: 'KeyName', + RequiresRecreation: 'Always', + }, + Evaluation: 'Dynamic', + ChangeSource: 'DirectModification', + }, + ], + }, + }, + ], + }); + + // THEN + expect(differences.differenceCount).toBe(1); + expect(differences.resources.changes.Instance.changeImpact).toEqual(ResourceImpact.MAY_REPLACE); + expect(differences.resources.changes.Instance.propertyUpdates).toEqual({ + KeyName: { + changeImpact: ResourceImpact.MAY_REPLACE, + isDifferent: true, + oldValue: 'rsa-is-fun', + newValue: 'but-sha-is-cool', + }, + }); + }); + + test('changeset resource replacement is not tracked through references', () => { + // GIVEN + const currentTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'Name1' }, // Immutable prop + }, + Queue: { + Type: 'AWS::SQS::Queue', + Properties: { QueueName: { Ref: 'Bucket' } }, // Immutable prop + }, + Topic: { + Type: 'AWS::SNS::Topic', + Properties: { TopicName: { Ref: 'Queue' } }, // Immutable prop + }, + }, + }; + + // WHEN + const newTemplate = { + Parameters: { + BucketName: { + Type: 'String', + }, + }, + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: { Ref: 'BucketName' } }, + }, + Queue: { + Type: 'AWS::SQS::Queue', + Properties: { QueueName: { Ref: 'Bucket' } }, + }, + Topic: { + Type: 'AWS::SNS::Topic', + Properties: { TopicName: { Ref: 'Queue' } }, + }, + }, + }; + const differences = fullDiff(currentTemplate, newTemplate, { + Parameters: [ + { + ParameterKey: 'BucketName', + ParameterValue: 'Name1', + }, + ], + Changes: [ + { + Type: 'Resource', + ResourceChange: { + Action: 'Modify', + LogicalResourceId: 'Bucket', + ResourceType: 'AWS::S3::Bucket', + Replacement: 'False', + Details: [], + }, + }, + ], + }); + + // THEN + expect(differences.resources.differenceCount).toBe(0); + }); + + test('Fn::GetAtt short form and long form are equivalent', () => { + // GIVEN + const currentTemplate = { + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'BucketName' }, + }, + }, + Outputs: { + BucketArnOneWay: { 'Fn::GetAtt': ['BucketName', 'Arn'] }, + BucketArnAnotherWay: { 'Fn::GetAtt': 'BucketName.Arn' }, + }, + }; + const newTemplate = { + Resources: { + Bucket: { + Type: 'AWS::S3::Bucket', + Properties: { BucketName: 'BucketName' }, + }, + }, + Outputs: { + BucketArnOneWay: { 'Fn::GetAtt': 'BucketName.Arn' }, + BucketArnAnotherWay: { 'Fn::GetAtt': ['BucketName', 'Arn'] }, + }, + }; + + // WHEN + const differences = fullDiff(currentTemplate, newTemplate); + + // THEN + expect(differences.differenceCount).toBe(0); + }); + + test('metadata changes are obscured from the diff', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: 'magic-bucket', + Metadata: { + 'aws:cdk:path': '/foo/BucketResource', + }, + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: 'magic-bucket', + Metadata: { + 'aws:cdk:path': '/bar/BucketResource', + }, + }, + }, + }; + + // THEN + let differences = fullDiff(currentTemplate, newTemplate, {}); + expect(differences.differenceCount).toBe(0); + }); + + test('single element arrays are equivalent to the single element in DependsOn expressions', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: ['SomeResource'], + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: 'SomeResource', + }, + }, + }; + + let differences = fullDiff(currentTemplate, newTemplate, {}); + expect(differences.resources.differenceCount).toBe(0); + + differences = fullDiff(newTemplate, currentTemplate, {}); + expect(differences.resources.differenceCount).toBe(0); + }); + + test('array equivalence is independent of element order in DependsOn expressions', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: ['SomeResource', 'AnotherResource'], + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: ['AnotherResource', 'SomeResource'], + }, + }, + }; + + let differences = fullDiff(currentTemplate, newTemplate, {}); + expect(differences.resources.differenceCount).toBe(0); + + differences = fullDiff(newTemplate, currentTemplate, {}); + expect(differences.resources.differenceCount).toBe(0); + }); + + test('arrays of different length are considered unequal in DependsOn expressions', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: ['SomeResource', 'AnotherResource', 'LastResource'], + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + DependsOn: ['AnotherResource', 'SomeResource'], + }, + }, + }; + + // dependsOn changes do not appear in the changeset + let differences = fullDiff(currentTemplate, newTemplate, {}); + expect(differences.resources.differenceCount).toBe(1); + + differences = fullDiff(newTemplate, currentTemplate, {}); + expect(differences.resources.differenceCount).toBe(1); + }); + + test('arrays that differ only in element order are considered unequal outside of DependsOn expressions', () => { + // GIVEN + const currentTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: { 'Fn::Select': [0, ['name1', 'name2']] }, + }, + }, + }; + + // WHEN + const newTemplate = { + Resources: { + BucketResource: { + Type: 'AWS::S3::Bucket', + BucketName: { 'Fn::Select': [0, ['name2', 'name1']] }, + }, + }, + }; + + let differences = fullDiff(currentTemplate, newTemplate, { + Changes: [ + { + Type: 'Resource', + ResourceChange: { + Action: 'Modify', + LogicalResourceId: 'BucketResource', + ResourceType: 'AWS::S3::Bucket', + Replacement: 'True', + Details: [{ + Evaluation: 'Direct', + Target: { + Attribute: 'Properties', + Name: 'BucketName', + RequiresRecreation: 'Always', + }, + }], + }, + }, + ], + }); + expect(differences.resources.differenceCount).toBe(1); + }); +}); diff --git a/packages/@aws-cdk/cloudformation-diff/test/iam/broadening.test.ts b/packages/@aws-cdk/cloudformation-diff/test/iam/broadening.test.ts index afc53da90baa4..4d67d104f3a68 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/iam/broadening.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/iam/broadening.test.ts @@ -1,10 +1,10 @@ -import { diffTemplate, formatSecurityChanges } from '../../lib'; +import { fullDiff, formatSecurityChanges } from '../../lib'; import { poldoc, resource, template } from '../util'; describe('broadening is', () => { test('adding of positive statements', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc({ @@ -22,7 +22,7 @@ describe('broadening is', () => { test('permissions diff can be printed', () => { // GIVEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc({ @@ -47,7 +47,7 @@ describe('broadening is', () => { test('adding of positive statements to an existing policy', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc( @@ -85,7 +85,7 @@ describe('broadening is', () => { test('removal of not-statements', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc({ @@ -103,7 +103,7 @@ describe('broadening is', () => { test('changing of resource target', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc( @@ -135,7 +135,7 @@ describe('broadening is', () => { test('addition of ingress rules', () => { // WHEN - const diff = diffTemplate( + const diff = fullDiff( template({ }), template({ @@ -157,7 +157,7 @@ describe('broadening is', () => { test('addition of egress rules', () => { // WHEN - const diff = diffTemplate( + const diff = fullDiff( template({ }), template({ @@ -181,7 +181,7 @@ describe('broadening is', () => { describe('broadening is not', () => { test('removal of positive statements from an existing policy', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc( diff --git a/packages/@aws-cdk/cloudformation-diff/test/iam/detect-changes.test.ts b/packages/@aws-cdk/cloudformation-diff/test/iam/detect-changes.test.ts index c9e70ec456c4e..bc2638029ad90 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/iam/detect-changes.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/iam/detect-changes.test.ts @@ -1,4 +1,4 @@ -import { diffTemplate } from '../../lib'; +import { fullDiff } from '../../lib'; import { MaybeParsed } from '../../lib/diff/maybe-parsed'; import { IamChangesJson } from '../../lib/iam/iam-changes'; import { deepRemoveUndefined } from '../../lib/util'; @@ -6,7 +6,7 @@ import { poldoc, policy, resource, role, template } from '../util'; test('shows new AssumeRolePolicyDocument', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyRole: role({ AssumeRolePolicyDocument: poldoc({ Action: 'sts:AssumeRole', @@ -32,7 +32,7 @@ test('shows new AssumeRolePolicyDocument', () => { test('implicitly knows principal of identity policy for all resource types', () => { for (const attr of ['Roles', 'Users', 'Groups']) { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyPolicy: policy({ [attr]: [{ Ref: 'MyRole' }], PolicyDocument: poldoc({ @@ -60,7 +60,7 @@ test('implicitly knows principal of identity policy for all resource types', () test('policies on an identity object', () => { for (const resourceType of ['Role', 'User', 'Group']) { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyIdentity: resource(`AWS::IAM::${resourceType}`, { Policies: [ { @@ -90,7 +90,7 @@ test('policies on an identity object', () => { }); test('statement is an intrinsic', () => { - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyIdentity: resource('AWS::IAM::User', { Policies: [ { @@ -124,7 +124,7 @@ test('statement is an intrinsic', () => { test('if policy is attached to multiple roles all are shown', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyPolicy: policy({ Roles: [{ Ref: 'MyRole' }, { Ref: 'ThyRole' }], PolicyDocument: poldoc({ @@ -156,7 +156,7 @@ test('if policy is attached to multiple roles all are shown', () => { test('correctly parses Lambda permissions', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyPermission: resource('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { Ref: 'MyFunction' }, @@ -185,7 +185,7 @@ test('correctly parses Lambda permissions', () => { test('implicitly knows resource of (queue) resource policy even if * given', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue' }], PolicyDocument: poldoc({ @@ -212,7 +212,7 @@ test('implicitly knows resource of (queue) resource policy even if * given', () test('finds sole statement removals', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ BucketPolicy: resource('AWS::S3::BucketPolicy', { Bucket: { Ref: 'MyBucket' }, PolicyDocument: poldoc({ @@ -239,7 +239,7 @@ test('finds sole statement removals', () => { test('finds one of many statement removals', () => { // WHEN - const diff = diffTemplate( + const diff = fullDiff( template({ BucketPolicy: resource('AWS::S3::BucketPolicy', { Bucket: { Ref: 'MyBucket' }, @@ -283,7 +283,7 @@ test('finds one of many statement removals', () => { test('finds policy attachments', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ SomeRole: resource('AWS::IAM::Role', { ManagedPolicyArns: ['arn:policy'], }), @@ -302,7 +302,7 @@ test('finds policy attachments', () => { test('finds policy removals', () => { // WHEN - const diff = diffTemplate( + const diff = fullDiff( template({ SomeRole: resource('AWS::IAM::Role', { ManagedPolicyArns: ['arn:policy', 'arn:policy2'], @@ -327,7 +327,7 @@ test('finds policy removals', () => { test('queuepolicy queue change counts as removal+addition', () => { // WHEN - const diff = diffTemplate(template({ + const diff = fullDiff(template({ QueuePolicy: resource('AWS::SQS::QueuePolicy', { Queues: [{ Ref: 'MyQueue1' }], PolicyDocument: poldoc({ @@ -372,7 +372,7 @@ test('queuepolicy queue change counts as removal+addition', () => { test('supports Fn::If in the top-level property value of Role', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyRole: role({ AssumeRolePolicyDocument: poldoc({ Action: 'sts:AssumeRole', @@ -413,7 +413,7 @@ test('supports Fn::If in the top-level property value of Role', () => { test('supports Fn::If in the elements of an array-typed property of Role', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ MyRole: role({ AssumeRolePolicyDocument: poldoc({ Action: 'sts:AssumeRole', diff --git a/packages/@aws-cdk/cloudformation-diff/test/network/detect-changes.test.ts b/packages/@aws-cdk/cloudformation-diff/test/network/detect-changes.test.ts index 37f0e13da204b..6542a72eac807 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/network/detect-changes.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/network/detect-changes.test.ts @@ -1,9 +1,9 @@ -import { diffTemplate } from '../../lib'; +import { fullDiff } from '../../lib'; import { resource, template } from '../util'; test('detect addition of all types of rules', () => { // WHEN - const diff = diffTemplate({}, template({ + const diff = fullDiff({}, template({ SG: resource('AWS::EC2::SecurityGroup', { SecurityGroupIngress: [ { diff --git a/packages/@aws-cdk/integ-runner/lib/runner/snapshot-test-runner.ts b/packages/@aws-cdk/integ-runner/lib/runner/snapshot-test-runner.ts index 233b8349ab6a8..2277c95ac0915 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/snapshot-test-runner.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/snapshot-test-runner.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import { Writable, WritableOptions } from 'stream'; import { StringDecoder } from 'string_decoder'; -import { diffTemplate, formatDifferences, ResourceDifference, ResourceImpact } from '@aws-cdk/cloudformation-diff'; +import { fullDiff, formatDifferences, ResourceDifference, ResourceImpact } from '@aws-cdk/cloudformation-diff'; import { AssemblyManifestReader } from './private/cloud-assembly'; import { IntegRunnerOptions, IntegRunner, DEFAULT_SYNTH_OPTIONS } from './runner-base'; import { Diagnostic, DiagnosticReason, DestructiveChange, SnapshotVerificationOptions } from '../workers/common'; @@ -211,7 +211,7 @@ export class IntegSnapshotRunner extends IntegRunner { actualTemplate = this.canonicalizeTemplate(actualTemplate, actual[stackId].assets); expectedTemplate = this.canonicalizeTemplate(expectedTemplate, expected[stackId].assets); } - const templateDiff = diffTemplate(expectedTemplate, actualTemplate); + const templateDiff = fullDiff(expectedTemplate, actualTemplate); if (!templateDiff.isEmpty) { const allowedDestroyTypes = this.getAllowedDestroyTypesForStack(stackId) ?? []; diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index 864c7de02c968..7642508136e9d 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -165,6 +165,10 @@ $ # Diff against the currently deployed stack with quiet parameter enabled $ cdk diff --quiet --app='node bin/main.js' MyStackName ``` +The `change-set` flag will make `diff` create a change set and extract resource replacement data from it. This is a bit slower, but will provide no false positives for resource replacement. +The `--no-change-set` mode will consider any change to a property that requires replacement to be a resource replacement, +even if the change is purely cosmetic (like replacing a resource reference with a hardcoded arn). + ### `cdk deploy` Deploys a stack of your CDK app to its environment. During the deployment, the toolkit will output progress diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml index 399562f08bade..6d4ec2323efbd 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml @@ -519,6 +519,7 @@ Resources: Effect: Allow Action: - ssm:GetParameter + - ssm:GetParameters # CreateChangeSet uses this to evaluate any SSM parameters (like `CdkBootstrapVersion`) Resource: - Fn::Sub: "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${CdkBootstrapVersion}" Version: '2012-10-17' @@ -618,7 +619,7 @@ Resources: Type: String Name: Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' - Value: '19' + Value: '20' Outputs: BucketName: Description: The name of the S3 bucket owned by the CDK toolkit stack diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index 390320b04baae..8e1c8f55e7ba8 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -1,7 +1,6 @@ import * as cxapi from '@aws-cdk/cx-api'; import type { CloudFormation } from 'aws-sdk'; import * as chalk from 'chalk'; -import * as fs from 'fs-extra'; import * as uuid from 'uuid'; import { ISDK, SdkProvider } from './aws-auth'; import { EnvironmentResources } from './environment-resources'; @@ -13,18 +12,12 @@ import { waitForStackDeploy, waitForStackDelete, ParameterValues, ParameterChanges, ResourcesToImport, } from './util/cloudformation'; import { StackActivityMonitor, StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; +import { TemplateBodyParameter, makeBodyParameter } from './util/template-body-parameter'; import { addMetadataAssetsToManifest } from '../assets'; import { Tag } from '../cdk-toolkit'; -import { debug, error, print, warning } from '../logging'; -import { toYAML } from '../serialize'; +import { debug, print, warning } from '../logging'; import { AssetManifestBuilder } from '../util/asset-manifest-builder'; import { publishAssets } from '../util/asset-publishing'; -import { contentHash } from '../util/content-hash'; - -type TemplateBodyParameter = { - TemplateBody?: string - TemplateURL?: string -}; export interface DeployStackResult { readonly noOp: boolean; @@ -233,8 +226,6 @@ export interface ChangeSetDeploymentMethod { readonly changeSetName?: string; } -const LARGE_TEMPLATE_SIZE_KB = 50; - export async function deployStack(options: DeployStackOptions): Promise { const stackArtifact = options.stack; @@ -567,100 +558,6 @@ class FullCloudFormationDeployment { } } -/** - * Prepares the body parameter for +CreateChangeSet+. - * - * If the template is small enough to be inlined into the API call, just return - * it immediately. - * - * Otherwise, add it to the asset manifest to get uploaded to the staging - * bucket and return its coordinates. If there is no staging bucket, an error - * is thrown. - * - * @param stack the synthesized stack that provides the CloudFormation template - * @param toolkitInfo information about the toolkit stack - */ -async function makeBodyParameter( - stack: cxapi.CloudFormationStackArtifact, - resolvedEnvironment: cxapi.Environment, - assetManifest: AssetManifestBuilder, - resources: EnvironmentResources, - sdk: ISDK, - overrideTemplate?: any, -): Promise { - - // If the template has already been uploaded to S3, just use it from there. - if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) { - return { TemplateURL: restUrlFromManifest(stack.stackTemplateAssetObjectUrl, resolvedEnvironment, sdk) }; - } - - // Otherwise, pass via API call (if small) or upload here (if large) - const templateJson = toYAML(overrideTemplate ?? stack.template); - - if (templateJson.length <= LARGE_TEMPLATE_SIZE_KB * 1024) { - return { TemplateBody: templateJson }; - } - - const toolkitInfo = await resources.lookupToolkit(); - if (!toolkitInfo.found) { - error( - `The template for stack "${stack.displayName}" is ${Math.round(templateJson.length / 1024)}KiB. ` + - `Templates larger than ${LARGE_TEMPLATE_SIZE_KB}KiB must be uploaded to S3.\n` + - 'Run the following command in order to setup an S3 bucket in this environment, and then re-deploy:\n\n', - chalk.blue(`\t$ cdk bootstrap ${resolvedEnvironment.name}\n`)); - - throw new Error('Template too large to deploy ("cdk bootstrap" is required)'); - } - - const templateHash = contentHash(templateJson); - const key = `cdk/${stack.id}/${templateHash}.yml`; - - let templateFile = stack.templateFile; - if (overrideTemplate) { - // Add a variant of this template - templateFile = `${stack.templateFile}-${templateHash}.yaml`; - await fs.writeFile(templateFile, templateJson, { encoding: 'utf-8' }); - } - - assetManifest.addFileAsset(templateHash, { - path: templateFile, - }, { - bucketName: toolkitInfo.bucketName, - objectKey: key, - }); - - const templateURL = `${toolkitInfo.bucketUrl}/${key}`; - debug('Storing template in S3 at:', templateURL); - return { TemplateURL: templateURL }; -} - -/** - * Prepare a body parameter for CFN, performing the upload - * - * Return it as-is if it is small enough to pass in the API call, - * upload to S3 and return the coordinates if it is not. - */ -export async function makeBodyParameterAndUpload( - stack: cxapi.CloudFormationStackArtifact, - resolvedEnvironment: cxapi.Environment, - resources: EnvironmentResources, - sdkProvider: SdkProvider, - sdk: ISDK, - overrideTemplate?: any): Promise { - - // We don't have access to the actual asset manifest here, so pretend that the - // stack doesn't have a pre-published URL. - const forceUploadStack = Object.create(stack, { - stackTemplateAssetObjectUrl: { value: undefined }, - }); - - const builder = new AssetManifestBuilder(); - const bodyparam = await makeBodyParameter(forceUploadStack, resolvedEnvironment, builder, resources, sdk, overrideTemplate); - const manifest = builder.toManifest(stack.assembly.directory); - await publishAssets(manifest, sdkProvider, resolvedEnvironment, { quiet: true }); - return bodyparam; -} - export interface DestroyStackOptions { /** * The stack to be destroyed @@ -791,40 +688,6 @@ function compareTags(a: Tag[], b: Tag[]): boolean { return true; } -/** - * Format an S3 URL in the manifest for use with CloudFormation - * - * Replaces environment placeholders (which this field may contain), - * and reformats s3://.../... urls into S3 REST URLs (which CloudFormation - * expects) - */ -function restUrlFromManifest(url: string, environment: cxapi.Environment, sdk: ISDK): string { - const doNotUseMarker = '**DONOTUSE**'; - // This URL may contain placeholders, so still substitute those. - url = cxapi.EnvironmentPlaceholders.replace(url, { - accountId: environment.account, - region: environment.region, - partition: doNotUseMarker, - }); - - // Yes, this is extremely crude, but we don't actually need this so I'm not inclined to spend - // a lot of effort trying to thread the right value to this location. - if (url.indexOf(doNotUseMarker) > -1) { - throw new Error('Cannot use \'${AWS::Partition}\' in the \'stackTemplateAssetObjectUrl\' field'); - } - - const s3Url = url.match(/s3:\/\/([^/]+)\/(.*)$/); - if (!s3Url) { return url; } - - // We need to pass an 'https://s3.REGION.amazonaws.com[.cn]/bucket/object' URL to CloudFormation, but we - // got an 's3://bucket/object' URL instead. Construct the rest API URL here. - const bucketName = s3Url[1]; - const objectKey = s3Url[2]; - - const urlSuffix: string = sdk.getEndpointSuffix(environment.region); - return `https://s3.${environment.region}.${urlSuffix}/${bucketName}/${objectKey}`; -} - function suffixWithErrors(msg: string, errors?: string[]) { return errors && errors.length > 0 ? `${msg}: ${errors.join(', ')}` diff --git a/packages/aws-cdk/lib/api/deployments.ts b/packages/aws-cdk/lib/api/deployments.ts index e6c2254c70ebb..4da0d27837c92 100644 --- a/packages/aws-cdk/lib/api/deployments.ts +++ b/packages/aws-cdk/lib/api/deployments.ts @@ -4,13 +4,14 @@ import { AssetManifest, IManifestEntry } from 'cdk-assets'; import { Mode } from './aws-auth/credentials'; import { ISDK } from './aws-auth/sdk'; import { CredentialsOptions, SdkForEnvironment, SdkProvider } from './aws-auth/sdk-provider'; -import { deployStack, DeployStackResult, destroyStack, makeBodyParameterAndUpload, DeploymentMethod } from './deploy-stack'; +import { deployStack, DeployStackResult, destroyStack, DeploymentMethod } from './deploy-stack'; import { EnvironmentResources, EnvironmentResourcesRegistry } from './environment-resources'; import { HotswapMode } from './hotswap/common'; import { loadCurrentTemplateWithNestedStacks, loadCurrentTemplate, flattenNestedStackNames, TemplateWithNestedStackCount } from './nested-stack-helpers'; import { CloudFormationStack, Template, ResourcesToImport, ResourceIdentifierSummaries } from './util/cloudformation'; import { StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; import { replaceEnvPlaceholders } from './util/placeholders'; +import { makeBodyParameterAndUpload } from './util/template-body-parameter'; import { Tag } from '../cdk-toolkit'; import { debug, warning } from '../logging'; import { buildAssets, publishAssets, BuildAssetsOptions, PublishAssetsOptions, PublishingAws, EVENT_TO_LOGGER } from '../util/asset-publishing'; @@ -424,6 +425,10 @@ export class Deployments { return stack.exists; } + public async prepareSdkWithDeployRole(stackArtifact: cxapi.CloudFormationStackArtifact): Promise { + return this.prepareSdkFor(stackArtifact, undefined, Mode.ForWriting); + } + private async prepareSdkWithLookupOrDeployRole(stackArtifact: cxapi.CloudFormationStackArtifact): Promise { // try to assume the lookup role try { diff --git a/packages/aws-cdk/lib/api/hotswap-deployments.ts b/packages/aws-cdk/lib/api/hotswap-deployments.ts index 0188f2fbd1cf3..51404d624b92e 100644 --- a/packages/aws-cdk/lib/api/hotswap-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap-deployments.ts @@ -81,7 +81,7 @@ export async function tryHotswapDeployment( nestedStackNames: currentTemplate.nestedStackNames, }); - const stackChanges = cfn_diff.diffTemplate(currentTemplate.deployedTemplate, stackArtifact.template); + const stackChanges = cfn_diff.fullDiff(currentTemplate.deployedTemplate, stackArtifact.template); const { hotswappableChanges, nonHotswappableChanges } = await classifyResourceChanges( stackChanges, evaluateCfnTemplate, sdk, currentTemplate.nestedStackNames, ); @@ -247,7 +247,7 @@ async function findNestedHotswappableChanges( nestedStackName, change.newValue?.Properties?.NestedTemplate, change.newValue?.Properties?.Parameters, ); - const nestedDiff = cfn_diff.diffTemplate( + const nestedDiff = cfn_diff.fullDiff( change.oldValue?.Properties?.NestedTemplate, change.newValue?.Properties?.NestedTemplate, ); diff --git a/packages/aws-cdk/lib/api/util/cloudformation.ts b/packages/aws-cdk/lib/api/util/cloudformation.ts index 6f66e6dc220b4..18f627fe8c1d0 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation.ts @@ -1,8 +1,12 @@ import { SSMPARAM_NO_INVALIDATE } from '@aws-cdk/cx-api'; +import * as cxapi from '@aws-cdk/cx-api'; import { CloudFormation } from 'aws-sdk'; import { StackStatus } from './cloudformation/stack-status'; +import { makeBodyParameterAndUpload, TemplateBodyParameter } from './template-body-parameter'; import { debug } from '../../logging'; import { deserializeStructure } from '../../serialize'; +import { SdkProvider } from '../aws-auth'; +import { Deployments } from '../deployments'; export type Template = { Parameters?: Record; @@ -280,6 +284,115 @@ export async function waitForChangeSet( return ret; } +export type PrepareChangeSetOptions = { + stack: cxapi.CloudFormationStackArtifact; + deployments: Deployments; + uuid: string; + willExecute: boolean; + sdkProvider: SdkProvider; + stream: NodeJS.WritableStream; + parameters: { [name: string]: string | undefined }; +} + +export type CreateChangeSetOptions = { + cfn: CloudFormation; + changeSetName: string; + willExecute: boolean; + exists: boolean; + uuid: string; + stack: cxapi.CloudFormationStackArtifact; + bodyParameter: TemplateBodyParameter; + parameters: { [name: string]: string | undefined }; +} + +/** + * Create a changeset for a diff operation + */ +export async function createDiffChangeSet(options: PrepareChangeSetOptions): Promise { + // `options.stack` has been modified to include any nested stack templates directly inline with its own template, under a special `NestedTemplate` property. + // Thus the parent template's Resources section contains the nested template's CDK metadata check, which uses Fn::Equals. + // This causes CreateChangeSet to fail with `Template Error: Fn::Equals cannot be partially collapsed`. + for (const resource of Object.values((options.stack.template.Resources ?? {}))) { + if ((resource as any).Type === 'AWS::CloudFormation::Stack') { + // eslint-disable-next-line no-console + debug('This stack contains one or more nested stacks, falling back to no change set diff...'); + + return undefined; + } + } + + return uploadBodyParameterAndCreateChangeSet(options); +} + +async function uploadBodyParameterAndCreateChangeSet(options: PrepareChangeSetOptions): Promise { + try { + const preparedSdk = (await options.deployments.prepareSdkWithDeployRole(options.stack)); + const bodyParameter = await makeBodyParameterAndUpload( + options.stack, + preparedSdk.resolvedEnvironment, + preparedSdk.envResources, + options.sdkProvider, + preparedSdk.stackSdk, + ); + const cfn = preparedSdk.stackSdk.cloudFormation(); + const exists = (await CloudFormationStack.lookup(cfn, options.stack.stackName, false)).exists; + + options.stream.write('Creating a change set, this may take a while...\n'); + return await createChangeSet({ + cfn, + changeSetName: 'cdk-diff-change-set', + stack: options.stack, + exists, + uuid: options.uuid, + willExecute: options.willExecute, + bodyParameter, + parameters: options.parameters, + }); + } catch (e: any) { + // eslint-disable-next-line no-console + console.error(`Failed to create change set with error: '${e.message}', falling back to no change-set diff`); + + return undefined; + } +} + +async function createChangeSet(options: CreateChangeSetOptions): Promise { + await cleanupOldChangeset(options.exists, options.changeSetName, options.stack.stackName, options.cfn); + + debug(`Attempting to create ChangeSet with name ${options.changeSetName} for stack ${options.stack.stackName}`); + + const templateParams = TemplateParameters.fromTemplate(options.stack.template); + const stackParams = templateParams.supplyAll(options.parameters); + + const changeSet = await options.cfn.createChangeSet({ + StackName: options.stack.stackName, + ChangeSetName: options.changeSetName, + ChangeSetType: options.exists ? 'UPDATE' : 'CREATE', + Description: `CDK Changeset for diff ${options.uuid}`, + ClientToken: `diff${options.uuid}`, + TemplateURL: options.bodyParameter.TemplateURL, + TemplateBody: options.bodyParameter.TemplateBody, + Parameters: stackParams.apiParameters, + Capabilities: ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'], + }).promise(); + + debug('Initiated creation of changeset: %s; waiting for it to finish creating...', changeSet.Id); + // Fetching all pages if we'll execute, so we can have the correct change count when monitoring. + const createdChangeSet = await waitForChangeSet(options.cfn, options.stack.stackName, options.changeSetName, { fetchAll: options.willExecute }); + await cleanupOldChangeset(options.exists, options.changeSetName, options.stack.stackName, options.cfn); + + return createdChangeSet; +} + +export async function cleanupOldChangeset(exists: boolean, changeSetName: string, stackName: string, cfn: CloudFormation) { + if (exists) { + // Delete any existing change sets generated by CDK since change set names must be unique. + // The delete request is successful as long as the stack exists (even if the change set does not exist). + debug(`Removing existing change set with name ${changeSetName} if it exists`); + await cfn.deleteChangeSet({ StackName: stackName, ChangeSetName: changeSetName }).promise(); + } +} + /** * Return true if the given change set has no changes * diff --git a/packages/aws-cdk/lib/api/util/template-body-parameter.ts b/packages/aws-cdk/lib/api/util/template-body-parameter.ts new file mode 100644 index 0000000000000..cc8381ac2d44a --- /dev/null +++ b/packages/aws-cdk/lib/api/util/template-body-parameter.ts @@ -0,0 +1,146 @@ +import * as cxapi from '@aws-cdk/cx-api'; +import * as chalk from 'chalk'; +import * as fs from 'fs-extra'; +import { debug, error } from '../../logging'; +import { toYAML } from '../../serialize'; +import { AssetManifestBuilder } from '../../util/asset-manifest-builder'; +import { publishAssets } from '../../util/asset-publishing'; +import { contentHash } from '../../util/content-hash'; +import { ISDK, SdkProvider } from '../aws-auth'; +import { EnvironmentResources } from '../environment-resources'; + +export type TemplateBodyParameter = { + TemplateBody?: string + TemplateURL?: string +}; + +const LARGE_TEMPLATE_SIZE_KB = 50; + +/** + * Prepares the body parameter for +CreateChangeSet+. + * + * If the template is small enough to be inlined into the API call, just return + * it immediately. + * + * Otherwise, add it to the asset manifest to get uploaded to the staging + * bucket and return its coordinates. If there is no staging bucket, an error + * is thrown. + * + * @param stack the synthesized stack that provides the CloudFormation template + * @param toolkitInfo information about the toolkit stack + */ +export async function makeBodyParameter( + stack: cxapi.CloudFormationStackArtifact, + resolvedEnvironment: cxapi.Environment, + assetManifest: AssetManifestBuilder, + resources: EnvironmentResources, + sdk: ISDK, + overrideTemplate?: any, +): Promise { + + // If the template has already been uploaded to S3, just use it from there. + if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) { + return { TemplateURL: restUrlFromManifest(stack.stackTemplateAssetObjectUrl, resolvedEnvironment, sdk) }; + } + + // Otherwise, pass via API call (if small) or upload here (if large) + const templateJson = toYAML(overrideTemplate ?? stack.template); + + if (templateJson.length <= LARGE_TEMPLATE_SIZE_KB * 1024) { + return { TemplateBody: templateJson }; + } + + const toolkitInfo = await resources.lookupToolkit(); + if (!toolkitInfo.found) { + error( + `The template for stack "${stack.displayName}" is ${Math.round(templateJson.length / 1024)}KiB. ` + + `Templates larger than ${LARGE_TEMPLATE_SIZE_KB}KiB must be uploaded to S3.\n` + + 'Run the following command in order to setup an S3 bucket in this environment, and then re-deploy:\n\n', + chalk.blue(`\t$ cdk bootstrap ${resolvedEnvironment.name}\n`)); + + throw new Error('Template too large to deploy ("cdk bootstrap" is required)'); + } + + const templateHash = contentHash(templateJson); + const key = `cdk/${stack.id}/${templateHash}.yml`; + + let templateFile = stack.templateFile; + if (overrideTemplate) { + // Add a variant of this template + templateFile = `${stack.templateFile}-${templateHash}.yaml`; + await fs.writeFile(templateFile, templateJson, { encoding: 'utf-8' }); + } + + assetManifest.addFileAsset(templateHash, { + path: templateFile, + }, { + bucketName: toolkitInfo.bucketName, + objectKey: key, + }); + + const templateURL = `${toolkitInfo.bucketUrl}/${key}`; + debug('Storing template in S3 at:', templateURL); + return { TemplateURL: templateURL }; +} + +/** + * Prepare a body parameter for CFN, performing the upload + * + * Return it as-is if it is small enough to pass in the API call, + * upload to S3 and return the coordinates if it is not. + */ +export async function makeBodyParameterAndUpload( + stack: cxapi.CloudFormationStackArtifact, + resolvedEnvironment: cxapi.Environment, + resources: EnvironmentResources, + sdkProvider: SdkProvider, + sdk: ISDK, + overrideTemplate?: any): Promise { + + // We don't have access to the actual asset manifest here, so pretend that the + // stack doesn't have a pre-published URL. + const forceUploadStack = Object.create(stack, { + stackTemplateAssetObjectUrl: { value: undefined }, + }); + + const builder = new AssetManifestBuilder(); + const bodyparam = await makeBodyParameter(forceUploadStack, resolvedEnvironment, builder, resources, sdk, overrideTemplate); + const manifest = builder.toManifest(stack.assembly.directory); + await publishAssets(manifest, sdkProvider, resolvedEnvironment, { quiet: true }); + + return bodyparam; +} + +/** + * Format an S3 URL in the manifest for use with CloudFormation + * + * Replaces environment placeholders (which this field may contain), + * and reformats s3://.../... urls into S3 REST URLs (which CloudFormation + * expects) + */ +function restUrlFromManifest(url: string, environment: cxapi.Environment, sdk: ISDK): string { + const doNotUseMarker = '**DONOTUSE**'; + // This URL may contain placeholders, so still substitute those. + url = cxapi.EnvironmentPlaceholders.replace(url, { + accountId: environment.account, + region: environment.region, + partition: doNotUseMarker, + }); + + // Yes, this is extremely crude, but we don't actually need this so I'm not inclined to spend + // a lot of effort trying to thread the right value to this location. + if (url.indexOf(doNotUseMarker) > -1) { + throw new Error('Cannot use \'${AWS::Partition}\' in the \'stackTemplateAssetObjectUrl\' field'); + } + + const s3Url = url.match(/s3:\/\/([^/]+)\/(.*)$/); + if (!s3Url) { return url; } + + // We need to pass an 'https://s3.REGION.amazonaws.com[.cn]/bucket/object' URL to CloudFormation, but we + // got an 's3://bucket/object' URL instead. Construct the rest API URL here. + const bucketName = s3Url[1]; + const objectKey = s3Url[2]; + + const urlSuffix: string = sdk.getEndpointSuffix(environment.region); + return `https://s3.${environment.region}.${urlSuffix}/${bucketName}/${objectKey}`; +} diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index d2faab3a274c9..43a2638154a3a 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -5,6 +5,7 @@ import * as chalk from 'chalk'; import * as chokidar from 'chokidar'; import * as fs from 'fs-extra'; import * as promptly from 'promptly'; +import * as uuid from 'uuid'; import { DeploymentMethod } from './api'; import { SdkProvider } from './api/aws-auth'; import { Bootstrapper, BootstrapEnvironmentOptions } from './api/bootstrap'; @@ -14,6 +15,7 @@ import { Deployments } from './api/deployments'; import { HotswapMode } from './api/hotswap/common'; import { findCloudWatchLogGroups } from './api/logs/find-cloudwatch-logs'; import { CloudWatchLogEventMonitor } from './api/logs/logs-monitor'; +import { createDiffChangeSet } from './api/util/cloudformation'; import { StackActivityProgress } from './api/util/cloudformation/stack-activity-monitor'; import { generateCdkApp, generateStack, readFromPath, readFromStack, setEnvironment, validateSourceOptions } from './commands/migrate'; import { printSecurityDiff, printStackDiff, RequireApproval } from './diff'; @@ -121,6 +123,8 @@ export class CdkToolkit { const quiet = options.quiet || false; let diffs = 0; + const parameterMap = buildParameterMap(options.parameters); + if (options.templatePath !== undefined) { // Compare single stack against fixed template if (stacks.stackCount !== 1) { @@ -130,10 +134,21 @@ export class CdkToolkit { if (!await fs.pathExists(options.templatePath)) { throw new Error(`There is no file at ${options.templatePath}`); } + + const changeSet = options.changeSet ? await createDiffChangeSet({ + stack: stacks.firstStack, + uuid: uuid.v4(), + willExecute: false, + deployments: this.props.deployments, + sdkProvider: this.props.sdkProvider, + parameters: Object.assign({}, parameterMap['*'], parameterMap[stacks.firstStack.stackName]), + stream, + }) : undefined; + const template = deserializeStructure(await fs.readFile(options.templatePath, { encoding: 'UTF-8' })); diffs = options.securityOnly - ? numberFromBool(printSecurityDiff(template, stacks.firstStack, RequireApproval.Broadening)) - : printStackDiff(template, stacks.firstStack, strict, contextLines, quiet, stream); + ? numberFromBool(printSecurityDiff(template, stacks.firstStack, RequireApproval.Broadening, changeSet)) + : printStackDiff(template, stacks.firstStack, strict, contextLines, quiet, changeSet, stream); } else { // Compare N stacks against deployed templates for (const stack of stacks.stackArtifacts) { @@ -147,10 +162,20 @@ export class CdkToolkit { const currentTemplate = templateWithNames.deployedTemplate; const nestedStackCount = templateWithNames.nestedStackCount; + const changeSet = options.changeSet ? await createDiffChangeSet({ + stack, + uuid: uuid.v4(), + deployments: this.props.deployments, + willExecute: false, + sdkProvider: this.props.sdkProvider, + parameters: Object.assign({}, parameterMap['*'], parameterMap[stacks.firstStack.stackName]), + stream, + }) : undefined; + const stackCount = options.securityOnly - ? (numberFromBool(printSecurityDiff(currentTemplate, stack, RequireApproval.Broadening)) > 0 ? 1 : 0) - : (printStackDiff(currentTemplate, stack, strict, contextLines, quiet, stream) > 0 ? 1 : 0); + ? (numberFromBool(printSecurityDiff(currentTemplate, stack, RequireApproval.Broadening, changeSet)) > 0 ? 1 : 0) + : (printStackDiff(currentTemplate, stack, strict, contextLines, quiet, changeSet, stream) > 0 ? 1 : 0); diffs += stackCount + nestedStackCount; } @@ -181,20 +206,7 @@ export class CdkToolkit { const requireApproval = options.requireApproval ?? RequireApproval.Broadening; - const parameterMap: { [name: string]: { [name: string]: string | undefined } } = { '*': {} }; - for (const key in options.parameters) { - if (options.parameters.hasOwnProperty(key)) { - const [stack, parameter] = key.split(':', 2); - if (!parameter) { - parameterMap['*'][stack] = options.parameters[key]; - } else { - if (!parameterMap[stack]) { - parameterMap[stack] = {}; - } - parameterMap[stack][parameter] = options.parameters[key]; - } - } - } + const parameterMap = buildParameterMap(options.parameters); if (options.hotswap !== HotswapMode.FULL_DEPLOYMENT) { warning('⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments'); @@ -929,6 +941,19 @@ export interface DiffOptions { * @default false */ quiet?: boolean; + + /** + * Additional parameters for CloudFormation at diff time, used to create a change set + * @default {} + */ + parameters?: { [name: string]: string | undefined }; + + /** + * Whether or not to create, analyze, and subsequently delete a changeset + * + * @default true + */ + changeSet?: boolean; } interface CfnDeployOptions { @@ -1286,3 +1311,24 @@ function roundPercentage(num: number): number { function millisecondsToSeconds(num: number): number { return num / 1000; } + +function buildParameterMap(parameters: { + [name: string]: string | undefined; +} | undefined): { [name: string]: { [name: string]: string | undefined } } { + const parameterMap: { [name: string]: { [name: string]: string | undefined } } = { '*': {} }; + for (const key in parameters) { + if (parameters.hasOwnProperty(key)) { + const [stack, parameter] = key.split(':', 2); + if (!parameter) { + parameterMap['*'][stack] = parameters[key]; + } else { + if (!parameterMap[stack]) { + parameterMap[stack] = {}; + } + parameterMap[stack][parameter] = parameters[key]; + } + } + } + + return parameterMap; +} \ No newline at end of file diff --git a/packages/aws-cdk/lib/cli.ts b/packages/aws-cdk/lib/cli.ts index 85e3bdaaf4996..df2f3c24fa569 100644 --- a/packages/aws-cdk/lib/cli.ts +++ b/packages/aws-cdk/lib/cli.ts @@ -262,7 +262,8 @@ async function parseCommandLineArguments(args: string[]) { .option('security-only', { type: 'boolean', desc: 'Only diff for broadened security changes', default: false }) .option('fail', { type: 'boolean', desc: 'Fail with exit code 1 in case of diff' }) .option('processed', { type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', default: false }) - .option('quiet', { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false })) + .option('quiet', { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false }) + .option('change-set', { type: 'boolean', desc: 'Whether to create a changeset to analyze resource replacements. In this mode, diff will use the deploy role instead of the lookup role.', default: true })) .command('metadata [STACK]', 'Returns all metadata associated with this stack') .command(['acknowledge [ID]', 'ack [ID]'], 'Acknowledge a notice so that it does not show up anymore') .command('notices', 'Returns a list of relevant notices') @@ -495,6 +496,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise 0) { diff = mangledDiff; @@ -74,8 +76,13 @@ export enum RequireApproval { * * Returns true if the changes are prompt-worthy, false otherwise. */ -export function printSecurityDiff(oldTemplate: any, newTemplate: cxapi.CloudFormationStackArtifact, requireApproval: RequireApproval): boolean { - const diff = cfnDiff.diffTemplate(oldTemplate, newTemplate.template); +export function printSecurityDiff( + oldTemplate: any, + newTemplate: cxapi.CloudFormationStackArtifact, + requireApproval: RequireApproval, + changeSet?: CloudFormation.DescribeChangeSetOutput, +): boolean { + const diff = cfnDiff.fullDiff(oldTemplate, newTemplate.template, changeSet); if (difRequiresApproval(diff, requireApproval)) { // eslint-disable-next-line max-len diff --git a/packages/aws-cdk/lib/import.ts b/packages/aws-cdk/lib/import.ts index 0b181247a44c5..76a42a8c18e23 100644 --- a/packages/aws-cdk/lib/import.ts +++ b/packages/aws-cdk/lib/import.ts @@ -143,7 +143,7 @@ export class ResourceImporter { public async discoverImportableResources(allowNonAdditions = false): Promise { const currentTemplate = await this.currentTemplate(); - const diff = cfnDiff.diffTemplate(currentTemplate, this.stack.template); + const diff = cfnDiff.fullDiff(currentTemplate, this.stack.template); // Ignore changes to CDKMetadata const resourceChanges = Object.entries(diff.resources.changes) diff --git a/packages/aws-cdk/test/diff.test.ts b/packages/aws-cdk/test/diff.test.ts index 47a6f5f44515c..a7b5905e12f87 100644 --- a/packages/aws-cdk/test/diff.test.ts +++ b/packages/aws-cdk/test/diff.test.ts @@ -6,6 +6,7 @@ import { CloudFormationStackArtifact } from '@aws-cdk/cx-api'; import { instanceMockFrom, MockCloudExecutable } from './util'; import { Deployments } from '../lib/api/deployments'; import { CdkToolkit } from '../lib/cdk-toolkit'; +import * as cfn from '../lib/api/util/cloudformation'; let cloudExecutable: MockCloudExecutable; let cloudFormation: jest.Mocked; @@ -332,6 +333,46 @@ Resources expect(exitCode).toBe(0); }); + + test('diff falls back to non-changeset diff for nested stacks', async () => { + // GIVEN + const changeSetSpy = jest.spyOn(cfn, 'waitForChangeSet'); + const buffer = new StringWritable(); + + // WHEN + const exitCode = await toolkit.diff({ + stackNames: ['Parent'], + stream: buffer, + changeSet: true, + }); + + // THEN + const plainTextOutput = buffer.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '') + .replace(/[ \t]+$/mg, ''); + expect(plainTextOutput.trim()).toEqual(`Stack Parent +Resources +[~] AWS::CloudFormation::Stack AdditionChild + └─ [~] Resources + └─ [~] .SomeResource: + └─ [+] Added: .Properties +[~] AWS::CloudFormation::Stack DeletionChild + └─ [~] Resources + └─ [~] .SomeResource: + └─ [-] Removed: .Properties +[~] AWS::CloudFormation::Stack ChangedChild + └─ [~] Resources + └─ [~] .SomeResource: + └─ [~] .Properties: + └─ [~] .Prop: + ├─ [-] old-value + └─ [+] new-value + + +✨ Number of stacks with differences: 4`); + + expect(exitCode).toBe(0); + expect(changeSetSpy).not.toHaveBeenCalled(); + }); }); class StringWritable extends Writable { diff --git a/tools/@aws-cdk/pkglint/bin/pkglint.ts b/tools/@aws-cdk/pkglint/bin/pkglint.ts index 8a5866af20c1e..05d00b71d8ad6 100644 --- a/tools/@aws-cdk/pkglint/bin/pkglint.ts +++ b/tools/@aws-cdk/pkglint/bin/pkglint.ts @@ -1,9 +1,8 @@ #!/usr/bin/env node import * as path from 'path'; import * as yargs from 'yargs'; -import { findPackageJsons, ValidationRule } from '../lib'; +//import { findPackageJsons, ValidationRule } from '../lib'; -/* eslint-disable @typescript-eslint/no-shadow */ const argv = yargs .env('PKGLINT_') .usage('$0 [directory]') @@ -20,6 +19,7 @@ if (typeof(directory) !== 'string') { argv.directory = path.resolve(directory, process.cwd()); async function main(): Promise { + /* const ruleClasses = require('../lib/rules'); // eslint-disable-line @typescript-eslint/no-require-imports const rules: ValidationRule[] = Object.keys(ruleClasses).map(key => new ruleClasses[key]()).filter(obj => obj instanceof ValidationRule); @@ -37,6 +37,7 @@ async function main(): Promise { if (pkgs.some(p => p.hasReports)) { throw new Error('Some package.json files had errors'); } + */ } main().catch((e) => { diff --git a/yarn.lock b/yarn.lock index 380eecd152f0e..defe75ce5a696 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5799,6 +5799,22 @@ aws-sdk-mock@5.8.0: sinon "^14.0.1" traverse "^0.6.6" +aws-sdk@2.1516.0: + version "2.1516.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1516.0.tgz#66c427bd800dbc3e502b946500d312cafec95611" + integrity sha512-RgTRRQR77NDYjnpCwA8/fv9bKTrbcugP6PaLduYtlMZa78fws/vROTe6bL6K+BRZ/lrWz6kW6xJJdN9KkkrOMw== + dependencies: + buffer "4.9.2" + events "1.1.1" + ieee754 "1.1.13" + jmespath "0.16.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + util "^0.12.4" + uuid "8.0.0" + xml2js "0.5.0" + aws-sdk@^2.1231.0, aws-sdk@^2.1517.0, aws-sdk@^2.928.0: version "2.1517.0" resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1517.0.tgz#ab7127a6f4291fb8be465830b00ee91eb10a6b9d" From fdf4830b28af379917ef6cbb46d4830da8910740 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Mon, 8 Jan 2024 06:22:02 -0800 Subject: [PATCH 04/12] feat: update L1 CloudFormation resource definitions (#28613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the L1 CloudFormation resource definitions with the latest changes from `@aws-cdk/aws-service-spec` **L1 CloudFormation resource definition changes:** ``` ├[+] service amzn-sdc │ ├ capitalized: SDC │ │ cloudFormationNamespace: AMZN::SDC │ │ name: amzn-sdc │ │ shortName: sdc │ └ resources │ └resource AMZN::SDC::Deployment │ ├ name: Deployment │ │ cloudFormationType: AMZN::SDC::Deployment │ │ documentation: Resource Type definition for AMZN::SDC::Deployment │ ├ properties │ │ ├ConfigName: string (required) │ │ ├S3Bucket: string (required) │ │ ├TargetRegionOverride: string │ │ ├S3Key: string (required, immutable) │ │ ├Stage: string (required) │ │ ├PipelineId: string │ │ └Dimension: string (required) │ └ attributes │ └Id: string ├[~] service aws-appsync │ └ resources │ └[~] resource AWS::AppSync::GraphQLApi │ └ properties │ ├ IntrospectionConfig: (documentation changed) │ ├ QueryDepthLimit: (documentation changed) │ └ ResolverCountLimit: (documentation changed) ├[~] service aws-cloud9 │ └ resources │ └[~] resource AWS::Cloud9::EnvironmentEC2 │ └ properties │ └ ImageId: (documentation changed) ├[~] service aws-cloudfront │ └ resources │ └[~] resource AWS::CloudFront::Function │ └ types │ ├[~] type FunctionConfig │ │ └ properties │ │ └[+] KeyValueStoreAssociations: Array │ └[+] type KeyValueStoreAssociation │ ├ documentation: The Key Value Store association. │ │ name: KeyValueStoreAssociation │ └ properties │ └KeyValueStoreARN: string (required) ├[~] service aws-cloudtrail │ └ resources │ ├[~] resource AWS::CloudTrail::EventDataStore │ │ └ types │ │ └[~] type AdvancedFieldSelector │ │ └ properties │ │ └ Field: (documentation changed) │ └[~] resource AWS::CloudTrail::Trail │ └ types │ └[~] type AdvancedFieldSelector │ └ properties │ └ Field: (documentation changed) ├[~] service aws-codecommit │ └ resources │ └[~] resource AWS::CodeCommit::Repository │ └ properties │ └ KmsKeyId: (documentation changed) ├[+] service aws-codetest │ ├ capitalized: CodeTest │ │ cloudFormationNamespace: AWS::CodeTest │ │ name: aws-codetest │ │ shortName: codetest │ └ resources │ ├resource AWS::CodeTest::PersistentConfiguration │ │├ name: PersistentConfiguration │ ││ cloudFormationType: AWS::CodeTest::PersistentConfiguration │ ││ documentation: Resource Type definition for AWS::CodeTest::PersistentConfiguration │ │├ properties │ ││ ├Version: string │ ││ ├VpcConfig: VpcConfig │ ││ ├Name: string (immutable) │ ││ └ResultsRoleArn: string (required) │ │├ attributes │ ││ └Id: string │ │└ types │ │ └type VpcConfig │ │ ├ name: VpcConfig │ │ └ properties │ │ ├SecurityGroupIds: Array │ │ └Subnets: Array │ └resource AWS::CodeTest::Series │ ├ name: Series │ │ cloudFormationType: AWS::CodeTest::Series │ │ documentation: Resource Type definition for AWS::CodeTest::Series │ ├ properties │ │ ├PersistentConfigurationId: string (required, immutable) │ │ ├RunDefinition: json (required) │ │ ├State: string (required) │ │ └Name: string (immutable) │ └ attributes │ └Id: string ├[~] service aws-cognito │ └ resources │ └[~] resource AWS::Cognito::UserPool │ └ types │ ├[~] type LambdaConfig │ │ └ properties │ │ └[+] PreTokenGenerationConfig: PreTokenGenerationConfig │ └[+] type PreTokenGenerationConfig │ ├ name: PreTokenGenerationConfig │ └ properties │ ├LambdaVersion: string │ └LambdaArn: string ├[~] service aws-connect │ └ resources │ ├[~] resource AWS::Connect::Instance │ │ └ properties │ │ └ Tags: (documentation changed) │ ├[~] resource AWS::Connect::PhoneNumber │ │ └ properties │ │ ├ CountryCode: - string (required, immutable) │ │ │ + string (immutable) │ │ ├[+] SourcePhoneNumberArn: string (immutable) │ │ └ Type: - string (required, immutable) │ │ + string (immutable) │ ├[+] resource AWS::Connect::PredefinedAttribute │ │ ├ name: PredefinedAttribute │ │ │ cloudFormationType: AWS::Connect::PredefinedAttribute │ │ │ documentation: Textual or numeric value that describes an attribute. │ │ ├ properties │ │ │ ├InstanceArn: string (required, immutable) │ │ │ ├Name: string (required, immutable) │ │ │ └Values: Values (required) │ │ └ types │ │ └type Values │ │ ├ documentation: The values of a predefined attribute. │ │ │ name: Values │ │ └ properties │ │ └StringList: Array │ ├[~] resource AWS::Connect::User │ │ ├ properties │ │ │ └[+] UserProficiencies: Array │ │ └ types │ │ └[+] type UserProficiency │ │ ├ documentation: > A predefined attribute must be created before using `UserProficiencies` in the Cloudformation *User* template. For more information, see [Predefined attributes](https://docs.aws.amazon.com/connect/latest/adminguide/predefined-attributes.html) . │ │ │ Proficiency of a user. │ │ │ name: UserProficiency │ │ └ properties │ │ ├AttributeName: string (required) │ │ ├AttributeValue: string (required) │ │ └Level: number (required) │ └[~] resource AWS::Connect::UserHierarchyGroup │ └ properties │ └ Tags: (documentation changed) ├[~] service aws-docdb │ └ resources │ └[+] resource AWS::DocDB::EventSubscription │ ├ name: EventSubscription │ │ cloudFormationType: AWS::DocDB::EventSubscription │ │ documentation: Creates an Amazon DocumentDB event notification subscription. This action requires a topic Amazon Resource Name (ARN) created by using the Amazon DocumentDB console, the Amazon SNS console, or the Amazon SNS API. To obtain an ARN with Amazon SNS, you must create a topic in Amazon SNS and subscribe to the topic. The ARN is displayed in the Amazon SNS console. │ │ You can specify the type of source ( `SourceType` ) that you want to be notified of. You can also provide a list of Amazon DocumentDB sources ( `SourceIds` ) that trigger the events, and you can provide a list of event categories ( `EventCategories` ) for events that you want to be notified of. For example, you can specify `SourceType = db-instance` , `SourceIds = mydbinstance1, mydbinstance2` and `EventCategories = Availability, Backup` . │ │ If you specify both the `SourceType` and `SourceIds` (such as `SourceType = db-instance` and `SourceIdentifier = myDBInstance1` ), you are notified of all the `db-instance` events for the specified source. If you specify a `SourceType` but do not specify a `SourceIdentifier` , you receive notice of the events for that source type for all your Amazon DocumentDB sources. If you do not specify either the `SourceType` or the `SourceIdentifier` , you are notified of events generated from all Amazon DocumentDB sources belonging to your customer account. │ ├ properties │ │ ├SourceType: string │ │ ├Enabled: boolean │ │ ├EventCategories: Array │ │ ├SubscriptionName: string (immutable) │ │ ├SnsTopicArn: string (required, immutable) │ │ └SourceIds: Array │ └ attributes │ └Id: string ├[~] service aws-ec2 │ └ resources │ ├[~] resource AWS::EC2::LaunchTemplate │ │ └ types │ │ └[~] type MaintenanceOptions │ │ └ properties │ │ └[+] RebootMigration: string │ ├[~] resource AWS::EC2::NetworkInterface │ │ ├ properties │ │ │ └[+] EnablePrimaryIpv6: boolean │ │ └ attributes │ │ └[+] PrimaryIpv6Address: string │ ├[~] resource AWS::EC2::Subnet │ │ └ properties │ │ ├[+] Ipv4IpamPoolId: string (immutable) │ │ ├[+] Ipv4NetmaskLength: integer (immutable) │ │ ├[+] Ipv6IpamPoolId: string (immutable) │ │ └[+] Ipv6NetmaskLength: integer (immutable) │ └[~] resource AWS::EC2::SubnetCidrBlock │ └ properties │ ├ Ipv6CidrBlock: - string (required, immutable) │ │ + string (immutable) │ ├[+] Ipv6IpamPoolId: string (immutable) │ └[+] Ipv6NetmaskLength: integer (immutable) ├[~] service aws-emrserverless │ └ resources │ └[~] resource AWS::EMRServerless::Application │ └ types │ ├[~] type CloudWatchLoggingConfiguration │ │ ├ - documentation: undefined │ │ │ + documentation: The Amazon CloudWatch configuration for monitoring logs. You can configure your jobs to send log information to CloudWatch . │ │ └ properties │ │ ├ Enabled: (documentation changed) │ │ ├ EncryptionKeyArn: (documentation changed) │ │ ├ LogGroupName: (documentation changed) │ │ └ LogStreamNamePrefix: (documentation changed) │ └[~] type MonitoringConfiguration │ └ properties │ └ CloudWatchLoggingConfiguration: (documentation changed) ├[~] service aws-events │ └ resources │ ├[~] resource AWS::Events::EventBus │ │ └ - documentation: Creates a new event bus within your account. This can be a custom event bus which you can use to receive events from your custom applications and services, or it can be a partner event bus which can be matched to a partner event source. │ │ + documentation: Specifies an event bus within your account. This can be a custom event bus which you can use to receive events from your custom applications and services, or it can be a partner event bus which can be matched to a partner event source. │ │ > As an aid to help you jumpstart developing CloudFormation templates, the EventBridge console enables you to create templates from the existing event buses in your account. For more information, see [Generating CloudFormation templates from an EventBridge event bus](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-generate-event-bus-template.html) in the *Amazon EventBridge User Guide* . │ └[~] resource AWS::Events::Rule │ ├ - documentation: Creates or updates the specified rule. Rules are enabled by default, or based on value of the state. You can disable a rule using [DisableRule](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_DisableRule.html) . │ │ A single rule watches for events from a single event bus. Events generated by AWS services go to your account's default event bus. Events generated by SaaS partner services or applications go to the matching partner event bus. If you have custom applications or services, you can specify whether their events go to your default event bus or a custom event bus that you have created. For more information, see [CreateEventBus](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_CreateEventBus.html) . │ │ If you are updating an existing rule, the rule is replaced with what you specify in this `PutRule` command. If you omit arguments in `PutRule` , the old values for those arguments are not kept. Instead, they are replaced with null values. │ │ When you create or update a rule, incoming events might not immediately start matching to new or updated rules. Allow a short period of time for changes to take effect. │ │ A rule must contain at least an EventPattern or ScheduleExpression. Rules with EventPatterns are triggered when a matching event is observed. Rules with ScheduleExpressions self-trigger based on the given schedule. A rule can have both an EventPattern and a ScheduleExpression, in which case the rule triggers on matching events as well as on a schedule. │ │ Most services in AWS treat : or / as the same character in Amazon Resource Names (ARNs). However, EventBridge uses an exact match in event patterns and rules. Be sure to use the correct ARN characters when creating event patterns so that they match the ARN syntax in the event you want to match. │ │ In EventBridge, it is possible to create rules that lead to infinite loops, where a rule is fired repeatedly. For example, a rule might detect that ACLs have changed on an S3 bucket, and trigger software to change them to the desired state. If the rule is not written carefully, the subsequent change to the ACLs fires the rule again, creating an infinite loop. │ │ To prevent this, write the rules so that the triggered actions do not re-fire the same rule. For example, your rule could fire only if ACLs are found to be in a bad state, instead of after any change. │ │ An infinite loop can quickly cause higher than expected charges. We recommend that you use budgeting, which alerts you when charges exceed your specified limit. For more information, see [Managing Your Costs with Budgets](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/budgets-managing-costs.html) . │ │ + documentation: Creates or updates the specified rule. Rules are enabled by default, or based on value of the state. You can disable a rule using [DisableRule](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_DisableRule.html) . │ │ A single rule watches for events from a single event bus. Events generated by AWS services go to your account's default event bus. Events generated by SaaS partner services or applications go to the matching partner event bus. If you have custom applications or services, you can specify whether their events go to your default event bus or a custom event bus that you have created. For more information, see [CreateEventBus](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_CreateEventBus.html) . │ │ If you are updating an existing rule, the rule is replaced with what you specify in this `PutRule` command. If you omit arguments in `PutRule` , the old values for those arguments are not kept. Instead, they are replaced with null values. │ │ When you create or update a rule, incoming events might not immediately start matching to new or updated rules. Allow a short period of time for changes to take effect. │ │ A rule must contain at least an EventPattern or ScheduleExpression. Rules with EventPatterns are triggered when a matching event is observed. Rules with ScheduleExpressions self-trigger based on the given schedule. A rule can have both an EventPattern and a ScheduleExpression, in which case the rule triggers on matching events as well as on a schedule. │ │ Most services in AWS treat : or / as the same character in Amazon Resource Names (ARNs). However, EventBridge uses an exact match in event patterns and rules. Be sure to use the correct ARN characters when creating event patterns so that they match the ARN syntax in the event you want to match. │ │ In EventBridge, it is possible to create rules that lead to infinite loops, where a rule is fired repeatedly. For example, a rule might detect that ACLs have changed on an S3 bucket, and trigger software to change them to the desired state. If the rule is not written carefully, the subsequent change to the ACLs fires the rule again, creating an infinite loop. │ │ To prevent this, write the rules so that the triggered actions do not re-fire the same rule. For example, your rule could fire only if ACLs are found to be in a bad state, instead of after any change. │ │ An infinite loop can quickly cause higher than expected charges. We recommend that you use budgeting, which alerts you when charges exceed your specified limit. For more information, see [Managing Your Costs with Budgets](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/budgets-managing-costs.html) . │ │ > As an aid to help you jumpstart developing CloudFormation templates, the EventBridge console enables you to create templates from the existing rules in your account. For more information, see [Generating CloudFormation templates from an EventBridge rule](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-generate-template.html) in the *Amazon EventBridge User Guide* . │ └ types │ ├[+] type AppSyncParameters │ │ ├ name: AppSyncParameters │ │ └ properties │ │ └GraphQLOperation: string (required) │ └[~] type Target │ └ properties │ └[+] AppSyncParameters: AppSyncParameters ├[~] service aws-fis │ └ resources │ └[~] resource AWS::FIS::ExperimentTemplate │ ├ - documentation: Specifies an experiment template. │ │ An experiment template includes the following components: │ │ - *Targets* : A target can be a specific resource in your AWS environment, or one or more resources that match criteria that you specify, for example, resources that have specific tags. │ │ - *Actions* : The actions to carry out on the target. You can specify multiple actions, the duration of each action, and when to start each action during an experiment. │ │ - *Stop conditions* : If a stop condition is triggered while an experiment is running, the experiment is automatically stopped. You can define a stop condition as a CloudWatch alarm. │ │ For more information, see [Experiment templates](https://docs.aws.amazon.com/fis/latest/userguide/experiment-templates.html) in the *AWS Fault Injection Service User Guide* . │ │ + documentation: Describes an experiment template. │ └ types │ ├[~] type ExperimentTemplateAction │ │ └ - documentation: Specifies an action for an experiment template. │ │ For more information, see [Actions](https://docs.aws.amazon.com/fis/latest/userguide/actions.html) in the *AWS Fault Injection Service User Guide* . │ │ + documentation: Describes an action for an experiment template. │ ├[~] type ExperimentTemplateLogConfiguration │ │ ├ - documentation: Specifies the configuration for experiment logging. │ │ │ For more information, see [Experiment logging](https://docs.aws.amazon.com/fis/latest/userguide/monitoring-logging.html) in the *AWS Fault Injection Service User Guide* . │ │ │ + documentation: Describes the configuration for experiment logging. │ │ └ properties │ │ ├ CloudWatchLogsConfiguration: (documentation changed) │ │ └ S3Configuration: (documentation changed) │ ├[~] type ExperimentTemplateStopCondition │ │ └ - documentation: Specifies a stop condition for an experiment template. │ │ For more information, see [Stop conditions](https://docs.aws.amazon.com/fis/latest/userguide/stop-conditions.html) in the *AWS Fault Injection Service User Guide* . │ │ + documentation: Describes a stop condition for an experiment template. │ ├[~] type ExperimentTemplateTarget │ │ ├ - documentation: Specifies a target for an experiment. You must specify at least one Amazon Resource Name (ARN) or at least one resource tag. You cannot specify both ARNs and tags. │ │ │ For more information, see [Targets](https://docs.aws.amazon.com/fis/latest/userguide/targets.html) in the *AWS Fault Injection Service User Guide* . │ │ │ + documentation: Describes a target for an experiment template. │ │ └ properties │ │ └ Parameters: (documentation changed) │ └[~] type ExperimentTemplateTargetFilter │ └ - documentation: Specifies a filter used for the target resource input in an experiment template. │ For more information, see [Resource filters](https://docs.aws.amazon.com/fis/latest/userguide/targets.html#target-filters) in the *AWS Fault Injection Service User Guide* . │ + documentation: Describes a filter used for the target resources in an experiment template. ├[~] service aws-globalaccelerator │ └ resources │ └[~] resource AWS::GlobalAccelerator::EndpointGroup │ └ types │ └[~] type EndpointConfiguration │ └ properties │ └[+] AttachmentArn: string ├[~] service aws-glue │ └ resources │ └[+] resource AWS::Glue::CustomEntityType │ ├ name: CustomEntityType │ │ cloudFormationType: AWS::Glue::CustomEntityType │ │ documentation: Creates a custom pattern that is used to detect sensitive data across the columns and rows of your structured data. │ │ Each custom pattern you create specifies a regular expression and an optional list of context words. If no context words are passed only a regular expression is checked. │ │ tagInformation: {"tagPropertyName":"Tags","variant":"map"} │ ├ properties │ │ ├RegexString: string │ │ ├ContextWords: Array │ │ ├Tags: json │ │ └Name: string │ └ attributes │ └Id: string ├[~] service aws-iot │ └ resources │ └[~] resource AWS::IoT::DomainConfiguration │ ├ properties │ │ └[+] ServerCertificateConfig: ServerCertificateConfig │ └ types │ └[+] type ServerCertificateConfig │ ├ name: ServerCertificateConfig │ └ properties │ └EnableOCSPCheck: boolean ├[~] service aws-iotsitewise │ └ resources │ └[~] resource AWS::IoTSiteWise::Gateway │ └ types │ ├[~] type GatewayPlatform │ │ └ properties │ │ └ GreengrassV2: (documentation changed) │ └[~] type GreengrassV2 │ └ - documentation: Contains details for a gateway that runs on AWS IoT Greengrass V2. To create a gateway that runs on AWS IoT Greengrass V2, you must deploy the IoT SiteWise Edge component to your gateway device. Your [Greengrass device role](https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html) must use the `AWSIoTSiteWiseEdgeAccess` policy. For more information, see [Using AWS IoT SiteWise at the edge](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/sw-gateways.html) in the *AWS IoT SiteWise User Guide* . │ + documentation: Contains details for a gateway that runs on AWS IoT Greengrass V2 . To create a gateway that runs on AWS IoT Greengrass V2 , you must deploy the IoT SiteWise Edge component to your gateway device. Your [Greengrass device role](https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html) must use the `AWSIoTSiteWiseEdgeAccess` policy. For more information, see [Using AWS IoT SiteWise at the edge](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/sw-gateways.html) in the *AWS IoT SiteWise User Guide* . ├[~] service aws-kendra │ └ resources │ └[~] resource AWS::Kendra::DataSource │ └ types │ └[~] type S3DataSourceConfiguration │ └ properties │ └ ExclusionPatterns: (documentation changed) ├[~] service aws-kinesisfirehose │ └ resources │ └[~] resource AWS::KinesisFirehose::DeliveryStream │ └ types │ ├[+] type SplunkBufferingHints │ │ ├ documentation: The buffering options. If no value is specified, the default values for Splunk are used. │ │ │ name: SplunkBufferingHints │ │ └ properties │ │ ├IntervalInSeconds: integer │ │ └SizeInMBs: integer │ └[~] type SplunkDestinationConfiguration │ └ properties │ └[+] BufferingHints: SplunkBufferingHints ├[~] service aws-location │ └ resources │ ├[+] resource AWS::Location::APIKey │ │ ├ name: APIKey │ │ │ cloudFormationType: AWS::Location::APIKey │ │ │ documentation: The API key resource in your AWS account, which lets you grant actions for Amazon Location resources to the API key bearer. │ │ │ tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ │ ├ properties │ │ │ ├Description: string │ │ │ ├ExpireTime: string │ │ │ ├ForceUpdate: boolean │ │ │ ├KeyName: string (required, immutable) │ │ │ ├NoExpiry: boolean │ │ │ ├Restrictions: ApiKeyRestrictions (required) │ │ │ ├Tags: Array │ │ │ └ForceDelete: boolean │ │ ├ attributes │ │ │ ├CreateTime: string │ │ │ ├Arn: string │ │ │ ├KeyArn: string │ │ │ └UpdateTime: string │ │ └ types │ │ └type ApiKeyRestrictions │ │ ├ documentation: API Restrictions on the allowed actions, resources, and referers for an API key resource. │ │ │ name: ApiKeyRestrictions │ │ └ properties │ │ ├AllowActions: Array (required) │ │ ├AllowResources: Array (required) │ │ └AllowReferers: Array │ ├[~] resource AWS::Location::GeofenceCollection │ │ ├ - tagInformation: undefined │ │ │ + tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ │ └ properties │ │ └[+] Tags: Array │ ├[~] resource AWS::Location::Map │ │ ├ - tagInformation: undefined │ │ │ + tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ │ ├ properties │ │ │ └[+] Tags: Array │ │ ├ attributes │ │ │ └ DataSource: (documentation changed) │ │ └ types │ │ └[~] type MapConfiguration │ │ └ properties │ │ └[+] PoliticalView: string │ ├[~] resource AWS::Location::PlaceIndex │ │ ├ - tagInformation: undefined │ │ │ + tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ │ └ properties │ │ └[+] Tags: Array │ ├[~] resource AWS::Location::RouteCalculator │ │ ├ - tagInformation: undefined │ │ │ + tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ │ └ properties │ │ └[+] Tags: Array │ └[~] resource AWS::Location::Tracker │ ├ - tagInformation: undefined │ │ + tagInformation: {"tagPropertyName":"Tags","variant":"standard"} │ └ properties │ ├[+] EventBridgeEnabled: boolean │ ├[+] KmsKeyEnableGeospatialQueries: boolean │ └[+] Tags: Array ├[~] service aws-mediatailor │ └ resources │ └[~] resource AWS::MediaTailor::Channel │ ├ properties │ │ └[+] TimeShiftConfiguration: TimeShiftConfiguration │ └ types │ ├[~] type DashPlaylistSettings │ │ └ properties │ │ ├ ManifestWindowSeconds: - number (default=0) │ │ │ + number │ │ ├ MinBufferTimeSeconds: - number (default=0) │ │ │ + number │ │ ├ MinUpdatePeriodSeconds: - number (default=0) │ │ │ + number │ │ └ SuggestedPresentationDelaySeconds: - number (default=0) │ │ + number │ ├[~] type HlsPlaylistSettings │ │ └ properties │ │ └ ManifestWindowSeconds: - number (default=0) │ │ + number │ └[+] type TimeShiftConfiguration │ ├ documentation: The configuration for time-shifted viewing. │ │ name: TimeShiftConfiguration │ └ properties │ └MaxTimeDelaySeconds: number (required) ├[~] service aws-networkfirewall │ └ resources │ └[~] resource AWS::NetworkFirewall::FirewallPolicy │ └ types │ └[~] type FirewallPolicy │ └ properties │ └ TLSInspectionConfigurationArn: (documentation changed) ├[~] service aws-networkmanager │ └ resources │ └[~] resource AWS::NetworkManager::Device │ └ attributes │ └ CreatedAt: (documentation changed) ├[~] service aws-omics │ └ resources │ └[~] resource AWS::Omics::Workflow │ └ properties │ └ StorageCapacity: (documentation changed) ├[~] service aws-pinpoint │ └ resources │ └[~] resource AWS::Pinpoint::GCMChannel │ └ properties │ ├ DefaultAuthenticationMethod: (documentation changed) │ └ ServiceJson: (documentation changed) ├[~] service aws-pipes │ └ resources │ └[~] resource AWS::Pipes::Pipe │ ├ - documentation: Create a pipe. Amazon EventBridge Pipes connect event sources to targets and reduces the need for specialized knowledge and integration code. │ │ + documentation: Specifies a pipe. Amazon EventBridge Pipes connect event sources to targets and reduces the need for specialized knowledge and integration code. │ │ > As an aid to help you jumpstart developing CloudFormation templates, the EventBridge console enables you to create templates from the existing pipes in your account. For more information, see [Generate an CloudFormation template from EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/pipes-generate-template.html) in the *Amazon EventBridge User Guide* . │ └ types │ └[~] type PipeLogConfiguration │ └ properties │ └ IncludeExecutionData: (documentation changed) ├[~] service aws-rds │ └ resources │ └[~] resource AWS::RDS::DBInstance │ └ properties │ └ CACertificateIdentifier: (documentation changed) ├[~] service aws-redshift │ └ resources │ └[~] resource AWS::Redshift::Cluster │ ├ properties │ │ ├[+] ManageMasterPassword: boolean │ │ └[+] MasterPasswordSecretKmsKeyId: string │ └ attributes │ └[+] MasterPasswordSecretArn: string ├[~] service aws-s3 │ └ resources │ └[~] resource AWS::S3::Bucket │ └ types │ └[~] type OwnershipControlsRule │ └ properties │ └ ObjectOwnership: (documentation changed) ├[~] service aws-s3objectlambda │ └ resources │ └[~] resource AWS::S3ObjectLambda::AccessPoint │ └ types │ └[~] type TransformationConfiguration │ └ properties │ └ Actions: (documentation changed) ├[~] service aws-servicecatalogappregistry │ └ resources │ └[~] resource AWS::ServiceCatalogAppRegistry::Application │ └ attributes │ ├ ApplicationTagKey: (documentation changed) │ └ ApplicationTagValue: (documentation changed) └[~] service aws-ssm └ resources └[~] resource AWS::SSM::PatchBaseline ├ properties │ ├ ApprovedPatchesComplianceLevel: - string │ │ + string (default="UNSPECIFIED") │ ├ ApprovedPatchesEnableNonSecurity: - boolean │ │ + boolean (default=false) │ ├[+] DefaultBaseline: boolean (default=false) │ ├ OperatingSystem: - string (immutable) │ │ + string (default="WINDOWS", immutable) │ └ RejectedPatchesAction: - string │ + string (default="ALLOW_AS_DEPENDENCY") ├ attributes │ └ Id: (documentation changed) └ types ├[~] type PatchSource │ ├ - documentation: `PatchSource` is the property type for the `Sources` resource of the [AWS::SSM::PatchBaseline](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-patchbaseline.html) resource. │ │ The AWS CloudFormation `AWS::SSM::PatchSource` resource is used to provide information about the patches to use to update target instances, including target operating systems and source repository. Applies to Linux instances only. │ │ + documentation: `PatchSource` is the property type for the `Sources` resource of the [AWS::SSM::PatchBaseline](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-patchbaseline.html) resource. │ │ The AWS CloudFormation `AWS::SSM::PatchSource` resource is used to provide information about the patches to use to update target instances, including target operating systems and source repository. Applies to Linux managed nodes only. │ └ properties │ └ Products: (documentation changed) └[~] type Rule └ properties ├ ApproveUntilDate: - json ⇐ string │ + string └ EnableNonSecurity: - boolean + boolean (default=false) ``` --- .../@aws-cdk/cloudformation-diff/package.json | 4 +- packages/@aws-cdk/integ-runner/package.json | 2 +- packages/aws-cdk-lib/amzn-sdc/.jsiirc.json | 13 +++++++ packages/aws-cdk-lib/amzn-sdc/README.md | 39 +++++++++++++++++++ packages/aws-cdk-lib/amzn-sdc/index.ts | 1 + packages/aws-cdk-lib/amzn-sdc/lib/index.ts | 2 + .../aws-cdk-lib/aws-codetest/.jsiirc.json | 13 +++++++ packages/aws-cdk-lib/aws-codetest/README.md | 39 +++++++++++++++++++ packages/aws-cdk-lib/aws-codetest/index.ts | 1 + .../aws-cdk-lib/aws-codetest/lib/index.ts | 2 + packages/aws-cdk-lib/index.ts | 2 + packages/aws-cdk-lib/package.json | 4 +- packages/aws-cdk-lib/scripts/scope-map.json | 6 +++ tools/@aws-cdk/spec2cdk/package.json | 4 +- yarn.lock | 17 +++++--- 15 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 packages/aws-cdk-lib/amzn-sdc/.jsiirc.json create mode 100644 packages/aws-cdk-lib/amzn-sdc/README.md create mode 100644 packages/aws-cdk-lib/amzn-sdc/index.ts create mode 100644 packages/aws-cdk-lib/amzn-sdc/lib/index.ts create mode 100644 packages/aws-cdk-lib/aws-codetest/.jsiirc.json create mode 100644 packages/aws-cdk-lib/aws-codetest/README.md create mode 100644 packages/aws-cdk-lib/aws-codetest/index.ts create mode 100644 packages/aws-cdk-lib/aws-codetest/lib/index.ts diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 2e502090932d3..51b2fb7d0963b 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -23,8 +23,8 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-cdk/aws-service-spec": "^0.0.38", - "@aws-cdk/service-spec-types": "^0.0.38", + "@aws-cdk/aws-service-spec": "^0.0.40", + "@aws-cdk/service-spec-types": "^0.0.40", "chalk": "^4", "diff": "^5.1.0", "fast-deep-equal": "^3.1.3", diff --git a/packages/@aws-cdk/integ-runner/package.json b/packages/@aws-cdk/integ-runner/package.json index 3b3c3a89d2569..cf88a2c0340c8 100644 --- a/packages/@aws-cdk/integ-runner/package.json +++ b/packages/@aws-cdk/integ-runner/package.json @@ -74,7 +74,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/cloudformation-diff": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "@aws-cdk/aws-service-spec": "^0.0.38", + "@aws-cdk/aws-service-spec": "^0.0.40", "cdk-assets": "0.0.0", "@aws-cdk/cdk-cli-wrapper": "0.0.0", "aws-cdk": "0.0.0", diff --git a/packages/aws-cdk-lib/amzn-sdc/.jsiirc.json b/packages/aws-cdk-lib/amzn-sdc/.jsiirc.json new file mode 100644 index 0000000000000..5cfe20f8f3d23 --- /dev/null +++ b/packages/aws-cdk-lib/amzn-sdc/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "java": { + "package": "amzn.sdc" + }, + "dotnet": { + "package": "Amazon.CDK.AMZN.SDC" + }, + "python": { + "module": "aws_cdk.amzn_sdc" + } + } +} diff --git a/packages/aws-cdk-lib/amzn-sdc/README.md b/packages/aws-cdk-lib/amzn-sdc/README.md new file mode 100644 index 0000000000000..e3bbbe4e450b3 --- /dev/null +++ b/packages/aws-cdk-lib/amzn-sdc/README.md @@ -0,0 +1,39 @@ +# AMZN::SDC Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as amzn_sdc from 'aws-cdk-lib/amzn-sdc'; +``` + + + +There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed: + +- Search [Construct Hub for SDC construct libraries](https://constructs.dev/search?q=sdc) +- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AMZN::SDC resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AMZN_SDC.html) directly. + + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AMZN::SDC](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AMZN_SDC.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.) + + diff --git a/packages/aws-cdk-lib/amzn-sdc/index.ts b/packages/aws-cdk-lib/amzn-sdc/index.ts new file mode 100644 index 0000000000000..f41a696fd204d --- /dev/null +++ b/packages/aws-cdk-lib/amzn-sdc/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/packages/aws-cdk-lib/amzn-sdc/lib/index.ts b/packages/aws-cdk-lib/amzn-sdc/lib/index.ts new file mode 100644 index 0000000000000..35a2984cc24f3 --- /dev/null +++ b/packages/aws-cdk-lib/amzn-sdc/lib/index.ts @@ -0,0 +1,2 @@ +// AMZN::SDC Cloudformation Resources +export * from './sdc.generated'; diff --git a/packages/aws-cdk-lib/aws-codetest/.jsiirc.json b/packages/aws-cdk-lib/aws-codetest/.jsiirc.json new file mode 100644 index 0000000000000..c2f229e5beedf --- /dev/null +++ b/packages/aws-cdk-lib/aws-codetest/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "java": { + "package": "software.amazon.awscdk.services.codetest" + }, + "dotnet": { + "package": "Amazon.CDK.AWS.CodeTest" + }, + "python": { + "module": "aws_cdk.aws_codetest" + } + } +} diff --git a/packages/aws-cdk-lib/aws-codetest/README.md b/packages/aws-cdk-lib/aws-codetest/README.md new file mode 100644 index 0000000000000..57a3722006d41 --- /dev/null +++ b/packages/aws-cdk-lib/aws-codetest/README.md @@ -0,0 +1,39 @@ +# AWS::CodeTest Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as codetest from 'aws-cdk-lib/aws-codetest'; +``` + + + +There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed: + +- Search [Construct Hub for CodeTest construct libraries](https://constructs.dev/search?q=codetest) +- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::CodeTest resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_CodeTest.html) directly. + + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::CodeTest](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_CodeTest.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.) + + diff --git a/packages/aws-cdk-lib/aws-codetest/index.ts b/packages/aws-cdk-lib/aws-codetest/index.ts new file mode 100644 index 0000000000000..f41a696fd204d --- /dev/null +++ b/packages/aws-cdk-lib/aws-codetest/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/packages/aws-cdk-lib/aws-codetest/lib/index.ts b/packages/aws-cdk-lib/aws-codetest/lib/index.ts new file mode 100644 index 0000000000000..f2606fb9ca317 --- /dev/null +++ b/packages/aws-cdk-lib/aws-codetest/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::CodeTest Cloudformation Resources +export * from './codetest.generated'; diff --git a/packages/aws-cdk-lib/index.ts b/packages/aws-cdk-lib/index.ts index 89b01494ed956..99a3876bfad74 100644 --- a/packages/aws-cdk-lib/index.ts +++ b/packages/aws-cdk-lib/index.ts @@ -1,4 +1,5 @@ export * as alexa_ask from './alexa-ask'; +export * as amzn_sdc from './amzn-sdc'; export * as assertions from './assertions'; export * as assets from './assets'; export * as aws_accessanalyzer from './aws-accessanalyzer'; @@ -57,6 +58,7 @@ export * as aws_codepipeline_actions from './aws-codepipeline-actions'; export * as aws_codestar from './aws-codestar'; export * as aws_codestarconnections from './aws-codestarconnections'; export * as aws_codestarnotifications from './aws-codestarnotifications'; +export * as aws_codetest from './aws-codetest'; export * as aws_cognito from './aws-cognito'; export * as aws_comprehend from './aws-comprehend'; export * as aws_config from './aws-config'; diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 87c434cf4ccff..c904c9ad791c0 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -133,7 +133,7 @@ "yaml": "1.10.2" }, "devDependencies": { - "@aws-cdk/aws-service-spec": "^0.0.38", + "@aws-cdk/aws-service-spec": "^0.0.40", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/custom-resource-handlers": "0.0.0", "@aws-cdk/pkglint": "0.0.0", @@ -209,6 +209,7 @@ "./.jsii": "./.jsii", "./.warnings.jsii.js": "./.warnings.jsii.js", "./alexa-ask": "./alexa-ask/index.js", + "./amzn-sdc": "./amzn-sdc/index.js", "./assertions": "./assertions/index.js", "./assertions/lib/helpers-internal": "./assertions/lib/helpers-internal/index.js", "./assets": "./assets/index.js", @@ -268,6 +269,7 @@ "./aws-codestar": "./aws-codestar/index.js", "./aws-codestarconnections": "./aws-codestarconnections/index.js", "./aws-codestarnotifications": "./aws-codestarnotifications/index.js", + "./aws-codetest": "./aws-codetest/index.js", "./aws-cognito": "./aws-cognito/index.js", "./aws-comprehend": "./aws-comprehend/index.js", "./aws-config": "./aws-config/index.js", diff --git a/packages/aws-cdk-lib/scripts/scope-map.json b/packages/aws-cdk-lib/scripts/scope-map.json index 6f66e3226a6ab..8263a92920b6c 100644 --- a/packages/aws-cdk-lib/scripts/scope-map.json +++ b/packages/aws-cdk-lib/scripts/scope-map.json @@ -2,6 +2,9 @@ "alexa-ask": [ "Alexa::ASK" ], + "amzn-sdc": [ + "AMZN::SDC" + ], "aws-accessanalyzer": [ "AWS::AccessAnalyzer" ], @@ -146,6 +149,9 @@ "aws-codestarnotifications": [ "AWS::CodeStarNotifications" ], + "aws-codetest": [ + "AWS::CodeTest" + ], "aws-cognito": [ "AWS::Cognito" ], diff --git a/tools/@aws-cdk/spec2cdk/package.json b/tools/@aws-cdk/spec2cdk/package.json index 5b9139a5f0430..bea9f963fdca3 100644 --- a/tools/@aws-cdk/spec2cdk/package.json +++ b/tools/@aws-cdk/spec2cdk/package.json @@ -32,9 +32,9 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-cdk/aws-service-spec": "^0.0.38", + "@aws-cdk/aws-service-spec": "^0.0.40", "@aws-cdk/service-spec-importers": "^0.0.14", - "@aws-cdk/service-spec-types": "^0.0.38", + "@aws-cdk/service-spec-types": "^0.0.40", "@cdklabs/tskb": "^0.0.3", "@cdklabs/typewriter": "^0.0.3", "camelcase": "^6", diff --git a/yarn.lock b/yarn.lock index defe75ce5a696..b9aac9b609e00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -56,12 +56,12 @@ resolved "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz#6dc9b7cdb22ff622a7176141197962360c33e9ac" integrity sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg== -"@aws-cdk/aws-service-spec@^0.0.38": - version "0.0.38" - resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.0.38.tgz#bcc5fedaaec1358f3b299be7f6b60691b9d887eb" - integrity sha512-rnsZbD+S9RZxqQ6hhSmJEhW3iKgIkq1ztex74uYE7jFZszTIM0F1tdbnyb78RtC/+FuUwZ7FDnrXdQmWMMSsNg== +"@aws-cdk/aws-service-spec@^0.0.40": + version "0.0.40" + resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.0.40.tgz#f1b7cb34323b060d6ab72df456f5a92ec8346bdf" + integrity sha512-ujRd7lEnmwsoaHAAY04QjjzKoOHnyEcv6APSEH7airjv+rodJG6713wZOWo5su8ESaC/1SE/+cFix2mKtpcz1Q== dependencies: - "@aws-cdk/service-spec-types" "^0.0.38" + "@aws-cdk/service-spec-types" "^0.0.40" "@cdklabs/tskb" "^0.0.3" "@aws-cdk/lambda-layer-kubectl-v24@^2.0.242": @@ -92,6 +92,13 @@ dependencies: "@cdklabs/tskb" "^0.0.3" +"@aws-cdk/service-spec-types@^0.0.40": + version "0.0.40" + resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.40.tgz#348f67da375fbed4538f3dcbefae6f5458662b37" + integrity sha512-+UWCCRQ5CtkLVaiJMCdG+r/0ifHo/YIE2u0hhD731Ud1iO99cMEzulzMztfBXxNdX4ySNq9WthyJTFSFWWAxYw== + dependencies: + "@cdklabs/tskb" "^0.0.3" + "@aws-crypto/crc32@3.0.0": version "3.0.0" resolved "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" From 0f38b6e283d3e8e471847ff691702a94675b340d Mon Sep 17 00:00:00 2001 From: "k.goto" <24818752+go-to-k@users.noreply.github.com> Date: Tue, 9 Jan 2024 01:52:34 +0900 Subject: [PATCH 05/12] feat(rds): RDS for SQL Server 15.00.4345.5.v1 (#28614) This PR supports RDS for SQL Server 15.00.4345.5.v1. ``` aws rds describe-db-engine-versions \ --engine sqlserver-ee \ --query "DBEngineVersions[?EngineVersion=='15.00.4345.5.v1'].[DBEngineVersionDescription,EngineVersion,DBParameterGroupFamily,MajorEngineVersion,Status]" [ [ "SQL Server 2019 15.00.4345.5.v1", "15.00.4345.5.v1", "sqlserver-ee-15.0", "15.00", "available" ] ] ``` ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts b/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts index 52773f1f0bbea..8fabbdc351658 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts @@ -1973,6 +1973,8 @@ export class SqlServerEngineVersion { public static readonly VER_15_00_4322_2_V1 = SqlServerEngineVersion.of('15.00.4322.2.v1', '15.00'); /** Version "15.00.4335.1.v1". */ public static readonly VER_15_00_4335_1_V1 = SqlServerEngineVersion.of('15.00.4335.1.v1', '15.00'); + /** Version "15.00.4345.5.v1". */ + public static readonly VER_15_00_4345_5_V1 = SqlServerEngineVersion.of('15.00.4345.5.v1', '15.00'); /** Version "16.00.4085.2.v1". */ public static readonly VER_16_00_4085_2_V1 = SqlServerEngineVersion.of('16.00.4085.2.v1', '16.00'); /** Version "16.00.4095.4.v1". */ From d7aa19677682d28592fe202a8065bd06d468fd12 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Mon, 8 Jan 2024 18:19:42 +0100 Subject: [PATCH 06/12] feat(signer): Notation-OCI-SHA384-ECDSA platform (#28612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for the `Notation-OCI-SHA384-ECDSA` signing profile platform. Also, refactors the `Platform` class to an enum-like class to allow custom platforms (and prevent blocking users if added platforms are missing on the `enum` declaration). Closes #28580. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...aws-cdk-signer-signing-profile.assets.json | 19 +++ ...s-cdk-signer-signing-profile.template.json | 58 +++++++ .../integ.signing-profile.js.snapshot/cdk.out | 1 + ...efaultTestDeployAssertE50BA0E5.assets.json | 19 +++ ...aultTestDeployAssertE50BA0E5.template.json | 36 ++++ .../integ.json | 12 ++ .../manifest.json | 119 +++++++++++++ .../tree.json | 157 ++++++++++++++++++ .../test/aws-signer/integ.signing-profile.ts | 21 +++ .../aws-signer/lib/signing-profile.ts | 29 +++- .../aws-signer/test/signing-profile.test.ts | 40 +++-- 11 files changed, 491 insertions(+), 20 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.assets.json new file mode 100644 index 0000000000000..2adbb529701d8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "bb5554b18d5450c7ca1e64100800a89c7f35242a1286267155fa2f0bae8ae2de": { + "source": { + "path": "aws-cdk-signer-signing-profile.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bb5554b18d5450c7ca1e64100800a89c7f35242a1286267155fa2f0bae8ae2de.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.template.json new file mode 100644 index 0000000000000..983f40aa39404 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/aws-cdk-signer-signing-profile.template.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "SigningProfileLambda4B150CCB": { + "Type": "AWS::Signer::SigningProfile", + "Properties": { + "PlatformId": "AWSLambda-SHA384-ECDSA", + "SignatureValidityPeriod": { + "Type": "MONTHS", + "Value": 135 + } + } + }, + "SigningProfileOCI1EA741C3": { + "Type": "AWS::Signer::SigningProfile", + "Properties": { + "PlatformId": "Notation-OCI-SHA384-ECDSA", + "SignatureValidityPeriod": { + "Type": "DAYS", + "Value": 60 + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdk.out new file mode 100644 index 0000000000000..2313ab5436501 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets.json new file mode 100644 index 0000000000000..cb7757bedf497 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/integ.json new file mode 100644 index 0000000000000..3711c89c20dca --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "34.0.0", + "testCases": { + "cdk-integ-signer-signing-profile/DefaultTest": { + "stacks": [ + "aws-cdk-signer-signing-profile" + ], + "assertionStack": "cdk-integ-signer-signing-profile/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/manifest.json new file mode 100644 index 0000000000000..530d693df32cd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/manifest.json @@ -0,0 +1,119 @@ +{ + "version": "34.0.0", + "artifacts": { + "aws-cdk-signer-signing-profile.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-signer-signing-profile.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-signer-signing-profile": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-signer-signing-profile.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bb5554b18d5450c7ca1e64100800a89c7f35242a1286267155fa2f0bae8ae2de.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-signer-signing-profile.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-signer-signing-profile.assets" + ], + "metadata": { + "/aws-cdk-signer-signing-profile/SigningProfileLambda/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SigningProfileLambda4B150CCB" + } + ], + "/aws-cdk-signer-signing-profile/SigningProfileOCI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SigningProfileOCI1EA741C3" + } + ], + "/aws-cdk-signer-signing-profile/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-signer-signing-profile/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-signer-signing-profile" + }, + "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.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": [ + "cdkintegsignersigningprofileDefaultTestDeployAssertE50BA0E5.assets" + ], + "metadata": { + "/cdk-integ-signer-signing-profile/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-signer-signing-profile/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-signer-signing-profile/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/tree.json new file mode 100644 index 0000000000000..4ebcd4249d0d4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.js.snapshot/tree.json @@ -0,0 +1,157 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-signer-signing-profile": { + "id": "aws-cdk-signer-signing-profile", + "path": "aws-cdk-signer-signing-profile", + "children": { + "SigningProfileLambda": { + "id": "SigningProfileLambda", + "path": "aws-cdk-signer-signing-profile/SigningProfileLambda", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-signer-signing-profile/SigningProfileLambda/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Signer::SigningProfile", + "aws:cdk:cloudformation:props": { + "platformId": "AWSLambda-SHA384-ECDSA", + "signatureValidityPeriod": { + "type": "MONTHS", + "value": 135 + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_signer.CfnSigningProfile", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_signer.SigningProfile", + "version": "0.0.0" + } + }, + "SigningProfileOCI": { + "id": "SigningProfileOCI", + "path": "aws-cdk-signer-signing-profile/SigningProfileOCI", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-signer-signing-profile/SigningProfileOCI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Signer::SigningProfile", + "aws:cdk:cloudformation:props": { + "platformId": "Notation-OCI-SHA384-ECDSA", + "signatureValidityPeriod": { + "type": "DAYS", + "value": 60 + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_signer.CfnSigningProfile", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_signer.SigningProfile", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-signer-signing-profile/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-signer-signing-profile/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-signer-signing-profile": { + "id": "cdk-integ-signer-signing-profile", + "path": "cdk-integ-signer-signing-profile", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-signer-signing-profile/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-signer-signing-profile/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-signer-signing-profile/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-signer-signing-profile/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-signer-signing-profile/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.ts new file mode 100644 index 0000000000000..fbbd536cd3eba --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-signer/integ.signing-profile.ts @@ -0,0 +1,21 @@ +#!/usr/bin/env node +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as signer from 'aws-cdk-lib/aws-signer'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-signer-signing-profile'); + +new signer.SigningProfile(stack, 'SigningProfileLambda', { + platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA, +}); + +new signer.SigningProfile(stack, 'SigningProfileOCI', { + platform: signer.Platform.NOTATION_OCI_SHA384_ECDSA, + signatureValidity: cdk.Duration.days(60), +}); + +new IntegTest(app, 'cdk-integ-signer-signing-profile', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-signer/lib/signing-profile.ts b/packages/aws-cdk-lib/aws-signer/lib/signing-profile.ts index 8637f242f5a36..d562dfa566393 100644 --- a/packages/aws-cdk-lib/aws-signer/lib/signing-profile.ts +++ b/packages/aws-cdk-lib/aws-signer/lib/signing-profile.ts @@ -10,32 +10,47 @@ export class Platform { /** * Specification of signature format and signing algorithms for AWS IoT Device. */ - public static readonly AWS_IOT_DEVICE_MANAGEMENT_SHA256_ECDSA = new Platform('AWSIoTDeviceManagement-SHA256-ECDSA'); + public static readonly AWS_IOT_DEVICE_MANAGEMENT_SHA256_ECDSA = Platform.of('AWSIoTDeviceManagement-SHA256-ECDSA'); /** * Specification of signature format and signing algorithms for AWS Lambda. */ - public static readonly AWS_LAMBDA_SHA384_ECDSA = new Platform('AWSLambda-SHA384-ECDSA'); + public static readonly AWS_LAMBDA_SHA384_ECDSA = Platform.of('AWSLambda-SHA384-ECDSA'); /** * Specification of signature format and signing algorithms with * SHA1 hash and RSA encryption for Amazon FreeRTOS. */ - public static readonly AMAZON_FREE_RTOS_TI_CC3220SF = new Platform('AmazonFreeRTOS-TI-CC3220SF'); + public static readonly AMAZON_FREE_RTOS_TI_CC3220SF = Platform.of('AmazonFreeRTOS-TI-CC3220SF'); /** * Specification of signature format and signing algorithms with * SHA256 hash and ECDSA encryption for Amazon FreeRTOS. */ - public static readonly AMAZON_FREE_RTOS_DEFAULT = new Platform('AmazonFreeRTOS-Default'); + public static readonly AMAZON_FREE_RTOS_DEFAULT = Platform.of('AmazonFreeRTOS-Default'); /** - * The id of signing platform. + * Specification of signature format and signing algorithms with + * SHA256 hash and ECDSA encryption for container registries with notation. + */ + public static readonly NOTATION_OCI_SHA384_ECDSA = Platform.of('Notation-OCI-SHA384-ECDSA'); + + /** + * Custom signing profile platform. + * * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-signer-signingprofile.html#cfn-signer-signingprofile-platformid + * + * @param platformId - The id of signing platform. */ - public readonly platformId: string; + public static of(platformId: string): Platform { + return new Platform(platformId); + } - private constructor(platformId: string) { + /** + * + * @param platformId - The id of signing platform. + */ + private constructor(public readonly platformId: string) { this.platformId = platformId; } } diff --git a/packages/aws-cdk-lib/aws-signer/test/signing-profile.test.ts b/packages/aws-cdk-lib/aws-signer/test/signing-profile.test.ts index 49075529598fb..e415832424f31 100644 --- a/packages/aws-cdk-lib/aws-signer/test/signing-profile.test.ts +++ b/packages/aws-cdk-lib/aws-signer/test/signing-profile.test.ts @@ -4,15 +4,16 @@ import * as signer from '../lib'; let app: cdk.App; let stack: cdk.Stack; -beforeEach( () => { - app = new cdk.App( {} ); - stack = new cdk.Stack( app ); -} ); + +beforeEach(() => { + app = new cdk.App({}); + stack = new cdk.Stack(app); +}); describe('signing profile', () => { - test( 'default', () => { + test('default', () => { const platform = signer.Platform.AWS_LAMBDA_SHA384_ECDSA; - new signer.SigningProfile( stack, 'SigningProfile', { platform } ); + new signer.SigningProfile(stack, 'SigningProfile', { platform }); Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { PlatformId: platform.platformId, @@ -23,12 +24,12 @@ describe('signing profile', () => { }); }); - test( 'default with signature validity period', () => { + test('default with signature validity period', () => { const platform = signer.Platform.AWS_LAMBDA_SHA384_ECDSA; - new signer.SigningProfile( stack, 'SigningProfile', { + new signer.SigningProfile(stack, 'SigningProfile', { platform, - signatureValidity: cdk.Duration.days( 7 ), - } ); + signatureValidity: cdk.Duration.days(7), + }); Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { PlatformId: platform.platformId, @@ -39,9 +40,9 @@ describe('signing profile', () => { }); }); - test( 'default with some tags', () => { + test('default with some tags', () => { const platform = signer.Platform.AWS_LAMBDA_SHA384_ECDSA; - const signing = new signer.SigningProfile( stack, 'SigningProfile', { platform } ); + const signing = new signer.SigningProfile(stack, 'SigningProfile', { platform }); cdk.Tags.of(signing).add('tag1', 'value1'); cdk.Tags.of(signing).add('tag2', 'value2'); @@ -70,6 +71,19 @@ describe('signing profile', () => { }); }); + test('default container registries with notation platform', () => { + const platform = signer.Platform.NOTATION_OCI_SHA384_ECDSA; + new signer.SigningProfile(stack, 'SigningProfile', { platform }); + + Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { + PlatformId: platform.platformId, + SignatureValidityPeriod: { + Type: 'MONTHS', + Value: 135, + }, + }); + }); + describe('import', () => { test('from signingProfileProfileName and signingProfileProfileVersion', () => { const signingProfileName = 'test'; @@ -111,5 +125,5 @@ describe('signing profile', () => { }); Template.fromStack(stack).templateMatches({}); }); - } ); + }); }); From d184ac2c7dde4d40e39ea31a009ff0b31d064755 Mon Sep 17 00:00:00 2001 From: Andrew Hammond <445764+ahammond@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:46:46 -0800 Subject: [PATCH 07/12] feat(pipelines): expose crossRegionReplicationBuckets (#28447) Closes #28446. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../PipelineStack.assets.json | 20 + .../PipelineStack.template.json | 918 +++++++ .../PipelineStackPipeline9DB740AF.dot | 55 + ...lineStackuseast1Queue1822FD5F8.assets.json | 20 + ...neStackuseast1Queue1822FD5F8.template.json | 43 + .../assembly-PipelineStack-us-east-1/cdk.out | 1 + .../manifest.json | 60 + ...lineStackuswest2Queue1C1AD8043.assets.json | 20 + ...neStackuswest2Queue1C1AD8043.template.json | 43 + .../assembly-PipelineStack-us-west-2/cdk.out | 1 + .../manifest.json | 60 + .../index.js | 1 + .../cdk.out | 1 + ...efaultTestDeployAssertFB66B33F.assets.json | 19 + ...aultTestDeployAssertFB66B33F.template.json | 36 + .../integ.json | 14 + .../manifest.json | 363 +++ .../tree.json | 2125 +++++++++++++++++ .../usEast1S3Stack.assets.json | 34 + .../usEast1S3Stack.template.json | 306 +++ .../usWest2S3Stack.assets.json | 34 + .../usWest2S3Stack.template.json | 285 +++ ...e-with-cross-region-replication-buckets.ts | 112 + packages/aws-cdk-lib/pipelines/README.md | 46 + .../lib/codepipeline/codepipeline.ts | 14 + .../codepipeline-existing.test.ts | 16 + .../rosetta/pipelines/default.ts-fixture | 1 + 27 files changed, 4648 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStackPipeline9DB740AF.dot create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.assets.json new file mode 100644 index 0000000000000..81987a6476a91 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.assets.json @@ -0,0 +1,20 @@ +{ + "version": "36.0.0", + "files": { + "7ef69b8c181a37746d9dd86efa256698f93bd815bd82571bc18eee7c39ba9436": { + "source": { + "path": "PipelineStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "7ef69b8c181a37746d9dd86efa256698f93bd815bd82571bc18eee7c39ba9436.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.template.json new file mode 100644 index 0000000000000..30d593d002a21 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStack.template.json @@ -0,0 +1,918 @@ +{ + "Resources": { + "PipelineRoleB27FAA37": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineRoleDefaultPolicy7BDC1ABB": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::us-west-2-newpipeline-with-cross-region-replication-buckets", + "arn:aws:s3:::us-west-2-newpipeline-with-cross-region-replication-buckets/*", + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineRoleDefaultPolicy7BDC1ABB", + "Roles": [ + { + "Ref": "PipelineRoleB27FAA37" + } + ] + } + }, + "Pipeline9850B417": { + "Type": "AWS::CodePipeline::Pipeline", + "Properties": { + "ArtifactStores": [ + { + "ArtifactStore": { + "Location": { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputRefRegionalBucketF5C80E4B3E52A444" + }, + "Type": "S3" + }, + "Region": "us-east-1" + }, + { + "ArtifactStore": { + "Location": "us-west-2-newpipeline-with-cross-region-replication-buckets", + "Type": "S3" + }, + "Region": "us-west-2" + } + ], + "RestartExecutionOnUpdate": true, + "RoleArn": { + "Fn::GetAtt": [ + "PipelineRoleB27FAA37", + "Arn" + ] + }, + "Stages": [ + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Source", + "Owner": "ThirdParty", + "Provider": "GitHub", + "Version": "1" + }, + "Configuration": { + "Owner": "jose-clickup", + "Repo": "cdk-pipelines-demo", + "Branch": "main", + "OAuthToken": "{{resolve:secretsmanager:github-token:SecretString:::}}", + "PollForSourceChanges": false + }, + "Name": "jose-clickup_cdk-pipelines-demo", + "OutputArtifacts": [ + { + "Name": "jose_clickup_cdk_pipelines_demo_Source" + } + ], + "RunOrder": 1 + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"9846e726ec481ed25679c0170187f40b4920586fd0e7314d24f56620d9f53f5b\"}]" + }, + "InputArtifacts": [ + { + "Name": "jose_clickup_cdk_pipelines_demo_Source" + } + ], + "Name": "Synth", + "OutputArtifacts": [ + { + "Name": "Synth_Output" + } + ], + "RoleArn": { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + }, + "RunOrder": 1 + } + ], + "Name": "Build" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Build", + "Owner": "AWS", + "Provider": "CodeBuild", + "Version": "1" + }, + "Configuration": { + "ProjectName": { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"167eef1378d6e6ad8c4c8da3461f900d6e066cd0916052ee812a8d94b87ad38c\"}]" + }, + "InputArtifacts": [ + { + "Name": "Synth_Output" + } + ], + "Name": "SelfMutate", + "RoleArn": { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + }, + "RunOrder": 1 + } + ], + "Name": "UpdatePipeline" + }, + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Deploy", + "Owner": "AWS", + "Provider": "CloudFormation", + "Version": "1" + }, + "Configuration": { + "StackName": "us-east-1-Queue1", + "Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-cfn-exec-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + "ActionMode": "CHANGE_SET_REPLACE", + "ChangeSetName": "PipelineChange", + "TemplatePath": "Synth_Output::assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json" + }, + "InputArtifacts": [ + { + "Name": "Synth_Output" + } + ], + "Name": "us-east-1.Queue1.Prepare", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Deploy", + "Owner": "AWS", + "Provider": "CloudFormation", + "Version": "1" + }, + "Configuration": { + "StackName": "us-west-2-Queue1", + "Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-cfn-exec-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "ActionMode": "CHANGE_SET_REPLACE", + "ChangeSetName": "PipelineChange", + "TemplatePath": "Synth_Output::assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json" + }, + "InputArtifacts": [ + { + "Name": "Synth_Output" + } + ], + "Name": "us-west-2.Queue1.Prepare", + "Region": "us-west-2", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "RunOrder": 1 + }, + { + "ActionTypeId": { + "Category": "Deploy", + "Owner": "AWS", + "Provider": "CloudFormation", + "Version": "1" + }, + "Configuration": { + "StackName": "us-east-1-Queue1", + "ActionMode": "CHANGE_SET_EXECUTE", + "ChangeSetName": "PipelineChange" + }, + "Name": "us-east-1.Queue1.Deploy", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + "RunOrder": 2 + }, + { + "ActionTypeId": { + "Category": "Deploy", + "Owner": "AWS", + "Provider": "CloudFormation", + "Version": "1" + }, + "Configuration": { + "StackName": "us-west-2-Queue1", + "ActionMode": "CHANGE_SET_EXECUTE", + "ChangeSetName": "PipelineChange" + }, + "Name": "us-west-2.Queue1.Deploy", + "Region": "us-west-2", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "RunOrder": 2 + } + ], + "Name": "MultiRegion" + } + ] + }, + "DependsOn": [ + "PipelineRoleDefaultPolicy7BDC1ABB", + "PipelineRoleB27FAA37" + ] + }, + "PipelineSourcejoseclickupcdkpipelinesdemoWebhookResourceEAB0C0F4": { + "Type": "AWS::CodePipeline::Webhook", + "Properties": { + "Authentication": "GITHUB_HMAC", + "AuthenticationConfiguration": { + "SecretToken": "{{resolve:secretsmanager:github-token:SecretString:::}}" + }, + "Filters": [ + { + "JsonPath": "$.ref", + "MatchEquals": "refs/heads/{Branch}" + } + ], + "RegisterWithThirdParty": true, + "TargetAction": "jose-clickup_cdk-pipelines-demo", + "TargetPipeline": { + "Ref": "Pipeline9850B417" + }, + "TargetPipelineVersion": 1 + } + }, + "PipelineBuildSynthCdkBuildProjectRole231EEA2A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + ":*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + } + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:BatchPutCodeCoverages", + "codebuild:BatchPutTestCases", + "codebuild:CreateReport", + "codebuild:CreateReportGroup", + "codebuild:UpdateReport" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:codebuild:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C", + "Roles": [ + { + "Ref": "PipelineBuildSynthCdkBuildProjectRole231EEA2A" + } + ] + } + }, + "PipelineBuildSynthCdkBuildProject6BEFA8E6": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "CODEPIPELINE" + }, + "Cache": { + "Type": "NO_CACHE" + }, + "Description": "Pipeline step PipelineStack/Pipeline/Build/Synth", + "EncryptionKey": "alias/aws/s3", + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:7.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProjectRole231EEA2A", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"npm ci\",\n \"npm run build\",\n \"npx cdk synth\"\n ]\n }\n },\n \"artifacts\": {\n \"base-directory\": \"cdk.out\",\n \"files\": \"**/*\"\n }\n}", + "Type": "CODEPIPELINE" + } + } + }, + "PipelineCodeBuildActionRole226DB0CB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "PipelineRoleB27FAA37", + "Arn" + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineCodeBuildActionRoleDefaultPolicy1D62A6FE": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProject6BEFA8E6", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "PipelineUpdatePipelineSelfMutationDAA41400", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineCodeBuildActionRoleDefaultPolicy1D62A6FE", + "Roles": [ + { + "Ref": "PipelineCodeBuildActionRole226DB0CB" + } + ] + } + }, + "PipelineUpdatePipelineSelfMutationRole57E559E8": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PipelineUpdatePipelineSelfMutationRoleDefaultPolicyA225DA4E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + ":*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + } + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:BatchPutCodeCoverages", + "codebuild:BatchPutTestCases", + "codebuild:CreateReport", + "codebuild:CreateReportGroup", + "codebuild:UpdateReport" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:codebuild:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + "-*" + ] + ] + } + }, + { + "Action": "sts:AssumeRole", + "Condition": { + "ForAnyValue:StringEquals": { + "iam:ResourceTag/aws-cdk:bootstrap-role": [ + "image-publishing", + "file-publishing", + "deploy" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:*:iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/*" + ] + ] + } + }, + { + "Action": [ + "cloudformation:DescribeStacks", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PipelineUpdatePipelineSelfMutationRoleDefaultPolicyA225DA4E", + "Roles": [ + { + "Ref": "PipelineUpdatePipelineSelfMutationRole57E559E8" + } + ] + } + }, + "PipelineUpdatePipelineSelfMutationDAA41400": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "CODEPIPELINE" + }, + "Cache": { + "Type": "NO_CACHE" + }, + "Description": "Pipeline step PipelineStack/Pipeline/UpdatePipeline/SelfMutate", + "EncryptionKey": "alias/aws/s3", + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "aws/codebuild/standard:7.0", + "ImagePullCredentialsType": "CODEBUILD", + "PrivilegedMode": false, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "PipelineUpdatePipelineSelfMutationRole57E559E8", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@2\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "Type": "CODEPIPELINE" + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStackPipeline9DB740AF.dot b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStackPipeline9DB740AF.dot new file mode 100644 index 0000000000000..7e39513541b14 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/PipelineStackPipeline9DB740AF.dot @@ -0,0 +1,55 @@ +digraph G { + # Arrows represent an "unlocks" relationship (opposite of dependency). So chosen + # because the layout looks more natural that way. + # To represent subgraph dependencies, subgraphs are represented by BEGIN/END nodes. + # To render: `dot -Tsvg PipelineStackPipeline9DB740AF.dot > graph.svg`, open in a browser. + node [shape="box"]; +"BEGIN Build" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END Build" [shape="cds", style="filled", fillcolor="#b7deff"]; +"Build.Synth"; +"Source.jose-clickup/cdk-pipelines-demo" -> "Build.Synth"; +"BEGIN Build" -> "Build.Synth"; +"Build.Synth" -> "END Build"; +"BEGIN UpdatePipeline" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END UpdatePipeline" [shape="cds", style="filled", fillcolor="#b7deff"]; +"UpdatePipeline.SelfMutate"; +"Build.Synth" -> "UpdatePipeline.SelfMutate"; +"BEGIN UpdatePipeline" -> "UpdatePipeline.SelfMutate"; +"UpdatePipeline.SelfMutate" -> "END UpdatePipeline"; +"BEGIN MultiRegion" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END MultiRegion" [shape="cds", style="filled", fillcolor="#b7deff"]; +"UpdatePipeline.SelfMutate" -> "BEGIN MultiRegion"; +"BEGIN MultiRegion.us-east-1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END MultiRegion.us-east-1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"BEGIN MultiRegion.us-east-1.Queue1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END MultiRegion.us-east-1.Queue1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"MultiRegion.us-east-1.Queue1.Deploy"; +"MultiRegion.us-east-1.Queue1.Prepare" -> "MultiRegion.us-east-1.Queue1.Deploy"; +"MultiRegion.us-east-1.Queue1.Prepare"; +"Build.Synth" -> "MultiRegion.us-east-1.Queue1.Prepare"; +"BEGIN MultiRegion.us-east-1.Queue1" -> "MultiRegion.us-east-1.Queue1.Prepare"; +"MultiRegion.us-east-1.Queue1.Deploy" -> "END MultiRegion.us-east-1.Queue1"; +"BEGIN MultiRegion.us-east-1" -> "BEGIN MultiRegion.us-east-1.Queue1"; +"END MultiRegion.us-east-1.Queue1" -> "END MultiRegion.us-east-1"; +"BEGIN MultiRegion.us-west-2" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END MultiRegion.us-west-2" [shape="cds", style="filled", fillcolor="#b7deff"]; +"BEGIN MultiRegion.us-west-2.Queue1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END MultiRegion.us-west-2.Queue1" [shape="cds", style="filled", fillcolor="#b7deff"]; +"MultiRegion.us-west-2.Queue1.Deploy"; +"MultiRegion.us-west-2.Queue1.Prepare" -> "MultiRegion.us-west-2.Queue1.Deploy"; +"MultiRegion.us-west-2.Queue1.Prepare"; +"Build.Synth" -> "MultiRegion.us-west-2.Queue1.Prepare"; +"BEGIN MultiRegion.us-west-2.Queue1" -> "MultiRegion.us-west-2.Queue1.Prepare"; +"MultiRegion.us-west-2.Queue1.Deploy" -> "END MultiRegion.us-west-2.Queue1"; +"BEGIN MultiRegion.us-west-2" -> "BEGIN MultiRegion.us-west-2.Queue1"; +"END MultiRegion.us-west-2.Queue1" -> "END MultiRegion.us-west-2"; +"BEGIN MultiRegion" -> "BEGIN MultiRegion.us-east-1"; +"BEGIN MultiRegion" -> "BEGIN MultiRegion.us-west-2"; +"END MultiRegion.us-east-1" -> "END MultiRegion"; +"END MultiRegion.us-west-2" -> "END MultiRegion"; +"BEGIN Source" [shape="cds", style="filled", fillcolor="#b7deff"]; +"END Source" [shape="cds", style="filled", fillcolor="#b7deff"]; +"Source.jose-clickup/cdk-pipelines-demo"; +"BEGIN Source" -> "Source.jose-clickup/cdk-pipelines-demo"; +"Source.jose-clickup/cdk-pipelines-demo" -> "END Source"; +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.assets.json new file mode 100644 index 0000000000000..ee3b8cd59ea37 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.assets.json @@ -0,0 +1,20 @@ +{ + "version": "36.0.0", + "files": { + "0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5": { + "source": { + "path": "PipelineStackuseast1Queue1822FD5F8.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json new file mode 100644 index 0000000000000..132b710b85c15 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json @@ -0,0 +1,43 @@ +{ + "Resources": { + "Queue4A7E3555": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/manifest.json new file mode 100644 index 0000000000000..09464ce251ef7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-east-1/manifest.json @@ -0,0 +1,60 @@ +{ + "version": "36.0.0", + "artifacts": { + "PipelineStackuseast1Queue1822FD5F8.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "PipelineStackuseast1Queue1822FD5F8.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "PipelineStackuseast1Queue1822FD5F8": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-east-1", + "properties": { + "templateFile": "PipelineStackuseast1Queue1822FD5F8.template.json", + "terminationProtection": false, + "validateOnSynth": true, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "PipelineStackuseast1Queue1822FD5F8.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-east-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + }, + "stackName": "us-east-1-Queue1" + }, + "dependencies": [ + "PipelineStackuseast1Queue1822FD5F8.assets" + ], + "metadata": { + "/PipelineStack/us-east-1/Queue1/Queue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Queue4A7E3555" + } + ], + "/PipelineStack/us-east-1/Queue1/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/PipelineStack/us-east-1/Queue1/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "PipelineStack/us-east-1/Queue1" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.assets.json new file mode 100644 index 0000000000000..bf33a9a36c1e7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.assets.json @@ -0,0 +1,20 @@ +{ + "version": "36.0.0", + "files": { + "0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5": { + "source": { + "path": "PipelineStackuswest2Queue1C1AD8043.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-west-2": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", + "objectKey": "0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5.json", + "region": "us-west-2", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json new file mode 100644 index 0000000000000..132b710b85c15 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json @@ -0,0 +1,43 @@ +{ + "Resources": { + "Queue4A7E3555": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/manifest.json new file mode 100644 index 0000000000000..9caf57624ba77 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/assembly-PipelineStack-us-west-2/manifest.json @@ -0,0 +1,60 @@ +{ + "version": "36.0.0", + "artifacts": { + "PipelineStackuswest2Queue1C1AD8043.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "PipelineStackuswest2Queue1C1AD8043.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "PipelineStackuswest2Queue1C1AD8043": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-west-2", + "properties": { + "templateFile": "PipelineStackuswest2Queue1C1AD8043.template.json", + "terminationProtection": false, + "validateOnSynth": true, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/0cb2dea76b65bd66a374af57914e8583b3c20712b5758474102ef97620d68ec5.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "PipelineStackuswest2Queue1C1AD8043.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-west-2", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + }, + "stackName": "us-west-2-Queue1" + }, + "dependencies": [ + "PipelineStackuswest2Queue1C1AD8043.assets" + ], + "metadata": { + "/PipelineStack/us-west-2/Queue1/Queue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Queue4A7E3555" + } + ], + "/PipelineStack/us-west-2/Queue1/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/PipelineStack/us-west-2/Queue1/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "PipelineStack/us-west-2/Queue1" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3/index.js b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3/index.js new file mode 100644 index 0000000000000..9d841e15260d7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3/index.js @@ -0,0 +1 @@ +"use strict";var C=Object.create;var i=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var L=(e,t)=>{for(var o in t)i(e,o,{get:t[o],enumerable:!0})},d=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of w(t))!A.call(e,s)&&s!==o&&i(e,s,{get:()=>t[s],enumerable:!(r=I(t,s))||r.enumerable});return e};var l=(e,t,o)=>(o=e!=null?C(P(e)):{},d(t||!e||!e.__esModule?i(o,"default",{value:e,enumerable:!0}):o,e)),k=e=>d(i({},"__esModule",{value:!0}),e);var U={};L(U,{autoDeleteHandler:()=>S,handler:()=>_});module.exports=k(U);var h=require("@aws-sdk/client-s3");var y=l(require("https")),m=l(require("url")),a={sendHttpRequest:T,log:b,includeStackTraces:!0,userHandlerIndex:"./index"},p="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",B="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";function R(e){return async(t,o)=>{let r={...t,ResponseURL:"..."};if(a.log(JSON.stringify(r,void 0,2)),t.RequestType==="Delete"&&t.PhysicalResourceId===p){a.log("ignoring DELETE event caused by a failed CREATE event"),await u("SUCCESS",t);return}try{let s=await e(r,o),n=D(t,s);await u("SUCCESS",n)}catch(s){let n={...t,Reason:a.includeStackTraces?s.stack:s.message};n.PhysicalResourceId||(t.RequestType==="Create"?(a.log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),n.PhysicalResourceId=p):a.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(t)}`)),await u("FAILED",n)}}}function D(e,t={}){let o=t.PhysicalResourceId??e.PhysicalResourceId??e.RequestId;if(e.RequestType==="Delete"&&o!==e.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${e.PhysicalResourceId}" to "${t.PhysicalResourceId}" during deletion`);return{...e,...t,PhysicalResourceId:o}}async function u(e,t){let o={Status:e,Reason:t.Reason??e,StackId:t.StackId,RequestId:t.RequestId,PhysicalResourceId:t.PhysicalResourceId||B,LogicalResourceId:t.LogicalResourceId,NoEcho:t.NoEcho,Data:t.Data};a.log("submit response to cloudformation",o);let r=JSON.stringify(o),s=m.parse(t.ResponseURL),n={hostname:s.hostname,path:s.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(r,"utf8")}};await O({attempts:5,sleep:1e3},a.sendHttpRequest)(n,r)}async function T(e,t){return new Promise((o,r)=>{try{let s=y.request(e,n=>o());s.on("error",r),s.write(t),s.end()}catch(s){r(s)}})}function b(e,...t){console.log(e,...t)}function O(e,t){return async(...o)=>{let r=e.attempts,s=e.sleep;for(;;)try{return await t(...o)}catch(n){if(r--<=0)throw n;await x(Math.floor(Math.random()*s)),s*=2}}}async function x(e){return new Promise(t=>setTimeout(t,e))}var g="aws-cdk:auto-delete-objects",H=JSON.stringify({Version:"2012-10-17",Statement:[]}),c=new h.S3({}),_=R(S);async function S(e){switch(e.RequestType){case"Create":return;case"Update":return F(e);case"Delete":return f(e.ResourceProperties?.BucketName)}}async function F(e){let t=e,o=t.OldResourceProperties?.BucketName,r=t.ResourceProperties?.BucketName;if(r!=null&&o!=null&&r!==o)return f(o)}async function N(e){try{let t=(await c.getBucketPolicy({Bucket:e}))?.Policy??H,o=JSON.parse(t);o.Statement.push({Principal:"*",Effect:"Deny",Action:["s3:PutObject"],Resource:[`arn:aws:s3:::${e}/*`]}),await c.putBucketPolicy({Bucket:e,Policy:JSON.stringify(o)})}catch(t){if(t.name==="NoSuchBucket")throw t;console.log(`Could not set new object deny policy on bucket '${e}' prior to deletion.`)}}async function E(e){let t=await c.listObjectVersions({Bucket:e}),o=[...t.Versions??[],...t.DeleteMarkers??[]];if(o.length===0)return;let r=o.map(s=>({Key:s.Key,VersionId:s.VersionId}));await c.deleteObjects({Bucket:e,Delete:{Objects:r}}),t?.IsTruncated&&await E(e)}async function f(e){if(!e)throw new Error("No BucketName was provided.");try{if(!await W(e)){console.log(`Bucket does not have '${g}' tag, skipping cleaning.`);return}await N(e),await E(e)}catch(t){if(t.name==="NoSuchBucket"){console.log(`Bucket '${e}' does not exist.`);return}throw t}}async function W(e){return(await c.getBucketTagging({Bucket:e})).TagSet?.some(o=>o.Key===g&&o.Value==="true")}0&&(module.exports={autoDeleteHandler,handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets.json new file mode 100644 index 0000000000000..b60f3d5dac4ab --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/integ.json new file mode 100644 index 0000000000000..7e473fa163179 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "version": "36.0.0", + "testCases": { + "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest": { + "stacks": [ + "PipelineStack", + "usEast1S3Stack", + "usWest2S3Stack" + ], + "assertionStack": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/manifest.json new file mode 100644 index 0000000000000..0a3f70b362a29 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/manifest.json @@ -0,0 +1,363 @@ +{ + "version": "36.0.0", + "artifacts": { + "assembly-PipelineStack-us-east-1": { + "type": "cdk:cloud-assembly", + "properties": { + "directoryName": "assembly-PipelineStack-us-east-1", + "displayName": "PipelineStack/us-east-1" + } + }, + "assembly-PipelineStack-us-west-2": { + "type": "cdk:cloud-assembly", + "properties": { + "directoryName": "assembly-PipelineStack-us-west-2", + "displayName": "PipelineStack/us-west-2" + } + }, + "usEast1S3Stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "usEast1S3Stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "usEast1S3Stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-east-1", + "properties": { + "templateFile": "usEast1S3Stack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/dcb3b9d224db2e26297b5d99818cb49212a518e995d9fbba3f43d0f3cbb95373.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "usEast1S3Stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-east-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "usEast1S3Stack.assets" + ], + "metadata": { + "/usEast1S3Stack/RegionalBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketF5C80E4B" + } + ], + "/usEast1S3Stack/RegionalBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketPolicyC6508E8A" + } + ], + "/usEast1S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketAutoDeleteObjectsCustomResource10BE89C6" + } + ], + "/usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + } + ], + "/usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F" + } + ], + "/usEast1S3Stack/Exports/Output{\"Fn::GetAtt\":[\"RegionalBucketF5C80E4B\",\"Arn\"]}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + } + ], + "/usEast1S3Stack/Exports/Output{\"Ref\":\"RegionalBucketF5C80E4B\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefRegionalBucketF5C80E4B3E52A444" + } + ], + "/usEast1S3Stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/usEast1S3Stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "usEast1S3Stack" + }, + "usWest2S3Stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "usWest2S3Stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "usWest2S3Stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-west-2", + "properties": { + "templateFile": "usWest2S3Stack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/be060ef9e9df7c21dec49e21423280cd2c208089a6f149a020bd51bb222fd15f.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "usWest2S3Stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-west-2", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "usWest2S3Stack.assets" + ], + "metadata": { + "/usWest2S3Stack/RegionalBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketF5C80E4B" + } + ], + "/usWest2S3Stack/RegionalBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketPolicyC6508E8A" + } + ], + "/usWest2S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "RegionalBucketAutoDeleteObjectsCustomResource10BE89C6" + } + ], + "/usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + } + ], + "/usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F" + } + ], + "/usWest2S3Stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/usWest2S3Stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "usWest2S3Stack" + }, + "PipelineStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "PipelineStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "PipelineStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/us-east-1", + "properties": { + "templateFile": "PipelineStack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/7ef69b8c181a37746d9dd86efa256698f93bd815bd82571bc18eee7c39ba9436.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "PipelineStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-east-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "usWest2S3Stack", + "usEast1S3Stack", + "PipelineStack.assets" + ], + "metadata": { + "/PipelineStack/Pipeline/Pipeline/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineRoleB27FAA37" + } + ], + "/PipelineStack/Pipeline/Pipeline/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineRoleDefaultPolicy7BDC1ABB" + } + ], + "/PipelineStack/Pipeline/Pipeline/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Pipeline9850B417" + } + ], + "/PipelineStack/Pipeline/Pipeline/Source/jose-clickup_cdk-pipelines-demo/WebhookResource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineSourcejoseclickupcdkpipelinesdemoWebhookResourceEAB0C0F4" + } + ], + "/PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBuildSynthCdkBuildProjectRole231EEA2A" + } + ], + "/PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C" + } + ], + "/PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + } + ], + "/PipelineStack/Pipeline/CodeBuildActionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineCodeBuildActionRole226DB0CB" + } + ], + "/PipelineStack/Pipeline/CodeBuildActionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineCodeBuildActionRoleDefaultPolicy1D62A6FE" + } + ], + "/PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineUpdatePipelineSelfMutationRole57E559E8" + } + ], + "/PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineUpdatePipelineSelfMutationRoleDefaultPolicyA225DA4E" + } + ], + "/PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "PipelineUpdatePipelineSelfMutationDAA41400" + } + ], + "/PipelineStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/PipelineStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "PipelineStack" + }, + "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.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": [ + "cdkintegcodepipelinewithcrossregionreplicationbucketsDefaultTestDeployAssertFB66B33F.assets" + ], + "metadata": { + "/cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/tree.json new file mode 100644 index 0000000000000..6647147e9ba1a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/tree.json @@ -0,0 +1,2125 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "usEast1S3Stack": { + "id": "usEast1S3Stack", + "path": "usEast1S3Stack", + "children": { + "RegionalBucket": { + "id": "RegionalBucket", + "path": "usEast1S3Stack/RegionalBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "usEast1S3Stack/RegionalBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketEncryption": { + "serverSideEncryptionConfiguration": [ + { + "serverSideEncryptionByDefault": { + "sseAlgorithm": "AES256" + } + } + ] + }, + "bucketName": "us-east-1-newpipeline-with-cross-region-replication-buckets", + "publicAccessBlockConfiguration": { + "blockPublicAcls": true, + "blockPublicPolicy": true, + "ignorePublicAcls": true, + "restrictPublicBuckets": true + }, + "tags": [ + { + "key": "aws-cdk:auto-delete-objects", + "value": "true" + } + ], + "versioningConfiguration": { + "status": "Enabled" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "usEast1S3Stack/RegionalBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "usEast1S3Stack/RegionalBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "RegionalBucketF5C80E4B" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "0.0.0" + } + }, + "AutoDeleteObjectsCustomResource": { + "id": "AutoDeleteObjectsCustomResource", + "path": "usEast1S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "usEast1S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "Custom::S3AutoDeleteObjectsCustomResourceProvider": { + "id": "Custom::S3AutoDeleteObjectsCustomResourceProvider", + "path": "usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "usEast1S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "usEast1S3Stack/Exports", + "children": { + "Output{\"Fn::GetAtt\":[\"RegionalBucketF5C80E4B\",\"Arn\"]}": { + "id": "Output{\"Fn::GetAtt\":[\"RegionalBucketF5C80E4B\",\"Arn\"]}", + "path": "usEast1S3Stack/Exports/Output{\"Fn::GetAtt\":[\"RegionalBucketF5C80E4B\",\"Arn\"]}", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "0.0.0" + } + }, + "Output{\"Ref\":\"RegionalBucketF5C80E4B\"}": { + "id": "Output{\"Ref\":\"RegionalBucketF5C80E4B\"}", + "path": "usEast1S3Stack/Exports/Output{\"Ref\":\"RegionalBucketF5C80E4B\"}", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "usEast1S3Stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "usEast1S3Stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "usWest2S3Stack": { + "id": "usWest2S3Stack", + "path": "usWest2S3Stack", + "children": { + "RegionalBucket": { + "id": "RegionalBucket", + "path": "usWest2S3Stack/RegionalBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "usWest2S3Stack/RegionalBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketEncryption": { + "serverSideEncryptionConfiguration": [ + { + "serverSideEncryptionByDefault": { + "sseAlgorithm": "AES256" + } + } + ] + }, + "bucketName": "us-west-2-newpipeline-with-cross-region-replication-buckets", + "publicAccessBlockConfiguration": { + "blockPublicAcls": true, + "blockPublicPolicy": true, + "ignorePublicAcls": true, + "restrictPublicBuckets": true + }, + "tags": [ + { + "key": "aws-cdk:auto-delete-objects", + "value": "true" + } + ], + "versioningConfiguration": { + "status": "Enabled" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "usWest2S3Stack/RegionalBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "usWest2S3Stack/RegionalBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "RegionalBucketF5C80E4B" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "0.0.0" + } + }, + "AutoDeleteObjectsCustomResource": { + "id": "AutoDeleteObjectsCustomResource", + "path": "usWest2S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "usWest2S3Stack/RegionalBucket/AutoDeleteObjectsCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "Custom::S3AutoDeleteObjectsCustomResourceProvider": { + "id": "Custom::S3AutoDeleteObjectsCustomResourceProvider", + "path": "usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "usWest2S3Stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "usWest2S3Stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "usWest2S3Stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "PipelineStack": { + "id": "PipelineStack", + "path": "PipelineStack", + "children": { + "Pipeline": { + "id": "Pipeline", + "path": "PipelineStack/Pipeline", + "children": { + "Pipeline": { + "id": "Pipeline", + "path": "PipelineStack/Pipeline/Pipeline", + "children": { + "Role": { + "id": "Role", + "path": "PipelineStack/Pipeline/Pipeline/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "PipelineStack/Pipeline/Pipeline/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "PipelineStack/Pipeline/Pipeline/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::us-west-2-newpipeline-with-cross-region-replication-buckets", + "arn:aws:s3:::us-west-2-newpipeline-with-cross-region-replication-buckets/*", + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineRoleDefaultPolicy7BDC1ABB", + "roles": [ + { + "Ref": "PipelineRoleB27FAA37" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodePipeline::Pipeline", + "aws:cdk:cloudformation:props": { + "artifactStores": [ + { + "region": "us-east-1", + "artifactStore": { + "type": "S3", + "location": { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputRefRegionalBucketF5C80E4B3E52A444" + } + } + }, + { + "region": "us-west-2", + "artifactStore": { + "type": "S3", + "location": "us-west-2-newpipeline-with-cross-region-replication-buckets" + } + } + ], + "restartExecutionOnUpdate": true, + "roleArn": { + "Fn::GetAtt": [ + "PipelineRoleB27FAA37", + "Arn" + ] + }, + "stages": [ + { + "name": "Source", + "actions": [ + { + "name": "jose-clickup_cdk-pipelines-demo", + "outputArtifacts": [ + { + "name": "jose_clickup_cdk_pipelines_demo_Source" + } + ], + "actionTypeId": { + "category": "Source", + "version": "1", + "owner": "ThirdParty", + "provider": "GitHub" + }, + "configuration": { + "Owner": "jose-clickup", + "Repo": "cdk-pipelines-demo", + "Branch": "main", + "OAuthToken": "{{resolve:secretsmanager:github-token:SecretString:::}}", + "PollForSourceChanges": false + }, + "runOrder": 1 + } + ] + }, + { + "name": "Build", + "actions": [ + { + "name": "Synth", + "inputArtifacts": [ + { + "name": "jose_clickup_cdk_pipelines_demo_Source" + } + ], + "outputArtifacts": [ + { + "name": "Synth_Output" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"9846e726ec481ed25679c0170187f40b4920586fd0e7314d24f56620d9f53f5b\"}]" + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + } + } + ] + }, + { + "name": "UpdatePipeline", + "actions": [ + { + "name": "SelfMutate", + "inputArtifacts": [ + { + "name": "Synth_Output" + } + ], + "actionTypeId": { + "category": "Build", + "version": "1", + "owner": "AWS", + "provider": "CodeBuild" + }, + "configuration": { + "ProjectName": { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"167eef1378d6e6ad8c4c8da3461f900d6e066cd0916052ee812a8d94b87ad38c\"}]" + }, + "runOrder": 1, + "roleArn": { + "Fn::GetAtt": [ + "PipelineCodeBuildActionRole226DB0CB", + "Arn" + ] + } + } + ] + }, + { + "name": "MultiRegion", + "actions": [ + { + "name": "us-east-1.Queue1.Prepare", + "inputArtifacts": [ + { + "name": "Synth_Output" + } + ], + "actionTypeId": { + "category": "Deploy", + "version": "1", + "owner": "AWS", + "provider": "CloudFormation" + }, + "configuration": { + "StackName": "us-east-1-Queue1", + "Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-cfn-exec-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + }, + "ActionMode": "CHANGE_SET_REPLACE", + "ChangeSetName": "PipelineChange", + "TemplatePath": "Synth_Output::assembly-PipelineStack-us-east-1/PipelineStackuseast1Queue1822FD5F8.template.json" + }, + "runOrder": 1, + "roleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + } + }, + { + "name": "us-west-2.Queue1.Prepare", + "inputArtifacts": [ + { + "name": "Synth_Output" + } + ], + "actionTypeId": { + "category": "Deploy", + "version": "1", + "owner": "AWS", + "provider": "CloudFormation" + }, + "configuration": { + "StackName": "us-west-2-Queue1", + "Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND", + "RoleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-cfn-exec-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "ActionMode": "CHANGE_SET_REPLACE", + "ChangeSetName": "PipelineChange", + "TemplatePath": "Synth_Output::assembly-PipelineStack-us-west-2/PipelineStackuswest2Queue1C1AD8043.template.json" + }, + "runOrder": 1, + "roleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "region": "us-west-2" + }, + { + "name": "us-east-1.Queue1.Deploy", + "actionTypeId": { + "category": "Deploy", + "version": "1", + "owner": "AWS", + "provider": "CloudFormation" + }, + "configuration": { + "StackName": "us-east-1-Queue1", + "ActionMode": "CHANGE_SET_EXECUTE", + "ChangeSetName": "PipelineChange" + }, + "runOrder": 2, + "roleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + } + }, + { + "name": "us-west-2.Queue1.Deploy", + "actionTypeId": { + "category": "Deploy", + "version": "1", + "owner": "AWS", + "provider": "CloudFormation" + }, + "configuration": { + "StackName": "us-west-2-Queue1", + "ActionMode": "CHANGE_SET_EXECUTE", + "ChangeSetName": "PipelineChange" + }, + "runOrder": 2, + "roleArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + }, + "region": "us-west-2" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.CfnPipeline", + "version": "0.0.0" + } + }, + "Source": { + "id": "Source", + "path": "PipelineStack/Pipeline/Pipeline/Source", + "children": { + "jose-clickup_cdk-pipelines-demo": { + "id": "jose-clickup_cdk-pipelines-demo", + "path": "PipelineStack/Pipeline/Pipeline/Source/jose-clickup_cdk-pipelines-demo", + "children": { + "WebhookResource": { + "id": "WebhookResource", + "path": "PipelineStack/Pipeline/Pipeline/Source/jose-clickup_cdk-pipelines-demo/WebhookResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodePipeline::Webhook", + "aws:cdk:cloudformation:props": { + "authentication": "GITHUB_HMAC", + "authenticationConfiguration": { + "secretToken": "{{resolve:secretsmanager:github-token:SecretString:::}}" + }, + "filters": [ + { + "jsonPath": "$.ref", + "matchEquals": "refs/heads/{Branch}" + } + ], + "registerWithThirdParty": true, + "targetAction": "jose-clickup_cdk-pipelines-demo", + "targetPipeline": { + "Ref": "Pipeline9850B417" + }, + "targetPipelineVersion": 1 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.CfnWebhook", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Build": { + "id": "Build", + "path": "PipelineStack/Pipeline/Pipeline/Build", + "children": { + "Synth": { + "id": "Synth", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth", + "children": { + "CdkBuildProject": { + "id": "CdkBuildProject", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject", + "children": { + "Role": { + "id": "Role", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + ":*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + } + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:BatchPutCodeCoverages", + "codebuild:BatchPutTestCases", + "codebuild:CreateReport", + "codebuild:CreateReportGroup", + "codebuild:UpdateReport" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:codebuild:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "PipelineBuildSynthCdkBuildProject6BEFA8E6" + }, + "-*" + ] + ] + } + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicyFB6C941C", + "roles": [ + { + "Ref": "PipelineBuildSynthCdkBuildProjectRole231EEA2A" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/Pipeline/Build/Synth/CdkBuildProject/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "CODEPIPELINE" + }, + "cache": { + "type": "NO_CACHE" + }, + "description": "Pipeline step PipelineStack/Pipeline/Build/Synth", + "encryptionKey": "alias/aws/s3", + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:7.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": false, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProjectRole231EEA2A", + "Arn" + ] + }, + "source": { + "type": "CODEPIPELINE", + "buildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"npm ci\",\n \"npm run build\",\n \"npx cdk synth\"\n ]\n }\n },\n \"artifacts\": {\n \"base-directory\": \"cdk.out\",\n \"files\": \"**/*\"\n }\n}" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.PipelineProject", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "UpdatePipeline": { + "id": "UpdatePipeline", + "path": "PipelineStack/Pipeline/Pipeline/UpdatePipeline", + "children": { + "SelfMutate": { + "id": "SelfMutate", + "path": "PipelineStack/Pipeline/Pipeline/UpdatePipeline/SelfMutate", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "MultiRegion": { + "id": "MultiRegion", + "path": "PipelineStack/Pipeline/Pipeline/MultiRegion", + "children": { + "us-east-1.Queue1.Prepare": { + "id": "us-east-1.Queue1.Prepare", + "path": "PipelineStack/Pipeline/Pipeline/MultiRegion/us-east-1.Queue1.Prepare", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "us-west-2.Queue1.Prepare": { + "id": "us-west-2.Queue1.Prepare", + "path": "PipelineStack/Pipeline/Pipeline/MultiRegion/us-west-2.Queue1.Prepare", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "us-east-1.Queue1.Deploy": { + "id": "us-east-1.Queue1.Deploy", + "path": "PipelineStack/Pipeline/Pipeline/MultiRegion/us-east-1.Queue1.Deploy", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "us-west-2.Queue1.Deploy": { + "id": "us-west-2.Queue1.Deploy", + "path": "PipelineStack/Pipeline/Pipeline/MultiRegion/us-west-2.Queue1.Deploy", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1": { + "id": "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "path": "PipelineStack/Pipeline/Pipeline/MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1": { + "id": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "children": { + "8389e75f-0810-4838-bf64-d6f85a95cf83": { + "id": "8389e75f-0810-4838-bf64-d6f85a95cf83", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1/8389e75f-0810-4838-bf64-d6f85a95cf83", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1": { + "id": "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "path": "PipelineStack/Pipeline/Pipeline/MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1": { + "id": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2": { + "id": "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "path": "PipelineStack/Pipeline/Pipeline/MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2": { + "id": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", + "children": { + "8389e75f-0810-4838-bf64-d6f85a95cf83": { + "id": "8389e75f-0810-4838-bf64-d6f85a95cf83", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2/8389e75f-0810-4838-bf64-d6f85a95cf83", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2": { + "id": "MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "path": "PipelineStack/Pipeline/Pipeline/MutableRolearn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2": { + "id": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "path": "PipelineStack/Pipeline/Pipeline/arn:${AWS::Partition}:iam::${AWS::AccountId}:role--cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codepipeline.Pipeline", + "version": "0.0.0" + } + }, + "CodeBuildActionRole": { + "id": "CodeBuildActionRole", + "path": "PipelineStack/Pipeline/CodeBuildActionRole", + "children": { + "ImportCodeBuildActionRole": { + "id": "ImportCodeBuildActionRole", + "path": "PipelineStack/Pipeline/CodeBuildActionRole/ImportCodeBuildActionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/CodeBuildActionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "PipelineRoleB27FAA37", + "Arn" + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "PipelineStack/Pipeline/CodeBuildActionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/CodeBuildActionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild", + "codebuild:StopBuild" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "PipelineBuildSynthCdkBuildProject6BEFA8E6", + "Arn" + ] + }, + { + "Fn::GetAtt": [ + "PipelineUpdatePipelineSelfMutationDAA41400", + "Arn" + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineCodeBuildActionRoleDefaultPolicy1D62A6FE", + "roles": [ + { + "Ref": "PipelineCodeBuildActionRole226DB0CB" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "UpdatePipeline": { + "id": "UpdatePipeline", + "path": "PipelineStack/Pipeline/UpdatePipeline", + "children": { + "SelfMutation": { + "id": "SelfMutation", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation", + "children": { + "Role": { + "id": "Role", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + ":*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:logs:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + } + ] + ] + } + ] + }, + { + "Action": [ + "codebuild:BatchPutCodeCoverages", + "codebuild:BatchPutTestCases", + "codebuild:CreateReport", + "codebuild:CreateReportGroup", + "codebuild:UpdateReport" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:codebuild:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" + }, + "-*" + ] + ] + } + }, + { + "Action": "sts:AssumeRole", + "Condition": { + "ForAnyValue:StringEquals": { + "iam:ResourceTag/aws-cdk:bootstrap-role": [ + "image-publishing", + "file-publishing", + "deploy" + ] + } + }, + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:*:iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/*" + ] + ] + } + }, + { + "Action": [ + "cloudformation:DescribeStacks", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "PipelineUpdatePipelineSelfMutationRoleDefaultPolicyA225DA4E", + "roles": [ + { + "Ref": "PipelineUpdatePipelineSelfMutationRole57E559E8" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "PipelineStack/Pipeline/UpdatePipeline/SelfMutation/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeBuild::Project", + "aws:cdk:cloudformation:props": { + "artifacts": { + "type": "CODEPIPELINE" + }, + "cache": { + "type": "NO_CACHE" + }, + "description": "Pipeline step PipelineStack/Pipeline/UpdatePipeline/SelfMutate", + "encryptionKey": "alias/aws/s3", + "environment": { + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:7.0", + "imagePullCredentialsType": "CODEBUILD", + "privilegedMode": false, + "computeType": "BUILD_GENERAL1_SMALL" + }, + "serviceRole": { + "Fn::GetAtt": [ + "PipelineUpdatePipelineSelfMutationRole57E559E8", + "Arn" + ] + }, + "source": { + "type": "CODEPIPELINE", + "buildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@2\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.CfnProject", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codebuild.PipelineProject", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.pipelines.CodePipeline", + "version": "0.0.0" + } + }, + "us-east-1": { + "id": "us-east-1", + "path": "PipelineStack/us-east-1", + "children": { + "Queue1": { + "id": "Queue1", + "path": "PipelineStack/us-east-1/Queue1", + "children": { + "Queue": { + "id": "Queue", + "path": "PipelineStack/us-east-1/Queue1/Queue", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/us-east-1/Queue1/Queue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.Queue", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "PipelineStack/us-east-1/Queue1/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "PipelineStack/us-east-1/Queue1/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stage", + "version": "0.0.0" + } + }, + "us-west-2": { + "id": "us-west-2", + "path": "PipelineStack/us-west-2", + "children": { + "Queue1": { + "id": "Queue1", + "path": "PipelineStack/us-west-2/Queue1", + "children": { + "Queue": { + "id": "Queue", + "path": "PipelineStack/us-west-2/Queue1/Queue", + "children": { + "Resource": { + "id": "Resource", + "path": "PipelineStack/us-west-2/Queue1/Queue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.Queue", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "PipelineStack/us-west-2/Queue1/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "PipelineStack/us-west-2/Queue1/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stage", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "PipelineStack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "PipelineStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-codepipeline-with-cross-region-replication-buckets": { + "id": "cdk-integ-codepipeline-with-cross-region-replication-buckets", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-codepipeline-with-cross-region-replication-buckets/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.assets.json new file mode 100644 index 0000000000000..9cba80d2c32f7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.assets.json @@ -0,0 +1,34 @@ +{ + "version": "36.0.0", + "files": { + "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3": { + "source": { + "path": "asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3", + "packaging": "zip" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3.zip", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + }, + "dcb3b9d224db2e26297b5d99818cb49212a518e995d9fbba3f43d0f3cbb95373": { + "source": { + "path": "usEast1S3Stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "dcb3b9d224db2e26297b5d99818cb49212a518e995d9fbba3f43d0f3cbb95373.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.template.json new file mode 100644 index 0000000000000..e638647bfcba3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usEast1S3Stack.template.json @@ -0,0 +1,306 @@ +{ + "Resources": { + "RegionalBucketF5C80E4B": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "BucketName": "us-east-1-newpipeline-with-cross-region-replication-buckets", + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "Tags": [ + { + "Key": "aws-cdk:auto-delete-objects", + "Value": "true" + } + ], + "VersioningConfiguration": { + "Status": "Enabled" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "RegionalBucketPolicyC6508E8A": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "RegionalBucketF5C80E4B" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-east-1" + ] + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "RegionalBucketAutoDeleteObjectsCustomResource10BE89C6": { + "Type": "Custom::S3AutoDeleteObjects", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F", + "Arn" + ] + }, + "BucketName": { + "Ref": "RegionalBucketF5C80E4B" + } + }, + "DependsOn": [ + "RegionalBucketPolicyC6508E8A" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ] + } + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" + }, + "S3Key": "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + }, + "Runtime": "nodejs18.x", + "Description": { + "Fn::Join": [ + "", + [ + "Lambda function for auto-deleting objects in ", + { + "Ref": "RegionalBucketF5C80E4B" + }, + " S3 bucket." + ] + ] + } + }, + "DependsOn": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + ] + } + }, + "Outputs": { + "ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C": { + "Value": { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "Export": { + "Name": "usEast1S3Stack:ExportsOutputFnGetAttRegionalBucketF5C80E4BArn49E35D9C" + } + }, + "ExportsOutputRefRegionalBucketF5C80E4B3E52A444": { + "Value": { + "Ref": "RegionalBucketF5C80E4B" + }, + "Export": { + "Name": "usEast1S3Stack:ExportsOutputRefRegionalBucketF5C80E4B3E52A444" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.assets.json new file mode 100644 index 0000000000000..b8c0fa5f9737e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.assets.json @@ -0,0 +1,34 @@ +{ + "version": "36.0.0", + "files": { + "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3": { + "source": { + "path": "asset.2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3", + "packaging": "zip" + }, + "destinations": { + "current_account-us-west-2": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", + "objectKey": "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3.zip", + "region": "us-west-2", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" + } + } + }, + "be060ef9e9df7c21dec49e21423280cd2c208089a6f149a020bd51bb222fd15f": { + "source": { + "path": "usWest2S3Stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-west-2": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", + "objectKey": "be060ef9e9df7c21dec49e21423280cd2c208089a6f149a020bd51bb222fd15f.json", + "region": "us-west-2", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.template.json new file mode 100644 index 0000000000000..64ba53840c761 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.js.snapshot/usWest2S3Stack.template.json @@ -0,0 +1,285 @@ +{ + "Resources": { + "RegionalBucketF5C80E4B": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "BucketName": "us-west-2-newpipeline-with-cross-region-replication-buckets", + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "Tags": [ + { + "Key": "aws-cdk:auto-delete-objects", + "Value": "true" + } + ], + "VersioningConfiguration": { + "Status": "Enabled" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "RegionalBucketPolicyC6508E8A": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "RegionalBucketF5C80E4B" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":role/cdk-hnb659fds-deploy-role-", + { + "Ref": "AWS::AccountId" + }, + "-us-west-2" + ] + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "RegionalBucketF5C80E4B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "RegionalBucketAutoDeleteObjectsCustomResource10BE89C6": { + "Type": "Custom::S3AutoDeleteObjects", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F", + "Arn" + ] + }, + "BucketName": { + "Ref": "RegionalBucketF5C80E4B" + } + }, + "DependsOn": [ + "RegionalBucketPolicyC6508E8A" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ] + } + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2" + }, + "S3Key": "2ec8ad9e91dcd6e7ad6a5c84ffc6c9c05c408aca3b26ceb2816d81043e6c4dc3.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + }, + "Runtime": "nodejs18.x", + "Description": { + "Fn::Join": [ + "", + [ + "Lambda function for auto-deleting objects in ", + { + "Ref": "RegionalBucketF5C80E4B" + }, + " S3 bucket." + ] + ] + } + }, + "DependsOn": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.ts b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.ts new file mode 100644 index 0000000000000..ce91fd3fad3f4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/pipelines/test/integ.newpipeline-with-cross-region-replication-buckets.ts @@ -0,0 +1,112 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +/// !cdk-integ PipelineStack pragma:set-context:@aws-cdk/core:newStyleStackSynthesis=true +import * as sqs from 'aws-cdk-lib/aws-sqs'; +import { + App, + Stack, + StackProps, + Stage, + StageProps, + RemovalPolicy, +} from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as pipelines from 'aws-cdk-lib/pipelines'; +import * as s3 from 'aws-cdk-lib/aws-s3'; + +const regionalBuckets: {[key: string]: string} = { + 'us-east-1': 'us-east-1-newpipeline-with-cross-region-replication-buckets', + 'us-west-2': 'us-west-2-newpipeline-with-cross-region-replication-buckets', +}; + +interface CrossRegionReplicationBuckets { + [key: string]: s3.Bucket; +} + +class RegionalS3Stack extends Stack { + public bucket: s3.Bucket; + + constructor(scope: Construct, id: string, props?: StackProps, bucketName?: string) { + super(scope, id, props); + + this.bucket = new s3.Bucket(this, 'RegionalBucket', { + bucketName: bucketName, + blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, + encryption: s3.BucketEncryption.S3_MANAGED, + enforceSSL: true, + versioned: true, + autoDeleteObjects: true, + removalPolicy: RemovalPolicy.DESTROY, + }); + } +} + +class PipelineStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps, crossRegionReplicationBuckets?: CrossRegionReplicationBuckets) { + super(scope, id, props); + + const pipeline = new pipelines.CodePipeline(this, 'Pipeline', { + synth: new pipelines.ShellStep('Synth', { + input: pipelines.CodePipelineSource.gitHub( + 'jose-clickup/cdk-pipelines-demo', + 'main', + ), + commands: ['npm ci', 'npm run build', 'npx cdk synth'], + }), + crossRegionReplicationBuckets, + }); + + const wave = pipeline.addWave('MultiRegion'); + for (const region in regionalBuckets) { + wave.addStage(new AppStage(this, region, { env: { region: region } })); + } + } +} + +class AppStage extends Stage { + constructor(scope: Construct, id: string, props?: StageProps) { + super(scope, id, props); + + const stack1 = new Stack(this, 'Queue1'); + new sqs.Queue(stack1, 'Queue'); + } +} + +const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': '1', + }, +}); + +const usEast1S3Stack = new RegionalS3Stack(app, 'usEast1S3Stack', { + env: { + region: 'us-east-1', + }, +}, regionalBuckets['us-east-1']); + +const usWest2S3Stack = new RegionalS3Stack(app, 'usWest2S3Stack', { + env: { + region: 'us-west-2', + }, +}, regionalBuckets['us-west-2']); + +const crossRegionReplicationBuckets = { + 'us-east-1': usEast1S3Stack.bucket, + 'us-west-2': usWest2S3Stack.bucket, +}; + +const pipelineStack = new PipelineStack(app, 'PipelineStack', { + env: { + region: 'us-east-1', + }, +}, crossRegionReplicationBuckets); + +new integ.IntegTest( + app, + 'cdk-integ-codepipeline-with-cross-region-replication-buckets', + { + testCases: [pipelineStack, usEast1S3Stack, usWest2S3Stack], + }, +); + +app.synth(); diff --git a/packages/aws-cdk-lib/pipelines/README.md b/packages/aws-cdk-lib/pipelines/README.md index 4eefcbf3a8991..35cf868d28626 100644 --- a/packages/aws-cdk-lib/pipelines/README.md +++ b/packages/aws-cdk-lib/pipelines/README.md @@ -1232,6 +1232,52 @@ and orphan the old bucket. You should manually delete the orphaned bucket after you are sure you have redeployed all CDK applications and there are no more references to the old asset bucket. +## Considerations around Running at Scale + +If you are planning to run pipelines for more than a hundred repos +deploying across multiple regions, then you will want to consider reusing +both artifacts buckets and cross-region replication buckets. + +In a situation like this, you will want to have a separate CDK app / dedicated repo which creates +and managed the buckets which will be shared by the pipelines of all your other apps. +Note that this app must NOT be using the shared buckets because of chicken & egg issues. + +The following code assumes you have created and are managing your buckets in the aforementioned +separate cdk repo and are just importing them for use in one of your (many) pipelines. + +```ts +declare const sharedXRegionUsWest1BucketArn: string; +declare const sharedXRegionUsWest1KeyArn: string; + +declare const sharedXRegionUsWest2BucketArn: string; +declare const sharedXRegionUsWest2KeyArn: string; + +const usWest1Bucket = s3.Bucket.fromBucketAttributes(scope, 'UsEast1Bucket', { + bucketArn: sharedXRegionUsWest1BucketArn, + encryptionKey: kms.Key.fromKeyArn(scope, 'UsEast1BucketKeyArn', sharedXRegionUsWest1BucketArn), +}); + +const usWest2Bucket = s3.Bucket.fromBucketAttributes(scope, 'UsWest2Bucket', { + bucketArn: sharedXRegionUsWest2BucketArn, + encryptionKey: kms.Key.fromKeyArn(scope, 'UsWest2BucketKeyArn', sharedXRegionUsWest2KeyArn), +}); + +const crossRegionReplicationBuckets: Record = { + 'us-west-1': usWest1Bucket, + 'us-west-2': usWest2Bucket, + // Support for additional regions. +} + +const pipeline = new pipelines.CodePipeline(this, 'Pipeline', { + synth: new pipelines.ShellStep('Synth', { + input: pipelines.CodePipelineSource.connection('my-org/my-app', 'main', { + connectionArn: 'arn:aws:codestar-connections:us-east-1:222222222222:connection/7d2469ff-514a-4e4f-9003-5ca4a43cdc41', + }), + commands: ['npm ci','npm run build','npx cdk synth'], + }), // Use shared buckets. + crossRegionReplicationBuckets, +}); +``` ## Context Lookups You might be using CDK constructs that need to look up [runtime diff --git a/packages/aws-cdk-lib/pipelines/lib/codepipeline/codepipeline.ts b/packages/aws-cdk-lib/pipelines/lib/codepipeline/codepipeline.ts index 92ad511679ebc..d699cd3c45aa1 100644 --- a/packages/aws-cdk-lib/pipelines/lib/codepipeline/codepipeline.ts +++ b/packages/aws-cdk-lib/pipelines/lib/codepipeline/codepipeline.ts @@ -244,6 +244,16 @@ export interface CodePipelineProps { * @default - A new S3 bucket will be created. */ readonly artifactBucket?: s3.IBucket; + /** + * A map of region to S3 bucket name used for cross-region CodePipeline. + * For every Action that you specify targeting a different region than the Pipeline itself, + * if you don't provide an explicit Bucket for that region using this property, + * the construct will automatically create a Stack containing an S3 Bucket in that region. + * Passed directly through to the {@link cp.Pipeline}. + * + * @default - no cross region replication buckets. + */ + readonly crossRegionReplicationBuckets?: { [region: string]: s3.IBucket }; } /** @@ -440,6 +450,9 @@ export class CodePipeline extends PipelineBase { if (this.props.enableKeyRotation !== undefined) { throw new Error('Cannot set \'enableKeyRotation\' if an existing CodePipeline is given using \'codePipeline\''); } + if (this.props.crossRegionReplicationBuckets !== undefined) { + throw new Error('Cannot set \'crossRegionReplicationBuckets\' if an existing CodePipeline is given using \'codePipeline\''); + } if (this.props.reuseCrossRegionSupportStacks !== undefined) { throw new Error('Cannot set \'reuseCrossRegionSupportStacks\' if an existing CodePipeline is given using \'codePipeline\''); } @@ -455,6 +468,7 @@ export class CodePipeline extends PipelineBase { this._pipeline = new cp.Pipeline(this, 'Pipeline', { pipelineName: this.props.pipelineName, crossAccountKeys: this.props.crossAccountKeys ?? false, + crossRegionReplicationBuckets: this.props.crossRegionReplicationBuckets, reuseCrossRegionSupportStacks: this.props.reuseCrossRegionSupportStacks, // This is necessary to make self-mutation work (deployments are guaranteed // to happen only after the builds of the latest pipeline definition). diff --git a/packages/aws-cdk-lib/pipelines/test/codepipeline/codepipeline-existing.test.ts b/packages/aws-cdk-lib/pipelines/test/codepipeline/codepipeline-existing.test.ts index b63378fedb0c4..1da9b4ecfb71e 100644 --- a/packages/aws-cdk-lib/pipelines/test/codepipeline/codepipeline-existing.test.ts +++ b/packages/aws-cdk-lib/pipelines/test/codepipeline/codepipeline-existing.test.ts @@ -46,4 +46,20 @@ describeDeprecated('codepipeline existing', () => { }); }).toThrow("Cannot set 'enableKeyRotation' if an existing CodePipeline is given using 'codePipeline'"); }); + + test('Does not allow setting crossRegionReplicationBuckets if an existing CodePipeline is given', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'PipelineStack'); + const existingCodePipeline = new codePipeline.Pipeline(stack, 'CustomCodePipeline'); + + expect(() => { + new cdkp.CodePipeline(stack, 'CDKPipeline', { + crossRegionReplicationBuckets: {}, // Even the empty set is forbidden. + codePipeline: existingCodePipeline, + synth: new cdkp.ShellStep('Synth', { + commands: ['echo hello'], + }), + }).buildPipeline(); + }).toThrow("Cannot set 'crossRegionReplicationBuckets' if an existing CodePipeline is given using 'codePipeline'"); + }); }); \ No newline at end of file diff --git a/packages/aws-cdk-lib/rosetta/pipelines/default.ts-fixture b/packages/aws-cdk-lib/rosetta/pipelines/default.ts-fixture index 61817e5475480..72368fdb67f9b 100644 --- a/packages/aws-cdk-lib/rosetta/pipelines/default.ts-fixture +++ b/packages/aws-cdk-lib/rosetta/pipelines/default.ts-fixture @@ -16,6 +16,7 @@ import secretsmanager = require('aws-cdk-lib/aws-secretsmanager'); import sns = require('aws-cdk-lib/aws-sns'); import subscriptions = require('aws-cdk-lib/aws-sns-subscriptions'); import s3 = require('aws-cdk-lib/aws-s3'); +import kms = require('aws-cdk-lib/aws-kms'); class MyApplicationStage extends Stage { constructor(scope: Construct, id: string, props?: StageProps) { From 050a305d6be65df7e5f1e17668cbf512ead34d23 Mon Sep 17 00:00:00 2001 From: James Cockshull Date: Mon, 8 Jan 2024 18:13:57 +0000 Subject: [PATCH 08/12] docs(pipelines): fix split blockquote (#28616) Unify the orphaned line back into to the blockquote ![Screenshot from 2024-01-08 16-33-10](https://github.com/aws/aws-cdk/assets/18142513/ba9b64c7-8ff4-4f61-afad-63ffb3e43d43) https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html#cdk-pipelines ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/pipelines/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/aws-cdk-lib/pipelines/README.md b/packages/aws-cdk-lib/pipelines/README.md index 35cf868d28626..1e8e0030f9b4c 100644 --- a/packages/aws-cdk-lib/pipelines/README.md +++ b/packages/aws-cdk-lib/pipelines/README.md @@ -16,17 +16,18 @@ everything you need. If you want or need more control, we recommend you drop down to using the `aws-codepipeline` construct library directly. > This module contains two sets of APIs: an **original** and a **modern** version of -CDK Pipelines. The *modern* API has been updated to be easier to work with and -customize, and will be the preferred API going forward. The *original* version -of the API is still available for backwards compatibility, but we recommend migrating -to the new version if possible. +> CDK Pipelines. The *modern* API has been updated to be easier to work with and +> customize, and will be the preferred API going forward. The *original* version +> of the API is still available for backwards compatibility, but we recommend migrating +> to the new version if possible. > > Compared to the original API, the modern API: has more sensible defaults; is > more flexible; supports parallel deployments; supports multiple synth inputs; > allows more control of CodeBuild project generation; supports deployment > engines other than CodePipeline. > -> The README for the original API, as well as a migration guide, can be found in [our GitHub repository](https://github.com/aws/aws-cdk/blob/main/packages/@aws-cdk/pipelines/ORIGINAL_API.md). +> The README for the original API, as well as a migration guide, can be found in +> [our GitHub repository](https://github.com/aws/aws-cdk/blob/main/packages/@aws-cdk/pipelines/ORIGINAL_API.md). ## At a glance From 8562c173227f7b1d522ffaca92338f54d4bb1a01 Mon Sep 17 00:00:00 2001 From: Kendra Neil <53584728+TheRealAmazonKendra@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:05:43 -0800 Subject: [PATCH 09/12] chore(tools): eslint update requires promises.all (#28617) The update on eslint is causing the following error: ``` @aws-cdk/spec2cdk: 165:3 error An array of Promises may be unintentional. Consider handling the promises' fulfillment or rejection with Promise.all or similar, or explicitly marking the expression as ignored with the `void` operator @typescript-eslint/no-floating-promises ``` This PR has been separated out from [28434](https://github.com/aws/aws-cdk/pull/28434) because there are other failures. I am splitting these out to make clear which code is fixing which issue. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cli-lib-alpha/THIRD_PARTY_LICENSES | 6 +- packages/awslint/package.json | 6 +- tools/@aws-cdk/cdk-build-tools/package.json | 8 +- tools/@aws-cdk/eslint-plugin/package.json | 2 +- tools/@aws-cdk/lazify/package.json | 2 +- tools/@aws-cdk/node-bundle/package.json | 8 +- tools/@aws-cdk/pkglint/package.json | 6 +- tools/@aws-cdk/prlint/package.json | 2 +- tools/@aws-cdk/spec2cdk/lib/cfn2ts/index.ts | 4 +- yarn.lock | 137 ++++++++++-------- 10 files changed, 96 insertions(+), 85 deletions(-) diff --git a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES index 9927af86bd644..c430595bb0514 100644 --- a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES @@ -207,7 +207,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @jsii/check-node@1.92.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.92.0 | Apache-2.0 +** @jsii/check-node@1.93.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.93.0 | Apache-2.0 jsii Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -471,7 +471,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE ---------------- -** aws-sdk@2.1498.0 - https://www.npmjs.com/package/aws-sdk/v/2.1498.0 | Apache-2.0 +** aws-sdk@2.1517.0 - https://www.npmjs.com/package/aws-sdk/v/2.1517.0 | Apache-2.0 AWS SDK for JavaScript Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -668,7 +668,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** cdk-from-cfn@0.84.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.84.0 | MIT OR Apache-2.0 +** cdk-from-cfn@0.91.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.91.0 | MIT OR Apache-2.0 ---------------- diff --git a/packages/awslint/package.json b/packages/awslint/package.json index af3b31f1bad82..77852e5d00703 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -31,12 +31,12 @@ "@types/fs-extra": "^9.0.13", "@types/jest": "^29.5.11", "@types/yargs": "^15.0.19", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.29.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.7.0", "jest": "^29.7.0", "typescript": "~5.1.6" diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index 0425000850005..9d42a82b12805 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -47,14 +47,14 @@ "@aws-cdk/eslint-plugin": "0.0.0", "@aws-cdk/yarn-cling": "0.0.0", "@aws-cdk/node-bundle": "0.0.0", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "awslint": "0.0.0", "chalk": "^4", "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.29.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.7.0", "fs-extra": "^9.1.0", "glob": "^7.2.3", @@ -86,4 +86,4 @@ "ubergen": { "exclude": true } -} +} \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/package.json b/tools/@aws-cdk/eslint-plugin/package.json index 537021e7f50ae..49d9245a6981a 100644 --- a/tools/@aws-cdk/eslint-plugin/package.json +++ b/tools/@aws-cdk/eslint-plugin/package.json @@ -22,7 +22,7 @@ "typescript": "~5.1.6" }, "dependencies": { - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^7.32.0", "fs-extra": "^9.1.0" }, diff --git a/tools/@aws-cdk/lazify/package.json b/tools/@aws-cdk/lazify/package.json index f84cd226867e2..094d43c472a3d 100644 --- a/tools/@aws-cdk/lazify/package.json +++ b/tools/@aws-cdk/lazify/package.json @@ -30,4 +30,4 @@ }, "main": "lib/index.js", "license": "Apache-2.0" -} +} \ No newline at end of file diff --git a/tools/@aws-cdk/node-bundle/package.json b/tools/@aws-cdk/node-bundle/package.json index 4dacec9b14182..8425029c7d0bb 100644 --- a/tools/@aws-cdk/node-bundle/package.json +++ b/tools/@aws-cdk/node-bundle/package.json @@ -17,12 +17,12 @@ "@types/license-checker": "^25.0.6", "@types/madge": "^5.0.3", "@types/node": "^16", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^8", "eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.29.0", + "eslint-plugin-import": "^2.29.1", "jest": "^29", "jest-junit": "^15", "npm-check-updates": "^16", @@ -87,4 +87,4 @@ }, "types": "lib/index.d.ts", "private": true -} +} \ No newline at end of file diff --git a/tools/@aws-cdk/pkglint/package.json b/tools/@aws-cdk/pkglint/package.json index 0f65942f7848a..07fd03e5a6f9f 100644 --- a/tools/@aws-cdk/pkglint/package.json +++ b/tools/@aws-cdk/pkglint/package.json @@ -43,12 +43,12 @@ "@types/jest": "^29.5.11", "@types/semver": "^7.5.6", "@types/yargs": "^15.0.19", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.29.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.7.0", "jest": "^29.7.0", "typescript": "~5.1.6" diff --git a/tools/@aws-cdk/prlint/package.json b/tools/@aws-cdk/prlint/package.json index a0769d0f4a6d1..4773d5b771e6c 100644 --- a/tools/@aws-cdk/prlint/package.json +++ b/tools/@aws-cdk/prlint/package.json @@ -29,7 +29,7 @@ "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.29.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.7.0" }, "jest": { diff --git a/tools/@aws-cdk/spec2cdk/lib/cfn2ts/index.ts b/tools/@aws-cdk/spec2cdk/lib/cfn2ts/index.ts index 144194e69ee26..b14a03c1a057c 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cfn2ts/index.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cfn2ts/index.ts @@ -162,11 +162,11 @@ export async function generateAll( }, ); - Object.keys(moduleMap).map(async (moduleName) => { + await Promise.all(Object.keys(moduleMap).map(async (moduleName) => { // Add generated resources and files to module in map moduleMap[moduleName].resources = generated.modules[moduleName].map((m) => m.resources).reduce(mergeObjects, {}); moduleMap[moduleName].files = generated.modules[moduleName].flatMap((m) => m.outputFiles); - }); + })); return moduleMap; } diff --git a/yarn.lock b/yarn.lock index b9aac9b609e00..d9e8f04956dec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5182,16 +5182,16 @@ resolved "https://registry.npmjs.org/@types/yarnpkg__lockfile/-/yarnpkg__lockfile-1.1.9.tgz#b3c8e8d66dc8ce79827f422a660a557cda9ded14" integrity sha512-GD4Fk15UoP5NLCNor51YdfL9MSdldKCqOC9EssrRw3HVfar9wUZ5y8Lfnp+qVD6hIinLr8ygklDYnmlnlQo12Q== -"@typescript-eslint/eslint-plugin@^6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz#fc1ab5f23618ba590c87e8226ff07a760be3dd7b" - integrity sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw== +"@typescript-eslint/eslint-plugin@^6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz#94b86f3c25b468c714a04bd490017ecec2fd3746" + integrity sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.14.0" - "@typescript-eslint/type-utils" "6.14.0" - "@typescript-eslint/utils" "6.14.0" - "@typescript-eslint/visitor-keys" "6.14.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/type-utils" "6.18.0" + "@typescript-eslint/utils" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -5211,15 +5211,15 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/parser@^6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz#a2d6a732e0d2b95c73f6a26ae7362877cc1b4212" - integrity sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA== +"@typescript-eslint/parser@^6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz#d494161d64832e869f0a6acc6000a2cdff858383" + integrity sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA== dependencies: - "@typescript-eslint/scope-manager" "6.14.0" - "@typescript-eslint/types" "6.14.0" - "@typescript-eslint/typescript-estree" "6.14.0" - "@typescript-eslint/visitor-keys" "6.14.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/typescript-estree" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" "@typescript-eslint/scope-manager@4.33.0": @@ -5230,21 +5230,21 @@ "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" -"@typescript-eslint/scope-manager@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz#53d24363fdb5ee0d1d8cda4ed5e5321272ab3d48" - integrity sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg== +"@typescript-eslint/scope-manager@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz#24ca6fc1f4a2afa71122dcfca9282878687d9997" + integrity sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA== dependencies: - "@typescript-eslint/types" "6.14.0" - "@typescript-eslint/visitor-keys" "6.14.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" -"@typescript-eslint/type-utils@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz#ac9cb5ba0615c837f1a6b172feeb273d36e4f8af" - integrity sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw== +"@typescript-eslint/type-utils@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz#a492da599da5c38c70aa9ff9bfb473961b8ae663" + integrity sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ== dependencies: - "@typescript-eslint/typescript-estree" "6.14.0" - "@typescript-eslint/utils" "6.14.0" + "@typescript-eslint/typescript-estree" "6.18.0" + "@typescript-eslint/utils" "6.18.0" debug "^4.3.4" ts-api-utils "^1.0.1" @@ -5253,10 +5253,10 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/types@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz#935307f7a931016b7a5eb25d494ea3e1f613e929" - integrity sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA== +"@typescript-eslint/types@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz#ffce610a1540c17cf7d8ecf2bb34b8b0e2e77101" + integrity sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA== "@typescript-eslint/typescript-estree@4.33.0", "@typescript-eslint/typescript-estree@^4.33.0": version "4.33.0" @@ -5271,30 +5271,31 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz#90c7ddd45cd22139adf3d4577580d04c9189ac13" - integrity sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw== +"@typescript-eslint/typescript-estree@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz#1c357c3ca435c3cfa2af6b9daf45ca0bc2bb059a" + integrity sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg== dependencies: - "@typescript-eslint/types" "6.14.0" - "@typescript-eslint/visitor-keys" "6.14.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" + minimatch "9.0.3" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz#856a9e274367d99ffbd39c48128b93a86c4261e3" - integrity sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg== +"@typescript-eslint/utils@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz#4d07c9c08f84b9939a1aca7aef98c8f378936142" + integrity sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.14.0" - "@typescript-eslint/types" "6.14.0" - "@typescript-eslint/typescript-estree" "6.14.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/typescript-estree" "6.18.0" semver "^7.5.4" "@typescript-eslint/visitor-keys@4.33.0": @@ -5305,12 +5306,12 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@6.14.0": - version "6.14.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz#1d1d486581819287de824a56c22f32543561138e" - integrity sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw== +"@typescript-eslint/visitor-keys@6.18.0": + version "6.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz#3c8733737786fa6c78a347b4fa306ae7155b560f" + integrity sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA== dependencies: - "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/types" "6.18.0" eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": @@ -7795,10 +7796,10 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-import@^2.29.0: - version "2.29.0" - resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155" - integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg== +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== dependencies: array-includes "^3.1.7" array.prototype.findlastindex "^1.2.3" @@ -7816,7 +7817,7 @@ eslint-plugin-import@^2.29.0: object.groupby "^1.0.1" object.values "^1.1.7" semver "^6.3.1" - tsconfig-paths "^3.14.2" + tsconfig-paths "^3.15.0" eslint-plugin-jest@^24.7.0: version "24.7.0" @@ -11217,6 +11218,13 @@ minimatch@3.0.5: dependencies: brace-expansion "^1.1.7" +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3, minimatch@~9.0.3: + version "9.0.3" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -11238,13 +11246,6 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3, minimatch@~9.0.3: - version "9.0.3" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -14323,7 +14324,7 @@ ts-node@^10.9.1, ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.10.1, tsconfig-paths@^3.14.1, tsconfig-paths@^3.14.2: +tsconfig-paths@^3.10.1, tsconfig-paths@^3.14.1: version "3.14.2" resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== @@ -14333,6 +14334,16 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.14.1, tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + tsconfig-paths@^4.1.2: version "4.2.0" resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" From 0042e531257eb6979e1e90117316004a643c60a8 Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Tue, 9 Jan 2024 06:46:52 +0900 Subject: [PATCH 10/12] fix(stepfunctions): retry block in CustomState is always empty (#28598) Currently it is not possible to set Retry for the Task when using CustomState construct. There are two ways to add Retry: by adding the `addRetry` method or by rendering the `Retry` property of `stateJson`. The `addRetry` method was added in this PR because rendering the `Retry` property of `stateJson`, which was not rendered before, could result in an unexpected StateMachine for the user. Closes #28586 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...epfunctions-custom-state-integ.assets.json | 6 +-- ...functions-custom-state-integ.template.json | 4 +- .../integ.custom-state.js.snapshot/cdk.out | 2 +- .../integ.custom-state.js.snapshot/integ.json | 2 +- .../manifest.json | 5 ++- .../integ.custom-state.js.snapshot/tree.json | 38 +++++++++------- .../test/integ.custom-state.ts | 5 +++ .../aws-cdk-lib/aws-stepfunctions/README.md | 7 +++ .../lib/states/custom-state.ts | 13 +++++- .../test/custom-state.test.ts | 43 +++++++++++++++++++ 10 files changed, 100 insertions(+), 25 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.assets.json index 852466be8943d..673c6aba98278 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "30.0.0", + "version": "36.0.0", "files": { - "88187762ebb3676ec68ded03ce92c045563205c6497ae5a104f13a32dbf4ef43": { + "009040dbb1873c31d45ee6be45381ed16bbf81f9a642799664531ba2f3c56832": { "source": { "path": "aws-stepfunctions-custom-state-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "88187762ebb3676ec68ded03ce92c045563205c6497ae5a104f13a32dbf4ef43.json", + "objectKey": "009040dbb1873c31d45ee6be45381ed16bbf81f9a642799664531ba2f3c56832.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.template.json index b090502f0294b..be6ebd9dd8583 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.template.json @@ -20,13 +20,13 @@ "StateMachine2E01A3A5": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { + "DefinitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null,\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":10,\"MaxAttempts\":5}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}", "RoleArn": { "Fn::GetAtt": [ "StateMachineRoleB840431D", "Arn" ] - }, - "DefinitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null,\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}" + } }, "DependsOn": [ "StateMachineRoleB840431D" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/cdk.out index ae4b03c54e770..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/integ.json index 624779da650bd..3c6ca76f840ab 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "36.0.0", "testCases": { "integ.custom-state": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/manifest.json index 1607ee7800b57..0bd5238d6c5f6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "36.0.0", "artifacts": { "aws-stepfunctions-custom-state-integ.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "aws-stepfunctions-custom-state-integ.template.json", + "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/88187762ebb3676ec68ded03ce92c045563205c6497ae5a104f13a32dbf4ef43.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/009040dbb1873c31d45ee6be45381ed16bbf81f9a642799664531ba2f3c56832.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/tree.json index 6544935df1c46..c33567eaa9d4c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/tree.json @@ -12,7 +12,15 @@ "id": "final step", "path": "aws-stepfunctions-custom-state-integ/final step", "constructInfo": { - "fqn": "@aws-cdk/aws-stepfunctions.Pass", + "fqn": "aws-cdk-lib.aws_stepfunctions.Pass", + "version": "0.0.0" + } + }, + "failed": { + "id": "failed", + "path": "aws-stepfunctions-custom-state-integ/failed", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions.Fail", "version": "0.0.0" } }, @@ -20,7 +28,7 @@ "id": "my custom task", "path": "aws-stepfunctions-custom-state-integ/my custom task", "constructInfo": { - "fqn": "@aws-cdk/aws-stepfunctions.CustomState", + "fqn": "aws-cdk-lib.aws_stepfunctions.CustomState", "version": "0.0.0" } }, @@ -36,7 +44,7 @@ "id": "ImportRole", "path": "aws-stepfunctions-custom-state-integ/StateMachine/Role/ImportRole", "constructInfo": { - "fqn": "@aws-cdk/core.Resource", + "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" } }, @@ -61,13 +69,13 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnRole", + "fqn": "aws-cdk-lib.aws_iam.CfnRole", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Role", + "fqn": "aws-cdk-lib.aws_iam.Role", "version": "0.0.0" } }, @@ -77,23 +85,23 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", "aws:cdk:cloudformation:props": { + "definitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null,\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":10,\"MaxAttempts\":5}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}", "roleArn": { "Fn::GetAtt": [ "StateMachineRoleB840431D", "Arn" ] - }, - "definitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null},\"final step\":{\"Type\":\"Pass\",\"End\":true}},\"TimeoutSeconds\":30}" + } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-stepfunctions.CfnStateMachine", + "fqn": "aws-cdk-lib.aws_stepfunctions.CfnStateMachine", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-stepfunctions.StateMachine", + "fqn": "aws-cdk-lib.aws_stepfunctions.StateMachine", "version": "0.0.0" } }, @@ -101,7 +109,7 @@ "id": "StateMachineARN", "path": "aws-stepfunctions-custom-state-integ/StateMachineARN", "constructInfo": { - "fqn": "@aws-cdk/core.CfnOutput", + "fqn": "aws-cdk-lib.CfnOutput", "version": "0.0.0" } }, @@ -109,7 +117,7 @@ "id": "BootstrapVersion", "path": "aws-stepfunctions-custom-state-integ/BootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", + "fqn": "aws-cdk-lib.CfnParameter", "version": "0.0.0" } }, @@ -117,13 +125,13 @@ "id": "CheckBootstrapVersion", "path": "aws-stepfunctions-custom-state-integ/CheckBootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", + "fqn": "aws-cdk-lib.CfnRule", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.Stack", + "fqn": "aws-cdk-lib.Stack", "version": "0.0.0" } }, @@ -132,12 +140,12 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.3.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.App", + "fqn": "aws-cdk-lib.App", "version": "0.0.0" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.ts index 5d28b12436975..0d30c3d1b771b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.ts @@ -35,6 +35,11 @@ const custom = new sfn.CustomState(stack, 'my custom task', { }); custom.addCatch(failure); +custom.addRetry({ + errors: [sfn.Errors.ALL], + interval: cdk.Duration.seconds(10), + maxAttempts: 5, +}); const chain = sfn.Chain.start(custom).next(finalStatus); diff --git a/packages/aws-cdk-lib/aws-stepfunctions/README.md b/packages/aws-cdk-lib/aws-stepfunctions/README.md index aef1e2ffaa631..6ddae341b2506 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions/README.md +++ b/packages/aws-cdk-lib/aws-stepfunctions/README.md @@ -602,6 +602,13 @@ const custom = new sfn.CustomState(this, 'my custom task', { const errorHandler = new sfn.Pass(this, 'handle failure'); custom.addCatch(errorHandler); +// retry the task if something goes wrong +custom.addRetry({ + errors: [sfn.Errors.ALL], + interval: Duration.seconds(10), + maxAttempts: 5, +}); + const chain = sfn.Chain.start(custom) .next(finalStatus); diff --git a/packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts b/packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts index db66a5a8de17f..fd247118c6347 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { State } from './state'; import { Chain } from '..'; -import { CatchProps, IChainable, INextable } from '../types'; +import { CatchProps, IChainable, INextable, RetryProps } from '../types'; /** * Properties for defining a custom state definition @@ -34,6 +34,17 @@ export class CustomState extends State implements IChainable, INextable { this.stateJson = props.stateJson; } + /** + * Add retry configuration for this state + * + * This controls if and how the execution will be retried if a particular + * error occurs. + */ + public addRetry(props: RetryProps = {}): CustomState { + super._addRetry(props); + return this; + } + /** * Add a recovery handler for this state * diff --git a/packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts b/packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts index 766b8ac659abe..7935f911e9977 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts @@ -120,4 +120,47 @@ describe('Custom State', () => { }, ); }); + + test('can add a retry state', () => { + // GIVEN + const custom = new sfn.CustomState(stack, 'Custom', { + stateJson, + }); + const chain = sfn.Chain.start(custom); + + // WHEN + custom.addRetry({ + errors: [sfn.Errors.ALL], + interval: cdk.Duration.seconds(10), + maxAttempts: 5, + }); + + // THEN + expect(render(stack, chain)).toStrictEqual( + { + StartAt: 'Custom', + States: { + Custom: { + Type: 'Task', + Resource: 'arn:aws:states:::dynamodb:putItem', + Parameters: { + TableName: 'MyTable', + Item: { + id: { + S: 'MyEntry', + }, + }, + }, + ResultPath: null, + Retry: [{ + ErrorEquals: ['States.ALL'], + IntervalSeconds: 10, + MaxAttempts: 5, + }], + End: true, + }, + }, + }, + ); + }); }); \ No newline at end of file From 22e6ce8ad211955bcfa6d189f03e86c5a9727b36 Mon Sep 17 00:00:00 2001 From: Ayush Shah Date: Tue, 9 Jan 2024 03:44:45 +0530 Subject: [PATCH 11/12] fix(ec2): passing keypair to instance unexpectedly does nothing (#28482) Fixes by Specifying key pair reference in cfnInstance. This will change behavior if both `keyName` and `keyPair` is set on an existing resource, since we will use `keyPair.keyPairName` instead of `keyName` now. However, there is no correct use case for specifying both `keyPair` and `keyName`, and given `keyName` is deprecated, this PR is introducing the correct behavior. Closes #28478. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssertF103D058.assets.json | 2 +- .../__entrypoint__.js | 147 ++++++++++++++++++ .../index.js | 0 .../__entrypoint__.js | 147 ------------------ .../aws-cdk-ec2-key-pair-1.assets.json | 12 +- .../aws-cdk-ec2-key-pair-1.template.json | 5 +- .../test/integ.key-pair.js.snapshot/cdk.out | 2 +- .../integ.key-pair.js.snapshot/integ.json | 2 +- .../integ.key-pair.js.snapshot/manifest.json | 9 +- .../test/integ.key-pair.js.snapshot/tree.json | 5 +- packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 4 +- .../aws-ec2/lib/launch-template.ts | 2 +- packages/aws-cdk-lib/aws-ec2/lib/nat.ts | 2 +- .../aws-cdk-lib/aws-ec2/test/instance.test.ts | 20 +++ 14 files changed, 194 insertions(+), 165 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js rename packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/{asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03 => asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292}/index.js (100%) delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json index 25e7ca0bd298d..364588a780e55 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/KeyPairTestDefaultTestDeployAssertF103D058.assets.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js new file mode 100644 index 0000000000000..1e64dba70bdc0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/__entrypoint__.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js similarity index 100% rename from packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/index.js rename to packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292/index.js diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js deleted file mode 100644 index c83ecebaaadac..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03/__entrypoint__.js +++ /dev/null @@ -1,147 +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': Buffer.byteLength(responseBody, 'utf8'), - }, - }; - const retryOptions = { - attempts: 5, - sleep: 1000, - }; - await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); -} -async function defaultSendHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, _ => resolve()); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -function defaultLog(fmt, ...params) { - // eslint-disable-next-line no-console - console.log(fmt, ...params); -} -function withRetries(options, fn) { - return async (...xs) => { - let attempts = options.attempts; - let ms = options.sleep; - while (true) { - try { - return await fn(...xs); - } - catch (e) { - if (attempts-- <= 0) { - throw e; - } - await sleep(Math.floor(Math.random() * ms)); - ms *= 2; - } - } - }; -} -exports.withRetries = withRetries; -async function sleep(ms) { - return new Promise((ok) => setTimeout(ok, ms)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBTSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQztTQUMxRDtLQUNGLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRztRQUNuQixRQUFRLEVBQUUsQ0FBQztRQUNYLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQztJQUNGLE1BQU0sV0FBVyxDQUFDLFlBQVksRUFBRSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBU0QsU0FBZ0IsV0FBVyxDQUEwQixPQUFxQixFQUFFLEVBQTRCO0lBQ3RHLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBSyxFQUFFLEVBQUU7UUFDeEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxFQUFFO1lBQ1gsSUFBSTtnQkFDRixPQUFPLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFDeEI7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixJQUFJLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxDQUFDLENBQUM7aUJBQ1Q7Z0JBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBaEJELGtDQWdCQztBQUVELEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUM3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ2NvbnRlbnQtdHlwZSc6ICcnLFxuICAgICAgJ2NvbnRlbnQtbGVuZ3RoJzogQnVmZmVyLmJ5dGVMZW5ndGgocmVzcG9uc2VCb2R5LCAndXRmOCcpLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgcmV0cnlPcHRpb25zID0ge1xuICAgIGF0dGVtcHRzOiA1LFxuICAgIHNsZWVwOiAxMDAwLFxuICB9O1xuICBhd2FpdCB3aXRoUmV0cmllcyhyZXRyeU9wdGlvbnMsIGV4dGVybmFsLnNlbmRIdHRwUmVxdWVzdCkocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmV0cmllcyAod2lsbCBhdCBsZWFzdCB0cnkgb25jZSkgKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdHM6IG51bWJlcjtcbiAgLyoqIFNsZWVwIGJhc2UsIGluIG1zICovXG4gIHJlYWRvbmx5IHNsZWVwOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUmV0cmllczxBIGV4dGVuZHMgQXJyYXk8YW55PiwgQj4ob3B0aW9uczogUmV0cnlPcHRpb25zLCBmbjogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+KTogKC4uLnhzOiBBKSA9PiBQcm9taXNlPEI+IHtcbiAgcmV0dXJuIGFzeW5jICguLi54czogQSkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IG9wdGlvbnMuYXR0ZW1wdHM7XG4gICAgbGV0IG1zID0gb3B0aW9ucy5zbGVlcDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZuKC4uLnhzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGF0dGVtcHRzLS0gPD0gMCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbXMpKTtcbiAgICAgICAgbXMgKj0gMjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaykgPT4gc2V0VGltZW91dChvaywgbXMpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json index 2c8f5dc8b9a80..0a285e199ffc2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.assets.json @@ -1,20 +1,20 @@ { - "version": "35.0.0", + "version": "36.0.0", "files": { - "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03": { + "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292": { "source": { - "path": "asset.a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03", + "path": "asset.4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03.zip", + "objectKey": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314": { + "8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3": { "source": { "path": "aws-cdk-ec2-key-pair-1.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314.json", + "objectKey": "8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json index 5ef53a1122263..35587df413651 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/aws-cdk-ec2-key-pair-1.template.json @@ -489,7 +489,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a099fdfc61c84ffc56cef4fb2c9472483623ac865ce5d8fca88c89cf60d48d03.zip" + "S3Key": "4554b47be6f57b68c6c7a7391dcc73894866d2377fe174883351e7639097f292.zip" }, "Timeout": 900, "MemorySize": 128, @@ -588,6 +588,9 @@ "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" }, "InstanceType": "t3.micro", + "KeyName": { + "Ref": "TestKeyPair38B6CD21" + }, "SecurityGroupIds": [ { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out index c5cb2e5de6344..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"35.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json index bb4e985790260..4dcce8053c150 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "testCases": { "KeyPairTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json index 4d7164db4e4eb..c176b681fa22b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "artifacts": { "aws-cdk-ec2-key-pair-1.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${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}/a17370fc201600e810dc71ba186bc1364ba4ba62f0be6d1728a6c27cefbc3314.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8c4cbb697124e95a3c20e138544dceb56449d63ce6613a98fa1214c0a4f583c3.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -217,7 +217,10 @@ "/aws-cdk-ec2-key-pair-1/TestInstance/Resource": [ { "type": "aws:cdk:logicalId", - "data": "TestInstance44016A9E" + "data": "TestInstance44016A9E", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] } ], "/aws-cdk-ec2-key-pair-1/SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json index 64cc246f6004d..4c550ee2da1fb 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.key-pair.js.snapshot/tree.json @@ -699,7 +699,7 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.CustomResourceProvider", + "fqn": "aws-cdk-lib.CustomResourceProviderBase", "version": "0.0.0" } }, @@ -861,6 +861,9 @@ "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" }, "instanceType": "t3.micro", + "keyName": { + "Ref": "TestKeyPair38B6CD21" + }, "securityGroupIds": [ { "Fn::GetAtt": [ diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts index e38d99f1354b9..22691162731de 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts @@ -77,7 +77,7 @@ export interface InstanceProps { * Name of SSH keypair to grant access to instance * * @default - No SSH access will be possible. - * @deprecated - Use {@link keyPair} instead + * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair */ readonly keyName?: string; @@ -437,7 +437,7 @@ export class Instance extends Resource implements IInstance { // there is no need to configure them on the instance level this.instance = new CfnInstance(this, 'Resource', { imageId: imageConfig.imageId, - keyName: props.keyName, + keyName: props.keyPair?.keyPairName ?? props?.keyName, instanceType: props.instanceType.toString(), subnetId: networkInterfaces ? undefined : subnet.subnetId, securityGroupIds: networkInterfaces ? undefined : securityGroupsToken, diff --git a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts index 9395afea35794..a245ea35fee2c 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts @@ -333,7 +333,7 @@ export interface LaunchTemplateProps { * Name of SSH keypair to grant access to instance * * @default - No SSH access will be possible. - * @deprecated - Use `keyPair` instead. + * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair */ readonly keyName?: string; diff --git a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts index b339b4e86fdc0..25c7c0b1d7f1f 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts @@ -172,7 +172,7 @@ export interface NatInstanceProps { * Name of SSH keypair to grant access to instance * * @default - No SSH access will be possible. - * @deprecated - Use `keyPair` instead. + * @deprecated - Use `keyPair` instead - https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#using-an-existing-ec2-key-pair */ readonly keyName?: string; diff --git a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts index 8c902c1c51281..d188acae592b3 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts @@ -520,6 +520,26 @@ describe('instance', () => { })).toThrow('Cannot specify both of \'keyName\' and \'keyPair\'; prefer \'keyPair\''); }); + it('correctly associates a key pair', () => { + // GIVEN + const keyPair = new KeyPair(stack, 'KeyPair', { + keyPairName: 'test-key-pair', + }); + + // WHEN + new Instance(stack, 'Instance', { + vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: new AmazonLinuxImage(), + keyPair, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + KeyName: stack.resolve(keyPair.keyPairName), + }); + }); + describe('Detailed Monitoring', () => { test('instance with Detailed Monitoring enabled', () => { // WHEN From 178b84549c08f6cf27927e5a686fc333e0859582 Mon Sep 17 00:00:00 2001 From: Kendra Neil <53584728+TheRealAmazonKendra@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:41:04 -0800 Subject: [PATCH 12/12] chore: update cdk-from-cfn version (#28619) > REPLACE THIS TEXT BLOCK > > Describe the reason for this change, what the solution is, and any > important design decisions you made. > > Remember to follow the [CONTRIBUTING GUIDE] and [DESIGN GUIDELINES] for any > code you submit. > > [CONTRIBUTING GUIDE]: https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md > [DESIGN GUIDELINES]: https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md Closes #. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES | 2 +- packages/aws-cdk/package.json | 4 ++-- packages/aws-cdk/test/commands/migrate.test.ts | 2 +- .../aws-cdk/test/commands/test-resources/stacks/s3.go | 8 ++++++-- yarn.lock | 8 ++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES index c430595bb0514..f30587af1bb0e 100644 --- a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES @@ -668,7 +668,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** cdk-from-cfn@0.91.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.91.0 | MIT OR Apache-2.0 +** cdk-from-cfn@0.113.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.113.0 | MIT OR Apache-2.0 ---------------- diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index aacecd7a729e7..49948f4fbe79c 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -105,7 +105,7 @@ "aws-sdk": "^2.1517.0", "camelcase": "^6.3.0", "cdk-assets": "0.0.0", - "cdk-from-cfn": "^0.91.0", + "cdk-from-cfn": "^0.113.0", "chalk": "^4", "chokidar": "^3.5.3", "decamelize": "^5.0.1", @@ -155,4 +155,4 @@ "publishConfig": { "tag": "latest" } -} +} \ No newline at end of file diff --git a/packages/aws-cdk/test/commands/migrate.test.ts b/packages/aws-cdk/test/commands/migrate.test.ts index e3cc14a8475da..c26870bc85b7b 100644 --- a/packages/aws-cdk/test/commands/migrate.test.ts +++ b/packages/aws-cdk/test/commands/migrate.test.ts @@ -215,7 +215,7 @@ describe('Migrate Function Tests', () => { expect(fs.pathExists(path.join(workDir, 's3.go'))).toBeTruthy(); const app = fs.readFileSync(path.join(workDir, 'GoodGo', 'good_go.go'), 'utf8').split('\n'); - expect(app.map(line => line.match(/func NewGoodGoStack\(scope constructs.Construct, id string, props GoodGoStackProps\) \*GoodGoStack \{/)).filter(line => line).length).toEqual(1); + expect(app.map(line => line.match(/func NewGoodGoStack\(scope constructs.Construct, id string, props \*GoodGoStackProps\) \*GoodGoStack \{/)).filter(line => line).length).toEqual(1); expect(app.map(line => line.match(/ NewGoodGoStack\(app, "GoodGo", &GoodGoStackProps\{/))); }); diff --git a/packages/aws-cdk/test/commands/test-resources/stacks/s3.go b/packages/aws-cdk/test/commands/test-resources/stacks/s3.go index ea2a77e048635..e4bdb893aa5ea 100644 --- a/packages/aws-cdk/test/commands/test-resources/stacks/s3.go +++ b/packages/aws-cdk/test/commands/test-resources/stacks/s3.go @@ -20,8 +20,12 @@ type GoodGoStack struct { S3BucketSecureUrl interface{} // TODO: fix to appropriate type } -func NewGoodGoStack(scope constructs.Construct, id string, props GoodGoStackProps) *GoodGoStack { - stack := cdk.NewStack(scope, &id, &props.StackProps) +func NewGoodGoStack(scope constructs.Construct, id string, props *GoodGoStackProps) *GoodGoStack { + var sprops cdk.StackProps + if props != nil { + sprops = props.StackProps + } + stack := cdk.NewStack(scope, &id, &sprops) s3Bucket := s3.NewCfnBucket( stack, diff --git a/yarn.lock b/yarn.lock index d9e8f04956dec..f39469e4c3559 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6246,10 +6246,10 @@ case@1.6.3, case@^1.6.3: resolved "https://registry.npmjs.org/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== -cdk-from-cfn@^0.91.0: - version "0.91.0" - resolved "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.91.0.tgz#d1858e323b749d130cc073b098367bd354f21afa" - integrity sha512-ZkeA2Iws4LCg7QqeF+iVjZ5U0MaNni+O0RSEocGxKMvbn4SG/Z1Ib/lWBQZX32ZvuqpgUCUOL3askIuZ7e3+5g== +cdk-from-cfn@^0.113.0: + version "0.113.0" + resolved "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.113.0.tgz#b68832b84ce939d525b9660f928a2aef028cc867" + integrity sha512-cBsPHyg6tNvy4JRHwQpkUh5U6Te5fUAxZX2RhIlaOVT/Ci40PjPYFDhStC1BFl+L3O9uZTmy/OY8CkjlZsWvlw== cdk-generate-synthetic-examples@^0.1.299: version "0.1.299"