@cdktn/hcl2cdk 0.23.0-pre.7 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient.d.ts +0 -1
- package/build/__tests__/coerceType.test.js +165 -0
- package/build/__tests__/expressionToTs.test.js +693 -0
- package/build/__tests__/expressions.test.js +415 -0
- package/build/__tests__/findExpressionType.test.js +105 -0
- package/build/__tests__/functions.test.js +605 -0
- package/build/__tests__/generation.test.js +45 -0
- package/build/__tests__/jsii-rosetta-workarounds.test.js +86 -0
- package/build/__tests__/partialCode.test.js +390 -0
- package/build/__tests__/terraformSchema.test.js +105 -0
- package/build/__tests__/testHelpers.js +16 -0
- package/build/coerceType.js +240 -0
- package/build/dynamic-blocks.js +44 -0
- package/build/expressions.js +633 -0
- package/build/function-bindings/functions.generated.js +1142 -0
- package/build/function-bindings/functions.js +73 -0
- package/{lib → build}/generation.js +4 -4
- package/{lib → build}/index.d.ts +2 -2
- package/build/index.js +364 -0
- package/build/iteration.js +87 -0
- package/build/jsii-rosetta-workarounds.js +126 -0
- package/build/partialCode.js +116 -0
- package/build/provider.js +40 -0
- package/build/references.js +141 -0
- package/build/schema.js +81 -0
- package/build/telemetryAllowList.json +24 -0
- package/build/terraformSchema.js +136 -0
- package/build/types.js +3 -0
- package/build/utils.js +25 -0
- package/build/variables.js +172 -0
- package/package.json +13 -14
- package/tsconfig.json +4 -2
- package/lib/__tests__/coerceType.test.js +0 -165
- package/lib/__tests__/expressionToTs.test.js +0 -693
- package/lib/__tests__/expressions.test.js +0 -415
- package/lib/__tests__/findExpressionType.test.js +0 -105
- package/lib/__tests__/functions.test.js +0 -605
- package/lib/__tests__/generation.test.js +0 -45
- package/lib/__tests__/jsii-rosetta-workarounds.test.js +0 -86
- package/lib/__tests__/partialCode.test.js +0 -390
- package/lib/__tests__/terraformSchema.test.js +0 -105
- package/lib/__tests__/testHelpers.js +0 -16
- package/lib/coerceType.js +0 -240
- package/lib/dynamic-blocks.js +0 -44
- package/lib/expressions.js +0 -634
- package/lib/function-bindings/functions.generated.js +0 -1142
- package/lib/function-bindings/functions.js +0 -73
- package/lib/index.js +0 -364
- package/lib/iteration.js +0 -87
- package/lib/jsii-rosetta-workarounds.js +0 -126
- package/lib/partialCode.js +0 -116
- package/lib/provider.js +0 -40
- package/lib/references.js +0 -141
- package/lib/schema.js +0 -81
- package/lib/terraformSchema.js +0 -136
- package/lib/types.js +0 -3
- package/lib/utils.js +0 -25
- package/lib/variables.js +0 -172
- /package/{lib → build}/__tests__/coerceType.test.d.ts +0 -0
- /package/{lib → build}/__tests__/expressionToTs.test.d.ts +0 -0
- /package/{lib → build}/__tests__/expressions.test.d.ts +0 -0
- /package/{lib → build}/__tests__/findExpressionType.test.d.ts +0 -0
- /package/{lib → build}/__tests__/functions.test.d.ts +0 -0
- /package/{lib → build}/__tests__/generation.test.d.ts +0 -0
- /package/{lib → build}/__tests__/jsii-rosetta-workarounds.test.d.ts +0 -0
- /package/{lib → build}/__tests__/partialCode.test.d.ts +0 -0
- /package/{lib → build}/__tests__/terraformSchema.test.d.ts +0 -0
- /package/{lib → build}/__tests__/testHelpers.d.ts +0 -0
- /package/{lib → build}/coerceType.d.ts +0 -0
- /package/{lib → build}/dynamic-blocks.d.ts +0 -0
- /package/{lib → build}/expressions.d.ts +0 -0
- /package/{lib → build}/function-bindings/functions.d.ts +0 -0
- /package/{lib → build}/function-bindings/functions.generated.d.ts +0 -0
- /package/{lib → build}/generation.d.ts +0 -0
- /package/{lib → build}/iteration.d.ts +0 -0
- /package/{lib → build}/jsii-rosetta-workarounds.d.ts +0 -0
- /package/{lib → build}/partialCode.d.ts +0 -0
- /package/{lib → build}/provider.d.ts +0 -0
- /package/{lib → build}/references.d.ts +0 -0
- /package/{lib → build}/schema.d.ts +0 -0
- /package/{lib → build}/terraformSchema.d.ts +0 -0
- /package/{lib → build}/types.d.ts +0 -0
- /package/{lib → build}/utils.d.ts +0 -0
- /package/{lib → build}/variables.d.ts +0 -0
- /package/{lib → src}/telemetryAllowList.json +0 -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc2lvblRvVHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fX3Rlc3RzX18vZXhwcmVzc2lvblRvVHMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOztBQUVILGdEQUFnRTtBQUdoRSwrQ0FBa0Q7QUFFbEQsTUFBTSxpQkFBaUIsR0FBRztJQUN4QixjQUFjLEVBQUUsS0FBSztJQUNyQixnQkFBZ0IsRUFBRTtRQUNoQixxQ0FBcUMsRUFBRTtZQUNyQyxRQUFRLEVBQUUsRUFBRTtZQUNaLGdCQUFnQixFQUFFO2dCQUNoQixhQUFhLEVBQUU7b0JBQ2IsS0FBSyxFQUFFO3dCQUNMLFVBQVUsRUFBRTs0QkFDVixHQUFHLEVBQUU7Z0NBQ0gsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQztnQ0FDdkIsZ0JBQWdCLEVBQUUsT0FBTzs2QkFDMUI7eUJBQ0Y7cUJBQ0Y7aUJBQ0Y7YUFDRjtZQUNELG1CQUFtQixFQUFFO2dCQUNuQixzQkFBc0IsRUFBRTtvQkFDdEIsT0FBTyxFQUFFLENBQUM7b0JBQ1YsS0FBSyxFQUFFO3dCQUNMLFVBQVUsRUFBRTs0QkFDVixzQkFBc0IsRUFBRTtnQ0FDdEIsSUFBSSxFQUFFLE1BQU07Z0NBQ1osZ0JBQWdCLEVBQUUsT0FBTztnQ0FDekIsUUFBUSxFQUFFLElBQUk7NkJBQ2Y7NEJBQ0QsYUFBYSxFQUFFO2dDQUNiLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUM7Z0NBQ3ZCLGdCQUFnQixFQUFFLE9BQU87Z0NBQ3pCLFFBQVEsRUFBRSxJQUFJOzZCQUNmOzRCQUNELGdCQUFnQixFQUFFO2dDQUNoQixJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDO2dDQUN2QixnQkFBZ0IsRUFBRSxPQUFPO2dDQUN6QixRQUFRLEVBQUUsSUFBSTs2QkFDZjs0QkFDRCxXQUFXLEVBQUU7Z0NBQ1gsSUFBSSxFQUFFLENBQUMsS0FB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YykgSGFzaGlDb3JwLCBJbmMuXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTVBMLTIuMFxuICovXG5cbmltcG9ydCB7IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyB9IGZyb20gXCIuLi9leHByZXNzaW9uc1wiO1xuaW1wb3J0IHsgUmVzb3VyY2VTY29wZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgQXR0cmlidXRlVHlwZSB9IGZyb20gXCJAY2RrdG4vY29tbW9uc1wiO1xuaW1wb3J0IHsgYXN0VG9Db2RlIGFzIGNvZGUgfSBmcm9tIFwiLi90ZXN0SGVscGVyc1wiO1xuXG5jb25zdCBhd3NQcm92aWRlclNjaGVtYSA9IHtcbiAgZm9ybWF0X3ZlcnNpb246IFwiMS4wXCIsXG4gIHByb3ZpZGVyX3NjaGVtYXM6IHtcbiAgICBcInJlZ2lzdHJ5LnRlcnJhZm9ybS5pby9oYXNoaWNvcnAvYXdzXCI6IHtcbiAgICAgIHByb3ZpZGVyOiB7fSxcbiAgICAgIHJlc291cmNlX3NjaGVtYXM6IHtcbiAgICAgICAgYXdzX3MzX2J1Y2tldDoge1xuICAgICAgICAgIGJsb2NrOiB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgIGZvbzoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcIm1hcFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgZGF0YV9zb3VyY2Vfc2NoZW1hczoge1xuICAgICAgICBhd3NfYXZhaWxhYmlsaXR5X3pvbmVzOiB7XG4gICAgICAgICAgdmVyc2lvbjogMCxcbiAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICBhbGxfYXZhaWxhYmlsaXR5X3pvbmVzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJib29sXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBleGNsdWRlX25hbWVzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wic2V0XCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZXhjbHVkZV96b25lX2lkczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGdyb3VwX25hbWVzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wic2V0XCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgaWQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgbmFtZXM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJsaXN0XCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgc3RhdGU6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgem9uZV9pZHM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJsaXN0XCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgdGVzdGluZ19tYXA6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIGNvbXB1dGVkOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJsb2NrX3R5cGVzOiB7XG4gICAgICAgICAgICAgIGZpbHRlcjoge1xuICAgICAgICAgICAgICAgIG5lc3RpbmdfbW9kZTogXCJzZXRcIixcbiAgICAgICAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczoge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRpbWVvdXRzOiB7XG4gICAgICAgICAgICAgICAgbmVzdGluZ19tb2RlOiBcInNpbmdsZVwiLFxuICAgICAgICAgICAgICAgIGJsb2NrOiB7XG4gICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn07XG5cbmNvbnN0IGV4dGVybmFsUHJvdmlkZXJTY2hlbWEgPSB7XG4gIGZvcm1hdF92ZXJzaW9uOiBcIjEuMFwiLFxuICBwcm92aWRlcl9zY2hlbWFzOiB7XG4gICAgXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8vaGFzaGljb3JwL2V4dGVybmFsXCI6IHtcbiAgICAgIHByb3ZpZGVyOiB7fSxcbiAgICAgIHJlc291cmNlX3NjaGVtYXM6IHt9LFxuICAgICAgZGF0YV9zb3VyY2Vfc2NoZW1hczoge1xuICAgICAgICBleHRlcm5hbDoge1xuICAgICAgICAgIHZlcnNpb246IDAsXG4gICAgICAgICAgYmxvY2s6IHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgaWQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgXCJUaGUgaWQgb2YgdGhlIGRhdGEgc291cmNlLiBUaGlzIHdpbGwgYWx3YXlzIGJlIHNldCB0byBgLWBcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHByb2dyYW06IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJsaXN0XCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgXCJBIGxpc3Qgb2Ygc3RyaW5ncywgd2hvc2UgZmlyc3QgZWxlbWVudCBpcyB0aGUgcHJvZ3JhbSB0byBydW4gYW5kIHdob3NlIHN1YnNlcXVlbnQgZWxlbWVudHMgYXJlIG9wdGlvbmFsIGNvbW1hbmQgbGluZSBhcmd1bWVudHMgdG8gdGhlIHByb2dyYW0uIFRlcnJhZm9ybSBkb2VzIG5vdCBleGVjdXRlIHRoZSBwcm9ncmFtIHRocm91Z2ggYSBzaGVsbCwgc28gaXQgaXMgbm90IG5lY2Vzc2FyeSB0byBlc2NhcGUgc2hlbGwgbWV0YWNoYXJhY3RlcnMgbm9yIGFkZCBxdW90ZXMgYXJvdW5kIGFyZ3VtZW50cyBjb250YWluaW5nIHNwYWNlcy5cIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHF1ZXJ5OiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgXCJBIG1hcCBvZiBzdHJpbmcgdmFsdWVzIHRvIHBhc3MgdG8gdGhlIGV4dGVybmFsIHByb2dyYW0gYXMgdGhlIHF1ZXJ5IGFyZ3VtZW50cy4gSWYgbm90IHN1cHBsaWVkLCB0aGUgcHJvZ3JhbSB3aWxsIHJlY2VpdmUgYW4gZW1wdHkgb2JqZWN0IGFzIGl0cyBpbnB1dC5cIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHJlc3VsdDoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcIm1hcFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiQSBtYXAgb2Ygc3RyaW5nIHZhbHVlcyByZXR1cm5lZCBmcm9tIHRoZSBleHRlcm5hbCBwcm9ncmFtLlwiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgd29ya2luZ19kaXI6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgXCJXb3JraW5nIGRpcmVjdG9yeSBvZiB0aGUgcHJvZ3JhbS4gSWYgbm90IHN1cHBsaWVkLCB0aGUgcHJvZ3JhbSB3aWxsIHJ1biBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkuXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAnVGhlIGBleHRlcm5hbGAgZGF0YSBzb3VyY2UgYWxsb3dzIGFuIGV4dGVybmFsIHByb2dyYW0gaW1wbGVtZW50aW5nIGEgc3BlY2lmaWMgcHJvdG9jb2wgKGRlZmluZWQgYmVsb3cpIHRvIGFjdCBhcyBhIGRhdGEgc291cmNlLCBleHBvc2luZyBhcmJpdHJhcnkgZGF0YSBmb3IgdXNlIGVsc2V3aGVyZSBpbiB0aGUgVGVycmFmb3JtIGNvbmZpZ3VyYXRpb24uXFxuXFxuKipXYXJuaW5nKiogVGhpcyBtZWNoYW5pc20gaXMgcHJvdmlkZWQgYXMgYW4gXCJlc2NhcGUgaGF0Y2hcIiBmb3IgZXhjZXB0aW9uYWwgc2l0dWF0aW9ucyB3aGVyZSBhIGZpcnN0LWNsYXNzIFRlcnJhZm9ybSBwcm92aWRlciBpcyBub3QgbW9yZSBhcHByb3ByaWF0ZS4gSXRzIGNhcGFiaWxpdGllcyBhcmUgbGltaXRlZCBpbiBjb21wYXJpc29uIHRvIGEgdHJ1ZSBkYXRhIHNvdXJjZSwgYW5kIGltcGxlbWVudGluZyBhIGRhdGEgc291cmNlIHZpYSBhbiBleHRlcm5hbCBwcm9ncmFtIGlzIGxpa2VseSB0byBodXJ0IHRoZSBwb3J0YWJpbGl0eSBvZiB5b3VyIFRlcnJhZm9ybSBjb25maWd1cmF0aW9uIGJ5IGNyZWF0aW5nIGRlcGVuZGVuY2llcyBvbiBleHRlcm5hbCBwcm9ncmFtcyBhbmQgbGlicmFyaWVzIHRoYXQgbWF5IG5vdCBiZSBhdmFpbGFibGUgKG9yIG1heSBuZWVkIHRvIGJlIHVzZWQgZGlmZmVyZW50bHkpIG9uIGRpZmZlcmVudCBvcGVyYXRpbmcgc3lzdGVtcy5cXG5cXG4qKldhcm5pbmcqKiBUZXJyYWZvcm0gRW50ZXJwcmlzZSBkb2VzIG5vdCBndWFyYW50ZWUgYXZhaWxhYmlsaXR5IG9mIGFueSBwYXJ0aWN1bGFyIGxhbmd1YWdlIHJ1bnRpbWVzIG9yIGV4dGVybmFsIHByb2dyYW1zIGJleW9uZCBzdGFuZGFyZCBzaGVsbCB1dGlsaXRpZXMsIHNvIGl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byB1c2UgdGhpcyBkYXRhIHNvdXJjZSB3aXRoaW4gY29uZmlndXJhdGlvbnMgdGhhdCBhcmUgYXBwbGllZCB3aXRoaW4gVGVycmFmb3JtIEVudGVycHJpc2UuJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9LFxufTtcblxudHlwZSBHZXRTY29wZVBhcmFtcyA9IHtcbiAgcHJvdmlkZXI/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICByZXNvdXJjZXM/OiBzdHJpbmdbXTtcbiAgZGF0YT86IHN0cmluZ1tdO1xuICB2YXJpYWJsZXM/OiBzdHJpbmdbXTtcbiAgbG9jYWxzPzogc3RyaW5nW107XG4gIGZvckVhY2hJdGVyYXRvck5hbWU/OiBzdHJpbmc7XG4gIHdpdGhpbk92ZXJyaWRlRXhwcmVzc2lvbj86IGJvb2xlYW47XG4gIHNjb3BlZFZhcmlhYmxlcz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG5mdW5jdGlvbiBnZXRTY29wZSh7XG4gIHByb3ZpZGVyLFxuICByZXNvdXJjZXMsXG4gIGRhdGEsXG4gIHZhcmlhYmxlcyxcbiAgbG9jYWxzLFxuICBmb3JFYWNoSXRlcmF0b3JOYW1lLFxuICBzY29wZWRWYXJpYWJsZXMsXG4gIHdpdGhpbk92ZXJyaWRlRXhwcmVzc2lvbiA9IGZhbHNlLFxufTogR2V0U2NvcGVQYXJhbXMgPSB7fSk6IFJlc291cmNlU2NvcGUge1xuICBjb25zdCBzY29wZVZhcmlhYmxlczogUmVzb3VyY2VTY29wZVtcInZhcmlhYmxlc1wiXSA9IHt9O1xuXG4gIHJlc291cmNlcz8uZm9yRWFjaCgodmFyTmFtZSkgPT4ge1xuICAgIGxldCBbcmVzb3VyY2VUeXBlLCByZXNvdXJjZU5hbWVdID0gdmFyTmFtZS5zcGxpdChcIi5cIik7XG4gICAgaWYgKCFyZXNvdXJjZU5hbWUpIHtcbiAgICAgIHJlc291cmNlTmFtZSA9IHZhck5hbWU7XG4gICAgICByZXNvdXJjZVR5cGUgPSBcImF3c19zM19idWNrZXRcIjtcbiAgICB9XG5cbiAgICBzY29wZVZhcmlhYmxlc1t2YXJOYW1lXSA9IHtcbiAgICAgIHJlc291cmNlOiByZXNvdXJjZVR5cGUsXG4gICAgICB2YXJpYWJsZU5hbWU6IHJlc291cmNlTmFtZSxcbiAgICB9O1xuICB9KTtcblxuICBkYXRhPy5mb3JFYWNoKCh2YXJOYW1lKSA9PiB7XG4gICAgc2NvcGVWYXJpYWJsZXNbdmFyTmFtZV0gPSB7XG4gICAgICByZXNvdXJjZTogXCJkYXRhLmF3c19zM19idWNrZXRcIixcbiAgICAgIHZhcmlhYmxlTmFtZTogdmFyTmFtZSxcbiAgICB9O1xuICB9KTtcblxuICB2YXJpYWJsZXM/LmZvckVhY2goKHZhck5hbWUpID0+IHtcbiAgICBzY29wZVZhcmlhYmxlc1t2YXJOYW1lXSA9IHtcbiAgICAgIHJlc291cmNlOiBcInZhclwiLFxuICAgICAgdmFyaWFibGVOYW1lOiB2YXJOYW1lLFxuICAgIH07XG4gIH0pO1xuXG4gIGxvY2Fscz8uZm9yRWFjaCgodmFyTmFtZSkgPT4ge1xuICAgIHNjb3BlVmFyaWFibGVzW3Zhck5hbWVdID0ge1xuICAgICAgcmVzb3VyY2U6IFwibG9jYWxcIixcbiAgICAgIHZhcmlhYmxlTmFtZTogdmFyTmFtZSxcbiAgICB9O1xuICB9KTtcblxuICBjb25zdCBzY29wZSA9IHtcbiAgICBwcm92aWRlclNjaGVtYTogcHJvdmlkZXIgPz8ge30sXG4gICAgcHJvdmlkZXJHZW5lcmF0b3I6IHt9LFxuICAgIGNvbnN0cnVjdHM6IG5ldyBTZXQ8c3RyaW5nPigpLFxuICAgIHZhcmlhYmxlczogc2NvcGVWYXJpYWJsZXMsXG4gICAgaGFzVG9rZW5CYXNlZFR5cGVDb2VyY2lvbjogdHJ1ZSxcbiAgICBzY29wZWRWYXJpYWJsZXM6IHNjb3BlZFZhcmlhYmxlcyB8fCB7fSxcbiAgICBmb3JFYWNoSXRlcmF0b3JOYW1lLFxuICAgIHdpdGhpbk92ZXJyaWRlRXhwcmVzc2lvbixcbiAgICBub2RlSWRzOiBbXSxcbiAgICBpbXBvcnRhYmxlczogW10sXG4gICAgdG9wTGV2ZWxDb25maWc6IHt9LFxuICB9O1xuXG4gIHJldHVybiBzY29wZTtcbn1cblxuY29uc3QgZ2V0VHlwZSA9ICgpOiBBdHRyaWJ1dGVUeXBlID0+IFwic3RyaW5nXCI7XG5cbmRlc2NyaWJlKFwiZXhwcmVzc2lvblRvVHNcIiwgKCkgPT4ge1xuICB0ZXN0KFwiY29udmVydHMgYSBzaW1wbGUgc3RyaW5nIHRvIGEgc3RyaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCJoZWxsb1wiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwiaGVsbG9cIlwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIHNpbXBsZSBleHByZXNzaW9uIHdpdGggYSB0ZW1wbGF0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHsyMn1cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJUb2tlbi5hc1N0cmluZygyMilcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSB2YXJpYWJsZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7dmFyLmZvb31cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJmb28uc3RyaW5nVmFsdWVcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHZhcmlhYmxlIHJlZmVyZW5jZSB3aXRoIHNuYWtlIGNhc2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7dmFyLmZvb19iYXJ9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1wiZm9vX2JhclwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoZm9vQmFyLnZhbHVlKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGZ1bmN0aW9uIGNhbGxcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke3JlcGxhY2UoXCJoZWxsb1wiLCBcImxcIiwgXCJ3XCIpfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5yZXBsYWNlKFwiaGVsbG9cIiwgXCJsXCIsIFwid1wiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZnVuY3Rpb24gY2FsbCB3aXRoIGFuIGV4cHJlc3Npb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke3JlcGxhY2UoXCJoZWxsby1cXCR7MjIrMjJ9XCIsIFwiNDRcIiwgXCJ3b3JsZFwiKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ucmVwbGFjZShcImhlbGxvLVwiICsgVG9rZW4uYXNTdHJpbmcoT3AuYWRkKDIyLCAyMikpLCBcIjQ0XCIsIFwid29ybGRcIikpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBzdHJpbmcgY29uY2F0ZW5hdGlvbiBvZiBpdGVyYXRvciBrZXlcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSAnJHtcImR5bmFtaWMtaW5ncmVzcy0ke2luZ3Jlc3Mua2V5fVwifSc7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBzY29wZWRWYXJpYWJsZXM6IHtcbiAgICAgICAgaW5ncmVzczogXCJkeW5hbWljX2l0ZXJhdG9yMFwiLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJkeW5hbWljLWluZ3Jlc3MtXFwke1wiICsgVG9rZW4uYXNTdHJpbmcoZHluYW1pY19pdGVyYXRvcjAua2V5KSArIFwifVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgdmFyaWFibGUgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHt2YXIuZm9vX2Jhcn1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcImZvb19iYXJcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIC8vIFRPRE86IFRoaXMgc2VlbXMgYnJva2VuXG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoZm9vQmFyLnZhbHVlKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHJlc291cmNlIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcInNpbXBsZS1cXCR7YXdzX3MzX2J1Y2tldC5mb28uaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZm9vXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiXCJzaW1wbGUtXFwke1wiICsgZm9vLmlkICsgXCJ9XCJcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHJlc291cmNlIHJlZmVyZW5jZSB3aXRoIG5lc3RlZCBwcm9wZXJ0aWVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwic2ltcGxlLVxcJHthd3NfczNfYnVja2V0LmZvby5wcm9wLnRlc3R9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZm9vXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcInNpbXBsZS1cXCR7XCIgKyBmb28ucHJvcC50ZXN0ICsgXCJ9XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBsb2NhbCByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJzaW1wbGUtXFwke2xvY2FsLmZvb31cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IGxvY2FsczogW1wiZm9vXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiXCJzaW1wbGUtXFwke1wiICsgZm9vICsgXCJ9XCJcImApO1xuICB9KTtcblxuICB0ZXN0KFwicGxhaW4gcmVzb3VyY2UgcmVmZXJlbmNlcyBpbiBhcml0aG1ldGljc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LmNvdW50ICsgYXdzX3MzX2J1Y2tldC5vdGhlcmJ1Y2tldC5jb3VudCB9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiLCBcImF3c19zM19idWNrZXQub3RoZXJidWNrZXRcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKE9wLmFkZChleGFtcGxlYnVja2V0LmNvdW50LCBvdGhlcmJ1Y2tldC5jb3VudCkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJ1c2UgZnFuIGZvciBzcGxhdCByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke2F3c19zM19idWNrZXQuZm9vLiouaWR9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGZvbywgW1wiKlwiLCBcImlkXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInVzZSBmcW4gaWYgcHJvcGVydHkgaXMgcHJlc2VudCBvbiBudW1lcmljIGFjY2VzcyB1c2luZyBkb3Qgbm90YXRpb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgXCIke2F3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5uZXR3b3JrX2ludGVyZmFjZS4wLmFjY2Vzc19jb25maWcuMC5hc3NpZ25lZF9uYXRfaXB9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldC5uZXR3b3JrSW50ZXJmYWNlLCBbXCIwXCIsIFwiYWNjZXNzX2NvbmZpZ1wiLCBcIjBcIiwgXCJhc3NpZ25lZF9uYXRfaXBcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwidXNlIGZxbiBpZiBwcm9wZXJ0eSBpcyBwcmVzZW50IG9uIG51bWVyaWMgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQubmV0d29ya19pbnRlcmZhY2VbMF0uYWNjZXNzX2NvbmZpZ1swXS5hc3NpZ25lZF9uYXRfaXB9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldC5uZXR3b3JrSW50ZXJmYWNlLCBbXCIwXCIsIFwiYWNjZXNzX2NvbmZpZ1wiLCBcIjBcIiwgXCJhc3NpZ25lZF9uYXRfaXBcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwidXNlIG5vIGZxbiBpZiBwcm9wZXJ0eSBpcyBwcmVzZW50IG9uIG51bWVyaWMgYWNjZXNzIHVzaW5nIFtdXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQubmV0d29ya19pbnRlcmZhY2VbMF0uYWNjZXNzX2NvbmZpZ1swXS5hc3NpZ25lZF9uYXRfaXB9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldC5uZXR3b3JrSW50ZXJmYWNlLCBbXCIwXCIsIFwiYWNjZXNzX2NvbmZpZ1wiLCBcIjBcIiwgXCJhc3NpZ25lZF9uYXRfaXBcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZGV0ZWN0cyBzcGxhdCByZWZlcmVuY2Ugd2l0aGluIGZ1bmN0aW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke3Rvc2V0KGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC4qKX1cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLnRvc2V0KEZuLmxvb2t1cE5lc3RlZChleGFtcGxlYnVja2V0LCBbXCIqXCJdKSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGNvbmRpdGlvbmFsXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHthd3Nfa21zX2tleS5rZXkuZGVsZXRpb25fd2luZG93X2luX2RheXMgPiAzID8gYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LmlkIDogW119XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX2ttc19rZXkua2V5XCIsIFwiZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoY29uZGl0aW9uYWwoT3AuZ3Qoa2V5LmRlbGV0aW9uV2luZG93SW5EYXlzLCAzKSwgZXhhbXBsZWJ1Y2tldC5pZCwgW10pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBmdW5jdGlvbiB3aXRoIHJlZmVyZW5jZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7ZWxlbWVudChhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQsIDApLmlkfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKEZuLmVsZW1lbnQoZXhhbXBsZWJ1Y2tldCwgMCksIFtcImlkXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZnVuY3Rpb24gd2l0aCBzcGxhdCByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7ZWxlbWVudChhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuKi5pZCwgMCl9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5lbGVtZW50KEZuLmxvb2t1cE5lc3RlZChleGFtcGxlYnVja2V0LCBbXCIqXCIsIFwiaWRcIl0pLCAwKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgZm9yIGxvb3BzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHt7IGZvciBuYW1lLCB1c2VyIGluIHZhci51c2VycyA6IHVzZXIucm9sZSA9PiBuYW1lLi4ufX1cIjtcblxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7eyBmb3IgbmFtZSwgdXNlciBpbiBcXCR7XCIgKyB1c2Vycy52YWx1ZSArIFwifSA6IHVzZXIucm9sZSA9PiBuYW1lLi4ufX1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZm9yIGV4cHJlc3Npb25zXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCJ7Zm9yIHMgaW4gdmFyLmxpc3QgOiBzID0+IHVwcGVyKHMpfVwiO1xuXG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHt7IGZvciBzIGluIFxcJHtcIiArIGxpc3QudmFsdWUgKyBcIn0gOiBzID0+IHVwcGVyKHMpfX1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZm9yIGxpc3QgZXhwcmVzc2lvbiBcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIltmb3IgcyBpbiB2YXIubGlzdCA6IHVwcGVyKHMpXVwiO1xuXG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtbIGZvciBzIGluIFxcJHtcIiArIGxpc3QudmFsdWUgKyBcIn0gOiB1cHBlcihzKV19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImZvciBsaXN0IHdpdGggY29uZGl0aW9uYWxcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSAnW2ZvciBzIGluIHZhci5saXN0IDogdXBwZXIocykgaWYgcyAhPSBcIlwiXSc7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtbIGZvciBzIGluIFxcJHtcIiArIGxpc3QudmFsdWUgKyBcIn0gOiB1cHBlcihzKSBpZiBzICE9IFxcXFxcIlxcXFxcIl19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgcHJvcGVydHkgYWNjZXNzIHJlc291cmNlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRbMF0uaWR9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiMFwiLCBcImlkXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgdW5hcnkgb3BlcmF0b3JzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHshdmFyLmVuYWJsZWR9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJlbmFibGVkXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgICgpID0+IFwiYm9vbFwiLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNCb29sZWFuKE9wLm5vdChlbmFibGVkLnZhbHVlKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgZnVuY3Rpb24gd2l0aCBhcnJheXMgYW5kIGNvbW1lbnRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtjb21wYWN0KFtcbiAgICAgICAgICAgICMgVGhlIGV4YW1wbGUgXCJidWNrZXRcIlxuICAgICAgICAgICAgYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LFxuICAgICAgICBcbiAgICAgICAgICAgICMgVGhlIFwiTGVhcm5cIiBzaW5nbGUgcGFnZSBhcHBsaWNhdGlvbi4gVGhpcyBpcyBub3QgY29uZmlndXJlZCBpbiBhbGwgZW52aXJvbm1lbnRzLlxuICAgICAgICAgICAgdmFyLmlucHV0LFxuICAgICAgICAgIF0pfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSxcbiAgICAgIHZhcmlhYmxlczogW1wiaW5wdXRcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIC8vIFRPRE86IFNlZSBpZiB3ZSBoYXZlIGEgd2F5IHRvIHByZXNlcnZlIGNvbW1lbnRzXG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uY29tcGFjdChUb2tlbi5hc0xpc3QoW2V4YW1wbGVidWNrZXQsIGlucHV0LnZhbHVlXSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCByZWZlcmVuY2VzIGZvciBzYW1lIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7dmFyLmlucHV0ID09IFwidGVzdFwiID8gXCJhenVyZS1hZC1pbnRcIiA6IFwiYXp1cmUtYWQtXFwke3Zhci5pbnB1dH1cIn1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcImlucHV0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhjb25kaXRpb25hbChPcC5lcShpbnB1dC52YWx1ZSwgXCJ0ZXN0XCIpLCBcImF6dXJlLWFkLWludFwiLCBcImF6dXJlLWFkLVxcJHtcIiArIGlucHV0LnZhbHVlICsgXCJ9XCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwibmVzdGVkIHZhcmlhYmxlIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7ZWxlbWVudCh2YXIudGVzdDJbXCJ2YWwxXCJdLCAwKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInRlc3QyXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5lbGVtZW50KEZuLmxvb2t1cE5lc3RlZCh0ZXN0Mi52YWx1ZSwgW1wiXFxcXFwidmFsMVxcXFxcIlwiXSksIDApKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29tcGxpY2F0ZWQgbmVzdGVkIGxvY2FsIHZhbHVlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke2ZsYXR0ZW4odmFyLnZuZXRzWypdLnN1Ym5ldHNbKl0ubmFtZSl9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widm5ldHNcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmZsYXR0ZW4oRm4ubG9va3VwTmVzdGVkKHZuZXRzLnZhbHVlLCBbXCIqXCIsIFwic3VibmV0c1wiLCBcIipcIiwgXCJuYW1lXCJdKSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIC8vIFRPSU1QUk9WRTogSSBkb24ndCB0aGluayB3ZSBjYW4gaGFuZGxlIHRoaXMgY2FzZSB5ZXQsIHNpbmNlIHRoZSB2YXJpYWJsZVxuICAvLyBuZWVkcyB0byBiZSB3cmFwcGVkIGluIGFuIGl0ZXJhdG9yLiBJJ20gbGVhdmluZyB0aGlzIGluLCBidXQgaXQncyBicm9rZW5cbiAgdGVzdChcImNvbXBsaWNhdGVkIG5lc3RlZCB2YXJpYWJsZSBhY2Nlc3Mgd2l0aCBtYXBcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgeyBcbiAgICBmb3Igdm5ldCBpbiB2YXIudm5ldHNbKl06XG4gICAgKHZuZXQudm5ldF9uYW1lKSA9PiB2bmV0LnN1Ym5ldHNbKl0ubmFtZVxuICB9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ2bmV0c1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7eyBmb3Igdm5ldCBpbiBcXCR7XCIgKyBGbi5sb29rdXBOZXN0ZWQodm5ldHMudmFsdWUsIFtcIipcIl0pICsgXCJ9IDogKHZuZXQudm5ldF9uYW1lKSA9PiB2bmV0LnN1Ym5ldHNbKl0ubmFtZX19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbXBsaWNhdGVkIG5lc3RlZCB2YXJpYWJsZSBhY2Nlc3Mgd2l0aCBsaXN0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtmbGF0dGVuKFtcbiAgICBmb3IgaywgdiBpbiB2YXIucm91dGUgOiBbXG4gICAgICBmb3IgbiwgcyBpbiB2IDogW1xuICAgICAgICB7XG4gICAgICAgICAga2V5ID0gayxcbiAgICAgICAgICBuYW1lID0gbixcbiAgICAgICAgICBzdmNfdXJsID0gc1xuICAgICAgICB9XG4gICAgICBdXG4gICAgXVxuICBdKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInJvdXRlXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5mbGF0dGVuKFwiXFwke1sgZm9yIGssIHYgaW4gXFwke1wiICsgcm91dGUudmFsdWUgKyBcIn0gOiBbXFxcXG4gICAgICBmb3IgbiwgcyBpbiB2IDogW1xcXFxuICAgICAgICB7XFxcXG4gICAgICAgICAga2V5ID0gayxcXFxcbiAgICAgICAgICBuYW1lID0gbixcXFxcbiAgICAgICAgICBzdmNfdXJsID0gc1xcXFxuICAgICAgICB9XFxcXG4gICAgICBdXFxcXG4gICAgXV19XCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwic2ltcGxlIGxvY2FsIHZhcmlhYmxlIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHshbG9jYWwuZW5hYmxlZH1cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgbG9jYWxzOiBbXCJlbmFibGVkXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhPcC5ub3QoZW5hYmxlZCkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJtdWx0aSBsb2NhbCBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgJ1wiJHtsb2NhbC5zZXJ2aWNlX25hbWV9LCR7bG9jYWwub3duZXJ9LCR7bG9jYWwuaXNfaXRfZ3JlYXR9LCR7bG9jYWwuaG93X21hbnl9XCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgbG9jYWxzOiBbXCJzZXJ2aWNlX25hbWVcIiwgXCJvd25lclwiLCBcImlzX2l0X2dyZWF0XCIsIFwiaG93X21hbnlcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke1wiICsgc2VydmljZU5hbWUgKyBcIn0sXFwke1wiICsgb3duZXIgKyBcIn0sXFwke1wiICsgaXNJdEdyZWF0ICsgXCJ9LFxcJHtcIiArIGhvd01hbnkgKyBcIn1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiYmluYXJ5IG9wZXJhdGlvbnMgd2l0aGluIGxpdGVyYWxzIGFuZCB2YXJpYWJsZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSAnXCIke3Zhci50ZXN0fSArIDFcIic7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widGVzdFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7XCIgKyB0ZXN0LnZhbHVlICsgXCJ9ICsgMVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJsb2NhbCB2YXJpYWJsZSBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSAnXCIke2xvY2FsLmVuYWJsZWR9XCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyBsb2NhbHM6IFtcImVuYWJsZWRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJlbmFibGVkXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIHRyYXZlcnNhbHMgdGhhdCBjYW5ub3QgYmUgcmVmZXJlbmNlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHtzZWxmLnBhdGh9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhUZXJyYWZvcm1TZWxmLmdldEFueShcInBhdGhcIikpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBqb2luIGZ1bmN0aW9uIHdpdGggdmFyaWFibGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJyR7am9pbihcIi1cIiwgW3Zhci50YWdzLmFwcCwgdmFyLnRhZ3MuZW52XSl9JztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ0YWdzXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5qb2luKFwiLVwiLCBUb2tlbi5hc0xpc3QoW0ZuLmxvb2t1cE5lc3RlZCh0YWdzLnZhbHVlLCBbXCJhcHBcIl0pLCBGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiZW52XCJdKV0pKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGpvaW4gZnVuY3Rpb24gd2l0aCBtYW55IGFyZ3VtZW50cyB2YXJpYWJsZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgJyR7am9pbihcIi1cIiwgdmFyLnRhZ3MuYXBwLCB2YXIudGFncy5lbnYsIHZhci50YWdzLm90aGVyKX0nO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInRhZ3NcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmpvaW4oXCItXCIsIFRva2VuLmFzTGlzdChGbi5jb25jYXQoW0ZuLmxvb2t1cE5lc3RlZCh0YWdzLnZhbHVlLCBbXCJhcHBcIl0pLCBGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiZW52XCJdKSwgRm4ubG9va3VwTmVzdGVkKHRhZ3MudmFsdWUsIFtcIm90aGVyXCJdKV0pKSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJkb2Vzbid0IHdyYXAgYW55IGV4dHJhIHRlbXBsYXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcImFwcC1cXCR7dGVycmFmb3JtLndvcmtzcGFjZX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcImFwcC1cXCR7dGVycmFmb3JtLndvcmtzcGFjZX1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBmb3IgZXhwcmVzc2lvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBbZm9yIHJlY29yZCBpbiBhd3Nfcm91dGU1M19yZWNvcmQuZXhhbXBsZSA6IHJlY29yZC5mcWRuXWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtbIGZvciByZWNvcmQgaW4gXFwke1wiICsgZXhhbXBsZS5mcW4gKyBcIn0gOiByZWNvcmQuZnFkbl19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZGF0YSBzb3VyY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3Nfcm91dGU1M196b25lLmV4YW1wbGUuem9uZV9pZH1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhleGFtcGxlLnpvbmVJZClcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYW4gZWFjaCBleHByZXNzaW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2VhY2gudmFsdWUubmFtZX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IGZvckVhY2hJdGVyYXRvck5hbWU6IFwibXlJdGVyYXRvclwiIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQobXlJdGVyYXRvci52YWx1ZSwgW1wibmFtZVwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIHByb3BlcnR5IG9mIGEgZnVuY3Rpb24gY29udGFpbmluZyBhIHJlc291cmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2VsZW1lbnQoYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LCAwKS5pZH1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoRm4uZWxlbWVudChleGFtcGxlYnVja2V0LCAwKSwgW1wiaWRcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGZ1bmN0aW9uIHdpdGggcmVmZXJlbmNlcyB3aXRoIHNwbGF0c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtjb25jYXQodmFyLnByaXZhdGVfc3VibmV0cy4qLmlkLCB2YXIucHVibGljX3N1Ym5ldHMuKi5pZCl9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgdmFyaWFibGVzOiBbXCJwcml2YXRlX3N1Ym5ldHNcIiwgXCJwdWJsaWNfc3VibmV0c1wiXSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uY29uY2F0KFtGbi5sb29rdXBOZXN0ZWQocHJpdmF0ZVN1Ym5ldHMudmFsdWUsIFtcIipcIiwgXCJpZFwiXSksIEZuLmxvb2t1cE5lc3RlZChwdWJsaWNTdWJuZXRzLnZhbHVlLCBbXCIqXCIsIFwiaWRcIl0pXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgaXRlcmF0b3IgdmFyaWFibGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZWFjaC5rZXl9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgdmFyaWFibGVzOiBbXCJwcml2YXRlX3N1Ym5ldHNcIiwgXCJwdWJsaWNfc3VibmV0c1wiXSxcbiAgICAgIGZvckVhY2hJdGVyYXRvck5hbWU6IFwibXlJdGVyYXRvclwiLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhteUl0ZXJhdG9yLmtleSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBzZWxmIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtzZWxmLnN1Ym5ldC5pZH1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICB2YXJpYWJsZXM6IFtcInByaXZhdGVfc3VibmV0c1wiLCBcInB1YmxpY19zdWJuZXRzXCJdLFxuICAgICAgZm9yRWFjaEl0ZXJhdG9yTmFtZTogXCJteUl0ZXJhdG9yXCIsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKFRlcnJhZm9ybVNlbGYuZ2V0QW55KFwic3VibmV0LmlkXCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBoZXJlZG9jc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGA8PEVPRlxuW3tcbiAgICBcIkNvbmRpdGlvblwiOiB7XG4gICAgICAgIFwiS2V5UHJlZml4RXF1YWxzXCI6IFwiZG9jcy9cIlxuICAgIH0sXG4gICAgXCJSZWRpcmVjdFwiOiB7XG4gICAgICAgIFwiUmVwbGFjZUtleVByZWZpeFdpdGhcIjogXCJkb2N1bWVudHMvXCJcbiAgICB9XG59XVxuRU9GXG5gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJbe1xcXFxuICAgIFxcXFxcIkNvbmRpdGlvblxcXFxcIjoge1xcXFxuICAgICAgICBcXFxcXCJLZXlQcmVmaXhFcXVhbHNcXFxcXCI6IFxcXFxcImRvY3MvXFxcXFwiXFxcXG4gICAgfSxcXFxcbiAgICBcXFxcXCJSZWRpcmVjdFxcXFxcIjoge1xcXFxuICAgICAgICBcXFxcXCJSZXBsYWNlS2V5UHJlZml4V2l0aFxcXFxcIjogXFxcXFwiZG9jdW1lbnRzL1xcXFxcIlxcXFxuICAgIH1cXFxcbn1dXFxcXG5cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBoZXJlZG9jcyB3aXRob3V0IGEgdHJhaWxpbmcgbmV3bGluZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGA8PEVPRlxuaGVsbG8gd29ybGRcbkVPRmA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiXCJoZWxsbyB3b3JsZFxcXFxuXCJcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBpbmRlbnRlZCBoZXJlZG9jc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGA8PC1FT0ZcbiAgICAgICAgICAgICAgaGVsbG8gd29ybGRcbiAgICAgICAgICBFT0ZgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwiaGVsbG8gd29ybGRcXFxcblwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgb3ZlcnJpZGUgZXhwcmVzc2lvbnNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSAnXCIke3JlcXVpcmVkX3Jlc291cmNlX2FjY2Vzcy52YWx1ZVtcInJlc291cmNlX2FjY2Vzc1wiXX1cIic7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb246IHRydWUsXG4gICAgICBzY29wZWRWYXJpYWJsZXM6IHtcbiAgICAgICAgcmVxdWlyZWRfcmVzb3VyY2VfYWNjZXNzOiBcImR5bmFtaWMtYmxvY2tcIixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke3JlcXVpcmVkX3Jlc291cmNlX2FjY2Vzcy52YWx1ZVtcXFxcXCJyZXNvdXJjZV9hY2Nlc3NcXFxcXCJdfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHVzaW5nIG9wZXJhdGlvbnMgd2hpbGUgY29udGFpbmluZyBzdWJzdHJpbmdcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAnXCIke2xlbmd0aCh2YXIuaW1hZ2VfaWQpID4gNCAmJiBzdWJzdHIodmFyLmltYWdlX2lkLCAwLCA0KSA9PSBcImFtaS1cIn1cIic7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7fSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKE9wLmFuZChPcC5ndChGbi5sZW5ndGhPZihpbWFnZUlkLnZhbHVlKSwgNCksIE9wLmVxKEZuLnN1YnN0cihpbWFnZUlkLnN0cmluZ1ZhbHVlLCAwLCA0KSwgXCJhbWktXCIpKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBkYXRhIHNvdXJjZSB3aXRoIG51bWVyaWMgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2RhdGEuYXdzX2F2YWlsYWJpbGl0eV96b25lcy5jaGFuZ2VtZV9hel9saXN0X2Vic19zbmFwc2hvdC5uYW1lc1swXX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICBkYXRhOiBbXCJhd3Nfc3VibmV0X2lkc1wiXSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGNoYW5nZW1lQXpMaXN0RWJzU25hcHNob3QubmFtZXMsIFtcIjBcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHJlZmVyZW5jZSB0byBhIG1hcCBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3NfYXZhaWxhYmlsaXR5X3pvbmVzLmNoYW5nZW1lX2F6X2xpc3RfZWJzX3NuYXBzaG90LnRlc3RpbmdfbWFwLmZvb31cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICBkYXRhOiBbXCJhd3Nfc3VibmV0X2lkc1wiXSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGNoYW5nZW1lQXpMaXN0RWJzU25hcHNob3QsIFtcInRlc3RpbmdfbWFwXCIsIFwiZm9vXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYXR0cmlidXRlIHVwIHRvIGEgbWFwIGFuZCBub3Qgd2l0aGluIGF0dHJpYnV0ZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3NfYXZhaWxhYmlsaXR5X3pvbmVzLmNoYW5nZW1lX2F6X2xpc3RfZWJzX3NuYXBzaG90LnRlc3RpbmdfbWFwfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgICgpID0+IFtcIm1hcFwiLCBcInN0cmluZ1wiXSxcbiAgICApO1xuXG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmdNYXAoY2hhbmdlbWVBekxpc3RFYnNTbmFwc2hvdC50ZXN0aW5nTWFwKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZG9uJ3QgY29udmVydCBleHRlcm5hbCB1bmtub3duIGZpZWxkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmV4dGVybmFsLmNoYW5nZW1lX2V4dGVybmFsX3RodW1icHJpbnRfZGF0YS5yZXN1bHQudGh1bWJwcmludH1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogZXh0ZXJuYWxQcm92aWRlclNjaGVtYSxcbiAgICAgIGRhdGE6IFtcImF3c19zdWJuZXRfaWRzXCJdLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmdNYXAoRm4ubG9va3VwTmVzdGVkKGNoYW5nZW1lRXh0ZXJuYWxUaHVtYnByaW50RGF0YSwgW1wicmVzdWx0XCIsIFwidGh1bWJwcmludFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHJlc291cmNlIHJlZmVyZW5jZSB3aXRoIG1hcCBhdHRyaWJ1dGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LmZvby5iYXJ9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcHJvdmlkZXI6IGF3c1Byb3ZpZGVyU2NoZW1hLFxuICAgICAgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgICgpID0+IFwic3RyaW5nXCIsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiZm9vXCIsIFwiYmFyXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgY29tcGxleCB2YXJpYWJsZSByZWZlcmVuY2UgaW4gdGVtcGxhdGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7dmFyLmRlZmF1bHRfdGFncy5wcm9qZWN0fS1jbGllbnQtdGdcImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXRcIl0sXG4gICAgICB2YXJpYWJsZXM6IFtcImRlZmF1bHRfdGFnc1wiXSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBcInN0cmluZ1wiLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGRlZmF1bHRUYWdzLnZhbHVlLCBbXCJwcm9qZWN0XCJdKSkgKyBcIi1jbGllbnQtdGdcIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBib29sZWFuIHZhbHVlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtmYWxzZX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gXCJib29sXCIsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiZmFsc2VcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGRhdGEgc291cmNlIHdpdGggY291bnRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3NfYXZhaWxhYmlsaXR5X3pvbmVzLmF2YWlsYWJsZS5uYW1lc1tjb3VudC5pbmRleF19XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcHJvdmlkZXI6IGF3c1Byb3ZpZGVyU2NoZW1hLFxuICAgICAgZGF0YTogW1wiYXdzX2F2YWlsYWJpbGl0eV96b25lc1wiXSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGF2YWlsYWJsZS5uYW1lcywgW1wiXFwke2NvdW50LmluZGV4fVwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJhY2NlcHQgZXNjYXBlZCBxdW90ZXMgd2l0aGluIHN0cmluZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtqc29uZW5jb2RlKHtcbiAgICAgICAgICBcIlN0YXRlbWVudFwiID0gW3tcbiAgICAgICAgICAgIFwiQWN0aW9uXCIgPSBcInMzOipcIixcbiAgICAgICAgICAgIFwiRWZmZWN0XCIgPSBcIkFsbG93XCIsXG4gICAgICAgICAgfV0sXG4gICAgICAgIH0pfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXG4gICAgICBcIlRva2VuLmFzU3RyaW5nKEZuLmpzb25lbmNvZGUoe1xuICAgICAgICBcIlN0YXRlbWVudFwiOiBbe1xuICAgICAgICAgIFwiQWN0aW9uXCI6IFwiczM6KlwiLFxuICAgICAgICAgIFwiRWZmZWN0XCI6IFwiQWxsb3dcIlxuICAgICAgICB9XVxuICAgICAgfSkpXCJcbiAgICBgKTtcbiAgfSk7XG5cbiAgdGVzdChcInN1cHBvcnQgdmFyaWFkaWMgcGFyYW1ldGVycyBpbiBhbnkgcG9zaXRpb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7Y2lkcnN1Ym5ldHMoXCJmZDAwOmZkMTI6MzQ1Njo3ODkwOjovNTZcIiwgMTYsIDE2LCAxNiwgMzIpfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuXG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uY2lkcnN1Ym5ldHMoXCJmZDAwOmZkMTI6MzQ1Njo3ODkwOjovNTZcIiwgWzE2LCAxNiwgMTYsIDMyXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyB0ZW1wbGF0ZSBleHByZXNzaW9uIHdpdGggZXNjYXBlZCAke30gZXhwcmVzc2lvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9ICdbXCIkJHtwYXRoOm5hbWUuZ2l2ZW5OYW1lfVwiXSc7IC8vIGZyb20gYXdzX3Nzb2FkbWluX2luc3RhbmNlX2FjY2Vzc19jb250cm9sX2F0dHJpYnV0ZXMgZXhhbXBsZVxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG5cbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJbXCIkXFwke3BhdGg6bmFtZS5naXZlbk5hbWV9XCJdXCJgLFxuICAgICk7XG4gIH0pO1xufSk7XG4iXX0=
|