aws-cdk 2.14.0 → 2.15.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/README.md +2 -1
- package/build-info.json +2 -2
- package/does-not-exist.json +1 -0
- package/lib/api/cloudformation-deployments.d.ts +1 -6
- package/lib/api/cloudformation-deployments.js +6 -72
- package/lib/api/evaluate-cloudformation-template.d.ts +9 -2
- package/lib/api/evaluate-cloudformation-template.js +14 -2
- package/lib/api/hotswap-deployments.js +34 -7
- package/lib/api/logs/find-cloudwatch-logs.js +2 -2
- package/lib/api/nested-stack-helpers.d.ts +28 -0
- package/lib/api/nested-stack-helpers.js +97 -0
- package/lib/cli.js +2 -2
- package/lib/index.js +1139 -389
- package/lib/notices.js +16 -7
- package/package.json +9 -9
- package/test/api/hotswap/hotswap-deployments.test.js +38 -2
- package/test/api/hotswap/hotswap-test-setup.d.ts +6 -4
- package/test/api/hotswap/hotswap-test-setup.js +46 -6
- package/test/api/hotswap/nested-stacks-hotswap.test.d.ts +1 -0
- package/test/api/hotswap/nested-stacks-hotswap.test.js +840 -0
- package/test/api/hotswap/state-machine-hotswap-deployments.test.js +2 -2
- package/test/integ/cli/cli.integtest.js +2 -2
- package/test/nested-stack-templates/one-lambda-one-stack-stack-with-asset-parameters.nested.template.json +52 -0
- package/test/nested-stack-templates/one-lambda-one-stack-stack.nested.template.json +26 -0
- package/test/nested-stack-templates/one-lambda-stack-with-asset-parameters.nested.template.json +29 -0
- package/test/nested-stack-templates/one-lambda-stack.nested.template.json +17 -0
- package/test/nested-stack-templates/one-lambda-version-stack.nested.template.json +20 -0
- package/test/{diff-nested-stacks-templates → nested-stack-templates}/one-output-one-param-stack.nested.template.json +0 -0
- package/test/{diff-nested-stacks-templates → nested-stack-templates}/one-resource-one-stack-stack.nested.template.json +0 -0
- package/test/{diff-nested-stacks-templates → nested-stack-templates}/one-resource-stack.nested.template.json +0 -0
- package/test/{diff-nested-stacks-templates → nested-stack-templates}/one-resource-two-stacks-stack.nested.template.json +0 -0
- package/test/nested-stack-templates/one-unnamed-lambda-stack.nested.template.json +16 -0
- package/test/nested-stack-templates/one-unnamed-lambda-two-stacks-stack.nested.template.json +34 -0
- package/test/notices.test.js +26 -3
- package/test/util.js +2 -2
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const util_1 = require("../../util");
|
|
4
|
+
const setup = require("./hotswap-test-setup");
|
|
5
|
+
let mockUpdateLambdaCode;
|
|
6
|
+
let mockPublishVersion;
|
|
7
|
+
let hotswapMockSdkProvider;
|
|
8
|
+
test('can hotswap a lambda function in a 1-level nested stack', async () => {
|
|
9
|
+
// GIVEN
|
|
10
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('LambdaRoot');
|
|
11
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
12
|
+
hotswapMockSdkProvider.stubLambda({
|
|
13
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
14
|
+
});
|
|
15
|
+
const rootStack = util_1.testStack({
|
|
16
|
+
stackName: 'LambdaRoot',
|
|
17
|
+
template: {
|
|
18
|
+
Resources: {
|
|
19
|
+
NestedStack: {
|
|
20
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
21
|
+
Properties: {
|
|
22
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
23
|
+
},
|
|
24
|
+
Metadata: {
|
|
25
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
32
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
33
|
+
stackName: 'NestedStack',
|
|
34
|
+
template: {
|
|
35
|
+
Resources: {
|
|
36
|
+
Func: {
|
|
37
|
+
Type: 'AWS::Lambda::Function',
|
|
38
|
+
Properties: {
|
|
39
|
+
Code: {
|
|
40
|
+
S3Bucket: 'current-bucket',
|
|
41
|
+
S3Key: 'current-key',
|
|
42
|
+
},
|
|
43
|
+
FunctionName: 'my-function',
|
|
44
|
+
},
|
|
45
|
+
Metadata: {
|
|
46
|
+
'aws:asset:path': 'old-path',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}));
|
|
52
|
+
setup.pushNestedStackResourceSummaries('LambdaRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
53
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'LambdaRoot', template: rootStack.template });
|
|
54
|
+
// WHEN
|
|
55
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
56
|
+
// THEN
|
|
57
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
58
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
59
|
+
FunctionName: 'my-function',
|
|
60
|
+
S3Bucket: 'current-bucket',
|
|
61
|
+
S3Key: 'new-key',
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
test('hotswappable changes do not override hotswappable changes in their ancestors', async () => {
|
|
65
|
+
// GIVEN
|
|
66
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('TwoLevelLambdaRoot');
|
|
67
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
68
|
+
hotswapMockSdkProvider.stubLambda({
|
|
69
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
70
|
+
});
|
|
71
|
+
const rootStack = util_1.testStack({
|
|
72
|
+
stackName: 'TwoLevelLambdaRoot',
|
|
73
|
+
template: {
|
|
74
|
+
Resources: {
|
|
75
|
+
ChildStack: {
|
|
76
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
77
|
+
Properties: {
|
|
78
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
79
|
+
},
|
|
80
|
+
Metadata: {
|
|
81
|
+
'aws:asset:path': 'one-lambda-one-stack-stack.nested.template.json',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
88
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
89
|
+
stackName: 'ChildStack',
|
|
90
|
+
template: {
|
|
91
|
+
Resources: {
|
|
92
|
+
Func: {
|
|
93
|
+
Type: 'AWS::Lambda::Function',
|
|
94
|
+
Properties: {
|
|
95
|
+
Code: {
|
|
96
|
+
S3Bucket: 'current-bucket',
|
|
97
|
+
S3Key: 'current-key',
|
|
98
|
+
},
|
|
99
|
+
FunctionName: 'child-function',
|
|
100
|
+
},
|
|
101
|
+
Metadata: {
|
|
102
|
+
'aws:asset:path': 'old-path',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
GrandChildStack: {
|
|
106
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
107
|
+
Properties: {
|
|
108
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
109
|
+
},
|
|
110
|
+
Metadata: {
|
|
111
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
}));
|
|
117
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
118
|
+
stackName: 'GrandChildStack',
|
|
119
|
+
template: {
|
|
120
|
+
Resources: {
|
|
121
|
+
Func: {
|
|
122
|
+
Type: 'AWS::Lambda::Function',
|
|
123
|
+
Properties: {
|
|
124
|
+
Code: {
|
|
125
|
+
S3Bucket: 'current-bucket',
|
|
126
|
+
S3Key: 'current-key',
|
|
127
|
+
},
|
|
128
|
+
FunctionName: 'my-function',
|
|
129
|
+
},
|
|
130
|
+
Metadata: {
|
|
131
|
+
'aws:asset:path': 'old-path',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
setup.pushNestedStackResourceSummaries('TwoLevelLambdaRoot', setup.stackSummaryOf('ChildStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/ChildStack/abcd'));
|
|
138
|
+
setup.pushNestedStackResourceSummaries('ChildStack', setup.stackSummaryOf('GrandChildStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/GrandChildStack/abcd'));
|
|
139
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'TwoLevelLambdaRoot', template: rootStack.template });
|
|
140
|
+
// WHEN
|
|
141
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
142
|
+
// THEN
|
|
143
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
144
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
145
|
+
FunctionName: 'child-function',
|
|
146
|
+
S3Bucket: 'new-bucket',
|
|
147
|
+
S3Key: 'current-key',
|
|
148
|
+
});
|
|
149
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
150
|
+
FunctionName: 'my-function',
|
|
151
|
+
S3Bucket: 'current-bucket',
|
|
152
|
+
S3Key: 'new-key',
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
test('hotswappable changes in nested stacks do not override hotswappable changes in their parent stack', async () => {
|
|
156
|
+
// GIVEN
|
|
157
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('SiblingLambdaRoot');
|
|
158
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
159
|
+
hotswapMockSdkProvider.stubLambda({
|
|
160
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
161
|
+
});
|
|
162
|
+
const rootStack = util_1.testStack({
|
|
163
|
+
stackName: 'SiblingLambdaRoot',
|
|
164
|
+
template: {
|
|
165
|
+
Resources: {
|
|
166
|
+
NestedStack: {
|
|
167
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
168
|
+
Properties: {
|
|
169
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
170
|
+
},
|
|
171
|
+
Metadata: {
|
|
172
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
Func: {
|
|
176
|
+
Type: 'AWS::Lambda::Function',
|
|
177
|
+
Properties: {
|
|
178
|
+
Code: {
|
|
179
|
+
S3Bucket: 'current-bucket',
|
|
180
|
+
S3Key: 'current-key',
|
|
181
|
+
},
|
|
182
|
+
FunctionName: 'root-function',
|
|
183
|
+
},
|
|
184
|
+
Metadata: {
|
|
185
|
+
'aws:asset:path': 'old-path',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
192
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
193
|
+
stackName: 'NestedStack',
|
|
194
|
+
template: {
|
|
195
|
+
Resources: {
|
|
196
|
+
Func: {
|
|
197
|
+
Type: 'AWS::Lambda::Function',
|
|
198
|
+
Properties: {
|
|
199
|
+
Code: {
|
|
200
|
+
S3Bucket: 'current-bucket',
|
|
201
|
+
S3Key: 'current-key',
|
|
202
|
+
},
|
|
203
|
+
FunctionName: 'my-function',
|
|
204
|
+
},
|
|
205
|
+
Metadata: {
|
|
206
|
+
'aws:asset:path': 'old-path',
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
}));
|
|
212
|
+
setup.pushNestedStackResourceSummaries('SiblingLambdaRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
213
|
+
rootStack.template.Resources.Func.Properties.Code.S3Bucket = 'new-bucket';
|
|
214
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'SiblingLambdaRoot', template: rootStack.template });
|
|
215
|
+
// WHEN
|
|
216
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
217
|
+
// THEN
|
|
218
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
219
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
220
|
+
FunctionName: 'root-function',
|
|
221
|
+
S3Bucket: 'new-bucket',
|
|
222
|
+
S3Key: 'current-key',
|
|
223
|
+
});
|
|
224
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
225
|
+
FunctionName: 'my-function',
|
|
226
|
+
S3Bucket: 'current-bucket',
|
|
227
|
+
S3Key: 'new-key',
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
test('non-hotswappable changes in nested stacks result in a full deployment, even if their parent contains a hotswappable change', async () => {
|
|
231
|
+
// GIVEN
|
|
232
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('NonHotswappableRoot');
|
|
233
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
234
|
+
hotswapMockSdkProvider.stubLambda({
|
|
235
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
236
|
+
});
|
|
237
|
+
const rootStack = util_1.testStack({
|
|
238
|
+
stackName: 'NonHotswappableRoot',
|
|
239
|
+
template: {
|
|
240
|
+
Resources: {
|
|
241
|
+
NestedStack: {
|
|
242
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
243
|
+
Properties: {
|
|
244
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
245
|
+
},
|
|
246
|
+
Metadata: {
|
|
247
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
Func: {
|
|
251
|
+
Type: 'AWS::Lambda::Function',
|
|
252
|
+
Properties: {
|
|
253
|
+
Code: {
|
|
254
|
+
S3Bucket: 'current-bucket',
|
|
255
|
+
S3Key: 'current-key',
|
|
256
|
+
},
|
|
257
|
+
FunctionName: 'root-function',
|
|
258
|
+
},
|
|
259
|
+
Metadata: {
|
|
260
|
+
'aws:asset:path': 'old-path',
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
267
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
268
|
+
stackName: 'NestedStack',
|
|
269
|
+
template: {
|
|
270
|
+
Resources: {
|
|
271
|
+
Func: {
|
|
272
|
+
Type: 'AWS::Lambda::Function',
|
|
273
|
+
Properties: {
|
|
274
|
+
Code: {
|
|
275
|
+
S3Bucket: 'current-bucket',
|
|
276
|
+
S3Key: 'current-key',
|
|
277
|
+
},
|
|
278
|
+
PackageType: 'Image',
|
|
279
|
+
FunctionName: 'my-function',
|
|
280
|
+
},
|
|
281
|
+
Metadata: {
|
|
282
|
+
'aws:asset:path': 'old-path',
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
}));
|
|
288
|
+
setup.pushNestedStackResourceSummaries('NonHotswappableRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
289
|
+
rootStack.template.Resources.Func.Properties.Code.S3Bucket = 'new-bucket';
|
|
290
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'NonHotswappableRoot', template: rootStack.template });
|
|
291
|
+
// WHEN
|
|
292
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
293
|
+
// THEN
|
|
294
|
+
expect(deployStackResult).toBeUndefined();
|
|
295
|
+
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
|
|
296
|
+
});
|
|
297
|
+
test('deleting a nested stack results in a full deployment, even if their parent contains a hotswappable change', async () => {
|
|
298
|
+
// GIVEN
|
|
299
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('NestedStackDeletionRoot');
|
|
300
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
301
|
+
hotswapMockSdkProvider.stubLambda({
|
|
302
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
303
|
+
});
|
|
304
|
+
const rootStack = util_1.testStack({
|
|
305
|
+
stackName: 'NestedStackDeletionRoot',
|
|
306
|
+
template: {
|
|
307
|
+
Resources: {
|
|
308
|
+
NestedStack: {
|
|
309
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
310
|
+
Properties: {
|
|
311
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
312
|
+
},
|
|
313
|
+
Metadata: {
|
|
314
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
Func: {
|
|
318
|
+
Type: 'AWS::Lambda::Function',
|
|
319
|
+
Properties: {
|
|
320
|
+
Code: {
|
|
321
|
+
S3Bucket: 'current-bucket',
|
|
322
|
+
S3Key: 'current-key',
|
|
323
|
+
},
|
|
324
|
+
FunctionName: 'root-function',
|
|
325
|
+
},
|
|
326
|
+
Metadata: {
|
|
327
|
+
'aws:asset:path': 'old-path',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
334
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
335
|
+
stackName: 'NestedStack',
|
|
336
|
+
template: {
|
|
337
|
+
Resources: {
|
|
338
|
+
Func: {
|
|
339
|
+
Type: 'AWS::Lambda::Function',
|
|
340
|
+
Properties: {
|
|
341
|
+
Code: {
|
|
342
|
+
S3Bucket: 'current-bucket',
|
|
343
|
+
S3Key: 'current-key',
|
|
344
|
+
},
|
|
345
|
+
FunctionName: 'my-function',
|
|
346
|
+
},
|
|
347
|
+
Metadata: {
|
|
348
|
+
'aws:asset:path': 'old-path',
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
}));
|
|
354
|
+
setup.pushNestedStackResourceSummaries('NestedStackDeletionRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
355
|
+
rootStack.template.Resources.Func.Properties.Code.S3Bucket = 'new-bucket';
|
|
356
|
+
delete rootStack.template.Resources.NestedStack;
|
|
357
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'NestedStackDeletionRoot', template: rootStack.template });
|
|
358
|
+
// WHEN
|
|
359
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
360
|
+
// THEN
|
|
361
|
+
expect(deployStackResult).toBeUndefined();
|
|
362
|
+
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
|
|
363
|
+
});
|
|
364
|
+
test('creating a nested stack results in a full deployment, even if their parent contains a hotswappable change', async () => {
|
|
365
|
+
// GIVEN
|
|
366
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('NestedStackCreationRoot');
|
|
367
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
368
|
+
hotswapMockSdkProvider.stubLambda({
|
|
369
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
370
|
+
});
|
|
371
|
+
const rootStack = util_1.testStack({
|
|
372
|
+
stackName: 'NestedStackCreationRoot',
|
|
373
|
+
template: {
|
|
374
|
+
Resources: {
|
|
375
|
+
Func: {
|
|
376
|
+
Type: 'AWS::Lambda::Function',
|
|
377
|
+
Properties: {
|
|
378
|
+
Code: {
|
|
379
|
+
S3Bucket: 'current-bucket',
|
|
380
|
+
S3Key: 'current-key',
|
|
381
|
+
},
|
|
382
|
+
FunctionName: 'root-function',
|
|
383
|
+
},
|
|
384
|
+
Metadata: {
|
|
385
|
+
'aws:asset:path': 'old-path',
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
392
|
+
rootStack.template.Resources.Func.Properties.Code.S3Bucket = 'new-bucket';
|
|
393
|
+
rootStack.template.Resources.NestedStack = {
|
|
394
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
395
|
+
Properties: {
|
|
396
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
397
|
+
},
|
|
398
|
+
Metadata: {
|
|
399
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'NestedStackCreationRoot', template: rootStack.template });
|
|
403
|
+
// WHEN
|
|
404
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
405
|
+
// THEN
|
|
406
|
+
expect(deployStackResult).toBeUndefined();
|
|
407
|
+
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
|
|
408
|
+
});
|
|
409
|
+
test('attempting to hotswap a newly created nested stack with the same logical ID as a resource with a different type results in a full deployment', async () => {
|
|
410
|
+
// GIVEN
|
|
411
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('NestedStackTypeChangeRoot');
|
|
412
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
413
|
+
hotswapMockSdkProvider.stubLambda({
|
|
414
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
415
|
+
});
|
|
416
|
+
const rootStack = util_1.testStack({
|
|
417
|
+
stackName: 'NestedStackTypeChangeRoot',
|
|
418
|
+
template: {
|
|
419
|
+
Resources: {
|
|
420
|
+
Func: {
|
|
421
|
+
Type: 'AWS::Lambda::Function',
|
|
422
|
+
Properties: {
|
|
423
|
+
Code: {
|
|
424
|
+
S3Bucket: 'current-bucket',
|
|
425
|
+
S3Key: 'current-key',
|
|
426
|
+
},
|
|
427
|
+
FunctionName: 'root-function',
|
|
428
|
+
},
|
|
429
|
+
Metadata: {
|
|
430
|
+
'aws:asset:path': 'old-path',
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
FutureNestedStack: {
|
|
434
|
+
Type: 'AWS::Lambda::Function',
|
|
435
|
+
Properties: {
|
|
436
|
+
Code: {
|
|
437
|
+
S3Bucket: 'current-bucket',
|
|
438
|
+
S3Key: 'new-key',
|
|
439
|
+
},
|
|
440
|
+
FunctionName: 'spooky-function',
|
|
441
|
+
},
|
|
442
|
+
Metadata: {
|
|
443
|
+
'aws:asset:path': 'old-path',
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
450
|
+
rootStack.template.Resources.Func.Properties.Code.S3Bucket = 'new-bucket';
|
|
451
|
+
rootStack.template.Resources.FutureNestedStack = {
|
|
452
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
453
|
+
Properties: {
|
|
454
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
455
|
+
},
|
|
456
|
+
Metadata: {
|
|
457
|
+
'aws:asset:path': 'one-lambda-stack.nested.template.json',
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'NestedStackTypeChangeRoot', template: rootStack.template });
|
|
461
|
+
// WHEN
|
|
462
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
463
|
+
// THEN
|
|
464
|
+
expect(deployStackResult).toBeUndefined();
|
|
465
|
+
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
|
|
466
|
+
});
|
|
467
|
+
test('multi-sibling + 3-layer nested stack structure is hotswappable', async () => {
|
|
468
|
+
// GIVEN
|
|
469
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('MultiLayerRoot');
|
|
470
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
471
|
+
hotswapMockSdkProvider.stubLambda({
|
|
472
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
473
|
+
});
|
|
474
|
+
const lambdaFunctionResource = {
|
|
475
|
+
Type: 'AWS::Lambda::Function',
|
|
476
|
+
Properties: {
|
|
477
|
+
Code: {
|
|
478
|
+
S3Bucket: 'current-bucket',
|
|
479
|
+
S3Key: 'current-key',
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
Metadata: {
|
|
483
|
+
'aws:asset:path': 'old-path',
|
|
484
|
+
},
|
|
485
|
+
};
|
|
486
|
+
const rootStack = util_1.testStack({
|
|
487
|
+
stackName: 'MultiLayerRoot',
|
|
488
|
+
template: {
|
|
489
|
+
Resources: {
|
|
490
|
+
ChildStack: {
|
|
491
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
492
|
+
Properties: {
|
|
493
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
494
|
+
},
|
|
495
|
+
Metadata: {
|
|
496
|
+
'aws:asset:path': 'one-unnamed-lambda-two-stacks-stack.nested.template.json',
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
Func: lambdaFunctionResource,
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
504
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
505
|
+
stackName: 'ChildStack',
|
|
506
|
+
template: {
|
|
507
|
+
Resources: {
|
|
508
|
+
GrandChildStackA: {
|
|
509
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
510
|
+
Properties: {
|
|
511
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
512
|
+
},
|
|
513
|
+
Metadata: {
|
|
514
|
+
'aws:asset:path': 'one-unnamed-lambda-stack.nested.template.json',
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
GrandChildStackB: {
|
|
518
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
519
|
+
Properties: {
|
|
520
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
521
|
+
},
|
|
522
|
+
Metadata: {
|
|
523
|
+
'aws:asset:path': 'one-unnamed-lambda-stack.nested.template.json',
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
Func: lambdaFunctionResource,
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
}));
|
|
530
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
531
|
+
stackName: 'GrandChildStackA',
|
|
532
|
+
template: {
|
|
533
|
+
Resources: {
|
|
534
|
+
Func: lambdaFunctionResource,
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
}));
|
|
538
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
539
|
+
stackName: 'GrandChildStackB',
|
|
540
|
+
template: {
|
|
541
|
+
Resources: {
|
|
542
|
+
Func: lambdaFunctionResource,
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
}));
|
|
546
|
+
setup.pushNestedStackResourceSummaries('MultiLayerRoot', setup.stackSummaryOf('ChildStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/ChildStack/abcd'), setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'root-function'));
|
|
547
|
+
setup.pushNestedStackResourceSummaries('ChildStack', setup.stackSummaryOf('GrandChildStackA', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/GrandChildStackA/abcd'), setup.stackSummaryOf('GrandChildStackB', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/GrandChildStackB/abcd'), setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'child-function'));
|
|
548
|
+
setup.pushNestedStackResourceSummaries('GrandChildStackA', setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'grandchild-A-function'));
|
|
549
|
+
setup.pushNestedStackResourceSummaries('GrandChildStackB', setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'grandchild-B-function'));
|
|
550
|
+
rootStack.template.Resources.Func.Properties.Code.S3Key = 'new-key';
|
|
551
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'MultiLayerRoot', template: rootStack.template });
|
|
552
|
+
// WHEN
|
|
553
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
554
|
+
// THEN
|
|
555
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
556
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
557
|
+
FunctionName: 'root-function',
|
|
558
|
+
S3Bucket: 'current-bucket',
|
|
559
|
+
S3Key: 'new-key',
|
|
560
|
+
});
|
|
561
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
562
|
+
FunctionName: 'child-function',
|
|
563
|
+
S3Bucket: 'current-bucket',
|
|
564
|
+
S3Key: 'new-key',
|
|
565
|
+
});
|
|
566
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
567
|
+
FunctionName: 'grandchild-A-function',
|
|
568
|
+
S3Bucket: 'current-bucket',
|
|
569
|
+
S3Key: 'new-key',
|
|
570
|
+
});
|
|
571
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
572
|
+
FunctionName: 'grandchild-B-function',
|
|
573
|
+
S3Bucket: 'current-bucket',
|
|
574
|
+
S3Key: 'new-key',
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
test('can hotswap a lambda function in a 1-level nested stack with asset parameters', async () => {
|
|
578
|
+
// GIVEN
|
|
579
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('LambdaRoot');
|
|
580
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
581
|
+
hotswapMockSdkProvider.stubLambda({
|
|
582
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
583
|
+
});
|
|
584
|
+
const rootStack = util_1.testStack({
|
|
585
|
+
stackName: 'LambdaRoot',
|
|
586
|
+
template: {
|
|
587
|
+
Resources: {
|
|
588
|
+
NestedStack: {
|
|
589
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
590
|
+
Properties: {
|
|
591
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
592
|
+
Parameters: {
|
|
593
|
+
referencetoS3BucketParam: {
|
|
594
|
+
Ref: 'S3BucketParam',
|
|
595
|
+
},
|
|
596
|
+
referencetoS3KeyParam: {
|
|
597
|
+
Ref: 'S3KeyParam',
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
Metadata: {
|
|
602
|
+
'aws:asset:path': 'one-lambda-stack-with-asset-parameters.nested.template.json',
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
Parameters: {
|
|
607
|
+
S3BucketParam: {
|
|
608
|
+
Type: 'String',
|
|
609
|
+
Description: 'S3 bucket for asset',
|
|
610
|
+
},
|
|
611
|
+
S3KeyParam: {
|
|
612
|
+
Type: 'String',
|
|
613
|
+
Description: 'S3 bucket for asset',
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
});
|
|
618
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
619
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
620
|
+
stackName: 'NestedStack',
|
|
621
|
+
template: {
|
|
622
|
+
Resources: {
|
|
623
|
+
Func: {
|
|
624
|
+
Type: 'AWS::Lambda::Function',
|
|
625
|
+
Properties: {
|
|
626
|
+
Code: {
|
|
627
|
+
S3Bucket: 'current-bucket',
|
|
628
|
+
S3Key: 'current-key',
|
|
629
|
+
},
|
|
630
|
+
FunctionName: 'my-function',
|
|
631
|
+
},
|
|
632
|
+
Metadata: {
|
|
633
|
+
'aws:asset:path': 'old-path',
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
},
|
|
638
|
+
}));
|
|
639
|
+
setup.pushNestedStackResourceSummaries('LambdaRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
640
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'LambdaRoot', template: rootStack.template });
|
|
641
|
+
// WHEN
|
|
642
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact, {
|
|
643
|
+
S3BucketParam: 'bucket-param-value',
|
|
644
|
+
S3KeyParam: 'key-param-value',
|
|
645
|
+
});
|
|
646
|
+
// THEN
|
|
647
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
648
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
649
|
+
FunctionName: 'my-function',
|
|
650
|
+
S3Bucket: 'bucket-param-value',
|
|
651
|
+
S3Key: 'key-param-value',
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
test('can hotswap a lambda function in a 2-level nested stack with asset parameters', async () => {
|
|
655
|
+
// GIVEN
|
|
656
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('LambdaRoot');
|
|
657
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
658
|
+
hotswapMockSdkProvider.stubLambda({
|
|
659
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
660
|
+
});
|
|
661
|
+
const rootStack = util_1.testStack({
|
|
662
|
+
stackName: 'LambdaRoot',
|
|
663
|
+
template: {
|
|
664
|
+
Resources: {
|
|
665
|
+
ChildStack: {
|
|
666
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
667
|
+
Properties: {
|
|
668
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
669
|
+
Parameters: {
|
|
670
|
+
referencetoGrandChildS3BucketParam: {
|
|
671
|
+
Ref: 'GrandChildS3BucketParam',
|
|
672
|
+
},
|
|
673
|
+
referencetoGrandChildS3KeyParam: {
|
|
674
|
+
Ref: 'GrandChildS3KeyParam',
|
|
675
|
+
},
|
|
676
|
+
referencetoChildS3BucketParam: {
|
|
677
|
+
Ref: 'ChildS3BucketParam',
|
|
678
|
+
},
|
|
679
|
+
referencetoChildS3KeyParam: {
|
|
680
|
+
Ref: 'ChildS3KeyParam',
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
Metadata: {
|
|
685
|
+
'aws:asset:path': 'one-lambda-one-stack-stack-with-asset-parameters.nested.template.json',
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
Parameters: {
|
|
690
|
+
GrandChildS3BucketParam: {
|
|
691
|
+
Type: 'String',
|
|
692
|
+
Description: 'S3 bucket for asset',
|
|
693
|
+
},
|
|
694
|
+
GrandChildS3KeyParam: {
|
|
695
|
+
Type: 'String',
|
|
696
|
+
Description: 'S3 bucket for asset',
|
|
697
|
+
},
|
|
698
|
+
ChildS3BucketParam: {
|
|
699
|
+
Type: 'String',
|
|
700
|
+
Description: 'S3 bucket for asset',
|
|
701
|
+
},
|
|
702
|
+
ChildS3KeyParam: {
|
|
703
|
+
Type: 'String',
|
|
704
|
+
Description: 'S3 bucket for asset',
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
710
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
711
|
+
stackName: 'ChildStack',
|
|
712
|
+
template: {
|
|
713
|
+
Resources: {
|
|
714
|
+
Func: {
|
|
715
|
+
Type: 'AWS::Lambda::Function',
|
|
716
|
+
Properties: {
|
|
717
|
+
Code: {
|
|
718
|
+
S3Bucket: 'current-bucket',
|
|
719
|
+
S3Key: 'current-key',
|
|
720
|
+
},
|
|
721
|
+
FunctionName: 'my-function',
|
|
722
|
+
},
|
|
723
|
+
Metadata: {
|
|
724
|
+
'aws:asset:path': 'old-path',
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
GrandChildStack: {
|
|
728
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
729
|
+
Properties: {
|
|
730
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
731
|
+
},
|
|
732
|
+
Metadata: {
|
|
733
|
+
'aws:asset:path': 'one-lambda-stack-with-asset-parameters.nested.template.json',
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
}));
|
|
739
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
740
|
+
stackName: 'GrandChildStack',
|
|
741
|
+
template: {
|
|
742
|
+
Resources: {
|
|
743
|
+
Func: {
|
|
744
|
+
Type: 'AWS::Lambda::Function',
|
|
745
|
+
Properties: {
|
|
746
|
+
Code: {
|
|
747
|
+
S3Bucket: 'current-bucket',
|
|
748
|
+
S3Key: 'current-key',
|
|
749
|
+
},
|
|
750
|
+
FunctionName: 'my-function',
|
|
751
|
+
},
|
|
752
|
+
Metadata: {
|
|
753
|
+
'aws:asset:path': 'old-path',
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
},
|
|
758
|
+
}));
|
|
759
|
+
setup.pushNestedStackResourceSummaries('LambdaRoot', setup.stackSummaryOf('ChildStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/ChildStack/abcd'));
|
|
760
|
+
setup.pushNestedStackResourceSummaries('ChildStack', setup.stackSummaryOf('GrandChildStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/GrandChildStack/abcd'));
|
|
761
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'LambdaRoot', template: rootStack.template });
|
|
762
|
+
// WHEN
|
|
763
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact, {
|
|
764
|
+
GrandChildS3BucketParam: 'child-bucket-param-value',
|
|
765
|
+
GrandChildS3KeyParam: 'child-key-param-value',
|
|
766
|
+
ChildS3BucketParam: 'bucket-param-value',
|
|
767
|
+
ChildS3KeyParam: 'key-param-value',
|
|
768
|
+
});
|
|
769
|
+
// THEN
|
|
770
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
771
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
772
|
+
FunctionName: 'my-function',
|
|
773
|
+
S3Bucket: 'bucket-param-value',
|
|
774
|
+
S3Key: 'key-param-value',
|
|
775
|
+
});
|
|
776
|
+
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
|
|
777
|
+
FunctionName: 'my-function',
|
|
778
|
+
S3Bucket: 'child-bucket-param-value',
|
|
779
|
+
S3Key: 'child-key-param-value',
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
test('looking up objects in nested stacks works', async () => {
|
|
783
|
+
hotswapMockSdkProvider = setup.setupHotswapNestedStackTests('LambdaRoot');
|
|
784
|
+
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
|
|
785
|
+
mockPublishVersion = jest.fn();
|
|
786
|
+
hotswapMockSdkProvider.stubLambda({
|
|
787
|
+
updateFunctionCode: mockUpdateLambdaCode,
|
|
788
|
+
publishVersion: mockPublishVersion,
|
|
789
|
+
});
|
|
790
|
+
const rootStack = util_1.testStack({
|
|
791
|
+
stackName: 'LambdaRoot',
|
|
792
|
+
template: {
|
|
793
|
+
Resources: {
|
|
794
|
+
NestedStack: {
|
|
795
|
+
Type: 'AWS::CloudFormation::Stack',
|
|
796
|
+
Properties: {
|
|
797
|
+
TemplateURL: 'https://www.magic-url.com',
|
|
798
|
+
},
|
|
799
|
+
Metadata: {
|
|
800
|
+
'aws:asset:path': 'one-lambda-version-stack.nested.template.json',
|
|
801
|
+
},
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
},
|
|
805
|
+
});
|
|
806
|
+
setup.addTemplateToCloudFormationLookupMock(rootStack);
|
|
807
|
+
setup.addTemplateToCloudFormationLookupMock(util_1.testStack({
|
|
808
|
+
stackName: 'NestedStack',
|
|
809
|
+
template: {
|
|
810
|
+
Resources: {
|
|
811
|
+
Func: {
|
|
812
|
+
Type: 'AWS::Lambda::Function',
|
|
813
|
+
Properties: {
|
|
814
|
+
Code: {
|
|
815
|
+
S3Bucket: 'current-bucket',
|
|
816
|
+
S3Key: 'current-key',
|
|
817
|
+
},
|
|
818
|
+
FunctionName: 'my-function',
|
|
819
|
+
},
|
|
820
|
+
},
|
|
821
|
+
Version: {
|
|
822
|
+
Type: 'AWS::Lambda::Version',
|
|
823
|
+
Properties: {
|
|
824
|
+
FunctionName: { Ref: 'Func' },
|
|
825
|
+
},
|
|
826
|
+
},
|
|
827
|
+
},
|
|
828
|
+
},
|
|
829
|
+
}));
|
|
830
|
+
setup.pushNestedStackResourceSummaries('LambdaRoot', setup.stackSummaryOf('NestedStack', 'AWS::CloudFormation::Stack', 'arn:aws:cloudformation:bermuda-triangle-1337:123456789012:stack/NestedStack/abcd'));
|
|
831
|
+
const cdkStackArtifact = util_1.testStack({ stackName: 'LambdaRoot', template: rootStack.template });
|
|
832
|
+
// WHEN
|
|
833
|
+
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
|
|
834
|
+
// THEN
|
|
835
|
+
expect(deployStackResult).not.toBeUndefined();
|
|
836
|
+
expect(mockPublishVersion).toHaveBeenCalledWith({
|
|
837
|
+
FunctionName: 'my-function',
|
|
838
|
+
});
|
|
839
|
+
});
|
|
840
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVzdGVkLXN0YWNrcy1ob3Rzd2FwLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJuZXN0ZWQtc3RhY2tzLWhvdHN3YXAudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUNBLHFDQUF1QztBQUN2Qyw4Q0FBOEM7QUFFOUMsSUFBSSxvQkFBNEcsQ0FBQztBQUNqSCxJQUFJLGtCQUEyRixDQUFDO0FBQ2hHLElBQUksc0JBQW9ELENBQUM7QUFFekQsSUFBSSxDQUFDLHlEQUF5RCxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3pFLFFBQVE7SUFDUixzQkFBc0IsR0FBRyxLQUFLLENBQUMsNEJBQTRCLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUUsb0JBQW9CLEdBQUcsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRCxzQkFBc0IsQ0FBQyxVQUFVLENBQUM7UUFDaEMsa0JBQWtCLEVBQUUsb0JBQW9CO0tBQ3pDLENBQUMsQ0FBQztJQUVILE1BQU0sU0FBUyxHQUFHLGdCQUFTLENBQUM7UUFDMUIsU0FBUyxFQUFFLFlBQVk7UUFDdkIsUUFBUSxFQUFFO1lBQ1IsU0FBUyxFQUFFO2dCQUNULFdBQVcsRUFBRTtvQkFDWCxJQUFJLEVBQUUsNEJBQTRCO29CQUNsQyxVQUFVLEVBQUU7d0JBQ1YsV0FBVyxFQUFFLDJCQUEyQjtxQkFDekM7b0JBQ0QsUUFBUSxFQUFFO3dCQUNSLGdCQUFnQixFQUFFLHVDQUF1QztxQkFDMUQ7aUJBQ0Y7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZELEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxnQkFBUyxDQUFDO1FBQ3BELFNBQVMsRUFBRSxhQUFhO1FBQ3hCLFFBQVEsRUFBRTtZQUNSLFNBQVMsRUFBRTtnQkFDVCxJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLHVCQUF1QjtvQkFD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QUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM5QyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztRQUM5QyxZQUFZLEVBQUUsYUFBYTtLQUM1QixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExhbWJkYSB9IGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgdGVzdFN0YWNrIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgKiBhcyBzZXR1cCBmcm9tICcuL2hvdHN3YXAtdGVzdC1zZXR1cCc7XG5cbmxldCBtb2NrVXBkYXRlTGFtYmRhQ29kZTogKHBhcmFtczogTGFtYmRhLlR5cGVzLlVwZGF0ZUZ1bmN0aW9uQ29kZVJlcXVlc3QpID0+IExhbWJkYS5UeXBlcy5GdW5jdGlvbkNvbmZpZ3VyYXRpb247XG5sZXQgbW9ja1B1Ymxpc2hWZXJzaW9uOiBqZXN0Lk1vY2s8TGFtYmRhLkZ1bmN0aW9uQ29uZmlndXJhdGlvbiwgTGFtYmRhLlB1Ymxpc2hWZXJzaW9uUmVxdWVzdFtdPjtcbmxldCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyOiBzZXR1cC5Ib3Rzd2FwTW9ja1Nka1Byb3ZpZGVyO1xuXG50ZXN0KCdjYW4gaG90c3dhcCBhIGxhbWJkYSBmdW5jdGlvbiBpbiBhIDEtbGV2ZWwgbmVzdGVkIHN0YWNrJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnTGFtYmRhUm9vdCcpO1xuICBtb2NrVXBkYXRlTGFtYmRhQ29kZSA9IGplc3QuZm4oKS5tb2NrUmV0dXJuVmFsdWUoe30pO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnN0dWJMYW1iZGEoe1xuICAgIHVwZGF0ZUZ1bmN0aW9uQ29kZTogbW9ja1VwZGF0ZUxhbWJkYUNvZGUsXG4gIH0pO1xuXG4gIGNvbnN0IHJvb3RTdGFjayA9IHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTGFtYmRhUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBOZXN0ZWRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTmVzdGVkU3RhY2snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pKTtcblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnTGFtYmRhUm9vdCcsXG4gICAgc2V0dXAuc3RhY2tTdW1tYXJ5T2YoJ05lc3RlZFN0YWNrJywgJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICdhcm46YXdzOmNsb3VkZm9ybWF0aW9uOmJlcm11ZGEtdHJpYW5nbGUtMTMzNzoxMjM0NTY3ODkwMTI6c3RhY2svTmVzdGVkU3RhY2svYWJjZCcsXG4gICAgKSxcbiAgKTtcblxuICBjb25zdCBjZGtTdGFja0FydGlmYWN0ID0gdGVzdFN0YWNrKHsgc3RhY2tOYW1lOiAnTGFtYmRhUm9vdCcsIHRlbXBsYXRlOiByb290U3RhY2sudGVtcGxhdGUgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICBTM0tleTogJ25ldy1rZXknLFxuICB9KTtcbn0pO1xuXG50ZXN0KCdob3Rzd2FwcGFibGUgY2hhbmdlcyBkbyBub3Qgb3ZlcnJpZGUgaG90c3dhcHBhYmxlIGNoYW5nZXMgaW4gdGhlaXIgYW5jZXN0b3JzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnVHdvTGV2ZWxMYW1iZGFSb290Jyk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpLm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkxhbWJkYSh7XG4gICAgdXBkYXRlRnVuY3Rpb25Db2RlOiBtb2NrVXBkYXRlTGFtYmRhQ29kZSxcbiAgfSk7XG5cbiAgY29uc3Qgcm9vdFN0YWNrID0gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdUd29MZXZlbExhbWJkYVJvb3QnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgQ2hpbGRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1vbmUtc3RhY2stc3RhY2submVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIHNldHVwLmFkZFRlbXBsYXRlVG9DbG91ZEZvcm1hdGlvbkxvb2t1cE1vY2socm9vdFN0YWNrKTtcbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayh0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ0NoaWxkU3RhY2snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ2NoaWxkLWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIEdyYW5kQ2hpbGRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSkpO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnR3JhbmRDaGlsZFN0YWNrJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6ICdteS1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KSk7XG5cbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ1R3b0xldmVsTGFtYmRhUm9vdCcsXG4gICAgc2V0dXAuc3RhY2tTdW1tYXJ5T2YoJ0NoaWxkU3RhY2snLCAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgJ2Fybjphd3M6Y2xvdWRmb3JtYXRpb246YmVybXVkYS10cmlhbmdsZS0xMzM3OjEyMzQ1Njc4OTAxMjpzdGFjay9DaGlsZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG4gIHNldHVwLnB1c2hOZXN0ZWRTdGFja1Jlc291cmNlU3VtbWFyaWVzKCdDaGlsZFN0YWNrJyxcbiAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignR3JhbmRDaGlsZFN0YWNrJywgJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICdhcm46YXdzOmNsb3VkZm9ybWF0aW9uOmJlcm11ZGEtdHJpYW5nbGUtMTMzNzoxMjM0NTY3ODkwMTI6c3RhY2svR3JhbmRDaGlsZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ1R3b0xldmVsTGFtYmRhUm9vdCcsIHRlbXBsYXRlOiByb290U3RhY2sudGVtcGxhdGUgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgIEZ1bmN0aW9uTmFtZTogJ2NoaWxkLWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ25ldy1idWNrZXQnLFxuICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICB9KTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xufSk7XG5cbnRlc3QoJ2hvdHN3YXBwYWJsZSBjaGFuZ2VzIGluIG5lc3RlZCBzdGFja3MgZG8gbm90IG92ZXJyaWRlIGhvdHN3YXBwYWJsZSBjaGFuZ2VzIGluIHRoZWlyIHBhcmVudCBzdGFjaycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcE5lc3RlZFN0YWNrVGVzdHMoJ1NpYmxpbmdMYW1iZGFSb290Jyk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpLm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkxhbWJkYSh7XG4gICAgdXBkYXRlRnVuY3Rpb25Db2RlOiBtb2NrVXBkYXRlTGFtYmRhQ29kZSxcbiAgfSk7XG5cbiAgY29uc3Qgcm9vdFN0YWNrID0gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdTaWJsaW5nTGFtYmRhUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBOZXN0ZWRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ3Jvb3QtZnVuY3Rpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTmVzdGVkU3RhY2snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pKTtcblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnU2libGluZ0xhbWJkYVJvb3QnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdOZXN0ZWRTdGFjaycsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL05lc3RlZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgcm9vdFN0YWNrLnRlbXBsYXRlLlJlc291cmNlcy5GdW5jLlByb3BlcnRpZXMuQ29kZS5TM0J1Y2tldCA9ICduZXctYnVja2V0JztcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ1NpYmxpbmdMYW1iZGFSb290JywgdGVtcGxhdGU6IHJvb3RTdGFjay50ZW1wbGF0ZSB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IGRlcGxveVN0YWNrUmVzdWx0ID0gYXdhaXQgaG90c3dhcE1vY2tTZGtQcm92aWRlci50cnlIb3Rzd2FwRGVwbG95bWVudChjZGtTdGFja0FydGlmYWN0KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkubm90LnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAncm9vdC1mdW5jdGlvbicsXG4gICAgUzNCdWNrZXQ6ICduZXctYnVja2V0JyxcbiAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgfSk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICBTM0tleTogJ25ldy1rZXknLFxuICB9KTtcbn0pO1xuXG50ZXN0KCdub24taG90c3dhcHBhYmxlIGNoYW5nZXMgaW4gbmVzdGVkIHN0YWNrcyByZXN1bHQgaW4gYSBmdWxsIGRlcGxveW1lbnQsIGV2ZW4gaWYgdGhlaXIgcGFyZW50IGNvbnRhaW5zIGEgaG90c3dhcHBhYmxlIGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcE5lc3RlZFN0YWNrVGVzdHMoJ05vbkhvdHN3YXBwYWJsZVJvb3QnKTtcbiAgbW9ja1VwZGF0ZUxhbWJkYUNvZGUgPSBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KTtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlci5zdHViTGFtYmRhKHtcbiAgICB1cGRhdGVGdW5jdGlvbkNvZGU6IG1vY2tVcGRhdGVMYW1iZGFDb2RlLFxuICB9KTtcblxuICBjb25zdCByb290U3RhY2sgPSB0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ05vbkhvdHN3YXBwYWJsZVJvb3QnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgTmVzdGVkU3RhY2s6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly93d3cubWFnaWMtdXJsLmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29uZS1sYW1iZGEtc3RhY2submVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6ICdyb290LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIHNldHVwLmFkZFRlbXBsYXRlVG9DbG91ZEZvcm1hdGlvbkxvb2t1cE1vY2socm9vdFN0YWNrKTtcbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayh0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ05lc3RlZFN0YWNrJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBQYWNrYWdlVHlwZTogJ0ltYWdlJyxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pKTtcblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnTm9uSG90c3dhcHBhYmxlUm9vdCcsXG4gICAgc2V0dXAuc3RhY2tTdW1tYXJ5T2YoJ05lc3RlZFN0YWNrJywgJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICdhcm46YXdzOmNsb3VkZm9ybWF0aW9uOmJlcm11ZGEtdHJpYW5nbGUtMTMzNzoxMjM0NTY3ODkwMTI6c3RhY2svTmVzdGVkU3RhY2svYWJjZCcsXG4gICAgKSxcbiAgKTtcblxuICByb290U3RhY2sudGVtcGxhdGUuUmVzb3VyY2VzLkZ1bmMuUHJvcGVydGllcy5Db2RlLlMzQnVja2V0ID0gJ25ldy1idWNrZXQnO1xuICBjb25zdCBjZGtTdGFja0FydGlmYWN0ID0gdGVzdFN0YWNrKHsgc3RhY2tOYW1lOiAnTm9uSG90c3dhcHBhYmxlUm9vdCcsIHRlbXBsYXRlOiByb290U3RhY2sudGVtcGxhdGUgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2RlbGV0aW5nIGEgbmVzdGVkIHN0YWNrIHJlc3VsdHMgaW4gYSBmdWxsIGRlcGxveW1lbnQsIGV2ZW4gaWYgdGhlaXIgcGFyZW50IGNvbnRhaW5zIGEgaG90c3dhcHBhYmxlIGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcE5lc3RlZFN0YWNrVGVzdHMoJ05lc3RlZFN0YWNrRGVsZXRpb25Sb290Jyk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpLm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkxhbWJkYSh7XG4gICAgdXBkYXRlRnVuY3Rpb25Db2RlOiBtb2NrVXBkYXRlTGFtYmRhQ29kZSxcbiAgfSk7XG5cbiAgY29uc3Qgcm9vdFN0YWNrID0gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdOZXN0ZWRTdGFja0RlbGV0aW9uUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBOZXN0ZWRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ3Jvb3QtZnVuY3Rpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTmVzdGVkU3RhY2snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pKTtcblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnTmVzdGVkU3RhY2tEZWxldGlvblJvb3QnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdOZXN0ZWRTdGFjaycsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL05lc3RlZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgcm9vdFN0YWNrLnRlbXBsYXRlLlJlc291cmNlcy5GdW5jLlByb3BlcnRpZXMuQ29kZS5TM0J1Y2tldCA9ICduZXctYnVja2V0JztcbiAgZGVsZXRlIHJvb3RTdGFjay50ZW1wbGF0ZS5SZXNvdXJjZXMuTmVzdGVkU3RhY2s7XG4gIGNvbnN0IGNka1N0YWNrQXJ0aWZhY3QgPSB0ZXN0U3RhY2soeyBzdGFja05hbWU6ICdOZXN0ZWRTdGFja0RlbGV0aW9uUm9vdCcsIHRlbXBsYXRlOiByb290U3RhY2sudGVtcGxhdGUgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2NyZWF0aW5nIGEgbmVzdGVkIHN0YWNrIHJlc3VsdHMgaW4gYSBmdWxsIGRlcGxveW1lbnQsIGV2ZW4gaWYgdGhlaXIgcGFyZW50IGNvbnRhaW5zIGEgaG90c3dhcHBhYmxlIGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcE5lc3RlZFN0YWNrVGVzdHMoJ05lc3RlZFN0YWNrQ3JlYXRpb25Sb290Jyk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpLm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkxhbWJkYSh7XG4gICAgdXBkYXRlRnVuY3Rpb25Db2RlOiBtb2NrVXBkYXRlTGFtYmRhQ29kZSxcbiAgfSk7XG5cbiAgY29uc3Qgcm9vdFN0YWNrID0gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdOZXN0ZWRTdGFja0NyZWF0aW9uUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgICAgUzNLZXk6ICdjdXJyZW50LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgRnVuY3Rpb25OYW1lOiAncm9vdC1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcblxuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHJvb3RTdGFjayk7XG5cbiAgcm9vdFN0YWNrLnRlbXBsYXRlLlJlc291cmNlcy5GdW5jLlByb3BlcnRpZXMuQ29kZS5TM0J1Y2tldCA9ICduZXctYnVja2V0JztcbiAgcm9vdFN0YWNrLnRlbXBsYXRlLlJlc291cmNlcy5OZXN0ZWRTdGFjayA9IHtcbiAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgIFByb3BlcnRpZXM6IHtcbiAgICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly93d3cubWFnaWMtdXJsLmNvbScsXG4gICAgfSxcbiAgICBNZXRhZGF0YToge1xuICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29uZS1sYW1iZGEtc3RhY2submVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgIH0sXG4gIH07XG4gIGNvbnN0IGNka1N0YWNrQXJ0aWZhY3QgPSB0ZXN0U3RhY2soeyBzdGFja05hbWU6ICdOZXN0ZWRTdGFja0NyZWF0aW9uUm9vdCcsIHRlbXBsYXRlOiByb290U3RhY2sudGVtcGxhdGUgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2F0dGVtcHRpbmcgdG8gaG90c3dhcCBhIG5ld2x5IGNyZWF0ZWQgbmVzdGVkIHN0YWNrIHdpdGggdGhlIHNhbWUgbG9naWNhbCBJRCBhcyBhIHJlc291cmNlIHdpdGggYSBkaWZmZXJlbnQgdHlwZSByZXN1bHRzIGluIGEgZnVsbCBkZXBsb3ltZW50JywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnTmVzdGVkU3RhY2tUeXBlQ2hhbmdlUm9vdCcpO1xuICBtb2NrVXBkYXRlTGFtYmRhQ29kZSA9IGplc3QuZm4oKS5tb2NrUmV0dXJuVmFsdWUoe30pO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnN0dWJMYW1iZGEoe1xuICAgIHVwZGF0ZUZ1bmN0aW9uQ29kZTogbW9ja1VwZGF0ZUxhbWJkYUNvZGUsXG4gIH0pO1xuXG4gIGNvbnN0IHJvb3RTdGFjayA9IHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTmVzdGVkU3RhY2tUeXBlQ2hhbmdlUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgICAgUzNLZXk6ICdjdXJyZW50LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgRnVuY3Rpb25OYW1lOiAncm9vdC1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBGdXR1cmVOZXN0ZWRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnbmV3LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgRnVuY3Rpb25OYW1lOiAnc3Bvb2t5LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIHNldHVwLmFkZFRlbXBsYXRlVG9DbG91ZEZvcm1hdGlvbkxvb2t1cE1vY2socm9vdFN0YWNrKTtcblxuICByb290U3RhY2sudGVtcGxhdGUuUmVzb3VyY2VzLkZ1bmMuUHJvcGVydGllcy5Db2RlLlMzQnVja2V0ID0gJ25ldy1idWNrZXQnO1xuICByb290U3RhY2sudGVtcGxhdGUuUmVzb3VyY2VzLkZ1dHVyZU5lc3RlZFN0YWNrID0ge1xuICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgUHJvcGVydGllczoge1xuICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICB9LFxuICAgIE1ldGFkYXRhOiB7XG4gICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgfSxcbiAgfTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ05lc3RlZFN0YWNrVHlwZUNoYW5nZVJvb3QnLCB0ZW1wbGF0ZTogcm9vdFN0YWNrLnRlbXBsYXRlIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG5cbnRlc3QoJ211bHRpLXNpYmxpbmcgKyAzLWxheWVyIG5lc3RlZCBzdGFjayBzdHJ1Y3R1cmUgaXMgaG90c3dhcHBhYmxlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnTXVsdGlMYXllclJvb3QnKTtcbiAgbW9ja1VwZGF0ZUxhbWJkYUNvZGUgPSBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KTtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlci5zdHViTGFtYmRhKHtcbiAgICB1cGRhdGVGdW5jdGlvbkNvZGU6IG1vY2tVcGRhdGVMYW1iZGFDb2RlLFxuICB9KTtcblxuICBjb25zdCBsYW1iZGFGdW5jdGlvblJlc291cmNlID0ge1xuICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgIFByb3BlcnRpZXM6IHtcbiAgICAgIENvZGU6IHtcbiAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgfSxcbiAgICB9LFxuICAgIE1ldGFkYXRhOiB7XG4gICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3Qgcm9vdFN0YWNrID0gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdNdWx0aUxheWVyUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBDaGlsZFN0YWNrOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBUZW1wbGF0ZVVSTDogJ2h0dHBzOi8vd3d3Lm1hZ2ljLXVybC5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbmUtdW5uYW1lZC1sYW1iZGEtdHdvLXN0YWNrcy1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgRnVuYzogbGFtYmRhRnVuY3Rpb25SZXNvdXJjZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnQ2hpbGRTdGFjaycsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBHcmFuZENoaWxkU3RhY2tBOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBUZW1wbGF0ZVVSTDogJ2h0dHBzOi8vd3d3Lm1hZ2ljLXVybC5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbmUtdW5uYW1lZC1sYW1iZGEtc3RhY2submVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIEdyYW5kQ2hpbGRTdGFja0I6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly93d3cubWFnaWMtdXJsLmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29uZS11bm5hbWVkLWxhbWJkYS1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgRnVuYzogbGFtYmRhRnVuY3Rpb25SZXNvdXJjZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSkpO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnR3JhbmRDaGlsZFN0YWNrQScsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiBsYW1iZGFGdW5jdGlvblJlc291cmNlLFxuICAgICAgfSxcbiAgICB9LFxuICB9KSk7XG4gIHNldHVwLmFkZFRlbXBsYXRlVG9DbG91ZEZvcm1hdGlvbkxvb2t1cE1vY2sodGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdHcmFuZENoaWxkU3RhY2tCJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IGxhbWJkYUZ1bmN0aW9uUmVzb3VyY2UsXG4gICAgICB9LFxuICAgIH0sXG4gIH0pKTtcblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnTXVsdGlMYXllclJvb3QnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdDaGlsZFN0YWNrJywgJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICdhcm46YXdzOmNsb3VkZm9ybWF0aW9uOmJlcm11ZGEtdHJpYW5nbGUtMTMzNzoxMjM0NTY3ODkwMTI6c3RhY2svQ2hpbGRTdGFjay9hYmNkJyxcbiAgICApLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdGdW5jJywgJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsICdyb290LWZ1bmN0aW9uJyksXG4gICk7XG4gIHNldHVwLnB1c2hOZXN0ZWRTdGFja1Jlc291cmNlU3VtbWFyaWVzKCdDaGlsZFN0YWNrJyxcbiAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignR3JhbmRDaGlsZFN0YWNrQScsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL0dyYW5kQ2hpbGRTdGFja0EvYWJjZCcsXG4gICAgKSxcbiAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignR3JhbmRDaGlsZFN0YWNrQicsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL0dyYW5kQ2hpbGRTdGFja0IvYWJjZCcsXG4gICAgKSxcbiAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignRnVuYycsICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCAnY2hpbGQtZnVuY3Rpb24nKSxcbiAgKTtcbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ0dyYW5kQ2hpbGRTdGFja0EnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdGdW5jJywgJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsICdncmFuZGNoaWxkLUEtZnVuY3Rpb24nKSxcbiAgKTtcbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ0dyYW5kQ2hpbGRTdGFja0InLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdGdW5jJywgJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsICdncmFuZGNoaWxkLUItZnVuY3Rpb24nKSxcbiAgKTtcblxuICByb290U3RhY2sudGVtcGxhdGUuUmVzb3VyY2VzLkZ1bmMuUHJvcGVydGllcy5Db2RlLlMzS2V5ID0gJ25ldy1rZXknO1xuICBjb25zdCBjZGtTdGFja0FydGlmYWN0ID0gdGVzdFN0YWNrKHsgc3RhY2tOYW1lOiAnTXVsdGlMYXllclJvb3QnLCB0ZW1wbGF0ZTogcm9vdFN0YWNrLnRlbXBsYXRlIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS5ub3QudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QobW9ja1VwZGF0ZUxhbWJkYUNvZGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICBGdW5jdGlvbk5hbWU6ICdyb290LWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICBTM0tleTogJ25ldy1rZXknLFxuICB9KTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnY2hpbGQtZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xuICBleHBlY3QobW9ja1VwZGF0ZUxhbWJkYUNvZGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICBGdW5jdGlvbk5hbWU6ICdncmFuZGNoaWxkLUEtZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xuICBleHBlY3QobW9ja1VwZGF0ZUxhbWJkYUNvZGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICBGdW5jdGlvbk5hbWU6ICdncmFuZGNoaWxkLUItZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xufSk7XG5cbnRlc3QoJ2NhbiBob3Rzd2FwIGEgbGFtYmRhIGZ1bmN0aW9uIGluIGEgMS1sZXZlbCBuZXN0ZWQgc3RhY2sgd2l0aCBhc3NldCBwYXJhbWV0ZXJzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnTGFtYmRhUm9vdCcpO1xuICBtb2NrVXBkYXRlTGFtYmRhQ29kZSA9IGplc3QuZm4oKS5tb2NrUmV0dXJuVmFsdWUoe30pO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnN0dWJMYW1iZGEoe1xuICAgIHVwZGF0ZUZ1bmN0aW9uQ29kZTogbW9ja1VwZGF0ZUxhbWJkYUNvZGUsXG4gIH0pO1xuXG4gIGNvbnN0IHJvb3RTdGFjayA9IHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTGFtYmRhUm9vdCcsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBOZXN0ZWRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICAgIFBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgcmVmZXJlbmNldG9TM0J1Y2tldFBhcmFtOiB7XG4gICAgICAgICAgICAgICAgUmVmOiAnUzNCdWNrZXRQYXJhbScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHJlZmVyZW5jZXRvUzNLZXlQYXJhbToge1xuICAgICAgICAgICAgICAgIFJlZjogJ1MzS2V5UGFyYW0nLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb25lLWxhbWJkYS1zdGFjay13aXRoLWFzc2V0LXBhcmFtZXRlcnMubmVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgUGFyYW1ldGVyczoge1xuICAgICAgICBTM0J1Y2tldFBhcmFtOiB7XG4gICAgICAgICAgVHlwZTogJ1N0cmluZycsXG4gICAgICAgICAgRGVzY3JpcHRpb246ICdTMyBidWNrZXQgZm9yIGFzc2V0JyxcbiAgICAgICAgfSxcbiAgICAgICAgUzNLZXlQYXJhbToge1xuICAgICAgICAgIFR5cGU6ICdTdHJpbmcnLFxuICAgICAgICAgIERlc2NyaXB0aW9uOiAnUzMgYnVja2V0IGZvciBhc3NldCcsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIHNldHVwLmFkZFRlbXBsYXRlVG9DbG91ZEZvcm1hdGlvbkxvb2t1cE1vY2socm9vdFN0YWNrKTtcbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayh0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ05lc3RlZFN0YWNrJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6ICdteS1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KSk7XG5cbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ0xhbWJkYVJvb3QnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdOZXN0ZWRTdGFjaycsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL05lc3RlZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ0xhbWJkYVJvb3QnLCB0ZW1wbGF0ZTogcm9vdFN0YWNrLnRlbXBsYXRlIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QsIHtcbiAgICBTM0J1Y2tldFBhcmFtOiAnYnVja2V0LXBhcmFtLXZhbHVlJyxcbiAgICBTM0tleVBhcmFtOiAna2V5LXBhcmFtLXZhbHVlJyxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ2J1Y2tldC1wYXJhbS12YWx1ZScsXG4gICAgUzNLZXk6ICdrZXktcGFyYW0tdmFsdWUnLFxuICB9KTtcbn0pO1xuXG50ZXN0KCdjYW4gaG90c3dhcCBhIGxhbWJkYSBmdW5jdGlvbiBpbiBhIDItbGV2ZWwgbmVzdGVkIHN0YWNrIHdpdGggYXNzZXQgcGFyYW1ldGVycycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcE5lc3RlZFN0YWNrVGVzdHMoJ0xhbWJkYVJvb3QnKTtcbiAgbW9ja1VwZGF0ZUxhbWJkYUNvZGUgPSBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KTtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlci5zdHViTGFtYmRhKHtcbiAgICB1cGRhdGVGdW5jdGlvbkNvZGU6IG1vY2tVcGRhdGVMYW1iZGFDb2RlLFxuICB9KTtcblxuICBjb25zdCByb290U3RhY2sgPSB0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ0xhbWJkYVJvb3QnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgQ2hpbGRTdGFjazoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGVtcGxhdGVVUkw6ICdodHRwczovL3d3dy5tYWdpYy11cmwuY29tJyxcbiAgICAgICAgICAgIFBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgcmVmZXJlbmNldG9HcmFuZENoaWxkUzNCdWNrZXRQYXJhbToge1xuICAgICAgICAgICAgICAgIFJlZjogJ0dyYW5kQ2hpbGRTM0J1Y2tldFBhcmFtJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgcmVmZXJlbmNldG9HcmFuZENoaWxkUzNLZXlQYXJhbToge1xuICAgICAgICAgICAgICAgIFJlZjogJ0dyYW5kQ2hpbGRTM0tleVBhcmFtJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgcmVmZXJlbmNldG9DaGlsZFMzQnVja2V0UGFyYW06IHtcbiAgICAgICAgICAgICAgICBSZWY6ICdDaGlsZFMzQnVja2V0UGFyYW0nLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICByZWZlcmVuY2V0b0NoaWxkUzNLZXlQYXJhbToge1xuICAgICAgICAgICAgICAgIFJlZjogJ0NoaWxkUzNLZXlQYXJhbScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbmUtbGFtYmRhLW9uZS1zdGFjay1zdGFjay13aXRoLWFzc2V0LXBhcmFtZXRlcnMubmVzdGVkLnRlbXBsYXRlLmpzb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgUGFyYW1ldGVyczoge1xuICAgICAgICBHcmFuZENoaWxkUzNCdWNrZXRQYXJhbToge1xuICAgICAgICAgIFR5cGU6ICdTdHJpbmcnLFxuICAgICAgICAgIERlc2NyaXB0aW9uOiAnUzMgYnVja2V0IGZvciBhc3NldCcsXG4gICAgICAgIH0sXG4gICAgICAgIEdyYW5kQ2hpbGRTM0tleVBhcmFtOiB7XG4gICAgICAgICAgVHlwZTogJ1N0cmluZycsXG4gICAgICAgICAgRGVzY3JpcHRpb246ICdTMyBidWNrZXQgZm9yIGFzc2V0JyxcbiAgICAgICAgfSxcbiAgICAgICAgQ2hpbGRTM0J1Y2tldFBhcmFtOiB7XG4gICAgICAgICAgVHlwZTogJ1N0cmluZycsXG4gICAgICAgICAgRGVzY3JpcHRpb246ICdTMyBidWNrZXQgZm9yIGFzc2V0JyxcbiAgICAgICAgfSxcbiAgICAgICAgQ2hpbGRTM0tleVBhcmFtOiB7XG4gICAgICAgICAgVHlwZTogJ1N0cmluZycsXG4gICAgICAgICAgRGVzY3JpcHRpb246ICdTMyBidWNrZXQgZm9yIGFzc2V0JyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnQ2hpbGRTdGFjaycsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgICAgUzNLZXk6ICdjdXJyZW50LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgR3JhbmRDaGlsZFN0YWNrOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBUZW1wbGF0ZVVSTDogJ2h0dHBzOi8vd3d3Lm1hZ2ljLXVybC5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbmUtbGFtYmRhLXN0YWNrLXdpdGgtYXNzZXQtcGFyYW1ldGVycy5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSkpO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnR3JhbmRDaGlsZFN0YWNrJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6ICdteS1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KSk7XG5cblxuICBzZXR1cC5wdXNoTmVzdGVkU3RhY2tSZXNvdXJjZVN1bW1hcmllcygnTGFtYmRhUm9vdCcsXG4gICAgc2V0dXAuc3RhY2tTdW1tYXJ5T2YoJ0NoaWxkU3RhY2snLCAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgJ2Fybjphd3M6Y2xvdWRmb3JtYXRpb246YmVybXVkYS10cmlhbmdsZS0xMzM3OjEyMzQ1Njc4OTAxMjpzdGFjay9DaGlsZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ0NoaWxkU3RhY2snLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdHcmFuZENoaWxkU3RhY2snLCAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgJ2Fybjphd3M6Y2xvdWRmb3JtYXRpb246YmVybXVkYS10cmlhbmdsZS0xMzM3OjEyMzQ1Njc4OTAxMjpzdGFjay9HcmFuZENoaWxkU3RhY2svYWJjZCcsXG4gICAgKSxcbiAgKTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ0xhbWJkYVJvb3QnLCB0ZW1wbGF0ZTogcm9vdFN0YWNrLnRlbXBsYXRlIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QsIHtcbiAgICBHcmFuZENoaWxkUzNCdWNrZXRQYXJhbTogJ2NoaWxkLWJ1Y2tldC1wYXJhbS12YWx1ZScsXG4gICAgR3JhbmRDaGlsZFMzS2V5UGFyYW06ICdjaGlsZC1rZXktcGFyYW0tdmFsdWUnLFxuICAgIENoaWxkUzNCdWNrZXRQYXJhbTogJ2J1Y2tldC1wYXJhbS12YWx1ZScsXG4gICAgQ2hpbGRTM0tleVBhcmFtOiAna2V5LXBhcmFtLXZhbHVlJyxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICBTM0J1Y2tldDogJ2J1Y2tldC1wYXJhbS12YWx1ZScsXG4gICAgUzNLZXk6ICdrZXktcGFyYW0tdmFsdWUnLFxuICB9KTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY2hpbGQtYnVja2V0LXBhcmFtLXZhbHVlJyxcbiAgICBTM0tleTogJ2NoaWxkLWtleS1wYXJhbS12YWx1ZScsXG4gIH0pO1xufSk7XG5cbnRlc3QoJ2xvb2tpbmcgdXAgb2JqZWN0cyBpbiBuZXN0ZWQgc3RhY2tzIHdvcmtzJywgYXN5bmMgKCkgPT4ge1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyID0gc2V0dXAuc2V0dXBIb3Rzd2FwTmVzdGVkU3RhY2tUZXN0cygnTGFtYmRhUm9vdCcpO1xuICBtb2NrVXBkYXRlTGFtYmRhQ29kZSA9IGplc3QuZm4oKS5tb2NrUmV0dXJuVmFsdWUoe30pO1xuICBtb2NrUHVibGlzaFZlcnNpb24gPSBqZXN0LmZuKCk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkxhbWJkYSh7XG4gICAgdXBkYXRlRnVuY3Rpb25Db2RlOiBtb2NrVXBkYXRlTGFtYmRhQ29kZSxcbiAgICBwdWJsaXNoVmVyc2lvbjogbW9ja1B1Ymxpc2hWZXJzaW9uLFxuICB9KTtcblxuICBjb25zdCByb290U3RhY2sgPSB0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ0xhbWJkYVJvb3QnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgTmVzdGVkU3RhY2s6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly93d3cubWFnaWMtdXJsLmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29uZS1sYW1iZGEtdmVyc2lvbi1zdGFjay5uZXN0ZWQudGVtcGxhdGUuanNvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgc2V0dXAuYWRkVGVtcGxhdGVUb0Nsb3VkRm9ybWF0aW9uTG9va3VwTW9jayhyb290U3RhY2spO1xuICBzZXR1cC5hZGRUZW1wbGF0ZVRvQ2xvdWRGb3JtYXRpb25Mb29rdXBNb2NrKHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnTmVzdGVkU3RhY2snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBWZXJzaW9uOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpWZXJzaW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6IHsgUmVmOiAnRnVuYycgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KSk7XG5cbiAgc2V0dXAucHVzaE5lc3RlZFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoJ0xhbWJkYVJvb3QnLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdOZXN0ZWRTdGFjaycsICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjpiZXJtdWRhLXRyaWFuZ2xlLTEzMzc6MTIzNDU2Nzg5MDEyOnN0YWNrL05lc3RlZFN0YWNrL2FiY2QnLFxuICAgICksXG4gICk7XG5cbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHRlc3RTdGFjayh7IHN0YWNrTmFtZTogJ0xhbWJkYVJvb3QnLCB0ZW1wbGF0ZTogcm9vdFN0YWNrLnRlbXBsYXRlIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS5ub3QudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QobW9ja1B1Ymxpc2hWZXJzaW9uKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICB9KTtcbn0pO1xuIl19
|