@cdktn/hcl2cdk 0.23.0-pre.7 → 0.23.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 (85) hide show
  1. package/ambient.d.ts +0 -1
  2. package/build/__tests__/coerceType.test.js +165 -0
  3. package/build/__tests__/expressionToTs.test.js +693 -0
  4. package/build/__tests__/expressions.test.js +415 -0
  5. package/build/__tests__/findExpressionType.test.js +105 -0
  6. package/build/__tests__/functions.test.js +605 -0
  7. package/build/__tests__/generation.test.js +45 -0
  8. package/build/__tests__/jsii-rosetta-workarounds.test.js +86 -0
  9. package/build/__tests__/partialCode.test.js +390 -0
  10. package/build/__tests__/terraformSchema.test.js +105 -0
  11. package/build/__tests__/testHelpers.js +16 -0
  12. package/build/coerceType.js +240 -0
  13. package/build/dynamic-blocks.js +44 -0
  14. package/build/expressions.js +633 -0
  15. package/build/function-bindings/functions.generated.js +1142 -0
  16. package/build/function-bindings/functions.js +73 -0
  17. package/{lib → build}/generation.js +4 -4
  18. package/{lib → build}/index.d.ts +2 -2
  19. package/build/index.js +364 -0
  20. package/build/iteration.js +87 -0
  21. package/build/jsii-rosetta-workarounds.js +126 -0
  22. package/build/partialCode.js +116 -0
  23. package/build/provider.js +40 -0
  24. package/build/references.js +141 -0
  25. package/build/schema.js +81 -0
  26. package/build/telemetryAllowList.json +24 -0
  27. package/build/terraformSchema.js +136 -0
  28. package/build/types.js +3 -0
  29. package/build/utils.js +25 -0
  30. package/build/variables.js +172 -0
  31. package/package.json +13 -14
  32. package/tsconfig.json +4 -2
  33. package/lib/__tests__/coerceType.test.js +0 -165
  34. package/lib/__tests__/expressionToTs.test.js +0 -693
  35. package/lib/__tests__/expressions.test.js +0 -415
  36. package/lib/__tests__/findExpressionType.test.js +0 -105
  37. package/lib/__tests__/functions.test.js +0 -605
  38. package/lib/__tests__/generation.test.js +0 -45
  39. package/lib/__tests__/jsii-rosetta-workarounds.test.js +0 -86
  40. package/lib/__tests__/partialCode.test.js +0 -390
  41. package/lib/__tests__/terraformSchema.test.js +0 -105
  42. package/lib/__tests__/testHelpers.js +0 -16
  43. package/lib/coerceType.js +0 -240
  44. package/lib/dynamic-blocks.js +0 -44
  45. package/lib/expressions.js +0 -634
  46. package/lib/function-bindings/functions.generated.js +0 -1142
  47. package/lib/function-bindings/functions.js +0 -73
  48. package/lib/index.js +0 -364
  49. package/lib/iteration.js +0 -87
  50. package/lib/jsii-rosetta-workarounds.js +0 -126
  51. package/lib/partialCode.js +0 -116
  52. package/lib/provider.js +0 -40
  53. package/lib/references.js +0 -141
  54. package/lib/schema.js +0 -81
  55. package/lib/terraformSchema.js +0 -136
  56. package/lib/types.js +0 -3
  57. package/lib/utils.js +0 -25
  58. package/lib/variables.js +0 -172
  59. /package/{lib → build}/__tests__/coerceType.test.d.ts +0 -0
  60. /package/{lib → build}/__tests__/expressionToTs.test.d.ts +0 -0
  61. /package/{lib → build}/__tests__/expressions.test.d.ts +0 -0
  62. /package/{lib → build}/__tests__/findExpressionType.test.d.ts +0 -0
  63. /package/{lib → build}/__tests__/functions.test.d.ts +0 -0
  64. /package/{lib → build}/__tests__/generation.test.d.ts +0 -0
  65. /package/{lib → build}/__tests__/jsii-rosetta-workarounds.test.d.ts +0 -0
  66. /package/{lib → build}/__tests__/partialCode.test.d.ts +0 -0
  67. /package/{lib → build}/__tests__/terraformSchema.test.d.ts +0 -0
  68. /package/{lib → build}/__tests__/testHelpers.d.ts +0 -0
  69. /package/{lib → build}/coerceType.d.ts +0 -0
  70. /package/{lib → build}/dynamic-blocks.d.ts +0 -0
  71. /package/{lib → build}/expressions.d.ts +0 -0
  72. /package/{lib → build}/function-bindings/functions.d.ts +0 -0
  73. /package/{lib → build}/function-bindings/functions.generated.d.ts +0 -0
  74. /package/{lib → build}/generation.d.ts +0 -0
  75. /package/{lib → build}/iteration.d.ts +0 -0
  76. /package/{lib → build}/jsii-rosetta-workarounds.d.ts +0 -0
  77. /package/{lib → build}/partialCode.d.ts +0 -0
  78. /package/{lib → build}/provider.d.ts +0 -0
  79. /package/{lib → build}/references.d.ts +0 -0
  80. /package/{lib → build}/schema.d.ts +0 -0
  81. /package/{lib → build}/terraformSchema.d.ts +0 -0
  82. /package/{lib → build}/types.d.ts +0 -0
  83. /package/{lib → build}/utils.d.ts +0 -0
  84. /package/{lib → build}/variables.d.ts +0 -0
  85. /package/{lib → src}/telemetryAllowList.json +0 -0
