@aws-solutions-constructs/aws-cloudfront-apigateway-lambda 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.
Files changed (38) hide show
  1. package/.jsii +9 -12
  2. package/lib/index.js +4 -2
  3. package/package.json +8 -9
  4. package/test/cloudfront-apigateway-lambda.test.js +399 -0
  5. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js +2 -2
  6. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/cdk.out +1 -1
  7. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/cftaplam-customCloudfrontLoggingBucket.assets.json +4 -4
  8. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/cftaplam-customCloudfrontLoggingBucket.template.json +1 -4
  9. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/cftaplamcustomCloudfrontLoggingBucketIntegDefaultTestDeployAssert35A683E0.assets.json +1 -1
  10. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/integ.json +2 -2
  11. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/manifest.json +23 -31
  12. package/test/integ.cftaplam-customCloudfrontLoggingBucket.js.snapshot/tree.json +1 -1
  13. package/test/integ.cftaplam-no-arguments.js +2 -2
  14. package/test/integ.cftaplam-no-arguments.js.snapshot/cdk.out +1 -1
  15. package/test/integ.cftaplam-no-arguments.js.snapshot/cftaplam-no-arguments.assets.json +4 -4
  16. package/test/integ.cftaplam-no-arguments.js.snapshot/cftaplam-no-arguments.template.json +1 -4
  17. package/test/integ.cftaplam-no-arguments.js.snapshot/cftaplamnoargumentsIntegDefaultTestDeployAssertACC32F59.assets.json +1 -1
  18. package/test/integ.cftaplam-no-arguments.js.snapshot/integ.json +2 -2
  19. package/test/integ.cftaplam-no-arguments.js.snapshot/manifest.json +23 -31
  20. package/test/integ.cftaplam-no-arguments.js.snapshot/tree.json +1 -1
  21. package/test/integ.cftaplam-no-usage-plan.js +2 -2
  22. package/test/integ.cftaplam-no-usage-plan.js.snapshot/cdk.out +1 -1
  23. package/test/integ.cftaplam-no-usage-plan.js.snapshot/cftaplam-no-usage-plan.assets.json +4 -4
  24. package/test/integ.cftaplam-no-usage-plan.js.snapshot/cftaplam-no-usage-plan.template.json +1 -4
  25. package/test/integ.cftaplam-no-usage-plan.js.snapshot/cftaplamnousageplanIntegDefaultTestDeployAssertABA4F4C5.assets.json +1 -1
  26. package/test/integ.cftaplam-no-usage-plan.js.snapshot/integ.json +2 -2
  27. package/test/integ.cftaplam-no-usage-plan.js.snapshot/manifest.json +23 -31
  28. package/test/integ.cftaplam-no-usage-plan.js.snapshot/tree.json +1 -1
  29. package/test/integ.cftaplam-override-behavior.js +2 -2
  30. package/test/integ.cftaplam-override-behavior.js.snapshot/cdk.out +1 -1
  31. package/test/integ.cftaplam-override-behavior.js.snapshot/cftaplam-override-behavior.assets.json +4 -4
  32. package/test/integ.cftaplam-override-behavior.js.snapshot/cftaplam-override-behavior.template.json +1 -4
  33. package/test/integ.cftaplam-override-behavior.js.snapshot/cftaplamoverridebehaviorIntegDefaultTestDeployAssert3DC30427.assets.json +1 -1
  34. package/test/integ.cftaplam-override-behavior.js.snapshot/integ.json +2 -2
  35. package/test/integ.cftaplam-override-behavior.js.snapshot/manifest.json +23 -31
  36. package/test/integ.cftaplam-override-behavior.js.snapshot/tree.json +1 -1
  37. package/test/test.cloudfront-apigateway-lambda.test.js +0 -364
  38. /package/test/{test.cloudfront-apigateway-lambda.test.d.ts → cloudfront-apigateway-lambda.test.d.ts} +0 -0
