Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add description to exportValue and exportStringListValue methods #29150

Merged
merged 7 commits into from Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -1,4 +1,20 @@
{
"Outputs": {
"ExportMyExportValue": {
"Description": "This is a description for MyExportValue",
"Value": "someValue",
"Export": {
"Name": "MyExportValue"
}
},
"ExportMyExportStringListValue": {
"Description": "This is a description for MyExportStringListValue",
"Value": "someValue||anotherValue",
"Export": {
"Name": "MyExportStringListValue"
}
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -9,4 +9,13 @@ const app = new cdk.App();
const stack = new cdk.Stack(app, 'Stack', { terminationProtection: false });
stack.terminationProtection = true;

stack.exportValue('someValue', {
name: 'MyExportValue',
description: 'This is a description for MyExportValue',
});
stack.exportStringListValue(['someValue', 'anotherValue'], {
name: 'MyExportStringListValue',
description: 'This is a description for MyExportStringListValue',
});

new IntegTest(app, 'stack', { testCases: [stack] });
11 changes: 11 additions & 0 deletions packages/aws-cdk-lib/core/README.md
Expand Up @@ -836,6 +836,17 @@ new CfnOutput(this, 'OutputName', {
});
```

You can also use the `exportValue` method to export values as stack outputs:

```ts
declare const stack: Stack;

stack.exportValue(myBucket.bucketName, {
name: 'TheAwesomeBucket',
description: 'The name of an S3 bucket',
});
```

[cfn-stack-output]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html

### Parameters
Expand Down
11 changes: 11 additions & 0 deletions packages/aws-cdk-lib/core/lib/stack.ts
Expand Up @@ -1204,6 +1204,7 @@ export class Stack extends Construct implements ITaggable {
new CfnOutput(this, `Export${options.name}`, {
value: exportedValue,
exportName: options.name,
description: options.description,
});
return Fn.importValue(options.name);
}
Expand All @@ -1215,6 +1216,7 @@ export class Stack extends Construct implements ITaggable {
new CfnOutput(exportsScope, id, {
value: Token.asString(exportable),
exportName,
description: options.description,
});
}

Expand Down Expand Up @@ -1253,6 +1255,7 @@ export class Stack extends Construct implements ITaggable {
new CfnOutput(this, `Export${options.name}`, {
value: Fn.join(STRING_LIST_REFERENCE_DELIMITER, exportedValue),
exportName: options.name,
description: options.description,
});
return Fn.split(STRING_LIST_REFERENCE_DELIMITER, Fn.importValue(options.name));
}
Expand All @@ -1268,6 +1271,7 @@ export class Stack extends Construct implements ITaggable {
// (string lists are invalid)
value: Fn.join(STRING_LIST_REFERENCE_DELIMITER, Token.asList(exportable)),
exportName,
description: options.description,
});
}

Expand Down Expand Up @@ -1766,6 +1770,13 @@ export interface ExportValueOptions {
* @default - A name is automatically chosen
*/
readonly name?: string;

/**
* The description of the outputs
*
* @default - No description
*/
readonly description?: string;
}

function count(xs: string[]): Record<string, number> {
Expand Down
77 changes: 77 additions & 0 deletions packages/aws-cdk-lib/core/test/stack.test.ts
Expand Up @@ -1489,6 +1489,83 @@ describe('stack', () => {
});
});

test('exports with name can include description', () => {
const app = new App();
const stack = new Stack(app, 'Stack');

stack.exportValue('someValue', {
name: 'MyExport',
description: 'This is a description',
});

const template = app.synth().getStackByName(stack.stackName).template;
expect(template).toMatchObject({
Outputs: {
ExportMyExport: {
Description: 'This is a description',
},
},
});
});

test('list exports with name can include description', () => {
const app = new App();
const stack = new Stack(app, 'Stack');

stack.exportStringListValue(['someValue', 'anotherValue'], {
name: 'MyExport',
description: 'This is a description',
});

const template = app.synth().getStackByName(stack.stackName).template;
expect(template).toMatchObject({
Outputs: {
ExportMyExport: {
Description: 'This is a description',
},
},
});
});

test('exports without name can include description', () => {
const app = new App();
const stack = new Stack(app, 'Stack');

const resource = new CfnResource(stack, 'Resource', { type: 'AWS::Resource' });
stack.exportValue(resource.getAtt('Att'), {
description: 'This is a description',
});

const template = app.synth().getStackByName(stack.stackName).template;
expect(template).toMatchObject({
Outputs: {
ExportsOutputFnGetAttResourceAttB5968E71: {
Description: 'This is a description',
},
},
});
});

test('list exports without name can include description', () => {
const app = new App();
const stack = new Stack(app, 'Stack');

const resource = new CfnResource(stack, 'Resource', { type: 'AWS::Resource' });
(resource as any).attrAtt = ['Foo', 'Bar'];
stack.exportStringListValue(resource.getAtt('Att', ResolutionTypeHint.STRING_LIST), {
description: 'This is a description',
});

const template = app.synth().getStackByName(stack.stackName).template;
expect(template).toMatchObject({
Outputs: {
ExportsOutputFnGetAttResourceAttB5968E71: {
Description: 'This is a description',
},
},
});
});

test('CfnSynthesisError is ignored when preparing cross references', () => {
// GIVEN
const app = new App();
Expand Down