From be24aa56cfa77b4efdd3196a8bf1467e694b41df Mon Sep 17 00:00:00 2001 From: Kendra Neil <53584728+TheRealAmazonKendra@users.noreply.github.com> Date: Mon, 20 Nov 2023 12:16:08 -0800 Subject: [PATCH] chore(core): use key instead of logicalId for key when provided (#28075) In CDK Migrate, when a user has a construct with the same name as their CfnOutput key, it creates a naming collision. This change enables us to name the construct something else and still use the correct key in creating the output. Note that the logicalId only makes it into the synthesized template as the output key so this change won't impact existing apps using the CfnOutput construct. 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-lib/core/lib/cfn-output.ts | 9 ++++++- packages/aws-cdk-lib/core/test/output.test.ts | 26 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/cfn-output.ts b/packages/aws-cdk-lib/core/lib/cfn-output.ts index e9b8d654cb81a..8f1bf310ddead 100644 --- a/packages/aws-cdk-lib/core/lib/cfn-output.ts +++ b/packages/aws-cdk-lib/core/lib/cfn-output.ts @@ -10,6 +10,11 @@ export interface CfnOutputProps { */ readonly description?: string; + /** + * The key of the property returned by aws cloudformation describe-stacks command. + */ + readonly key?: string; + /** * The value of the property returned by the aws cloudformation describe-stacks command. * The value of an output can include literals, parameter references, pseudo-parameters, @@ -38,6 +43,7 @@ export interface CfnOutputProps { export class CfnOutput extends CfnElement { private _description?: string; private _condition?: CfnCondition; + private _key?: string; private _value?: any; private _exportName?: string; @@ -58,6 +64,7 @@ export class CfnOutput extends CfnElement { } this._description = props.description; + this._key = props.key; this._value = props.value; this._condition = props.condition; this._exportName = props.exportName; @@ -160,7 +167,7 @@ export class CfnOutput extends CfnElement { public _toCloudFormation(): object { return { Outputs: { - [this.logicalId]: { + [this._key ?? this.logicalId]: { Description: this._description, Value: this._value, Export: this._exportName != null ? { Name: this._exportName } : undefined, diff --git a/packages/aws-cdk-lib/core/test/output.test.ts b/packages/aws-cdk-lib/core/test/output.test.ts index a215d65079c58..335173bd944d4 100644 --- a/packages/aws-cdk-lib/core/test/output.test.ts +++ b/packages/aws-cdk-lib/core/test/output.test.ts @@ -9,7 +9,7 @@ beforeEach(() => { }); describe('output', () => { - test('outputs can be added to the stack', () => { + test('outputs can be added to the stack with no key provided', () => { const res = new CfnResource(stack, 'MyResource', { type: 'R' }); const ref = res.ref; @@ -32,6 +32,30 @@ describe('output', () => { }); }); + test('outputs can be added to the stack with a key provided', () => { + const res = new CfnResource(stack, 'MyResource', { type: 'R' }); + const ref = res.ref; + + new CfnOutput(stack, 'MyOutput', { + exportName: 'ExportName', + key: 'MyOutputWithKey', + value: ref, + description: 'CfnOutput properties', + }); + expect(toCloudFormation(stack)).toEqual({ + Resources: { MyResource: { Type: 'R' } }, + Outputs: + { + MyOutputWithKey: + { + Description: 'CfnOutput properties', + Export: { Name: 'ExportName' }, + Value: { Ref: 'MyResource' }, + }, + }, + }); + }); + test('No export is created by default', () => { // WHEN new CfnOutput(stack, 'SomeOutput', { value: 'x' });