@@ -1,364 +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 lib_1 = require("../lib");
16
- const cdk = require("aws-cdk-lib");
17
- const lambda = require("aws-cdk-lib/aws-lambda");
18
- const api = require("aws-cdk-lib/aws-apigateway");
19
- const s3 = require("aws-cdk-lib/aws-s3");
20
- const assertions_1 = require("aws-cdk-lib/assertions");
21
- const defaults = require("@aws-solutions-constructs/core");
22
- function deployNewFunc(stack) {
23
- const lambdaFunctionProps = {
24
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
25
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
26
- handler: 'index.handler'
27
- };
28
- return new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', {
29
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
30
- lambdaFunctionProps
31
- });
32
- }
33
- function useExistingFunc(stack) {
34
- const lambdaFunctionProps = {
35
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
36
- handler: 'index.handler',
37
- code: lambda.Code.fromAsset(`${__dirname}/lambda`)
38
- };
39
- return new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', {
40
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
41
- existingLambdaObj: new lambda.Function(stack, 'MyExistingFunction', lambdaFunctionProps)
42
- });
43
- }
44
- test('check properties', () => {
45
- const stack = new cdk.Stack();
46
- const construct = deployNewFunc(stack);
47
- expect(construct.cloudFrontWebDistribution).toBeDefined();
48
- expect(construct.apiGateway).toBeDefined();
49
- expect(construct.lambdaFunction).toBeDefined();
50
- expect(construct.cloudFrontFunction).toBeDefined();
51
- expect(construct.cloudFrontLoggingBucket).toBeDefined();
52
- expect(construct.apiGatewayCloudWatchRole).toBeDefined();
53
- expect(construct.apiGatewayLogGroup).toBeDefined();
54
- });
55
- test('check lambda function properties for deploy: true', () => {
56
- const stack = new cdk.Stack();
57
- deployNewFunc(stack);
58
- const template = assertions_1.Template.fromStack(stack);
59
- template.hasResourceProperties('AWS::Lambda::Function', {
60
- Handler: "index.handler",
61
- Role: {
62
- "Fn::GetAtt": [
63
- "testcloudfrontapigatewaylambdaLambdaFunctionServiceRoleCB74590F",
64
- "Arn"
65
- ]
66
- },
67
- Runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_STRING,
68
- Environment: {
69
- Variables: {
70
- AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1"
71
- }
72
- }
73
- });
74
- template.resourceCountIs('AWS::ApiGateway::UsagePlan', 1);
75
- });
76
- test('check lambda function role for deploy: false', () => {
77
- const stack = new cdk.Stack();
78
- useExistingFunc(stack);
79
- const template = assertions_1.Template.fromStack(stack);
80
- template.hasResourceProperties('AWS::IAM::Role', {
81
- AssumeRolePolicyDocument: {
82
- Statement: [
83
- {
84
- Action: "sts:AssumeRole",
85
- Effect: "Allow",
86
- Principal: {
87
- Service: "lambda.amazonaws.com"
88
- }
89
- }
90
- ],
91
- Version: "2012-10-17"
92
- },
93
- ManagedPolicyArns: [
94
- {
95
- "Fn::Join": [
96
- "",
97
- [
98
- "arn:",
99
- {
100
- Ref: "AWS::Partition"
101
- },
102
- ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
103
- ]
104
- ]
105
- }
106
- ]
107
- });
108
- });
109
- test('check exception for Missing existingObj from props', () => {
110
- const stack = new cdk.Stack();
111
- const props = {
112
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
113
- };
114
- try {
115
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', props);
116
- }
117
- catch (e) {
118
- expect(e).toBeInstanceOf(Error);
119
- }
120
- });
121
- test('check no prop', () => {
122
- const stack = new cdk.Stack();
123
- const props = {
124
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
125
- };
126
- try {
127
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', props);
128
- }
129
- catch (e) {
130
- expect(e).toBeInstanceOf(Error);
131
- }
132
- });
133
- test('override api gateway properties with existingLambdaObj', () => {
134
- const stack = new cdk.Stack();
135
- const lambdaFunctionProps = {
136
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
137
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
138
- handler: 'index.handler'
139
- };
140
- const fn = new lambda.Function(stack, 'MyExistingFunction', lambdaFunctionProps);
141
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', {
142
- existingLambdaObj: fn,
143
- apiGatewayProps: {
144
- defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE },
145
- description: "Override description"
146
- }
147
- });
148
- const template = assertions_1.Template.fromStack(stack);
149
- template.hasResourceProperties('AWS::ApiGateway::RestApi', {
150
- Description: "Override description",
151
- EndpointConfiguration: {
152
- Types: [
153
- "REGIONAL"
154
- ]
155
- },
156
- Name: "LambdaRestApi"
157
- });
158
- });
159
- test('override api gateway properties without existingLambdaObj', () => {
160
- const stack = new cdk.Stack();
161
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', {
162
- lambdaFunctionProps: {
163
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
164
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
165
- handler: 'index.handler'
166
- },
167
- apiGatewayProps: {
168
- defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE },
169
- endpointConfiguration: {
170
- types: [api.EndpointType.PRIVATE],
171
- },
172
- description: "Override description"
173
- }
174
- });
175
- const template = assertions_1.Template.fromStack(stack);
176
- template.hasResourceProperties('AWS::ApiGateway::RestApi', {
177
- Description: "Override description",
178
- EndpointConfiguration: {
179
- Types: [
180
- "PRIVATE"
181
- ]
182
- },
183
- Name: "LambdaRestApi"
184
- });
185
- });
186
- test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => {
187
- const stack = new cdk.Stack();
188
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', {
189
- lambdaFunctionProps: {
190
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
191
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
192
- handler: 'index.handler'
193
- },
194
- apiGatewayProps: {
195
- defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE },
196
- endpointConfiguration: {
197
- types: [api.EndpointType.PRIVATE],
198
- }
199
- },
200
- cloudFrontLoggingBucketProps: {
201
- removalPolicy: cdk.RemovalPolicy.DESTROY,
202
- autoDeleteObjects: true
203
- }
204
- });
205
- const template = assertions_1.Template.fromStack(stack);
206
- template.hasResourceProperties("AWS::S3::Bucket", {
207
- OwnershipControls: { Rules: [{ ObjectOwnership: "ObjectWriter" }] },
208
- });
209
- template.hasResourceProperties("Custom::S3AutoDeleteObjects", {
210
- ServiceToken: {
211
- "Fn::GetAtt": [
212
- "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F",
213
- "Arn"
214
- ]
215
- },
216
- BucketName: {
217
- Ref: "testcloudfrontapigatewaylambdaCloudFrontToApiGatewayCloudfrontLoggingBucket7F467421"
218
- }
219
- });
220
- });
221
- test('Cloudfront logging bucket error when providing existing log bucket and logBucketProps', () => {
222
- const stack = new cdk.Stack();
223
- const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
224
- const app = () => {
225
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'cloudfront-s3', {
226
- lambdaFunctionProps: {
227
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
228
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
229
- handler: 'index.handler'
230
- },
231
- apiGatewayProps: {
232
- endpointConfiguration: {
233
- types: [api.EndpointType.PRIVATE],
234
- }
235
- },
236
- cloudFrontLoggingBucketProps: {
237
- removalPolicy: cdk.RemovalPolicy.DESTROY,
238
- autoDeleteObjects: true
239
- },
240
- cloudFrontDistributionProps: {
241
- logBucket
242
- },
243
- });
244
- };
245
- expect(app).toThrowError();
246
- });
247
- test('Confirm CheckLambdaProps is being called', () => {
248
- const stack = new cdk.Stack();
249
- const existingLambdaObj = new lambda.Function(stack, 'ExistingLambda', {
250
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
251
- handler: 'index.handler',
252
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
253
- });
254
- const props = {
255
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
256
- existingLambdaObj,
257
- lambdaFunctionProps: {
258
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
259
- handler: 'index.handler',
260
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
261
- }
262
- };
263
- const app = () => {
264
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'cf-test-apigateway-lambda', props);
265
- };
266
- expect(app).toThrowError('Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n');
267
- });
268
- test("Confirm CheckCloudFrontProps is being called", () => {
269
- const stack = new cdk.Stack();
270
- expect(() => {
271
- new lib_1.CloudFrontToApiGatewayToLambda(stack, "test-cloudfront-apigateway-lambda", {
272
- apiGatewayProps: { defaultMethodOptions: { authorizationType: api.AuthorizationType.NONE } },
273
- lambdaFunctionProps: {
274
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
275
- handler: 'index.handler',
276
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
277
- },
278
- insertHttpSecurityHeaders: true,
279
- responseHeadersPolicyProps: {
280
- securityHeadersBehavior: {
281
- strictTransportSecurity: {
282
- accessControlMaxAge: cdk.Duration.seconds(63072),
283
- includeSubdomains: true,
284
- override: false,
285
- preload: true
286
- }
287
- }
288
- }
289
- });
290
- }).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.');
291
- });
292
- test('confirm error thrown for AWS_IAM authorization', () => {
293
- const stack = new cdk.Stack();
294
- const lambdaFunctionProps = {
295
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
296
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
297
- handler: 'index.handler'
298
- };
299
- const props = {
300
- apiGatewayProps: { defaultMethodOptions: { authorizationType: 'AWS_IAM' } },
301
- lambdaFunctionProps
302
- };
303
- const app = () => {
304
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-one', props);
305
- };
306
- expect(app).toThrowError(/Amazon API Gateway Rest APIs integrated with Amazon CloudFront do not support AWS_IAM authorization/);
307
- });
308
- test('confirm error thrown for unspecified authorization', () => {
309
- const stack = new cdk.Stack();
310
- const lambdaFunctionProps = {
311
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
312
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
313
- handler: 'index.handler'
314
- };
315
- const props = {
316
- apiGatewayProps: {},
317
- lambdaFunctionProps
318
- };
319
- const app = () => {
320
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-one', props);
321
- };
322
- expect(app).toThrowError(/As of v2.48.0, an explicit authorization type is required for CloudFront\/API Gateway patterns/);
323
- });
324
- test('Confirm call to CheckApiProps', () => {
325
- // Initial Setup
326
- const stack = new cdk.Stack();
327
- const lambdaFunction = new lambda.Function(stack, 'a-function', {
328
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
329
- handler: 'index.handler',
330
- code: lambda.Code.fromAsset(`${__dirname}/lambda`),
331
- });
332
- const props = {
333
- existingLambdaObj: lambdaFunction,
334
- apiGatewayProps: {
335
- defaultMethodOptions: {
336
- authorizationType: 'AWS_NONE',
337
- apiKeyRequired: true
338
- },
339
- },
340
- createUsagePlan: false,
341
- };
342
- const app = () => {
343
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', props);
344
- };
345
- // Assertion
346
- expect(app).toThrowError('Error - if API key is required, then the Usage plan must be created\n');
347
- });
348
- test('Confirm suppression of Usage Plan', () => {
349
- // Initial Setup
350
- const stack = new cdk.Stack();
351
- const props = {
352
- apiGatewayProps: { defaultMethodOptions: { authorizationType: 'AWS_NONE' } },
353
- lambdaFunctionProps: {
354
- code: new lambda.InlineCode('exports.handler = async (event) => { console.log(event); return {\'statusCode\': 200, \'body\': \'\'}; }'),
355
- runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME,
356
- handler: 'index.handler',
357
- },
358
- createUsagePlan: false
359
- };
360
- new lib_1.CloudFrontToApiGatewayToLambda(stack, 'test-cloudfront-apigateway-lambda', props);
361
- const template = assertions_1.Template.fromStack(stack);
362
- template.resourceCountIs('AWS::ApiGateway::UsagePlan', 0);
363
- });
364
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5jbG91ZGZyb250LWFwaWdhdGV3YXktbGFtYmRhLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LmNsb3VkZnJvbnQtYXBpZ2F0ZXdheS1sYW1iZGEudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBRUgsZ0NBQTZGO0FBQzdGLG1DQUFtQztBQUNuQyxpREFBaUQ7QUFDakQsa0RBQWtEO0FBQ2xELHlDQUF5QztBQUN6Qyx1REFBa0Q7QUFDbEQsMkRBQTJEO0FBRTNELFNBQVMsYUFBYSxDQUFDLEtBQWdCO0lBQ3JDLE1BQU0sbUJBQW1CLEdBQXlCO1FBQ2hELElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLFNBQVMsU0FBUyxDQUFDO1FBQ2xELE9BQU8sRUFBRSxRQUFRLENBQUMscUNBQXFDO1FBQ3ZELE9BQU8sRUFBRSxlQUFlO0tBQ3pCLENBQUM7SUFFRixPQUFPLElBQUksb0NBQThCLENBQUMsS0FBSyxFQUFFLG1DQUFtQyxFQUFFO1FBQ3BGLGVBQWUsRUFBRSxFQUFFLG9CQUFvQixFQUFFLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxFQUFDO1FBQzNGLG1CQUFtQjtLQUNwQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBZ0I7SUFDdkMsTUFBTSxtQkFBbUIsR0FBeUI7UUFDaEQsT0FBTyxFQUFFLFFBQVEsQ0FBQyxxQ0FBcUM7UUFDdkQsT0FBTyxFQUFFLGVBQWU7UUFDeEIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsU0FBUyxTQUFTLENBQUM7S0FDbkQsQ0FBQztJQUVGLE9BQU8sSUFBSSxvQ0FBOEIsQ0FBQyxLQUFLLEVBQUUsbUNBQW1DLEVBQUU7UUFDcEYsZUFBZSxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxpQkFB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QUFVLENBQUMsMEdBQTBHLENBQUM7WUFDdkksT0FBTyxFQUFFLFFBQVEsQ0FBQyxxQ0FBcUM7WUFDdkQsT0FBTyxFQUFFLGVBQWU7U0FDMUI7UUFDRCxlQUFlLEVBQUUsS0FBSztLQUN2QixDQUFDO0lBQ0YsSUFBSSxvQ0FBOEIsQ0FBQyxLQUFLLEVBQUUsbUNBQW1DLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFdEYsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsUUFBUSxDQUFDLGVBQWUsQ0FBQyw0QkFBNEIsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM1RCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpLiBZb3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiAgd2l0aCB0aGUgTGljZW5zZS4gQSBjb3B5IG9mIHRoZSBMaWNlbnNlIGlzIGxvY2F0ZWQgYXRcbiAqXG4gKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqICBvciBpbiB0aGUgJ2xpY2Vuc2UnIGZpbGUgYWNjb21wYW55aW5nIHRoaXMgZmlsZS4gVGhpcyBmaWxlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICdBUyBJUycgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFU1xuICogIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXG4gKiAgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYSwgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhUHJvcHMgfSBmcm9tIFwiLi4vbGliXCI7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBhcGkgZnJvbSAnYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXknO1xuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hc3NlcnRpb25zJztcbmltcG9ydCAqIGFzIGRlZmF1bHRzIGZyb20gJ0Bhd3Mtc29sdXRpb25zLWNvbnN0cnVjdHMvY29yZSc7XG5cbmZ1bmN0aW9uIGRlcGxveU5ld0Z1bmMoc3RhY2s6IGNkay5TdGFjaykge1xuICBjb25zdCBsYW1iZGFGdW5jdGlvblByb3BzOiBsYW1iZGEuRnVuY3Rpb25Qcm9wcyA9IHtcbiAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJ1xuICB9O1xuXG4gIHJldHVybiBuZXcgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LWFwaWdhdGV3YXktbGFtYmRhJywge1xuICAgIGFwaUdhdGV3YXlQcm9wczogeyBkZWZhdWx0TWV0aG9kT3B0aW9uczogeyBhdXRob3JpemF0aW9uVHlwZTogYXBpLkF1dGhvcml6YXRpb25UeXBlLk5PTkUgfX0sXG4gICAgbGFtYmRhRnVuY3Rpb25Qcm9wc1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdXNlRXhpc3RpbmdGdW5jKHN0YWNrOiBjZGsuU3RhY2spIHtcbiAgY29uc3QgbGFtYmRhRnVuY3Rpb25Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhYClcbiAgfTtcblxuICByZXR1cm4gbmV3IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYShzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1hcGlnYXRld2F5LWxhbWJkYScsIHtcbiAgICBhcGlHYXRld2F5UHJvcHM6IHsgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6IGFwaS5BdXRob3JpemF0aW9uVHlwZS5OT05FIH19LFxuICAgIGV4aXN0aW5nTGFtYmRhT2JqOiBuZXcgbGFtYmRhLkZ1bmN0aW9uKHN0YWNrLCAnTXlFeGlzdGluZ0Z1bmN0aW9uJywgbGFtYmRhRnVuY3Rpb25Qcm9wcylcbiAgfSk7XG59XG5cbnRlc3QoJ2NoZWNrIHByb3BlcnRpZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGNvbnN0cnVjdDogQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhID0gZGVwbG95TmV3RnVuYyhzdGFjayk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250V2ViRGlzdHJpYnV0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmFwaUdhdGV3YXkpLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QubGFtYmRhRnVuY3Rpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udEZ1bmN0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmFwaUdhdGV3YXlDbG91ZFdhdGNoUm9sZSkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5hcGlHYXRld2F5TG9nR3JvdXApLnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdCgnY2hlY2sgbGFtYmRhIGZ1bmN0aW9uIHByb3BlcnRpZXMgZm9yIGRlcGxveTogdHJ1ZScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgZGVwbG95TmV3RnVuYyhzdGFjayk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICBIYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICBSb2xlOiB7XG4gICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICBcInRlc3RjbG91ZGZyb250YXBpZ2F0ZXdheWxhbWJkYUxhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGVDQjc0NTkwRlwiLFxuICAgICAgICBcIkFyblwiXG4gICAgICBdXG4gICAgfSxcbiAgICBSdW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9TVFJJTkcsXG4gICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICBBV1NfTk9ERUpTX0NPTk5FQ1RJT05fUkVVU0VfRU5BQkxFRDogXCIxXCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6QXBpR2F0ZXdheTo6VXNhZ2VQbGFuJywgMSk7XG59KTtcblxudGVzdCgnY2hlY2sgbGFtYmRhIGZ1bmN0aW9uIHJvbGUgZm9yIGRlcGxveTogZmFsc2UnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIHVzZUV4aXN0aW5nRnVuYyhzdGFjayk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6SUFNOjpSb2xlJywge1xuICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudDoge1xuICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBBY3Rpb246IFwic3RzOkFzc3VtZVJvbGVcIixcbiAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIFNlcnZpY2U6IFwibGFtYmRhLmFtYXpvbmF3cy5jb21cIlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgfSxcbiAgICBNYW5hZ2VkUG9saWN5QXJuczogW1xuICAgICAge1xuICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICBcIlwiLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIFwiYXJuOlwiLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBSZWY6IFwiQVdTOjpQYXJ0aXRpb25cIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiOmlhbTo6YXdzOnBvbGljeS9zZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlXCJcbiAgICAgICAgICBdXG4gICAgICAgIF1cbiAgICAgIH1cbiAgICBdXG4gIH0pO1xufSk7XG5cbnRlc3QoJ2NoZWNrIGV4Y2VwdGlvbiBmb3IgTWlzc2luZyBleGlzdGluZ09iaiBmcm9tIHByb3BzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBwcm9wczogQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhUHJvcHMgPSB7XG4gICAgYXBpR2F0ZXdheVByb3BzOiB7IGRlZmF1bHRNZXRob2RPcHRpb25zOiB7IGF1dGhvcml6YXRpb25UeXBlOiBhcGkuQXV0aG9yaXphdGlvblR5cGUuTk9ORSB9fSxcbiAgfTtcblxuICB0cnkge1xuICAgIG5ldyBDbG91ZEZyb250VG9BcGlHYXRld2F5VG9MYW1iZGEoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtYXBpZ2F0ZXdheS1sYW1iZGEnLCBwcm9wcyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBleHBlY3QoZSkudG9CZUluc3RhbmNlT2YoRXJyb3IpO1xuICB9XG59KTtcblxudGVzdCgnY2hlY2sgbm8gcHJvcCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYVByb3BzID0ge1xuICAgIGFwaUdhdGV3YXlQcm9wczogeyBkZWZhdWx0TWV0aG9kT3B0aW9uczogeyBhdXRob3JpemF0aW9uVHlwZTogYXBpLkF1dGhvcml6YXRpb25UeXBlLk5PTkUgfX0sXG4gIH07XG5cbiAgdHJ5IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LWFwaWdhdGV3YXktbGFtYmRhJywgcHJvcHMpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgZXhwZWN0KGUpLnRvQmVJbnN0YW5jZU9mKEVycm9yKTtcbiAgfVxufSk7XG5cbnRlc3QoJ292ZXJyaWRlIGFwaSBnYXRld2F5IHByb3BlcnRpZXMgd2l0aCBleGlzdGluZ0xhbWJkYU9iaicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgbGFtYmRhRnVuY3Rpb25Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhYCksXG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcidcbiAgfTtcblxuICBjb25zdCBmbjogbGFtYmRhLkZ1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbihzdGFjaywgJ015RXhpc3RpbmdGdW5jdGlvbicsIGxhbWJkYUZ1bmN0aW9uUHJvcHMpO1xuXG4gIG5ldyBDbG91ZEZyb250VG9BcGlHYXRld2F5VG9MYW1iZGEoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtYXBpZ2F0ZXdheS1sYW1iZGEnLCB7XG4gICAgZXhpc3RpbmdMYW1iZGFPYmo6IGZuLFxuICAgIGFwaUdhdGV3YXlQcm9wczoge1xuICAgICAgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6IGFwaS5BdXRob3JpemF0aW9uVHlwZS5OT05FIH0sXG4gICAgICBkZXNjcmlwdGlvbjogXCJPdmVycmlkZSBkZXNjcmlwdGlvblwiXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpBcGlHYXRld2F5OjpSZXN0QXBpJyxcbiAgICB7XG4gICAgICBEZXNjcmlwdGlvbjogXCJPdmVycmlkZSBkZXNjcmlwdGlvblwiLFxuICAgICAgRW5kcG9pbnRDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIFR5cGVzOiBbXG4gICAgICAgICAgXCJSRUdJT05BTFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBOYW1lOiBcIkxhbWJkYVJlc3RBcGlcIlxuICAgIH0pO1xufSk7XG5cbnRlc3QoJ292ZXJyaWRlIGFwaSBnYXRld2F5IHByb3BlcnRpZXMgd2l0aG91dCBleGlzdGluZ0xhbWJkYU9iaicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYShzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1hcGlnYXRld2F5LWxhbWJkYScsIHtcbiAgICBsYW1iZGFGdW5jdGlvblByb3BzOiB7XG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgICAgIHJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1JVTlRJTUUsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcidcbiAgICB9LFxuICAgIGFwaUdhdGV3YXlQcm9wczoge1xuICAgICAgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6IGFwaS5BdXRob3JpemF0aW9uVHlwZS5OT05FIH0sXG4gICAgICBlbmRwb2ludENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgdHlwZXM6IFthcGkuRW5kcG9pbnRUeXBlLlBSSVZBVEVdLFxuICAgICAgfSxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIk92ZXJyaWRlIGRlc2NyaXB0aW9uXCJcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkFwaUdhdGV3YXk6OlJlc3RBcGknLFxuICAgIHtcbiAgICAgIERlc2NyaXB0aW9uOiBcIk92ZXJyaWRlIGRlc2NyaXB0aW9uXCIsXG4gICAgICBFbmRwb2ludENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgVHlwZXM6IFtcbiAgICAgICAgICBcIlBSSVZBVEVcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgTmFtZTogXCJMYW1iZGFSZXN0QXBpXCJcbiAgICB9KTtcbn0pO1xuXG50ZXN0KCdDbG91ZGZyb250IGxvZ2dpbmcgYnVja2V0IHdpdGggZGVzdHJveSByZW1vdmFsIHBvbGljeSBhbmQgYXV0byBkZWxldGUgb2JqZWN0cycsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYShzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1hcGlnYXRld2F5LWxhbWJkYScsIHtcbiAgICBsYW1iZGFGdW5jdGlvblByb3BzOiB7XG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgICAgIHJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1JVTlRJTUUsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcidcbiAgICB9LFxuICAgIGFwaUdhdGV3YXlQcm9wczoge1xuICAgICAgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6IGFwaS5BdXRob3JpemF0aW9uVHlwZS5OT05FIH0sXG4gICAgICBlbmRwb2ludENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgdHlwZXM6IFthcGkuRW5kcG9pbnRUeXBlLlBSSVZBVEVdLFxuICAgICAgfVxuICAgIH0sXG4gICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgT3duZXJzaGlwQ29udHJvbHM6IHsgUnVsZXM6IFsgeyBPYmplY3RPd25lcnNoaXA6IFwiT2JqZWN0V3JpdGVyXCIgfSBdIH0sXG4gIH0pO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkN1c3RvbTo6UzNBdXRvRGVsZXRlT2JqZWN0c1wiLCB7XG4gICAgU2VydmljZVRva2VuOiB7XG4gICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICBcIkN1c3RvbVMzQXV0b0RlbGV0ZU9iamVjdHNDdXN0b21SZXNvdXJjZVByb3ZpZGVySGFuZGxlcjlEOTAxODRGXCIsXG4gICAgICAgIFwiQXJuXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIEJ1Y2tldE5hbWU6IHtcbiAgICAgIFJlZjogXCJ0ZXN0Y2xvdWRmcm9udGFwaWdhdGV3YXlsYW1iZGFDbG91ZEZyb250VG9BcGlHYXRld2F5Q2xvdWRmcm9udExvZ2dpbmdCdWNrZXQ3RjQ2NzQyMVwiXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdDbG91ZGZyb250IGxvZ2dpbmcgYnVja2V0IGVycm9yIHdoZW4gcHJvdmlkaW5nIGV4aXN0aW5nIGxvZyBidWNrZXQgYW5kIGxvZ0J1Y2tldFByb3BzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7IG5ldyBDbG91ZEZyb250VG9BcGlHYXRld2F5VG9MYW1iZGEoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGxhbWJkYUZ1bmN0aW9uUHJvcHM6IHtcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYWApLFxuICAgICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJ1xuICAgIH0sXG4gICAgYXBpR2F0ZXdheVByb3BzOiB7XG4gICAgICBlbmRwb2ludENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgdHlwZXM6IFthcGkuRW5kcG9pbnRUeXBlLlBSSVZBVEVdLFxuICAgICAgfVxuICAgIH0sXG4gICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlXG4gICAgfSxcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGxvZ0J1Y2tldFxuICAgIH0sXG4gIH0pO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigpO1xufSk7XG5cbnRlc3QoJ0NvbmZpcm0gQ2hlY2tMYW1iZGFQcm9wcyBpcyBiZWluZyBjYWxsZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBleGlzdGluZ0xhbWJkYU9iaiA9IG5ldyBsYW1iZGEuRnVuY3Rpb24oc3RhY2ssICdFeGlzdGluZ0xhbWJkYScsIHtcbiAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgfSk7XG5cbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYVByb3BzID0ge1xuICAgIGFwaUdhdGV3YXlQcm9wczogeyBkZWZhdWx0TWV0aG9kT3B0aW9uczogeyBhdXRob3JpemF0aW9uVHlwZTogYXBpLkF1dGhvcml6YXRpb25UeXBlLk5PTkUgfX0sXG4gICAgZXhpc3RpbmdMYW1iZGFPYmosXG4gICAgbGFtYmRhRnVuY3Rpb25Qcm9wczoge1xuICAgICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYWApLFxuICAgIH1cbiAgfTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYShzdGFjaywgJ2NmLXRlc3QtYXBpZ2F0ZXdheS1sYW1iZGEnLCBwcm9wcyk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcignRXJyb3IgLSBFaXRoZXIgcHJvdmlkZSBsYW1iZGFGdW5jdGlvblByb3BzIG9yIGV4aXN0aW5nTGFtYmRhT2JqLCBidXQgbm90IGJvdGguXFxuJyk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tDbG91ZEZyb250UHJvcHMgaXMgYmVpbmcgY2FsbGVkXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgZXhwZWN0KCgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhKHN0YWNrLCBcInRlc3QtY2xvdWRmcm9udC1hcGlnYXRld2F5LWxhbWJkYVwiLCB7XG4gICAgICBhcGlHYXRld2F5UHJvcHM6IHsgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6IGFwaS5BdXRob3JpemF0aW9uVHlwZS5OT05FIH19LFxuICAgICAgbGFtYmRhRnVuY3Rpb25Qcm9wczoge1xuICAgICAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYWApLFxuICAgICAgfSxcbiAgICAgIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnM6IHRydWUsXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wczoge1xuICAgICAgICBzZWN1cml0eUhlYWRlcnNCZWhhdmlvcjoge1xuICAgICAgICAgIHN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICAgICAgICBhY2Nlc3NDb250cm9sTWF4QWdlOiBjZGsuRHVyYXRpb24uc2Vjb25kcyg2MzA3MiksXG4gICAgICAgICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgICAgICAgIG92ZXJyaWRlOiBmYWxzZSxcbiAgICAgICAgICAgIHByZWxvYWQ6IHRydWVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSkudG9UaHJvd0Vycm9yKCdyZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcy5zZWN1cml0eUhlYWRlcnNCZWhhdmlvciBjYW4gb25seSBiZSBwYXNzZWQgaWYgaHR0cFNlY3VyaXR5SGVhZGVycyBpcyBzZXQgdG8gYGZhbHNlYC4nKTtcbn0pO1xuXG50ZXN0KCdjb25maXJtIGVycm9yIHRocm93biBmb3IgQVdTX0lBTSBhdXRob3JpemF0aW9uJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbGFtYmRhRnVuY3Rpb25Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhYCksXG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcidcbiAgfTtcblxuICBjb25zdCBwcm9wcyA9IHtcbiAgICBhcGlHYXRld2F5UHJvcHM6IHsgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHsgYXV0aG9yaXphdGlvblR5cGU6ICdBV1NfSUFNJyB9fSxcbiAgICBsYW1iZGFGdW5jdGlvblByb3BzXG4gIH07XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9BcGlHYXRld2F5VG9MYW1iZGEoc3RhY2ssICd0ZXN0LW9uZScsIHByb3BzKTtcbiAgfTtcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKC9BbWF6b24gQVBJIEdhdGV3YXkgUmVzdCBBUElzIGludGVncmF0ZWQgd2l0aCBBbWF6b24gQ2xvdWRGcm9udCBkbyBub3Qgc3VwcG9ydCBBV1NfSUFNIGF1dGhvcml6YXRpb24vKTtcbn0pO1xuXG50ZXN0KCdjb25maXJtIGVycm9yIHRocm93biBmb3IgdW5zcGVjaWZpZWQgYXV0aG9yaXphdGlvbicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxhbWJkYUZ1bmN0aW9uUHJvcHM6IGxhbWJkYS5GdW5jdGlvblByb3BzID0ge1xuICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYWApLFxuICAgIHJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1JVTlRJTUUsXG4gICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInXG4gIH07XG5cbiAgY29uc3QgcHJvcHMgPSB7XG4gICAgYXBpR2F0ZXdheVByb3BzOiB7IH0sXG4gICAgbGFtYmRhRnVuY3Rpb25Qcm9wc1xuICB9O1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhKHN0YWNrLCAndGVzdC1vbmUnLCBwcm9wcyk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvQXMgb2YgdjIuNDguMCwgYW4gZXhwbGljaXQgYXV0aG9yaXphdGlvbiB0eXBlIGlzIHJlcXVpcmVkIGZvciBDbG91ZEZyb250XFwvQVBJIEdhdGV3YXkgcGF0dGVybnMvKTtcbn0pO1xuXG50ZXN0KCdDb25maXJtIGNhbGwgdG8gQ2hlY2tBcGlQcm9wcycsICgpID0+IHtcbiAgLy8gSW5pdGlhbCBTZXR1cFxuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbGFtYmRhRnVuY3Rpb24gPSBuZXcgbGFtYmRhLkZ1bmN0aW9uKHN0YWNrLCAnYS1mdW5jdGlvbicsIHtcbiAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgfSk7XG5cbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb0FwaUdhdGV3YXlUb0xhbWJkYVByb3BzID0ge1xuICAgIGV4aXN0aW5nTGFtYmRhT2JqOiBsYW1iZGFGdW5jdGlvbixcbiAgICBhcGlHYXRld2F5UHJvcHM6IHtcbiAgICAgIGRlZmF1bHRNZXRob2RPcHRpb25zOiB7XG4gICAgICAgIGF1dGhvcml6YXRpb25UeXBlOiAnQVdTX05PTkUnLFxuICAgICAgICBhcGlLZXlSZXF1aXJlZDogdHJ1ZVxuICAgICAgfSxcbiAgICB9LFxuICAgIGNyZWF0ZVVzYWdlUGxhbjogZmFsc2UsXG4gIH07XG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LWFwaWdhdGV3YXktbGFtYmRhJywgcHJvcHMpO1xuICB9O1xuICAvLyBBc3NlcnRpb25cbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKCdFcnJvciAtIGlmIEFQSSBrZXkgaXMgcmVxdWlyZWQsIHRoZW4gdGhlIFVzYWdlIHBsYW4gbXVzdCBiZSBjcmVhdGVkXFxuJyk7XG59KTtcblxudGVzdCgnQ29uZmlybSBzdXBwcmVzc2lvbiBvZiBVc2FnZSBQbGFuJywgKCkgPT4ge1xuICAvLyBJbml0aWFsIFNldHVwXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBwcm9wczogQ2xvdWRGcm9udFRvQXBpR2F0ZXdheVRvTGFtYmRhUHJvcHMgPSB7XG4gICAgYXBpR2F0ZXdheVByb3BzOiB7IGRlZmF1bHRNZXRob2RPcHRpb25zOiB7IGF1dGhvcml6YXRpb25UeXBlOiAnQVdTX05PTkUnIH19LFxuICAgIGxhbWJkYUZ1bmN0aW9uUHJvcHM6IHtcbiAgICAgICBjb2RlOiBuZXcgbGFtYmRhLklubGluZUNvZGUoJ2V4cG9ydHMuaGFuZGxlciA9IGFzeW5jIChldmVudCkgPT4geyBjb25zb2xlLmxvZyhldmVudCk7IHJldHVybiB7XFwnc3RhdHVzQ29kZVxcJzogMjAwLCBcXCdib2R5XFwnOiBcXCdcXCd9OyB9JyksXG4gICAgICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgfSxcbiAgICBjcmVhdGVVc2FnZVBsYW46IGZhbHNlXG4gIH07XG4gIG5ldyBDbG91ZEZyb250VG9BcGlHYXRld2F5VG9MYW1iZGEoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtYXBpZ2F0ZXdheS1sYW1iZGEnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6QXBpR2F0ZXdheTo6VXNhZ2VQbGFuJywgMCk7XG59KTtcbiJdfQ==