diff --git a/packages/@aws-cdk/integ-runner/lib/runner/private/cloud-assembly.ts b/packages/@aws-cdk/integ-runner/lib/runner/private/cloud-assembly.ts index 71a08392615db..9420f2113561a 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/private/cloud-assembly.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/private/cloud-assembly.ts @@ -78,6 +78,25 @@ export class AssemblyManifestReader { return stacks; } + /** + * Get the nested stacks for a given stack + * returns a map of artifactId to CloudFormation template + */ + public getNestedStacksForStack(stackId: string): Record { + const nestedTemplates: string[] = this.getAssetManifestsForStack(stackId).flatMap( + manifest => manifest.files + .filter(asset => asset.source.path?.endsWith('.nested.template.json')) + .map(asset => asset.source.path!), + ); + + const nestedStacks: Record = Object.fromEntries(nestedTemplates.map(templateFile => ([ + templateFile.split('.', 1)[0], + fs.readJSONSync(path.resolve(this.directory, templateFile)), + ]))); + + return nestedStacks; + } + /** * Write trace data to the assembly manifest metadata */ @@ -125,6 +144,19 @@ export class AssemblyManifestReader { return assets; } + /** + * Return a list of asset artifacts for a given stack + */ + public getAssetManifestsForStack(stackId: string): AssetManifest[] { + return Object.values(this.manifest.artifacts ?? {}) + .filter(artifact => + artifact.type === ArtifactType.ASSET_MANIFEST && (artifact.properties as AssetManifestProperties)?.file === `${stackId}.assets.json`) + .map(artifact => { + const fileName = (artifact.properties as AssetManifestProperties).file; + return AssetManifest.fromFile(path.join(this.directory, fileName)); + }); + } + /** * Get a list of assets from the assembly manifest */ @@ -153,7 +185,7 @@ export class AssemblyManifestReader { assetManifest.entries.forEach(entry => { if (entry.type === 'file') { const source = (entry as FileManifestEntry).source; - if (source.path && source.path.startsWith('asset.')) { + if (source.path && (source.path.startsWith('asset.') || source.path.endsWith('nested.template.json'))) { assets.push(entry as FileManifestEntry); } } else if (entry.type === 'docker-image') { 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 fd7ef514d51a0..c832d1a3f5437 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 @@ -6,6 +6,25 @@ import { Diagnostic, DiagnosticReason, DestructiveChange, SnapshotVerificationOp import { AssemblyManifestReader } from './private/cloud-assembly'; import { IntegRunnerOptions, IntegRunner, DEFAULT_SYNTH_OPTIONS } from './runner-base'; +interface SnapshotAssembly { + /** + * Map of stacks that are part of this assembly + */ + [key: string]: { + /** + * All templates for this stack, including nested stacks + */ + templates: { + [key: string]: any + }, + + /** + * List of asset Ids that are used by this assembly + */ + assets: string[] + } +} + /** * Runner for snapshot tests. This handles orchestrating * the validation of the integration test snapshots @@ -24,15 +43,7 @@ export class IntegSnapshotRunner extends IntegRunner { public testSnapshot(options: SnapshotVerificationOptions = {}): { diagnostics: Diagnostic[], destructiveChanges: DestructiveChange[] } { let doClean = true; try { - // read the existing snapshot - const expectedStacks = this.readAssembly(this.snapshotDir); - // only diff stacks that are part of the test case - const expectedStacksToDiff: Record = {}; - for (const [stackName, template] of Object.entries(expectedStacks)) { - if (this.expectedTestSuite?.stacks.includes(stackName)) { - expectedStacksToDiff[stackName] = template; - } - } + const expectedSnapshotAssembly = this.getSnapshotAssembly(this.snapshotDir, this.expectedTestSuite?.stacks); // synth the integration test // FIXME: ideally we should not need to run this again if @@ -52,18 +63,10 @@ export class IntegSnapshotRunner extends IntegRunner { }); // read the "actual" snapshot - const actualDir = this.cdkOutDir; - const actualStacks = this.readAssembly(actualDir); - // only diff stacks that are part of the test case - const actualStacksToDiff: Record = {}; - for (const [stackName, template] of Object.entries(actualStacks)) { - if (this.actualTestSuite.stacks.includes(stackName)) { - actualStacksToDiff[stackName] = template; - } - } + const actualSnapshotAssembly = this.getSnapshotAssembly(this.cdkOutDir, this.actualTestSuite.stacks); // diff the existing snapshot (expected) with the integration test (actual) - const diagnostics = this.diffAssembly(expectedStacksToDiff, actualStacksToDiff); + const diagnostics = this.diffAssembly(expectedSnapshotAssembly, actualSnapshotAssembly); if (diagnostics.diagnostics.length) { // Attach additional messages to the first diagnostic @@ -72,7 +75,7 @@ export class IntegSnapshotRunner extends IntegRunner { if (options.retain) { additionalMessages.push( `(Failure retained) Expected: ${path.relative(process.cwd(), this.snapshotDir)}`, - ` Actual: ${path.relative(process.cwd(), actualDir)}`, + ` Actual: ${path.relative(process.cwd(), this.cdkOutDir)}`, ), doClean = false; } @@ -107,6 +110,36 @@ export class IntegSnapshotRunner extends IntegRunner { } } + /** + * For a given cloud assembly return a collection of all templates + * that should be part of the snapshot and any required meta data. + * + * @param cloudAssemblyDir The directory of the cloud assembly to look for snapshots + * @param pickStacks Pick only these stacks from the cloud assembly + * @returns A SnapshotAssembly, the collection of all templates in this snapshot and required meta data + */ + private getSnapshotAssembly(cloudAssemblyDir: string, pickStacks: string[] = []): SnapshotAssembly { + const assembly = this.readAssembly(cloudAssemblyDir); + const stacks = assembly.stacks; + const snapshots: SnapshotAssembly = {}; + for (const [stackName, stackTemplate] of Object.entries(stacks)) { + if (pickStacks.includes(stackName)) { + const manifest = AssemblyManifestReader.fromPath(cloudAssemblyDir); + const assets = manifest.getAssetIdsForStack(stackName); + + snapshots[stackName] = { + templates: { + [stackName]: stackTemplate, + ...assembly.getNestedStacksForStack(stackName), + }, + assets, + }; + } + } + + return snapshots; + } + /** * For a given stack return all resource types that are allowed to be destroyed * as part of a stack update @@ -131,86 +164,94 @@ export class IntegSnapshotRunner extends IntegRunner { * @returns any diagnostics and any destructive changes */ private diffAssembly( - expected: Record, - actual: Record, + expected: SnapshotAssembly, + actual: SnapshotAssembly, ): { diagnostics: Diagnostic[], destructiveChanges: DestructiveChange[] } { const failures: Diagnostic[] = []; const destructiveChanges: DestructiveChange[] = []; // check if there is a CFN template in the current snapshot // that does not exist in the "actual" snapshot - for (const templateId of Object.keys(expected)) { - if (!actual.hasOwnProperty(templateId)) { - failures.push({ - testName: this.testName, - reason: DiagnosticReason.SNAPSHOT_FAILED, - message: `${templateId} exists in snapshot, but not in actual`, - }); + for (const [stackId, stack] of Object.entries(expected)) { + for (const templateId of Object.keys(stack.templates)) { + if (!actual[stackId]?.templates[templateId]) { + failures.push({ + testName: this.testName, + stackName: templateId, + reason: DiagnosticReason.SNAPSHOT_FAILED, + message: `${templateId} exists in snapshot, but not in actual`, + }); + } } } - for (const templateId of Object.keys(actual)) { + for (const [stackId, stack] of Object.entries(actual)) { + for (const templateId of Object.keys(stack.templates)) { // check if there is a CFN template in the "actual" snapshot // that does not exist in the current snapshot - if (!expected.hasOwnProperty(templateId)) { - failures.push({ - testName: this.testName, - reason: DiagnosticReason.SNAPSHOT_FAILED, - message: `${templateId} does not exist in snapshot, but does in actual`, - }); - continue; - } else { - let actualTemplate = actual[templateId]; - let expectedTemplate = expected[templateId]; - const allowedDestroyTypes = this.getAllowedDestroyTypesForStack(templateId) ?? []; - - // if we are not verifying asset hashes then remove the specific - // asset hashes from the templates so they are not part of the diff - // comparison - if (!this.actualTestSuite.getOptionsForStack(templateId)?.diffAssets) { - actualTemplate = this.canonicalizeTemplate(actualTemplate, templateId, this.cdkOutDir); - expectedTemplate = this.canonicalizeTemplate(expectedTemplate, templateId, this.snapshotDir); - } - const templateDiff = diffTemplate(expectedTemplate, actualTemplate); - if (!templateDiff.isEmpty) { - // go through all the resource differences and check for any - // "destructive" changes - templateDiff.resources.forEachDifference((logicalId: string, change: ResourceDifference) => { + if (!expected[stackId]?.templates[templateId]) { + failures.push({ + testName: this.testName, + stackName: templateId, + reason: DiagnosticReason.SNAPSHOT_FAILED, + message: `${templateId} does not exist in snapshot, but does in actual`, + }); + continue; + } else { + let actualTemplate = actual[stackId].templates[templateId]; + let expectedTemplate = expected[stackId].templates[templateId]; + + // if we are not verifying asset hashes then remove the specific + // asset hashes from the templates so they are not part of the diff + // comparison + if (!this.actualTestSuite.getOptionsForStack(stackId)?.diffAssets) { + actualTemplate = this.canonicalizeTemplate(actualTemplate, actual[stackId].assets); + expectedTemplate = this.canonicalizeTemplate(expectedTemplate, expected[stackId].assets); + } + const templateDiff = diffTemplate(expectedTemplate, actualTemplate); + if (!templateDiff.isEmpty) { + const allowedDestroyTypes = this.getAllowedDestroyTypesForStack(stackId) ?? []; + + // go through all the resource differences and check for any + // "destructive" changes + templateDiff.resources.forEachDifference((logicalId: string, change: ResourceDifference) => { // if the change is a removal it will not show up as a 'changeImpact' // so need to check for it separately, unless it is a resourceType that // has been "allowed" to be destroyed - const resourceType = change.oldValue?.Type ?? change.newValue?.Type; - if (resourceType && allowedDestroyTypes.includes(resourceType)) { - return; - } - if (change.isRemoval) { - destructiveChanges.push({ - impact: ResourceImpact.WILL_DESTROY, - logicalId, - stackName: templateId, - }); - } else { - switch (change.changeImpact) { - case ResourceImpact.MAY_REPLACE: - case ResourceImpact.WILL_ORPHAN: - case ResourceImpact.WILL_DESTROY: - case ResourceImpact.WILL_REPLACE: - destructiveChanges.push({ - impact: change.changeImpact, - logicalId, - stackName: templateId, - }); - break; + const resourceType = change.oldValue?.Type ?? change.newValue?.Type; + if (resourceType && allowedDestroyTypes.includes(resourceType)) { + return; } - } - }); - const writable = new StringWritable({}); - formatDifferences(writable, templateDiff); - failures.push({ - reason: DiagnosticReason.SNAPSHOT_FAILED, - message: writable.data, - testName: this.testName, - }); + if (change.isRemoval) { + destructiveChanges.push({ + impact: ResourceImpact.WILL_DESTROY, + logicalId, + stackName: templateId, + }); + } else { + switch (change.changeImpact) { + case ResourceImpact.MAY_REPLACE: + case ResourceImpact.WILL_ORPHAN: + case ResourceImpact.WILL_DESTROY: + case ResourceImpact.WILL_REPLACE: + destructiveChanges.push({ + impact: change.changeImpact, + logicalId, + stackName: templateId, + }); + break; + } + } + }); + const writable = new StringWritable({}); + formatDifferences(writable, templateDiff); + failures.push({ + reason: DiagnosticReason.SNAPSHOT_FAILED, + message: writable.data, + stackName: templateId, + testName: this.testName, + }); + } } } } @@ -221,11 +262,8 @@ export class IntegSnapshotRunner extends IntegRunner { }; } - private readAssembly(dir: string): Record { - const assembly = AssemblyManifestReader.fromPath(dir); - const stacks = assembly.stacks; - - return stacks; + private readAssembly(dir: string): AssemblyManifestReader { + return AssemblyManifestReader.fromPath(dir); } /** @@ -234,7 +272,7 @@ export class IntegSnapshotRunner extends IntegRunner { * This makes it possible to compare templates if all that's different between * them is the hashes of the asset values. */ - private canonicalizeTemplate(template: any, stackName: string, manifestDir: string): any { + private canonicalizeTemplate(template: any, assets: string[]): any { const assetsSeen = new Set(); const stringSubstitutions = new Array<[RegExp, string]>(); @@ -262,8 +300,6 @@ export class IntegSnapshotRunner extends IntegRunner { // find assets defined in the asset manifest try { - const manifest = AssemblyManifestReader.fromPath(manifestDir); - const assets = manifest.getAssetIdsForStack(stackName); assets.forEach(asset => { if (!assetsSeen.has(asset)) { assetsSeen.add(asset); diff --git a/packages/@aws-cdk/integ-runner/lib/workers/common.ts b/packages/@aws-cdk/integ-runner/lib/workers/common.ts index 7f49cb73b864c..fc8babd7a05a9 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/common.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/common.ts @@ -221,6 +221,11 @@ export interface Diagnostic { */ readonly testName: string; + /** + * The name of the stack + */ + readonly stackName: string; + /** * The diagnostic message */ diff --git a/packages/@aws-cdk/integ-runner/package.json b/packages/@aws-cdk/integ-runner/package.json index 2f9199680f427..809b2a923cc9d 100644 --- a/packages/@aws-cdk/integ-runner/package.json +++ b/packages/@aws-cdk/integ-runner/package.json @@ -52,7 +52,12 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-sns": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@types/mock-fs": "^4.13.1", + "constructs": "^10.0.0", "mock-fs": "^4.14.0", "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^8.1.2", diff --git a/packages/@aws-cdk/integ-runner/test/cli.test.ts b/packages/@aws-cdk/integ-runner/test/cli.test.ts index bf61aa7633aac..95d53dd58b706 100644 --- a/packages/@aws-cdk/integ-runner/test/cli.test.ts +++ b/packages/@aws-cdk/integ-runner/test/cli.test.ts @@ -32,6 +32,7 @@ describe('CLI', () => { [ 'xxxxx.integ-test1.js', 'xxxxx.integ-test2.js', + 'xxxxx.test-with-nested-stack.js', 'xxxxx.test-with-new-assets-diff.js', 'xxxxx.test-with-new-assets.js', 'xxxxx.test-with-snapshot-assets-diff.js', diff --git a/packages/@aws-cdk/integ-runner/test/helpers.ts b/packages/@aws-cdk/integ-runner/test/helpers.ts index 238bb77e1695d..6f60379a8f7b6 100644 --- a/packages/@aws-cdk/integ-runner/test/helpers.ts +++ b/packages/@aws-cdk/integ-runner/test/helpers.ts @@ -68,6 +68,7 @@ export class MockCdkProvider { }), integOutDir: actualSnapshot ? 'test/test-data/' + actualSnapshot : undefined, }); + integTest.actualTests(); const results = integTest.testSnapshot(); // THEN diff --git a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts index 89101796b966e..958380e5df5ef 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts @@ -99,6 +99,21 @@ describe('IntegTest runSnapshotTests', () => { })])); }); + describe('Nested Stacks', () => { + test('it will compare snapshots for nested stacks', () => { + // WHEN + const results = cdkMock.snapshotTest('xxxxx.test-with-nested-stack.js', 'xxxxx.test-with-nested-stack-changed.js.snapshot'); + + // THEN + expect(results.diagnostics).toEqual(expect.arrayContaining([expect.objectContaining({ + reason: DiagnosticReason.SNAPSHOT_FAILED, + testName: 'xxxxx.test-with-nested-stack', + stackName: expect.stringContaining('teststacknested'), + message: expect.stringContaining('AWS::SNS::Topic'), + })])); + }); + }); + describe('Legacy parameter based assets ', () => { test('diff asset hashes', () => { // WHEN diff --git a/packages/@aws-cdk/integ-runner/test/test-data/assets/code-asset/.keep b/packages/@aws-cdk/integ-runner/test/test-data/assets/code-asset/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json new file mode 100644 index 0000000000000..91488886727c6 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/cdk.out b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/integ.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/integ.json new file mode 100644 index 0000000000000..56b2c82cb6d9e --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "TestWithNestedStack/DefaultTest": { + "stacks": [ + "test-stack" + ], + "assertionStack": "TestWithNestedStack/DefaultTest/DeployAssert", + "assertionStackName": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/manifest.json new file mode 100644 index 0000000000000..e45aa1d70111d --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/manifest.json @@ -0,0 +1,141 @@ +{ + "version": "21.0.0", + "artifacts": { + "test-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "test-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-stack.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "test-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "test-stack.assets" + ], + "metadata": { + "/test-stack/MyFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunctionServiceRole3C357FF2" + } + ], + "/test-stack/MyFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction3BAA72D1" + } + ], + "/test-stack/nested/MyTopic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyTopic86869434" + } + ], + "/test-stack/nested/MyNestedFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyNestedFunctionServiceRole56B518B8" + } + ], + "/test-stack/nested/MyNestedFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyNestedFunctionA0269B76" + } + ], + "/test-stack/nested.NestedStack/nested.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "nestedNestedStacknestedNestedStackResource3DD143BF" + } + ], + "/test-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/test-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "test-stack" + }, + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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": [ + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets" + ], + "metadata": { + "/TestWithNestedStack/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/TestWithNestedStack/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "TestWithNestedStack/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.assets.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.assets.json new file mode 100644 index 0000000000000..06cae34119b66 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.assets.json @@ -0,0 +1,45 @@ +{ + "version": "21.0.0", + "files": { + "CHANGED_ASSET_HASH": { + "source": { + "path": "asset.CHANGED_ASSET_HASH", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "CHANGED_ASSET_HASH.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234": { + "source": { + "path": "teststacknested140612C4.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381": { + "source": { + "path": "test-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.template.json new file mode 100644 index 0000000000000..7418c1ab361ac --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/test-stack.template.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "MyFunctionServiceRole3C357FF2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction3BAA72D1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunctionServiceRole3C357FF2" + ] + }, + "nestedNestedStacknestedNestedStackResource3DD143BF": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json" + ] + ] + } + }, + "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/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/teststacknested140612C4.nested.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/teststacknested140612C4.nested.template.json new file mode 100644 index 0000000000000..0e7b67cd27fe5 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/teststacknested140612C4.nested.template.json @@ -0,0 +1,63 @@ +{ + "Resources": { + "MyTopic86869434": { + "Type": "AWS::SNS::Topic", + "Properties": { + "DisplayName": "MyTopic" + } + }, + "MyNestedFunctionServiceRole56B518B8": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyNestedFunctionA0269B76": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "CHANGED_ASSET_HASH.zip" + }, + "Role": { + "Fn::GetAtt": [ + "MyNestedFunctionServiceRole56B518B8", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyNestedFunctionServiceRole56B518B8" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/tree.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/tree.json new file mode 100644 index 0000000000000..8597834c8351d --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack-changed.js.snapshot/tree.json @@ -0,0 +1,387 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "test-stack": { + "id": "test-stack", + "path": "test-stack", + "children": { + "MyFunction": { + "id": "MyFunction", + "path": "test-stack/MyFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/MyFunction/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-stack/MyFunction/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "nested": { + "id": "nested", + "path": "test-stack/nested", + "children": { + "MyTopic": { + "id": "MyTopic", + "path": "test-stack/nested/MyTopic", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyTopic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.CfnTopic", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.Topic", + "version": "0.0.0" + } + }, + "MyNestedFunction": { + "id": "MyNestedFunction", + "path": "test-stack/nested/MyNestedFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/nested/MyNestedFunction/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-stack/nested/MyNestedFunction/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyNestedFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "test-stack/nested/MyNestedFunction/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "test-stack/nested/MyNestedFunction/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "test-stack/nested/MyNestedFunction/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyNestedFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68.zip" + }, + "role": { + "Fn::GetAtt": [ + "MyNestedFunctionServiceRole56B518B8", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "nested.NestedStack": { + "id": "nested.NestedStack", + "path": "test-stack/nested.NestedStack", + "children": { + "nested.NestedStackResource": { + "id": "nested.NestedStackResource", + "path": "test-stack/nested.NestedStack/nested.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "TestWithNestedStack": { + "id": "TestWithNestedStack", + "path": "TestWithNestedStack", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "TestWithNestedStack/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "TestWithNestedStack/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "TestWithNestedStack/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "TestWithNestedStack/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "TestWithNestedStack/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json new file mode 100644 index 0000000000000..91488886727c6 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/asset.b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68/.keep b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/asset.b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/cdk.out b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/integ.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/integ.json new file mode 100644 index 0000000000000..56b2c82cb6d9e --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "TestWithNestedStack/DefaultTest": { + "stacks": [ + "test-stack" + ], + "assertionStack": "TestWithNestedStack/DefaultTest/DeployAssert", + "assertionStackName": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/manifest.json new file mode 100644 index 0000000000000..e45aa1d70111d --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/manifest.json @@ -0,0 +1,141 @@ +{ + "version": "21.0.0", + "artifacts": { + "test-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "test-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-stack.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "test-stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "test-stack.assets" + ], + "metadata": { + "/test-stack/MyFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunctionServiceRole3C357FF2" + } + ], + "/test-stack/MyFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction3BAA72D1" + } + ], + "/test-stack/nested/MyTopic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyTopic86869434" + } + ], + "/test-stack/nested/MyNestedFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyNestedFunctionServiceRole56B518B8" + } + ], + "/test-stack/nested/MyNestedFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyNestedFunctionA0269B76" + } + ], + "/test-stack/nested.NestedStack/nested.NestedStackResource": [ + { + "type": "aws:cdk:logicalId", + "data": "nestedNestedStacknestedNestedStackResource3DD143BF" + } + ], + "/test-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/test-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "test-stack" + }, + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.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": [ + "TestWithNestedStackDefaultTestDeployAssert9F80D3B6.assets" + ], + "metadata": { + "/TestWithNestedStack/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/TestWithNestedStack/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "TestWithNestedStack/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.assets.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.assets.json new file mode 100644 index 0000000000000..9232e135ecce2 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.assets.json @@ -0,0 +1,45 @@ +{ + "version": "21.0.0", + "files": { + "b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68": { + "source": { + "path": "asset.b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234": { + "source": { + "path": "teststacknested140612C4.nested.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381": { + "source": { + "path": "test-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "e329bc2347c70a89ff078c2c93444d2b59a21f04cbf91afff7e9e5cab307b381.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/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.template.json new file mode 100644 index 0000000000000..7418c1ab361ac --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/test-stack.template.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "MyFunctionServiceRole3C357FF2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction3BAA72D1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunctionServiceRole3C357FF2" + ] + }, + "nestedNestedStacknestedNestedStackResource3DD143BF": { + "Type": "AWS::CloudFormation::Stack", + "Properties": { + "TemplateURL": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json" + ] + ] + } + }, + "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/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/teststacknested140612C4.nested.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/teststacknested140612C4.nested.template.json new file mode 100644 index 0000000000000..68c6227f90d58 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/teststacknested140612C4.nested.template.json @@ -0,0 +1,60 @@ +{ + "Resources": { + "MyTopic86869434": { + "Type": "AWS::SNS::Topic" + }, + "MyNestedFunctionServiceRole56B518B8": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyNestedFunctionA0269B76": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68.zip" + }, + "Role": { + "Fn::GetAtt": [ + "MyNestedFunctionServiceRole56B518B8", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyNestedFunctionServiceRole56B518B8" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/tree.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/tree.json new file mode 100644 index 0000000000000..8597834c8351d --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.js.snapshot/tree.json @@ -0,0 +1,387 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "test-stack": { + "id": "test-stack", + "path": "test-stack", + "children": { + "MyFunction": { + "id": "MyFunction", + "path": "test-stack/MyFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/MyFunction/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-stack/MyFunction/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "nested": { + "id": "nested", + "path": "test-stack/nested", + "children": { + "MyTopic": { + "id": "MyTopic", + "path": "test-stack/nested/MyTopic", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyTopic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.CfnTopic", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.Topic", + "version": "0.0.0" + } + }, + "MyNestedFunction": { + "id": "MyNestedFunction", + "path": "test-stack/nested/MyNestedFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/nested/MyNestedFunction/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-stack/nested/MyNestedFunction/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyNestedFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "test-stack/nested/MyNestedFunction/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "test-stack/nested/MyNestedFunction/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "test-stack/nested/MyNestedFunction/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/nested/MyNestedFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "b7826d21185e020066e56b133136e1082372d08cf21209a8823ac39710782f68.zip" + }, + "role": { + "Fn::GetAtt": [ + "MyNestedFunctionServiceRole56B518B8", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.NestedStack", + "version": "0.0.0" + } + }, + "nested.NestedStack": { + "id": "nested.NestedStack", + "path": "test-stack/nested.NestedStack", + "children": { + "nested.NestedStackResource": { + "id": "nested.NestedStackResource", + "path": "test-stack/nested.NestedStack/nested.NestedStackResource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFormation::Stack", + "aws:cdk:cloudformation:props": { + "templateUrl": { + "Fn::Join": [ + "", + [ + "https://s3.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/68d244d71d1a0f2942feda5bea8f07b26ee3b09b4e9df7eac4296dcaf8532234.json" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CfnStack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "TestWithNestedStack": { + "id": "TestWithNestedStack", + "path": "TestWithNestedStack", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "TestWithNestedStack/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "TestWithNestedStack/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "TestWithNestedStack/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "TestWithNestedStack/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "TestWithNestedStack/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.154" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.ts b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.ts new file mode 100644 index 0000000000000..b9e8e8dc39be4 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-nested-stack.ts @@ -0,0 +1,32 @@ +/** + * This is NOT a real integ test! + * It is used to test functionality of the integ-runner. + */ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as sns from '@aws-cdk/aws-sns'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'test-stack'); +new lambda.Function(stack, 'MyFunction', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, +}); + +const nestedStack = new cdk.NestedStack(stack, 'nested', {}); +new sns.Topic(nestedStack, 'MyTopic'); +new lambda.Function(nestedStack, 'MyNestedFunction', { + code: lambda.Code.fromAsset('assets/code-asset'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, +}); + + +new integ.IntegTest(app, 'TestWithNestedStack', { + testCases: [stack], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/cdk-assets/lib/asset-manifest.ts b/packages/cdk-assets/lib/asset-manifest.ts index 1e4f240212042..bb5d468085823 100644 --- a/packages/cdk-assets/lib/asset-manifest.ts +++ b/packages/cdk-assets/lib/asset-manifest.ts @@ -113,20 +113,27 @@ export class AssetManifest { ...makeEntries(this.manifest.files || {}, FileManifestEntry), ...makeEntries(this.manifest.dockerImages || {}, DockerImageManifestEntry), ]; + } - function makeEntries( - assets: Record }>, - ctor: new (id: DestinationIdentifier, source: A, destination: B) => C): C[] { + /** + * List of assets, splat out to destinations + */ + public get files(): FileManifestEntry[] { + return makeEntries(this.manifest.files || {}, FileManifestEntry); + } +} - const ret = new Array(); - for (const [assetId, asset] of Object.entries(assets)) { - for (const [destId, destination] of Object.entries(asset.destinations)) { - ret.push(new ctor(new DestinationIdentifier(assetId, destId), asset.source, destination)); - } - } - return ret; +function makeEntries( + assets: Record }>, + ctor: new (id: DestinationIdentifier, source: A, destination: B) => C): C[] { + + const ret = new Array(); + for (const [assetId, asset] of Object.entries(assets)) { + for (const [destId, destination] of Object.entries(asset.destinations)) { + ret.push(new ctor(new DestinationIdentifier(assetId, destId), asset.source, destination)); } } + return ret; } type AssetType = 'files' | 'dockerImages';