@aws-solutions-constructs/aws-cloudfront-oai-s3 2.99.0 → 2.100.1

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,715 @@
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 assertions_1 = require("aws-cdk-lib/assertions");
16
+ const s3 = require("aws-cdk-lib/aws-s3");
17
+ const cdk = require("aws-cdk-lib");
18
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
19
+ const lib_1 = require("../lib");
20
+ const acm = require("aws-cdk-lib/aws-certificatemanager");
21
+ const defaults = require("@aws-solutions-constructs/core");
22
+ const aws_kms_1 = require("aws-cdk-lib/aws-kms");
23
+ function deploy(stack, props) {
24
+ return new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', {
25
+ bucketProps: {
26
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
27
+ },
28
+ ...props
29
+ });
30
+ }
31
+ test('construct defaults set properties correctly', () => {
32
+ const stack = new cdk.Stack();
33
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', {});
34
+ expect(construct.cloudFrontWebDistribution).toBeDefined();
35
+ expect(construct.cloudFrontFunction).toBeDefined();
36
+ expect(construct.cloudFrontLoggingBucket).toBeDefined();
37
+ expect(construct.s3Bucket).toBeDefined();
38
+ expect(construct.s3LoggingBucket).toBeDefined();
39
+ expect(construct.s3BucketInterface).toBeDefined();
40
+ expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
41
+ expect(construct.originAccessIdentity).toBeDefined();
42
+ });
43
+ test('check s3Bucket default encryption', () => {
44
+ const stack = new cdk.Stack();
45
+ deploy(stack);
46
+ const template = assertions_1.Template.fromStack(stack);
47
+ template.hasResourceProperties('AWS::S3::Bucket', {
48
+ BucketEncryption: {
49
+ ServerSideEncryptionConfiguration: [{
50
+ ServerSideEncryptionByDefault: {
51
+ SSEAlgorithm: "AES256"
52
+ }
53
+ }]
54
+ }
55
+ });
56
+ });
57
+ test('check that an OAI is created', () => {
58
+ const stack = new cdk.Stack();
59
+ deploy(stack);
60
+ const template = assertions_1.Template.fromStack(stack);
61
+ template.hasResourceProperties("AWS::CloudFront::Distribution", {
62
+ DistributionConfig: {
63
+ Origins: [
64
+ {
65
+ S3OriginConfig: {
66
+ OriginAccessIdentity: assertions_1.Match.anyValue()
67
+ }
68
+ }
69
+ ]
70
+ }
71
+ });
72
+ });
73
+ test('confirm NO OAC is created', () => {
74
+ const stack = new cdk.Stack();
75
+ deploy(stack);
76
+ const template = assertions_1.Template.fromStack(stack);
77
+ template.resourcePropertiesCountIs("AWS::CloudFront::Distribution", {
78
+ DistributionConfig: {
79
+ Origins: [
80
+ {
81
+ OriginAccessControlId: assertions_1.Match.anyValue(),
82
+ }
83
+ ]
84
+ }
85
+ }, 0);
86
+ });
87
+ test('check s3Bucket public access block configuration', () => {
88
+ const stack = new cdk.Stack();
89
+ deploy(stack);
90
+ const template = assertions_1.Template.fromStack(stack);
91
+ template.hasResourceProperties('AWS::S3::Bucket', {
92
+ PublicAccessBlockConfiguration: {
93
+ BlockPublicAcls: true,
94
+ BlockPublicPolicy: true,
95
+ IgnorePublicAcls: true,
96
+ RestrictPublicBuckets: true
97
+ }
98
+ });
99
+ });
100
+ test('test s3Bucket override publicAccessBlockConfiguration', () => {
101
+ const stack = new cdk.Stack();
102
+ const props = {
103
+ bucketProps: {
104
+ blockPublicAccess: {
105
+ blockPublicAcls: false,
106
+ blockPublicPolicy: true,
107
+ ignorePublicAcls: false,
108
+ restrictPublicBuckets: true
109
+ }
110
+ }
111
+ };
112
+ new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', props);
113
+ const template = assertions_1.Template.fromStack(stack);
114
+ template.hasResourceProperties("AWS::S3::Bucket", {
115
+ PublicAccessBlockConfiguration: {
116
+ BlockPublicAcls: false,
117
+ BlockPublicPolicy: true,
118
+ IgnorePublicAcls: false,
119
+ RestrictPublicBuckets: true
120
+ },
121
+ });
122
+ });
123
+ test('check existing bucket', () => {
124
+ const bucketName = "my-bucket";
125
+ const stack = new cdk.Stack();
126
+ const existingBucket = new s3.Bucket(stack, bucketName, {
127
+ bucketName: 'my-bucket'
128
+ });
129
+ const props = {
130
+ existingBucketObj: existingBucket
131
+ };
132
+ new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', props);
133
+ const template = assertions_1.Template.fromStack(stack);
134
+ template.hasResourceProperties("AWS::S3::Bucket", {
135
+ BucketName: bucketName
136
+ });
137
+ });
138
+ test('check properties', () => {
139
+ const stack = new cdk.Stack();
140
+ const construct = deploy(stack);
141
+ expect(construct.cloudFrontWebDistribution).toBeDefined();
142
+ expect(construct.s3Bucket).toBeDefined();
143
+ });
144
+ test("Confirm CheckS3Props is called", () => {
145
+ // Stack
146
+ const stack = new cdk.Stack();
147
+ const testBucket = new s3.Bucket(stack, 'test-bucket', {});
148
+ const app = () => {
149
+ // Helper declaration
150
+ new lib_1.CloudFrontToOaiToS3(stack, "bad-s3-args", {
151
+ existingBucketObj: testBucket,
152
+ bucketProps: {
153
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
154
+ },
155
+ });
156
+ };
157
+ // Assertion
158
+ expect(app).toThrow('Error - Either provide bucketProps or existingBucketObj, but not both.\n');
159
+ });
160
+ test("Test existingBucketObj", () => {
161
+ // Stack
162
+ const stack = new cdk.Stack();
163
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, "existingIBucket", {
164
+ existingBucketObj: s3.Bucket.fromBucketName(stack, 'mybucket', 'mybucket')
165
+ });
166
+ // Assertion
167
+ expect(construct.cloudFrontWebDistribution).toBeDefined();
168
+ const template = assertions_1.Template.fromStack(stack);
169
+ template.resourceCountIs("AWS::S3::Bucket", 2);
170
+ template.hasResourceProperties("AWS::CloudFront::Distribution", {
171
+ DistributionConfig: {
172
+ Origins: [
173
+ {
174
+ DomainName: {
175
+ "Fn::Join": [
176
+ "",
177
+ [
178
+ "mybucket.s3.",
179
+ {
180
+ Ref: "AWS::Region"
181
+ },
182
+ ".",
183
+ {
184
+ Ref: "AWS::URLSuffix"
185
+ }
186
+ ]
187
+ ]
188
+ },
189
+ Id: "existingIBucketCloudFrontDistributionOrigin1D5849125",
190
+ S3OriginConfig: {
191
+ OriginAccessIdentity: assertions_1.Match.anyValue()
192
+ }
193
+ }
194
+ ]
195
+ }
196
+ });
197
+ });
198
+ test('test cloudfront with custom domain names', () => {
199
+ const stack = new cdk.Stack();
200
+ const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:${Aws.PARTITION}:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012');
201
+ const props = {
202
+ cloudFrontDistributionProps: {
203
+ domainNames: ['mydomains'],
204
+ certificate
205
+ }
206
+ };
207
+ new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', props);
208
+ const template = assertions_1.Template.fromStack(stack);
209
+ template.hasResourceProperties("AWS::CloudFront::Distribution", {
210
+ DistributionConfig: {
211
+ Aliases: [
212
+ "mydomains"
213
+ ]
214
+ }
215
+ });
216
+ });
217
+ test("Test that a CMK on the bucket throws an error", () => {
218
+ // Stack
219
+ const stack = new cdk.Stack();
220
+ const existingBucket = defaults.CreateScrapBucket(stack, "encrypted", {
221
+ encryption: s3.BucketEncryption.KMS,
222
+ encryptionKey: new aws_kms_1.Key(stack, 'Key', {
223
+ enableKeyRotation: true
224
+ })
225
+ });
226
+ const app = () => {
227
+ new lib_1.CloudFrontToOaiToS3(stack, "existingIBucket", {
228
+ existingBucketObj: existingBucket
229
+ });
230
+ };
231
+ expect(app).toThrow(/Error - buckets cannot use CMKs with OAIs\n/);
232
+ });
233
+ test("Test that a CMK in the props throws an error", () => {
234
+ // Stack
235
+ const stack = new cdk.Stack();
236
+ const encryptionKey = new aws_kms_1.Key(stack, 'cmkKey', {
237
+ enableKeyRotation: true,
238
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
239
+ });
240
+ const app = () => {
241
+ new lib_1.CloudFrontToOaiToS3(stack, "existingIBucket", {
242
+ bucketProps: {
243
+ enforceSSL: true,
244
+ encryption: s3.BucketEncryption.KMS,
245
+ encryptionKey
246
+ },
247
+ });
248
+ };
249
+ expect(app).toThrow(/Error - buckets cannot use CMKs with OAIs\n/);
250
+ });
251
+ test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => {
252
+ const stack = new cdk.Stack();
253
+ const cloudfrontLogBucketName = 'cf-log-bucket';
254
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
255
+ cloudFrontLoggingBucketProps: {
256
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
257
+ autoDeleteObjects: true,
258
+ bucketName: cloudfrontLogBucketName
259
+ }
260
+ });
261
+ const template = assertions_1.Template.fromStack(stack);
262
+ template.hasResourceProperties("AWS::S3::Bucket", {
263
+ OwnershipControls: { Rules: [{ ObjectOwnership: "ObjectWriter" }] },
264
+ BucketName: cloudfrontLogBucketName,
265
+ });
266
+ template.hasResourceProperties("Custom::S3AutoDeleteObjects", {
267
+ ServiceToken: {
268
+ "Fn::GetAtt": [
269
+ "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F",
270
+ "Arn"
271
+ ]
272
+ },
273
+ BucketName: {
274
+ Ref: assertions_1.Match.stringLikeRegexp("cloudfrontoais3CloudfrontLoggingBucket")
275
+ }
276
+ });
277
+ });
278
+ test('s3 bucket with one content bucket and no access logging of CONTENT bucket', () => {
279
+ const stack = new cdk.Stack();
280
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
281
+ bucketProps: {
282
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
283
+ },
284
+ logS3AccessLogs: false
285
+ });
286
+ const template = assertions_1.Template.fromStack(stack);
287
+ // Content bucket+Cloudfront Logs bucket+
288
+ // Access Log bucket for Cloudfront Logs bucket = 3 buckets
289
+ template.resourceCountIs("AWS::S3::Bucket", 3);
290
+ expect(construct.s3LoggingBucket).toEqual(undefined);
291
+ });
292
+ test('CloudFront origin path present when provided', () => {
293
+ const stack = new cdk.Stack();
294
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
295
+ originPath: '/testPath'
296
+ });
297
+ const template = assertions_1.Template.fromStack(stack);
298
+ template.hasResourceProperties("AWS::CloudFront::Distribution", {
299
+ DistributionConfig: {
300
+ Origins: [
301
+ {
302
+ OriginPath: "/testPath",
303
+ }
304
+ ]
305
+ }
306
+ });
307
+ });
308
+ test('CloudFront origin path should not be present if not provided', () => {
309
+ const stack = new cdk.Stack();
310
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {});
311
+ defaults.expectNonexistence(stack, "AWS::CloudFront::Distribution", {
312
+ DistributionConfig: {
313
+ Origins: [
314
+ {
315
+ OriginPath: assertions_1.Match.anyValue(),
316
+ }
317
+ ]
318
+ }
319
+ });
320
+ });
321
+ test('Test the deployment with securityHeadersBehavior instead of HTTP security headers', () => {
322
+ // Initial setup
323
+ const stack = new aws_cdk_lib_1.Stack();
324
+ const testConstruct = new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', {
325
+ insertHttpSecurityHeaders: false,
326
+ responseHeadersPolicyProps: {
327
+ securityHeadersBehavior: {
328
+ strictTransportSecurity: {
329
+ accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
330
+ includeSubdomains: true,
331
+ override: true,
332
+ preload: true
333
+ },
334
+ contentSecurityPolicy: {
335
+ contentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
336
+ override: true
337
+ },
338
+ }
339
+ }
340
+ });
341
+ // Assertion
342
+ const template = assertions_1.Template.fromStack(stack);
343
+ template.hasResourceProperties("AWS::CloudFront::ResponseHeadersPolicy", {
344
+ ResponseHeadersPolicyConfig: {
345
+ SecurityHeadersConfig: {
346
+ ContentSecurityPolicy: {
347
+ ContentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
348
+ Override: true
349
+ },
350
+ StrictTransportSecurity: {
351
+ AccessControlMaxAgeSec: 63072,
352
+ IncludeSubdomains: true,
353
+ Override: true,
354
+ Preload: true
355
+ }
356
+ }
357
+ }
358
+ });
359
+ expect(testConstruct.cloudFrontFunction).toEqual(undefined);
360
+ });
361
+ test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProps are provided", () => {
362
+ const stack = new cdk.Stack();
363
+ expect(() => {
364
+ new lib_1.CloudFrontToOaiToS3(stack, "test-cloudfront-oai-s3", {
365
+ insertHttpSecurityHeaders: true,
366
+ responseHeadersPolicyProps: {
367
+ securityHeadersBehavior: {
368
+ strictTransportSecurity: {
369
+ accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
370
+ includeSubdomains: true,
371
+ override: false,
372
+ preload: true
373
+ }
374
+ }
375
+ }
376
+ });
377
+ }).toThrow();
378
+ });
379
+ test("Confirm CheckCloudFrontProps is being called", () => {
380
+ const stack = new cdk.Stack();
381
+ expect(() => {
382
+ new lib_1.CloudFrontToOaiToS3(stack, "test-cloudfront-apigateway", {
383
+ insertHttpSecurityHeaders: true,
384
+ responseHeadersPolicyProps: {
385
+ securityHeadersBehavior: {
386
+ strictTransportSecurity: {
387
+ accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
388
+ includeSubdomains: true,
389
+ override: false,
390
+ preload: true
391
+ }
392
+ }
393
+ }
394
+ });
395
+ }).toThrow('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.');
396
+ });
397
+ test('Test that we do not create an Access Log bucket for CF logs if one is provided', () => {
398
+ const stack = new cdk.Stack();
399
+ const cfS3AccessLogBucket = new s3.Bucket(stack, 'cf-s3-access-logs');
400
+ new lib_1.CloudFrontToOaiToS3(stack, 'test-cloudfront-oai-s3', {
401
+ cloudFrontLoggingBucketProps: {
402
+ serverAccessLogsBucket: cfS3AccessLogBucket
403
+ }
404
+ });
405
+ const template = assertions_1.Template.fromStack(stack);
406
+ template.resourceCountIs("AWS::S3::Bucket", 4);
407
+ });
408
+ // =====================
409
+ // S3 Content Bucket Access Logs Bucket
410
+ // =====================
411
+ test('Providing loggingBucketProps and existingLoggingBucket is an error', () => {
412
+ const stack = new cdk.Stack();
413
+ const logBucket = new s3.Bucket(stack, 'log-bucket', {});
414
+ const app = () => {
415
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
416
+ bucketProps: {
417
+ serverAccessLogsBucket: logBucket,
418
+ },
419
+ loggingBucketProps: {
420
+ bucketName: 'anything'
421
+ }
422
+ });
423
+ };
424
+ expect(app).toThrow(/Error - bothlog bucket props and an existing log bucket were provided.\n/);
425
+ });
426
+ test('Providing existingLoggingBucket and logS3AccessLogs=false is an error', () => {
427
+ const stack = new cdk.Stack();
428
+ const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
429
+ const app = () => {
430
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
431
+ bucketProps: {
432
+ serverAccessLogsBucket: logBucket,
433
+ },
434
+ logS3AccessLogs: false
435
+ });
436
+ };
437
+ expect(app).toThrow(/Error - logS3AccessLogs is false, but a log bucket was provided in bucketProps.\n/);
438
+ });
439
+ test('Providing loggingBucketProps and logS3AccessLogs=false is an error', () => {
440
+ const stack = new cdk.Stack();
441
+ const app = () => {
442
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
443
+ loggingBucketProps: {
444
+ bucketName: 'anything'
445
+ },
446
+ logS3AccessLogs: false
447
+ });
448
+ };
449
+ // NOTE: This error is thrown by CheckS3Props(), not CheckConstructSpecificProps()
450
+ expect(app).toThrow(/Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n/);
451
+ });
452
+ // test('No new loggingBucket is created if existingLoggingBucket is supplied', () => {
453
+ test('loggingBucketProps is supplied is integrated into architecture correctly', () => {
454
+ const stack = new cdk.Stack();
455
+ const testName = "test-name";
456
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
457
+ bucketProps: {
458
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
459
+ },
460
+ loggingBucketProps: {
461
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
462
+ autoDeleteObjects: true,
463
+ bucketName: testName
464
+ }
465
+ });
466
+ expect(construct.s3LoggingBucket).toBeDefined();
467
+ const template = assertions_1.Template.fromStack(stack);
468
+ template.resourceCountIs("AWS::S3::Bucket", 4);
469
+ template.hasResourceProperties("AWS::S3::Bucket", {
470
+ BucketName: testName
471
+ });
472
+ template.hasResourceProperties("AWS::S3::Bucket", {
473
+ LoggingConfiguration: {
474
+ DestinationBucketName: {
475
+ Ref: assertions_1.Match.stringLikeRegexp('cloudfrontoais3S3LoggingBucket')
476
+ }
477
+ }
478
+ });
479
+ });
480
+ test('bucketProps:serverAccessLogsBucket is supplied is integrated into architecture correctly', () => {
481
+ const testName = 'some-name';
482
+ const stack = new cdk.Stack();
483
+ const logBucket = new s3.Bucket(stack, 'test-log', {
484
+ bucketName: testName,
485
+ });
486
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
487
+ bucketProps: {
488
+ serverAccessLogsBucket: logBucket,
489
+ },
490
+ });
491
+ expect(construct.s3LoggingBucket).toBeDefined();
492
+ const template = assertions_1.Template.fromStack(stack);
493
+ template.resourceCountIs("AWS::S3::Bucket", 4);
494
+ template.hasResourceProperties("AWS::S3::Bucket", {
495
+ LoggingConfiguration: {
496
+ DestinationBucketName: {
497
+ Ref: "testlogE88B4C6B"
498
+ }
499
+ }
500
+ });
501
+ });
502
+ // =====================
503
+ // CloudFront Log Bucket
504
+ // =====================
505
+ test('Providing cloudFrontLoggingBucketProps and a log bucket in cloudFrontDistrbutionProps is an error', () => {
506
+ const stack = new cdk.Stack();
507
+ const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
508
+ const app = () => {
509
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
510
+ cloudFrontDistributionProps: {
511
+ logBucket
512
+ },
513
+ cloudFrontLoggingBucketProps: {
514
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
515
+ autoDeleteObjects: true
516
+ }
517
+ });
518
+ };
519
+ expect(app).toThrow();
520
+ });
521
+ test('cloudFrontLoggingBucketProps are used correctly', () => {
522
+ const stack = new cdk.Stack();
523
+ const testName = "test-name";
524
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
525
+ cloudFrontLoggingBucketProps: {
526
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
527
+ autoDeleteObjects: true,
528
+ bucketName: testName
529
+ }
530
+ });
531
+ expect(construct.cloudFrontLoggingBucket).toBeDefined();
532
+ const template = assertions_1.Template.fromStack(stack);
533
+ template.resourceCountIs("AWS::S3::Bucket", 4);
534
+ template.hasResourceProperties("AWS::S3::Bucket", {
535
+ BucketName: testName
536
+ });
537
+ });
538
+ test('Logging disabled in CloudFront props is handled correctly', () => {
539
+ const stack = new cdk.Stack();
540
+ const construct = deploy(stack, { cloudFrontDistributionProps: { enableLogging: false } });
541
+ const template = assertions_1.Template.fromStack(stack);
542
+ // Only the content bucket and it S3 Access Log bucket (no Cloudfront log bucket)
543
+ template.resourceCountIs("AWS::S3::Bucket", 2);
544
+ // No logging is configured
545
+ template.resourcePropertiesCountIs("AWS::CloudFront::Distribution", {
546
+ DistributionConfig: {
547
+ Logging: assertions_1.Match.anyValue()
548
+ }
549
+ }, 0);
550
+ expect(construct.cloudFrontLoggingBucket === undefined);
551
+ });
552
+ test('No new CloudFrontLoggingBucket is created if cloudFrontLoggingBucketProps:logBucket is supplied', () => {
553
+ const testName = 'random-value';
554
+ const stack = new cdk.Stack();
555
+ const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {
556
+ bucketName: testName
557
+ });
558
+ // const construct =
559
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
560
+ cloudFrontDistributionProps: {
561
+ logBucket
562
+ },
563
+ });
564
+ expect(construct.cloudFrontLoggingBucket).toBeDefined();
565
+ const template = assertions_1.Template.fromStack(stack);
566
+ // Content bucket, Content bucket S3 Access Log bucket, cloudfront log bucket
567
+ template.resourceCountIs("AWS::S3::Bucket", 3);
568
+ // Ensure our existing bucket has been used for cloudfront logging
569
+ template.hasResourceProperties("AWS::CloudFront::Distribution", {
570
+ DistributionConfig: {
571
+ Logging: {
572
+ Bucket: {
573
+ "Fn::GetAtt": [
574
+ "cloudfrontlogbucketDF7058FB",
575
+ "RegionalDomainName"
576
+ ]
577
+ }
578
+ }
579
+ }
580
+ });
581
+ });
582
+ // =====================
583
+ // CloudFront Logs Bucket Access Log Bucket
584
+ // =====================
585
+ test('Providing cloudFrontLoggingBucketAccessLogBucketProps and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
586
+ const stack = new cdk.Stack();
587
+ const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
588
+ const app = () => {
589
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
590
+ cloudFrontLoggingBucketProps: {
591
+ serverAccessLogsBucket: logBucket,
592
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
593
+ autoDeleteObjects: true
594
+ },
595
+ cloudFrontLoggingBucketAccessLogBucketProps: {
596
+ bucketName: 'specfic-name-is-inconsequential'
597
+ }
598
+ });
599
+ };
600
+ expect(app).toThrow(/Error - an existing CloudFront log bucket S3 access log bucket and cloudFrontLoggingBucketAccessLogBucketProps were provided\n/);
601
+ });
602
+ test('Providing cloudFrontLoggingBucketAccessLogBucketProps and logCloudFrontAccessLog=false is an error', () => {
603
+ const stack = new cdk.Stack();
604
+ const app = () => {
605
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
606
+ logCloudFrontAccessLog: false,
607
+ cloudFrontLoggingBucketAccessLogBucketProps: {
608
+ bucketName: 'specfic-name-is-inconsequential'
609
+ }
610
+ });
611
+ };
612
+ expect(app).toThrow(/Error - cloudFrontLoggingBucketAccessLogBucketProps were provided but logCloudFrontAccessLog was false\n/);
613
+ });
614
+ test('Providing logCloudFrontAccessLog=false and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
615
+ const stack = new cdk.Stack();
616
+ const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
617
+ const app = () => {
618
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
619
+ cloudFrontLoggingBucketProps: {
620
+ serverAccessLogsBucket: logBucket,
621
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
622
+ autoDeleteObjects: true
623
+ },
624
+ logCloudFrontAccessLog: false,
625
+ });
626
+ };
627
+ expect(app).toThrow(/Error - props.cloudFrontLoggingBucketProps.serverAccessLogsBucket was provided but logCloudFrontAccessLog was false\n/);
628
+ });
629
+ test('cloudFrontLoggingBucketAccessLogBucketProps are used correctly', () => {
630
+ const stack = new cdk.Stack();
631
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
632
+ cloudFrontLoggingBucketAccessLogBucketProps: {
633
+ websiteErrorDocument: 'placeholder',
634
+ websiteIndexDocument: 'placeholde-two'
635
+ }
636
+ });
637
+ const template = assertions_1.Template.fromStack(stack);
638
+ // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
639
+ template.resourceCountIs("AWS::S3::Bucket", 4);
640
+ template.hasResourceProperties("AWS::S3::Bucket", {
641
+ WebsiteConfiguration: {
642
+ ErrorDocument: 'placeholder',
643
+ IndexDocument: 'placeholde-two'
644
+ }
645
+ });
646
+ });
647
+ test('If existing CloudFront Log bucket S3 Access Logging bucket is provided, it is used correctly', () => {
648
+ const stack = new cdk.Stack();
649
+ const testName = 'cf-log-s3-log';
650
+ const cfLogS3AccessLogBucket = new s3.Bucket(stack, 'cf-log-s3-access-log-bucket', {
651
+ bucketName: testName
652
+ });
653
+ new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
654
+ cloudFrontLoggingBucketProps: {
655
+ serverAccessLogsBucket: cfLogS3AccessLogBucket
656
+ }
657
+ });
658
+ const template = assertions_1.Template.fromStack(stack);
659
+ // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
660
+ template.resourceCountIs("AWS::S3::Bucket", 4);
661
+ template.hasResourceProperties("AWS::S3::Bucket", {
662
+ BucketName: testName
663
+ });
664
+ template.hasResourceProperties("AWS::S3::Bucket", {
665
+ LoggingConfiguration: {
666
+ DestinationBucketName: {
667
+ Ref: "cflogs3accesslogbucketDE374C27"
668
+ }
669
+ }
670
+ });
671
+ });
672
+ test('cloudFrontLoggingBucketAccessLogBucket property is set correctly', () => {
673
+ const stack = new cdk.Stack();
674
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
675
+ cloudFrontLoggingBucketAccessLogBucketProps: {
676
+ websiteErrorDocument: 'placeholder',
677
+ websiteIndexDocument: 'placeholde-two'
678
+ }
679
+ });
680
+ const template = assertions_1.Template.fromStack(stack);
681
+ // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
682
+ template.resourceCountIs("AWS::S3::Bucket", 4);
683
+ template.hasResourceProperties("AWS::S3::Bucket", {
684
+ WebsiteConfiguration: {
685
+ ErrorDocument: 'placeholder',
686
+ IndexDocument: 'placeholde-two'
687
+ }
688
+ });
689
+ expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
690
+ expect(construct.cloudFrontLoggingBucketAccessLogBucket.bucketName).toBeDefined();
691
+ });
692
+ test('logCloudFrontAccessLog property is used correctly', () => {
693
+ const stack = new cdk.Stack();
694
+ const construct = new lib_1.CloudFrontToOaiToS3(stack, 'cloudfront-oai-s3', {
695
+ logCloudFrontAccessLog: false
696
+ });
697
+ const template = assertions_1.Template.fromStack(stack);
698
+ // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
699
+ template.resourceCountIs("AWS::S3::Bucket", 3);
700
+ expect(construct.cloudFrontLoggingBucket).toBeDefined();
701
+ expect(construct.cloudFrontLoggingBucketAccessLogBucket).not.toBeDefined();
702
+ });
703
+ test('Test that ValidateDistributionProps() is being called', () => {
704
+ const stack = new cdk.Stack();
705
+ const props = {
706
+ cloudFrontDistributionProps: {
707
+ invalidProperty: true
708
+ }
709
+ };
710
+ const app = () => {
711
+ new lib_1.CloudFrontToOaiToS3(stack, 'test-construct', props);
712
+ };
713
+ expect(app).toThrow(/ERROR - invalidProperty is not a valid property of DistributionProps/);
714
+ });
715
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWRmcm9udC1vYWktczMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsb3VkZnJvbnQtb2FpLXMzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7OztHQVdHOztBQUVILHVEQUF5RDtBQUN6RCx5Q0FBeUM7QUFDekMsbUNBQW1DO0FBQ25DLDZDQUE2RDtBQUM3RCxnQ0FBdUU7QUFDdkUsMERBQTBEO0FBQzFELDJEQUEyRDtBQUMzRCxpREFBMEM7QUFFMUMsU0FBUyxNQUFNLENBQUMsS0FBZ0IsRUFBRSxLQUFnQztJQUNoRSxPQUFPLElBQUkseUJBQW1CLENBQUMsS0FBSyxFQUFFLHdCQUF3QixFQUFFO1FBQzlELFdBQVcsRUFBRTtZQUNYLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLE9BQU87U0FDekM7UUFDRCxHQUFHLEtBQUs7S0FDVCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtJQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixNQUFNLFNBQVMsR0FBRyxJQUFJLHlCQUFtQixDQUFDLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUUvRSxNQUFNLENBQUMsU0FBUyxDQUFDLHlCQUF5QixDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDMUQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ25ELE1BQU0sQ0FBQyxTQUFTLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4RCxNQUFNLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3pDLE1BQU0sQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDaEQsTUFB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QztBQUNyRixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxtREFBbUQsRUFBRSxHQUFHLEVBQUU7SUFDN0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSx5QkFBbUIsQ0FBQyxLQUFLLEVBQUUsbUJBQW1CLEVBQUU7UUFDcEUsc0JBQXNCLEVBQUUsS0FBSztLQUM5QixDQUFDLENBQUM7SUFFSCxNQUFNLFFBQVEsR0FBRyxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUUzQyx5SEFBeUg7SUFDekgsUUFBUSxDQUFDLGVBQWUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvQyxNQUFNLENBQUMsU0FBUyxDQUFDLHVCQUF1QixDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDeEQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUM3RSxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyx1REFBdUQsRUFBRSxHQUFHLEVBQUU7SUFDakUsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDOUIsTUFBTSxLQUFLLEdBQTZCO1FBQ3RDLDJCQUEyQixFQUFFO1lBQzNCLGVBQWUsRUFBRSxJQUFJO1NBQ3RCO0tBQ0YsQ0FBQztJQUVGLE1BQU0sR0FBRyxHQUFHLEdBQUcsRUFBRTtRQUNmLElBQUkseUJBQW1CLENBQUMsS0FBSyxFQUFFLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzFELENBQUMsQ0FBQztJQUVGLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsc0VBQXNFLENBQUMsQ0FBQztBQUM5RixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpLiBZb3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiAgd2l0aCB0aGUgTGljZW5zZS4gQSBjb3B5IG9mIHRoZSBMaWNlbnNlIGlzIGxvY2F0ZWQgYXRcbiAqXG4gKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqICBvciBpbiB0aGUgJ2xpY2Vuc2UnIGZpbGUgYWNjb21wYW55aW5nIHRoaXMgZmlsZS4gVGhpcyBmaWxlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICdBUyBJUycgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFU1xuICogIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXG4gKiAgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IE1hdGNoLCBUZW1wbGF0ZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hc3NlcnRpb25zXCI7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgRHVyYXRpb24sIFJlbW92YWxQb2xpY3ksIFN0YWNrIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBDbG91ZEZyb250VG9PYWlUb1MzLCBDbG91ZEZyb250VG9PYWlUb1MzUHJvcHMgfSBmcm9tIFwiLi4vbGliXCI7XG5pbXBvcnQgKiBhcyBhY20gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tICdAYXdzLXNvbHV0aW9ucy1jb25zdHJ1Y3RzL2NvcmUnO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1rbXNcIjtcblxuZnVuY3Rpb24gZGVwbG95KHN0YWNrOiBjZGsuU3RhY2ssIHByb3BzPzogQ2xvdWRGcm9udFRvT2FpVG9TM1Byb3BzKSB7XG4gIHJldHVybiBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIHJlbW92YWxQb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgfSxcbiAgICAuLi5wcm9wc1xuICB9KTtcbn1cblxudGVzdCgnY29uc3RydWN0IGRlZmF1bHRzIHNldCBwcm9wZXJ0aWVzIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LW9haS1zMycsIHt9KTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udEZ1bmN0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzTG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0J1Y2tldEludGVyZmFjZSkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NJZGVudGl0eSkudG9CZURlZmluZWQoKTtcbn0pO1xuXG50ZXN0KCdjaGVjayBzM0J1Y2tldCBkZWZhdWx0IGVuY3J5cHRpb24nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBkZXBsb3koc3RhY2spO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTMzo6QnVja2V0Jywge1xuICAgIEJ1Y2tldEVuY3J5cHRpb246IHtcbiAgICAgIFNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvbjogW3tcbiAgICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQ6IHtcbiAgICAgICAgICBTU0VBbGdvcml0aG06IFwiQUVTMjU2XCJcbiAgICAgICAgfVxuICAgICAgfV1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ2NoZWNrIHRoYXQgYW4gT0FJIGlzIGNyZWF0ZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBkZXBsb3koc3RhY2spO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIFMzT3JpZ2luQ29uZmlnOiB7XG4gICAgICAgICAgICBPcmlnaW5BY2Nlc3NJZGVudGl0eTogTWF0Y2guYW55VmFsdWUoKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnY29uZmlybSBOTyBPQUMgaXMgY3JlYXRlZCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGRlcGxveShzdGFjayk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICB0ZW1wbGF0ZS5yZXNvdXJjZVByb3BlcnRpZXNDb3VudElzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgT3JpZ2luczogW1xuICAgICAgICB7XG4gICAgICAgICAgT3JpZ2luQWNjZXNzQ29udHJvbElkOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9LCAwKTtcbn0pO1xuXG50ZXN0KCdjaGVjayBzM0J1Y2tldCBwdWJsaWMgYWNjZXNzIGJsb2NrIGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBkZXBsb3koc3RhY2spO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTMzo6QnVja2V0Jywge1xuICAgIFB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgQmxvY2tQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgQmxvY2tQdWJsaWNQb2xpY3k6IHRydWUsXG4gICAgICBJZ25vcmVQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgUmVzdHJpY3RQdWJsaWNCdWNrZXRzOiB0cnVlXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCd0ZXN0IHMzQnVja2V0IG92ZXJyaWRlIHB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb09haVRvUzNQcm9wcyA9IHtcbiAgICBidWNrZXRQcm9wczoge1xuICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IHtcbiAgICAgICAgYmxvY2tQdWJsaWNBY2xzOiBmYWxzZSxcbiAgICAgICAgYmxvY2tQdWJsaWNQb2xpY3k6IHRydWUsXG4gICAgICAgIGlnbm9yZVB1YmxpY0FjbHM6IGZhbHNlLFxuICAgICAgICByZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWVcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtb2FpLXMzJywgcHJvcHMpO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICBQdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIEJsb2NrUHVibGljQWNsczogZmFsc2UsXG4gICAgICBCbG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgIElnbm9yZVB1YmxpY0FjbHM6IGZhbHNlLFxuICAgICAgUmVzdHJpY3RQdWJsaWNCdWNrZXRzOiB0cnVlXG4gICAgfSxcbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgZXhpc3RpbmcgYnVja2V0JywgKCkgPT4ge1xuICBjb25zdCBidWNrZXROYW1lID0gXCJteS1idWNrZXRcIjtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgZXhpc3RpbmdCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCBidWNrZXROYW1lLCB7XG4gICAgYnVja2V0TmFtZTogJ215LWJ1Y2tldCdcbiAgfSk7XG5cbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb09haVRvUzNQcm9wcyA9IHtcbiAgICBleGlzdGluZ0J1Y2tldE9iajogZXhpc3RpbmdCdWNrZXRcbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1vYWktczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IGJ1Y2tldE5hbWVcbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgcHJvcGVydGllcycsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0OiBDbG91ZEZyb250VG9PYWlUb1MzID0gZGVwbG95KHN0YWNrKTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tTM1Byb3BzIGlzIGNhbGxlZFwiLCAoKSA9PiB7XG4gIC8vIFN0YWNrXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3RCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAndGVzdC1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIC8vIEhlbHBlciBkZWNsYXJhdGlvblxuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCBcImJhZC1zMy1hcmdzXCIsIHtcbiAgICAgIGV4aXN0aW5nQnVja2V0T2JqOiB0ZXN0QnVja2V0LFxuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZXG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xuICAvLyBBc3NlcnRpb25cbiAgZXhwZWN0KGFwcCkudG9UaHJvdygnRXJyb3IgLSBFaXRoZXIgcHJvdmlkZSBidWNrZXRQcm9wcyBvciBleGlzdGluZ0J1Y2tldE9iaiwgYnV0IG5vdCBib3RoLlxcbicpO1xufSk7XG5cbnRlc3QoXCJUZXN0IGV4aXN0aW5nQnVja2V0T2JqXCIsICgpID0+IHtcbiAgLy8gU3RhY2tcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdDogQ2xvdWRGcm9udFRvT2FpVG9TMyA9IG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCBcImV4aXN0aW5nSUJ1Y2tldFwiLCB7XG4gICAgZXhpc3RpbmdCdWNrZXRPYmo6IHMzLkJ1Y2tldC5mcm9tQnVja2V0TmFtZShzdGFjaywgJ215YnVja2V0JywgJ215YnVja2V0JylcbiAgfSk7XG4gIC8vIEFzc2VydGlvblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpTMzo6QnVja2V0XCIsIDIpO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBEb21haW5OYW1lOiB7XG4gICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFwibXlidWNrZXQuczMuXCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UmVnaW9uXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiLlwiLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlVSTFN1ZmZpeFwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBJZDogXCJleGlzdGluZ0lCdWNrZXRDbG91ZEZyb250RGlzdHJpYnV0aW9uT3JpZ2luMUQ1ODQ5MTI1XCIsXG4gICAgICAgICAgUzNPcmlnaW5Db25maWc6IHtcbiAgICAgICAgICAgIE9yaWdpbkFjY2Vzc0lkZW50aXR5OiBNYXRjaC5hbnlWYWx1ZSgpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCd0ZXN0IGNsb3VkZnJvbnQgd2l0aCBjdXN0b20gZG9tYWluIG5hbWVzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGFjbS5DZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oc3RhY2ssICdDZXJ0JywgJ2Fybjoke0F3cy5QQVJUSVRJT059OmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzExMTEyMjIyLTMzMzMtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMicpO1xuXG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9PYWlUb1MzUHJvcHMgPSB7XG4gICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiB7XG4gICAgICBkb21haW5OYW1lczogWydteWRvbWFpbnMnXSxcbiAgICAgIGNlcnRpZmljYXRlXG4gICAgfVxuICB9O1xuXG4gIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LW9haS1zMycsIHByb3BzKTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIEFsaWFzZXM6IFtcbiAgICAgICAgXCJteWRvbWFpbnNcIlxuICAgICAgXVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdChcIlRlc3QgdGhhdCBhIENNSyBvbiB0aGUgYnVja2V0IHRocm93cyBhbiBlcnJvclwiLCAoKSA9PiB7XG4gIC8vIFN0YWNrXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBleGlzdGluZ0J1Y2tldCA9IGRlZmF1bHRzLkNyZWF0ZVNjcmFwQnVja2V0KHN0YWNrLCBcImVuY3J5cHRlZFwiLCB7XG4gICAgZW5jcnlwdGlvbjogczMuQnVja2V0RW5jcnlwdGlvbi5LTVMsXG4gICAgZW5jcnlwdGlvbktleTogbmV3IEtleShzdGFjaywgJ0tleScsIHtcbiAgICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0cnVlXG4gICAgfSlcbiAgfSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCBcImV4aXN0aW5nSUJ1Y2tldFwiLCB7XG4gICAgICBleGlzdGluZ0J1Y2tldE9iajogZXhpc3RpbmdCdWNrZXRcbiAgICB9KTtcbiAgfTtcbiAgZXhwZWN0KGFwcCkudG9UaHJvdygvRXJyb3IgLSBidWNrZXRzIGNhbm5vdCB1c2UgQ01LcyB3aXRoIE9BSXNcXG4vKTtcbn0pO1xuXG50ZXN0KFwiVGVzdCB0aGF0IGEgQ01LIGluIHRoZSBwcm9wcyB0aHJvd3MgYW4gZXJyb3JcIiwgKCkgPT4ge1xuICAvLyBTdGFja1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgZW5jcnlwdGlvbktleSA9IG5ldyBLZXkoc3RhY2ssICdjbWtLZXknLCB7XG4gICAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZXG4gIH0pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgXCJleGlzdGluZ0lCdWNrZXRcIiwge1xuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgZW5mb3JjZVNTTDogdHJ1ZSxcbiAgICAgICAgZW5jcnlwdGlvbjogczMuQnVja2V0RW5jcnlwdGlvbi5LTVMsXG4gICAgICAgIGVuY3J5cHRpb25LZXlcbiAgICAgIH0sXG4gICAgfSk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3coL0Vycm9yIC0gYnVja2V0cyBjYW5ub3QgdXNlIENNS3Mgd2l0aCBPQUlzXFxuLyk7XG59KTtcblxudGVzdCgnQ2xvdWRmcm9udCBsb2dnaW5nIGJ1Y2tldCB3aXRoIGRlc3Ryb3kgcmVtb3ZhbCBwb2xpY3kgYW5kIGF1dG8gZGVsZXRlIG9iamVjdHMnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGNsb3VkZnJvbnRMb2dCdWNrZXROYW1lID0gJ2NmLWxvZy1idWNrZXQnO1xuICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgIHJlbW92YWxQb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgICAgIGJ1Y2tldE5hbWU6IGNsb3VkZnJvbnRMb2dCdWNrZXROYW1lXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgT3duZXJzaGlwQ29udHJvbHM6IHsgUnVsZXM6IFt7IE9iamVjdE93bmVyc2hpcDogXCJPYmplY3RXcml0ZXJcIiB9XSB9LFxuICAgIEJ1Y2tldE5hbWU6IGNsb3VkZnJvbnRMb2dCdWNrZXROYW1lLFxuICB9KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJDdXN0b206OlMzQXV0b0RlbGV0ZU9iamVjdHNcIiwge1xuICAgIFNlcnZpY2VUb2tlbjoge1xuICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgXCJDdXN0b21TM0F1dG9EZWxldGVPYmplY3RzQ3VzdG9tUmVzb3VyY2VQcm92aWRlckhhbmRsZXI5RDkwMTg0RlwiLFxuICAgICAgICBcIkFyblwiXG4gICAgICBdXG4gICAgfSxcbiAgICBCdWNrZXROYW1lOiB7XG4gICAgICBSZWY6IE1hdGNoLnN0cmluZ0xpa2VSZWdleHAoXCJjbG91ZGZyb250b2FpczNDbG91ZGZyb250TG9nZ2luZ0J1Y2tldFwiKVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnczMgYnVja2V0IHdpdGggb25lIGNvbnRlbnQgYnVja2V0IGFuZCBubyBhY2Nlc3MgbG9nZ2luZyBvZiBDT05URU5UIGJ1Y2tldCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBidWNrZXRQcm9wczoge1xuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICB9LFxuICAgIGxvZ1MzQWNjZXNzTG9nczogZmFsc2VcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAvLyBDb250ZW50IGJ1Y2tldCtDbG91ZGZyb250IExvZ3MgYnVja2V0K1xuICAvLyBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ2xvdWRmcm9udCBMb2dzIGJ1Y2tldCA9IDMgYnVja2V0c1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNMb2dnaW5nQnVja2V0KS50b0VxdWFsKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdCgnQ2xvdWRGcm9udCBvcmlnaW4gcGF0aCBwcmVzZW50IHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgb3JpZ2luUGF0aDogJy90ZXN0UGF0aCdcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOlxuICAgIHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIE9yaWdpblBhdGg6IFwiL3Rlc3RQYXRoXCIsXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ0Nsb3VkRnJvbnQgb3JpZ2luIHBhdGggc2hvdWxkIG5vdCBiZSBwcmVzZW50IGlmIG5vdCBwcm92aWRlZCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHt9KTtcblxuICBkZWZhdWx0cy5leHBlY3ROb25leGlzdGVuY2Uoc3RhY2ssIFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgIERpc3RyaWJ1dGlvbkNvbmZpZzpcbiAgICB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBPcmlnaW5QYXRoOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoZSBkZXBsb3ltZW50IHdpdGggc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgaW5zdGVhZCBvZiBIVFRQIHNlY3VyaXR5IGhlYWRlcnMnLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgc2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgY29uc3QgdGVzdENvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzOiBmYWxzZSxcbiAgICByZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wczoge1xuICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHtcbiAgICAgICAgc3RyaWN0VHJhbnNwb3J0U2VjdXJpdHk6IHtcbiAgICAgICAgICBhY2Nlc3NDb250cm9sTWF4QWdlOiBEdXJhdGlvbi5zZWNvbmRzKDYzMDcyKSxcbiAgICAgICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgICAgICBvdmVycmlkZTogdHJ1ZSxcbiAgICAgICAgICBwcmVsb2FkOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIGNvbnRlbnRTZWN1cml0eVBvbGljeToge1xuICAgICAgICAgIGNvbnRlbnRTZWN1cml0eVBvbGljeTogXCJ1cGdyYWRlLWluc2VjdXJlLXJlcXVlc3RzOyBkZWZhdWx0LXNyYyAnbm9uZSc7XCIsXG4gICAgICAgICAgb3ZlcnJpZGU6IHRydWVcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIC8vIEFzc2VydGlvblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6UmVzcG9uc2VIZWFkZXJzUG9saWN5XCIsIHtcbiAgICBSZXNwb25zZUhlYWRlcnNQb2xpY3lDb25maWc6IHtcbiAgICAgIFNlY3VyaXR5SGVhZGVyc0NvbmZpZzoge1xuICAgICAgICBDb250ZW50U2VjdXJpdHlQb2xpY3k6IHtcbiAgICAgICAgICBDb250ZW50U2VjdXJpdHlQb2xpY3k6IFwidXBncmFkZS1pbnNlY3VyZS1yZXF1ZXN0czsgZGVmYXVsdC1zcmMgJ25vbmUnO1wiLFxuICAgICAgICAgIE92ZXJyaWRlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIFN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICAgICAgQWNjZXNzQ29udHJvbE1heEFnZVNlYzogNjMwNzIsXG4gICAgICAgICAgSW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgT3ZlcnJpZGU6IHRydWUsXG4gICAgICAgICAgUHJlbG9hZDogdHJ1ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgZXhwZWN0KHRlc3RDb25zdHJ1Y3QuY2xvdWRGcm9udEZ1bmN0aW9uKS50b0VxdWFsKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdChcInRocm93IGV4Y2VwdGlvbiBpZiBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzIGFuZCByZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyBhcmUgcHJvdmlkZWRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBleHBlY3QoKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCBcInRlc3QtY2xvdWRmcm9udC1vYWktczNcIiwge1xuICAgICAgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVyczogdHJ1ZSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzOiB7XG4gICAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB7XG4gICAgICAgICAgc3RyaWN0VHJhbnNwb3J0U2VjdXJpdHk6IHtcbiAgICAgICAgICAgIGFjY2Vzc0NvbnRyb2xNYXhBZ2U6IER1cmF0aW9uLnNlY29uZHMoNjMwNzIpLFxuICAgICAgICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICAgICAgICBwcmVsb2FkOiB0cnVlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pLnRvVGhyb3coKTtcbn0pO1xuXG50ZXN0KFwiQ29uZmlybSBDaGVja0Nsb3VkRnJvbnRQcm9wcyBpcyBiZWluZyBjYWxsZWRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBleHBlY3QoKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCBcInRlc3QtY2xvdWRmcm9udC1hcGlnYXRld2F5XCIsIHtcbiAgICAgIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnM6IHRydWUsXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wczoge1xuICAgICAgICBzZWN1cml0eUhlYWRlcnNCZWhhdmlvcjoge1xuICAgICAgICAgIHN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICAgICAgICBhY2Nlc3NDb250cm9sTWF4QWdlOiBEdXJhdGlvbi5zZWNvbmRzKDYzMDcyKSxcbiAgICAgICAgICAgIGluY2x1ZGVTdWJkb21haW5zOiB0cnVlLFxuICAgICAgICAgICAgb3ZlcnJpZGU6IGZhbHNlLFxuICAgICAgICAgICAgcHJlbG9hZDogdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9KS50b1Rocm93KCdyZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcy5zZWN1cml0eUhlYWRlcnNCZWhhdmlvciBjYW4gb25seSBiZSBwYXNzZWQgaWYgaHR0cFNlY3VyaXR5SGVhZGVycyBpcyBzZXQgdG8gYGZhbHNlYC4nKTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoYXQgd2UgZG8gbm90IGNyZWF0ZSBhbiBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ0YgbG9ncyBpZiBvbmUgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBjZlMzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLXMzLWFjY2Vzcy1sb2dzJyk7XG4gIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBjZlMzQWNjZXNzTG9nQnVja2V0XG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gUzMgQ29udGVudCBCdWNrZXQgQWNjZXNzIExvZ3MgQnVja2V0XG4vLyA9PT09PT09PT09PT09PT09PT09PT1cbnRlc3QoJ1Byb3ZpZGluZyBsb2dnaW5nQnVja2V0UHJvcHMgYW5kIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdsb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgfSxcbiAgICAgIGxvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgICBidWNrZXROYW1lOiAnYW55dGhpbmcnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3coL0Vycm9yIC0gYm90aGxvZyBidWNrZXQgcHJvcHMgYW5kIGFuIGV4aXN0aW5nIGxvZyBidWNrZXQgd2VyZSBwcm92aWRlZC5cXG4vKTtcbn0pO1xuXG50ZXN0KCdQcm92aWRpbmcgZXhpc3RpbmdMb2dnaW5nQnVja2V0IGFuZCBsb2dTM0FjY2Vzc0xvZ3M9ZmFsc2UgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBsb2dCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAnY2xvdWRmcm9udC1sb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgfSxcbiAgICAgIGxvZ1MzQWNjZXNzTG9nczogZmFsc2VcbiAgICB9KTtcbiAgfTtcbiAgZXhwZWN0KGFwcCkudG9UaHJvdygvRXJyb3IgLSBsb2dTM0FjY2Vzc0xvZ3MgaXMgZmFsc2UsIGJ1dCBhIGxvZyBidWNrZXQgd2FzIHByb3ZpZGVkIGluIGJ1Y2tldFByb3BzLlxcbi8pO1xufSk7XG5cbnRlc3QoJ1Byb3ZpZGluZyBsb2dnaW5nQnVja2V0UHJvcHMgYW5kIGxvZ1MzQWNjZXNzTG9ncz1mYWxzZSBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgICBsb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgYnVja2V0TmFtZTogJ2FueXRoaW5nJ1xuICAgICAgfSxcbiAgICAgIGxvZ1MzQWNjZXNzTG9nczogZmFsc2VcbiAgICB9KTtcbiAgfTtcbiAgLy8gTk9URTogVGhpcyBlcnJvciBpcyB0aHJvd24gYnkgQ2hlY2tTM1Byb3BzKCksIG5vdCBDaGVja0NvbnN0cnVjdFNwZWNpZmljUHJvcHMoKVxuICBleHBlY3QoYXBwKS50b1Rocm93KC9FcnJvciAtIElmIGxvZ1MzQWNjZXNzTG9ncyBpcyBmYWxzZSwgc3VwcGx5aW5nIGxvZ2dpbmdCdWNrZXRQcm9wcyBvciBleGlzdGluZ0xvZ2dpbmdCdWNrZXRPYmogaXMgaW52YWxpZC5cXG4vKTtcbn0pO1xuXG4vLyB0ZXN0KCdObyBuZXcgbG9nZ2luZ0J1Y2tldCBpcyBjcmVhdGVkIGlmIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbnRlc3QoJ2xvZ2dpbmdCdWNrZXRQcm9wcyBpcyBzdXBwbGllZCBpcyBpbnRlZ3JhdGVkIGludG8gYXJjaGl0ZWN0dXJlIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgdGVzdE5hbWUgPSBcInRlc3QtbmFtZVwiO1xuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0sXG4gICAgbG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0xvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG5cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICBCdWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIExvZ2dpbmdDb25maWd1cmF0aW9uOiB7XG4gICAgICBEZXN0aW5hdGlvbkJ1Y2tldE5hbWU6IHtcbiAgICAgICAgUmVmOiBNYXRjaC5zdHJpbmdMaWtlUmVnZXhwKCdjbG91ZGZyb250b2FpczNTM0xvZ2dpbmdCdWNrZXQnKVxuICAgICAgfVxuICAgIH1cbiAgfSk7XG59KTtcbnRlc3QoJ2J1Y2tldFByb3BzOnNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQgaXMgc3VwcGxpZWQgaXMgaW50ZWdyYXRlZCBpbnRvIGFyY2hpdGVjdHVyZSBjb3JyZWN0bHknLCAoKSA9PiB7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ3NvbWUtbmFtZSc7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBsb2dCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAndGVzdC1sb2cnLCB7XG4gICAgYnVja2V0TmFtZTogdGVzdE5hbWUsXG4gIH0pO1xuXG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGxvZ0J1Y2tldCxcbiAgICB9LFxuICB9KTtcblxuICBleHBlY3QoY29uc3RydWN0LnMzTG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICBMb2dnaW5nQ29uZmlndXJhdGlvbjoge1xuICAgICAgRGVzdGluYXRpb25CdWNrZXROYW1lOiB7XG4gICAgICAgIFJlZjogXCJ0ZXN0bG9nRTg4QjRDNkJcIlxuICAgICAgfVxuICAgIH1cbiAgfSk7XG59KTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09XG4vLyBDbG91ZEZyb250IExvZyBCdWNrZXRcbi8vID09PT09PT09PT09PT09PT09PT09PVxudGVzdCgnUHJvdmlkaW5nIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHMgYW5kIGEgbG9nIGJ1Y2tldCBpbiBjbG91ZEZyb250RGlzdHJidXRpb25Qcm9wcyBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgICAgbG9nQnVja2V0XG4gICAgICB9LFxuICAgICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3coKTtcbn0pO1xudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wcyBhcmUgdXNlZCBjb3JyZWN0bHknLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3ROYW1lID0gXCJ0ZXN0LW5hbWVcIjtcbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG59KTtcbnRlc3QoJ0xvZ2dpbmcgZGlzYWJsZWQgaW4gQ2xvdWRGcm9udCBwcm9wcyBpcyBoYW5kbGVkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gZGVwbG95KHN0YWNrLCB7IGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczogeyBlbmFibGVMb2dnaW5nOiBmYWxzZSB9IH0pO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gT25seSB0aGUgY29udGVudCBidWNrZXQgYW5kIGl0IFMzIEFjY2VzcyBMb2cgYnVja2V0IChubyBDbG91ZGZyb250IGxvZyBidWNrZXQpXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAyKTtcblxuICAvLyBObyBsb2dnaW5nIGlzIGNvbmZpZ3VyZWRcbiAgdGVtcGxhdGUucmVzb3VyY2VQcm9wZXJ0aWVzQ291bnRJcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IE1hdGNoLmFueVZhbHVlKClcbiAgICB9XG4gIH0sIDApO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0ID09PSB1bmRlZmluZWQpO1xufSk7XG50ZXN0KCdObyBuZXcgQ2xvdWRGcm9udExvZ2dpbmdCdWNrZXQgaXMgY3JlYXRlZCBpZiBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOmxvZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbiAgY29uc3QgdGVzdE5hbWUgPSAncmFuZG9tLXZhbHVlJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7XG4gICAgYnVja2V0TmFtZTogdGVzdE5hbWVcbiAgfSk7XG5cbiAgLy8gY29uc3QgY29uc3RydWN0ID1cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGxvZ0J1Y2tldFxuICAgIH0sXG4gIH0pO1xuXG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IGJ1Y2tldCwgQ29udGVudCBidWNrZXQgUzMgQWNjZXNzIExvZyBidWNrZXQsIGNsb3VkZnJvbnQgbG9nIGJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG5cbiAgLy8gRW5zdXJlIG91ciBleGlzdGluZyBidWNrZXQgaGFzIGJlZW4gdXNlZCBmb3IgY2xvdWRmcm9udCBsb2dnaW5nXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IHtcbiAgICAgICAgQnVja2V0OiB7XG4gICAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICAgIFwiY2xvdWRmcm9udGxvZ2J1Y2tldERGNzA1OEZCXCIsXG4gICAgICAgICAgICBcIlJlZ2lvbmFsRG9tYWluTmFtZVwiXG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2xvdWRGcm9udCBMb2dzIEJ1Y2tldCBBY2Nlc3MgTG9nIEJ1Y2tldFxuLy8gPT09PT09PT09PT09PT09PT09PT09XG50ZXN0KCdQcm92aWRpbmcgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgYnVja2V0TmFtZTogJ3NwZWNmaWMtbmFtZS1pcy1pbmNvbnNlcXVlbnRpYWwnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvdyhcbiAgICAvRXJyb3IgLSBhbiBleGlzdGluZyBDbG91ZEZyb250IGxvZyBidWNrZXQgUzMgYWNjZXNzIGxvZyBidWNrZXQgYW5kIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0UHJvcHMgd2VyZSBwcm92aWRlZFxcbi8pO1xufSk7XG50ZXN0KCdQcm92aWRpbmcgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyBhbmQgbG9nQ2xvdWRGcm9udEFjY2Vzc0xvZz1mYWxzZSBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9PYWlUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1vYWktczMnLCB7XG4gICAgICBsb2dDbG91ZEZyb250QWNjZXNzTG9nOiBmYWxzZSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgYnVja2V0TmFtZTogJ3NwZWNmaWMtbmFtZS1pcy1pbmNvbnNlcXVlbnRpYWwnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvdygvRXJyb3IgLSBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIHdlcmUgcHJvdmlkZWQgYnV0IGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2cgd2FzIGZhbHNlXFxuLyk7XG59KTtcbnRlc3QoJ1Byb3ZpZGluZyBsb2dDbG91ZEZyb250QWNjZXNzTG9nPWZhbHNlIGFuZCBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOnNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBsb2dCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAnY2xvdWRmcm9udC1sb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgICAgIHJlbW92YWxQb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlXG4gICAgICB9LFxuICAgICAgbG9nQ2xvdWRGcm9udEFjY2Vzc0xvZzogZmFsc2UsXG4gICAgfSk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvdygvRXJyb3IgLSBwcm9wcy5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzLnNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQgd2FzIHByb3ZpZGVkIGJ1dCBsb2dDbG91ZEZyb250QWNjZXNzTG9nIHdhcyBmYWxzZVxcbi8pO1xufSk7XG50ZXN0KCdjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIGFyZSB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxufSk7XG50ZXN0KCdJZiBleGlzdGluZyBDbG91ZEZyb250IExvZyBidWNrZXQgUzMgQWNjZXNzIExvZ2dpbmcgYnVja2V0IGlzIHByb3ZpZGVkLCBpdCBpcyB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ2NmLWxvZy1zMy1sb2cnO1xuICBjb25zdCBjZkxvZ1MzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLWxvZy1zMy1hY2Nlc3MtbG9nLWJ1Y2tldCcsIHtcbiAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGNmTG9nUzNBY2Nlc3NMb2dCdWNrZXRcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgTG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIERlc3RpbmF0aW9uQnVja2V0TmFtZToge1xuICAgICAgICBSZWY6IFwiY2Zsb2dzM2FjY2Vzc2xvZ2J1Y2tldERFMzc0QzI3XCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG59KTtcblxudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXQgcHJvcGVydHkgaXMgc2V0IGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb09haVRvUzMoc3RhY2ssICdjbG91ZGZyb250LW9haS1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCEuYnVja2V0TmFtZSkudG9CZURlZmluZWQoKTtcbn0pO1xuXG50ZXN0KCdsb2dDbG91ZEZyb250QWNjZXNzTG9nIHByb3BlcnR5IGlzIHVzZWQgY29ycmVjdGx5JywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtb2FpLXMzJywge1xuICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlXG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAzKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkubm90LnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdCgnVGVzdCB0aGF0IFZhbGlkYXRlRGlzdHJpYnV0aW9uUHJvcHMoKSBpcyBiZWluZyBjYWxsZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBwcm9wczogQ2xvdWRGcm9udFRvT2FpVG9TM1Byb3BzID0ge1xuICAgIGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczoge1xuICAgICAgaW52YWxpZFByb3BlcnR5OiB0cnVlXG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvT2FpVG9TMyhzdGFjaywgJ3Rlc3QtY29uc3RydWN0JywgcHJvcHMpO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3coL0VSUk9SIC0gaW52YWxpZFByb3BlcnR5IGlzIG5vdCBhIHZhbGlkIHByb3BlcnR5IG9mIERpc3RyaWJ1dGlvblByb3BzLyk7XG59KTtcbiJdfQ==