@cdktn/hcl2cdk 0.21.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.
- package/README.md +95 -0
- package/ambient.d.ts +14 -0
- package/jest.config.js +16 -0
- package/lib/__tests__/coerceType.test.d.ts +2 -0
- package/lib/__tests__/coerceType.test.js +165 -0
- package/lib/__tests__/expressionToTs.test.d.ts +6 -0
- package/lib/__tests__/expressionToTs.test.js +693 -0
- package/lib/__tests__/expressions.test.d.ts +4 -0
- package/lib/__tests__/expressions.test.js +415 -0
- package/lib/__tests__/findExpressionType.test.d.ts +6 -0
- package/lib/__tests__/findExpressionType.test.js +105 -0
- package/lib/__tests__/functions.test.d.ts +6 -0
- package/lib/__tests__/functions.test.js +605 -0
- package/lib/__tests__/generation.test.d.ts +6 -0
- package/lib/__tests__/generation.test.js +45 -0
- package/lib/__tests__/jsii-rosetta-workarounds.test.d.ts +2 -0
- package/lib/__tests__/jsii-rosetta-workarounds.test.js +86 -0
- package/lib/__tests__/partialCode.test.d.ts +6 -0
- package/lib/__tests__/partialCode.test.js +390 -0
- package/lib/__tests__/terraformSchema.test.d.ts +6 -0
- package/lib/__tests__/terraformSchema.test.js +105 -0
- package/lib/__tests__/testHelpers.d.ts +7 -0
- package/lib/__tests__/testHelpers.js +16 -0
- package/lib/coerceType.d.ts +7 -0
- package/lib/coerceType.js +240 -0
- package/lib/dynamic-blocks.d.ts +8 -0
- package/lib/dynamic-blocks.js +44 -0
- package/lib/expressions.d.ts +9 -0
- package/lib/expressions.js +634 -0
- package/lib/function-bindings/functions.d.ts +31 -0
- package/lib/function-bindings/functions.generated.d.ts +806 -0
- package/lib/function-bindings/functions.generated.js +1142 -0
- package/lib/function-bindings/functions.js +73 -0
- package/lib/generation.d.ts +26 -0
- package/lib/generation.js +676 -0
- package/lib/index.d.ts +136 -0
- package/lib/index.js +364 -0
- package/lib/iteration.d.ts +23 -0
- package/lib/iteration.js +87 -0
- package/lib/jsii-rosetta-workarounds.d.ts +5 -0
- package/lib/jsii-rosetta-workarounds.js +126 -0
- package/lib/partialCode.d.ts +11 -0
- package/lib/partialCode.js +116 -0
- package/lib/provider.d.ts +8 -0
- package/lib/provider.js +40 -0
- package/lib/references.d.ts +11 -0
- package/lib/references.js +141 -0
- package/lib/schema.d.ts +297 -0
- package/lib/schema.js +81 -0
- package/lib/telemetryAllowList.json +24 -0
- package/lib/terraformSchema.d.ts +6 -0
- package/lib/terraformSchema.js +136 -0
- package/lib/types.d.ts +50 -0
- package/lib/types.js +3 -0
- package/lib/utils.d.ts +6 -0
- package/lib/utils.js +25 -0
- package/lib/variables.d.ts +10 -0
- package/lib/variables.js +172 -0
- package/package.json +71 -0
- package/package.sh +9 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,693 @@
|
|
|
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==
|