Skip to content

Commit 85fc87f

Browse files
authored
fix(core): asset names for nested stacks contain Tokens (#33966)
Since Nested Stack names are Tokens (resolving to `{ Ref: 'AWS::StackName' }`), if we use `this.stackName` as the asset name just like we do for regular stacks, we end up with Tokens in the display name of the nested stack template asset. This is pointless because the token will not be resolved and look like `${Token[TOKEN.639]}`; plus, it breaks tests because the Token numbers are different on every run. In CDK Pipelines, it would also lead to the pipeline restarting on every pipeline run. Instead, test for and reject Tokens, and use the nested stack's construct path instead just like we do for other assets. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2ebac0a commit 85fc87f

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

Diff for: packages/aws-cdk-lib/core/lib/nested-stack.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ export class NestedStack extends Stack {
226226
packaging: FileAssetPackaging.FILE,
227227
sourceHash: templateHash,
228228
fileName: this.templateFile,
229-
displayName: `${this.stackName} Template`,
229+
// this.stackName is a Token for nested stacks, so use something else
230+
displayName: `${Names.stackRelativeConstructPath(this)} Nested Stack Template`,
230231
});
231232

232233
this.addResourceMetadata(this.resource, 'TemplateURL');

Diff for: packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as cxschema from '../../../cloud-assembly-schema';
55
import { FileAssetSource, FileAssetPackaging, DockerImageAssetSource } from '../assets';
66
import { resolvedOr } from '../helpers-internal/string-specializer';
77
import { Stack } from '../stack';
8+
import { Token } from '../token';
89

910
/**
1011
* Build an asset manifest from assets added to a stack
@@ -289,13 +290,21 @@ function validateFileAssetSource(asset: FileAssetSource) {
289290
if (!!asset.packaging !== !!asset.fileName) {
290291
throw new Error(`'packaging' is expected in combination with 'fileName', got: ${JSON.stringify(asset)}`);
291292
}
293+
294+
if (Token.isUnresolved(asset.displayName)) {
295+
throw new Error(`'displayName' may not contain a Token, got: ${JSON.stringify(asset.displayName)}`);
296+
}
292297
}
293298

294299
function validateDockerImageAssetSource(asset: DockerImageAssetSource) {
295300
if (!!asset.executable === !!asset.directoryName) {
296301
throw new Error(`Exactly one of 'directoryName' or 'executable' is required, got: ${JSON.stringify(asset)}`);
297302
}
298303

304+
if (Token.isUnresolved(asset.displayName)) {
305+
throw new Error(`'displayName' may not contain a Token, got: ${JSON.stringify(asset.displayName)}`);
306+
}
307+
299308
check('dockerBuildArgs');
300309
check('dockerBuildTarget');
301310
check('dockerOutputs');

Diff for: packages/aws-cdk-lib/core/test/stack-synthesis/all-synthesizers.test.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FileAssetPackaging } from '@aws-cdk/cloud-assembly-schema';
22
import { getAssetManifest, readAssetManifest } from './_helpers';
3-
import { CliCredentialsStackSynthesizer, LegacyStackSynthesizer } from '../../lib';
3+
import { Aws, CliCredentialsStackSynthesizer, LegacyStackSynthesizer } from '../../lib';
44
import { App } from '../../lib/app';
55
import { Stack } from '../../lib/stack';
66
import { DefaultStackSynthesizer } from '../../lib/stack-synthesizers/default-synthesizer';
@@ -45,3 +45,29 @@ test.each([
4545
});
4646
});
4747

48+
test.each([
49+
['DefaultStackSynthesizer', () => new DefaultStackSynthesizer()],
50+
['CliCredentialsStackSynthesizer', () => new CliCredentialsStackSynthesizer()],
51+
])('%p: displayName may not contain tokens', (_name, factory) => {
52+
// GIVEN
53+
const app = new App();
54+
const stack = new Stack(app, 'Stack', {
55+
synthesizer: factory(),
56+
env: {
57+
account: '111111111111', region: 'us-east-1',
58+
},
59+
});
60+
61+
expect(() => stack.synthesizer.addFileAsset({
62+
fileName: __filename,
63+
packaging: FileAssetPackaging.FILE,
64+
sourceHash: 'fileHash',
65+
displayName: Aws.STACK_NAME,
66+
})).toThrow(/may not contain a Token/);
67+
68+
expect(() => stack.synthesizer.addDockerImageAsset({
69+
directoryName: '.',
70+
sourceHash: 'dockerHash',
71+
displayName: Aws.STACK_NAME,
72+
})).toThrow(/may not contain a Token/);
73+
});

0 commit comments

Comments
 (0)