aws-cdk 2.3.0 → 2.7.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.
Files changed (77) hide show
  1. package/LICENSE +1 -1
  2. package/NOTICE +1 -1
  3. package/README.md +4 -1
  4. package/bin/cdk.js +7 -6
  5. package/build-info.json +2 -2
  6. package/lib/api/aws-auth/sdk-provider.d.ts +26 -1
  7. package/lib/api/aws-auth/sdk-provider.js +14 -24
  8. package/lib/api/aws-auth/sdk.d.ts +2 -0
  9. package/lib/api/aws-auth/sdk.js +4 -1
  10. package/lib/api/bootstrap/bootstrap-template.yaml +3 -1
  11. package/lib/api/bootstrap/deploy-bootstrap.js +2 -2
  12. package/lib/api/cloudformation-deployments.d.ts +63 -1
  13. package/lib/api/cloudformation-deployments.js +66 -3
  14. package/lib/api/cxapp/cloud-assembly.js +5 -5
  15. package/lib/api/deploy-stack.js +10 -4
  16. package/lib/api/hotswap/code-build-projects.d.ts +3 -0
  17. package/lib/api/hotswap/code-build-projects.js +53 -0
  18. package/lib/api/hotswap/common.d.ts +17 -1
  19. package/lib/api/hotswap/common.js +30 -6
  20. package/lib/api/hotswap/ecs-services.js +4 -18
  21. package/lib/api/hotswap/lambda-functions.js +169 -44
  22. package/lib/api/hotswap/s3-bucket-deployments.js +3 -10
  23. package/lib/api/hotswap/stepfunctions-state-machines.js +2 -1
  24. package/lib/api/hotswap-deployments.d.ts +0 -7
  25. package/lib/api/hotswap-deployments.js +85 -13
  26. package/lib/api/toolkit-info.d.ts +5 -5
  27. package/lib/api/toolkit-info.js +10 -10
  28. package/lib/api/util/cloudformation/stack-activity-monitor.js +22 -22
  29. package/lib/assets.js +3 -3
  30. package/lib/cdk-toolkit.js +66 -32
  31. package/lib/commands/context.js +7 -7
  32. package/lib/commands/docs.js +5 -5
  33. package/lib/commands/doctor.js +6 -6
  34. package/lib/context-providers/ami.js +2 -2
  35. package/lib/context-providers/availability-zones.js +2 -2
  36. package/lib/context-providers/endpoint-service-availability-zones.js +2 -2
  37. package/lib/context-providers/hosted-zones.js +2 -2
  38. package/lib/context-providers/keys.js +2 -2
  39. package/lib/context-providers/load-balancers.js +3 -3
  40. package/lib/context-providers/security-groups.js +2 -2
  41. package/lib/context-providers/ssm-parameters.js +2 -2
  42. package/lib/context-providers/vpcs.js +2 -2
  43. package/lib/diff.js +3 -3
  44. package/lib/init.js +15 -14
  45. package/lib/logging.js +7 -7
  46. package/lib/os.js +3 -3
  47. package/lib/plugin.js +4 -4
  48. package/lib/util/asset-publishing.js +3 -3
  49. package/lib/util/console-formatters.js +4 -3
  50. package/lib/util/npm.d.ts +1 -0
  51. package/lib/util/npm.js +21 -0
  52. package/lib/version.d.ts +1 -1
  53. package/lib/version.js +23 -20
  54. package/npm-shrinkwrap.json +229 -101
  55. package/package.json +19 -18
  56. package/test/api/cloudformation-deployments.test.js +2 -2
  57. package/test/api/hotswap/{lambda-hotswap-deployments.test.d.ts → code-build-projects-hotswap-deployments.test.d.ts} +0 -0
  58. package/test/api/hotswap/code-build-projects-hotswap-deployments.test.js +576 -0
  59. package/test/api/hotswap/hotswap-deployments.test.js +4 -2
  60. package/test/api/hotswap/hotswap-test-setup.d.ts +3 -1
  61. package/test/api/hotswap/hotswap-test-setup.js +7 -4
  62. package/test/api/hotswap/lambda-functions-hotswap-deployments.test.d.ts +1 -0
  63. package/test/api/hotswap/lambda-functions-hotswap-deployments.test.js +502 -0
  64. package/test/api/hotswap/lambda-versions-aliases-hotswap-deployments.test.d.ts +1 -0
  65. package/test/api/hotswap/lambda-versions-aliases-hotswap-deployments.test.js +197 -0
  66. package/test/api/sdk-provider.test.js +11 -11
  67. package/test/api/stack-activity-monitor.test.js +13 -13
  68. package/test/cdk-toolkit.test.js +240 -13
  69. package/test/context-providers/load-balancers.test.js +4 -4
  70. package/test/init.test.js +5 -4
  71. package/test/util/cloudformation.test.js +2 -2
  72. package/test/util/console-formatters.test.js +6 -6
  73. package/test/util/mock-sdk.d.ts +4 -2
  74. package/test/util/mock-sdk.js +6 -2
  75. package/test/util/mock-toolkitinfo.js +2 -2
  76. package/test/version.test.js +45 -3
  77. package/test/api/hotswap/lambda-hotswap-deployments.test.js +0 -418
