@aws-solutions-constructs/core 2.41.0 → 2.43.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.
@@ -0,0 +1,489 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
6
+ * with the License. A copy of the License is located at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
11
+ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
12
+ * and limitations under the License.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
16
+ // import * as defaults from '../index';
17
+ const assertions_1 = require("aws-cdk-lib/assertions");
18
+ const kendra_helper_1 = require("../lib/kendra-helper");
19
+ const kendra = require("aws-cdk-lib/aws-kendra");
20
+ const iam = require("aws-cdk-lib/aws-iam");
21
+ // import { Construct } from 'constructs';
22
+ test('Launch Kendra index with defaults', () => {
23
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
24
+ kendra_helper_1.buildKendraIndex(stack, 'test', {});
25
+ const template = assertions_1.Template.fromStack(stack);
26
+ template.hasResourceProperties('AWS::Kendra::Index', {});
27
+ template.resourceCountIs("AWS::IAM::Role", 1);
28
+ });
29
+ test('Confirm kendra has log wrting privileges', () => {
30
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
31
+ kendra_helper_1.buildKendraIndex(stack, 'test', {});
32
+ const template = assertions_1.Template.fromStack(stack);
33
+ template.hasResourceProperties("AWS::IAM::Role", {
34
+ Description: "Allow Kendra index to write CloudWatch Logs",
35
+ Policies: [
36
+ {
37
+ PolicyDocument: {
38
+ Statement: [
39
+ {
40
+ Action: "cloudwatch:PutMetricData",
41
+ Condition: {
42
+ StringEquals: {
43
+ "cloudwatch:namespace": "AWS/Kendra"
44
+ }
45
+ },
46
+ Effect: "Allow",
47
+ Resource: "*"
48
+ },
49
+ {
50
+ Action: "logs:CreateLogGroup",
51
+ Effect: "Allow",
52
+ Resource: {
53
+ "Fn::Join": [
54
+ "",
55
+ [
56
+ "arn:aws:logs:",
57
+ {
58
+ Ref: "AWS::Region"
59
+ },
60
+ ":",
61
+ {
62
+ Ref: "AWS::AccountId"
63
+ },
64
+ ":log-group:/aws/kendra/*"
65
+ ]
66
+ ]
67
+ }
68
+ },
69
+ {
70
+ Action: "logs:DescribeLogGroups",
71
+ Effect: "Allow",
72
+ Resource: {
73
+ "Fn::Join": [
74
+ "",
75
+ [
76
+ "arn:",
77
+ {
78
+ Ref: "AWS::Partition"
79
+ },
80
+ ":logs:",
81
+ {
82
+ Ref: "AWS::Region"
83
+ },
84
+ ":",
85
+ {
86
+ Ref: "AWS::AccountId"
87
+ },
88
+ ":log-group:/aws/kendra/*"
89
+ ]
90
+ ]
91
+ }
92
+ },
93
+ {
94
+ Action: [
95
+ "logs:CreateLogStream",
96
+ "logs:PutLogEvents",
97
+ "logs:DescribeLogStream"
98
+ ],
99
+ Effect: "Allow",
100
+ Resource: {
101
+ "Fn::Join": [
102
+ "",
103
+ [
104
+ "arn:",
105
+ {
106
+ Ref: "AWS::Partition"
107
+ },
108
+ ":logs:",
109
+ {
110
+ Ref: "AWS::Region"
111
+ },
112
+ ":",
113
+ {
114
+ Ref: "AWS::AccountId"
115
+ },
116
+ ":log-group:/aws/kendra/*:log-stream:*"
117
+ ]
118
+ ]
119
+ }
120
+ }
121
+ ],
122
+ Version: "2012-10-17"
123
+ },
124
+ PolicyName: "AllowLogging"
125
+ }
126
+ ],
127
+ });
128
+ });
129
+ test('Launch Kendra index with custom properties', () => {
130
+ const testName = 'test-index-name';
131
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
132
+ kendra_helper_1.buildKendraIndex(stack, 'test', {
133
+ kendraIndexProps: {
134
+ name: testName
135
+ }
136
+ });
137
+ const template = assertions_1.Template.fromStack(stack);
138
+ template.hasResourceProperties('AWS::Kendra::Index', {
139
+ Name: testName
140
+ });
141
+ template.resourceCountIs("AWS::IAM::Role", 1);
142
+ });
143
+ test('Launch Kendra index with existing role', () => {
144
+ const fakeRoleArn = 'fake-arn';
145
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
146
+ kendra_helper_1.buildKendraIndex(stack, 'test', {
147
+ kendraIndexProps: {
148
+ roleArn: fakeRoleArn
149
+ }
150
+ });
151
+ const template = assertions_1.Template.fromStack(stack);
152
+ template.hasResourceProperties('AWS::Kendra::Index', {
153
+ RoleArn: fakeRoleArn
154
+ });
155
+ template.resourceCountIs("AWS::IAM::Role", 0);
156
+ });
157
+ test('use existing Kendra index', () => {
158
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
159
+ const indexProps = {
160
+ edition: 'DEVELOPER_EDITION',
161
+ name: 'kendra-test',
162
+ roleArn: 'fake-arn'
163
+ };
164
+ const testIndex = new kendra.CfnIndex(stack, `test`, indexProps);
165
+ kendra_helper_1.buildKendraIndex(stack, 'test', {
166
+ existingIndexObj: testIndex
167
+ });
168
+ const template = assertions_1.Template.fromStack(stack);
169
+ template.resourceCountIs('AWS::Kendra::Index', 1);
170
+ });
171
+ test('Launch Kendra index with an S3 data source', () => {
172
+ const testName = 'test-name';
173
+ const testBucketName = 'test-bucket-name';
174
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
175
+ const newIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
176
+ kendra_helper_1.AddKendraDataSource(stack, 'testSource', newIndex, {
177
+ type: 'S3',
178
+ name: testName,
179
+ dataSourceConfiguration: {
180
+ s3Configuration: {
181
+ bucketName: testBucketName,
182
+ }
183
+ },
184
+ });
185
+ const template = assertions_1.Template.fromStack(stack);
186
+ template.resourceCountIs('AWS::Kendra::Index', 1);
187
+ template.resourceCountIs("AWS::Kendra::DataSource", 1);
188
+ template.resourceCountIs("AWS::IAM::Role", 2);
189
+ template.hasResourceProperties("AWS::Kendra::DataSource", {
190
+ Name: testName,
191
+ RoleArn: assertions_1.Match.anyValue(),
192
+ Type: 'S3',
193
+ DataSourceConfiguration: {
194
+ S3Configuration: {
195
+ BucketName: testBucketName
196
+ }
197
+ }
198
+ });
199
+ template.hasResourceProperties("AWS::IAM::Role", {
200
+ AssumeRolePolicyDocument: {
201
+ Statement: [
202
+ {
203
+ Action: "sts:AssumeRole",
204
+ Effect: "Allow",
205
+ Principal: {
206
+ Service: "kendra.amazonaws.com"
207
+ }
208
+ }
209
+ ],
210
+ Version: "2012-10-17"
211
+ },
212
+ Policies: [
213
+ {
214
+ PolicyDocument: {
215
+ Statement: [
216
+ {
217
+ Action: "s3:GetObject",
218
+ Effect: "Allow",
219
+ Resource: `arn:aws:s3:::${testBucketName}/*`
220
+ },
221
+ {
222
+ Action: "s3:ListBucket",
223
+ Effect: "Allow",
224
+ Resource: `arn:aws:s3:::${testBucketName}`
225
+ },
226
+ {
227
+ Action: [
228
+ "kendra:BatchPutDocument",
229
+ "kendra:BatchDeleteDocument"
230
+ ],
231
+ Effect: "Allow",
232
+ Resource: {
233
+ "Fn::GetAtt": [
234
+ "kendraindextest",
235
+ "Arn"
236
+ ]
237
+ }
238
+ }
239
+ ],
240
+ Version: "2012-10-17"
241
+ },
242
+ PolicyName: "s3CrawlPolicy"
243
+ }
244
+ ]
245
+ });
246
+ });
247
+ test('Launch Kendra index with a customized S3 data source', () => {
248
+ const testName = 'test-name';
249
+ const testBucketName = 'test-bucket-name';
250
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
251
+ const newIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
252
+ kendra_helper_1.AddKendraDataSource(stack, 'testSource', newIndex, {
253
+ type: 'S3',
254
+ name: testName,
255
+ dataSourceConfiguration: {
256
+ s3Configuration: {
257
+ bucketName: testBucketName,
258
+ inclusionPatterns: ['IncludeThis'],
259
+ }
260
+ },
261
+ });
262
+ const template = assertions_1.Template.fromStack(stack);
263
+ template.hasResourceProperties("AWS::Kendra::DataSource", {
264
+ DataSourceConfiguration: {
265
+ S3Configuration: {
266
+ BucketName: "test-bucket-name",
267
+ InclusionPatterns: ['IncludeThis'],
268
+ }
269
+ },
270
+ });
271
+ template.resourceCountIs('AWS::Kendra::Index', 1);
272
+ template.resourceCountIs("AWS::Kendra::DataSource", 1);
273
+ template.resourceCountIs("AWS::IAM::Role", 2);
274
+ });
275
+ test('Launch Kendra index with non-implemented data source', () => {
276
+ const nonImplementedSourceType = "WEBCRAWLER";
277
+ const nonImplementedSourceName = "test-other-source";
278
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
279
+ const testIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
280
+ // Create a role
281
+ const fakeRole = new iam.Role(stack, 'fakeRole', {
282
+ assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'),
283
+ roleName: 'externalFakeRole'
284
+ });
285
+ // Create data source props
286
+ const dataSourceProps = {
287
+ name: nonImplementedSourceName,
288
+ roleArn: fakeRole.roleArn,
289
+ type: nonImplementedSourceType,
290
+ };
291
+ // Add a data source
292
+ kendra_helper_1.AddKendraDataSource(stack, 'test-other-source', testIndex, dataSourceProps);
293
+ const template = assertions_1.Template.fromStack(stack);
294
+ template.resourceCountIs('AWS::Kendra::Index', 1);
295
+ template.resourceCountIs('AWS::Kendra::DataSource', 1);
296
+ template.resourceCountIs('AWS::IAM::Role', 2);
297
+ template.hasResourceProperties("AWS::Kendra::DataSource", {
298
+ Name: nonImplementedSourceName,
299
+ Type: nonImplementedSourceType
300
+ });
301
+ });
302
+ test('Confirm error if client supplies an index in the DataSource props', () => {
303
+ const nonImplementedSourceType = "WEBCRAWLER";
304
+ const nonImplementedSourceName = "test-other-source";
305
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
306
+ const testIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
307
+ // Create a role
308
+ const fakeRole = new iam.Role(stack, 'fakeRole', {
309
+ assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'),
310
+ roleName: 'externalFakeRole'
311
+ });
312
+ // Create data source props
313
+ const dataSourceProps = {
314
+ name: nonImplementedSourceName,
315
+ roleArn: fakeRole.roleArn,
316
+ type: nonImplementedSourceType,
317
+ indexId: testIndex.attrId,
318
+ };
319
+ // Add a data source
320
+ const app = () => {
321
+ kendra_helper_1.AddKendraDataSource(stack, 'test-other-source', testIndex, dataSourceProps);
322
+ };
323
+ expect(app).toThrowError(/Invalid DataSource prop specified - Construct must set the indexId prop/);
324
+ });
325
+ test('Confirm error if does not provide DataSource configuration', () => {
326
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
327
+ const testIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
328
+ // Create data source props
329
+ const dataSourceProps = {
330
+ type: "S3"
331
+ };
332
+ // Add a data source
333
+ const app = () => {
334
+ kendra_helper_1.AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps);
335
+ };
336
+ expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceCofiguration prop/);
337
+ });
338
+ test('Confirm error if does not provide S3 DataSource configuration', () => {
339
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
340
+ const testIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
341
+ // Create data source props
342
+ const dataSourceProps = {
343
+ type: "S3",
344
+ dataSourceConfiguration: {}
345
+ };
346
+ // Add a data source
347
+ const app = () => {
348
+ kendra_helper_1.AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps);
349
+ };
350
+ expect(app).toThrowError(/Error - an S3 Kendra DataSource requires an DataSourceCofiguration.S3Configuration prop/);
351
+ });
352
+ test('Confirm error if does not provide S3 Bucketname', () => {
353
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
354
+ const testIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
355
+ // Create data source props
356
+ const dataSourceProps = {
357
+ type: "S3",
358
+ dataSourceConfiguration: {
359
+ s3Configuration: {
360
+ // Going through some hoops here to force this conditiion, but since we
361
+ // allow | any for props, a client could do this
362
+ }
363
+ }
364
+ };
365
+ // Add a data source
366
+ const app = () => {
367
+ kendra_helper_1.AddKendraDataSource(stack, 'test-bad-source', testIndex, dataSourceProps);
368
+ };
369
+ expect(app).toThrowError(/Error - an S3 Kendra DataSource requires the DataSourceCofiguration.S3Configuration.bucketName prop/);
370
+ });
371
+ test('Launch Kendra index with multiple data sources', () => {
372
+ const testName = 'test-name';
373
+ const testBucketName = 'test-bucket-name';
374
+ const nonImplementedSourceType = "WEBCRAWLER";
375
+ const nonImplementedSourceName = "test-other-source";
376
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined);
377
+ const newIndex = kendra_helper_1.buildKendraIndex(stack, 'test', {});
378
+ const s3DataSourceProps = {
379
+ type: 'S3',
380
+ name: testName,
381
+ dataSourceConfiguration: {
382
+ s3Configuration: {
383
+ bucketName: testBucketName,
384
+ }
385
+ },
386
+ };
387
+ // Create a role
388
+ const fakeRole = new iam.Role(stack, 'fakeRole', {
389
+ assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'),
390
+ roleName: 'externalFakeRole'
391
+ });
392
+ // Create data source props
393
+ const otherDataSourceProps = {
394
+ name: nonImplementedSourceName,
395
+ roleArn: fakeRole.roleArn,
396
+ type: nonImplementedSourceType
397
+ };
398
+ // Add a data source
399
+ const sourceObjects = kendra_helper_1.AddMultipleKendraDataSources(stack, 'test-other-source', newIndex, [
400
+ s3DataSourceProps,
401
+ otherDataSourceProps
402
+ ]);
403
+ expect(sourceObjects.length).toEqual(2);
404
+ expect(sourceObjects[0].type).toEqual('S3');
405
+ expect(sourceObjects[1].name).toEqual(nonImplementedSourceName);
406
+ const template = assertions_1.Template.fromStack(stack);
407
+ template.resourceCountIs('AWS::Kendra::Index', 1);
408
+ template.resourceCountIs('AWS::Kendra::DataSource', 2);
409
+ template.resourceCountIs('AWS::IAM::Role', 3);
410
+ // Look for S3 data source
411
+ template.hasResourceProperties("AWS::Kendra::DataSource", {
412
+ Name: testName,
413
+ RoleArn: assertions_1.Match.anyValue(),
414
+ Type: 'S3',
415
+ DataSourceConfiguration: {
416
+ S3Configuration: {
417
+ BucketName: testBucketName
418
+ }
419
+ }
420
+ });
421
+ template.hasResourceProperties("AWS::IAM::Role", {
422
+ AssumeRolePolicyDocument: {
423
+ Statement: [
424
+ {
425
+ Action: "sts:AssumeRole",
426
+ Effect: "Allow",
427
+ Principal: {
428
+ Service: "kendra.amazonaws.com"
429
+ }
430
+ }
431
+ ],
432
+ Version: "2012-10-17"
433
+ },
434
+ Policies: [
435
+ {
436
+ PolicyDocument: {
437
+ Statement: [
438
+ {
439
+ Action: "s3:GetObject",
440
+ Effect: "Allow",
441
+ Resource: `arn:aws:s3:::${testBucketName}/*`
442
+ },
443
+ {
444
+ Action: "s3:ListBucket",
445
+ Effect: "Allow",
446
+ Resource: `arn:aws:s3:::${testBucketName}`
447
+ },
448
+ {
449
+ Action: [
450
+ "kendra:BatchPutDocument",
451
+ "kendra:BatchDeleteDocument"
452
+ ],
453
+ Effect: "Allow",
454
+ Resource: {
455
+ "Fn::GetAtt": [
456
+ "kendraindextest",
457
+ "Arn"
458
+ ]
459
+ }
460
+ }
461
+ ],
462
+ Version: "2012-10-17"
463
+ },
464
+ PolicyName: "s3CrawlPolicy"
465
+ }
466
+ ]
467
+ });
468
+ // Look for non-implemented data source
469
+ template.hasResourceProperties("AWS::Kendra::DataSource", {
470
+ Name: nonImplementedSourceName,
471
+ Type: nonImplementedSourceType,
472
+ IndexId: assertions_1.Match.anyValue()
473
+ });
474
+ });
475
+ test('Confirm Errof for bad kendra Permission in normalizeKendraPermissions()', () => {
476
+ const inputs = ["read", "submitfeedback", "write"];
477
+ const outputs = kendra_helper_1.normalizeKendraPermissions(inputs);
478
+ expect(outputs.includes("READ")).toBeTruthy();
479
+ expect(outputs.includes("SUBMITFEEDBACK")).toBeTruthy();
480
+ expect(outputs.includes("WRITE")).toBeTruthy();
481
+ });
482
+ test('Confirm successful operation of normalizeKendraPermissions()', () => {
483
+ const inputs = ["badvalue", "write"];
484
+ const app = () => {
485
+ kendra_helper_1.normalizeKendraPermissions(inputs);
486
+ };
487
+ expect(app).toThrowError(/Invalid indexPermission value - valid values are "READ", "SUBMITFEEDBACK" and "WRITE"/);
488
+ });
489
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2VuZHJhLWhlbHBlci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsia2VuZHJhLWhlbHBlci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7R0FXRzs7QUFFSCw2Q0FBb0M7QUFDcEMsd0NBQXdDO0FBQ3hDLHVEQUF5RDtBQUN6RCx3REFBdUk7QUFDdkksaURBQWlEO0FBQ2pELDJDQUEyQztBQUUzQywwQ0FBMEM7QUFFMUMsSUFBSSxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsRUFBRTtJQUM3QyxNQUFNLEtBQUssR0FBRyxJQUFJLG1CQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBRTlDLGdDQUFnQixDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFcEMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELFFBQVEsQ0FBQyxlQUFlLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDaEQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsMENBQTBDLEVBQUUsR0FBRyxFQUFFO0lBQ3BELE1BQU0sS0FBSyxHQUFHLElBQUksbUJBQUssQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFFOUMsZ0NBQWdCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUVwQyxNQUFNLFFBQVEsR0FBRyxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQyxRQUFRLENBQUMscUJBQXFCLENBQUMsZ0JBQWdCLEVBQUU7UUFDL0MsV0FBVyxFQUFFLDZDQUE2QztRQUMxRCxRQUFRLEVBQUU7WUFDUjtnQkFDRSxjQUFjLEVBQUU7b0JBQ2QsU0FBUyxFQUFFO3dCQUNU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LENBQUM7QUFDcEgsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbi8vIGltcG9ydCAqIGFzIGRlZmF1bHRzIGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IE1hdGNoLCBUZW1wbGF0ZSB9IGZyb20gJ2F3cy1jZGstbGliL2Fzc2VydGlvbnMnO1xuaW1wb3J0IHsgYnVpbGRLZW5kcmFJbmRleCwgQWRkS2VuZHJhRGF0YVNvdXJjZSwgQWRkTXVsdGlwbGVLZW5kcmFEYXRhU291cmNlcywgbm9ybWFsaXplS2VuZHJhUGVybWlzc2lvbnMgfSBmcm9tICcuLi9saWIva2VuZHJhLWhlbHBlcic7XG5pbXBvcnQgKiBhcyBrZW5kcmEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWtlbmRyYSc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5cbi8vIGltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG50ZXN0KCdMYXVuY2ggS2VuZHJhIGluZGV4IHdpdGggZGVmYXVsdHMnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcblxuICBidWlsZEtlbmRyYUluZGV4KHN0YWNrLCAndGVzdCcsIHt9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpLZW5kcmE6OkluZGV4Jywge30pO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OklBTTo6Um9sZVwiLCAxKTtcbn0pO1xuXG50ZXN0KCdDb25maXJtIGtlbmRyYSBoYXMgbG9nIHdydGluZyBwcml2aWxlZ2VzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG5cbiAgYnVpbGRLZW5kcmFJbmRleChzdGFjaywgJ3Rlc3QnLCB7fSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OklBTTo6Um9sZVwiLCB7XG4gICAgRGVzY3JpcHRpb246IFwiQWxsb3cgS2VuZHJhIGluZGV4IHRvIHdyaXRlIENsb3VkV2F0Y2ggTG9nc1wiLFxuICAgIFBvbGljaWVzOiBbXG4gICAgICB7XG4gICAgICAgIFBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIEFjdGlvbjogXCJjbG91ZHdhdGNoOlB1dE1ldHJpY0RhdGFcIixcbiAgICAgICAgICAgICAgQ29uZGl0aW9uOiB7XG4gICAgICAgICAgICAgICAgU3RyaW5nRXF1YWxzOiB7XG4gICAgICAgICAgICAgICAgICBcImNsb3Vkd2F0Y2g6bmFtZXNwYWNlXCI6IFwiQVdTL0tlbmRyYVwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IFwiKlwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBBY3Rpb246IFwibG9nczpDcmVhdGVMb2dHcm91cFwiLFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgICAgIFwiXCIsXG4gICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIFwiYXJuOmF3czpsb2dzOlwiLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UmVnaW9uXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6XCIsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBSZWY6IFwiQVdTOjpBY2NvdW50SWRcIlxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBcIjpsb2ctZ3JvdXA6L2F3cy9rZW5kcmEvKlwiXG4gICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBBY3Rpb246IFwibG9nczpEZXNjcmliZUxvZ0dyb3Vwc1wiLFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgICAgIFwiXCIsXG4gICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIFwiYXJuOlwiLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UGFydGl0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6bG9nczpcIixcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlJlZ2lvblwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiOlwiLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6QWNjb3VudElkXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6bG9nLWdyb3VwOi9hd3Mva2VuZHJhLypcIlxuICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgQWN0aW9uOiBbXG4gICAgICAgICAgICAgICAgXCJsb2dzOkNyZWF0ZUxvZ1N0cmVhbVwiLFxuICAgICAgICAgICAgICAgIFwibG9nczpQdXRMb2dFdmVudHNcIixcbiAgICAgICAgICAgICAgICBcImxvZ3M6RGVzY3JpYmVMb2dTdHJlYW1cIlxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgICAgIFwiXCIsXG4gICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIFwiYXJuOlwiLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UGFydGl0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6bG9nczpcIixcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlJlZ2lvblwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiOlwiLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6QWNjb3VudElkXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6bG9nLWdyb3VwOi9hd3Mva2VuZHJhLyo6bG9nLXN0cmVhbToqXCJcbiAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICBdLFxuICAgICAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgICAgIH0sXG4gICAgICAgIFBvbGljeU5hbWU6IFwiQWxsb3dMb2dnaW5nXCJcbiAgICAgIH1cbiAgICBdLFxuICB9KTtcbn0pO1xuXG50ZXN0KCdMYXVuY2ggS2VuZHJhIGluZGV4IHdpdGggY3VzdG9tIHByb3BlcnRpZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ3Rlc3QtaW5kZXgtbmFtZSc7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcblxuICBidWlsZEtlbmRyYUluZGV4KHN0YWNrLCAndGVzdCcsIHtcbiAgICBrZW5kcmFJbmRleFByb3BzOiB7XG4gICAgICBuYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6S2VuZHJhOjpJbmRleCcsIHtcbiAgICBOYW1lOiB0ZXN0TmFtZVxuICB9KTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpJQU06OlJvbGVcIiwgMSk7XG59KTtcblxudGVzdCgnTGF1bmNoIEtlbmRyYSBpbmRleCB3aXRoIGV4aXN0aW5nIHJvbGUnLCAoKSA9PiB7XG4gIGNvbnN0IGZha2VSb2xlQXJuID0gJ2Zha2UtYXJuJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuXG4gIGJ1aWxkS2VuZHJhSW5kZXgoc3RhY2ssICd0ZXN0Jywge1xuICAgIGtlbmRyYUluZGV4UHJvcHM6IHtcbiAgICAgIHJvbGVBcm46IGZha2VSb2xlQXJuXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpLZW5kcmE6OkluZGV4Jywge1xuICAgIFJvbGVBcm46IGZha2VSb2xlQXJuXG4gIH0pO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OklBTTo6Um9sZVwiLCAwKTtcbn0pO1xuXG50ZXN0KCd1c2UgZXhpc3RpbmcgS2VuZHJhIGluZGV4JywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG5cbiAgY29uc3QgaW5kZXhQcm9wczoga2VuZHJhLkNmbkluZGV4UHJvcHMgPSB7XG4gICAgZWRpdGlvbjogJ0RFVkVMT1BFUl9FRElUSU9OJyxcbiAgICBuYW1lOiAna2VuZHJhLXRlc3QnLFxuICAgIHJvbGVBcm46ICdmYWtlLWFybidcbiAgfTtcblxuICBjb25zdCB0ZXN0SW5kZXggPSBuZXcga2VuZHJhLkNmbkluZGV4KHN0YWNrLCBgdGVzdGAsIGluZGV4UHJvcHMpO1xuXG4gIGJ1aWxkS2VuZHJhSW5kZXgoc3RhY2ssICd0ZXN0Jywge1xuICAgIGV4aXN0aW5nSW5kZXhPYmo6IHRlc3RJbmRleFxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpLZW5kcmE6OkluZGV4JywgMSk7XG59KTtcblxudGVzdCgnTGF1bmNoIEtlbmRyYSBpbmRleCB3aXRoIGFuIFMzIGRhdGEgc291cmNlJywgKCkgPT4ge1xuICBjb25zdCB0ZXN0TmFtZSA9ICd0ZXN0LW5hbWUnO1xuICBjb25zdCB0ZXN0QnVja2V0TmFtZSA9ICd0ZXN0LWJ1Y2tldC1uYW1lJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuXG4gIGNvbnN0IG5ld0luZGV4ID0gYnVpbGRLZW5kcmFJbmRleChzdGFjaywgJ3Rlc3QnLCB7fSk7XG5cbiAgQWRkS2VuZHJhRGF0YVNvdXJjZShzdGFjaywgJ3Rlc3RTb3VyY2UnLCBuZXdJbmRleCwge1xuICAgIHR5cGU6ICdTMycsXG4gICAgbmFtZTogdGVzdE5hbWUsXG4gICAgZGF0YVNvdXJjZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIHMzQ29uZmlndXJhdGlvbjoge1xuICAgICAgICBidWNrZXROYW1lOiB0ZXN0QnVja2V0TmFtZSxcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpLZW5kcmE6OkluZGV4JywgMSk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6S2VuZHJhOjpEYXRhU291cmNlXCIsIDEpO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OklBTTo6Um9sZVwiLCAyKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpLZW5kcmE6OkRhdGFTb3VyY2VcIiwge1xuICAgIE5hbWU6IHRlc3ROYW1lLFxuICAgIFJvbGVBcm46IE1hdGNoLmFueVZhbHVlKCksXG4gICAgVHlwZTogJ1MzJyxcbiAgICBEYXRhU291cmNlQ29uZmlndXJhdGlvbjoge1xuICAgICAgUzNDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIEJ1Y2tldE5hbWU6IHRlc3RCdWNrZXROYW1lXG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpJQU06OlJvbGVcIiwge1xuICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudDoge1xuICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBBY3Rpb246IFwic3RzOkFzc3VtZVJvbGVcIixcbiAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIFNlcnZpY2U6IFwia2VuZHJhLmFtYXpvbmF3cy5jb21cIlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgfSxcbiAgICBQb2xpY2llczogW1xuICAgICAge1xuICAgICAgICBQb2xpY3lEb2N1bWVudDoge1xuICAgICAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBBY3Rpb246IFwiczM6R2V0T2JqZWN0XCIsXG4gICAgICAgICAgICAgIEVmZmVjdDogXCJBbGxvd1wiLFxuICAgICAgICAgICAgICBSZXNvdXJjZTogYGFybjphd3M6czM6Ojoke3Rlc3RCdWNrZXROYW1lfS8qYFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgQWN0aW9uOiBcInMzOkxpc3RCdWNrZXRcIixcbiAgICAgICAgICAgICAgRWZmZWN0OiBcIkFsbG93XCIsXG4gICAgICAgICAgICAgIFJlc291cmNlOiBgYXJuOmF3czpzMzo6OiR7dGVzdEJ1Y2tldE5hbWV9YFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgQWN0aW9uOiBbXG4gICAgICAgICAgICAgICAgXCJrZW5kcmE6QmF0Y2hQdXREb2N1bWVudFwiLFxuICAgICAgICAgICAgICAgIFwia2VuZHJhOkJhdGNoRGVsZXRlRG9jdW1lbnRcIlxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgICAgICAgICAgXCJrZW5kcmFpbmRleHRlc3RcIixcbiAgICAgICAgICAgICAgICAgIFwiQXJuXCJcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICBdLFxuICAgICAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgICAgIH0sXG4gICAgICAgIFBvbGljeU5hbWU6IFwiczNDcmF3bFBvbGljeVwiXG4gICAgICB9XG4gICAgXVxuICB9KTtcbn0pO1xuXG50ZXN0KCdMYXVuY2ggS2VuZHJhIGluZGV4IHdpdGggYSBjdXN0b21pemVkIFMzIGRhdGEgc291cmNlJywgKCkgPT4ge1xuICBjb25zdCB0ZXN0TmFtZSA9ICd0ZXN0LW5hbWUnO1xuICBjb25zdCB0ZXN0QnVja2V0TmFtZSA9ICd0ZXN0LWJ1Y2tldC1uYW1lJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuXG4gIGNvbnN0IG5ld0luZGV4ID0gYnVpbGRLZW5kcmFJbmRleChzdGFjaywgJ3Rlc3QnLCB7fSk7XG5cbiAgQWRkS2VuZHJhRGF0YVNvdXJjZShzdGFjaywgJ3Rlc3RTb3VyY2UnLCBuZXdJbmRleCwge1xuICAgIHR5cGU6ICdTMycsXG4gICAgbmFtZTogdGVzdE5hbWUsXG4gICAgZGF0YVNvdXJjZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIHMzQ29uZmlndXJhdGlvbjoge1xuICAgICAgICBidWNrZXROYW1lOiB0ZXN0QnVja2V0TmFtZSxcbiAgICAgICAgaW5jbHVzaW9uUGF0dGVybnM6IFsnSW5jbHVkZVRoaXMnXSxcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6S2VuZHJhOjpEYXRhU291cmNlXCIsIHtcbiAgICBEYXRhU291cmNlQ29uZmlndXJhdGlvbjoge1xuICAgICAgUzNDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIEJ1Y2tldE5hbWU6IFwidGVzdC1idWNrZXQtbmFtZVwiLFxuICAgICAgICBJbmNsdXNpb25QYXR0ZXJuczogWydJbmNsdWRlVGhpcyddLFxuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6S2VuZHJhOjpJbmRleCcsIDEpO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OktlbmRyYTo6RGF0YVNvdXJjZVwiLCAxKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpJQU06OlJvbGVcIiwgMik7XG59KTtcblxudGVzdCgnTGF1bmNoIEtlbmRyYSBpbmRleCB3aXRoIG5vbi1pbXBsZW1lbnRlZCBkYXRhIHNvdXJjZScsICgpID0+IHtcbiAgY29uc3Qgbm9uSW1wbGVtZW50ZWRTb3VyY2VUeXBlID0gXCJXRUJDUkFXTEVSXCI7XG4gIGNvbnN0IG5vbkltcGxlbWVudGVkU291cmNlTmFtZSA9IFwidGVzdC1vdGhlci1zb3VyY2VcIjtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuICBjb25zdCB0ZXN0SW5kZXggPSBidWlsZEtlbmRyYUluZGV4KHN0YWNrLCAndGVzdCcsIHt9KTtcblxuICAvLyBDcmVhdGUgYSByb2xlXG4gIGNvbnN0IGZha2VSb2xlID0gbmV3IGlhbS5Sb2xlKHN0YWNrLCAnZmFrZVJvbGUnLCB7XG4gICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2tlbmRyYS5hbWF6b25hd3MuY29tJyksXG4gICAgcm9sZU5hbWU6ICdleHRlcm5hbEZha2VSb2xlJ1xuICB9KTtcblxuICAvLyBDcmVhdGUgZGF0YSBzb3VyY2UgcHJvcHNcbiAgY29uc3QgZGF0YVNvdXJjZVByb3BzOiBQYXJ0aWFsPGtlbmRyYS5DZm5EYXRhU291cmNlUHJvcHM+ID0ge1xuICAgIG5hbWU6IG5vbkltcGxlbWVudGVkU291cmNlTmFtZSxcbiAgICByb2xlQXJuOiBmYWtlUm9sZS5yb2xlQXJuLFxuICAgIHR5cGU6IG5vbkltcGxlbWVudGVkU291cmNlVHlwZSxcbiAgfTtcblxuICAvLyBBZGQgYSBkYXRhIHNvdXJjZVxuICBBZGRLZW5kcmFEYXRhU291cmNlKHN0YWNrLCAndGVzdC1vdGhlci1zb3VyY2UnLCB0ZXN0SW5kZXgsIGRhdGFTb3VyY2VQcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6S2VuZHJhOjpJbmRleCcsIDEpO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6S2VuZHJhOjpEYXRhU291cmNlJywgMSk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpJQU06OlJvbGUnLCAyKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpLZW5kcmE6OkRhdGFTb3VyY2VcIiwge1xuICAgIE5hbWU6IG5vbkltcGxlbWVudGVkU291cmNlTmFtZSxcbiAgICBUeXBlOiBub25JbXBsZW1lbnRlZFNvdXJjZVR5cGVcbiAgfSk7XG59KTtcblxudGVzdCgnQ29uZmlybSBlcnJvciBpZiBjbGllbnQgc3VwcGxpZXMgYW4gaW5kZXggaW4gdGhlIERhdGFTb3VyY2UgcHJvcHMnLCAoKSA9PiB7XG4gIGNvbnN0IG5vbkltcGxlbWVudGVkU291cmNlVHlwZSA9IFwiV0VCQ1JBV0xFUlwiO1xuICBjb25zdCBub25JbXBsZW1lbnRlZFNvdXJjZU5hbWUgPSBcInRlc3Qtb3RoZXItc291cmNlXCI7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbiAgY29uc3QgdGVzdEluZGV4ID0gYnVpbGRLZW5kcmFJbmRleChzdGFjaywgJ3Rlc3QnLCB7fSk7XG5cbiAgLy8gQ3JlYXRlIGEgcm9sZVxuICBjb25zdCBmYWtlUm9sZSA9IG5ldyBpYW0uUm9sZShzdGFjaywgJ2Zha2VSb2xlJywge1xuICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdrZW5kcmEuYW1hem9uYXdzLmNvbScpLFxuICAgIHJvbGVOYW1lOiAnZXh0ZXJuYWxGYWtlUm9sZSdcbiAgfSk7XG5cbiAgLy8gQ3JlYXRlIGRhdGEgc291cmNlIHByb3BzXG4gIGNvbnN0IGRhdGFTb3VyY2VQcm9wczogUGFydGlhbDxrZW5kcmEuQ2ZuRGF0YVNvdXJjZVByb3BzPiA9IHtcbiAgICBuYW1lOiBub25JbXBsZW1lbnRlZFNvdXJjZU5hbWUsXG4gICAgcm9sZUFybjogZmFrZVJvbGUucm9sZUFybixcbiAgICB0eXBlOiBub25JbXBsZW1lbnRlZFNvdXJjZVR5cGUsXG4gICAgaW5kZXhJZDogdGVzdEluZGV4LmF0dHJJZCxcbiAgfTtcblxuICAvLyBBZGQgYSBkYXRhIHNvdXJjZVxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgQWRkS2VuZHJhRGF0YVNvdXJjZShzdGFjaywgJ3Rlc3Qtb3RoZXItc291cmNlJywgdGVzdEluZGV4LCBkYXRhU291cmNlUHJvcHMpO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvSW52YWxpZCBEYXRhU291cmNlIHByb3Agc3BlY2lmaWVkIC0gQ29uc3RydWN0IG11c3Qgc2V0IHRoZSBpbmRleElkIHByb3AvKTtcbn0pO1xuXG50ZXN0KCdDb25maXJtIGVycm9yIGlmIGRvZXMgbm90IHByb3ZpZGUgRGF0YVNvdXJjZSBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gIGNvbnN0IHRlc3RJbmRleCA9IGJ1aWxkS2VuZHJhSW5kZXgoc3RhY2ssICd0ZXN0Jywge30pO1xuXG4gIC8vIENyZWF0ZSBkYXRhIHNvdXJjZSBwcm9wc1xuICBjb25zdCBkYXRhU291cmNlUHJvcHM6IFBhcnRpYWw8a2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcz4gPSB7XG4gICAgdHlwZTogXCJTM1wiXG4gIH07XG5cbiAgLy8gQWRkIGEgZGF0YSBzb3VyY2VcbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIEFkZEtlbmRyYURhdGFTb3VyY2Uoc3RhY2ssICd0ZXN0LWJhZC1zb3VyY2UnLCB0ZXN0SW5kZXgsIGRhdGFTb3VyY2VQcm9wcyk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKC9FcnJvciAtIGFuIFMzIEtlbmRyYSBEYXRhU291cmNlIHJlcXVpcmVzIGFuIERhdGFTb3VyY2VDb2ZpZ3VyYXRpb24gcHJvcC8pO1xufSk7XG5cbnRlc3QoJ0NvbmZpcm0gZXJyb3IgaWYgZG9lcyBub3QgcHJvdmlkZSBTMyBEYXRhU291cmNlIGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbiAgY29uc3QgdGVzdEluZGV4ID0gYnVpbGRLZW5kcmFJbmRleChzdGFjaywgJ3Rlc3QnLCB7fSk7XG5cbiAgLy8gQ3JlYXRlIGRhdGEgc291cmNlIHByb3BzXG4gIGNvbnN0IGRhdGFTb3VyY2VQcm9wczogUGFydGlhbDxrZW5kcmEuQ2ZuRGF0YVNvdXJjZVByb3BzPiA9IHtcbiAgICB0eXBlOiBcIlMzXCIsXG4gICAgZGF0YVNvdXJjZUNvbmZpZ3VyYXRpb246IHtcblxuICAgIH1cbiAgfTtcblxuICAvLyBBZGQgYSBkYXRhIHNvdXJjZVxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgQWRkS2VuZHJhRGF0YVNvdXJjZShzdGFjaywgJ3Rlc3QtYmFkLXNvdXJjZScsIHRlc3RJbmRleCwgZGF0YVNvdXJjZVByb3BzKTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gYW4gUzMgS2VuZHJhIERhdGFTb3VyY2UgcmVxdWlyZXMgYW4gRGF0YVNvdXJjZUNvZmlndXJhdGlvbi5TM0NvbmZpZ3VyYXRpb24gcHJvcC8pO1xufSk7XG5cbnRlc3QoJ0NvbmZpcm0gZXJyb3IgaWYgZG9lcyBub3QgcHJvdmlkZSBTMyBCdWNrZXRuYW1lJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gIGNvbnN0IHRlc3RJbmRleCA9IGJ1aWxkS2VuZHJhSW5kZXgoc3RhY2ssICd0ZXN0Jywge30pO1xuXG4gIC8vIENyZWF0ZSBkYXRhIHNvdXJjZSBwcm9wc1xuICBjb25zdCBkYXRhU291cmNlUHJvcHM6IFBhcnRpYWw8a2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcz4gPSB7XG4gICAgdHlwZTogXCJTM1wiLFxuICAgIGRhdGFTb3VyY2VDb25maWd1cmF0aW9uOiB7XG4gICAgICBzM0NvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgLy8gR29pbmcgdGhyb3VnaCBzb21lIGhvb3BzIGhlcmUgdG8gZm9yY2UgdGhpcyBjb25kaXRpaW9uLCBidXQgc2luY2Ugd2VcbiAgICAgICAgLy8gYWxsb3cgfCBhbnkgZm9yIHByb3BzLCBhIGNsaWVudCBjb3VsZCBkbyB0aGlzXG4gICAgICB9IGFzIGtlbmRyYS5DZm5EYXRhU291cmNlLlMzRGF0YVNvdXJjZUNvbmZpZ3VyYXRpb25Qcm9wZXJ0eVxuICAgIH1cbiAgfTtcblxuICAvLyBBZGQgYSBkYXRhIHNvdXJjZVxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgQWRkS2VuZHJhRGF0YVNvdXJjZShzdGFjaywgJ3Rlc3QtYmFkLXNvdXJjZScsIHRlc3RJbmRleCwgZGF0YVNvdXJjZVByb3BzKTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gYW4gUzMgS2VuZHJhIERhdGFTb3VyY2UgcmVxdWlyZXMgdGhlIERhdGFTb3VyY2VDb2ZpZ3VyYXRpb24uUzNDb25maWd1cmF0aW9uLmJ1Y2tldE5hbWUgcHJvcC8pO1xufSk7XG5cbnRlc3QoJ0xhdW5jaCBLZW5kcmEgaW5kZXggd2l0aCBtdWx0aXBsZSBkYXRhIHNvdXJjZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ3Rlc3QtbmFtZSc7XG4gIGNvbnN0IHRlc3RCdWNrZXROYW1lID0gJ3Rlc3QtYnVja2V0LW5hbWUnO1xuICBjb25zdCBub25JbXBsZW1lbnRlZFNvdXJjZVR5cGUgPSBcIldFQkNSQVdMRVJcIjtcbiAgY29uc3Qgbm9uSW1wbGVtZW50ZWRTb3VyY2VOYW1lID0gXCJ0ZXN0LW90aGVyLXNvdXJjZVwiO1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG5cbiAgY29uc3QgbmV3SW5kZXggPSBidWlsZEtlbmRyYUluZGV4KHN0YWNrLCAndGVzdCcsIHt9KTtcblxuICBjb25zdCBzM0RhdGFTb3VyY2VQcm9wcyA9IHtcbiAgICB0eXBlOiAnUzMnLFxuICAgIG5hbWU6IHRlc3ROYW1lLFxuICAgIGRhdGFTb3VyY2VDb25maWd1cmF0aW9uOiB7XG4gICAgICBzM0NvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgYnVja2V0TmFtZTogdGVzdEJ1Y2tldE5hbWUsXG4gICAgICB9XG4gICAgfSxcbiAgfTtcblxuICAvLyBDcmVhdGUgYSByb2xlXG4gIGNvbnN0IGZha2VSb2xlID0gbmV3IGlhbS5Sb2xlKHN0YWNrLCAnZmFrZVJvbGUnLCB7XG4gICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2tlbmRyYS5hbWF6b25hd3MuY29tJyksXG4gICAgcm9sZU5hbWU6ICdleHRlcm5hbEZha2VSb2xlJ1xuICB9KTtcblxuICAvLyBDcmVhdGUgZGF0YSBzb3VyY2UgcHJvcHNcbiAgY29uc3Qgb3RoZXJEYXRhU291cmNlUHJvcHM6IFBhcnRpYWw8a2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcz4gPSB7XG4gICAgbmFtZTogbm9uSW1wbGVtZW50ZWRTb3VyY2VOYW1lLFxuICAgIHJvbGVBcm46IGZha2VSb2xlLnJvbGVBcm4sXG4gICAgdHlwZTogbm9uSW1wbGVtZW50ZWRTb3VyY2VUeXBlXG4gIH07XG5cbiAgLy8gQWRkIGEgZGF0YSBzb3VyY2VcbiAgY29uc3Qgc291cmNlT2JqZWN0cyA9IEFkZE11bHRpcGxlS2VuZHJhRGF0YVNvdXJjZXMoc3RhY2ssICd0ZXN0LW90aGVyLXNvdXJjZScsIG5ld0luZGV4LCBbXG4gICAgczNEYXRhU291cmNlUHJvcHMsXG4gICAgb3RoZXJEYXRhU291cmNlUHJvcHNcbiAgXVxuICApO1xuXG4gIGV4cGVjdChzb3VyY2VPYmplY3RzLmxlbmd0aCkudG9FcXVhbCgyKTtcbiAgZXhwZWN0KHNvdXJjZU9iamVjdHNbMF0udHlwZSkudG9FcXVhbCgnUzMnKTtcbiAgZXhwZWN0KHNvdXJjZU9iamVjdHNbMV0ubmFtZSkudG9FcXVhbChub25JbXBsZW1lbnRlZFNvdXJjZU5hbWUpO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OktlbmRyYTo6SW5kZXgnLCAxKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OktlbmRyYTo6RGF0YVNvdXJjZScsIDIpO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6SUFNOjpSb2xlJywgMyk7XG5cbiAgLy8gTG9vayBmb3IgUzMgZGF0YSBzb3VyY2VcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpLZW5kcmE6OkRhdGFTb3VyY2VcIiwge1xuICAgIE5hbWU6IHRlc3ROYW1lLFxuICAgIFJvbGVBcm46IE1hdGNoLmFueVZhbHVlKCksXG4gICAgVHlwZTogJ1MzJyxcbiAgICBEYXRhU291cmNlQ29uZmlndXJhdGlvbjoge1xuICAgICAgUzNDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIEJ1Y2tldE5hbWU6IHRlc3RCdWNrZXROYW1lXG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpJQU06OlJvbGVcIiwge1xuICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudDoge1xuICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBBY3Rpb246IFwic3RzOkFzc3VtZVJvbGVcIixcbiAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIFNlcnZpY2U6IFwia2VuZHJhLmFtYXpvbmF3cy5jb21cIlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgfSxcbiAgICBQb2xpY2llczogW1xuICAgICAge1xuICAgICAgICBQb2xpY3lEb2N1bWVudDoge1xuICAgICAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBBY3Rpb246IFwiczM6R2V0T2JqZWN0XCIsXG4gICAgICAgICAgICAgIEVmZmVjdDogXCJBbGxvd1wiLFxuICAgICAgICAgICAgICBSZXNvdXJjZTogYGFybjphd3M6czM6Ojoke3Rlc3RCdWNrZXROYW1lfS8qYFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgQWN0aW9uOiBcInMzOkxpc3RCdWNrZXRcIixcbiAgICAgICAgICAgICAgRWZmZWN0OiBcIkFsbG93XCIsXG4gICAgICAgICAgICAgIFJlc291cmNlOiBgYXJuOmF3czpzMzo6OiR7dGVzdEJ1Y2tldE5hbWV9YFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgQWN0aW9uOiBbXG4gICAgICAgICAgICAgICAgXCJrZW5kcmE6QmF0Y2hQdXREb2N1bWVudFwiLFxuICAgICAgICAgICAgICAgIFwia2VuZHJhOkJhdGNoRGVsZXRlRG9jdW1lbnRcIlxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgICAgICAgICAgXCJrZW5kcmFpbmRleHRlc3RcIixcbiAgICAgICAgICAgICAgICAgIFwiQXJuXCJcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICBdLFxuICAgICAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgICAgIH0sXG4gICAgICAgIFBvbGljeU5hbWU6IFwiczNDcmF3bFBvbGljeVwiXG4gICAgICB9XG4gICAgXVxuICB9KTtcblxuICAvLyBMb29rIGZvciBub24taW1wbGVtZW50ZWQgZGF0YSBzb3VyY2VcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpLZW5kcmE6OkRhdGFTb3VyY2VcIiwge1xuICAgIE5hbWU6IG5vbkltcGxlbWVudGVkU291cmNlTmFtZSxcbiAgICBUeXBlOiBub25JbXBsZW1lbnRlZFNvdXJjZVR5cGUsXG4gICAgSW5kZXhJZDogTWF0Y2guYW55VmFsdWUoKVxuICB9KTtcblxufSk7XG5cbnRlc3QoJ0NvbmZpcm0gRXJyb2YgZm9yIGJhZCBrZW5kcmEgUGVybWlzc2lvbiBpbiBub3JtYWxpemVLZW5kcmFQZXJtaXNzaW9ucygpJywgKCkgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBbXCJyZWFkXCIsIFwic3VibWl0ZmVlZGJhY2tcIiwgXCJ3cml0ZVwiXTtcblxuICBjb25zdCBvdXRwdXRzID0gbm9ybWFsaXplS2VuZHJhUGVybWlzc2lvbnMoaW5wdXRzKTtcblxuICBleHBlY3Qob3V0cHV0cy5pbmNsdWRlcyhcIlJFQURcIikpLnRvQmVUcnV0aHkoKTtcbiAgZXhwZWN0KG91dHB1dHMuaW5jbHVkZXMoXCJTVUJNSVRGRUVEQkFDS1wiKSkudG9CZVRydXRoeSgpO1xuICBleHBlY3Qob3V0cHV0cy5pbmNsdWRlcyhcIldSSVRFXCIpKS50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgnQ29uZmlybSBzdWNjZXNzZnVsIG9wZXJhdGlvbiBvZiBub3JtYWxpemVLZW5kcmFQZXJtaXNzaW9ucygpJywgKCkgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBbXCJiYWR2YWx1ZVwiLCBcIndyaXRlXCJdO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBub3JtYWxpemVLZW5kcmFQZXJtaXNzaW9ucyhpbnB1dHMpO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvSW52YWxpZCBpbmRleFBlcm1pc3Npb24gdmFsdWUgLSB2YWxpZCB2YWx1ZXMgYXJlIFwiUkVBRFwiLCBcIlNVQk1JVEZFRURCQUNLXCIgYW5kIFwiV1JJVEVcIi8pO1xufSk7Il19