Skip to content

Commit 621d725

Browse files
committed
feat(toolkit): add a return type for toolkit.deploy()
`toolkit.deploy()` now returns information about the stacks it deployed.
1 parent c14df8e commit 621d725

File tree

16 files changed

+607
-8
lines changed

16 files changed

+607
-8
lines changed

packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/schema.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ export interface ArtifactManifest {
100100
readonly properties?: ArtifactProperties;
101101

102102
/**
103-
* A string that represents this artifact. Should only be used in user interfaces.
103+
* A string that can be shown to a user to uniquely identify this artifact inside a cloud assembly tree
104+
*
105+
* Is used by the CLI to present a list of stacks to the user in a way that
106+
* makes sense to them. Even though the property name "display name" doesn't
107+
* imply it, this field is used to select stacks as well, so all stacks should
108+
* have a unique display name.
104109
*
105110
* @default - no display name
106111
*/

packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
]
8484
},
8585
"displayName": {
86-
"description": "A string that represents this artifact. Should only be used in user interfaces. (Default - no display name)",
86+
"description": "A string that can be shown to a user to uniquely identify this artifact inside a cloud assembly tree\n\nIs used by the CLI to present a list of stacks to the user in a way that\nmakes sense to them. Even though the property name \"display name\" doesn't\nimply it, this field is used to select stacks as well, so all stacks should\nhave a unique display name. (Default - no display name)",
8787
"type": "string"
8888
}
8989
},
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"schemaHash": "78936b0f9299bbe47497dd77f8065d71e65d8d739a0413ad7698ad03b22ef83e",
2+
"schemaHash": "96958a4c40e0a00e850f0c14dd6e9c0fc8db0b075f1f155cea41ab198c0514be",
33
"revision": 43
4-
}
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './toolkit';
22
export * from './non-interactive-io-host';
3+
export * from './types';
34
export * from '../api/shared-public';

packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as uuid from 'uuid';
77
import { NonInteractiveIoHost } from './non-interactive-io-host';
88
import type { ToolkitServices } from './private';
99
import { assemblyFromSource } from './private';
10+
import type { DeployResult } from './types';
1011
import type { BootstrapEnvironments, BootstrapOptions, BootstrapResult, EnvironmentBootstrapResult } from '../actions/bootstrap';
1112
import { BootstrapSource } from '../actions/bootstrap';
1213
import { AssetBuildTime, type DeployOptions } from '../actions/deploy';
@@ -413,7 +414,7 @@ export class Toolkit extends CloudAssemblySourceBuilder {
413414
*
414415
* Deploys the selected stacks into an AWS account
415416
*/
416-
public async deploy(cx: ICloudAssemblySource, options: DeployOptions = {}): Promise<void> {
417+
public async deploy(cx: ICloudAssemblySource, options: DeployOptions = {}): Promise<DeployResult> {
417418
const ioHelper = asIoHelper(this.ioHost, 'deploy');
418419
const assembly = await assemblyFromSource(ioHelper, cx);
419420
return this._deploy(assembly, 'deploy', options);
@@ -422,17 +423,21 @@ export class Toolkit extends CloudAssemblySourceBuilder {
422423
/**
423424
* Helper to allow deploy being called as part of the watch action.
424425
*/
425-
private async _deploy(assembly: StackAssembly, action: 'deploy' | 'watch', options: ExtendedDeployOptions = {}) {
426+
private async _deploy(assembly: StackAssembly, action: 'deploy' | 'watch', options: ExtendedDeployOptions = {}): Promise<DeployResult> {
426427
const ioHelper = asIoHelper(this.ioHost, action);
427428
const selectStacks = options.stacks ?? ALL_STACKS;
428429
const synthSpan = await ioHelper.span(SPAN.SYNTH_ASSEMBLY).begin({ stacks: selectStacks });
429430
const stackCollection = await assembly.selectStacksV2(selectStacks);
430431
await this.validateStacksMetadata(stackCollection, ioHelper);
431432
const synthDuration = await synthSpan.end();
432433

434+
const ret: DeployResult = {
435+
stacks: [],
436+
};
437+
433438
if (stackCollection.stackCount === 0) {
434439
await ioHelper.notify(IO.CDK_TOOLKIT_E5001.msg('This app contains no stacks'));
435-
return;
440+
return ret;
436441
}
437442

438443
const deployments = await this.deploymentsForAction('deploy');
@@ -655,6 +660,17 @@ export class Toolkit extends CloudAssemblySourceBuilder {
655660
await ioHelper.notify(IO.CDK_TOOLKIT_I5901.msg(buffer.join('\n')));
656661
}
657662
await ioHelper.notify(IO.CDK_TOOLKIT_I5901.msg(`Stack ARN:\n${deployResult.stackArn}`));
663+
664+
ret.stacks.push({
665+
stackName: stack.stackName,
666+
environment: {
667+
account: stack.environment.account,
668+
region: stack.environment.region,
669+
},
670+
stackArn: deployResult.stackArn,
671+
outputs: deployResult.outputs,
672+
hierarchicalId: stack.hierarchicalId,
673+
});
658674
} catch (e: any) {
659675
// It has to be exactly this string because an integration test tests for
660676
// "bold(stackname) failed: ResourceNotReady: <error>"
@@ -715,6 +731,8 @@ export class Toolkit extends CloudAssemblySourceBuilder {
715731
buildAsset,
716732
publishAsset,
717733
});
734+
735+
return ret;
718736
}
719737

720738
/**
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Result interface for toolkit.deploy operation
3+
*/
4+
export interface DeployResult {
5+
/**
6+
* Map of deployed stacks by artifact ID.
7+
*/
8+
readonly stacks: DeployedStack[];
9+
}
10+
11+
/**
12+
* Information about a deployed stack
13+
*/
14+
export interface DeployedStack {
15+
/**
16+
* The name of the deployed stack
17+
*
18+
* A stack name is unique inside its environment, but not unique globally.
19+
*/
20+
readonly stackName: string;
21+
22+
/**
23+
* The environment where the stack was deployed
24+
*
25+
* This environment is always concrete, because even though the CDK app's
26+
* stack may be region-agnostic, in order to be deployed it will have to have
27+
* been specialized.
28+
*/
29+
readonly environment: Environment;
30+
31+
/**
32+
* Hierarchical identifier
33+
*
34+
* This uniquely identifies the stack inside the CDK app.
35+
*
36+
* In practice this will be the stack's construct path, but unfortunately the
37+
* Cloud Assembly contract doesn't require or guarantee that.
38+
*/
39+
readonly hierarchicalId: string;
40+
41+
/**
42+
* The ARN of the deployed stack
43+
*/
44+
readonly stackArn: string;
45+
46+
/**
47+
* The outputs of the deployed CloudFormation stack
48+
*/
49+
readonly outputs: { [key: string]: string };
50+
}
51+
52+
/**
53+
* An environment, which is an (account, region) pair
54+
*/
55+
export interface Environment {
56+
/**
57+
* The account number
58+
*/
59+
readonly account: string;
60+
61+
/**
62+
* The region number
63+
*/
64+
readonly region: string;
65+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as cdk from 'aws-cdk-lib/core';
2+
3+
const app = new cdk.App({ autoSynth: false });
4+
const stage = new cdk.Stage(app, 'Stage');
5+
new cdk.Stack(stage, 'Stack1');
6+
7+
app.synth();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"app": "$(npx -c 'which tsx') app.ts"
3+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "40.0.0",
3+
"files": {
4+
"7f4fb64a3afca08edbdbaa369e00317cb253697278406a83c78e849e89045f9d": {
5+
"source": {
6+
"path": "StageStack130339B27.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "7f4fb64a3afca08edbdbaa369e00317cb253697278406a83c78e849e89045f9d.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}

0 commit comments

Comments
 (0)