@@ -1,418 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const setup = require("./hotswap-test-setup");
4
- let mockUpdateLambdaCode;
5
- let hotswapMockSdkProvider;
6
- beforeEach(() => {
7
- hotswapMockSdkProvider = setup.setupHotswapTests();
8
- mockUpdateLambdaCode = jest.fn();
9
- hotswapMockSdkProvider.setUpdateFunctionCodeMock(mockUpdateLambdaCode);
10
- });
11
- test('returns undefined when a new Lambda function is added to the Stack', async () => {
12
- // GIVEN
13
- const cdkStackArtifact = setup.cdkStackArtifactOf({
14
- template: {
15
- Resources: {
16
- Func: {
17
- Type: 'AWS::Lambda::Function',
18
- },
19
- },
20
- },
21
- });
22
- // WHEN
23
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
24
- // THEN
25
- expect(deployStackResult).toBeUndefined();
26
- });
27
- test('calls the updateLambdaCode() API when it receives only a code difference in a Lambda function', async () => {
28
- // GIVEN
29
- setup.setCurrentCfnStackTemplate({
30
- Resources: {
31
- Func: {
32
- Type: 'AWS::Lambda::Function',
33
- Properties: {
34
- Code: {
35
- S3Bucket: 'current-bucket',
36
- S3Key: 'current-key',
37
- },
38
- FunctionName: 'my-function',
39
- },
40
- Metadata: {
41
- 'aws:asset:path': 'old-path',
42
- },
43
- },
44
- },
45
- });
46
- const cdkStackArtifact = setup.cdkStackArtifactOf({
47
- template: {
48
- Resources: {
49
- Func: {
50
- Type: 'AWS::Lambda::Function',
51
- Properties: {
52
- Code: {
53
- S3Bucket: 'current-bucket',
54
- S3Key: 'new-key',
55
- },
56
- FunctionName: 'my-function',
57
- },
58
- Metadata: {
59
- 'aws:asset:path': 'new-path',
60
- },
61
- },
62
- },
63
- },
64
- });
65
- // WHEN
66
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
67
- // THEN
68
- expect(deployStackResult).not.toBeUndefined();
69
- expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
70
- FunctionName: 'my-function',
71
- S3Bucket: 'current-bucket',
72
- S3Key: 'new-key',
73
- });
74
- });
75
- test("correctly evaluates the function's name when it references a different resource from the template", async () => {
76
- // GIVEN
77
- setup.setCurrentCfnStackTemplate({
78
- Resources: {
79
- Bucket: {
80
- Type: 'AWS::S3::Bucket',
81
- },
82
- Func: {
83
- Type: 'AWS::Lambda::Function',
84
- Properties: {
85
- Code: {
86
- S3Bucket: 'current-bucket',
87
- S3Key: 'current-key',
88
- },
89
- FunctionName: {
90
- 'Fn::Join': ['-', [
91
- 'lambda',
92
- { Ref: 'Bucket' },
93
- 'function',
94
- ]],
95
- },
96
- },
97
- Metadata: {
98
- 'aws:asset:path': 'old-path',
99
- },
100
- },
101
- },
102
- });
103
- setup.pushStackResourceSummaries(setup.stackSummaryOf('Bucket', 'AWS::S3::Bucket', 'mybucket'));
104
- const cdkStackArtifact = setup.cdkStackArtifactOf({
105
- template: {
106
- Resources: {
107
- Bucket: {
108
- Type: 'AWS::S3::Bucket',
109
- },
110
- Func: {
111
- Type: 'AWS::Lambda::Function',
112
- Properties: {
113
- Code: {
114
- S3Bucket: 'current-bucket',
115
- S3Key: 'new-key',
116
- },
117
- FunctionName: {
118
- 'Fn::Join': ['-', [
119
- 'lambda',
120
- { Ref: 'Bucket' },
121
- 'function',
122
- ]],
123
- },
124
- },
125
- Metadata: {
126
- 'aws:asset:path': 'old-path',
127
- },
128
- },
129
- },
130
- },
131
- });
132
- // WHEN
133
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
134
- // THEN
135
- expect(deployStackResult).not.toBeUndefined();
136
- expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
137
- FunctionName: 'lambda-mybucket-function',
138
- S3Bucket: 'current-bucket',
139
- S3Key: 'new-key',
140
- });
141
- });
142
- test("correctly falls back to taking the function's name from the current stack if it can't evaluate it in the template", async () => {
143
- // GIVEN
144
- setup.setCurrentCfnStackTemplate({
145
- Parameters: {
146
- Param1: { Type: 'String' },
147
- AssetBucketParam: { Type: 'String' },
148
- },
149
- Resources: {
150
- Func: {
151
- Type: 'AWS::Lambda::Function',
152
- Properties: {
153
- Code: {
154
- S3Bucket: { Ref: 'AssetBucketParam' },
155
- S3Key: 'current-key',
156
- },
157
- FunctionName: { Ref: 'Param1' },
158
- },
159
- Metadata: {
160
- 'aws:asset:path': 'old-path',
161
- },
162
- },
163
- },
164
- });
165
- setup.pushStackResourceSummaries(setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'my-function'));
166
- const cdkStackArtifact = setup.cdkStackArtifactOf({
167
- template: {
168
- Parameters: {
169
- Param1: { Type: 'String' },
170
- AssetBucketParam: { Type: 'String' },
171
- },
172
- Resources: {
173
- Func: {
174
- Type: 'AWS::Lambda::Function',
175
- Properties: {
176
- Code: {
177
- S3Bucket: { Ref: 'AssetBucketParam' },
178
- S3Key: 'new-key',
179
- },
180
- FunctionName: { Ref: 'Param1' },
181
- },
182
- Metadata: {
183
- 'aws:asset:path': 'new-path',
184
- },
185
- },
186
- },
187
- },
188
- });
189
- // WHEN
190
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact, { AssetBucketParam: 'asset-bucket' });
191
- // THEN
192
- expect(deployStackResult).not.toBeUndefined();
193
- expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
194
- FunctionName: 'my-function',
195
- S3Bucket: 'asset-bucket',
196
- S3Key: 'new-key',
197
- });
198
- });
199
- test("will not perform a hotswap deployment if it cannot find a Ref target (outside the function's name)", async () => {
200
- // GIVEN
201
- setup.setCurrentCfnStackTemplate({
202
- Parameters: {
203
- Param1: { Type: 'String' },
204
- },
205
- Resources: {
206
- Func: {
207
- Type: 'AWS::Lambda::Function',
208
- Properties: {
209
- Code: {
210
- S3Bucket: { 'Fn::Sub': '${Param1}' },
211
- S3Key: 'current-key',
212
- },
213
- },
214
- Metadata: {
215
- 'aws:asset:path': 'old-path',
216
- },
217
- },
218
- },
219
- });
220
- setup.pushStackResourceSummaries(setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'my-func'));
221
- const cdkStackArtifact = setup.cdkStackArtifactOf({
222
- template: {
223
- Parameters: {
224
- Param1: { Type: 'String' },
225
- },
226
- Resources: {
227
- Func: {
228
- Type: 'AWS::Lambda::Function',
229
- Properties: {
230
- Code: {
231
- S3Bucket: { 'Fn::Sub': '${Param1}' },
232
- S3Key: 'new-key',
233
- },
234
- },
235
- Metadata: {
236
- 'aws:asset:path': 'new-path',
237
- },
238
- },
239
- },
240
- },
241
- });
242
- // THEN
243
- await expect(() => hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact)).rejects.toThrow(/Parameter or resource 'Param1' could not be found for evaluation/);
244
- });
245
- test("will not perform a hotswap deployment if it doesn't know how to handle a specific attribute (outside the function's name)", async () => {
246
- // GIVEN
247
- setup.setCurrentCfnStackTemplate({
248
- Resources: {
249
- Bucket: {
250
- Type: 'AWS::S3::Bucket',
251
- },
252
- Func: {
253
- Type: 'AWS::Lambda::Function',
254
- Properties: {
255
- Code: {
256
- S3Bucket: { 'Fn::GetAtt': ['Bucket', 'UnknownAttribute'] },
257
- S3Key: 'current-key',
258
- },
259
- },
260
- Metadata: {
261
- 'aws:asset:path': 'old-path',
262
- },
263
- },
264
- },
265
- });
266
- setup.pushStackResourceSummaries(setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'my-func'), setup.stackSummaryOf('Bucket', 'AWS::S3::Bucket', 'my-bucket'));
267
- const cdkStackArtifact = setup.cdkStackArtifactOf({
268
- template: {
269
- Resources: {
270
- Bucket: {
271
- Type: 'AWS::S3::Bucket',
272
- },
273
- Func: {
274
- Type: 'AWS::Lambda::Function',
275
- Properties: {
276
- Code: {
277
- S3Bucket: { 'Fn::GetAtt': ['Bucket', 'UnknownAttribute'] },
278
- S3Key: 'new-key',
279
- },
280
- },
281
- Metadata: {
282
- 'aws:asset:path': 'new-path',
283
- },
284
- },
285
- },
286
- },
287
- });
288
- // THEN
289
- await expect(() => hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact)).rejects.toThrow("We don't support the 'UnknownAttribute' attribute of the 'AWS::S3::Bucket' resource. This is a CDK limitation. Please report it at https://github.com/aws/aws-cdk/issues/new/choose");
290
- });
291
- test('calls the updateLambdaCode() API when it receives a code difference in a Lambda function with no name', async () => {
292
- // GIVEN
293
- setup.setCurrentCfnStackTemplate({
294
- Resources: {
295
- Func: {
296
- Type: 'AWS::Lambda::Function',
297
- Properties: {
298
- Code: {
299
- S3Bucket: 'current-bucket',
300
- S3Key: 'current-key',
301
- },
302
- },
303
- Metadata: {
304
- 'aws:asset:path': 'current-path',
305
- },
306
- },
307
- },
308
- });
309
- const cdkStackArtifact = setup.cdkStackArtifactOf({
310
- template: {
311
- Resources: {
312
- Func: {
313
- Type: 'AWS::Lambda::Function',
314
- Properties: {
315
- Code: {
316
- S3Bucket: 'current-bucket',
317
- S3Key: 'new-key',
318
- },
319
- },
320
- Metadata: {
321
- 'aws:asset:path': 'current-path',
322
- },
323
- },
324
- },
325
- },
326
- });
327
- // WHEN
328
- setup.pushStackResourceSummaries(setup.stackSummaryOf('Func', 'AWS::Lambda::Function', 'mock-function-resource-id'));
329
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
330
- // THEN
331
- expect(deployStackResult).not.toBeUndefined();
332
- expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
333
- FunctionName: 'mock-function-resource-id',
334
- S3Bucket: 'current-bucket',
335
- S3Key: 'new-key',
336
- });
337
- });
338
- test('does not call the updateLambdaCode() API when it receives a change that is not a code difference in a Lambda function', async () => {
339
- // GIVEN
340
- setup.setCurrentCfnStackTemplate({
341
- Resources: {
342
- Func: {
343
- Type: 'AWS::Lambda::Function',
344
- Properties: {
345
- Code: {
346
- S3Bucket: 'current-bucket',
347
- S3Key: 'current-key',
348
- },
349
- PackageType: 'Zip',
350
- },
351
- },
352
- },
353
- });
354
- const cdkStackArtifact = setup.cdkStackArtifactOf({
355
- template: {
356
- Resources: {
357
- Func: {
358
- Type: 'AWS::Lambda::Function',
359
- Properties: {
360
- Code: {
361
- S3Bucket: 'current-bucket',
362
- S3Key: 'current-key',
363
- },
364
- PackageType: 'Image',
365
- },
366
- },
367
- },
368
- },
369
- });
370
- // WHEN
371
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
372
- // THEN
373
- expect(deployStackResult).toBeUndefined();
374
- expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
375
- });
376
- test('does not call the updateLambdaCode() API when a resource with type that is not AWS::Lambda::Function but has the same properties is changed', async () => {
377
- // GIVEN
378
- setup.setCurrentCfnStackTemplate({
379
- Resources: {
380
- Func: {
381
- Type: 'AWS::NotLambda::NotAFunction',
382
- Properties: {
383
- Code: {
384
- S3Bucket: 'current-bucket',
385
- S3Key: 'current-key',
386
- },
387
- },
388
- Metadata: {
389
- 'aws:asset:path': 'old-path',
390
- },
391
- },
392
- },
393
- });
394
- const cdkStackArtifact = setup.cdkStackArtifactOf({
395
- template: {
396
- Resources: {
397
- Func: {
398
- Type: 'AWS::NotLambda::NotAFunction',
399
- Properties: {
400
- Code: {
401
- S3Bucket: 'current-bucket',
402
- S3Key: 'new-key',
403
- },
404
- },
405
- Metadata: {
406
- 'aws:asset:path': 'old-path',
407
- },
408
- },
409
- },
410
- },
411
- });
412
- // WHEN
413
- const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);
414
- // THEN
415
- expect(deployStackResult).toBeUndefined();
416
- expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
417
- });
418
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWhvdHN3YXAtZGVwbG95bWVudHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImxhbWJkYS1ob3Rzd2FwLWRlcGxveW1lbnRzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSw4Q0FBOEM7QUFFOUMsSUFBSSxvQkFBNEcsQ0FBQztBQUNqSCxJQUFJLHNCQUFvRCxDQUFDO0FBRXpELFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxzQkFBc0IsR0FBRyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUNuRCxvQkFBb0IsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDakMsc0JBQXNCLENBQUMseUJBQXlCLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQUN6RSxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxvRUFBb0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNwRixRQUFRO0lBQ1IsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUM7UUFDaEQsUUFBUSxFQUFFO1lBQ1IsU0FBUyxFQUFFO2dCQUNULElBQUksRUFBRTtvQkFDSixJQUFJLEVBQUUsdUJBQXVCO2lCQUM5QjthQUNGO1NBQ0Y7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFFOUYsT0FBTztJQUNQLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0FBQzVDLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLCtGQUErRixFQUFFLEtBQUssSUFBSSxFQUFFO0lBQy9HLFFBQVE7SUFDUixLQUFLLENBQUMsMEJBQTBCLENBQUM7UUFDL0IsU0FBUyxFQUFFO1lBQ1QsSUFBSSxFQUFFO2dCQUNKLElBQUksRUFBRSx1QkFBdUI7Z0JBQzdCLFVBQVUsRUFBRTtvQkFDVixJ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QUU7WUFDVCxJQUFJLEVBQUU7Z0JBQ0osSUFBSSxFQUFFLDhCQUE4QjtnQkFDcEMsVUFBVSxFQUFFO29CQUNWLElBQUksRUFBRTt3QkFDSixRQUFRLEVBQUUsZ0JBQWdCO3dCQUMxQixLQUFLLEVBQUUsYUFBYTtxQkFDckI7aUJBQ0Y7Z0JBQ0QsUUFBUSxFQUFFO29CQUNSLGdCQUFnQixFQUFFLFVBQVU7aUJBQzdCO2FBQ0Y7U0FDRjtLQUNGLENBQUMsQ0FBQztJQUNILE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDO1FBQ2hELFFBQVEsRUFBRTtZQUNSLFNBQVMsRUFBRTtnQkFDVCxJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLDhCQUE4QjtvQkFDcEMsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRTs0QkFDSixRQUFRLEVBQUUsZ0JBQWdCOzRCQUMxQixLQUFLLEVBQUUsU0FBUzt5QkFDakI7cUJBQ0Y7b0JBQ0QsUUFBUSxFQUFFO3dCQUNSLGdCQUFnQixFQUFFLFVBQVU7cUJBQzdCO2lCQUNGO2FBQ0Y7U0FDRjtLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUU5RixPQUFPO0lBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDMUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDdEQsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMYW1iZGEgfSBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCAqIGFzIHNldHVwIGZyb20gJy4vaG90c3dhcC10ZXN0LXNldHVwJztcblxubGV0IG1vY2tVcGRhdGVMYW1iZGFDb2RlOiAocGFyYW1zOiBMYW1iZGEuVHlwZXMuVXBkYXRlRnVuY3Rpb25Db2RlUmVxdWVzdCkgPT4gTGFtYmRhLlR5cGVzLkZ1bmN0aW9uQ29uZmlndXJhdGlvbjtcbmxldCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyOiBzZXR1cC5Ib3Rzd2FwTW9ja1Nka1Byb3ZpZGVyO1xuXG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcFRlc3RzKCk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnNldFVwZGF0ZUZ1bmN0aW9uQ29kZU1vY2sobW9ja1VwZGF0ZUxhbWJkYUNvZGUpO1xufSk7XG5cbnRlc3QoJ3JldHVybnMgdW5kZWZpbmVkIHdoZW4gYSBuZXcgTGFtYmRhIGZ1bmN0aW9uIGlzIGFkZGVkIHRvIHRoZSBTdGFjaycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS50b0JlVW5kZWZpbmVkKCk7XG59KTtcblxudGVzdCgnY2FsbHMgdGhlIHVwZGF0ZUxhbWJkYUNvZGUoKSBBUEkgd2hlbiBpdCByZWNlaXZlcyBvbmx5IGEgY29kZSBkaWZmZXJlbmNlIGluIGEgTGFtYmRhIGZ1bmN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzZXR1cC5zZXRDdXJyZW50Q2ZuU3RhY2tUZW1wbGF0ZSh7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICBGdW5jOiB7XG4gICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIEZ1bmN0aW9uTmFtZTogJ215LWZ1bmN0aW9uJyxcbiAgICAgICAgfSxcbiAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgICAgUzNLZXk6ICduZXcta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6ICdteS1mdW5jdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ25ldy1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IGRlcGxveVN0YWNrUmVzdWx0ID0gYXdhaXQgaG90c3dhcE1vY2tTZGtQcm92aWRlci50cnlIb3Rzd2FwRGVwbG95bWVudChjZGtTdGFja0FydGlmYWN0KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkubm90LnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xufSk7XG5cbnRlc3QoXCJjb3JyZWN0bHkgZXZhbHVhdGVzIHRoZSBmdW5jdGlvbidzIG5hbWUgd2hlbiBpdCByZWZlcmVuY2VzIGEgZGlmZmVyZW50IHJlc291cmNlIGZyb20gdGhlIHRlbXBsYXRlXCIsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgc2V0dXAuc2V0Q3VycmVudENmblN0YWNrVGVtcGxhdGUoe1xuICAgIFJlc291cmNlczoge1xuICAgICAgQnVja2V0OiB7XG4gICAgICAgIFR5cGU6ICdBV1M6OlMzOjpCdWNrZXQnLFxuICAgICAgfSxcbiAgICAgIEZ1bmM6IHtcbiAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgRnVuY3Rpb25OYW1lOiB7XG4gICAgICAgICAgICAnRm46OkpvaW4nOiBbJy0nLCBbXG4gICAgICAgICAgICAgICdsYW1iZGEnLFxuICAgICAgICAgICAgICB7IFJlZjogJ0J1Y2tldCcgfSxcbiAgICAgICAgICAgICAgJ2Z1bmN0aW9uJyxcbiAgICAgICAgICAgIF1dLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG4gIHNldHVwLnB1c2hTdGFja1Jlc291cmNlU3VtbWFyaWVzKHNldHVwLnN0YWNrU3VtbWFyeU9mKCdCdWNrZXQnLCAnQVdTOjpTMzo6QnVja2V0JywgJ215YnVja2V0JykpO1xuICBjb25zdCBjZGtTdGFja0FydGlmYWN0ID0gc2V0dXAuY2RrU3RhY2tBcnRpZmFjdE9mKHtcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEJ1Y2tldDoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OlMzOjpCdWNrZXQnLFxuICAgICAgICB9LFxuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogJ2N1cnJlbnQtYnVja2V0JyxcbiAgICAgICAgICAgICAgUzNLZXk6ICduZXcta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6IHtcbiAgICAgICAgICAgICAgJ0ZuOjpKb2luJzogWyctJywgW1xuICAgICAgICAgICAgICAgICdsYW1iZGEnLFxuICAgICAgICAgICAgICAgIHsgUmVmOiAnQnVja2V0JyB9LFxuICAgICAgICAgICAgICAgICdmdW5jdGlvbicsXG4gICAgICAgICAgICAgIF1dLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS5ub3QudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QobW9ja1VwZGF0ZUxhbWJkYUNvZGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICBGdW5jdGlvbk5hbWU6ICdsYW1iZGEtbXlidWNrZXQtZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgIFMzS2V5OiAnbmV3LWtleScsXG4gIH0pO1xufSk7XG5cbnRlc3QoXCJjb3JyZWN0bHkgZmFsbHMgYmFjayB0byB0YWtpbmcgdGhlIGZ1bmN0aW9uJ3MgbmFtZSBmcm9tIHRoZSBjdXJyZW50IHN0YWNrIGlmIGl0IGNhbid0IGV2YWx1YXRlIGl0IGluIHRoZSB0ZW1wbGF0ZVwiLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIHNldHVwLnNldEN1cnJlbnRDZm5TdGFja1RlbXBsYXRlKHtcbiAgICBQYXJhbWV0ZXJzOiB7XG4gICAgICBQYXJhbTE6IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICAgIEFzc2V0QnVja2V0UGFyYW06IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICB9LFxuICAgIFJlc291cmNlczoge1xuICAgICAgRnVuYzoge1xuICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgIFMzQnVja2V0OiB7IFJlZjogJ0Fzc2V0QnVja2V0UGFyYW0nIH0sXG4gICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIEZ1bmN0aW9uTmFtZTogeyBSZWY6ICdQYXJhbTEnIH0sXG4gICAgICAgIH0sXG4gICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ29sZC1wYXRoJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG4gIHNldHVwLnB1c2hTdGFja1Jlc291cmNlU3VtbWFyaWVzKHNldHVwLnN0YWNrU3VtbWFyeU9mKCdGdW5jJywgJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsICdteS1mdW5jdGlvbicpKTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFBhcmFtZXRlcnM6IHtcbiAgICAgICAgUGFyYW0xOiB7IFR5cGU6ICdTdHJpbmcnIH0sXG4gICAgICAgIEFzc2V0QnVja2V0UGFyYW06IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICAgIH0sXG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6IHsgUmVmOiAnQXNzZXRCdWNrZXRQYXJhbScgfSxcbiAgICAgICAgICAgICAgUzNLZXk6ICduZXcta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6IHsgUmVmOiAnUGFyYW0xJyB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICduZXctcGF0aCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCwgeyBBc3NldEJ1Y2tldFBhcmFtOiAnYXNzZXQtYnVja2V0JyB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkubm90LnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbXktZnVuY3Rpb24nLFxuICAgIFMzQnVja2V0OiAnYXNzZXQtYnVja2V0JyxcbiAgICBTM0tleTogJ25ldy1rZXknLFxuICB9KTtcbn0pO1xuXG50ZXN0KFwid2lsbCBub3QgcGVyZm9ybSBhIGhvdHN3YXAgZGVwbG95bWVudCBpZiBpdCBjYW5ub3QgZmluZCBhIFJlZiB0YXJnZXQgKG91dHNpZGUgdGhlIGZ1bmN0aW9uJ3MgbmFtZSlcIiwgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzZXR1cC5zZXRDdXJyZW50Q2ZuU3RhY2tUZW1wbGF0ZSh7XG4gICAgUGFyYW1ldGVyczoge1xuICAgICAgUGFyYW0xOiB7IFR5cGU6ICdTdHJpbmcnIH0sXG4gICAgfSxcbiAgICBSZXNvdXJjZXM6IHtcbiAgICAgIEZ1bmM6IHtcbiAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICBTM0J1Y2tldDogeyAnRm46OlN1Yic6ICcke1BhcmFtMX0nIH0sXG4gICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuICBzZXR1cC5wdXNoU3RhY2tSZXNvdXJjZVN1bW1hcmllcyhzZXR1cC5zdGFja1N1bW1hcnlPZignRnVuYycsICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCAnbXktZnVuYycpKTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFBhcmFtZXRlcnM6IHtcbiAgICAgICAgUGFyYW0xOiB7IFR5cGU6ICdTdHJpbmcnIH0sXG4gICAgICB9LFxuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEZ1bmM6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBDb2RlOiB7XG4gICAgICAgICAgICAgIFMzQnVja2V0OiB7ICdGbjo6U3ViJzogJyR7UGFyYW0xfScgfSxcbiAgICAgICAgICAgICAgUzNLZXk6ICduZXcta2V5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICAgJ2F3czphc3NldDpwYXRoJzogJ25ldy1wYXRoJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGF3YWl0IGV4cGVjdCgoKSA9PlxuICAgIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCksXG4gICkucmVqZWN0cy50b1Rocm93KC9QYXJhbWV0ZXIgb3IgcmVzb3VyY2UgJ1BhcmFtMScgY291bGQgbm90IGJlIGZvdW5kIGZvciBldmFsdWF0aW9uLyk7XG59KTtcblxudGVzdChcIndpbGwgbm90IHBlcmZvcm0gYSBob3Rzd2FwIGRlcGxveW1lbnQgaWYgaXQgZG9lc24ndCBrbm93IGhvdyB0byBoYW5kbGUgYSBzcGVjaWZpYyBhdHRyaWJ1dGUgKG91dHNpZGUgdGhlIGZ1bmN0aW9uJ3MgbmFtZSlcIiwgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzZXR1cC5zZXRDdXJyZW50Q2ZuU3RhY2tUZW1wbGF0ZSh7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICBCdWNrZXQ6IHtcbiAgICAgICAgVHlwZTogJ0FXUzo6UzM6OkJ1Y2tldCcsXG4gICAgICB9LFxuICAgICAgRnVuYzoge1xuICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgIFMzQnVja2V0OiB7ICdGbjo6R2V0QXR0JzogWydCdWNrZXQnLCAnVW5rbm93bkF0dHJpYnV0ZSddIH0sXG4gICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuICBzZXR1cC5wdXNoU3RhY2tSZXNvdXJjZVN1bW1hcmllcyhcbiAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignRnVuYycsICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCAnbXktZnVuYycpLFxuICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdCdWNrZXQnLCAnQVdTOjpTMzo6QnVja2V0JywgJ215LWJ1Y2tldCcpLFxuICApO1xuICBjb25zdCBjZGtTdGFja0FydGlmYWN0ID0gc2V0dXAuY2RrU3RhY2tBcnRpZmFjdE9mKHtcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIEJ1Y2tldDoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OlMzOjpCdWNrZXQnLFxuICAgICAgICB9LFxuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgICBTM0J1Y2tldDogeyAnRm46OkdldEF0dCc6IFsnQnVja2V0JywgJ1Vua25vd25BdHRyaWJ1dGUnXSB9LFxuICAgICAgICAgICAgICBTM0tleTogJ25ldy1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnbmV3LXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgYXdhaXQgZXhwZWN0KCgpID0+XG4gICAgaG90c3dhcE1vY2tTZGtQcm92aWRlci50cnlIb3Rzd2FwRGVwbG95bWVudChjZGtTdGFja0FydGlmYWN0KSxcbiAgKS5yZWplY3RzLnRvVGhyb3coXCJXZSBkb24ndCBzdXBwb3J0IHRoZSAnVW5rbm93bkF0dHJpYnV0ZScgYXR0cmlidXRlIG9mIHRoZSAnQVdTOjpTMzo6QnVja2V0JyByZXNvdXJjZS4gVGhpcyBpcyBhIENESyBsaW1pdGF0aW9uLiBQbGVhc2UgcmVwb3J0IGl0IGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvbmV3L2Nob29zZVwiKTtcbn0pO1xuXG50ZXN0KCdjYWxscyB0aGUgdXBkYXRlTGFtYmRhQ29kZSgpIEFQSSB3aGVuIGl0IHJlY2VpdmVzIGEgY29kZSBkaWZmZXJlbmNlIGluIGEgTGFtYmRhIGZ1bmN0aW9uIHdpdGggbm8gbmFtZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgc2V0dXAuc2V0Q3VycmVudENmblN0YWNrVGVtcGxhdGUoe1xuICAgIFJlc291cmNlczoge1xuICAgICAgRnVuYzoge1xuICAgICAgICBUeXBlOiAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgUzNLZXk6ICdjdXJyZW50LWtleScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnY3VycmVudC1wYXRoJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG4gIGNvbnN0IGNka1N0YWNrQXJ0aWZhY3QgPSBzZXR1cC5jZGtTdGFja0FydGlmYWN0T2Yoe1xuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnbmV3LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdjdXJyZW50LXBhdGgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgc2V0dXAucHVzaFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoc2V0dXAuc3RhY2tTdW1tYXJ5T2YoJ0Z1bmMnLCAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywgJ21vY2stZnVuY3Rpb24tcmVzb3VyY2UtaWQnKSk7XG4gIGNvbnN0IGRlcGxveVN0YWNrUmVzdWx0ID0gYXdhaXQgaG90c3dhcE1vY2tTZGtQcm92aWRlci50cnlIb3Rzd2FwRGVwbG95bWVudChjZGtTdGFja0FydGlmYWN0KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkubm90LnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgRnVuY3Rpb25OYW1lOiAnbW9jay1mdW5jdGlvbi1yZXNvdXJjZS1pZCcsXG4gICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgUzNLZXk6ICduZXcta2V5JyxcbiAgfSk7XG59KTtcblxudGVzdCgnZG9lcyBub3QgY2FsbCB0aGUgdXBkYXRlTGFtYmRhQ29kZSgpIEFQSSB3aGVuIGl0IHJlY2VpdmVzIGEgY2hhbmdlIHRoYXQgaXMgbm90IGEgY29kZSBkaWZmZXJlbmNlIGluIGEgTGFtYmRhIGZ1bmN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzZXR1cC5zZXRDdXJyZW50Q2ZuU3RhY2tUZW1wbGF0ZSh7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICBGdW5jOiB7XG4gICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgQ29kZToge1xuICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICBTM0tleTogJ2N1cnJlbnQta2V5JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFBhY2thZ2VUeXBlOiAnWmlwJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG4gIGNvbnN0IGNka1N0YWNrQXJ0aWZhY3QgPSBzZXR1cC5jZGtTdGFja0FydGlmYWN0T2Yoe1xuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgRnVuYzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnY3VycmVudC1rZXknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFBhY2thZ2VUeXBlOiAnSW1hZ2UnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0KS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChtb2NrVXBkYXRlTGFtYmRhQ29kZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdkb2VzIG5vdCBjYWxsIHRoZSB1cGRhdGVMYW1iZGFDb2RlKCkgQVBJIHdoZW4gYSByZXNvdXJjZSB3aXRoIHR5cGUgdGhhdCBpcyBub3QgQVdTOjpMYW1iZGE6OkZ1bmN0aW9uIGJ1dCBoYXMgdGhlIHNhbWUgcHJvcGVydGllcyBpcyBjaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzZXR1cC5zZXRDdXJyZW50Q2ZuU3RhY2tUZW1wbGF0ZSh7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICBGdW5jOiB7XG4gICAgICAgIFR5cGU6ICdBV1M6Ok5vdExhbWJkYTo6Tm90QUZ1bmN0aW9uJyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgIFMzQnVja2V0OiAnY3VycmVudC1idWNrZXQnLFxuICAgICAgICAgICAgUzNLZXk6ICdjdXJyZW50LWtleScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAnYXdzOmFzc2V0OnBhdGgnOiAnb2xkLXBhdGgnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbiAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBGdW5jOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6Tm90TGFtYmRhOjpOb3RBRnVuY3Rpb24nLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIENvZGU6IHtcbiAgICAgICAgICAgICAgUzNCdWNrZXQ6ICdjdXJyZW50LWJ1Y2tldCcsXG4gICAgICAgICAgICAgIFMzS2V5OiAnbmV3LWtleScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICdhd3M6YXNzZXQ6cGF0aCc6ICdvbGQtcGF0aCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KG1vY2tVcGRhdGVMYW1iZGFDb2RlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG4iXX0=