diff --git a/packages/@aws-cdk/core/lib/cfn-resource.ts b/packages/@aws-cdk/core/lib/cfn-resource.ts index 68c34c52bce1d..39b60a3d248b7 100644 --- a/packages/@aws-cdk/core/lib/cfn-resource.ts +++ b/packages/@aws-cdk/core/lib/cfn-resource.ts @@ -93,9 +93,7 @@ export class CfnResource extends CfnRefElement { // path in the CloudFormation template, so it will be possible to trace // back to the actual construct path. if (this.node.tryGetContext(cxapi.PATH_METADATA_ENABLE_CONTEXT)) { - this.cfnOptions.metadata = { - [cxapi.PATH_METADATA_KEY]: this.node.path, - }; + this.addMetadata(cxapi.PATH_METADATA_KEY, this.node.path); } } @@ -238,6 +236,22 @@ export class CfnResource extends CfnRefElement { addDependency(this, target, `"${this.node.path}" depends on "${target.node.path}"`); } + /** + * Add a value to the CloudFormation Resource Metadata + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html + * + * Note that this is a different set of metadata from CDK node metadata; this + * metadata ends up in the stack template under the resource, whereas CDK + * node metadata ends up in the Cloud Assembly. + */ + public addMetadata(key: string, value: any) { + if (!this.cfnOptions.metadata) { + this.cfnOptions.metadata = {}; + } + + this.cfnOptions.metadata[key] = value; + } + /** * @returns a string representation of this resource */ diff --git a/packages/@aws-cdk/core/test/test.cfn-resource.ts b/packages/@aws-cdk/core/test/test.cfn-resource.ts index dec09b5c96084..41d360296ec1d 100644 --- a/packages/@aws-cdk/core/test/test.cfn-resource.ts +++ b/packages/@aws-cdk/core/test/test.cfn-resource.ts @@ -73,4 +73,28 @@ export = nodeunit.testCase({ test.done(); }, + + 'can add metadata'(test: nodeunit.Test) { + // GIVEN + const app = new core.App(); + const stack = new core.Stack(app, 'TestStack'); + const resource = new core.CfnResource(stack, 'DefaultResource', { type: 'Test::Resource::Fake' }); + + // WHEN + resource.addMetadata('Beep', 'Boop'); + + // THEN + test.deepEqual(app.synth().getStackByName(stack.stackName).template, { + Resources: { + DefaultResource: { + Type: 'Test::Resource::Fake', + Metadata: { + Beep: 'Boop', + }, + }, + }, + }); + + test.done(); + }, });