@@ -1,693 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) HashiCorp, Inc.
4
- * SPDX-License-Identifier: MPL-2.0
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const expressions_1 = require("../expressions");
8
- const testHelpers_1 = require("./testHelpers");
9
- const awsProviderSchema = {
10
- format_version: "1.0",
11
- provider_schemas: {
12
- "registry.terraform.io/hashicorp/aws": {
13
- provider: {},
14
- resource_schemas: {
15
- aws_s3_bucket: {
16
- block: {
17
- attributes: {
18
- foo: {
19
- type: ["map", "string"],
20
- description_kind: "plain",
21
- },
22
- },
23
- },
24
- },
25
- },
26
- data_source_schemas: {
27
- aws_availability_zones: {
28
- version: 0,
29
- block: {
30
- attributes: {
31
- all_availability_zones: {
32
- type: "bool",
33
- description_kind: "plain",
34
- optional: true,
35
- },
36
- exclude_names: {
37
- type: ["set", "string"],
38
- description_kind: "plain",
39
- optional: true,
40
- },
41
- exclude_zone_ids: {
42
- type: ["set", "string"],
43
- description_kind: "plain",
44
- optional: true,
45
- },
46
- group_names: {
47
- type: ["set", "string"],
48
- description_kind: "plain",
49
- computed: true,
50
- },
51
- id: {
52
- type: "string",
53
- description_kind: "plain",
54
- optional: true,
55
- computed: true,
56
- },
57
- names: {
58
- type: ["list", "string"],
59
- description_kind: "plain",
60
- computed: true,
61
- },
62
- state: {
63
- type: "string",
64
- description_kind: "plain",
65
- optional: true,
66
- },
67
- zone_ids: {
68
- type: ["list", "string"],
69
- description_kind: "plain",
70
- computed: true,
71
- },
72
- testing_map: {
73
- type: ["map", "string"],
74
- description_kind: "plain",
75
- computed: true,
76
- },
77
- },
78
- block_types: {
79
- filter: {
80
- nesting_mode: "set",
81
- block: {
82
- attributes: {
83
- name: {
84
- type: "string",
85
- description_kind: "plain",
86
- required: true,
87
- },
88
- values: {
89
- type: ["set", "string"],
90
- description_kind: "plain",
91
- required: true,
92
- },
93
- },
94
- description_kind: "plain",
95
- },
96
- },
97
- timeouts: {
98
- nesting_mode: "single",
99
- block: {
100
- attributes: {
101
- read: {
102
- type: "string",
103
- description_kind: "plain",
104
- optional: true,
105
- },
106
- },
107
- description_kind: "plain",
108
- },
109
- },
110
- },
111
- description_kind: "plain",
112
- },
113
- },
114
- },
115
- },
116
- },
117
- };
118
- const externalProviderSchema = {
119
- format_version: "1.0",
120
- provider_schemas: {
121
- "registry.terraform.io/hashicorp/external": {
122
- provider: {},
123
- resource_schemas: {},
124
- data_source_schemas: {
125
- external: {
126
- version: 0,
127
- block: {
128
- attributes: {
129
- id: {
130
- type: "string",
131
- description: "The id of the data source. This will always be set to `-`",
132
- description_kind: "plain",
133
- computed: true,
134
- },
135
- program: {
136
- type: ["list", "string"],
137
- description: "A list of strings, whose first element is the program to run and whose subsequent elements are optional command line arguments to the program. Terraform does not execute the program through a shell, so it is not necessary to escape shell metacharacters nor add quotes around arguments containing spaces.",
138
- description_kind: "plain",
139
- required: true,
140
- },
141
- query: {
142
- type: ["map", "string"],
143
- description: "A map of string values to pass to the external program as the query arguments. If not supplied, the program will receive an empty object as its input.",
144
- description_kind: "plain",
145
- optional: true,
146
- },
147
- result: {
148
- type: ["map", "string"],
149
- description: "A map of string values returned from the external program.",
150
- description_kind: "plain",
151
- computed: true,
152
- },
153
- working_dir: {
154
- type: "string",
155
- description: "Working directory of the program. If not supplied, the program will run in the current directory.",
156
- description_kind: "plain",
157
- optional: true,
158
- },
159
- },
160
- description: 'The `external` data source allows an external program implementing a specific protocol (defined below) to act as a data source, exposing arbitrary data for use elsewhere in the Terraform configuration.\n\n**Warning** This mechanism is provided as an "escape hatch" for exceptional situations where a first-class Terraform provider is not more appropriate. Its capabilities are limited in comparison to a true data source, and implementing a data source via an external program is likely to hurt the portability of your Terraform configuration by creating dependencies on external programs and libraries that may not be available (or may need to be used differently) on different operating systems.\n\n**Warning** Terraform Enterprise does not guarantee availability of any particular language runtimes or external programs beyond standard shell utilities, so it is not recommended to use this data source within configurations that are applied within Terraform Enterprise.',
161
- description_kind: "plain",
162
- },
163
- },
164
- },
165
- },
166
- },
167
- };
168
- function getScope({ provider, resources, data, variables, locals, forEachIteratorName, scopedVariables, withinOverrideExpression = false, } = {}) {
169
- const scopeVariables = {};
170
- resources === null || resources === void 0 ? void 0 : resources.forEach((varName) => {
171
- let [resourceType, resourceName] = varName.split(".");
172
- if (!resourceName) {
173
- resourceName = varName;
174
- resourceType = "aws_s3_bucket";
175
- }
176
- scopeVariables[varName] = {
177
- resource: resourceType,
178
- variableName: resourceName,
179
- };
180
- });
181
- data === null || data === void 0 ? void 0 : data.forEach((varName) => {
182
- scopeVariables[varName] = {
183
- resource: "data.aws_s3_bucket",
184
- variableName: varName,
185
- };
186
- });
187
- variables === null || variables === void 0 ? void 0 : variables.forEach((varName) => {
188
- scopeVariables[varName] = {
189
- resource: "var",
190
- variableName: varName,
191
- };
192
- });
193
- locals === null || locals === void 0 ? void 0 : locals.forEach((varName) => {
194
- scopeVariables[varName] = {
195
- resource: "local",
196
- variableName: varName,
197
- };
198
- });
199
- const scope = {
200
- providerSchema: provider !== null && provider !== void 0 ? provider : {},
201
- providerGenerator: {},
202
- constructs: new Set(),
203
- variables: scopeVariables,
204
- hasTokenBasedTypeCoercion: true,
205
- scopedVariables: scopedVariables || {},
206
- forEachIteratorName,
207
- withinOverrideExpression,
208
- nodeIds: [],
209
- importables: [],
210
- topLevelConfig: {},
211
- };
212
- return scope;
213
- }
214
- const getType = () => "string";
215
- describe("expressionToTs", () => {
216
- test("converts a simple string to a string", async () => {
217
- const expression = "hello";
218
- const scope = getScope();
219
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
220
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello""`);
221
- });
222
- test("converts a simple expression with a template", async () => {
223
- const expression = "${22}";
224
- const scope = getScope();
225
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
226
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(22)"`);
227
- });
228
- test("converts a variable reference", async () => {
229
- const expression = "${var.foo}";
230
- const scope = getScope();
231
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
232
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"foo.stringValue"`);
233
- });
234
- test("convert a variable reference with snake case", async () => {
235
- const expression = "${var.foo_bar}";
236
- const scope = getScope({ variables: ["foo_bar"] });
237
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
238
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(fooBar.value)"`);
239
- });
240
- test("convert a function call", async () => {
241
- const expression = `\${replace("hello", "l", "w")}`;
242
- const scope = getScope();
243
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
244
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.replace("hello", "l", "w"))"`);
245
- });
246
- test("converts a function call with an expression", async () => {
247
- const expression = `\${replace("hello-\${22+22}", "44", "world")}`;
248
- const scope = getScope();
249
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
250
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.replace("hello-" + Token.asString(Op.add(22, 22)), "44", "world"))"`);
251
- });
252
- test("converts string concatenation of iterator key", async () => {
253
- const expression = '${"dynamic-ingress-${ingress.key}"}';
254
- const scope = getScope({
255
- scopedVariables: {
256
- ingress: "dynamic_iterator0",
257
- },
258
- });
259
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
260
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""dynamic-ingress-\${" + Token.asString(dynamic_iterator0.key) + "}""`);
261
- });
262
- test("convert a variable reference", async () => {
263
- const expression = `\${var.foo_bar}`;
264
- const scope = getScope({ variables: ["foo_bar"] });
265
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
266
- // TODO: This seems broken
267
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(fooBar.value)"`);
268
- });
269
- test("convert a resource reference", async () => {
270
- const expression = `"simple-\${aws_s3_bucket.foo.id}"`;
271
- const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
272
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
273
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo.id + "}""`);
274
- });
275
- test("convert a resource reference with nested properties", async () => {
276
- const expression = `"simple-\${aws_s3_bucket.foo.prop.test}"`;
277
- const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
278
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
279
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo.prop.test + "}""`);
280
- });
281
- test("convert a local reference", async () => {
282
- const expression = `"simple-\${local.foo}"`;
283
- const scope = getScope({ locals: ["foo"] });
284
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
285
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo + "}""`);
286
- });
287
- test("plain resource references in arithmetics", async () => {
288
- const expression = "${aws_s3_bucket.examplebucket.count + aws_s3_bucket.otherbucket.count }";
289
- const scope = getScope({
290
- resources: ["aws_s3_bucket.examplebucket", "aws_s3_bucket.otherbucket"],
291
- });
292
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
293
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.add(examplebucket.count, otherbucket.count))"`);
294
- });
295
- test("use fqn for splat reference", async () => {
296
- const expression = `\${aws_s3_bucket.foo.*.id}`;
297
- const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
298
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
299
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(foo, ["*", "id"]))"`);
300
- });
301
- test("use fqn if property is present on numeric access using dot notation", async () => {
302
- const expression = "${aws_s3_bucket.examplebucket.network_interface.0.access_config.0.assigned_nat_ip}";
303
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
304
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
305
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
306
- });
307
- test("use fqn if property is present on numeric access", async () => {
308
- const expression = "${aws_s3_bucket.examplebucket.network_interface[0].access_config[0].assigned_nat_ip}";
309
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
310
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
311
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
312
- });
313
- test("use no fqn if property is present on numeric access using []", async () => {
314
- const expression = "${aws_s3_bucket.examplebucket.network_interface[0].access_config[0].assigned_nat_ip}";
315
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
316
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
317
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
318
- });
319
- test("detects splat reference within function", async () => {
320
- const expression = "${toset(aws_s3_bucket.examplebucket.*)}";
321
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
322
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
323
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.toset(Fn.lookupNested(examplebucket, ["*"])))"`);
324
- });
325
- test("convert conditional", async () => {
326
- const expression = "${aws_kms_key.key.deletion_window_in_days > 3 ? aws_s3_bucket.examplebucket.id : []}";
327
- const scope = getScope({ resources: ["aws_kms_key.key", "examplebucket"] });
328
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
329
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(conditional(Op.gt(key.deletionWindowInDays, 3), examplebucket.id, []))"`);
330
- });
331
- test("converts a function with references", async () => {
332
- const expression = "${element(aws_s3_bucket.examplebucket, 0).id}";
333
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
334
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
335
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(Fn.element(examplebucket, 0), ["id"]))"`);
336
- });
337
- test("converts a function with splat reference", async () => {
338
- const expression = "${element(aws_s3_bucket.examplebucket.*.id, 0)}";
339
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
340
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
341
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.element(Fn.lookupNested(examplebucket, ["*", "id"]), 0))"`);
342
- });
343
- test("convert for loops", async () => {
344
- const expression = "${{ for name, user in var.users : user.role => name...}}";
345
- const scope = getScope();
346
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
347
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for name, user in \${" + users.value + "} : user.role => name...}}""`);
348
- });
349
- test("for expressions", async () => {
350
- const expression = "{for s in var.list : s => upper(s)}";
351
- const scope = getScope();
352
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
353
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for s in \${" + list.value + "} : s => upper(s)}}""`);
354
- });
355
- test("for list expression ", async () => {
356
- const expression = "[for s in var.list : upper(s)]";
357
- const scope = getScope();
358
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
359
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for s in \${" + list.value + "} : upper(s)]}""`);
360
- });
361
- test("for list with conditional", async () => {
362
- const expression = '[for s in var.list : upper(s) if s != ""]';
363
- const scope = getScope();
364
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
365
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for s in \${" + list.value + "} : upper(s) if s != \\"\\"]}""`);
366
- });
367
- test("convert property access resources", async () => {
368
- const expression = "${aws_s3_bucket.examplebucket[0].id}";
369
- const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
370
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
371
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket, ["0", "id"]))"`);
372
- });
373
- test("convert unary operators", async () => {
374
- const expression = `\${!var.enabled}`;
375
- const scope = getScope({ variables: ["enabled"] });
376
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "bool");
377
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asBoolean(Op.not(enabled.value))"`);
378
- });
379
- test("convert function with arrays and comments", async () => {
380
- const expression = `\${compact([
381
- # The example "bucket"
382
- aws_s3_bucket.examplebucket,
383
-
384
- # The "Learn" single page application. This is not configured in all environments.
385
- var.input,
386
- ])}`;
387
- const scope = getScope({
388
- resources: ["aws_s3_bucket.examplebucket"],
389
- variables: ["input"],
390
- });
391
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
392
- // TODO: See if we have a way to preserve comments
393
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.compact(Token.asList([examplebucket, input.value])))"`);
394
- });
395
- test("convert references for same reference", async () => {
396
- const expression = `\${var.input == "test" ? "azure-ad-int" : "azure-ad-\${var.input}"}`;
397
- const scope = getScope({ variables: ["input"] });
398
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
399
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(conditional(Op.eq(input.value, "test"), "azure-ad-int", "azure-ad-\${" + input.value + "}"))"`);
400
- });
401
- test("nested variable access", async () => {
402
- const expression = `\${element(var.test2["val1"], 0)}`;
403
- const scope = getScope({ variables: ["test2"] });
404
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
405
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.element(Fn.lookupNested(test2.value, ["\\"val1\\""]), 0))"`);
406
- });
407
- test("complicated nested local value", async () => {
408
- const expression = "${flatten(var.vnets[*].subnets[*].name)}";
409
- const scope = getScope({ variables: ["vnets"] });
410
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
411
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.flatten(Fn.lookupNested(vnets.value, ["*", "subnets", "*", "name"])))"`);
412
- });
413
- // TOIMPROVE: I don't think we can handle this case yet, since the variable
414
- // needs to be wrapped in an iterator. I'm leaving this in, but it's broken
415
- test("complicated nested variable access with map", async () => {
416
- const expression = `{
417
- for vnet in var.vnets[*]:
418
- (vnet.vnet_name) => vnet.subnets[*].name
419
- }`;
420
- const scope = getScope({ variables: ["vnets"] });
421
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
422
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for vnet in \${" + Fn.lookupNested(vnets.value, ["*"]) + "} : (vnet.vnet_name) => vnet.subnets[*].name}}""`);
423
- });
424
- test("complicated nested variable access with list", async () => {
425
- const expression = `\${flatten([
426
- for k, v in var.route : [
427
- for n, s in v : [
428
- {
429
- key = k,
430
- name = n,
431
- svc_url = s
432
- }
433
- ]
434
- ]
435
- ])}`;
436
- const scope = getScope({ variables: ["route"] });
437
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
438
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.flatten("\${[ for k, v in \${" + route.value + "} : [\\n for n, s in v : [\\n {\\n key = k,\\n name = n,\\n svc_url = s\\n }\\n ]\\n ]]}"))"`);
439
- });
440
- test("simple local variable access", async () => {
441
- const expression = "${!local.enabled}";
442
- const scope = getScope({ locals: ["enabled"] });
443
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
444
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.not(enabled))"`);
445
- });
446
- test("multi local access", async () => {
447
- const expression = '"${local.service_name},${local.owner},${local.is_it_great},${local.how_many}"';
448
- const scope = getScope({
449
- locals: ["service_name", "owner", "is_it_great", "how_many"],
450
- });
451
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
452
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${" + serviceName + "},\${" + owner + "},\${" + isItGreat + "},\${" + howMany + "}""`);
453
- });
454
- test("binary operations within literals and variables", async () => {
455
- const expression = '"${var.test} + 1"';
456
- const scope = getScope({ variables: ["test"] });
457
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
458
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${" + test.value + "} + 1""`);
459
- });
460
- test("local variable access", async () => {
461
- const expression = '"${local.enabled}"';
462
- const scope = getScope({ locals: ["enabled"] });
463
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
464
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"enabled"`);
465
- });
466
- test("converts traversals that cannot be references", async () => {
467
- const expression = "${self.path}";
468
- const scope = getScope();
469
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
470
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(TerraformSelf.getAny("path"))"`);
471
- });
472
- test("converts join function with variables", async () => {
473
- const expression = '${join("-", [var.tags.app, var.tags.env])}';
474
- const scope = getScope({ variables: ["tags"] });
475
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
476
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.join("-", Token.asList([Fn.lookupNested(tags.value, ["app"]), Fn.lookupNested(tags.value, ["env"])])))"`);
477
- });
478
- test("converts join function with many arguments variables", async () => {
479
- const expression = '${join("-", var.tags.app, var.tags.env, var.tags.other)}';
480
- const scope = getScope({ variables: ["tags"] });
481
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
482
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.join("-", Token.asList(Fn.concat([Fn.lookupNested(tags.value, ["app"]), Fn.lookupNested(tags.value, ["env"]), Fn.lookupNested(tags.value, ["other"])]))))"`);
483
- });
484
- test("doesn't wrap any extra templates", async () => {
485
- const expression = `"app-\${terraform.workspace}"`;
486
- const scope = getScope();
487
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
488
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""app-\${terraform.workspace}""`);
489
- });
490
- test("converts a for expression", async () => {
491
- const expression = `[for record in aws_route53_record.example : record.fqdn]`;
492
- const scope = getScope();
493
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
494
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for record in \${" + example.fqn + "} : record.fqdn]}""`);
495
- });
496
- test("converts a data source", async () => {
497
- const expression = `"\${data.aws_route53_zone.example.zone_id}"`;
498
- const scope = getScope();
499
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
500
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(example.zoneId)"`);
501
- });
502
- test("convert an each expression", async () => {
503
- const expression = `"\${each.value.name}"`;
504
- const scope = getScope({ forEachIteratorName: "myIterator" });
505
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
506
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(myIterator.value, ["name"]))"`);
507
- });
508
- test("converts a property of a function containing a resource", async () => {
509
- const expression = `"\${element(aws_s3_bucket.examplebucket, 0).id}"`;
510
- const scope = getScope();
511
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
512
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(Fn.element(examplebucket, 0), ["id"]))"`);
513
- });
514
- test("convert a function with references with splats", async () => {
515
- const expression = `"\${concat(var.private_subnets.*.id, var.public_subnets.*.id)}"`;
516
- const scope = getScope({
517
- variables: ["private_subnets", "public_subnets"],
518
- });
519
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
520
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.concat([Fn.lookupNested(privateSubnets.value, ["*", "id"]), Fn.lookupNested(publicSubnets.value, ["*", "id"])]))"`);
521
- });
522
- test("convert a iterator variable", async () => {
523
- const expression = `"\${each.key}"`;
524
- const scope = getScope({
525
- variables: ["private_subnets", "public_subnets"],
526
- forEachIteratorName: "myIterator",
527
- });
528
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
529
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(myIterator.key)"`);
530
- });
531
- test("convert a self reference", async () => {
532
- const expression = `"\${self.subnet.id}"`;
533
- const scope = getScope({
534
- variables: ["private_subnets", "public_subnets"],
535
- forEachIteratorName: "myIterator",
536
- });
537
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
538
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(TerraformSelf.getAny("subnet.id"))"`);
539
- });
540
- test("convert heredocs", async () => {
541
- const expression = `<<EOF
542
- [{
543
- "Condition": {
544
- "KeyPrefixEquals": "docs/"
545
- },
546
- "Redirect": {
547
- "ReplaceKeyPrefixWith": "documents/"
548
- }
549
- }]
550
- EOF
551
- `;
552
- const scope = getScope();
553
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
554
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""[{\\n \\"Condition\\": {\\n \\"KeyPrefixEquals\\": \\"docs/\\"\\n },\\n \\"Redirect\\": {\\n \\"ReplaceKeyPrefixWith\\": \\"documents/\\"\\n }\\n}]\\n""`);
555
- });
556
- test("convert heredocs without a trailing newline", async () => {
557
- const expression = `<<EOF
558
- hello world
559
- EOF`;
560
- const scope = getScope();
561
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
562
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello world\\n""`);
563
- });
564
- test("convert indented heredocs", async () => {
565
- const expression = `<<-EOF
566
- hello world
567
- EOF`;
568
- const scope = getScope();
569
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
570
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello world\\n""`);
571
- });
572
- test("convert override expressions", async () => {
573
- const expression = '"${required_resource_access.value["resource_access"]}"';
574
- const scope = getScope({
575
- withinOverrideExpression: true,
576
- scopedVariables: {
577
- required_resource_access: "dynamic-block",
578
- },
579
- });
580
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
581
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${required_resource_access.value[\\"resource_access\\"]}""`);
582
- });
583
- test("convert using operations while containing substring", async () => {
584
- const expression =
585
- // prettier-ignore
586
- '"${length(var.image_id) > 4 && substr(var.image_id, 0, 4) == \"ami-\"}"';
587
- const scope = getScope({});
588
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
589
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.and(Op.gt(Fn.lengthOf(imageId.value), 4), Op.eq(Fn.substr(imageId.stringValue, 0, 4), "ami-")))"`);
590
- });
591
- test("convert a data source with numeric access", async () => {
592
- const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.names[0]}"`;
593
- const scope = getScope({
594
- provider: awsProviderSchema,
595
- data: ["aws_subnet_ids"],
596
- });
597
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
598
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(changemeAzListEbsSnapshot.names, ["0"]))"`);
599
- });
600
- test("convert a reference to a map access", async () => {
601
- const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.testing_map.foo}"`;
602
- const scope = getScope({
603
- provider: awsProviderSchema,
604
- data: ["aws_subnet_ids"],
605
- });
606
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
607
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(changemeAzListEbsSnapshot, ["testing_map", "foo"]))"`);
608
- });
609
- test("convert attribute up to a map and not within attribute reference", async () => {
610
- const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.testing_map}"`;
611
- const scope = getScope({
612
- provider: awsProviderSchema,
613
- });
614
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => ["map", "string"]);
615
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asStringMap(changemeAzListEbsSnapshot.testingMap)"`);
616
- });
617
- test("don't convert external unknown fields", async () => {
618
- const expression = `"\${data.external.changeme_external_thumbprint_data.result.thumbprint}"`;
619
- const scope = getScope({
620
- provider: externalProviderSchema,
621
- data: ["aws_subnet_ids"],
622
- });
623
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => ["map", "string"]);
624
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asStringMap(Fn.lookupNested(changemeExternalThumbprintData, ["result", "thumbprint"]))"`);
625
- });
626
- test("convert resource reference with map attribute", async () => {
627
- const expression = `"\${aws_s3_bucket.examplebucket.foo.bar}"`;
628
- const scope = getScope({
629
- provider: awsProviderSchema,
630
- resources: ["aws_s3_bucket"],
631
- });
632
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "string");
633
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket, ["foo", "bar"]))"`);
634
- });
635
- test("convert complex variable reference in template", async () => {
636
- const expression = `"\${var.default_tags.project}-client-tg"`;
637
- const scope = getScope({
638
- provider: awsProviderSchema,
639
- resources: ["aws_s3_bucket"],
640
- variables: ["default_tags"],
641
- });
642
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "string");
643
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(defaultTags.value, ["project"])) + "-client-tg""`);
644
- });
645
- test("convert boolean values", async () => {
646
- const expression = `"\${false}"`;
647
- const scope = getScope({
648
- provider: awsProviderSchema,
649
- });
650
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "bool");
651
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"false"`);
652
- });
653
- test("convert a data source with count", async () => {
654
- const expression = `"\${data.aws_availability_zones.available.names[count.index]}"`;
655
- const scope = getScope({
656
- provider: awsProviderSchema,
657
- data: ["aws_availability_zones"],
658
- });
659
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
660
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(available.names, ["\${count.index}"]))"`);
661
- });
662
- test("accept escaped quotes within string", async () => {
663
- const expression = `"\${jsonencode({
664
- "Statement" = [{
665
- "Action" = "s3:*",
666
- "Effect" = "Allow",
667
- }],
668
- })}"`;
669
- const scope = getScope();
670
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
671
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`
672
- "Token.asString(Fn.jsonencode({
673
- "Statement": [{
674
- "Action": "s3:*",
675
- "Effect": "Allow"
676
- }]
677
- }))"
678
- `);
679
- });
680
- test("support variadic parameters in any position", async () => {
681
- const expression = `"\${cidrsubnets("fd00:fd12:3456:7890::/56", 16, 16, 16, 32)}"`;
682
- const scope = getScope();
683
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
684
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.cidrsubnets("fd00:fd12:3456:7890::/56", [16, 16, 16, 32]))"`);
685
- });
686
- test("converts template expression with escaped ${} expression", async () => {
687
- const expression = '["$${path:name.givenName}"]'; // from aws_ssoadmin_instance_access_control_attributes example
688
- const scope = getScope();
689
- const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
690
- expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"["$\${path:name.givenName}"]"`);
691
- });
692
- });
693
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc2lvblRvVHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4cHJlc3Npb25Ub1RzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUFFSCxnREFBZ0U7QUFHaEUsK0NBQWtEO0FBRWxELE1BQU0saUJBQWlCLEdBQUc7SUFDeEIsY0FBYyxFQUFFLEtBQUs7SUFDckIsZ0JBQWdCLEVBQUU7UUFDaEIscUNBQXFDLEVBQUU7WUFDckMsUUFBUSxFQUFFLEVBQUU7WUFDWixnQkFBZ0IsRUFBRTtnQkFDaEIsYUFBYSxFQUFFO29CQUNiLEtBQUssRUFBRTt3QkFDTCxVQUFVLEVBQUU7NEJBQ1YsR0FBRyxFQUFFO2dDQUNILElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUM7Z0NBQ3ZCLGdCQUFnQixFQUFFLE9BQU87NkJBQzFCO3lCQUNGO3FCQUNGO2lCQUNGO2FBQ0Y7WUFDRCxtQkFBbUIsRUFBRTtnQkFDbkIsc0JBQXNCLEVBQUU7b0JBQ3RCLE9BQU8sRUFBRSxDQUFDO29CQUNWLEtBQUssRUFBRTt3QkFDTCxVQUFVLEVBQUU7NEJBQ1Ysc0JBQXNCLEVBQUU7Z0NBQ3RCLElBQUksRUFBRSxNQUFNO2dDQUNaLGdCQUFnQixFQUFFLE9BQU87Z0NBQ3pCLFFBQVEsRUFBRSxJQUFJOzZCQUNmOzRCQUNELGFBQWEsRUFBRTtnQ0FDYixJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDO2dDQUN2QixnQkFBZ0IsRUFBRSxPQUFPO2dDQUN6QixRQUFRLEVBQUUsSUFBSTs2QkFDZjs0QkFDRCxnQkFBZ0IsRUFBRTtnQ0FDaEIsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQztnQ0FDdkIsZ0JBQWdCLEVBQUUsT0FBTztnQ0FDekIsUUFBUSxFQUFFLElBQUk7NkJBQ2Y7NEJBQ0QsV0FBVyxFQUFFO2dDQUNYLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUM7Z0NB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ICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1QTC0yLjBcbiAqL1xuXG5pbXBvcnQgeyBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMgfSBmcm9tIFwiLi4vZXhwcmVzc2lvbnNcIjtcbmltcG9ydCB7IFJlc291cmNlU2NvcGUgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IEF0dHJpYnV0ZVR5cGUgfSBmcm9tIFwiQGNka3RuL2NvbW1vbnNcIjtcbmltcG9ydCB7IGFzdFRvQ29kZSBhcyBjb2RlIH0gZnJvbSBcIi4vdGVzdEhlbHBlcnNcIjtcblxuY29uc3QgYXdzUHJvdmlkZXJTY2hlbWEgPSB7XG4gIGZvcm1hdF92ZXJzaW9uOiBcIjEuMFwiLFxuICBwcm92aWRlcl9zY2hlbWFzOiB7XG4gICAgXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8vaGFzaGljb3JwL2F3c1wiOiB7XG4gICAgICBwcm92aWRlcjoge30sXG4gICAgICByZXNvdXJjZV9zY2hlbWFzOiB7XG4gICAgICAgIGF3c19zM19idWNrZXQ6IHtcbiAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGRhdGFfc291cmNlX3NjaGVtYXM6IHtcbiAgICAgICAgYXdzX2F2YWlsYWJpbGl0eV96b25lczoge1xuICAgICAgICAgIHZlcnNpb246IDAsXG4gICAgICAgICAgYmxvY2s6IHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgYWxsX2F2YWlsYWJpbGl0eV96b25lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiYm9vbFwiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZXhjbHVkZV9uYW1lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGV4Y2x1ZGVfem9uZV9pZHM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJzZXRcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBncm91cF9uYW1lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGlkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG5hbWVzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHN0YXRlOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHpvbmVfaWRzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRlc3RpbmdfbWFwOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBibG9ja190eXBlczoge1xuICAgICAgICAgICAgICBmaWx0ZXI6IHtcbiAgICAgICAgICAgICAgICBuZXN0aW5nX21vZGU6IFwic2V0XCIsXG4gICAgICAgICAgICAgICAgYmxvY2s6IHtcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZToge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBbXCJzZXRcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aW1lb3V0czoge1xuICAgICAgICAgICAgICAgIG5lc3RpbmdfbW9kZTogXCJzaW5nbGVcIixcbiAgICAgICAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgICAgICByZWFkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59O1xuXG5jb25zdCBleHRlcm5hbFByb3ZpZGVyU2NoZW1hID0ge1xuICBmb3JtYXRfdmVyc2lvbjogXCIxLjBcIixcbiAgcHJvdmlkZXJfc2NoZW1hczoge1xuICAgIFwicmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9leHRlcm5hbFwiOiB7XG4gICAgICBwcm92aWRlcjoge30sXG4gICAgICByZXNvdXJjZV9zY2hlbWFzOiB7fSxcbiAgICAgIGRhdGFfc291cmNlX3NjaGVtYXM6IHtcbiAgICAgICAgZXh0ZXJuYWw6IHtcbiAgICAgICAgICB2ZXJzaW9uOiAwLFxuICAgICAgICAgIGJsb2NrOiB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgIGlkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiVGhlIGlkIG9mIHRoZSBkYXRhIHNvdXJjZS4gVGhpcyB3aWxsIGFsd2F5cyBiZSBzZXQgdG8gYC1gXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIGNvbXB1dGVkOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBwcm9ncmFtOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiQSBsaXN0IG9mIHN0cmluZ3MsIHdob3NlIGZpcnN0IGVsZW1lbnQgaXMgdGhlIHByb2dyYW0gdG8gcnVuIGFuZCB3aG9zZSBzdWJzZXF1ZW50IGVsZW1lbnRzIGFyZSBvcHRpb25hbCBjb21tYW5kIGxpbmUgYXJndW1lbnRzIHRvIHRoZSBwcm9ncmFtLiBUZXJyYWZvcm0gZG9lcyBub3QgZXhlY3V0ZSB0aGUgcHJvZ3JhbSB0aHJvdWdoIGEgc2hlbGwsIHNvIGl0IGlzIG5vdCBuZWNlc3NhcnkgdG8gZXNjYXBlIHNoZWxsIG1ldGFjaGFyYWN0ZXJzIG5vciBhZGQgcXVvdGVzIGFyb3VuZCBhcmd1bWVudHMgY29udGFpbmluZyBzcGFjZXMuXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBxdWVyeToge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcIm1hcFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiQSBtYXAgb2Ygc3RyaW5nIHZhbHVlcyB0byBwYXNzIHRvIHRoZSBleHRlcm5hbCBwcm9ncmFtIGFzIHRoZSBxdWVyeSBhcmd1bWVudHMuIElmIG5vdCBzdXBwbGllZCwgdGhlIHByb2dyYW0gd2lsbCByZWNlaXZlIGFuIGVtcHR5IG9iamVjdCBhcyBpdHMgaW5wdXQuXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICByZXN1bHQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgICBcIkEgbWFwIG9mIHN0cmluZyB2YWx1ZXMgcmV0dXJuZWQgZnJvbSB0aGUgZXh0ZXJuYWwgcHJvZ3JhbS5cIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHdvcmtpbmdfZGlyOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiV29ya2luZyBkaXJlY3Rvcnkgb2YgdGhlIHByb2dyYW0uIElmIG5vdCBzdXBwbGllZCwgdGhlIHByb2dyYW0gd2lsbCBydW4gaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5LlwiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgJ1RoZSBgZXh0ZXJuYWxgIGRhdGEgc291cmNlIGFsbG93cyBhbiBleHRlcm5hbCBwcm9ncmFtIGltcGxlbWVudGluZyBhIHNwZWNpZmljIHByb3RvY29sIChkZWZpbmVkIGJlbG93KSB0byBhY3QgYXMgYSBkYXRhIHNvdXJjZSwgZXhwb3NpbmcgYXJiaXRyYXJ5IGRhdGEgZm9yIHVzZSBlbHNld2hlcmUgaW4gdGhlIFRlcnJhZm9ybSBjb25maWd1cmF0aW9uLlxcblxcbioqV2FybmluZyoqIFRoaXMgbWVjaGFuaXNtIGlzIHByb3ZpZGVkIGFzIGFuIFwiZXNjYXBlIGhhdGNoXCIgZm9yIGV4Y2VwdGlvbmFsIHNpdHVhdGlvbnMgd2hlcmUgYSBmaXJzdC1jbGFzcyBUZXJyYWZvcm0gcHJvdmlkZXIgaXMgbm90IG1vcmUgYXBwcm9wcmlhdGUuIEl0cyBjYXBhYmlsaXRpZXMgYXJlIGxpbWl0ZWQgaW4gY29tcGFyaXNvbiB0byBhIHRydWUgZGF0YSBzb3VyY2UsIGFuZCBpbXBsZW1lbnRpbmcgYSBkYXRhIHNvdXJjZSB2aWEgYW4gZXh0ZXJuYWwgcHJvZ3JhbSBpcyBsaWtlbHkgdG8gaHVydCB0aGUgcG9ydGFiaWxpdHkgb2YgeW91ciBUZXJyYWZvcm0gY29uZmlndXJhdGlvbiBieSBjcmVhdGluZyBkZXBlbmRlbmNpZXMgb24gZXh0ZXJuYWwgcHJvZ3JhbXMgYW5kIGxpYnJhcmllcyB0aGF0IG1heSBub3QgYmUgYXZhaWxhYmxlIChvciBtYXkgbmVlZCB0byBiZSB1c2VkIGRpZmZlcmVudGx5KSBvbiBkaWZmZXJlbnQgb3BlcmF0aW5nIHN5c3RlbXMuXFxuXFxuKipXYXJuaW5nKiogVGVycmFmb3JtIEVudGVycHJpc2UgZG9lcyBub3QgZ3VhcmFudGVlIGF2YWlsYWJpbGl0eSBvZiBhbnkgcGFydGljdWxhciBsYW5ndWFnZSBydW50aW1lcyBvciBleHRlcm5hbCBwcm9ncmFtcyBiZXlvbmQgc3RhbmRhcmQgc2hlbGwgdXRpbGl0aWVzLCBzbyBpdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gdXNlIHRoaXMgZGF0YSBzb3VyY2Ugd2l0aGluIGNvbmZpZ3VyYXRpb25zIHRoYXQgYXJlIGFwcGxpZWQgd2l0aGluIFRlcnJhZm9ybSBFbnRlcnByaXNlLicsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn07XG5cbnR5cGUgR2V0U2NvcGVQYXJhbXMgPSB7XG4gIHByb3ZpZGVyPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgcmVzb3VyY2VzPzogc3RyaW5nW107XG4gIGRhdGE/OiBzdHJpbmdbXTtcbiAgdmFyaWFibGVzPzogc3RyaW5nW107XG4gIGxvY2Fscz86IHN0cmluZ1tdO1xuICBmb3JFYWNoSXRlcmF0b3JOYW1lPzogc3RyaW5nO1xuICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24/OiBib29sZWFuO1xuICBzY29wZWRWYXJpYWJsZXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxuZnVuY3Rpb24gZ2V0U2NvcGUoe1xuICBwcm92aWRlcixcbiAgcmVzb3VyY2VzLFxuICBkYXRhLFxuICB2YXJpYWJsZXMsXG4gIGxvY2FscyxcbiAgZm9yRWFjaEl0ZXJhdG9yTmFtZSxcbiAgc2NvcGVkVmFyaWFibGVzLFxuICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24gPSBmYWxzZSxcbn06IEdldFNjb3BlUGFyYW1zID0ge30pOiBSZXNvdXJjZVNjb3BlIHtcbiAgY29uc3Qgc2NvcGVWYXJpYWJsZXM6IFJlc291cmNlU2NvcGVbXCJ2YXJpYWJsZXNcIl0gPSB7fTtcblxuICByZXNvdXJjZXM/LmZvckVhY2goKHZhck5hbWUpID0+IHtcbiAgICBsZXQgW3Jlc291cmNlVHlwZSwgcmVzb3VyY2VOYW1lXSA9IHZhck5hbWUuc3BsaXQoXCIuXCIpO1xuICAgIGlmICghcmVzb3VyY2VOYW1lKSB7XG4gICAgICByZXNvdXJjZU5hbWUgPSB2YXJOYW1lO1xuICAgICAgcmVzb3VyY2VUeXBlID0gXCJhd3NfczNfYnVja2V0XCI7XG4gICAgfVxuXG4gICAgc2NvcGVWYXJpYWJsZXNbdmFyTmFtZV0gPSB7XG4gICAgICByZXNvdXJjZTogcmVzb3VyY2VUeXBlLFxuICAgICAgdmFyaWFibGVOYW1lOiByZXNvdXJjZU5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgZGF0YT8uZm9yRWFjaCgodmFyTmFtZSkgPT4ge1xuICAgIHNjb3BlVmFyaWFibGVzW3Zhck5hbWVdID0ge1xuICAgICAgcmVzb3VyY2U6IFwiZGF0YS5hd3NfczNfYnVja2V0XCIsXG4gICAgICB2YXJpYWJsZU5hbWU6IHZhck5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgdmFyaWFibGVzPy5mb3JFYWNoKCh2YXJOYW1lKSA9PiB7XG4gICAgc2NvcGVWYXJpYWJsZXNbdmFyTmFtZV0gPSB7XG4gICAgICByZXNvdXJjZTogXCJ2YXJcIixcbiAgICAgIHZhcmlhYmxlTmFtZTogdmFyTmFtZSxcbiAgICB9O1xuICB9KTtcblxuICBsb2NhbHM/LmZvckVhY2goKHZhck5hbWUpID0+IHtcbiAgICBzY29wZVZhcmlhYmxlc1t2YXJOYW1lXSA9IHtcbiAgICAgIHJlc291cmNlOiBcImxvY2FsXCIsXG4gICAgICB2YXJpYWJsZU5hbWU6IHZhck5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgY29uc3Qgc2NvcGUgPSB7XG4gICAgcHJvdmlkZXJTY2hlbWE6IHByb3ZpZGVyID8/IHt9LFxuICAgIHByb3ZpZGVyR2VuZXJhdG9yOiB7fSxcbiAgICBjb25zdHJ1Y3RzOiBuZXcgU2V0PHN0cmluZz4oKSxcbiAgICB2YXJpYWJsZXM6IHNjb3BlVmFyaWFibGVzLFxuICAgIGhhc1Rva2VuQmFzZWRUeXBlQ29lcmNpb246IHRydWUsXG4gICAgc2NvcGVkVmFyaWFibGVzOiBzY29wZWRWYXJpYWJsZXMgfHwge30sXG4gICAgZm9yRWFjaEl0ZXJhdG9yTmFtZSxcbiAgICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24sXG4gICAgbm9kZUlkczogW10sXG4gICAgaW1wb3J0YWJsZXM6IFtdLFxuICAgIHRvcExldmVsQ29uZmlnOiB7fSxcbiAgfTtcblxuICByZXR1cm4gc2NvcGU7XG59XG5cbmNvbnN0IGdldFR5cGUgPSAoKTogQXR0cmlidXRlVHlwZSA9PiBcInN0cmluZ1wiO1xuXG5kZXNjcmliZShcImV4cHJlc3Npb25Ub1RzXCIsICgpID0+IHtcbiAgdGVzdChcImNvbnZlcnRzIGEgc2ltcGxlIHN0cmluZyB0byBhIHN0cmluZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiaGVsbG9cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJcImhlbGxvXCJcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBzaW1wbGUgZXhwcmVzc2lvbiB3aXRoIGEgdGVtcGxhdGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7MjJ9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiVG9rZW4uYXNTdHJpbmcoMjIpXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgdmFyaWFibGUgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke3Zhci5mb299XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiZm9vLnN0cmluZ1ZhbHVlXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSB2YXJpYWJsZSByZWZlcmVuY2Ugd2l0aCBzbmFrZSBjYXNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke3Zhci5mb29fYmFyfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcImZvb19iYXJcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGZvb0Jhci52YWx1ZSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBmdW5jdGlvbiBjYWxsXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtyZXBsYWNlKFwiaGVsbG9cIiwgXCJsXCIsIFwid1wiKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ucmVwbGFjZShcImhlbGxvXCIsIFwibFwiLCBcIndcIikpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGZ1bmN0aW9uIGNhbGwgd2l0aCBhbiBleHByZXNzaW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtyZXBsYWNlKFwiaGVsbG8tXFwkezIyKzIyfVwiLCBcIjQ0XCIsIFwid29ybGRcIil9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLnJlcGxhY2UoXCJoZWxsby1cIiArIFRva2VuLmFzU3RyaW5nKE9wLmFkZCgyMiwgMjIpKSwgXCI0NFwiLCBcIndvcmxkXCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgc3RyaW5nIGNvbmNhdGVuYXRpb24gb2YgaXRlcmF0b3Iga2V5XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJyR7XCJkeW5hbWljLWluZ3Jlc3MtJHtpbmdyZXNzLmtleX1cIn0nO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgc2NvcGVkVmFyaWFibGVzOiB7XG4gICAgICAgIGluZ3Jlc3M6IFwiZHluYW1pY19pdGVyYXRvcjBcIixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiZHluYW1pYy1pbmdyZXNzLVxcJHtcIiArIFRva2VuLmFzU3RyaW5nKGR5bmFtaWNfaXRlcmF0b3IwLmtleSkgKyBcIn1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHZhcmlhYmxlIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7dmFyLmZvb19iYXJ9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJmb29fYmFyXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICAvLyBUT0RPOiBUaGlzIHNlZW1zIGJyb2tlblxuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGZvb0Jhci52YWx1ZSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSByZXNvdXJjZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJzaW1wbGUtXFwke2F3c19zM19idWNrZXQuZm9vLmlkfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwic2ltcGxlLVxcJHtcIiArIGZvby5pZCArIFwifVwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSByZXNvdXJjZSByZWZlcmVuY2Ugd2l0aCBuZXN0ZWQgcHJvcGVydGllc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcInNpbXBsZS1cXCR7YXdzX3MzX2J1Y2tldC5mb28ucHJvcC50ZXN0fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJzaW1wbGUtXFwke1wiICsgZm9vLnByb3AudGVzdCArIFwifVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgbG9jYWwgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwic2ltcGxlLVxcJHtsb2NhbC5mb299XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyBsb2NhbHM6IFtcImZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwic2ltcGxlLVxcJHtcIiArIGZvbyArIFwifVwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcInBsYWluIHJlc291cmNlIHJlZmVyZW5jZXMgaW4gYXJpdGhtZXRpY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgXCIke2F3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5jb3VudCArIGF3c19zM19idWNrZXQub3RoZXJidWNrZXQuY291bnQgfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIiwgXCJhd3NfczNfYnVja2V0Lm90aGVyYnVja2V0XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhPcC5hZGQoZXhhbXBsZWJ1Y2tldC5jb3VudCwgb3RoZXJidWNrZXQuY291bnQpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwidXNlIGZxbiBmb3Igc3BsYXQgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHthd3NfczNfYnVja2V0LmZvby4qLmlkfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5mb29cIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChmb28sIFtcIipcIiwgXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJ1c2UgZnFuIGlmIHByb3BlcnR5IGlzIHByZXNlbnQgb24gbnVtZXJpYyBhY2Nlc3MgdXNpbmcgZG90IG5vdGF0aW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQubmV0d29ya19pbnRlcmZhY2UuMC5hY2Nlc3NfY29uZmlnLjAuYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInVzZSBmcW4gaWYgcHJvcGVydHkgaXMgcHJlc2VudCBvbiBudW1lcmljIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0Lm5ldHdvcmtfaW50ZXJmYWNlWzBdLmFjY2Vzc19jb25maWdbMF0uYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInVzZSBubyBmcW4gaWYgcHJvcGVydHkgaXMgcHJlc2VudCBvbiBudW1lcmljIGFjY2VzcyB1c2luZyBbXVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0Lm5ldHdvcmtfaW50ZXJmYWNlWzBdLmFjY2Vzc19jb25maWdbMF0uYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImRldGVjdHMgc3BsYXQgcmVmZXJlbmNlIHdpdGhpbiBmdW5jdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHt0b3NldChhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuKil9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi50b3NldChGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiKlwiXSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBjb25kaXRpb25hbFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX2ttc19rZXkua2V5LmRlbGV0aW9uX3dpbmRvd19pbl9kYXlzID4gMyA/IGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5pZCA6IFtdfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19rbXNfa2V5LmtleVwiLCBcImV4YW1wbGVidWNrZXRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGNvbmRpdGlvbmFsKE9wLmd0KGtleS5kZWxldGlvbldpbmRvd0luRGF5cywgMyksIGV4YW1wbGVidWNrZXQuaWQsIFtdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZnVuY3Rpb24gd2l0aCByZWZlcmVuY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke2VsZW1lbnQoYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LCAwKS5pZH1cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChGbi5lbGVtZW50KGV4YW1wbGVidWNrZXQsIDApLCBbXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGZ1bmN0aW9uIHdpdGggc3BsYXQgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke2VsZW1lbnQoYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LiouaWQsIDApfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZWxlbWVudChGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiKlwiLCBcImlkXCJdKSwgMCkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGZvciBsb29wc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7eyBmb3IgbmFtZSwgdXNlciBpbiB2YXIudXNlcnMgOiB1c2VyLnJvbGUgPT4gbmFtZS4uLn19XCI7XG5cbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke3sgZm9yIG5hbWUsIHVzZXIgaW4gXFwke1wiICsgdXNlcnMudmFsdWUgKyBcIn0gOiB1c2VyLnJvbGUgPT4gbmFtZS4uLn19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImZvciBleHByZXNzaW9uc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwie2ZvciBzIGluIHZhci5saXN0IDogcyA9PiB1cHBlcihzKX1cIjtcblxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7eyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogcyA9PiB1cHBlcihzKX19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImZvciBsaXN0IGV4cHJlc3Npb24gXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCJbZm9yIHMgaW4gdmFyLmxpc3QgOiB1cHBlcihzKV1cIjtcblxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogdXBwZXIocyldfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJmb3IgbGlzdCB3aXRoIGNvbmRpdGlvbmFsXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1tmb3IgcyBpbiB2YXIubGlzdCA6IHVwcGVyKHMpIGlmIHMgIT0gXCJcIl0nO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogdXBwZXIocykgaWYgcyAhPSBcXFxcXCJcXFxcXCJdfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHByb3BlcnR5IGFjY2VzcyByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0WzBdLmlkfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQsIFtcIjBcIiwgXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHVuYXJ5IG9wZXJhdG9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7IXZhci5lbmFibGVkfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1wiZW5hYmxlZFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBcImJvb2xcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzQm9vbGVhbihPcC5ub3QoZW5hYmxlZC52YWx1ZSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGZ1bmN0aW9uIHdpdGggYXJyYXlzIGFuZCBjb21tZW50c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7Y29tcGFjdChbXG4gICAgICAgICAgICAjIFRoZSBleGFtcGxlIFwiYnVja2V0XCJcbiAgICAgICAgICAgIGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCxcbiAgICAgICAgXG4gICAgICAgICAgICAjIFRoZSBcIkxlYXJuXCIgc2luZ2xlIHBhZ2UgYXBwbGljYXRpb24uIFRoaXMgaXMgbm90IGNvbmZpZ3VyZWQgaW4gYWxsIGVudmlyb25tZW50cy5cbiAgICAgICAgICAgIHZhci5pbnB1dCxcbiAgICAgICAgICBdKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIl0sXG4gICAgICB2YXJpYWJsZXM6IFtcImlucHV0XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICAvLyBUT0RPOiBTZWUgaWYgd2UgaGF2ZSBhIHdheSB0byBwcmVzZXJ2ZSBjb21tZW50c1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmNvbXBhY3QoVG9rZW4uYXNMaXN0KFtleGFtcGxlYnVja2V0LCBpbnB1dC52YWx1ZV0pKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgcmVmZXJlbmNlcyBmb3Igc2FtZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke3Zhci5pbnB1dCA9PSBcInRlc3RcIiA/IFwiYXp1cmUtYWQtaW50XCIgOiBcImF6dXJlLWFkLVxcJHt2YXIuaW5wdXR9XCJ9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJpbnB1dFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoY29uZGl0aW9uYWwoT3AuZXEoaW5wdXQudmFsdWUsIFwidGVzdFwiKSwgXCJhenVyZS1hZC1pbnRcIiwgXCJhenVyZS1hZC1cXCR7XCIgKyBpbnB1dC52YWx1ZSArIFwifVwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcIm5lc3RlZCB2YXJpYWJsZSBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke2VsZW1lbnQodmFyLnRlc3QyW1widmFsMVwiXSwgMCl9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ0ZXN0MlwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZWxlbWVudChGbi5sb29rdXBOZXN0ZWQodGVzdDIudmFsdWUsIFtcIlxcXFxcInZhbDFcXFxcXCJcIl0pLCAwKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbXBsaWNhdGVkIG5lc3RlZCBsb2NhbCB2YWx1ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHtmbGF0dGVuKHZhci52bmV0c1sqXS5zdWJuZXRzWypdLm5hbWUpfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInZuZXRzXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5mbGF0dGVuKEZuLmxvb2t1cE5lc3RlZCh2bmV0cy52YWx1ZSwgW1wiKlwiLCBcInN1Ym5ldHNcIiwgXCIqXCIsIFwibmFtZVwiXSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICAvLyBUT0lNUFJPVkU6IEkgZG9uJ3QgdGhpbmsgd2UgY2FuIGhhbmRsZSB0aGlzIGNhc2UgeWV0LCBzaW5jZSB0aGUgdmFyaWFibGVcbiAgLy8gbmVlZHMgdG8gYmUgd3JhcHBlZCBpbiBhbiBpdGVyYXRvci4gSSdtIGxlYXZpbmcgdGhpcyBpbiwgYnV0IGl0J3MgYnJva2VuXG4gIHRlc3QoXCJjb21wbGljYXRlZCBuZXN0ZWQgdmFyaWFibGUgYWNjZXNzIHdpdGggbWFwXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYHsgXG4gICAgZm9yIHZuZXQgaW4gdmFyLnZuZXRzWypdOlxuICAgICh2bmV0LnZuZXRfbmFtZSkgPT4gdm5ldC5zdWJuZXRzWypdLm5hbWVcbiAgfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widm5ldHNcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke3sgZm9yIHZuZXQgaW4gXFwke1wiICsgRm4ubG9va3VwTmVzdGVkKHZuZXRzLnZhbHVlLCBbXCIqXCJdKSArIFwifSA6ICh2bmV0LnZuZXRfbmFtZSkgPT4gdm5ldC5zdWJuZXRzWypdLm5hbWV9fVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb21wbGljYXRlZCBuZXN0ZWQgdmFyaWFibGUgYWNjZXNzIHdpdGggbGlzdFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7ZmxhdHRlbihbXG4gICAgZm9yIGssIHYgaW4gdmFyLnJvdXRlIDogW1xuICAgICAgZm9yIG4sIHMgaW4gdiA6IFtcbiAgICAgICAge1xuICAgICAgICAgIGtleSA9IGssXG4gICAgICAgICAgbmFtZSA9IG4sXG4gICAgICAgICAgc3ZjX3VybCA9IHNcbiAgICAgICAgfVxuICAgICAgXVxuICAgIF1cbiAgXSl9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJyb3V0ZVwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZmxhdHRlbihcIlxcJHtbIGZvciBrLCB2IGluIFxcJHtcIiArIHJvdXRlLnZhbHVlICsgXCJ9IDogW1xcXFxuICAgICAgZm9yIG4sIHMgaW4gdiA6IFtcXFxcbiAgICAgICAge1xcXFxuICAgICAgICAgIGtleSA9IGssXFxcXG4gICAgICAgICAgbmFtZSA9IG4sXFxcXG4gICAgICAgICAgc3ZjX3VybCA9IHNcXFxcbiAgICAgICAgfVxcXFxuICAgICAgXVxcXFxuICAgIF1dfVwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInNpbXBsZSBsb2NhbCB2YXJpYWJsZSBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7IWxvY2FsLmVuYWJsZWR9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IGxvY2FsczogW1wiZW5hYmxlZFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoT3Aubm90KGVuYWJsZWQpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwibXVsdGkgbG9jYWwgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgICdcIiR7bG9jYWwuc2VydmljZV9uYW1lfSwke2xvY2FsLm93bmVyfSwke2xvY2FsLmlzX2l0X2dyZWF0fSwke2xvY2FsLmhvd19tYW55fVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIGxvY2FsczogW1wic2VydmljZV9uYW1lXCIsIFwib3duZXJcIiwgXCJpc19pdF9ncmVhdFwiLCBcImhvd19tYW55XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtcIiArIHNlcnZpY2VOYW1lICsgXCJ9LFxcJHtcIiArIG93bmVyICsgXCJ9LFxcJHtcIiArIGlzSXRHcmVhdCArIFwifSxcXCR7XCIgKyBob3dNYW55ICsgXCJ9XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImJpbmFyeSBvcGVyYXRpb25zIHdpdGhpbiBsaXRlcmFscyBhbmQgdmFyaWFibGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHt2YXIudGVzdH0gKyAxXCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInRlc3RcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke1wiICsgdGVzdC52YWx1ZSArIFwifSArIDFcIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwibG9jYWwgdmFyaWFibGUgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHtsb2NhbC5lbmFibGVkfVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgbG9jYWxzOiBbXCJlbmFibGVkXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiZW5hYmxlZFwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyB0cmF2ZXJzYWxzIHRoYXQgY2Fubm90IGJlIHJlZmVyZW5jZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7c2VsZi5wYXRofVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoVGVycmFmb3JtU2VsZi5nZXRBbnkoXCJwYXRoXCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgam9pbiBmdW5jdGlvbiB3aXRoIHZhcmlhYmxlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9ICcke2pvaW4oXCItXCIsIFt2YXIudGFncy5hcHAsIHZhci50YWdzLmVudl0pfSc7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widGFnc1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uam9pbihcIi1cIiwgVG9rZW4uYXNMaXN0KFtGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiYXBwXCJdKSwgRm4ubG9va3VwTmVzdGVkKHRhZ3MudmFsdWUsIFtcImVudlwiXSldKSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBqb2luIGZ1bmN0aW9uIHdpdGggbWFueSBhcmd1bWVudHMgdmFyaWFibGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgICcke2pvaW4oXCItXCIsIHZhci50YWdzLmFwcCwgdmFyLnRhZ3MuZW52LCB2YXIudGFncy5vdGhlcil9JztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ0YWdzXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5qb2luKFwiLVwiLCBUb2tlbi5hc0xpc3QoRm4uY29uY2F0KFtGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiYXBwXCJdKSwgRm4ubG9va3VwTmVzdGVkKHRhZ3MudmFsdWUsIFtcImVudlwiXSksIEZuLmxvb2t1cE5lc3RlZCh0YWdzLnZhbHVlLCBbXCJvdGhlclwiXSldKSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZG9lc24ndCB3cmFwIGFueSBleHRyYSB0ZW1wbGF0ZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJhcHAtXFwke3RlcnJhZm9ybS53b3Jrc3BhY2V9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJhcHAtXFwke3RlcnJhZm9ybS53b3Jrc3BhY2V9XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZm9yIGV4cHJlc3Npb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgW2ZvciByZWNvcmQgaW4gYXdzX3JvdXRlNTNfcmVjb3JkLmV4YW1wbGUgOiByZWNvcmQuZnFkbl1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcmVjb3JkIGluIFxcJHtcIiArIGV4YW1wbGUuZnFuICsgXCJ9IDogcmVjb3JkLmZxZG5dfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGRhdGEgc291cmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2RhdGEuYXdzX3JvdXRlNTNfem9uZS5leGFtcGxlLnpvbmVfaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoZXhhbXBsZS56b25lSWQpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGFuIGVhY2ggZXhwcmVzc2lvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtlYWNoLnZhbHVlLm5hbWV9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyBmb3JFYWNoSXRlcmF0b3JOYW1lOiBcIm15SXRlcmF0b3JcIiB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKG15SXRlcmF0b3IudmFsdWUsIFtcIm5hbWVcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBwcm9wZXJ0eSBvZiBhIGZ1bmN0aW9uIGNvbnRhaW5pbmcgYSByZXNvdXJjZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtlbGVtZW50KGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCwgMCkuaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKEZuLmVsZW1lbnQoZXhhbXBsZWJ1Y2tldCwgMCksIFtcImlkXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBmdW5jdGlvbiB3aXRoIHJlZmVyZW5jZXMgd2l0aCBzcGxhdHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7Y29uY2F0KHZhci5wcml2YXRlX3N1Ym5ldHMuKi5pZCwgdmFyLnB1YmxpY19zdWJuZXRzLiouaWQpfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHZhcmlhYmxlczogW1wicHJpdmF0ZV9zdWJuZXRzXCIsIFwicHVibGljX3N1Ym5ldHNcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmNvbmNhdChbRm4ubG9va3VwTmVzdGVkKHByaXZhdGVTdWJuZXRzLnZhbHVlLCBbXCIqXCIsIFwiaWRcIl0pLCBGbi5sb29rdXBOZXN0ZWQocHVibGljU3VibmV0cy52YWx1ZSwgW1wiKlwiLCBcImlkXCJdKV0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGl0ZXJhdG9yIHZhcmlhYmxlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2VhY2gua2V5fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHZhcmlhYmxlczogW1wicHJpdmF0ZV9zdWJuZXRzXCIsIFwicHVibGljX3N1Ym5ldHNcIl0sXG4gICAgICBmb3JFYWNoSXRlcmF0b3JOYW1lOiBcIm15SXRlcmF0b3JcIixcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcobXlJdGVyYXRvci5rZXkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgc2VsZiByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7c2VsZi5zdWJuZXQuaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgdmFyaWFibGVzOiBbXCJwcml2YXRlX3N1Ym5ldHNcIiwgXCJwdWJsaWNfc3VibmV0c1wiXSxcbiAgICAgIGZvckVhY2hJdGVyYXRvck5hbWU6IFwibXlJdGVyYXRvclwiLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhUZXJyYWZvcm1TZWxmLmdldEFueShcInN1Ym5ldC5pZFwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaGVyZWRvY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDxFT0Zcblt7XG4gICAgXCJDb25kaXRpb25cIjoge1xuICAgICAgICBcIktleVByZWZpeEVxdWFsc1wiOiBcImRvY3MvXCJcbiAgICB9LFxuICAgIFwiUmVkaXJlY3RcIjoge1xuICAgICAgICBcIlJlcGxhY2VLZXlQcmVmaXhXaXRoXCI6IFwiZG9jdW1lbnRzL1wiXG4gICAgfVxufV1cbkVPRlxuYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiW3tcXFxcbiAgICBcXFxcXCJDb25kaXRpb25cXFxcXCI6IHtcXFxcbiAgICAgICAgXFxcXFwiS2V5UHJlZml4RXF1YWxzXFxcXFwiOiBcXFxcXCJkb2NzL1xcXFxcIlxcXFxuICAgIH0sXFxcXG4gICAgXFxcXFwiUmVkaXJlY3RcXFxcXCI6IHtcXFxcbiAgICAgICAgXFxcXFwiUmVwbGFjZUtleVByZWZpeFdpdGhcXFxcXCI6IFxcXFxcImRvY3VtZW50cy9cXFxcXCJcXFxcbiAgICB9XFxcXG59XVxcXFxuXCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaGVyZWRvY3Mgd2l0aG91dCBhIHRyYWlsaW5nIG5ld2xpbmVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDxFT0ZcbmhlbGxvIHdvcmxkXG5FT0ZgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwiaGVsbG8gd29ybGRcXFxcblwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaW5kZW50ZWQgaGVyZWRvY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDwtRU9GXG4gICAgICAgICAgICAgIGhlbGxvIHdvcmxkXG4gICAgICAgICAgRU9GYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJcImhlbGxvIHdvcmxkXFxcXG5cIlwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IG92ZXJyaWRlIGV4cHJlc3Npb25zXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHtyZXF1aXJlZF9yZXNvdXJjZV9hY2Nlc3MudmFsdWVbXCJyZXNvdXJjZV9hY2Nlc3NcIl19XCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgd2l0aGluT3ZlcnJpZGVFeHByZXNzaW9uOiB0cnVlLFxuICAgICAgc2NvcGVkVmFyaWFibGVzOiB7XG4gICAgICAgIHJlcXVpcmVkX3Jlc291cmNlX2FjY2VzczogXCJkeW5hbWljLWJsb2NrXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtyZXF1aXJlZF9yZXNvdXJjZV9hY2Nlc3MudmFsdWVbXFxcXFwicmVzb3VyY2VfYWNjZXNzXFxcXFwiXX1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCB1c2luZyBvcGVyYXRpb25zIHdoaWxlIGNvbnRhaW5pbmcgc3Vic3RyaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgJ1wiJHtsZW5ndGgodmFyLmltYWdlX2lkKSA+IDQgJiYgc3Vic3RyKHZhci5pbWFnZV9pZCwgMCwgNCkgPT0gXFxcImFtaS1cXFwifVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHt9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoT3AuYW5kKE9wLmd0KEZuLmxlbmd0aE9mKGltYWdlSWQudmFsdWUpLCA0KSwgT3AuZXEoRm4uc3Vic3RyKGltYWdlSWQuc3RyaW5nVmFsdWUsIDAsIDQpLCBcImFtaS1cIikpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGRhdGEgc291cmNlIHdpdGggbnVtZXJpYyBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3NfYXZhaWxhYmlsaXR5X3pvbmVzLmNoYW5nZW1lX2F6X2xpc3RfZWJzX3NuYXBzaG90Lm5hbWVzWzBdfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIGRhdGE6IFtcImF3c19zdWJuZXRfaWRzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVBekxpc3RFYnNTbmFwc2hvdC5uYW1lcywgW1wiMFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgcmVmZXJlbmNlIHRvIGEgbWFwIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuY2hhbmdlbWVfYXpfbGlzdF9lYnNfc25hcHNob3QudGVzdGluZ19tYXAuZm9vfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIGRhdGE6IFtcImF3c19zdWJuZXRfaWRzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVBekxpc3RFYnNTbmFwc2hvdCwgW1widGVzdGluZ19tYXBcIiwgXCJmb29cIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhdHRyaWJ1dGUgdXAgdG8gYSBtYXAgYW5kIG5vdCB3aXRoaW4gYXR0cmlidXRlIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuY2hhbmdlbWVfYXpfbGlzdF9lYnNfc25hcHNob3QudGVzdGluZ19tYXB9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcHJvdmlkZXI6IGF3c1Byb3ZpZGVyU2NoZW1hLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICk7XG5cbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZ01hcChjaGFuZ2VtZUF6TGlzdEVic1NuYXBzaG90LnRlc3RpbmdNYXApXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJkb24ndCBjb252ZXJ0IGV4dGVybmFsIHVua25vd24gZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2RhdGEuZXh0ZXJuYWwuY2hhbmdlbWVfZXh0ZXJuYWxfdGh1bWJwcmludF9kYXRhLnJlc3VsdC50aHVtYnByaW50fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBleHRlcm5hbFByb3ZpZGVyU2NoZW1hLFxuICAgICAgZGF0YTogW1wiYXdzX3N1Ym5ldF9pZHNcIl0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZ01hcChGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVFeHRlcm5hbFRodW1icHJpbnREYXRhLCBbXCJyZXN1bHRcIiwgXCJ0aHVtYnByaW50XCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgcmVzb3VyY2UgcmVmZXJlbmNlIHdpdGggbWFwIGF0dHJpYnV0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuZm9vLmJhcn1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXRcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gXCJzdHJpbmdcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChleGFtcGxlYnVja2V0LCBbXCJmb29cIiwgXCJiYXJcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBjb21wbGV4IHZhcmlhYmxlIHJlZmVyZW5jZSBpbiB0ZW1wbGF0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHt2YXIuZGVmYXVsdF90YWdzLnByb2plY3R9LWNsaWVudC10Z1wiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldFwiXSxcbiAgICAgIHZhcmlhYmxlczogW1wiZGVmYXVsdF90YWdzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgICgpID0+IFwic3RyaW5nXCIsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZGVmYXVsdFRhZ3MudmFsdWUsIFtcInByb2plY3RcIl0pKSArIFwiLWNsaWVudC10Z1wiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGJvb2xlYW4gdmFsdWVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2ZhbHNlfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBcImJvb2xcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJmYWxzZVwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgZGF0YSBzb3VyY2Ugd2l0aCBjb3VudFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuYXZhaWxhYmxlLm5hbWVzW2NvdW50LmluZGV4XX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICBkYXRhOiBbXCJhd3NfYXZhaWxhYmlsaXR5X3pvbmVzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoYXZhaWxhYmxlLm5hbWVzLCBbXCJcXCR7Y291bnQuaW5kZXh9XCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImFjY2VwdCBlc2NhcGVkIHF1b3RlcyB3aXRoaW4gc3RyaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2pzb25lbmNvZGUoe1xuICAgICAgICAgIFwiU3RhdGVtZW50XCIgPSBbe1xuICAgICAgICAgICAgXCJBY3Rpb25cIiA9IFwiczM6KlwiLFxuICAgICAgICAgICAgXCJFZmZlY3RcIiA9IFwiQWxsb3dcIixcbiAgICAgICAgICB9XSxcbiAgICAgICAgfSl9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcbiAgICAgIFwiVG9rZW4uYXNTdHJpbmcoRm4uanNvbmVuY29kZSh7XG4gICAgICAgIFwiU3RhdGVtZW50XCI6IFt7XG4gICAgICAgICAgXCJBY3Rpb25cIjogXCJzMzoqXCIsXG4gICAgICAgICAgXCJFZmZlY3RcIjogXCJBbGxvd1wiXG4gICAgICAgIH1dXG4gICAgICB9KSlcIlxuICAgIGApO1xuICB9KTtcblxuICB0ZXN0KFwic3VwcG9ydCB2YXJpYWRpYyBwYXJhbWV0ZXJzIGluIGFueSBwb3NpdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtjaWRyc3VibmV0cyhcImZkMDA6ZmQxMjozNDU2Ojc4OTA6Oi81NlwiLCAxNiwgMTYsIDE2LCAzMil9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG5cbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5jaWRyc3VibmV0cyhcImZkMDA6ZmQxMjozNDU2Ojc4OTA6Oi81NlwiLCBbMTYsIDE2LCAxNiwgMzJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIHRlbXBsYXRlIGV4cHJlc3Npb24gd2l0aCBlc2NhcGVkICR7fSBleHByZXNzaW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1tcIiQke3BhdGg6bmFtZS5naXZlbk5hbWV9XCJdJzsgLy8gZnJvbSBhd3Nfc3NvYWRtaW5faW5zdGFuY2VfYWNjZXNzX2NvbnRyb2xfYXR0cmlidXRlcyBleGFtcGxlXG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcblxuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIltcIiRcXCR7cGF0aDpuYW1lLmdpdmVuTmFtZX1cIl1cImAsXG4gICAgKTtcbiAgfSk7XG59KTtcbiJdfQ==