Skip to content

Commit

Permalink
fix: deploy-time stack tags cause synthesis to fail (#32041)
Browse files Browse the repository at this point in the history
In #31457, we introduced a change that made synthesis fail if one of the stack tags was a deploy-time value. Since stack tags are assigned outside a CloudFormation context, deploy-time values cannot be evaluated, so the stack ends up with a tag like `{ Key: "my-tag", Value: "${Token[1234]}" }`, which is probably not what is intended.

Worse, those tags are automatically propagated to all resources in the stack by CloudFormation, and some may validate the tag value and find that `$` or any of the other characters are not valid tag values.

The intent was that customers would be alerted to these kinds of mistakes and apply their tags to resources, or skip stacks when applying tags to large scopes:

```ts
Tags.of(this).add('my-tag', Fn.importValue('SomeExport'), {
  excludeResourceTypes: ['aws:cdk:stack'],
});
```

The previous change was a bit drastic in its attempts.  In this one we ignore the unresolved tags and add a warning instead. That way, synthesis still succeeds.

Closes #32040.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
rix0rrr authored Nov 6, 2024
1 parent dd61d12 commit 18c19fd
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
21 changes: 14 additions & 7 deletions packages/aws-cdk-lib/core/lib/stack-synthesizers/_shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,22 @@ export function addStackArtifactToAssembly(
// nested stack tags are applied at the AWS::CloudFormation::Stack resource
// level and are not needed in the cloud assembly.
if (Object.entries(stackTags).length > 0) {
for (const [k, v] of Object.entries(stackTags)) {
if (Token.isUnresolved(k) || Token.isUnresolved(v)) {
throw new Error(`Stack tags may not contain deploy-time values (tag: ${k}=${v}). Apply tags containing deploy-time values to resources only, avoid tagging stacks.`);
}
const resolvedTags = Object.entries(stackTags).filter(([k, v]) => !(Token.isUnresolved(k) || Token.isUnresolved(v)));
const unresolvedTags = Object.entries(stackTags).filter(([k, v]) => Token.isUnresolved(k) || Token.isUnresolved(v));

if (unresolvedTags.length > 0) {
const rendered = unresolvedTags.map(([k, v]) => `${Token.isUnresolved(k) ? '<TOKEN>': k}=${Token.isUnresolved(v) ? '<TOKEN>' : v}`).join(', ');
stack.node.addMetadata(
cxschema.ArtifactMetadataEntryType.WARN,
`Ignoring stack tags that contain deploy-time values (found: ${rendered}). Apply tags containing deploy-time values to resources only, avoid tagging stacks (for example using { excludeResourceTypes: ['aws:cdk:stack'] }).`,
);
}

stack.node.addMetadata(
cxschema.ArtifactMetadataEntryType.STACK_TAGS,
Object.entries(stackTags).map(([key, value]) => ({ Key: key, Value: value })));
if (resolvedTags.length > 0) {
stack.node.addMetadata(
cxschema.ArtifactMetadataEntryType.STACK_TAGS,
resolvedTags.map(([key, value]) => ({ Key: key, Value: value })));
}
}

const deps = [
Expand Down
11 changes: 9 additions & 2 deletions packages/aws-cdk-lib/core/test/stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,7 +2075,7 @@ describe('stack', () => {
expect(asm.getStackArtifact(stack2.artifactId).tags).toEqual(expected);
});

test('stack tags may not contain tokens', () => {
test('warning when stack tags contain tokens', () => {
// GIVEN
const app = new App({
stackTraces: false,
Expand All @@ -2087,7 +2087,14 @@ describe('stack', () => {
},
});

expect(() => app.synth()).toThrow(/Stack tags may not contain deploy-time values/);
const asm = app.synth();
const stackArtifact = asm.stacks[0];
expect(stackArtifact.manifest.metadata?.['/stack1']).toEqual([
{
type: 'aws:cdk:warning',
data: expect.stringContaining('Ignoring stack tags that contain deploy-time values'),
},
]);
});

test('stack notification arns are reflected in the stack artifact properties', () => {
Expand Down

0 comments on commit 18c19fd

Please sign in to comment.