@aws-cdk-testing/cli-integ 2.173.4 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +9 -0
- package/LICENSE +2 -1
- package/bin/query-github.js +3 -3
- package/bin/query-github.ts +56 -0
- package/bin/run-suite.js +3 -3
- package/bin/run-suite.ts +140 -0
- package/bin/stage-distribution.js +3 -2
- package/bin/stage-distribution.ts +267 -0
- package/bin/test-root.ts +3 -0
- package/lib/aws.js +9 -6
- package/lib/aws.ts +263 -0
- package/lib/corking.ts +33 -0
- package/lib/eventually.js +3 -3
- package/lib/eventually.ts +42 -0
- package/lib/files.js +3 -2
- package/lib/files.ts +80 -0
- package/lib/github.js +6 -5
- package/lib/github.ts +43 -0
- package/lib/index.ts +13 -0
- package/lib/integ-test.ts +81 -0
- package/lib/lists.ts +9 -0
- package/lib/memoize.ts +14 -0
- package/lib/npm.ts +41 -0
- package/lib/package-sources/release-source.js +3 -2
- package/lib/package-sources/release-source.ts +81 -0
- package/lib/package-sources/repo-source.ts +111 -0
- package/lib/package-sources/repo-tools/npm.js +5 -4
- package/lib/package-sources/repo-tools/npm.ts +48 -0
- package/lib/package-sources/source.ts +35 -0
- package/lib/package-sources/subprocess.ts +15 -0
- package/lib/resource-pool.js +2 -2
- package/lib/resource-pool.ts +140 -0
- package/lib/resources.ts +4 -0
- package/lib/shell.js +8 -5
- package/lib/shell.ts +168 -0
- package/lib/staging/codeartifact.js +11 -8
- package/lib/staging/codeartifact.ts +387 -0
- package/lib/staging/maven.js +5 -3
- package/lib/staging/maven.ts +95 -0
- package/lib/staging/npm.ts +62 -0
- package/lib/staging/nuget.ts +75 -0
- package/lib/staging/parallel-shell.js +2 -2
- package/lib/staging/parallel-shell.ts +51 -0
- package/lib/staging/pypi.ts +50 -0
- package/lib/staging/usage-dir.ts +99 -0
- package/lib/with-aws.js +3 -2
- package/lib/with-aws.ts +67 -0
- package/lib/with-cdk-app.js +23 -14
- package/lib/with-cdk-app.ts +742 -0
- package/lib/with-cli-lib.ts +134 -0
- package/lib/with-packages.ts +15 -0
- package/lib/with-sam.js +7 -4
- package/lib/with-sam.ts +288 -0
- package/lib/with-temporary-directory.ts +35 -0
- package/lib/with-timeout.ts +33 -0
- package/lib/xpmutex.js +2 -2
- package/lib/xpmutex.ts +218 -0
- package/package.json +84 -62
- package/resources/cloud-assemblies/0.36.0/cdk.out +1 -0
- package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/cdk.out +1 -0
- package/resources/cloud-assemblies/1.10.0-request-azs/cdk.out +1 -0
- package/tests/cli-integ-tests/bootstrapping.integtest.js +22 -13
- package/tests/cli-integ-tests/bootstrapping.integtest.ts +493 -0
- package/tests/cli-integ-tests/cli-lib.integtest.js +3 -2
- package/tests/cli-integ-tests/cli-lib.integtest.ts +90 -0
- package/tests/cli-integ-tests/cli.integtest.js +76 -49
- package/tests/cli-integ-tests/cli.integtest.ts +2874 -0
- package/tests/cli-integ-tests/garbage-collection.integtest.js +2 -2
- package/tests/cli-integ-tests/garbage-collection.integtest.ts +392 -0
- package/tests/init-csharp/init-csharp.integtest.ts +15 -0
- package/tests/init-fsharp/init-fsharp.integtest.ts +15 -0
- package/tests/init-go/init-go.integtest.ts +23 -0
- package/tests/init-java/init-java.integtest.ts +14 -0
- package/tests/init-javascript/init-javascript.integtest.ts +59 -0
- package/tests/init-python/init-python.integtest.ts +20 -0
- package/tests/init-typescript-app/init-typescript-app.integtest.ts +66 -0
- package/tests/init-typescript-lib/init-typescript-lib.integtest.ts +13 -0
- package/tests/tool-integrations/amplify.integtest.ts +43 -0
- package/tests/tool-integrations/with-tool-context.ts +14 -0
- package/tests/uberpackage/uberpackage.integtest.ts +11 -0
- package/resources/cdk-apps/cfn-include-app/.gitignore +0 -1
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/* eslint-disable @cdklabs/no-literal-partition */
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { DescribeStackResourcesCommand, DescribeStacksCommand } from '@aws-sdk/client-cloudformation';
|
|
5
|
+
import { DescribeRepositoriesCommand } from '@aws-sdk/client-ecr';
|
|
6
|
+
import { CreatePolicyCommand, DeletePolicyCommand, GetRoleCommand } from '@aws-sdk/client-iam';
|
|
7
|
+
import * as yaml from 'yaml';
|
|
8
|
+
import { integTest, randomString, withoutBootstrap } from '../../lib';
|
|
9
|
+
import eventually from '../../lib/eventually';
|
|
10
|
+
|
|
11
|
+
jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime
|
|
12
|
+
|
|
13
|
+
integTest('can bootstrap without execution', withoutBootstrap(async (fixture) => {
|
|
14
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
15
|
+
|
|
16
|
+
await fixture.cdkBootstrapLegacy({
|
|
17
|
+
toolkitStackName: bootstrapStackName,
|
|
18
|
+
noExecute: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const resp = await fixture.aws.cloudFormation.send(
|
|
22
|
+
new DescribeStacksCommand({
|
|
23
|
+
StackName: bootstrapStackName,
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(resp.Stacks?.[0].StackStatus).toEqual('REVIEW_IN_PROGRESS');
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
integTest('upgrade legacy bootstrap stack to new bootstrap stack while in use', withoutBootstrap(async (fixture) => {
|
|
31
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
32
|
+
|
|
33
|
+
const legacyBootstrapBucketName = `aws-cdk-bootstrap-integ-test-legacy-bckt-${randomString()}`;
|
|
34
|
+
const newBootstrapBucketName = `aws-cdk-bootstrap-integ-test-v2-bckt-${randomString()}`;
|
|
35
|
+
fixture.rememberToDeleteBucket(legacyBootstrapBucketName); // This one will leak
|
|
36
|
+
fixture.rememberToDeleteBucket(newBootstrapBucketName); // This one shouldn't leak if the test succeeds, but let's be safe in case it doesn't
|
|
37
|
+
|
|
38
|
+
// Legacy bootstrap
|
|
39
|
+
await fixture.cdkBootstrapLegacy({
|
|
40
|
+
toolkitStackName: bootstrapStackName,
|
|
41
|
+
bootstrapBucketName: legacyBootstrapBucketName,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Deploy stack that uses file assets
|
|
45
|
+
await fixture.cdkDeploy('lambda', {
|
|
46
|
+
options: [
|
|
47
|
+
'--context', `bootstrapBucket=${legacyBootstrapBucketName}`,
|
|
48
|
+
'--context', 'legacySynth=true',
|
|
49
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
50
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Upgrade bootstrap stack to "new" style
|
|
55
|
+
await fixture.cdkBootstrapModern({
|
|
56
|
+
toolkitStackName: bootstrapStackName,
|
|
57
|
+
bootstrapBucketName: newBootstrapBucketName,
|
|
58
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// (Force) deploy stack again
|
|
62
|
+
// --force to bypass the check which says that the template hasn't changed.
|
|
63
|
+
await fixture.cdkDeploy('lambda', {
|
|
64
|
+
options: [
|
|
65
|
+
'--context', `bootstrapBucket=${newBootstrapBucketName}`,
|
|
66
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
67
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
68
|
+
'--force',
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
integTest('can and deploy if omitting execution policies', withoutBootstrap(async (fixture) => {
|
|
74
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
75
|
+
|
|
76
|
+
await fixture.cdkBootstrapModern({
|
|
77
|
+
toolkitStackName: bootstrapStackName,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Deploy stack that uses file assets
|
|
81
|
+
await fixture.cdkDeploy('lambda', {
|
|
82
|
+
options: [
|
|
83
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
84
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
85
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
integTest('can deploy with session tags on the deploy, lookup, file asset, and image asset publishing roles', withoutBootstrap(async (fixture) => {
|
|
91
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
92
|
+
|
|
93
|
+
await fixture.cdkBootstrapModern({
|
|
94
|
+
toolkitStackName: bootstrapStackName,
|
|
95
|
+
bootstrapTemplate: path.join(__dirname, '..', '..', 'resources', 'bootstrap-templates', 'session-tags.all-roles-deny-all.yaml'),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await fixture.cdkDeploy('session-tags', {
|
|
99
|
+
options: [
|
|
100
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
101
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
102
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
103
|
+
],
|
|
104
|
+
modEnv: {
|
|
105
|
+
ENABLE_VPC_TESTING: 'IMPORT',
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
integTest('can deploy without execution role and with session tags on deploy role', withoutBootstrap(async (fixture) => {
|
|
111
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
112
|
+
|
|
113
|
+
await fixture.cdkBootstrapModern({
|
|
114
|
+
toolkitStackName: bootstrapStackName,
|
|
115
|
+
bootstrapTemplate: path.join(__dirname, '..', '..', 'resources', 'bootstrap-templates', 'session-tags.deploy-role-deny-sqs.yaml'),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await fixture.cdkDeploy('session-tags-with-custom-synthesizer', {
|
|
119
|
+
options: [
|
|
120
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
121
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
122
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
}));
|
|
126
|
+
|
|
127
|
+
integTest('deploy new style synthesis to new style bootstrap', withoutBootstrap(async (fixture) => {
|
|
128
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
129
|
+
|
|
130
|
+
await fixture.cdkBootstrapModern({
|
|
131
|
+
toolkitStackName: bootstrapStackName,
|
|
132
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Deploy stack that uses file assets
|
|
136
|
+
await fixture.cdkDeploy('lambda', {
|
|
137
|
+
options: [
|
|
138
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
139
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
140
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
}));
|
|
144
|
+
|
|
145
|
+
integTest('deploy new style synthesis to new style bootstrap (with docker image)', withoutBootstrap(async (fixture) => {
|
|
146
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
147
|
+
|
|
148
|
+
await fixture.cdkBootstrapModern({
|
|
149
|
+
toolkitStackName: bootstrapStackName,
|
|
150
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Deploy stack that uses file assets
|
|
154
|
+
await fixture.cdkDeploy('docker', {
|
|
155
|
+
options: [
|
|
156
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
157
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
158
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
integTest('deploy old style synthesis to new style bootstrap', withoutBootstrap(async (fixture) => {
|
|
164
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
165
|
+
|
|
166
|
+
await fixture.cdkBootstrapModern({
|
|
167
|
+
toolkitStackName: bootstrapStackName,
|
|
168
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Deploy stack that uses file assets
|
|
172
|
+
await fixture.cdkDeploy('lambda', {
|
|
173
|
+
options: [
|
|
174
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
175
|
+
'--toolkit-stack-name', bootstrapStackName,
|
|
176
|
+
],
|
|
177
|
+
});
|
|
178
|
+
}));
|
|
179
|
+
|
|
180
|
+
integTest('can create a legacy bootstrap stack with --public-access-block-configuration=false', withoutBootstrap(async (fixture) => {
|
|
181
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
182
|
+
|
|
183
|
+
await fixture.cdkBootstrapLegacy({
|
|
184
|
+
verbose: true,
|
|
185
|
+
toolkitStackName: bootstrapStackName,
|
|
186
|
+
publicAccessBlockConfiguration: false,
|
|
187
|
+
tags: 'Foo=Bar',
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const response = await fixture.aws.cloudFormation.send(new DescribeStacksCommand({ StackName: bootstrapStackName }));
|
|
191
|
+
expect(response.Stacks?.[0].Tags).toEqual([
|
|
192
|
+
{ Key: 'Foo', Value: 'Bar' },
|
|
193
|
+
]);
|
|
194
|
+
}));
|
|
195
|
+
|
|
196
|
+
integTest('can create multiple legacy bootstrap stacks', withoutBootstrap(async (fixture) => {
|
|
197
|
+
const bootstrapStackName1 = `${fixture.bootstrapStackName}-1`;
|
|
198
|
+
const bootstrapStackName2 = `${fixture.bootstrapStackName}-2`;
|
|
199
|
+
|
|
200
|
+
// deploy two toolkit stacks into the same environment (see #1416)
|
|
201
|
+
// one with tags
|
|
202
|
+
await fixture.cdkBootstrapLegacy({
|
|
203
|
+
verbose: true,
|
|
204
|
+
toolkitStackName: bootstrapStackName1,
|
|
205
|
+
tags: 'Foo=Bar',
|
|
206
|
+
});
|
|
207
|
+
await fixture.cdkBootstrapLegacy({
|
|
208
|
+
verbose: true,
|
|
209
|
+
toolkitStackName: bootstrapStackName2,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const response = await fixture.aws.cloudFormation.send(new DescribeStacksCommand({ StackName: bootstrapStackName1 }));
|
|
213
|
+
expect(response.Stacks?.[0].Tags).toEqual([
|
|
214
|
+
{ Key: 'Foo', Value: 'Bar' },
|
|
215
|
+
]);
|
|
216
|
+
}));
|
|
217
|
+
|
|
218
|
+
integTest('can dump the template, modify and use it to deploy a custom bootstrap stack', withoutBootstrap(async (fixture) => {
|
|
219
|
+
let template = await fixture.cdkBootstrapModern({
|
|
220
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
221
|
+
toolkitStackName: fixture.bootstrapStackName,
|
|
222
|
+
showTemplate: true,
|
|
223
|
+
cliOptions: {
|
|
224
|
+
captureStderr: false,
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
expect(template).toContain('BootstrapVersion:');
|
|
229
|
+
|
|
230
|
+
template += '\n' + [
|
|
231
|
+
' TwiddleDee:',
|
|
232
|
+
' Value: Template got twiddled',
|
|
233
|
+
].join('\n');
|
|
234
|
+
|
|
235
|
+
const filename = path.join(fixture.integTestDir, `${fixture.qualifier}-template.yaml`);
|
|
236
|
+
fs.writeFileSync(filename, template, { encoding: 'utf-8' });
|
|
237
|
+
await fixture.cdkBootstrapModern({
|
|
238
|
+
toolkitStackName: fixture.bootstrapStackName,
|
|
239
|
+
template: filename,
|
|
240
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
241
|
+
});
|
|
242
|
+
}));
|
|
243
|
+
|
|
244
|
+
integTest('a customized template vendor will not overwrite the default template', withoutBootstrap(async (fixture) => {
|
|
245
|
+
// Initial bootstrap
|
|
246
|
+
const toolkitStackName = fixture.bootstrapStackName;
|
|
247
|
+
await fixture.cdkBootstrapModern({
|
|
248
|
+
toolkitStackName,
|
|
249
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Customize template
|
|
253
|
+
const templateStr = await fixture.cdkBootstrapModern({
|
|
254
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
255
|
+
toolkitStackName,
|
|
256
|
+
showTemplate: true,
|
|
257
|
+
cliOptions: {
|
|
258
|
+
captureStderr: false,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const template = yaml.parse(templateStr, { schema: 'core' });
|
|
263
|
+
template.Parameters.BootstrapVariant.Default = 'CustomizedVendor';
|
|
264
|
+
const filename = path.join(fixture.integTestDir, `${fixture.qualifier}-template.yaml`);
|
|
265
|
+
fs.writeFileSync(filename, yaml.stringify(template, { schema: 'yaml-1.1' }), { encoding: 'utf-8' });
|
|
266
|
+
|
|
267
|
+
// Rebootstrap. For some reason, this doesn't cause a failure, it's a successful no-op.
|
|
268
|
+
const output = await fixture.cdkBootstrapModern({
|
|
269
|
+
toolkitStackName,
|
|
270
|
+
template: filename,
|
|
271
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
272
|
+
cliOptions: {
|
|
273
|
+
captureStderr: true,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
expect(output).toContain('Not overwriting it with a template containing');
|
|
277
|
+
}));
|
|
278
|
+
|
|
279
|
+
integTest('can use the default permissions boundary to bootstrap', withoutBootstrap(async (fixture) => {
|
|
280
|
+
let template = await fixture.cdkBootstrapModern({
|
|
281
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
282
|
+
toolkitStackName: fixture.bootstrapStackName,
|
|
283
|
+
showTemplate: true,
|
|
284
|
+
examplePermissionsBoundary: true,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
expect(template).toContain('PermissionsBoundary');
|
|
288
|
+
}));
|
|
289
|
+
|
|
290
|
+
integTest('can use the custom permissions boundary to bootstrap', withoutBootstrap(async (fixture) => {
|
|
291
|
+
let template = await fixture.cdkBootstrapModern({
|
|
292
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
293
|
+
toolkitStackName: fixture.bootstrapStackName,
|
|
294
|
+
showTemplate: true,
|
|
295
|
+
customPermissionsBoundary: 'permission-boundary-name',
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(template).toContain('permission-boundary-name');
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
integTest('can use the custom permissions boundary (with slashes) to bootstrap', withoutBootstrap(async (fixture) => {
|
|
302
|
+
let template = await fixture.cdkBootstrapModern({
|
|
303
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
304
|
+
toolkitStackName: fixture.bootstrapStackName,
|
|
305
|
+
showTemplate: true,
|
|
306
|
+
customPermissionsBoundary: 'permission-boundary-name/with/path',
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
expect(template).toContain('permission-boundary-name/with/path');
|
|
310
|
+
}));
|
|
311
|
+
|
|
312
|
+
integTest('can remove customPermissionsBoundary', withoutBootstrap(async (fixture) => {
|
|
313
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
314
|
+
const policyName = `${bootstrapStackName}-pb`;
|
|
315
|
+
let policyArn;
|
|
316
|
+
try {
|
|
317
|
+
const policy = await fixture.aws.iam.send(
|
|
318
|
+
new CreatePolicyCommand({
|
|
319
|
+
PolicyName: policyName,
|
|
320
|
+
PolicyDocument: JSON.stringify({
|
|
321
|
+
Version: '2012-10-17',
|
|
322
|
+
Statement: {
|
|
323
|
+
Action: ['*'],
|
|
324
|
+
Resource: ['*'],
|
|
325
|
+
Effect: 'Allow',
|
|
326
|
+
},
|
|
327
|
+
}),
|
|
328
|
+
}),
|
|
329
|
+
);
|
|
330
|
+
policyArn = policy.Policy?.Arn;
|
|
331
|
+
|
|
332
|
+
// Policy creation and consistency across regions is "almost immediate"
|
|
333
|
+
// See: https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency
|
|
334
|
+
// We will put this in an `eventually` block to retry stack creation with a reasonable timeout
|
|
335
|
+
const createStackWithPermissionBoundary = async (): Promise<void> => {
|
|
336
|
+
await fixture.cdkBootstrapModern({
|
|
337
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
338
|
+
toolkitStackName: bootstrapStackName,
|
|
339
|
+
customPermissionsBoundary: policyName,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const response = await fixture.aws.cloudFormation.send(
|
|
343
|
+
new DescribeStacksCommand({ StackName: bootstrapStackName }),
|
|
344
|
+
);
|
|
345
|
+
expect(
|
|
346
|
+
response.Stacks?.[0].Parameters?.some(
|
|
347
|
+
param => (param.ParameterKey === 'InputPermissionsBoundary' && param.ParameterValue === policyName),
|
|
348
|
+
)).toEqual(true);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
await eventually(createStackWithPermissionBoundary, { maxAttempts: 3 });
|
|
352
|
+
|
|
353
|
+
await fixture.cdkBootstrapModern({
|
|
354
|
+
// toolkitStackName doesn't matter for this particular invocation
|
|
355
|
+
toolkitStackName: bootstrapStackName,
|
|
356
|
+
usePreviousParameters: false,
|
|
357
|
+
});
|
|
358
|
+
const response2 = await fixture.aws.cloudFormation.send(
|
|
359
|
+
new DescribeStacksCommand({ StackName: bootstrapStackName }),
|
|
360
|
+
);
|
|
361
|
+
expect(
|
|
362
|
+
response2.Stacks?.[0].Parameters?.some(
|
|
363
|
+
param => (param.ParameterKey === 'InputPermissionsBoundary' && !param.ParameterValue),
|
|
364
|
+
)).toEqual(true);
|
|
365
|
+
|
|
366
|
+
const region = fixture.aws.region;
|
|
367
|
+
const account = await fixture.aws.account();
|
|
368
|
+
const role = await fixture.aws.iam.send(
|
|
369
|
+
new GetRoleCommand({ RoleName: `cdk-${fixture.qualifier}-cfn-exec-role-${account}-${region}` }),
|
|
370
|
+
);
|
|
371
|
+
if (!role.Role) {
|
|
372
|
+
throw new Error('Role not found');
|
|
373
|
+
}
|
|
374
|
+
expect(role.Role.PermissionsBoundary).toBeUndefined();
|
|
375
|
+
|
|
376
|
+
} finally {
|
|
377
|
+
if (policyArn) {
|
|
378
|
+
await fixture.aws.iam.send(new DeletePolicyCommand({ PolicyArn: policyArn }));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}));
|
|
382
|
+
|
|
383
|
+
integTest('switch on termination protection, switch is left alone on re-bootstrap', withoutBootstrap(async (fixture) => {
|
|
384
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
385
|
+
|
|
386
|
+
await fixture.cdkBootstrapModern({
|
|
387
|
+
verbose: true,
|
|
388
|
+
toolkitStackName: bootstrapStackName,
|
|
389
|
+
terminationProtection: true,
|
|
390
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
391
|
+
});
|
|
392
|
+
await fixture.cdkBootstrapModern({
|
|
393
|
+
verbose: true,
|
|
394
|
+
toolkitStackName: bootstrapStackName,
|
|
395
|
+
force: true,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
const response = await fixture.aws.cloudFormation.send(new DescribeStacksCommand({ StackName: bootstrapStackName }));
|
|
399
|
+
expect(response.Stacks?.[0].EnableTerminationProtection).toEqual(true);
|
|
400
|
+
}));
|
|
401
|
+
|
|
402
|
+
integTest('add tags, left alone on re-bootstrap', withoutBootstrap(async (fixture) => {
|
|
403
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
404
|
+
|
|
405
|
+
await fixture.cdkBootstrapModern({
|
|
406
|
+
verbose: true,
|
|
407
|
+
toolkitStackName: bootstrapStackName,
|
|
408
|
+
tags: 'Foo=Bar',
|
|
409
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
410
|
+
});
|
|
411
|
+
await fixture.cdkBootstrapModern({
|
|
412
|
+
verbose: true,
|
|
413
|
+
toolkitStackName: bootstrapStackName,
|
|
414
|
+
force: true,
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const response = await fixture.aws.cloudFormation.send(new DescribeStacksCommand({ StackName: bootstrapStackName }));
|
|
418
|
+
expect(response.Stacks?.[0].Tags).toEqual([
|
|
419
|
+
{ Key: 'Foo', Value: 'Bar' },
|
|
420
|
+
]);
|
|
421
|
+
}));
|
|
422
|
+
|
|
423
|
+
integTest('can add tags then update tags during re-bootstrap', withoutBootstrap(async (fixture) => {
|
|
424
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
425
|
+
|
|
426
|
+
await fixture.cdkBootstrapModern({
|
|
427
|
+
verbose: true,
|
|
428
|
+
toolkitStackName: bootstrapStackName,
|
|
429
|
+
tags: 'Foo=Bar',
|
|
430
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
431
|
+
});
|
|
432
|
+
await fixture.cdkBootstrapModern({
|
|
433
|
+
verbose: true,
|
|
434
|
+
toolkitStackName: bootstrapStackName,
|
|
435
|
+
tags: 'Foo=BarBaz',
|
|
436
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
437
|
+
force: true,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const response = await fixture.aws.cloudFormation.send(new DescribeStacksCommand({ StackName: bootstrapStackName }));
|
|
441
|
+
expect(response.Stacks?.[0].Tags).toEqual([
|
|
442
|
+
{ Key: 'Foo', Value: 'BarBaz' },
|
|
443
|
+
]);
|
|
444
|
+
}));
|
|
445
|
+
|
|
446
|
+
integTest('can deploy modern-synthesized stack even if bootstrap stack name is unknown', withoutBootstrap(async (fixture) => {
|
|
447
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
448
|
+
|
|
449
|
+
await fixture.cdkBootstrapModern({
|
|
450
|
+
toolkitStackName: bootstrapStackName,
|
|
451
|
+
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Deploy stack that uses file assets
|
|
455
|
+
await fixture.cdkDeploy('lambda', {
|
|
456
|
+
options: [
|
|
457
|
+
// Explicity pass a name that's sure to not exist, otherwise the CLI might accidentally find a
|
|
458
|
+
// default bootstracp stack if that happens to be in the account already.
|
|
459
|
+
'--toolkit-stack-name', 'DefinitelyDoesNotExist',
|
|
460
|
+
'--context', `@aws-cdk/core:bootstrapQualifier=${fixture.qualifier}`,
|
|
461
|
+
'--context', '@aws-cdk/core:newStyleStackSynthesis=1',
|
|
462
|
+
],
|
|
463
|
+
});
|
|
464
|
+
}));
|
|
465
|
+
|
|
466
|
+
integTest('create ECR with tag IMMUTABILITY to set on', withoutBootstrap(async (fixture) => {
|
|
467
|
+
const bootstrapStackName = fixture.bootstrapStackName;
|
|
468
|
+
|
|
469
|
+
await fixture.cdkBootstrapModern({
|
|
470
|
+
verbose: true,
|
|
471
|
+
toolkitStackName: bootstrapStackName,
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
const response = await fixture.aws.cloudFormation.send(
|
|
475
|
+
new DescribeStackResourcesCommand({
|
|
476
|
+
StackName: bootstrapStackName,
|
|
477
|
+
}),
|
|
478
|
+
);
|
|
479
|
+
const ecrResource = response.StackResources?.find(resource => resource.LogicalResourceId === 'ContainerAssetsRepository');
|
|
480
|
+
expect(ecrResource).toBeDefined();
|
|
481
|
+
|
|
482
|
+
const ecrResponse = await fixture.aws.ecr.send(
|
|
483
|
+
new DescribeRepositoriesCommand({
|
|
484
|
+
repositoryNames: [
|
|
485
|
+
// This is set, as otherwise we don't end up here
|
|
486
|
+
ecrResource?.PhysicalResourceId ?? '',
|
|
487
|
+
],
|
|
488
|
+
}),
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
expect(ecrResponse.repositories?.[0].imageTagMutability).toEqual('IMMUTABLE');
|
|
492
|
+
}));
|
|
493
|
+
|
|
@@ -25,6 +25,7 @@ jest.setTimeout(2 * 60 * 60000); // Includes the time to acquire locks, worst-ca
|
|
|
25
25
|
expect(listing).toContain(fixture.fullStackName('simple-1'));
|
|
26
26
|
}));
|
|
27
27
|
(0, lib_1.integTest)('cli-lib deploy', (0, lib_1.withCliLibFixture)(async (fixture) => {
|
|
28
|
+
var _a;
|
|
28
29
|
const stackName = fixture.fullStackName('simple-1');
|
|
29
30
|
try {
|
|
30
31
|
// deploy the stack
|
|
@@ -35,7 +36,7 @@ jest.setTimeout(2 * 60 * 60000); // Includes the time to acquire locks, worst-ca
|
|
|
35
36
|
const expectedStack = await fixture.aws.cloudFormation.send(new client_cloudformation_1.DescribeStackResourcesCommand({
|
|
36
37
|
StackName: stackName,
|
|
37
38
|
}));
|
|
38
|
-
expect(expectedStack.StackResources
|
|
39
|
+
expect((_a = expectedStack.StackResources) === null || _a === void 0 ? void 0 : _a.length).toEqual(3);
|
|
39
40
|
}
|
|
40
41
|
finally {
|
|
41
42
|
// delete the stack
|
|
@@ -58,4 +59,4 @@ jest.setTimeout(2 * 60 * 60000); // Includes the time to acquire locks, worst-ca
|
|
|
58
59
|
StackName: fixture.fullStackName('simple-1'),
|
|
59
60
|
}))).rejects.toThrow('does not exist');
|
|
60
61
|
}));
|
|
61
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWxpYi5pbnRlZ3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjbGktbGliLmludGVndGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDBFQUFzRztBQUN0RyxtQ0FBeUQ7QUFFekQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQU0sQ0FBQyxDQUFDLENBQUMseUVBQXlFO0FBRTNHLElBQUEsZUFBUyxFQUNQLGVBQWUsRUFDZixJQUFBLHVCQUFpQixFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUNsQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQzFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUN0QixtRUFBbUU7UUFDbkUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztZQUNqQyxhQUFhLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDO2dCQUNyQyxJQUFJLEVBQUUsaUJBQWlCO2dCQUN2QixVQUFVLEVBQUU7b0JBQ1YsaUJBQWlCLEVBQUUsR0FBRztpQkFDdkI7Z0JBQ0QsUUFBUSxFQUFFO29CQUNSLGNBQWMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLDBCQUEwQjtpQkFDckU7YUFDRixDQUFDO1NBQ0gsQ0FBQztLQUNILENBQUMsQ0FDSCxDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUVGLElBQUEsZUFBUyxFQUNQLGNBQWMsRUFDZCxJQUFBLHVCQUFpQixFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUNsQyxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0FBQy9ELENBQUMsQ0FBQyxDQUNILENBQUM7QUFFRixJQUFBLGVBQVMsRUFDUCxnQkFBZ0IsRUFDaEIsSUFBQSx1QkFBaUIsRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQ2xDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFcEQsSUFBSSxDQUFDO1FBQ0gsbUJBQW1CO1FBQ25CLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsRUFBRTtZQUN2QyxvQkFBb0IsRUFBRSxJQUFJO1NBQzNCLENBQUMsQ0FBQztRQUVILDhDQUE4QztRQUM5QyxNQUFNLGFBQWEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksQ0FDekQsSUFBSSxxREFBNkIsQ0FBQztZQUNoQyxTQUFTLEVBQUUsU0FBUztTQUNyQixDQUFDLENBQ0gsQ0FBQztRQUNGLE1BQU0sQ0FBQyxNQUFBLGFBQWEsQ0FBQyxjQUFjLDBDQUFFLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRCxDQUFDO1lBQVMsQ0FBQztRQUNULG1CQUFtQjtRQUNuQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLEVBQUU7WUFDeEMsYUFBYSxFQUFFLEtBQUs7U0FDckIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUMsQ0FBQyxDQUNILENBQUM7QUFFRixJQUFBLGVBQVMsRUFDUCx1RkFBdUYsRUFDdkYsSUFBQSx1QkFBaUIsRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDbEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRTtRQUM5RSxVQUFVLEVBQUUsSUFBSTtRQUNoQixhQUFhLEVBQUUsSUFBSTtRQUNuQixZQUFZLEVBQUUsSUFBSTtRQUNsQixvQkFBb0IsRUFBRSxLQUFLO0tBQzVCLENBQUMsQ0FBQztJQUVILE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLENBQ3RCLDJHQUEyRyxDQUM1RyxDQUFDO0lBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFNBQVMsQ0FDdEIsK0VBQStFLENBQ2hGLENBQUM7SUFFRixnQ0FBZ0M7SUFDaEMsTUFBTSxNQUFNLENBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUM3QixJQUFJLDZDQUFxQixDQUFDO1FBQ3hCLFNBQVMsRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztLQUM3QyxDQUFDLENBQ0gsQ0FDRixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUN0QyxDQUFDLENBQUMsQ0FDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVzY3JpYmVTdGFja1Jlc291cmNlc0NvbW1hbmQsIERlc2NyaWJlU3RhY2tzQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZGZvcm1hdGlvbic7XG5pbXBvcnQgeyBpbnRlZ1Rlc3QsIHdpdGhDbGlMaWJGaXh0dXJlIH0gZnJvbSAnLi4vLi4vbGliJztcblxuamVzdC5zZXRUaW1lb3V0KDIgKiA2MCAqIDYwXzAwMCk7IC8vIEluY2x1ZGVzIHRoZSB0aW1lIHRvIGFjcXVpcmUgbG9ja3MsIHdvcnN0LWNhc2Ugc2luZ2xlLXRocmVhZGVkIHJ1bnRpbWVcblxuaW50ZWdUZXN0KFxuICAnY2xpLWxpYiBzeW50aCcsXG4gIHdpdGhDbGlMaWJGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gICAgYXdhaXQgZml4dHVyZS5jZGsoWydzeW50aCcsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgnc2ltcGxlLTEnKV0pO1xuICAgIGV4cGVjdChmaXh0dXJlLnRlbXBsYXRlKCdzaW1wbGUtMScpKS50b0VxdWFsKFxuICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgICAvLyBDaGVja2luZyBmb3IgYSBzbWFsbCBzdWJzZXQgaXMgZW5vdWdoIGFzIHByb29mIHRoYXQgc3ludGggd29ya2VkXG4gICAgICAgIFJlc291cmNlczogZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgICAgIHF1ZXVlMjc2RjcyOTc6IGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgICAgICAgIFR5cGU6ICdBV1M6OlNRUzo6UXVldWUnLFxuICAgICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgICBWaXNpYmlsaXR5VGltZW91dDogMzAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICdhd3M6Y2RrOnBhdGgnOiBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH0tc2ltcGxlLTEvcXVldWUvUmVzb3VyY2VgLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICApO1xuICB9KSxcbik7XG5cbmludGVnVGVzdChcbiAgJ2NsaS1saWIgbGlzdCcsXG4gIHdpdGhDbGlMaWJGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gICAgY29uc3QgbGlzdGluZyA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnbGlzdCddLCB7IGNhcHR1cmVTdGRlcnI6IGZhbHNlIH0pO1xuICAgIGV4cGVjdChsaXN0aW5nKS50b0NvbnRhaW4oZml4dHVyZS5mdWxsU3RhY2tOYW1lKCdzaW1wbGUtMScpKTtcbiAgfSksXG4pO1xuXG5pbnRlZ1Rlc3QoXG4gICdjbGktbGliIGRlcGxveScsXG4gIHdpdGhDbGlMaWJGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gICAgY29uc3Qgc3RhY2tOYW1lID0gZml4dHVyZS5mdWxsU3RhY2tOYW1lKCdzaW1wbGUtMScpO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGRlcGxveSB0aGUgc3RhY2tcbiAgICAgIGF3YWl0IGZpeHR1cmUuY2RrKFsnZGVwbG95Jywgc3RhY2tOYW1lXSwge1xuICAgICAgICBuZXZlclJlcXVpcmVBcHByb3ZhbDogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyB2ZXJpZnkgdGhlIG51bWJlciBvZiByZXNvdXJjZXMgaW4gdGhlIHN0YWNrXG4gICAgICBjb25zdCBleHBlY3RlZFN0YWNrID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24uc2VuZChcbiAgICAgICAgbmV3IERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kKHtcbiAgICAgICAgICBTdGFja05hbWU6IHN0YWNrTmFtZSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgICAgZXhwZWN0KGV4cGVjdGVkU3RhY2suU3RhY2tSZXNvdXJjZXM/Lmxlbmd0aCkudG9FcXVhbCgzKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gZGVsZXRlIHRoZSBzdGFja1xuICAgICAgYXdhaXQgZml4dHVyZS5jZGsoWydkZXN0cm95Jywgc3RhY2tOYW1lXSwge1xuICAgICAgICBjYXB0dXJlU3RkZXJyOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfSksXG4pO1xuXG5pbnRlZ1Rlc3QoXG4gICdzZWN1cml0eSByZWxhdGVkIGNoYW5nZXMgd2l0aG91dCBhIENMSSBhcmUgZXhwZWN0ZWQgdG8gZmFpbCB3aGVuIGFwcHJvdmFsIGlzIHJlcXVpcmVkJyxcbiAgd2l0aENsaUxpYkZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgICBjb25zdCBzdGRFcnIgPSBhd2FpdCBmaXh0dXJlLmNkayhbJ2RlcGxveScsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgnc2ltcGxlLTEnKV0sIHtcbiAgICAgIG9ubHlTdGRlcnI6IHRydWUsXG4gICAgICBjYXB0dXJlU3RkZXJyOiB0cnVlLFxuICAgICAgYWxsb3dFcnJFeGl0OiB0cnVlLFxuICAgICAgbmV2ZXJSZXF1aXJlQXBwcm92YWw6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHN0ZEVycikudG9Db250YWluKFxuICAgICAgJ1RoaXMgZGVwbG95bWVudCB3aWxsIG1ha2UgcG90ZW50aWFsbHkgc2Vuc2l0aXZlIGNoYW5nZXMgYWNjb3JkaW5nIHRvIHlvdXIgY3VycmVudCBzZWN1cml0eSBhcHByb3ZhbCBsZXZlbCcsXG4gICAgKTtcbiAgICBleHBlY3Qoc3RkRXJyKS50b0NvbnRhaW4oXG4gICAgICAnXCItLXJlcXVpcmUtYXBwcm92YWxcIiBpcyBlbmFibGVkIGFuZCBzdGFjayBpbmNsdWRlcyBzZWN1cml0eS1zZW5zaXRpdmUgdXBkYXRlcycsXG4gICAgKTtcblxuICAgIC8vIEVuc3VyZSBzdGFjayB3YXMgbm90IGRlcGxveWVkXG4gICAgYXdhaXQgZXhwZWN0KFxuICAgICAgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24uc2VuZChcbiAgICAgICAgbmV3IERlc2NyaWJlU3RhY2tzQ29tbWFuZCh7XG4gICAgICAgICAgU3RhY2tOYW1lOiBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ3NpbXBsZS0xJyksXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApLnJlamVjdHMudG9UaHJvdygnZG9lcyBub3QgZXhpc3QnKTtcbiAgfSksXG4pO1xuIl19
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { DescribeStackResourcesCommand, DescribeStacksCommand } from '@aws-sdk/client-cloudformation';
|
|
2
|
+
import { integTest, withCliLibFixture } from '../../lib';
|
|
3
|
+
|
|
4
|
+
jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime
|
|
5
|
+
|
|
6
|
+
integTest(
|
|
7
|
+
'cli-lib synth',
|
|
8
|
+
withCliLibFixture(async (fixture) => {
|
|
9
|
+
await fixture.cdk(['synth', fixture.fullStackName('simple-1')]);
|
|
10
|
+
expect(fixture.template('simple-1')).toEqual(
|
|
11
|
+
expect.objectContaining({
|
|
12
|
+
// Checking for a small subset is enough as proof that synth worked
|
|
13
|
+
Resources: expect.objectContaining({
|
|
14
|
+
queue276F7297: expect.objectContaining({
|
|
15
|
+
Type: 'AWS::SQS::Queue',
|
|
16
|
+
Properties: {
|
|
17
|
+
VisibilityTimeout: 300,
|
|
18
|
+
},
|
|
19
|
+
Metadata: {
|
|
20
|
+
'aws:cdk:path': `${fixture.stackNamePrefix}-simple-1/queue/Resource`,
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
}),
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
integTest(
|
|
30
|
+
'cli-lib list',
|
|
31
|
+
withCliLibFixture(async (fixture) => {
|
|
32
|
+
const listing = await fixture.cdk(['list'], { captureStderr: false });
|
|
33
|
+
expect(listing).toContain(fixture.fullStackName('simple-1'));
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
integTest(
|
|
38
|
+
'cli-lib deploy',
|
|
39
|
+
withCliLibFixture(async (fixture) => {
|
|
40
|
+
const stackName = fixture.fullStackName('simple-1');
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// deploy the stack
|
|
44
|
+
await fixture.cdk(['deploy', stackName], {
|
|
45
|
+
neverRequireApproval: true,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// verify the number of resources in the stack
|
|
49
|
+
const expectedStack = await fixture.aws.cloudFormation.send(
|
|
50
|
+
new DescribeStackResourcesCommand({
|
|
51
|
+
StackName: stackName,
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
expect(expectedStack.StackResources?.length).toEqual(3);
|
|
55
|
+
} finally {
|
|
56
|
+
// delete the stack
|
|
57
|
+
await fixture.cdk(['destroy', stackName], {
|
|
58
|
+
captureStderr: false,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
integTest(
|
|
65
|
+
'security related changes without a CLI are expected to fail when approval is required',
|
|
66
|
+
withCliLibFixture(async (fixture) => {
|
|
67
|
+
const stdErr = await fixture.cdk(['deploy', fixture.fullStackName('simple-1')], {
|
|
68
|
+
onlyStderr: true,
|
|
69
|
+
captureStderr: true,
|
|
70
|
+
allowErrExit: true,
|
|
71
|
+
neverRequireApproval: false,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(stdErr).toContain(
|
|
75
|
+
'This deployment will make potentially sensitive changes according to your current security approval level',
|
|
76
|
+
);
|
|
77
|
+
expect(stdErr).toContain(
|
|
78
|
+
'"--require-approval" is enabled and stack includes security-sensitive updates',
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Ensure stack was not deployed
|
|
82
|
+
await expect(
|
|
83
|
+
fixture.aws.cloudFormation.send(
|
|
84
|
+
new DescribeStacksCommand({
|
|
85
|
+
StackName: fixture.fullStackName('simple-1'),
|
|
86
|
+
}),
|
|
87
|
+
),
|
|
88
|
+
).rejects.toThrow('does not exist');
|
|
89
|
+
}),
|
|
90
|
+
);
|