@aws-solutions-constructs/aws-cloudfront-s3 2.99.0 → 2.100.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.
@@ -1,847 +0,0 @@
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
- const origins = require("aws-cdk-lib/aws-cloudfront-origins");
24
- const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
25
- function deploy(stack, props) {
26
- return new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
27
- bucketProps: {
28
- removalPolicy: cdk.RemovalPolicy.DESTROY,
29
- },
30
- ...props
31
- });
32
- }
33
- test('construct defaults set properties correctly', () => {
34
- const stack = new cdk.Stack();
35
- const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
36
- expect(construct.cloudFrontWebDistribution).toBeDefined();
37
- expect(construct.cloudFrontFunction).toBeDefined();
38
- expect(construct.cloudFrontLoggingBucket).toBeDefined();
39
- expect(construct.s3Bucket).toBeDefined();
40
- expect(construct.s3LoggingBucket).toBeDefined();
41
- expect(construct.s3BucketInterface).toBeDefined();
42
- expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
43
- expect(construct.originAccessControl).toBeDefined();
44
- });
45
- test('check s3Bucket default encryption', () => {
46
- const stack = new cdk.Stack();
47
- deploy(stack);
48
- const template = assertions_1.Template.fromStack(stack);
49
- template.hasResourceProperties('AWS::S3::Bucket', {
50
- BucketEncryption: {
51
- ServerSideEncryptionConfiguration: [{
52
- ServerSideEncryptionByDefault: {
53
- SSEAlgorithm: "AES256"
54
- }
55
- }]
56
- }
57
- });
58
- });
59
- test('check s3Bucket public access block configuration', () => {
60
- const stack = new cdk.Stack();
61
- deploy(stack);
62
- const template = assertions_1.Template.fromStack(stack);
63
- template.hasResourceProperties('AWS::S3::Bucket', {
64
- PublicAccessBlockConfiguration: {
65
- BlockPublicAcls: true,
66
- BlockPublicPolicy: true,
67
- IgnorePublicAcls: true,
68
- RestrictPublicBuckets: true
69
- }
70
- });
71
- });
72
- test('test s3Bucket override publicAccessBlockConfiguration', () => {
73
- const stack = new cdk.Stack();
74
- const props = {
75
- bucketProps: {
76
- blockPublicAccess: {
77
- blockPublicAcls: false,
78
- blockPublicPolicy: true,
79
- ignorePublicAcls: false,
80
- restrictPublicBuckets: true
81
- }
82
- }
83
- };
84
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
85
- const template = assertions_1.Template.fromStack(stack);
86
- template.hasResourceProperties("AWS::S3::Bucket", {
87
- PublicAccessBlockConfiguration: {
88
- BlockPublicAcls: false,
89
- BlockPublicPolicy: true,
90
- IgnorePublicAcls: false,
91
- RestrictPublicBuckets: true
92
- },
93
- });
94
- });
95
- test('check existing bucket', () => {
96
- const stack = new cdk.Stack();
97
- const existingBucket = new s3.Bucket(stack, 'my-bucket', {
98
- bucketName: 'my-bucket'
99
- });
100
- const props = {
101
- existingBucketObj: existingBucket
102
- };
103
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
104
- const template = assertions_1.Template.fromStack(stack);
105
- template.hasResourceProperties("AWS::S3::Bucket", {
106
- BucketName: "my-bucket"
107
- });
108
- });
109
- test('check exception for Missing existingObj from props for deploy = false', () => {
110
- const stack = new cdk.Stack();
111
- try {
112
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
113
- }
114
- catch (e) {
115
- expect(e).toBeInstanceOf(Error);
116
- }
117
- });
118
- test('check properties', () => {
119
- const stack = new cdk.Stack();
120
- const construct = deploy(stack);
121
- expect(construct.cloudFrontWebDistribution).toBeDefined();
122
- expect(construct.s3Bucket).toBeDefined();
123
- });
124
- test("Confirm CheckS3Props is called", () => {
125
- // Stack
126
- const stack = new cdk.Stack();
127
- const testBucket = new s3.Bucket(stack, 'test-bucket', {});
128
- const app = () => {
129
- // Helper declaration
130
- new lib_1.CloudFrontToS3(stack, "bad-s3-args", {
131
- existingBucketObj: testBucket,
132
- bucketProps: {
133
- removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
134
- },
135
- });
136
- };
137
- // Assertion
138
- expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n');
139
- });
140
- test("Test existingBucketObj", () => {
141
- // Stack
142
- const stack = new cdk.Stack();
143
- const construct = new lib_1.CloudFrontToS3(stack, "existingIBucket", {
144
- existingBucketObj: s3.Bucket.fromBucketName(stack, 'mybucket', 'mybucket')
145
- });
146
- // Assertion
147
- expect(construct.cloudFrontWebDistribution).toBeDefined();
148
- const template = assertions_1.Template.fromStack(stack);
149
- template.hasResourceProperties("AWS::CloudFront::Distribution", {
150
- DistributionConfig: {
151
- Origins: [
152
- {
153
- DomainName: {
154
- "Fn::Join": [
155
- "",
156
- [
157
- "mybucket.s3.",
158
- {
159
- Ref: "AWS::Region"
160
- },
161
- ".",
162
- {
163
- Ref: "AWS::URLSuffix"
164
- }
165
- ]
166
- ]
167
- },
168
- Id: "existingIBucketCloudFrontDistributionOrigin1D5849125",
169
- OriginAccessControlId: { "Fn::GetAtt": ["existingIBucketCloudFrontOacEB42E98F", "Id"] },
170
- S3OriginConfig: {}
171
- }
172
- ]
173
- }
174
- });
175
- });
176
- test('test cloudfront with custom domain names', () => {
177
- const stack = new cdk.Stack();
178
- const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:${Aws.PARTITION}:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012');
179
- const props = {
180
- cloudFrontDistributionProps: {
181
- domainNames: ['mydomains'],
182
- certificate
183
- }
184
- };
185
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
186
- const template = assertions_1.Template.fromStack(stack);
187
- template.hasResourceProperties("AWS::CloudFront::Distribution", {
188
- DistributionConfig: {
189
- Aliases: [
190
- "mydomains"
191
- ]
192
- }
193
- });
194
- });
195
- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => {
196
- const stack = new cdk.Stack();
197
- const cloudfrontLogBucketName = 'cf-log-bucket';
198
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
199
- cloudFrontLoggingBucketProps: {
200
- removalPolicy: cdk.RemovalPolicy.DESTROY,
201
- autoDeleteObjects: true,
202
- bucketName: cloudfrontLogBucketName
203
- }
204
- });
205
- const template = assertions_1.Template.fromStack(stack);
206
- template.hasResourceProperties("AWS::S3::Bucket", {
207
- OwnershipControls: { Rules: [{ ObjectOwnership: "ObjectWriter" }] },
208
- BucketName: cloudfrontLogBucketName,
209
- });
210
- template.hasResourceProperties("Custom::S3AutoDeleteObjects", {
211
- ServiceToken: {
212
- "Fn::GetAtt": [
213
- "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F",
214
- "Arn"
215
- ]
216
- },
217
- BucketName: {
218
- Ref: "cloudfronts3CloudfrontLoggingBucket5B845143"
219
- }
220
- });
221
- });
222
- test('s3 bucket with one content bucket and no access logging of CONTENT bucket', () => {
223
- const stack = new cdk.Stack();
224
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
225
- bucketProps: {
226
- removalPolicy: cdk.RemovalPolicy.DESTROY,
227
- },
228
- logS3AccessLogs: false
229
- });
230
- const template = assertions_1.Template.fromStack(stack);
231
- // Content bucket+Cloudfront Logs bucket+
232
- // Access Log bucket for Cloudfront Logs bucket = 3 buckets
233
- template.resourceCountIs("AWS::S3::Bucket", 3);
234
- expect(construct.s3LoggingBucket).toEqual(undefined);
235
- });
236
- test('CloudFront origin path present when provided', () => {
237
- const stack = new cdk.Stack();
238
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
239
- originPath: '/testPath'
240
- });
241
- const template = assertions_1.Template.fromStack(stack);
242
- template.hasResourceProperties("AWS::CloudFront::Distribution", {
243
- DistributionConfig: {
244
- Origins: [
245
- {
246
- OriginPath: "/testPath",
247
- }
248
- ]
249
- }
250
- });
251
- });
252
- test('CloudFront origin path should not be present if not provided', () => {
253
- const stack = new cdk.Stack();
254
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {});
255
- defaults.expectNonexistence(stack, "AWS::CloudFront::Distribution", {
256
- DistributionConfig: {
257
- Origins: [
258
- {
259
- OriginPath: "/testPath",
260
- }
261
- ]
262
- }
263
- });
264
- });
265
- test('Test the deployment with securityHeadersBehavior instead of HTTP security headers', () => {
266
- // Initial setup
267
- const stack = new aws_cdk_lib_1.Stack();
268
- const cloudFrontToS3 = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
269
- insertHttpSecurityHeaders: false,
270
- responseHeadersPolicyProps: {
271
- securityHeadersBehavior: {
272
- strictTransportSecurity: {
273
- accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
274
- includeSubdomains: true,
275
- override: true,
276
- preload: true
277
- },
278
- contentSecurityPolicy: {
279
- contentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
280
- override: true
281
- },
282
- }
283
- }
284
- });
285
- // Assertion
286
- const template = assertions_1.Template.fromStack(stack);
287
- template.hasResourceProperties("AWS::CloudFront::ResponseHeadersPolicy", {
288
- ResponseHeadersPolicyConfig: {
289
- SecurityHeadersConfig: {
290
- ContentSecurityPolicy: {
291
- ContentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
292
- Override: true
293
- },
294
- StrictTransportSecurity: {
295
- AccessControlMaxAgeSec: 63072,
296
- IncludeSubdomains: true,
297
- Override: true,
298
- Preload: true
299
- }
300
- }
301
- }
302
- });
303
- expect(cloudFrontToS3.cloudFrontFunction).toEqual(undefined);
304
- });
305
- test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProps are provided", () => {
306
- const stack = new cdk.Stack();
307
- expect(() => {
308
- new lib_1.CloudFrontToS3(stack, "test-cloudfront-s3", {
309
- insertHttpSecurityHeaders: true,
310
- responseHeadersPolicyProps: {
311
- securityHeadersBehavior: {
312
- strictTransportSecurity: {
313
- accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
314
- includeSubdomains: true,
315
- override: false,
316
- preload: true
317
- }
318
- }
319
- }
320
- });
321
- }).toThrowError();
322
- });
323
- test("Confirm CheckCloudFrontProps is being called", () => {
324
- const stack = new cdk.Stack();
325
- expect(() => {
326
- new lib_1.CloudFrontToS3(stack, "test-cloudfront-apigateway", {
327
- insertHttpSecurityHeaders: true,
328
- responseHeadersPolicyProps: {
329
- securityHeadersBehavior: {
330
- strictTransportSecurity: {
331
- accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
332
- includeSubdomains: true,
333
- override: false,
334
- preload: true
335
- }
336
- }
337
- }
338
- });
339
- }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.');
340
- });
341
- test("Custom resource is provisioned if encryption key is provided as bucketProp", () => {
342
- const stack = new cdk.Stack();
343
- const encryptionKey = new aws_kms_1.Key(stack, 'cmkKey', {
344
- enableKeyRotation: true,
345
- removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
346
- });
347
- deploy(stack, {
348
- bucketProps: {
349
- encryptionKey,
350
- encryption: s3.BucketEncryption.KMS
351
- }
352
- });
353
- const template = assertions_1.Template.fromStack(stack);
354
- // 2 Functions - our custom resource and a function created by the CDK
355
- template.resourceCountIs('AWS::Lambda::Function', 2);
356
- template.hasResourceProperties('AWS::Lambda::Function', {
357
- Description: "Custom resource function that updates a provided key policy to allow CloudFront access.",
358
- Role: {
359
- "Fn::GetAtt": ["testcloudfronts3LambdaFunctionServiceRole2A43EA92", "Arn"]
360
- }
361
- });
362
- });
363
- test("Custom resource is provisioned if CMK was used to encrypt an existing bucket", () => {
364
- const stack = new cdk.Stack();
365
- const encryptionKey = new aws_kms_1.Key(stack, 'cmkKey', {
366
- enableKeyRotation: true,
367
- removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
368
- });
369
- const existingBucketObj = defaults.buildS3Bucket(stack, {
370
- bucketProps: {
371
- encryption: s3.BucketEncryption.KMS,
372
- encryptionKey
373
- }
374
- }, 'existing-s3-bucket-encrypted-with-cmk').bucket;
375
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
376
- existingBucketObj
377
- });
378
- const template = assertions_1.Template.fromStack(stack);
379
- // 2 Functions - our custom resource and a function created by the CDK
380
- template.resourceCountIs('AWS::Lambda::Function', 2);
381
- // ensure that our Function has the correct role attached
382
- template.hasResourceProperties('AWS::Lambda::Function', {
383
- Description: "Custom resource function that updates a provided key policy to allow CloudFront access.",
384
- Role: {
385
- "Fn::GetAtt": ["testcloudfronts3LambdaFunctionServiceRole2A43EA92", "Arn"]
386
- }
387
- });
388
- });
389
- test("Custom resource is not provisioned if encryption key is not provided as bucketProp", () => {
390
- const stack = new cdk.Stack();
391
- deploy(stack);
392
- const template = assertions_1.Template.fromStack(stack);
393
- template.resourceCountIs('AWS::Lambda::Function', 0);
394
- });
395
- test("Custom resource is not provisioned if CMK was not used to encrypt an existing bucket", () => {
396
- const stack = new cdk.Stack();
397
- const existingBucketObj = defaults.buildS3Bucket(stack, {}, 'existing-s3-bucket-encrypted-with-cmk').bucket;
398
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
399
- existingBucketObj
400
- });
401
- const template = assertions_1.Template.fromStack(stack);
402
- template.resourceCountIs('AWS::Lambda::Function', 0);
403
- });
404
- test("HttpOrigin is provisioned if a static website bucket is used", () => {
405
- const stack = new cdk.Stack();
406
- const blockPublicAccess = false;
407
- const props = {
408
- bucketProps: {
409
- enforceSSL: false,
410
- publicReadAccess: true, // <-- required for isWebsite
411
- blockPublicAccess: {
412
- blockPublicAcls: blockPublicAccess,
413
- restrictPublicBuckets: blockPublicAccess,
414
- blockPublicPolicy: blockPublicAccess,
415
- ignorePublicAcls: blockPublicAccess
416
- },
417
- websiteIndexDocument: "index.html" // <-- required for isWebsite
418
- },
419
- insertHttpSecurityHeaders: false
420
- };
421
- const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
422
- const template = assertions_1.Template.fromStack(stack);
423
- // Assert resources
424
- template.resourceCountIs('AWS::CloudFront::OriginAccessControl', 0);
425
- template.hasResourceProperties('AWS::CloudFront::Distribution', {
426
- DistributionConfig: {
427
- Origins: [
428
- {
429
- CustomOriginConfig: {
430
- OriginProtocolPolicy: "http-only"
431
- }
432
- }
433
- ]
434
- }
435
- });
436
- template.resourceCountIs('AWS::CloudFront::OriginAccessIdentity', 0);
437
- // Assert pattern properties (output props)
438
- expect(construct.originAccessControl).toBe(undefined);
439
- });
440
- test("OAC is provisioned in all other cases", () => {
441
- const stack = new cdk.Stack();
442
- const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
443
- const template = assertions_1.Template.fromStack(stack);
444
- // Assert resources
445
- template.resourceCountIs('AWS::CloudFront::OriginAccessControl', 1);
446
- template.resourceCountIs('AWS::CloudFront::OriginAccessIdentity', 0);
447
- // Assert pattern properties (output props)
448
- expect(construct.originAccessControl).not.toBe(undefined);
449
- });
450
- test("If a customer provides their own httpOrigin, or other origin type, use that one", () => {
451
- const stack = new cdk.Stack();
452
- const blockPublicAccess = false;
453
- const props = {
454
- bucketProps: {
455
- enforceSSL: false,
456
- publicReadAccess: true, // <-- required for isWebsite
457
- blockPublicAccess: {
458
- blockPublicAcls: blockPublicAccess,
459
- restrictPublicBuckets: blockPublicAccess,
460
- blockPublicPolicy: blockPublicAccess,
461
- ignorePublicAcls: blockPublicAccess
462
- },
463
- websiteIndexDocument: "index.html" // <-- required for isWebsite
464
- },
465
- insertHttpSecurityHeaders: false,
466
- cloudFrontDistributionProps: {
467
- defaultBehavior: {
468
- origin: new origins.HttpOrigin('example.com', {
469
- originId: 'custom-http-origin-for-testing'
470
- })
471
- }
472
- }
473
- };
474
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
475
- const template = assertions_1.Template.fromStack(stack);
476
- // Assert resources
477
- template.hasResourceProperties('AWS::CloudFront::Distribution', {
478
- DistributionConfig: {
479
- Origins: [
480
- {
481
- DomainName: "example.com",
482
- Id: "custom-http-origin-for-testing"
483
- }
484
- ]
485
- }
486
- });
487
- });
488
- test('Test that we do not create an Access Log bucket for CF logs if one is provided', () => {
489
- const stack = new cdk.Stack();
490
- const cfS3AccessLogBucket = new s3.Bucket(stack, 'cf-s3-access-logs');
491
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
492
- cloudFrontLoggingBucketProps: {
493
- serverAccessLogsBucket: cfS3AccessLogBucket
494
- }
495
- });
496
- const template = assertions_1.Template.fromStack(stack);
497
- template.resourceCountIs("AWS::S3::Bucket", 4);
498
- });
499
- // =====================
500
- // S3 Content Bucket Access Logs Bucket
501
- // =====================
502
- test('Providing loggingBucketProps and existingLoggingBucket is an error', () => {
503
- const stack = new cdk.Stack();
504
- const logBucket = new s3.Bucket(stack, 'log-bucket', {});
505
- const app = () => {
506
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
507
- bucketProps: {
508
- serverAccessLogsBucket: logBucket,
509
- },
510
- loggingBucketProps: {
511
- bucketName: 'anything'
512
- }
513
- });
514
- };
515
- expect(app).toThrowError(/Error - bothlog bucket props and an existing log bucket were provided.\n/);
516
- });
517
- test('Providing existingLoggingBucket and logS3AccessLogs=false is an error', () => {
518
- const stack = new cdk.Stack();
519
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
520
- const app = () => {
521
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
522
- bucketProps: {
523
- serverAccessLogsBucket: logBucket,
524
- },
525
- logS3AccessLogs: false
526
- });
527
- };
528
- expect(app).toThrowError(/Error - logS3AccessLogs is false, but a log bucket was provided in bucketProps.\n/);
529
- });
530
- test('Providing loggingBucketProps and logS3AccessLogs=false is an error', () => {
531
- const stack = new cdk.Stack();
532
- const app = () => {
533
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
534
- loggingBucketProps: {
535
- bucketName: 'anything'
536
- },
537
- logS3AccessLogs: false
538
- });
539
- };
540
- // NOTE: This error is thrown by CheckS3Props(), not CheckConstructSpecificProps()
541
- expect(app).toThrowError(/Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n/);
542
- });
543
- // test('No new loggingBucket is created if existingLoggingBucket is supplied', () => {
544
- test('loggingBucketProps is supplied is integrated into architecture correctly', () => {
545
- const stack = new cdk.Stack();
546
- const testName = "test-name";
547
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
548
- bucketProps: {
549
- removalPolicy: cdk.RemovalPolicy.DESTROY,
550
- },
551
- loggingBucketProps: {
552
- removalPolicy: cdk.RemovalPolicy.DESTROY,
553
- autoDeleteObjects: true,
554
- bucketName: testName
555
- }
556
- });
557
- expect(construct.s3LoggingBucket).toBeDefined();
558
- const template = assertions_1.Template.fromStack(stack);
559
- template.resourceCountIs("AWS::S3::Bucket", 4);
560
- template.hasResourceProperties("AWS::S3::Bucket", {
561
- BucketName: testName
562
- });
563
- template.hasResourceProperties("AWS::S3::Bucket", {
564
- LoggingConfiguration: {
565
- DestinationBucketName: {
566
- Ref: "cloudfronts3S3LoggingBucket52EEB708"
567
- }
568
- }
569
- });
570
- });
571
- test('bucketProps:serverAccessLogsBucket is supplied is integrated into architecture correctly', () => {
572
- const testName = 'some-name';
573
- const stack = new cdk.Stack();
574
- const logBucket = new s3.Bucket(stack, 'test-log', {
575
- bucketName: testName,
576
- });
577
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
578
- bucketProps: {
579
- serverAccessLogsBucket: logBucket,
580
- },
581
- });
582
- expect(construct.s3LoggingBucket).toBeDefined();
583
- const template = assertions_1.Template.fromStack(stack);
584
- template.resourceCountIs("AWS::S3::Bucket", 4);
585
- template.hasResourceProperties("AWS::S3::Bucket", {
586
- LoggingConfiguration: {
587
- DestinationBucketName: {
588
- Ref: "testlogE88B4C6B"
589
- }
590
- }
591
- });
592
- });
593
- // =====================
594
- // CloudFront Log Bucket
595
- // =====================
596
- test('Providing cloudFrontLoggingBucketProps and a log bucket in cloudFrontDistrbutionProps is an error', () => {
597
- const stack = new cdk.Stack();
598
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
599
- const app = () => {
600
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
601
- cloudFrontDistributionProps: {
602
- logBucket
603
- },
604
- cloudFrontLoggingBucketProps: {
605
- removalPolicy: cdk.RemovalPolicy.DESTROY,
606
- autoDeleteObjects: true
607
- }
608
- });
609
- };
610
- expect(app).toThrowError();
611
- });
612
- test('cloudFrontLoggingBucketProps are used correctly', () => {
613
- const stack = new cdk.Stack();
614
- const testName = "test-name";
615
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
616
- cloudFrontLoggingBucketProps: {
617
- removalPolicy: cdk.RemovalPolicy.DESTROY,
618
- autoDeleteObjects: true,
619
- bucketName: testName
620
- }
621
- });
622
- expect(construct.cloudFrontLoggingBucket).toBeDefined();
623
- const template = assertions_1.Template.fromStack(stack);
624
- template.resourceCountIs("AWS::S3::Bucket", 4);
625
- template.hasResourceProperties("AWS::S3::Bucket", {
626
- BucketName: testName
627
- });
628
- });
629
- test('Logging disabled in CloudFront props is handled correctly', () => {
630
- const stack = new cdk.Stack();
631
- const construct = deploy(stack, { cloudFrontDistributionProps: { enableLogging: false } });
632
- const template = assertions_1.Template.fromStack(stack);
633
- // Only the content bucket and it S3 Access Log bucket (no Cloudfront log bucket)
634
- template.resourceCountIs("AWS::S3::Bucket", 2);
635
- // No logging is configured
636
- template.resourcePropertiesCountIs("AWS::CloudFront::Distribution", {
637
- DistributionConfig: {
638
- Logging: assertions_1.Match.anyValue()
639
- }
640
- }, 0);
641
- expect(construct.cloudFrontLoggingBucket === undefined);
642
- });
643
- test('No new CloudFrontLoggingBucket is created if cloudFrontLoggingBucketProps:logBucket is supplied', () => {
644
- const testName = 'random-value';
645
- const stack = new cdk.Stack();
646
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {
647
- bucketName: testName
648
- });
649
- // const construct =
650
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
651
- cloudFrontDistributionProps: {
652
- logBucket
653
- },
654
- });
655
- expect(construct.cloudFrontLoggingBucket).toBeDefined();
656
- const template = assertions_1.Template.fromStack(stack);
657
- // Content bucket, Content bucket S3 Access Log bucket, cloudfront log bucket
658
- template.resourceCountIs("AWS::S3::Bucket", 3);
659
- // Ensure our existing bucket has been used for cloudfront logging
660
- template.hasResourceProperties("AWS::CloudFront::Distribution", {
661
- DistributionConfig: {
662
- Logging: {
663
- Bucket: {
664
- "Fn::GetAtt": [
665
- "cloudfrontlogbucketDF7058FB",
666
- "RegionalDomainName"
667
- ]
668
- }
669
- }
670
- }
671
- });
672
- });
673
- // =====================
674
- // CloudFront Logs Bucket Access Log Bucket
675
- // =====================
676
- test('Providing cloudFrontLoggingBucketAccessLogBucketProps and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
677
- const stack = new cdk.Stack();
678
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
679
- const app = () => {
680
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
681
- cloudFrontLoggingBucketProps: {
682
- serverAccessLogsBucket: logBucket,
683
- removalPolicy: cdk.RemovalPolicy.DESTROY,
684
- autoDeleteObjects: true
685
- },
686
- cloudFrontLoggingBucketAccessLogBucketProps: {
687
- bucketName: 'specfic-name-is-inconsequential'
688
- }
689
- });
690
- };
691
- expect(app).toThrowError(/Error - an existing CloudFront log bucket S3 access log bucket and cloudFrontLoggingBucketAccessLogBucketProps were provided\n/);
692
- });
693
- test('Providing cloudFrontLoggingBucketAccessLogBucketProps and logCloudFrontAccessLog=false is an error', () => {
694
- const stack = new cdk.Stack();
695
- const app = () => {
696
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
697
- logCloudFrontAccessLog: false,
698
- cloudFrontLoggingBucketAccessLogBucketProps: {
699
- bucketName: 'specfic-name-is-inconsequential'
700
- }
701
- });
702
- };
703
- expect(app).toThrowError(/Error - cloudFrontLoggingBucketAccessLogBucketProps were provided but logCloudFrontAccessLog was false\n/);
704
- });
705
- test('Providing logCloudFrontAccessLog=false and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
706
- const stack = new cdk.Stack();
707
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
708
- const app = () => {
709
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
710
- cloudFrontLoggingBucketProps: {
711
- serverAccessLogsBucket: logBucket,
712
- removalPolicy: cdk.RemovalPolicy.DESTROY,
713
- autoDeleteObjects: true
714
- },
715
- logCloudFrontAccessLog: false,
716
- });
717
- };
718
- expect(app).toThrowError(/Error - props.cloudFrontLoggingBucketProps.serverAccessLogsBucket was provided but logCloudFrontAccessLog was false\n/);
719
- });
720
- test('cloudFrontLoggingBucketAccessLogBucketProps are used correctly', () => {
721
- const stack = new cdk.Stack();
722
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
723
- cloudFrontLoggingBucketAccessLogBucketProps: {
724
- websiteErrorDocument: 'placeholder',
725
- websiteIndexDocument: 'placeholde-two'
726
- }
727
- });
728
- const template = assertions_1.Template.fromStack(stack);
729
- // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
730
- template.resourceCountIs("AWS::S3::Bucket", 4);
731
- template.hasResourceProperties("AWS::S3::Bucket", {
732
- WebsiteConfiguration: {
733
- ErrorDocument: 'placeholder',
734
- IndexDocument: 'placeholde-two'
735
- }
736
- });
737
- });
738
- test('If existing CloudFront Log bucket S3 Access Logging bucket is provided, it is used correctly', () => {
739
- const stack = new cdk.Stack();
740
- const testName = 'cf-log-s3-log';
741
- const cfLogS3AccessLogBucket = new s3.Bucket(stack, 'cf-log-s3-access-log-bucket', {
742
- bucketName: testName
743
- });
744
- new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
745
- cloudFrontLoggingBucketProps: {
746
- serverAccessLogsBucket: cfLogS3AccessLogBucket
747
- }
748
- });
749
- const template = assertions_1.Template.fromStack(stack);
750
- // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
751
- template.resourceCountIs("AWS::S3::Bucket", 4);
752
- template.hasResourceProperties("AWS::S3::Bucket", {
753
- BucketName: testName
754
- });
755
- template.hasResourceProperties("AWS::S3::Bucket", {
756
- LoggingConfiguration: {
757
- DestinationBucketName: {
758
- Ref: "cflogs3accesslogbucketDE374C27"
759
- }
760
- }
761
- });
762
- });
763
- test('cloudFrontLoggingBucketAccessLogBucket property is set correctly', () => {
764
- const stack = new cdk.Stack();
765
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
766
- cloudFrontLoggingBucketAccessLogBucketProps: {
767
- websiteErrorDocument: 'placeholder',
768
- websiteIndexDocument: 'placeholde-two'
769
- }
770
- });
771
- const template = assertions_1.Template.fromStack(stack);
772
- // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
773
- template.resourceCountIs("AWS::S3::Bucket", 4);
774
- template.hasResourceProperties("AWS::S3::Bucket", {
775
- WebsiteConfiguration: {
776
- ErrorDocument: 'placeholder',
777
- IndexDocument: 'placeholde-two'
778
- }
779
- });
780
- expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
781
- expect(construct.cloudFrontLoggingBucketAccessLogBucket.bucketName).toBeDefined();
782
- });
783
- test('logCloudFrontAccessLog property is used correctly', () => {
784
- const stack = new cdk.Stack();
785
- const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
786
- logCloudFrontAccessLog: false
787
- });
788
- const template = assertions_1.Template.fromStack(stack);
789
- // Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
790
- template.resourceCountIs("AWS::S3::Bucket", 3);
791
- expect(construct.cloudFrontLoggingBucket).toBeDefined();
792
- expect(construct.cloudFrontLoggingBucketAccessLogBucket).not.toBeDefined();
793
- });
794
- test('additionalBehaviors have correct origin', () => {
795
- const stack = new cdk.Stack();
796
- const additionalBucket = defaults.CreateScrapBucket(stack, "scrapBucket", {
797
- removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
798
- autoDeleteObjects: true,
799
- });
800
- const originAccessControl = new aws_cloudfront_1.CfnOriginAccessControl(stack, 'CloudFrontOac', {
801
- originAccessControlConfig: {
802
- name: defaults.generatePhysicalOacName('aws-cloudfront-s3-', [__filename]),
803
- originAccessControlOriginType: 's3',
804
- signingBehavior: 'always',
805
- signingProtocol: 'sigv4',
806
- description: 'Origin access control provisioned by aws-cloudfront-s3'
807
- }
808
- });
809
- const additionalOrigin = new defaults.S3OacOrigin(additionalBucket, {
810
- originAccessControl
811
- });
812
- new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
813
- cloudFrontDistributionProps: {
814
- additionalBehaviors: {
815
- '/assets/public/*': {
816
- origin: additionalOrigin,
817
- cachePolicy: aws_cloudfront_1.CachePolicy.CACHING_DISABLED,
818
- },
819
- 'ngsw.json': {
820
- cachePolicy: aws_cloudfront_1.CachePolicy.CACHING_DISABLED,
821
- }
822
- }
823
- }
824
- });
825
- const template = assertions_1.Template.fromStack(stack);
826
- template.hasResourceProperties("AWS::CloudFront::Distribution", {
827
- DistributionConfig: {
828
- CacheBehaviors: [
829
- {
830
- CachePolicyId: "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
831
- Compress: true,
832
- PathPattern: "/assets/public/*",
833
- TargetOriginId: "testcloudfronts3CloudFrontDistributionOrigin21D78391C",
834
- ViewerProtocolPolicy: "allow-all"
835
- },
836
- {
837
- CachePolicyId: "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
838
- Compress: true,
839
- PathPattern: "ngsw.json",
840
- TargetOriginId: "testcloudfronts3CloudFrontDistributionOrigin124051039",
841
- ViewerProtocolPolicy: "allow-all"
842
- }
843
- ],
844
- }
845
- });
846
- });
847
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5jbG91ZGZyb250LXMzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LmNsb3VkZnJvbnQtczMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBRUgsdURBQXlEO0FBQ3pELHlDQUF5QztBQUN6QyxtQ0FBbUM7QUFDbkMsNkNBQTZEO0FBQzdELGdDQUE2RDtBQUM3RCwwREFBMEQ7QUFDMUQsMkRBQTJEO0FBQzNELGlEQUEwQztBQUMxQyw4REFBOEQ7QUFDOUQsK0RBQWlGO0FBRWpGLFNBQVMsTUFBTSxDQUFDLEtBQWdCLEVBQUUsS0FBMkI7SUFDM0QsT0FBTyxJQUFJLG9CQUFjLENBQUMsS0FBSyxFQUFFLG9CQUFvQixFQUFFO1FBQ3JELFdBQVcsRUFBRTtZQUNYLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLE9BQU87U0FDekM7UUFDRCxHQUFHLEtBQUs7S0FDVCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtJQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixNQUFNLFNBQVMsR0FBRyxJQUFJLG9CQUFjLENBQUMsS0FBSyxFQUFFLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXRFLE1BQU0sQ0FBQyxTQUFTLENBQUMseUJBQXlCLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUMxRCxNQUFNLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbkQsTUFBTSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3hELE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDekMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FB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RUFBRTtRQUNsRSxtQkFBbUI7S0FDcEIsQ0FBQyxDQUFDO0lBRUgsSUFBSSxvQkFBYyxDQUFDLEtBQUssRUFBRSxvQkFBb0IsRUFBRTtRQUM5QywyQkFBMkIsRUFBRTtZQUMzQixtQkFBbUIsRUFBRTtnQkFDbkIsa0JBQWtCLEVBQUU7b0JBQ2xCLE1BQU0sRUFBRSxnQkFBZ0I7b0JBQ3hCLFdBQVcsRUFBRSw0QkFBVyxDQUFDLGdCQUFnQjtpQkFDMUM7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLFdBQVcsRUFBRSw0QkFBVyxDQUFDLGdCQUFnQjtpQkFDMUM7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO1FBQzlELGtCQUFrQixFQUFFO1lBQ2xCLGNBQWMsRUFBRTtnQkFDZDtvQkFDRSxhQUFhLEVBQUUsc0NBQXNDO29CQUNyRCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxXQUFXLEVBQUUsa0JBQWtCO29CQUMvQixjQUFjLEVBQUUsdURBQXVEO29CQUN2RSxvQkFBb0IsRUFBRSxXQUFXO2lCQUNsQztnQkFDRDtvQkFDRSxhQUFhLEVBQUUsc0NBQXNDO29CQUNyRCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxXQUFXLEVBQUUsV0FBVztvQkFDeEIsY0FBYyxFQUFFLHVEQUF1RDtvQkFDdkUsb0JBQW9CLEVBQUUsV0FBVztpQkFDbEM7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBNYXRjaCwgVGVtcGxhdGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXNzZXJ0aW9uc1wiO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IER1cmF0aW9uLCBSZW1vdmFsUG9saWN5LCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRvUzMsIENsb3VkRnJvbnRUb1MzUHJvcHMgfSBmcm9tIFwiLi4vbGliXCI7XG5pbXBvcnQgKiBhcyBhY20gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tICdAYXdzLXNvbHV0aW9ucy1jb25zdHJ1Y3RzL2NvcmUnO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1rbXNcIjtcbmltcG9ydCAqIGFzIG9yaWdpbnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQtb3JpZ2lucyc7XG5pbXBvcnQgeyBDYWNoZVBvbGljeSwgQ2ZuT3JpZ2luQWNjZXNzQ29udHJvbCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udFwiO1xuXG5mdW5jdGlvbiBkZXBsb3koc3RhY2s6IGNkay5TdGFjaywgcHJvcHM/OiBDbG91ZEZyb250VG9TM1Byb3BzKSB7XG4gIHJldHVybiBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIHJlbW92YWxQb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgfSxcbiAgICAuLi5wcm9wc1xuICB9KTtcbn1cblxudGVzdCgnY29uc3RydWN0IGRlZmF1bHRzIHNldCBwcm9wZXJ0aWVzIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHt9KTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udEZ1bmN0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzTG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0J1Y2tldEludGVyZmFjZSkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS50b0JlRGVmaW5lZCgpO1xufSk7XG5cbnRlc3QoJ2NoZWNrIHMzQnVja2V0IGRlZmF1bHQgZW5jcnlwdGlvbicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGRlcGxveShzdGFjayk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgQnVja2V0RW5jcnlwdGlvbjoge1xuICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBbe1xuICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgIFNTRUFsZ29yaXRobTogXCJBRVMyNTZcIlxuICAgICAgICB9XG4gICAgICB9XVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgczNCdWNrZXQgcHVibGljIGFjY2VzcyBibG9jayBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgZGVwbG95KHN0YWNrKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHtcbiAgICBQdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIEJsb2NrUHVibGljQWNsczogdHJ1ZSxcbiAgICAgIEJsb2NrUHVibGljUG9saWN5OiB0cnVlLFxuICAgICAgSWdub3JlUHVibGljQWNsczogdHJ1ZSxcbiAgICAgIFJlc3RyaWN0UHVibGljQnVja2V0czogdHJ1ZVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgndGVzdCBzM0J1Y2tldCBvdmVycmlkZSBwdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBibG9ja1B1YmxpY0FjY2Vzczoge1xuICAgICAgICBibG9ja1B1YmxpY0FjbHM6IGZhbHNlLFxuICAgICAgICBibG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgICAgaWdub3JlUHVibGljQWNsczogZmFsc2UsXG4gICAgICAgIHJlc3RyaWN0UHVibGljQnVja2V0czogdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIFB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgQmxvY2tQdWJsaWNBY2xzOiBmYWxzZSxcbiAgICAgIEJsb2NrUHVibGljUG9saWN5OiB0cnVlLFxuICAgICAgSWdub3JlUHVibGljQWNsczogZmFsc2UsXG4gICAgICBSZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWVcbiAgICB9LFxuICB9KTtcbn0pO1xuXG50ZXN0KCdjaGVjayBleGlzdGluZyBidWNrZXQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGV4aXN0aW5nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ215LWJ1Y2tldCcsIHtcbiAgICBidWNrZXROYW1lOiAnbXktYnVja2V0J1xuICB9KTtcblxuICBjb25zdCBwcm9wczogQ2xvdWRGcm9udFRvUzNQcm9wcyA9IHtcbiAgICBleGlzdGluZ0J1Y2tldE9iajogZXhpc3RpbmdCdWNrZXRcbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IFwibXktYnVja2V0XCJcbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgZXhjZXB0aW9uIGZvciBNaXNzaW5nIGV4aXN0aW5nT2JqIGZyb20gcHJvcHMgZm9yIGRlcGxveSA9IGZhbHNlJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICB0cnkge1xuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHt9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGV4cGVjdChlKS50b0JlSW5zdGFuY2VPZihFcnJvcik7XG4gIH1cbn0pO1xuXG50ZXN0KCdjaGVjayBwcm9wZXJ0aWVzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjb25zdHJ1Y3Q6IENsb3VkRnJvbnRUb1MzID0gZGVwbG95KHN0YWNrKTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tTM1Byb3BzIGlzIGNhbGxlZFwiLCAoKSA9PiB7XG4gIC8vIFN0YWNrXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3RCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAndGVzdC1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIC8vIEhlbHBlciBkZWNsYXJhdGlvblxuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgXCJiYWQtczMtYXJnc1wiLCB7XG4gICAgICBleGlzdGluZ0J1Y2tldE9iajogdGVzdEJ1Y2tldCxcbiAgICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgICAgfSxcbiAgICB9KTtcbiAgfTtcbiAgLy8gQXNzZXJ0aW9uXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcignRXJyb3IgLSBFaXRoZXIgcHJvdmlkZSBidWNrZXRQcm9wcyBvciBleGlzdGluZ0J1Y2tldE9iaiwgYnV0IG5vdCBib3RoLlxcbicpO1xufSk7XG5cbnRlc3QoXCJUZXN0IGV4aXN0aW5nQnVja2V0T2JqXCIsICgpID0+IHtcbiAgLy8gU3RhY2tcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdDogQ2xvdWRGcm9udFRvUzMgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssIFwiZXhpc3RpbmdJQnVja2V0XCIsIHtcbiAgICBleGlzdGluZ0J1Y2tldE9iajogczMuQnVja2V0LmZyb21CdWNrZXROYW1lKHN0YWNrLCAnbXlidWNrZXQnLCAnbXlidWNrZXQnKVxuICB9KTtcbiAgLy8gQXNzZXJ0aW9uXG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbikudG9CZURlZmluZWQoKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBEb21haW5OYW1lOiB7XG4gICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFwibXlidWNrZXQuczMuXCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UmVnaW9uXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiLlwiLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlVSTFN1ZmZpeFwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBJZDogXCJleGlzdGluZ0lCdWNrZXRDbG91ZEZyb250RGlzdHJpYnV0aW9uT3JpZ2luMUQ1ODQ5MTI1XCIsXG4gICAgICAgICAgT3JpZ2luQWNjZXNzQ29udHJvbElkOiB7IFwiRm46OkdldEF0dFwiOiBbXCJleGlzdGluZ0lCdWNrZXRDbG91ZEZyb250T2FjRUI0MkU5OEZcIiwgXCJJZFwiXSB9LFxuICAgICAgICAgIFMzT3JpZ2luQ29uZmlnOiB7fVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCd0ZXN0IGNsb3VkZnJvbnQgd2l0aCBjdXN0b20gZG9tYWluIG5hbWVzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGFjbS5DZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oc3RhY2ssICdDZXJ0JywgJ2Fybjoke0F3cy5QQVJUSVRJT059OmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzExMTEyMjIyLTMzMzMtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMicpO1xuXG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczoge1xuICAgICAgZG9tYWluTmFtZXM6IFsnbXlkb21haW5zJ10sXG4gICAgICBjZXJ0aWZpY2F0ZVxuICAgIH1cbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBBbGlhc2VzOiBbXG4gICAgICAgIFwibXlkb21haW5zXCJcbiAgICAgIF1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ0Nsb3VkZnJvbnQgbG9nZ2luZyBidWNrZXQgd2l0aCBkZXN0cm95IHJlbW92YWwgcG9saWN5IGFuZCBhdXRvIGRlbGV0ZSBvYmplY3RzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjbG91ZGZyb250TG9nQnVja2V0TmFtZSA9ICdjZi1sb2ctYnVja2V0JztcbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiBjbG91ZGZyb250TG9nQnVja2V0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIE93bmVyc2hpcENvbnRyb2xzOiB7IFJ1bGVzOiBbeyBPYmplY3RPd25lcnNoaXA6IFwiT2JqZWN0V3JpdGVyXCIgfV0gfSxcbiAgICBCdWNrZXROYW1lOiBjbG91ZGZyb250TG9nQnVja2V0TmFtZSxcbiAgfSk7XG5cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQ3VzdG9tOjpTM0F1dG9EZWxldGVPYmplY3RzXCIsIHtcbiAgICBTZXJ2aWNlVG9rZW46IHtcbiAgICAgIFwiRm46OkdldEF0dFwiOiBbXG4gICAgICAgIFwiQ3VzdG9tUzNBdXRvRGVsZXRlT2JqZWN0c0N1c3RvbVJlc291cmNlUHJvdmlkZXJIYW5kbGVyOUQ5MDE4NEZcIixcbiAgICAgICAgXCJBcm5cIlxuICAgICAgXVxuICAgIH0sXG4gICAgQnVja2V0TmFtZToge1xuICAgICAgUmVmOiBcImNsb3VkZnJvbnRzM0Nsb3VkZnJvbnRMb2dnaW5nQnVja2V0NUI4NDUxNDNcIlxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnczMgYnVja2V0IHdpdGggb25lIGNvbnRlbnQgYnVja2V0IGFuZCBubyBhY2Nlc3MgbG9nZ2luZyBvZiBDT05URU5UIGJ1Y2tldCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBidWNrZXRQcm9wczoge1xuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICB9LFxuICAgIGxvZ1MzQWNjZXNzTG9nczogZmFsc2VcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAvLyBDb250ZW50IGJ1Y2tldCtDbG91ZGZyb250IExvZ3MgYnVja2V0K1xuICAvLyBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ2xvdWRmcm9udCBMb2dzIGJ1Y2tldCA9IDMgYnVja2V0c1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNMb2dnaW5nQnVja2V0KS50b0VxdWFsKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdCgnQ2xvdWRGcm9udCBvcmlnaW4gcGF0aCBwcmVzZW50IHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtczMnLCB7XG4gICAgb3JpZ2luUGF0aDogJy90ZXN0UGF0aCdcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOlxuICAgIHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIE9yaWdpblBhdGg6IFwiL3Rlc3RQYXRoXCIsXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ0Nsb3VkRnJvbnQgb3JpZ2luIHBhdGggc2hvdWxkIG5vdCBiZSBwcmVzZW50IGlmIG5vdCBwcm92aWRlZCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHt9KTtcblxuICBkZWZhdWx0cy5leHBlY3ROb25leGlzdGVuY2Uoc3RhY2ssIFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgIERpc3RyaWJ1dGlvbkNvbmZpZzpcbiAgICB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBPcmlnaW5QYXRoOiBcIi90ZXN0UGF0aFwiLFxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoZSBkZXBsb3ltZW50IHdpdGggc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgaW5zdGVhZCBvZiBIVFRQIHNlY3VyaXR5IGhlYWRlcnMnLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgc2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgY29uc3QgY2xvdWRGcm9udFRvUzMgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVyczogZmFsc2UsXG4gICAgcmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM6IHtcbiAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB7XG4gICAgICAgIHN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uc2Vjb25kcyg2MzA3MiksXG4gICAgICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgb3ZlcnJpZGU6IHRydWUsXG4gICAgICAgICAgcHJlbG9hZDogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IHtcbiAgICAgICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IFwidXBncmFkZS1pbnNlY3VyZS1yZXF1ZXN0czsgZGVmYXVsdC1zcmMgJ25vbmUnO1wiLFxuICAgICAgICAgIG92ZXJyaWRlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBBc3NlcnRpb25cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OlJlc3BvbnNlSGVhZGVyc1BvbGljeVwiLCB7XG4gICAgUmVzcG9uc2VIZWFkZXJzUG9saWN5Q29uZmlnOiB7XG4gICAgICBTZWN1cml0eUhlYWRlcnNDb25maWc6IHtcbiAgICAgICAgQ29udGVudFNlY3VyaXR5UG9saWN5OiB7XG4gICAgICAgICAgQ29udGVudFNlY3VyaXR5UG9saWN5OiBcInVwZ3JhZGUtaW5zZWN1cmUtcmVxdWVzdHM7IGRlZmF1bHQtc3JjICdub25lJztcIixcbiAgICAgICAgICBPdmVycmlkZTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBTdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgICAgIEFjY2Vzc0NvbnRyb2xNYXhBZ2VTZWM6IDYzMDcyLFxuICAgICAgICAgIEluY2x1ZGVTdWJkb21haW5zOiB0cnVlLFxuICAgICAgICAgIE92ZXJyaWRlOiB0cnVlLFxuICAgICAgICAgIFByZWxvYWQ6IHRydWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIGV4cGVjdChjbG91ZEZyb250VG9TMy5jbG91ZEZyb250RnVuY3Rpb24pLnRvRXF1YWwodW5kZWZpbmVkKTtcbn0pO1xuXG50ZXN0KFwidGhyb3cgZXhjZXB0aW9uIGlmIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnMgYW5kIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzIGFyZSBwcm92aWRlZFwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGV4cGVjdCgoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCBcInRlc3QtY2xvdWRmcm9udC1zM1wiLCB7XG4gICAgICBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzOiB0cnVlLFxuICAgICAgcmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM6IHtcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHtcbiAgICAgICAgICBzdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uc2Vjb25kcyg2MzA3MiksXG4gICAgICAgICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgICAgICAgIG92ZXJyaWRlOiBmYWxzZSxcbiAgICAgICAgICAgIHByZWxvYWQ6IHRydWVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSkudG9UaHJvd0Vycm9yKCk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tDbG91ZEZyb250UHJvcHMgaXMgYmVpbmcgY2FsbGVkXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgZXhwZWN0KCgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssIFwidGVzdC1jbG91ZGZyb250LWFwaWdhdGV3YXlcIiwge1xuICAgICAgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVyczogdHJ1ZSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzOiB7XG4gICAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB7XG4gICAgICAgICAgc3RyaWN0VHJhbnNwb3J0U2VjdXJpdHk6IHtcbiAgICAgICAgICAgIGFjY2Vzc0NvbnRyb2xNYXhBZ2U6IER1cmF0aW9uLnNlY29uZHMoNjMwNzIpLFxuICAgICAgICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICAgICAgICBwcmVsb2FkOiB0cnVlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pLnRvVGhyb3dFcnJvcigncmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHMuc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgY2FuIG9ubHkgYmUgcGFzc2VkIGlmIGh0dHBTZWN1cml0eUhlYWRlcnMgaXMgc2V0IHRvIGBmYWxzZWAuJyk7XG59KTtcblxudGVzdChcIkN1c3RvbSByZXNvdXJjZSBpcyBwcm92aXNpb25lZCBpZiBlbmNyeXB0aW9uIGtleSBpcyBwcm92aWRlZCBhcyBidWNrZXRQcm9wXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGVuY3J5cHRpb25LZXkgPSBuZXcgS2V5KHN0YWNrLCAnY21rS2V5Jywge1xuICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0cnVlLFxuICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICB9KTtcbiAgZGVwbG95KHN0YWNrLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICBlbmNyeXB0aW9uOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNU1xuICAgIH1cbiAgfSk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgLy8gMiBGdW5jdGlvbnMgLSBvdXIgY3VzdG9tIHJlc291cmNlIGFuZCBhIGZ1bmN0aW9uIGNyZWF0ZWQgYnkgdGhlIENES1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDIpO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgIERlc2NyaXB0aW9uOiBcIkN1c3RvbSByZXNvdXJjZSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgYSBwcm92aWRlZCBrZXkgcG9saWN5IHRvIGFsbG93IENsb3VkRnJvbnQgYWNjZXNzLlwiLFxuICAgIFJvbGU6IHtcbiAgICAgIFwiRm46OkdldEF0dFwiOiBbXCJ0ZXN0Y2xvdWRmcm9udHMzTGFtYmRhRnVuY3Rpb25TZXJ2aWNlUm9sZTJBNDNFQTkyXCIsIFwiQXJuXCJdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KFwiQ3VzdG9tIHJlc291cmNlIGlzIHByb3Zpc2lvbmVkIGlmIENNSyB3YXMgdXNlZCB0byBlbmNyeXB0IGFuIGV4aXN0aW5nIGJ1Y2tldFwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gbmV3IEtleShzdGFjaywgJ2Nta0tleScsIHtcbiAgICBlbmFibGVLZXlSb3RhdGlvbjogdHJ1ZSxcbiAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1lcbiAgfSk7XG4gIGNvbnN0IGV4aXN0aW5nQnVja2V0T2JqID0gZGVmYXVsdHMuYnVpbGRTM0J1Y2tldChzdGFjaywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBlbmNyeXB0aW9uOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNUyxcbiAgICAgIGVuY3J5cHRpb25LZXlcbiAgICB9XG4gIH0sICdleGlzdGluZy1zMy1idWNrZXQtZW5jcnlwdGVkLXdpdGgtY21rJykuYnVja2V0O1xuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgZXhpc3RpbmdCdWNrZXRPYmpcbiAgfSk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgLy8gMiBGdW5jdGlvbnMgLSBvdXIgY3VzdG9tIHJlc291cmNlIGFuZCBhIGZ1bmN0aW9uIGNyZWF0ZWQgYnkgdGhlIENES1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDIpO1xuXG4gIC8vIGVuc3VyZSB0aGF0IG91ciBGdW5jdGlvbiBoYXMgdGhlIGNvcnJlY3Qgcm9sZSBhdHRhY2hlZFxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICBEZXNjcmlwdGlvbjogXCJDdXN0b20gcmVzb3VyY2UgZnVuY3Rpb24gdGhhdCB1cGRhdGVzIGEgcHJvdmlkZWQga2V5IHBvbGljeSB0byBhbGxvdyBDbG91ZEZyb250IGFjY2Vzcy5cIixcbiAgICBSb2xlOiB7XG4gICAgICBcIkZuOjpHZXRBdHRcIjogW1widGVzdGNsb3VkZnJvbnRzM0xhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUyQTQzRUE5MlwiLCBcIkFyblwiXVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdChcIkN1c3RvbSByZXNvdXJjZSBpcyBub3QgcHJvdmlzaW9uZWQgaWYgZW5jcnlwdGlvbiBrZXkgaXMgbm90IHByb3ZpZGVkIGFzIGJ1Y2tldFByb3BcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgZGVwbG95KHN0YWNrKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDApO1xufSk7XG5cbnRlc3QoXCJDdXN0b20gcmVzb3VyY2UgaXMgbm90IHByb3Zpc2lvbmVkIGlmIENNSyB3YXMgbm90IHVzZWQgdG8gZW5jcnlwdCBhbiBleGlzdGluZyBidWNrZXRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgZXhpc3RpbmdCdWNrZXRPYmogPSBkZWZhdWx0cy5idWlsZFMzQnVja2V0KHN0YWNrLCB7fSwgJ2V4aXN0aW5nLXMzLWJ1Y2tldC1lbmNyeXB0ZWQtd2l0aC1jbWsnKS5idWNrZXQ7XG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHtcbiAgICBleGlzdGluZ0J1Y2tldE9ialxuICB9KTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDApO1xufSk7XG5cbnRlc3QoXCJIdHRwT3JpZ2luIGlzIHByb3Zpc2lvbmVkIGlmIGEgc3RhdGljIHdlYnNpdGUgYnVja2V0IGlzIHVzZWRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgYmxvY2tQdWJsaWNBY2Nlc3MgPSBmYWxzZTtcbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb1MzUHJvcHMgPSB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIGVuZm9yY2VTU0w6IGZhbHNlLFxuICAgICAgcHVibGljUmVhZEFjY2VzczogdHJ1ZSwgLy8gPC0tIHJlcXVpcmVkIGZvciBpc1dlYnNpdGVcbiAgICAgIGJsb2NrUHVibGljQWNjZXNzOiB7XG4gICAgICAgIGJsb2NrUHVibGljQWNsczogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIHJlc3RyaWN0UHVibGljQnVja2V0czogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIGJsb2NrUHVibGljUG9saWN5OiBibG9ja1B1YmxpY0FjY2VzcyxcbiAgICAgICAgaWdub3JlUHVibGljQWNsczogYmxvY2tQdWJsaWNBY2Nlc3NcbiAgICAgIH0sXG4gICAgICB3ZWJzaXRlSW5kZXhEb2N1bWVudDogXCJpbmRleC5odG1sXCIgLy8gPC0tIHJlcXVpcmVkIGZvciBpc1dlYnNpdGVcbiAgICB9LFxuICAgIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnM6IGZhbHNlXG4gIH07XG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHByb3BzKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAvLyBBc3NlcnQgcmVzb3VyY2VzXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpDbG91ZEZyb250OjpPcmlnaW5BY2Nlc3NDb250cm9sJywgMCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb24nLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBDdXN0b21PcmlnaW5Db25maWc6IHtcbiAgICAgICAgICAgIE9yaWdpblByb3RvY29sUG9saWN5OiBcImh0dHAtb25seVwiXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0lkZW50aXR5JywgMCk7XG4gIC8vIEFzc2VydCBwYXR0ZXJuIHByb3BlcnRpZXMgKG91dHB1dCBwcm9wcylcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS50b0JlKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdChcIk9BQyBpcyBwcm92aXNpb25lZCBpbiBhbGwgb3RoZXIgY2FzZXNcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LXMzJywge30pO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIC8vIEFzc2VydCByZXNvdXJjZXNcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0NvbnRyb2wnLCAxKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0lkZW50aXR5JywgMCk7XG4gIC8vIEFzc2VydCBwYXR0ZXJuIHByb3BlcnRpZXMgKG91dHB1dCBwcm9wcylcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS5ub3QudG9CZSh1bmRlZmluZWQpO1xufSk7XG5cbnRlc3QoXCJJZiBhIGN1c3RvbWVyIHByb3ZpZGVzIHRoZWlyIG93biBodHRwT3JpZ2luLCBvciBvdGhlciBvcmlnaW4gdHlwZSwgdXNlIHRoYXQgb25lXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGJsb2NrUHVibGljQWNjZXNzID0gZmFsc2U7XG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBlbmZvcmNlU1NMOiBmYWxzZSxcbiAgICAgIHB1YmxpY1JlYWRBY2Nlc3M6IHRydWUsIC8vIDwtLSByZXF1aXJlZCBmb3IgaXNXZWJzaXRlXG4gICAgICBibG9ja1B1YmxpY0FjY2Vzczoge1xuICAgICAgICBibG9ja1B1YmxpY0FjbHM6IGJsb2NrUHVibGljQWNjZXNzLFxuICAgICAgICByZXN0cmljdFB1YmxpY0J1Y2tldHM6IGJsb2NrUHVibGljQWNjZXNzLFxuICAgICAgICBibG9ja1B1YmxpY1BvbGljeTogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIGlnbm9yZVB1YmxpY0FjbHM6IGJsb2NrUHVibGljQWNjZXNzXG4gICAgICB9LFxuICAgICAgd2Vic2l0ZUluZGV4RG9jdW1lbnQ6IFwiaW5kZXguaHRtbFwiIC8vIDwtLSByZXF1aXJlZCBmb3IgaXNXZWJzaXRlXG4gICAgfSxcbiAgICBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzOiBmYWxzZSxcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGRlZmF1bHRCZWhhdmlvcjoge1xuICAgICAgICBvcmlnaW46IG5ldyBvcmlnaW5zLkh0dHBPcmlnaW4oJ2V4YW1wbGUuY29tJywge1xuICAgICAgICAgIG9yaWdpbklkOiAnY3VzdG9tLWh0dHAtb3JpZ2luLWZvci10ZXN0aW5nJ1xuICAgICAgICB9KVxuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LXMzJywgcHJvcHMpO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIC8vIEFzc2VydCByZXNvdXJjZXNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIERvbWFpbk5hbWU6IFwiZXhhbXBsZS5jb21cIixcbiAgICAgICAgICBJZDogXCJjdXN0b20taHR0cC1vcmlnaW4tZm9yLXRlc3RpbmdcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoYXQgd2UgZG8gbm90IGNyZWF0ZSBhbiBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ0YgbG9ncyBpZiBvbmUgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBjZlMzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLXMzLWFjY2Vzcy1sb2dzJyk7XG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBjZlMzQWNjZXNzTG9nQnVja2V0XG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gUzMgQ29udGVudCBCdWNrZXQgQWNjZXNzIExvZ3MgQnVja2V0XG4vLyA9PT09PT09PT09PT09PT09PT09PT1cbnRlc3QoJ1Byb3ZpZGluZyBsb2dnaW5nQnVja2V0UHJvcHMgYW5kIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdsb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgfSxcbiAgICAgIGxvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgICBidWNrZXROYW1lOiAnYW55dGhpbmcnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvRXJyb3IgLSBib3RobG9nIGJ1Y2tldCBwcm9wcyBhbmQgYW4gZXhpc3RpbmcgbG9nIGJ1Y2tldCB3ZXJlIHByb3ZpZGVkLlxcbi8pO1xufSk7XG5cbnRlc3QoJ1Byb3ZpZGluZyBleGlzdGluZ0xvZ2dpbmdCdWNrZXQgYW5kIGxvZ1MzQWNjZXNzTG9ncz1mYWxzZSBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtczMnLCB7XG4gICAgICBidWNrZXRQcm9wczoge1xuICAgICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgICB9LFxuICAgICAgbG9nUzNBY2Nlc3NMb2dzOiBmYWxzZVxuICAgIH0pO1xuICB9O1xuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gbG9nUzNBY2Nlc3NMb2dzIGlzIGZhbHNlLCBidXQgYSBsb2cgYnVja2V0IHdhcyBwcm92aWRlZCBpbiBidWNrZXRQcm9wcy5cXG4vKTtcbn0pO1xuXG50ZXN0KCdQcm92aWRpbmcgbG9nZ2luZ0J1Y2tldFByb3BzIGFuZCBsb2dTM0FjY2Vzc0xvZ3M9ZmFsc2UgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgbG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6ICdhbnl0aGluZydcbiAgICAgIH0sXG4gICAgICBsb2dTM0FjY2Vzc0xvZ3M6IGZhbHNlXG4gICAgfSk7XG4gIH07XG4gIC8vIE5PVEU6IFRoaXMgZXJyb3IgaXMgdGhyb3duIGJ5IENoZWNrUzNQcm9wcygpLCBub3QgQ2hlY2tDb25zdHJ1Y3RTcGVjaWZpY1Byb3BzKClcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKC9FcnJvciAtIElmIGxvZ1MzQWNjZXNzTG9ncyBpcyBmYWxzZSwgc3VwcGx5aW5nIGxvZ2dpbmdCdWNrZXRQcm9wcyBvciBleGlzdGluZ0xvZ2dpbmdCdWNrZXRPYmogaXMgaW52YWxpZC5cXG4vKTtcbn0pO1xuXG4vLyB0ZXN0KCdObyBuZXcgbG9nZ2luZ0J1Y2tldCBpcyBjcmVhdGVkIGlmIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbnRlc3QoJ2xvZ2dpbmdCdWNrZXRQcm9wcyBpcyBzdXBwbGllZCBpcyBpbnRlZ3JhdGVkIGludG8gYXJjaGl0ZWN0dXJlIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgdGVzdE5hbWUgPSBcInRlc3QtbmFtZVwiO1xuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0sXG4gICAgbG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0xvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG5cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICBCdWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIExvZ2dpbmdDb25maWd1cmF0aW9uOiB7XG4gICAgICBEZXN0aW5hdGlvbkJ1Y2tldE5hbWU6IHtcbiAgICAgICAgUmVmOiBcImNsb3VkZnJvbnRzM1MzTG9nZ2luZ0J1Y2tldDUyRUVCNzA4XCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufSk7XG50ZXN0KCdidWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIHN1cHBsaWVkIGlzIGludGVncmF0ZWQgaW50byBhcmNoaXRlY3R1cmUgY29ycmVjdGx5JywgKCkgPT4ge1xuICBjb25zdCB0ZXN0TmFtZSA9ICdzb21lLW5hbWUnO1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ3Rlc3QtbG9nJywge1xuICAgIGJ1Y2tldE5hbWU6IHRlc3ROYW1lLFxuICB9KTtcblxuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgfSxcbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0xvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgTG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIERlc3RpbmF0aW9uQnVja2V0TmFtZToge1xuICAgICAgICBSZWY6IFwidGVzdGxvZ0U4OEI0QzZCXCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2xvdWRGcm9udCBMb2cgQnVja2V0XG4vLyA9PT09PT09PT09PT09PT09PT09PT1cbnRlc3QoJ1Byb3ZpZGluZyBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzIGFuZCBhIGxvZyBidWNrZXQgaW4gY2xvdWRGcm9udERpc3RyYnV0aW9uUHJvcHMgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBsb2dCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAnY2xvdWRmcm9udC1sb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiB7XG4gICAgICAgIGxvZ0J1Y2tldFxuICAgICAgfSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoKTtcbn0pO1xudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wcyBhcmUgdXNlZCBjb3JyZWN0bHknLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3ROYW1lID0gXCJ0ZXN0LW5hbWVcIjtcbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG59KTtcbnRlc3QoJ0xvZ2dpbmcgZGlzYWJsZWQgaW4gQ2xvdWRGcm9udCBwcm9wcyBpcyBoYW5kbGVkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gZGVwbG95KHN0YWNrLCB7IGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczogeyBlbmFibGVMb2dnaW5nOiBmYWxzZSB9IH0pO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gT25seSB0aGUgY29udGVudCBidWNrZXQgYW5kIGl0IFMzIEFjY2VzcyBMb2cgYnVja2V0IChubyBDbG91ZGZyb250IGxvZyBidWNrZXQpXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAyKTtcblxuICAvLyBObyBsb2dnaW5nIGlzIGNvbmZpZ3VyZWRcbiAgdGVtcGxhdGUucmVzb3VyY2VQcm9wZXJ0aWVzQ291bnRJcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IE1hdGNoLmFueVZhbHVlKClcbiAgICB9XG4gIH0sIDApO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0ID09PSB1bmRlZmluZWQpO1xufSk7XG50ZXN0KCdObyBuZXcgQ2xvdWRGcm9udExvZ2dpbmdCdWNrZXQgaXMgY3JlYXRlZCBpZiBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOmxvZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbiAgY29uc3QgdGVzdE5hbWUgPSAncmFuZG9tLXZhbHVlJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7XG4gICAgYnVja2V0TmFtZTogdGVzdE5hbWVcbiAgfSk7XG5cbiAgLy8gY29uc3QgY29uc3RydWN0ID1cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGxvZ0J1Y2tldFxuICAgIH0sXG4gIH0pO1xuXG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IGJ1Y2tldCwgQ29udGVudCBidWNrZXQgUzMgQWNjZXNzIExvZyBidWNrZXQsIGNsb3VkZnJvbnQgbG9nIGJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG5cbiAgLy8gRW5zdXJlIG91ciBleGlzdGluZyBidWNrZXQgaGFzIGJlZW4gdXNlZCBmb3IgY2xvdWRmcm9udCBsb2dnaW5nXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IHtcbiAgICAgICAgQnVja2V0OiB7XG4gICAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICAgIFwiY2xvdWRmcm9udGxvZ2J1Y2tldERGNzA1OEZCXCIsXG4gICAgICAgICAgICBcIlJlZ2lvbmFsRG9tYWluTmFtZVwiXG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2xvdWRGcm9udCBMb2dzIEJ1Y2tldCBBY2Nlc3MgTG9nIEJ1Y2tldFxuLy8gPT09PT09PT09PT09PT09PT09PT09XG50ZXN0KCdQcm92aWRpbmcgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgYnVja2V0TmFtZTogJ3NwZWNmaWMtbmFtZS1pcy1pbmNvbnNlcXVlbnRpYWwnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKFxuICAgIC9FcnJvciAtIGFuIGV4aXN0aW5nIENsb3VkRnJvbnQgbG9nIGJ1Y2tldCBTMyBhY2Nlc3MgbG9nIGJ1Y2tldCBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyB3ZXJlIHByb3ZpZGVkXFxuLyk7XG59KTtcbnRlc3QoJ1Byb3ZpZGluZyBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIGFuZCBsb2dDbG91ZEZyb250QWNjZXNzTG9nPWZhbHNlIGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlLFxuICAgICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wczoge1xuICAgICAgICBidWNrZXROYW1lOiAnc3BlY2ZpYy1uYW1lLWlzLWluY29uc2VxdWVudGlhbCdcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyB3ZXJlIHByb3ZpZGVkIGJ1dCBsb2dDbG91ZEZyb250QWNjZXNzTG9nIHdhcyBmYWxzZVxcbi8pO1xufSk7XG50ZXN0KCdQcm92aWRpbmcgbG9nQ2xvdWRGcm9udEFjY2Vzc0xvZz1mYWxzZSBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfSxcbiAgICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlLFxuICAgIH0pO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvRXJyb3IgLSBwcm9wcy5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzLnNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQgd2FzIHByb3ZpZGVkIGJ1dCBsb2dDbG91ZEZyb250QWNjZXNzTG9nIHdhcyBmYWxzZVxcbi8pO1xufSk7XG50ZXN0KCdjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIGFyZSB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxufSk7XG50ZXN0KCdJZiBleGlzdGluZyBDbG91ZEZyb250IExvZyBidWNrZXQgUzMgQWNjZXNzIExvZ2dpbmcgYnVja2V0IGlzIHByb3ZpZGVkLCBpdCBpcyB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ2NmLWxvZy1zMy1sb2cnO1xuICBjb25zdCBjZkxvZ1MzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLWxvZy1zMy1hY2Nlc3MtbG9nLWJ1Y2tldCcsIHtcbiAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGNmTG9nUzNBY2Nlc3NMb2dCdWNrZXRcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgTG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIERlc3RpbmF0aW9uQnVja2V0TmFtZToge1xuICAgICAgICBSZWY6IFwiY2Zsb2dzM2FjY2Vzc2xvZ2J1Y2tldERFMzc0QzI3XCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG59KTtcblxudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXQgcHJvcGVydHkgaXMgc2V0IGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCEuYnVja2V0TmFtZSkudG9CZURlZmluZWQoKTtcbn0pO1xuXG50ZXN0KCdsb2dDbG91ZEZyb250QWNjZXNzTG9nIHByb3BlcnR5IGlzIHVzZWQgY29ycmVjdGx5JywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlXG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAzKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkubm90LnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdCgnYWRkaXRpb25hbEJlaGF2aW9ycyBoYXZlIGNvcnJlY3Qgb3JpZ2luJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBhZGRpdGlvbmFsQnVja2V0ID0gZGVmYXVsdHMuQ3JlYXRlU2NyYXBCdWNrZXQoc3RhY2ssIFwic2NyYXBCdWNrZXRcIiwge1xuICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgfSk7XG5cbiAgY29uc3Qgb3JpZ2luQWNjZXNzQ29udHJvbCA9IG5ldyBDZm5PcmlnaW5BY2Nlc3NDb250cm9sKHN0YWNrLCAnQ2xvdWRGcm9udE9hYycsIHtcbiAgICBvcmlnaW5BY2Nlc3NDb250cm9sQ29uZmlnOiB7XG4gICAgICBuYW1lOiBkZWZhdWx0cy5nZW5lcmF0ZVBoeXNpY2FsT2FjTmFtZSgnYXdzLWNsb3VkZnJvbnQtczMtJywgW19fZmlsZW5hbWVdKSxcbiAgICAgIG9yaWdpbkFjY2Vzc0NvbnRyb2xPcmlnaW5UeXBlOiAnczMnLFxuICAgICAgc2lnbmluZ0JlaGF2aW9yOiAnYWx3YXlzJyxcbiAgICAgIHNpZ25pbmdQcm90b2NvbDogJ3NpZ3Y0JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3JpZ2luIGFjY2VzcyBjb250cm9sIHByb3Zpc2lvbmVkIGJ5IGF3cy1jbG91ZGZyb250LXMzJ1xuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgYWRkaXRpb25hbE9yaWdpbiA9IG5ldyBkZWZhdWx0cy5TM09hY09yaWdpbihhZGRpdGlvbmFsQnVja2V0LCB7XG4gICAgb3JpZ2luQWNjZXNzQ29udHJvbFxuICB9KTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiB7XG4gICAgICBhZGRpdGlvbmFsQmVoYXZpb3JzOiB7XG4gICAgICAgICcvYXNzZXRzL3B1YmxpYy8qJzoge1xuICAgICAgICAgIG9yaWdpbjogYWRkaXRpb25hbE9yaWdpbixcbiAgICAgICAgICBjYWNoZVBvbGljeTogQ2FjaGVQb2xpY3kuQ0FDSElOR19ESVNBQkxFRCxcbiAgICAgICAgfSxcbiAgICAgICAgJ25nc3cuanNvbic6IHtcbiAgICAgICAgICBjYWNoZVBvbGljeTogQ2FjaGVQb2xpY3kuQ0FDSElOR19ESVNBQkxFRCxcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBDYWNoZUJlaGF2aW9yczogW1xuICAgICAgICB7XG4gICAgICAgICAgQ2FjaGVQb2xpY3lJZDogXCI0MTM1ZWEyZC02ZGY4LTQ0YTMtOWRmMy00YjVhODRiZTM5YWRcIixcbiAgICAgICAgICBDb21wcmVzczogdHJ1ZSxcbiAgICAgICAgICBQYXRoUGF0dGVybjogXCIvYXNzZXRzL3B1YmxpYy8qXCIsXG4gICAgICAgICAgVGFyZ2V0T3JpZ2luSWQ6IFwidGVzdGNsb3VkZnJvbnRzM0Nsb3VkRnJvbnREaXN0cmlidXRpb25PcmlnaW4yMUQ3ODM5MUNcIixcbiAgICAgICAgICBWaWV3ZXJQcm90b2NvbFBvbGljeTogXCJhbGxvdy1hbGxcIlxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgQ2FjaGVQb2xpY3lJZDogXCI0MTM1ZWEyZC02ZGY4LTQ0YTMtOWRmMy00YjVhODRiZTM5YWRcIixcbiAgICAgICAgICBDb21wcmVzczogdHJ1ZSxcbiAgICAgICAgICBQYXRoUGF0dGVybjogXCJuZ3N3Lmpzb25cIixcbiAgICAgICAgICBUYXJnZXRPcmlnaW5JZDogXCJ0ZXN0Y2xvdWRmcm9udHMzQ2xvdWRGcm9udERpc3RyaWJ1dGlvbk9yaWdpbjEyNDA1MTAzOVwiLFxuICAgICAgICAgIFZpZXdlclByb3RvY29sUG9saWN5OiBcImFsbG93LWFsbFwiXG4gICAgICAgIH1cbiAgICAgIF0sXG4gICAgfVxuICB9KTtcbn0pO1xuIl19