Skip to content

Commit d68d000

Browse files
authored
refactor(toolkit): move deployment apis (#336)
Moves all deployment related apis over to the temporary helper package. Due to inter-dependencies, these have to move together. (We should probably break this up at some point/) Tests will be moved later to keep the diff size manageable. Code is still tested as the tests are still running from `aws-cdk` package. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
1 parent b5cb910 commit d68d000

File tree

96 files changed

+1106
-1129
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+1106
-1129
lines changed

.projenrc.ts

+5
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,11 @@ tmpToolkitHelpers.eslint?.addOverride({
786786

787787
tmpToolkitHelpers.gitignore.addPatterns('test/**/*.map');
788788

789+
tmpToolkitHelpers.npmignore?.addPatterns(
790+
'!lib/api/bootstrap/bootstrap-template.yaml',
791+
);
792+
tmpToolkitHelpers.postCompileTask.exec('mkdir -p ./lib/api/bootstrap/ && cp ../../aws-cdk/lib/api/bootstrap/bootstrap-template.yaml ./lib/api/bootstrap/');
793+
789794
//////////////////////////////////////////////////////////////////////
790795

791796
const cli = configureProject(

packages/@aws-cdk/tmp-toolkit-helpers/.npmignore

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/tmp-toolkit-helpers/.projen/tasks.json

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/bootstrap/bootstrap-environment.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import type * as cxapi from '@aws-cdk/cx-api';
33
import type { BootstrapEnvironmentOptions, BootstrappingParameters } from './bootstrap-props';
44
import { BootstrapStack, bootstrapVersionFromTemplate } from './deploy-bootstrap';
55
import { legacyBootstrapTemplate } from './legacy-template';
6-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
7-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
86
import { bundledPackageRootDir, loadStructuredFile, serializeStructure } from '../../util';
97
import type { SDK, SdkProvider } from '../aws-auth';
108
import type { SuccessfulDeployStackResult } from '../deployments';
9+
import { IO, type IoHelper } from '../io/private';
1110
import { Mode } from '../plugin';
11+
import { ToolkitError } from '../toolkit-error';
1212
import { DEFAULT_TOOLKIT_STACK_NAME } from '../toolkit-info';
1313

1414
export type BootstrapSource = { source: 'legacy' } | { source: 'default' } | { source: 'custom'; templateFile: string };

packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/bootstrap/deploy-bootstrap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import {
1111
BOOTSTRAP_VERSION_RESOURCE,
1212
DEFAULT_BOOTSTRAP_VARIANT,
1313
} from './bootstrap-props';
14-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
1514
import type { SDK, SdkProvider } from '../aws-auth';
1615
import type { SuccessfulDeployStackResult } from '../deployments';
1716
import { assertIsSuccessfulDeployStackResult } from '../deployments';
1817
import { deployStack } from '../deployments/deploy-stack';
1918
import { NoBootstrapStackEnvironmentResources } from '../environment';
19+
import { IO, type IoHelper } from '../io/private';
2020
import { Mode } from '../plugin';
2121
import { DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo } from '../toolkit-info';
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './bootstrap-environment';
2+
export * from './bootstrap-props';
3+
4+
// testing exports
5+
export { legacyBootstrapTemplate } from './legacy-template';

packages/aws-cdk/lib/api/cloudformation/evaluate-cloudformation-template.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/cloudformation/evaluate-cloudformation-template.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import type { CloudFormationStackArtifact } from '@aws-cdk/cx-api';
22
import type { Export, ListExportsCommandOutput, StackResourceSummary } from '@aws-sdk/client-cloudformation';
33
import type { SDK } from '../aws-auth';
4+
import { ToolkitError } from '../toolkit-error';
45
import type { NestedStackTemplates } from './nested-stack-helpers';
56
import type { Template } from './stack-helpers';
6-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
7-
import { resourceMetadata } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/resource-metadata';
8-
import type { ResourceMetadata } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/resource-metadata';
7+
import type { ResourceMetadata } from '../resource-metadata';
8+
import { resourceMetadata } from '../resource-metadata';
99

1010
export interface ListStackResources {
1111
listStackResources(): Promise<StackResourceSummary[]>;
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
export * from './nested-stack-templates';
1+
export * from './evaluate-cloudformation-template';
2+
export * from './template-body-parameter';
3+
export * from './nested-stack-helpers';
24
export * from './stack-helpers';

packages/aws-cdk/lib/api/cloudformation/nested-stack-helpers.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/cloudformation/nested-stack-helpers.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import { formatErrorMessage } from '../../util';
55
import type { SDK } from '../aws-auth';
66
import { LazyListStackResources, type ListStackResources } from './evaluate-cloudformation-template';
77
import { CloudFormationStack, type Template } from './stack-helpers';
8-
import type { NestedStackTemplates } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
9-
10-
export { NestedStackTemplates } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
118

129
export interface RootTemplateWithNestedStacks {
1310
readonly deployedRootTemplate: Template;
@@ -139,6 +136,15 @@ function isCdkManagedNestedStack(stackResource: any): stackResource is NestedSta
139136
);
140137
}
141138

139+
export interface NestedStackTemplates {
140+
readonly physicalName: string | undefined;
141+
readonly deployedTemplate: Template;
142+
readonly generatedTemplate: Template;
143+
readonly nestedStackTemplates: {
144+
[nestedStackLogicalId: string]: NestedStackTemplates;
145+
};
146+
}
147+
142148
interface StackTemplates {
143149
readonly generatedTemplate: any;
144150
readonly deployedTemplate: any;

packages/@aws-cdk/tmp-toolkit-helpers/src/api/cloudformation/nested-stack-templates.ts

-10
This file was deleted.

packages/@aws-cdk/tmp-toolkit-helpers/src/api/cloudformation/stack-helpers.ts

+178
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import type { Stack, Tag } from '@aws-sdk/client-cloudformation';
2+
import { formatErrorMessage, deserializeStructure } from '../../util';
3+
import type { ICloudFormationClient } from '../aws-auth';
4+
import { StackStatus } from '../stack-events';
5+
import { ToolkitError } from '../toolkit-error';
6+
17
export interface Template {
28
Parameters?: Record<string, TemplateParameter>;
39
[section: string]: any;
@@ -9,3 +15,175 @@ export interface TemplateParameter {
915
Description?: string;
1016
[key: string]: any;
1117
}
18+
19+
/**
20+
* Represents an (existing) Stack in CloudFormation
21+
*
22+
* Bundle and cache some information that we need during deployment (so we don't have to make
23+
* repeated calls to CloudFormation).
24+
*/
25+
export class CloudFormationStack {
26+
public static async lookup(
27+
cfn: ICloudFormationClient,
28+
stackName: string,
29+
retrieveProcessedTemplate: boolean = false,
30+
): Promise<CloudFormationStack> {
31+
try {
32+
const response = await cfn.describeStacks({ StackName: stackName });
33+
return new CloudFormationStack(cfn, stackName, response.Stacks && response.Stacks[0], retrieveProcessedTemplate);
34+
} catch (e: any) {
35+
if (e.name === 'ValidationError' && formatErrorMessage(e) === `Stack with id ${stackName} does not exist`) {
36+
return new CloudFormationStack(cfn, stackName, undefined);
37+
}
38+
throw e;
39+
}
40+
}
41+
42+
/**
43+
* Return a copy of the given stack that does not exist
44+
*
45+
* It's a little silly that it needs arguments to do that, but there we go.
46+
*/
47+
public static doesNotExist(cfn: ICloudFormationClient, stackName: string) {
48+
return new CloudFormationStack(cfn, stackName);
49+
}
50+
51+
/**
52+
* From static information (for testing)
53+
*/
54+
public static fromStaticInformation(cfn: ICloudFormationClient, stackName: string, stack: Stack) {
55+
return new CloudFormationStack(cfn, stackName, stack);
56+
}
57+
58+
private _template: any;
59+
60+
protected constructor(
61+
private readonly cfn: ICloudFormationClient,
62+
public readonly stackName: string,
63+
private readonly stack?: Stack,
64+
private readonly retrieveProcessedTemplate: boolean = false,
65+
) {
66+
}
67+
68+
/**
69+
* Retrieve the stack's deployed template
70+
*
71+
* Cached, so will only be retrieved once. Will return an empty
72+
* structure if the stack does not exist.
73+
*/
74+
public async template(): Promise<Template> {
75+
if (!this.exists) {
76+
return {};
77+
}
78+
79+
if (this._template === undefined) {
80+
const response = await this.cfn.getTemplate({
81+
StackName: this.stackName,
82+
TemplateStage: this.retrieveProcessedTemplate ? 'Processed' : 'Original',
83+
});
84+
this._template = (response.TemplateBody && deserializeStructure(response.TemplateBody)) || {};
85+
}
86+
return this._template;
87+
}
88+
89+
/**
90+
* Whether the stack exists
91+
*/
92+
public get exists() {
93+
return this.stack !== undefined;
94+
}
95+
96+
/**
97+
* The stack's ID
98+
*
99+
* Throws if the stack doesn't exist.
100+
*/
101+
public get stackId() {
102+
this.assertExists();
103+
return this.stack!.StackId!;
104+
}
105+
106+
/**
107+
* The stack's current outputs
108+
*
109+
* Empty object if the stack doesn't exist
110+
*/
111+
public get outputs(): Record<string, string> {
112+
if (!this.exists) {
113+
return {};
114+
}
115+
const result: { [name: string]: string } = {};
116+
(this.stack!.Outputs || []).forEach((output) => {
117+
result[output.OutputKey!] = output.OutputValue!;
118+
});
119+
return result;
120+
}
121+
122+
/**
123+
* The stack's status
124+
*
125+
* Special status NOT_FOUND if the stack does not exist.
126+
*/
127+
public get stackStatus(): StackStatus {
128+
if (!this.exists) {
129+
return new StackStatus('NOT_FOUND', 'Stack not found during lookup');
130+
}
131+
return StackStatus.fromStackDescription(this.stack!);
132+
}
133+
134+
/**
135+
* The stack's current tags
136+
*
137+
* Empty list if the stack does not exist
138+
*/
139+
public get tags(): Tag[] {
140+
return this.stack?.Tags || [];
141+
}
142+
143+
/**
144+
* SNS Topic ARNs that will receive stack events.
145+
*
146+
* Empty list if the stack does not exist
147+
*/
148+
public get notificationArns(): string[] {
149+
return this.stack?.NotificationARNs ?? [];
150+
}
151+
152+
/**
153+
* Return the names of all current parameters to the stack
154+
*
155+
* Empty list if the stack does not exist.
156+
*/
157+
public get parameterNames(): string[] {
158+
return Object.keys(this.parameters);
159+
}
160+
161+
/**
162+
* Return the names and values of all current parameters to the stack
163+
*
164+
* Empty object if the stack does not exist.
165+
*/
166+
public get parameters(): Record<string, string> {
167+
if (!this.exists) {
168+
return {};
169+
}
170+
const ret: Record<string, string> = {};
171+
for (const param of this.stack!.Parameters ?? []) {
172+
ret[param.ParameterKey!] = param.ResolvedValue ?? param.ParameterValue!;
173+
}
174+
return ret;
175+
}
176+
177+
/**
178+
* Return the termination protection of the stack
179+
*/
180+
public get terminationProtection(): boolean | undefined {
181+
return this.stack?.EnableTerminationProtection;
182+
}
183+
184+
private assertExists() {
185+
if (!this.exists) {
186+
throw new ToolkitError(`No stack named '${this.stackName}'`);
187+
}
188+
}
189+
}

packages/aws-cdk/lib/api/cloudformation/template-body-parameter.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/cloudformation/template-body-parameter.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { type CloudFormationStackArtifact, type Environment, EnvironmentPlacehol
55
import { HeadObjectCommand, S3Client } from '@aws-sdk/client-s3';
66
import { getEndpointFromInstructions } from '@smithy/middleware-endpoint';
77
import * as chalk from 'chalk';
8-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
9-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
108
import { contentHash, toYAML } from '../../util';
119
import type { AssetManifestBuilder } from '../deployments';
1210
import type { EnvironmentResources } from '../environment';
11+
import { IO, type IoHelper } from '../io/private';
12+
import { ToolkitError } from '../toolkit-error';
1313

1414
export type TemplateBodyParameter = {
1515
TemplateBody?: string;

packages/aws-cdk/lib/api/deployments/asset-publishing.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/asset-publishing.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import {
1515
AssetPublishing,
1616
} from 'cdk-assets';
1717
import type { SDK } from '..';
18-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
19-
import type { IoMessageMaker, IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
20-
import { IO } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
2118
import type { SdkProvider } from '../aws-auth';
19+
import type { IoMessageMaker, IoHelper } from '../io/private';
20+
import { IO } from '../io/private';
2221
import { Mode } from '../plugin';
22+
import { ToolkitError } from '../toolkit-error';
2323

2424
interface PublishAssetsOptions {
2525
/**

packages/aws-cdk/lib/api/deployments/assets.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/assets.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema';
44
import * as cxapi from '@aws-cdk/cx-api';
55
import * as chalk from 'chalk';
66
import type { AssetManifestBuilder } from './asset-manifest-builder';
7-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
8-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
97
import type { EnvironmentResources } from '../environment';
8+
import { IO, type IoHelper } from '../io/private';
9+
import { ToolkitError } from '../toolkit-error';
1010
import type { ToolkitInfo } from '../toolkit-info';
1111

1212
/**

packages/aws-cdk/lib/api/deployments/cfn-api.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import type { FileManifestEntry } from 'cdk-assets';
1414
import { AssetManifest } from 'cdk-assets';
1515
import { AssetManifestBuilder } from './asset-manifest-builder';
1616
import type { Deployments } from './deployments';
17-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
18-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
1917
import type { ICloudFormationClient, SdkProvider } from '../aws-auth';
2018
import type { Template, TemplateBodyParameter, TemplateParameter } from '../cloudformation';
2119
import { CloudFormationStack, makeBodyParameter } from '../cloudformation';
20+
import { IO, type IoHelper } from '../io/private';
2221
import type { ResourcesToImport } from '../resource-import';
22+
import { ToolkitError } from '../toolkit-error';
2323

2424
/**
2525
* Describe a changeset in CloudFormation, regardless of its current state.

packages/aws-cdk/lib/api/deployments/checks.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/checks.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
2-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
31
import type { SDK } from '../aws-auth';
2+
import { IO, type IoHelper } from '../io/private';
3+
import { ToolkitError } from '../toolkit-error';
44

55
export async function determineAllowCrossAccountAssetPublishing(
66
sdk: SDK,

packages/aws-cdk/lib/api/deployments/deploy-stack.ts renamed to packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/deploy-stack.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ import {
2727
import { determineAllowCrossAccountAssetPublishing } from './checks';
2828
import type { ChangeSetDeploymentMethod, DeploymentMethod } from './deployment-method';
2929
import type { DeployStackResult, SuccessfulDeployStackResult } from './deployment-result';
30-
import { tryHotswapDeployment } from './hotswap-deployments';
31-
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
32-
import { IO, type IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
3330
import { formatErrorMessage } from '../../util';
3431
import type { SDK, SdkProvider, ICloudFormationClient } from '../aws-auth';
3532
import type { TemplateBodyParameter } from '../cloudformation';
3633
import { makeBodyParameter, CfnEvaluationException, CloudFormationStack } from '../cloudformation';
3734
import type { EnvironmentResources, StringWithoutPlaceholders } from '../environment';
3835
import { HotswapMode, HotswapPropertyOverrides, ICON } from '../hotswap/common';
36+
import { tryHotswapDeployment } from '../hotswap/hotswap-deployments';
37+
import { IO, type IoHelper } from '../io/private';
3938
import type { ResourcesToImport } from '../resource-import';
4039
import { StackActivityMonitor } from '../stack-events';
40+
import { ToolkitError } from '../toolkit-error';
4141

4242
export interface DeployStackOptions {
4343
/**

0 commit comments

Comments
 (0)