@cdktn/commons 0.25.0-pre.53 → 0.25.0-pre.54
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/build/config.d.ts +5 -0
- package/build/config.d.ts.map +1 -1
- package/build/config.js +26 -1
- package/build/config.test.js +23 -1
- package/build/construct-maker-target.d.ts +2 -0
- package/build/construct-maker-target.d.ts.map +1 -1
- package/build/construct-maker-target.js +3 -1
- package/build/debug.js +11 -11
- package/build/debug.test.js +9 -2
- package/build/errors.d.ts +3 -0
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js +31 -23
- package/build/errors.test.d.ts +2 -0
- package/build/errors.test.d.ts.map +1 -0
- package/build/errors.test.js +24 -0
- package/build/identity.d.ts +3 -0
- package/build/identity.d.ts.map +1 -0
- package/build/identity.js +88 -0
- package/build/index.d.ts +2 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -2
- package/build/process-state.d.ts +2 -0
- package/build/process-state.d.ts.map +1 -0
- package/build/process-state.js +15 -0
- package/build/telemetry.d.ts +24 -0
- package/build/telemetry.d.ts.map +1 -0
- package/build/telemetry.js +721 -0
- package/build/telemetry.test.d.ts +2 -0
- package/build/telemetry.test.d.ts.map +1 -0
- package/build/telemetry.test.js +1501 -0
- package/build/terraform.d.ts +10 -1
- package/build/terraform.d.ts.map +1 -1
- package/build/terraform.js +43 -8
- package/build/terraform.test.d.ts +2 -0
- package/build/terraform.test.d.ts.map +1 -0
- package/build/terraform.test.js +136 -0
- package/package.json +3 -3
- package/build/checkpoint.d.ts +0 -19
- package/build/checkpoint.d.ts.map +0 -1
- package/build/checkpoint.js +0 -185
|
@@ -0,0 +1,1501 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
// Copyright (c) HashiCorp, Inc
|
|
37
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
38
|
+
const Sentry = __importStar(require("@sentry/node"));
|
|
39
|
+
const fs = __importStar(require("fs-extra"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const telemetry_1 = require("./telemetry");
|
|
43
|
+
const terraform_1 = require("./terraform");
|
|
44
|
+
const config_1 = require("./config");
|
|
45
|
+
const construct_maker_target_1 = require("./construct-maker-target");
|
|
46
|
+
const errors_1 = require("./errors");
|
|
47
|
+
const DEFAULT_TARGET_VERSIONS_AS_ATTRIBUTES = {
|
|
48
|
+
target_terraform: config_1.DEFAULT_TARGET_VERSIONS.terraform,
|
|
49
|
+
target_opentofu: config_1.DEFAULT_TARGET_VERSIONS.opentofu,
|
|
50
|
+
};
|
|
51
|
+
// Mirrors recordEnvelope in tools/sentry-sink.mjs: an envelope-format change
|
|
52
|
+
// is fixed in both.
|
|
53
|
+
function parseMetricItems(envelopeBodies) {
|
|
54
|
+
const items = [];
|
|
55
|
+
for (const body of envelopeBodies) {
|
|
56
|
+
const lines = body.split("\n").filter(Boolean);
|
|
57
|
+
for (let i = 0; i < lines.length - 1; i++) {
|
|
58
|
+
let header;
|
|
59
|
+
try {
|
|
60
|
+
header = JSON.parse(lines[i]);
|
|
61
|
+
}
|
|
62
|
+
catch (_a) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (header.type === "trace_metric") {
|
|
66
|
+
const payload = JSON.parse(lines[i + 1]);
|
|
67
|
+
items.push(...payload.items);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return items;
|
|
72
|
+
}
|
|
73
|
+
function attributeValues(item) {
|
|
74
|
+
return Object.fromEntries(Object.entries(item.attributes).map(([k, v]) => [k, v.value]));
|
|
75
|
+
}
|
|
76
|
+
// On every metric of a command; the exact set is pinned once, on
|
|
77
|
+
// cli.command.completed.
|
|
78
|
+
const COMMAND_ATTRIBUTES = [
|
|
79
|
+
"arch",
|
|
80
|
+
"binary",
|
|
81
|
+
"binary_version",
|
|
82
|
+
"ci",
|
|
83
|
+
"command",
|
|
84
|
+
"language",
|
|
85
|
+
"os",
|
|
86
|
+
"package_manager",
|
|
87
|
+
"server.address",
|
|
88
|
+
"target_opentofu",
|
|
89
|
+
"target_terraform",
|
|
90
|
+
"targets_declared",
|
|
91
|
+
"validate_installed_binary",
|
|
92
|
+
];
|
|
93
|
+
// Each metric of that name as its value plus exactly the attributes it adds
|
|
94
|
+
// to the command's, so `toEqual` fails on any attribute that is not listed.
|
|
95
|
+
function metrics(items, name) {
|
|
96
|
+
return items
|
|
97
|
+
.filter((item) => item.name === name)
|
|
98
|
+
.map((item) => ({
|
|
99
|
+
value: item.value,
|
|
100
|
+
...Object.fromEntries(Object.entries(attributeValues(item)).filter(([key]) => !key.startsWith("sentry.") && !COMMAND_ATTRIBUTES.includes(key))),
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
describe("telemetry", () => {
|
|
104
|
+
let workdir;
|
|
105
|
+
let envelopeBodies;
|
|
106
|
+
const originalCwd = process.cwd();
|
|
107
|
+
const originalCheckpointDisable = process.env.CHECKPOINT_DISABLE;
|
|
108
|
+
const originalSentryEnvironment = process.env.SENTRY_ENVIRONMENT;
|
|
109
|
+
function initSentryWithCapturingTransport() {
|
|
110
|
+
Sentry.init({
|
|
111
|
+
dsn: "https://public@example.invalid/1",
|
|
112
|
+
release: "cdktn-cli-test",
|
|
113
|
+
environment: "production",
|
|
114
|
+
tracesSampleRate: 0,
|
|
115
|
+
serverName: "cdktn-cli",
|
|
116
|
+
// each test inits its own client; process-level integrations would
|
|
117
|
+
// pile up listeners across tests and are irrelevant to metrics
|
|
118
|
+
defaultIntegrations: false,
|
|
119
|
+
transport: (options) => Sentry.createTransport(options, async (request) => {
|
|
120
|
+
envelopeBodies.push(request.body);
|
|
121
|
+
return { statusCode: 200 };
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async function deliveredItems() {
|
|
126
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
127
|
+
return parseMetricItems(envelopeBodies);
|
|
128
|
+
}
|
|
129
|
+
beforeEach(() => {
|
|
130
|
+
workdir = fs.mkdtempSync(path.join(os.tmpdir(), "cdktn-telemetry-"));
|
|
131
|
+
process.chdir(workdir);
|
|
132
|
+
envelopeBodies = [];
|
|
133
|
+
delete process.env.CHECKPOINT_DISABLE;
|
|
134
|
+
delete process.env.SENTRY_ENVIRONMENT;
|
|
135
|
+
// the probe is process-global (see terraform.ts); a seeded output keeps
|
|
136
|
+
// the binary attributes independent of the machine running the tests
|
|
137
|
+
(0, terraform_1.seedTerraformCliProbeForTests)(Promise.resolve("Terraform v1.9.0\non darwin_arm64\n"));
|
|
138
|
+
});
|
|
139
|
+
afterEach(async () => {
|
|
140
|
+
(0, telemetry_1.setUsageTelemetryEnabled)(undefined);
|
|
141
|
+
(0, telemetry_1.resetCommandTelemetry)();
|
|
142
|
+
(0, telemetry_1.setProjectTargetAttributes)(undefined);
|
|
143
|
+
(0, terraform_1.seedTerraformCliProbeForTests)();
|
|
144
|
+
await Sentry.close(1000);
|
|
145
|
+
process.chdir(originalCwd);
|
|
146
|
+
fs.removeSync(workdir);
|
|
147
|
+
if (originalCheckpointDisable === undefined) {
|
|
148
|
+
delete process.env.CHECKPOINT_DISABLE;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
process.env.CHECKPOINT_DISABLE = originalCheckpointDisable;
|
|
152
|
+
}
|
|
153
|
+
if (originalSentryEnvironment === undefined) {
|
|
154
|
+
delete process.env.SENTRY_ENVIRONMENT;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
process.env.SENTRY_ENVIRONMENT = originalSentryEnvironment;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
describe("sendTelemetry delivery (real client + capturing transport)", () => {
|
|
161
|
+
it("stamps the command, language, binary and target attributes on every command metric", async () => {
|
|
162
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
163
|
+
language: "typescript",
|
|
164
|
+
sendUsageTelemetry: true,
|
|
165
|
+
targetVersions: { terraform: ">=1.9.0", opentofu: ">=1.8.0" },
|
|
166
|
+
validateInstalledBinary: true,
|
|
167
|
+
});
|
|
168
|
+
initSentryWithCapturingTransport();
|
|
169
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
170
|
+
await (0, telemetry_1.sendTelemetry)("synth", { totalTime: 1234, language: "typescript" });
|
|
171
|
+
await (0, telemetry_1.sendTelemetry)("synth", { error: true, synthOrigin: "watch" });
|
|
172
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
173
|
+
const items = parseMetricItems(envelopeBodies);
|
|
174
|
+
expect(items.map((i) => i.name)).toEqual([
|
|
175
|
+
"cli.command.invoked",
|
|
176
|
+
"cli.command.completed",
|
|
177
|
+
"cli.synth.duration",
|
|
178
|
+
"cli.command.error",
|
|
179
|
+
]);
|
|
180
|
+
const [invoked, completed, duration, error] = items;
|
|
181
|
+
for (const metric of items) {
|
|
182
|
+
expect(attributeValues(metric)).toMatchObject({
|
|
183
|
+
command: "synth",
|
|
184
|
+
os: process.platform,
|
|
185
|
+
arch: process.arch,
|
|
186
|
+
binary: "terraform",
|
|
187
|
+
binary_version: "1.9.0",
|
|
188
|
+
target_terraform: ">=1.9.0",
|
|
189
|
+
target_opentofu: ">=1.8.0",
|
|
190
|
+
targets_declared: true,
|
|
191
|
+
validate_installed_binary: true,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// the language comes from cdktf.json at start and from the payload
|
|
195
|
+
// at the end; the error metric has no payload and reuses the start read
|
|
196
|
+
expect(attributeValues(invoked).language).toBe("typescript");
|
|
197
|
+
expect(attributeValues(completed).language).toBe("typescript");
|
|
198
|
+
expect(duration.type).toBe("distribution");
|
|
199
|
+
expect(duration.value).toBe(1234);
|
|
200
|
+
expect(attributeValues(error)).toMatchObject({
|
|
201
|
+
error_type: "unexpected",
|
|
202
|
+
language: "typescript",
|
|
203
|
+
synth_origin: "watch",
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
it("uses the target attributes captured at command start over the current cwd", async () => {
|
|
207
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
208
|
+
targetVersions: { terraform: ">=1.0.0" },
|
|
209
|
+
});
|
|
210
|
+
initSentryWithCapturingTransport();
|
|
211
|
+
(0, telemetry_1.setProjectTargetAttributes)({
|
|
212
|
+
targets_declared: true,
|
|
213
|
+
validate_installed_binary: false,
|
|
214
|
+
target_opentofu: ">=1.7.0",
|
|
215
|
+
});
|
|
216
|
+
await (0, telemetry_1.startCommandTelemetry)("convert");
|
|
217
|
+
await (0, telemetry_1.sendTelemetry)("convert", {});
|
|
218
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
219
|
+
const items = parseMetricItems(envelopeBodies);
|
|
220
|
+
expect(items.map((i) => i.name)).toEqual([
|
|
221
|
+
"cli.command.invoked",
|
|
222
|
+
"cli.command.completed",
|
|
223
|
+
]);
|
|
224
|
+
for (const metric of items) {
|
|
225
|
+
expect(metric.attributes.target_opentofu.value).toBe(">=1.7.0");
|
|
226
|
+
expect(metric.attributes.target_terraform).toBeUndefined();
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
it.each([
|
|
230
|
+
["Usage", "Usage"],
|
|
231
|
+
["External", "External"],
|
|
232
|
+
["Internal", "Internal"],
|
|
233
|
+
["Something Else", "unexpected"],
|
|
234
|
+
])("stamps error_type %p as %p on cli.command.error", async (errorType, expected) => {
|
|
235
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
236
|
+
sendUsageTelemetry: true,
|
|
237
|
+
});
|
|
238
|
+
initSentryWithCapturingTransport();
|
|
239
|
+
await (0, telemetry_1.sendTelemetry)("deploy", { error: true, errorType });
|
|
240
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
241
|
+
const error = parseMetricItems(envelopeBodies).find((i) => i.name === "cli.command.error");
|
|
242
|
+
expect(error.attributes.error_type.value).toBe(expected);
|
|
243
|
+
expect(error.attributes.command.value).toBe("deploy");
|
|
244
|
+
});
|
|
245
|
+
it("forwards exactly the allow-listed attribute set and nothing else from the payload", async () => {
|
|
246
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
247
|
+
language: "typescript",
|
|
248
|
+
sendUsageTelemetry: true,
|
|
249
|
+
});
|
|
250
|
+
initSentryWithCapturingTransport();
|
|
251
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
252
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
253
|
+
totalTime: 5,
|
|
254
|
+
language: "typescript",
|
|
255
|
+
synthOrigin: "watch",
|
|
256
|
+
stackMetadata: [{ stackName: "prod-vpc", backend: "s3" }],
|
|
257
|
+
requiredProviders: [{ aws: { source: "aws" } }],
|
|
258
|
+
stackName: "prod-vpc",
|
|
259
|
+
outdir: "/Users/x/secret",
|
|
260
|
+
resources: { aws: { secret_resource: 3 } },
|
|
261
|
+
});
|
|
262
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
263
|
+
const items = parseMetricItems(envelopeBodies);
|
|
264
|
+
const invoked = items.find((i) => i.name === "cli.command.invoked");
|
|
265
|
+
const completed = items.find((i) => i.name === "cli.command.completed");
|
|
266
|
+
const keys = Object.keys(completed.attributes);
|
|
267
|
+
// the start metric carries the base set; the end-of-run scalars ride
|
|
268
|
+
// on completed only
|
|
269
|
+
expect(Object.keys(invoked.attributes).sort()).toEqual(keys.filter((key) => key !== "synth_origin").sort());
|
|
270
|
+
// the one place that fails when an attribute is added: extend it
|
|
271
|
+
// deliberately, together with the collected-data list in the docs
|
|
272
|
+
expect(keys.filter((key) => !key.startsWith("sentry.")).sort()).toEqual([
|
|
273
|
+
"arch",
|
|
274
|
+
"binary",
|
|
275
|
+
"binary_version",
|
|
276
|
+
"ci",
|
|
277
|
+
"command",
|
|
278
|
+
"language",
|
|
279
|
+
"os",
|
|
280
|
+
"package_manager",
|
|
281
|
+
// server.address is the fixed serverName from init
|
|
282
|
+
"server.address",
|
|
283
|
+
"synth_origin",
|
|
284
|
+
"target_opentofu",
|
|
285
|
+
"target_terraform",
|
|
286
|
+
"targets_declared",
|
|
287
|
+
"validate_installed_binary",
|
|
288
|
+
]);
|
|
289
|
+
// stamped by the SDK from init; a patch bump may add more of them
|
|
290
|
+
expect(keys).toEqual(expect.arrayContaining(["sentry.release", "sentry.environment"]));
|
|
291
|
+
const bytes = envelopeBodies.join("\n");
|
|
292
|
+
expect(bytes).not.toContain("prod-vpc");
|
|
293
|
+
expect(bytes).not.toContain("/Users/x/secret");
|
|
294
|
+
expect(bytes).not.toContain("secret_resource");
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
describe("sendTelemetry payload mapping", () => {
|
|
298
|
+
beforeEach(() => {
|
|
299
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
300
|
+
sendUsageTelemetry: true,
|
|
301
|
+
});
|
|
302
|
+
initSentryWithCapturingTransport();
|
|
303
|
+
});
|
|
304
|
+
it("counts get targets per normalized provider/module and puts only totals on the command metric", async () => {
|
|
305
|
+
const provider = (constraint) => new construct_maker_target_1.ConstructsMakerProviderTarget(new config_1.TerraformProviderConstraint(constraint), config_1.Language.TYPESCRIPT).trackingPayload;
|
|
306
|
+
const module = (constraint) => new construct_maker_target_1.ConstructsMakerModuleTarget(new config_1.TerraformModuleConstraint(constraint), config_1.Language.TYPESCRIPT).trackingPayload;
|
|
307
|
+
await (0, telemetry_1.sendTelemetry)("get", {
|
|
308
|
+
targets: [
|
|
309
|
+
provider("registry.terraform.io/hashicorp/aws@~> 5.0"),
|
|
310
|
+
provider("Hashicorp/AWS@~> 6.0"),
|
|
311
|
+
provider("Kreuzwerker/Docker"),
|
|
312
|
+
module("terraform-aws-modules/vpc/aws@5.0.0"),
|
|
313
|
+
module("./modules/secret-name"),
|
|
314
|
+
],
|
|
315
|
+
});
|
|
316
|
+
const items = await deliveredItems();
|
|
317
|
+
const totals = { provider_count: 3, module_count: 2 };
|
|
318
|
+
expect(metrics(items, "cli.command.completed")).toEqual([
|
|
319
|
+
{ value: 1, ...totals },
|
|
320
|
+
]);
|
|
321
|
+
expect(metrics(items, "cli.get.provider")).toEqual([
|
|
322
|
+
{ value: 2, provider: "hashicorp/aws", ...totals },
|
|
323
|
+
{ value: 1, provider: "kreuzwerker/docker", ...totals },
|
|
324
|
+
]);
|
|
325
|
+
expect(metrics(items, "cli.get.module")).toEqual([
|
|
326
|
+
{ value: 1, module: "local", ...totals },
|
|
327
|
+
{ value: 1, module: "terraform-aws-modules/vpc/aws", ...totals },
|
|
328
|
+
]);
|
|
329
|
+
expect(envelopeBodies.join("\n")).not.toContain("secret-name");
|
|
330
|
+
});
|
|
331
|
+
it("counts init providers per normalized provider and puts only the total on the command metric", async () => {
|
|
332
|
+
await (0, telemetry_1.sendTelemetry)("init", {
|
|
333
|
+
projectId: "should-not-be-sent",
|
|
334
|
+
addedProviders: [
|
|
335
|
+
"aws@~>5.0",
|
|
336
|
+
"hashicorp/random",
|
|
337
|
+
"registry.terraform.io/hashicorp/aws",
|
|
338
|
+
],
|
|
339
|
+
});
|
|
340
|
+
const items = await deliveredItems();
|
|
341
|
+
expect(metrics(items, "cli.command.completed")).toEqual([
|
|
342
|
+
{ value: 1, provider_count: 3 },
|
|
343
|
+
]);
|
|
344
|
+
expect(metrics(items, "cli.init.provider")).toEqual([
|
|
345
|
+
{ value: 2, provider: "hashicorp/aws", provider_count: 3 },
|
|
346
|
+
{ value: 1, provider: "hashicorp/random", provider_count: 3 },
|
|
347
|
+
]);
|
|
348
|
+
expect(envelopeBodies.join("\n")).not.toContain("should-not-be-sent");
|
|
349
|
+
});
|
|
350
|
+
it.each([
|
|
351
|
+
[
|
|
352
|
+
"get",
|
|
353
|
+
(sources) => ({
|
|
354
|
+
targets: sources.map((source) => ({ type: "provider", source })),
|
|
355
|
+
}),
|
|
356
|
+
"cli.get.provider",
|
|
357
|
+
{ provider_count: 40, module_count: 0 },
|
|
358
|
+
],
|
|
359
|
+
[
|
|
360
|
+
"init",
|
|
361
|
+
(sources) => ({ addedProviders: sources }),
|
|
362
|
+
"cli.init.provider",
|
|
363
|
+
{ provider_count: 40 },
|
|
364
|
+
],
|
|
365
|
+
])("%s folds the providers past 32 into one truncated count", async (command, payload, metric, totals) => {
|
|
366
|
+
const sources = Array.from({ length: 40 }, (_, k) => `acme/p${String(k).padStart(2, "0")}`);
|
|
367
|
+
await (0, telemetry_1.sendTelemetry)(command, payload([...sources].reverse()));
|
|
368
|
+
const items = await deliveredItems();
|
|
369
|
+
expect(metrics(items, metric)).toEqual([
|
|
370
|
+
...sources
|
|
371
|
+
.slice(0, 32)
|
|
372
|
+
.map((provider) => ({ value: 1, provider, ...totals })),
|
|
373
|
+
{ value: 8, truncated: true, ...totals },
|
|
374
|
+
]);
|
|
375
|
+
expect(metrics(items, "cli.command.completed")).toEqual([
|
|
376
|
+
{ value: 1, ...totals },
|
|
377
|
+
]);
|
|
378
|
+
});
|
|
379
|
+
it("counts the run as completed even when a per-source metric cannot be built", async () => {
|
|
380
|
+
await (0, telemetry_1.sendTelemetry)("get", {
|
|
381
|
+
targets: [null, { type: "provider", source: 7 }],
|
|
382
|
+
});
|
|
383
|
+
const items = await deliveredItems();
|
|
384
|
+
expect(metrics(items, "cli.command.completed")).toEqual([
|
|
385
|
+
{ value: 1, provider_count: 1, module_count: 0 },
|
|
386
|
+
]);
|
|
387
|
+
expect(metrics(items, "cli.get.provider")).toEqual([]);
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
describe("stack metrics", () => {
|
|
391
|
+
// one JSON-synthesized stack the way the library writes it: metadata
|
|
392
|
+
// carries the stack name and resource ids (imports/moved), overrides
|
|
393
|
+
// are keyed by schema type, module overrides by source
|
|
394
|
+
const stackMetadata = [
|
|
395
|
+
{
|
|
396
|
+
version: "0.21.0",
|
|
397
|
+
stackName: "SECRET-STACK-NAME",
|
|
398
|
+
backend: "s3",
|
|
399
|
+
overrides: {
|
|
400
|
+
stack: ["terraform.required_version"],
|
|
401
|
+
aws_s3_bucket: ["tags", "region"],
|
|
402
|
+
"module.../secret-path/vpc": ["providers"],
|
|
403
|
+
},
|
|
404
|
+
imports: { aws_s3_bucket: ["secret-resource-id"] },
|
|
405
|
+
moved: {
|
|
406
|
+
aws_s3_bucket: ["secret-resource-id"],
|
|
407
|
+
aws_iam_role: ["secret-resource-id"],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
version: "0.21.0",
|
|
412
|
+
stackName: "SECRET-STACK-NAME-2",
|
|
413
|
+
backend: "remote",
|
|
414
|
+
cloud: "tfc",
|
|
415
|
+
},
|
|
416
|
+
];
|
|
417
|
+
const requiredProviders = [
|
|
418
|
+
{
|
|
419
|
+
aws: { source: "aws", version: "~> 5.0" },
|
|
420
|
+
docker: {
|
|
421
|
+
source: "registry.terraform.io/kreuzwerker/docker",
|
|
422
|
+
version: "3.0.2",
|
|
423
|
+
},
|
|
424
|
+
google: { source: "hashicorp/google", version: "x".repeat(100) },
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
random: { source: "hashicorp/random" },
|
|
428
|
+
vault: {
|
|
429
|
+
source: "tfe.corp.example.com/acme-org/vault",
|
|
430
|
+
version: "~> 3.0",
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
];
|
|
434
|
+
const noCounts = { override_count: 0, import_count: 0, moved_count: 0 };
|
|
435
|
+
beforeEach(() => {
|
|
436
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
437
|
+
sendUsageTelemetry: true,
|
|
438
|
+
terraformProviders: [
|
|
439
|
+
"aws@~>5.0",
|
|
440
|
+
{ name: "docker", source: "kreuzwerker/docker", version: "3.0.2" },
|
|
441
|
+
],
|
|
442
|
+
});
|
|
443
|
+
initSentryWithCapturingTransport();
|
|
444
|
+
});
|
|
445
|
+
it("delivers no stack, provider or override metric when the project opts out", async () => {
|
|
446
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
447
|
+
sendUsageTelemetry: false,
|
|
448
|
+
});
|
|
449
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
450
|
+
language: "typescript",
|
|
451
|
+
stackMetadata,
|
|
452
|
+
requiredProviders,
|
|
453
|
+
failedStackCount: 0,
|
|
454
|
+
});
|
|
455
|
+
expect(await deliveredItems()).toEqual([]);
|
|
456
|
+
});
|
|
457
|
+
it("counts stacks by backend, cloud and library version with their group sizes", async () => {
|
|
458
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
459
|
+
language: "typescript",
|
|
460
|
+
stackMetadata,
|
|
461
|
+
requiredProviders,
|
|
462
|
+
failedStackCount: 0,
|
|
463
|
+
});
|
|
464
|
+
const items = await deliveredItems();
|
|
465
|
+
expect(metrics(items, "cli.stack")).toEqual([
|
|
466
|
+
{
|
|
467
|
+
value: 1,
|
|
468
|
+
backend: "remote",
|
|
469
|
+
cloud: true,
|
|
470
|
+
library_version: "0.21.0",
|
|
471
|
+
...noCounts,
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
value: 1,
|
|
475
|
+
backend: "s3",
|
|
476
|
+
cloud: false,
|
|
477
|
+
library_version: "0.21.0",
|
|
478
|
+
override_count: 4,
|
|
479
|
+
import_count: 1,
|
|
480
|
+
moved_count: 2,
|
|
481
|
+
},
|
|
482
|
+
]);
|
|
483
|
+
for (const stack of items.filter((i) => i.name === "cli.stack")) {
|
|
484
|
+
expect(attributeValues(stack)).toMatchObject({
|
|
485
|
+
command: "deploy",
|
|
486
|
+
language: "typescript",
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
expect(items.some((i) => i.name === "cli.stack.failed")).toBe(false);
|
|
490
|
+
expect(items.some((i) => i.name === "cli.command.completed")).toBe(true);
|
|
491
|
+
});
|
|
492
|
+
it("counts overrides per resource type, reducing module sources to their kind", async () => {
|
|
493
|
+
await (0, telemetry_1.sendTelemetry)("synth", { stackMetadata, requiredProviders });
|
|
494
|
+
expect(metrics(await deliveredItems(), "cli.stack.override")).toEqual([
|
|
495
|
+
{ value: 1, resource_type: "aws_s3_bucket", override_count: 2 },
|
|
496
|
+
{ value: 1, resource_type: "module.local", override_count: 1 },
|
|
497
|
+
{ value: 1, resource_type: "stack", override_count: 1 },
|
|
498
|
+
]);
|
|
499
|
+
});
|
|
500
|
+
it("counts required providers by normalized source, validated constraint and binding", async () => {
|
|
501
|
+
await (0, telemetry_1.sendTelemetry)("diff", { stackMetadata, requiredProviders });
|
|
502
|
+
expect(metrics(await deliveredItems(), "cli.stack.provider")).toEqual([
|
|
503
|
+
{
|
|
504
|
+
value: 1,
|
|
505
|
+
provider: "hashicorp/aws",
|
|
506
|
+
version_constraint: "~> 5.0",
|
|
507
|
+
binding: "generated",
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
value: 1,
|
|
511
|
+
provider: "hashicorp/google",
|
|
512
|
+
version_constraint: "invalid",
|
|
513
|
+
binding: "prebuilt",
|
|
514
|
+
},
|
|
515
|
+
{ value: 1, provider: "hashicorp/random", binding: "prebuilt" },
|
|
516
|
+
{
|
|
517
|
+
value: 1,
|
|
518
|
+
provider: "kreuzwerker/docker",
|
|
519
|
+
version_constraint: "3.0.2",
|
|
520
|
+
binding: "generated",
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
value: 1,
|
|
524
|
+
provider: "private-registry",
|
|
525
|
+
version_constraint: "~> 3.0",
|
|
526
|
+
binding: "prebuilt",
|
|
527
|
+
},
|
|
528
|
+
]);
|
|
529
|
+
});
|
|
530
|
+
it("classifies bindings against the project the command started in, not the current cwd", async () => {
|
|
531
|
+
await (0, telemetry_1.startCommandTelemetry)("diff");
|
|
532
|
+
const elsewhere = path.join(workdir, "elsewhere");
|
|
533
|
+
fs.mkdirSync(elsewhere);
|
|
534
|
+
fs.writeJsonSync(path.join(elsewhere, "cdktf.json"), {
|
|
535
|
+
terraformProviders: ["google"],
|
|
536
|
+
});
|
|
537
|
+
process.chdir(elsewhere);
|
|
538
|
+
await (0, telemetry_1.sendTelemetry)("diff", { stackMetadata, requiredProviders });
|
|
539
|
+
expect(metrics(await deliveredItems(), "cli.stack.provider").map((p) => [
|
|
540
|
+
p.provider,
|
|
541
|
+
p.binding,
|
|
542
|
+
])).toEqual([
|
|
543
|
+
["hashicorp/aws", "generated"],
|
|
544
|
+
["hashicorp/google", "prebuilt"],
|
|
545
|
+
["hashicorp/random", "prebuilt"],
|
|
546
|
+
["kreuzwerker/docker", "generated"],
|
|
547
|
+
["private-registry", "prebuilt"],
|
|
548
|
+
]);
|
|
549
|
+
});
|
|
550
|
+
it.each([3, 300])("sends the same stack events for %d alike stacks, with the stack count as their value", async (count) => {
|
|
551
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
552
|
+
stackMetadata: Array.from({ length: count }, (_, i) => ({
|
|
553
|
+
version: "0.21.0",
|
|
554
|
+
stackName: `stack-${i}`,
|
|
555
|
+
backend: "s3",
|
|
556
|
+
overrides: { aws_s3_bucket: ["tags"] },
|
|
557
|
+
})),
|
|
558
|
+
requiredProviders: Array.from({ length: count }, () => ({
|
|
559
|
+
aws: { source: "aws", version: "~> 5.0" },
|
|
560
|
+
random: { source: "hashicorp/random" },
|
|
561
|
+
})),
|
|
562
|
+
});
|
|
563
|
+
const items = await deliveredItems();
|
|
564
|
+
expect(metrics(items, "cli.stack")).toEqual([
|
|
565
|
+
{
|
|
566
|
+
value: count,
|
|
567
|
+
backend: "s3",
|
|
568
|
+
cloud: false,
|
|
569
|
+
library_version: "0.21.0",
|
|
570
|
+
override_count: count,
|
|
571
|
+
import_count: 0,
|
|
572
|
+
moved_count: 0,
|
|
573
|
+
},
|
|
574
|
+
]);
|
|
575
|
+
expect(metrics(items, "cli.stack.provider")).toEqual([
|
|
576
|
+
{
|
|
577
|
+
value: count,
|
|
578
|
+
provider: "hashicorp/aws",
|
|
579
|
+
version_constraint: "~> 5.0",
|
|
580
|
+
binding: "generated",
|
|
581
|
+
},
|
|
582
|
+
{ value: count, provider: "hashicorp/random", binding: "prebuilt" },
|
|
583
|
+
]);
|
|
584
|
+
expect(metrics(items, "cli.stack.override")).toEqual([
|
|
585
|
+
{
|
|
586
|
+
value: count,
|
|
587
|
+
resource_type: "aws_s3_bucket",
|
|
588
|
+
override_count: count,
|
|
589
|
+
},
|
|
590
|
+
]);
|
|
591
|
+
});
|
|
592
|
+
it("groups providers on what is sent: spellings and private hosts collapse, constraints do not", async () => {
|
|
593
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
594
|
+
stackMetadata: [{}, {}, {}],
|
|
595
|
+
requiredProviders: [
|
|
596
|
+
{
|
|
597
|
+
aws: { source: "aws", version: "~>5.0" },
|
|
598
|
+
vault: { source: "tfe.leak-one.example/leak-org-one/vault" },
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
aws: { source: "Hashicorp/AWS", version: "~> 5.0" },
|
|
602
|
+
// a stack counts once per group, however many entries reach it
|
|
603
|
+
vault: { source: "registry.leak-two.example/leak-org-two/vault" },
|
|
604
|
+
consul: { source: "mirror.leak-three.example/leak-org-two/consul" },
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
aws: {
|
|
608
|
+
source: "registry.terraform.io/hashicorp/aws",
|
|
609
|
+
version: "~> 5.0",
|
|
610
|
+
},
|
|
611
|
+
aws6: { source: "aws", version: "~> 6.0" },
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
});
|
|
615
|
+
expect(metrics(await deliveredItems(), "cli.stack.provider")).toEqual([
|
|
616
|
+
{
|
|
617
|
+
value: 3,
|
|
618
|
+
provider: "hashicorp/aws",
|
|
619
|
+
version_constraint: "~> 5.0",
|
|
620
|
+
binding: "generated",
|
|
621
|
+
},
|
|
622
|
+
{ value: 2, provider: "private-registry", binding: "prebuilt" },
|
|
623
|
+
{
|
|
624
|
+
value: 1,
|
|
625
|
+
provider: "hashicorp/aws",
|
|
626
|
+
version_constraint: "~> 6.0",
|
|
627
|
+
binding: "generated",
|
|
628
|
+
},
|
|
629
|
+
]);
|
|
630
|
+
expect(envelopeBodies.join("\n")).not.toContain("leak");
|
|
631
|
+
});
|
|
632
|
+
it("sums the group sizes of the stacks in a group and the paths of an override type", async () => {
|
|
633
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
634
|
+
stackMetadata: [
|
|
635
|
+
{
|
|
636
|
+
backend: "local",
|
|
637
|
+
overrides: { aws_s3_bucket: ["a", "b", "c"], "bad key 1": ["x"] },
|
|
638
|
+
imports: { aws_s3_bucket: ["id"] },
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
backend: "local",
|
|
642
|
+
overrides: {
|
|
643
|
+
aws_s3_bucket: ["a"],
|
|
644
|
+
"bad key 2": ["x"],
|
|
645
|
+
"bad key 3": ["x", "y", "z"],
|
|
646
|
+
},
|
|
647
|
+
moved: { aws_s3_bucket: ["id", "id"] },
|
|
648
|
+
},
|
|
649
|
+
],
|
|
650
|
+
});
|
|
651
|
+
const items = await deliveredItems();
|
|
652
|
+
expect(metrics(items, "cli.stack")).toEqual([
|
|
653
|
+
{
|
|
654
|
+
value: 2,
|
|
655
|
+
backend: "local",
|
|
656
|
+
cloud: false,
|
|
657
|
+
override_count: 9,
|
|
658
|
+
import_count: 1,
|
|
659
|
+
moved_count: 2,
|
|
660
|
+
},
|
|
661
|
+
]);
|
|
662
|
+
expect(metrics(items, "cli.stack.override")).toEqual([
|
|
663
|
+
{ value: 2, resource_type: "aws_s3_bucket", override_count: 4 },
|
|
664
|
+
{ value: 2, resource_type: "other", override_count: 5 },
|
|
665
|
+
]);
|
|
666
|
+
});
|
|
667
|
+
it("keeps the 32 most required providers and folds the rest into one truncated count", async () => {
|
|
668
|
+
const sources = Array.from({ length: 40 }, (_, k) => `acme/p${String(k).padStart(2, "0")}`);
|
|
669
|
+
// provider k is required by 40 - k stacks
|
|
670
|
+
const requiredByStack = sources.map((_, stack) => Object.fromEntries(sources
|
|
671
|
+
.slice(0, sources.length - stack)
|
|
672
|
+
.map((source, k) => [`p${k}`, { source }])));
|
|
673
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
674
|
+
stackMetadata: sources.map(() => ({})),
|
|
675
|
+
requiredProviders: requiredByStack,
|
|
676
|
+
});
|
|
677
|
+
const providers = metrics(await deliveredItems(), "cli.stack.provider");
|
|
678
|
+
expect(providers).toEqual([
|
|
679
|
+
...sources.slice(0, 32).map((provider, k) => ({
|
|
680
|
+
value: 40 - k,
|
|
681
|
+
provider,
|
|
682
|
+
binding: "prebuilt",
|
|
683
|
+
})),
|
|
684
|
+
{ value: 36, truncated: true },
|
|
685
|
+
]);
|
|
686
|
+
expect(providers.reduce((total, p) => total + p.value, 0)).toBe(820);
|
|
687
|
+
});
|
|
688
|
+
it("keeps the first 32 override types by name on a tie and folds the rest with their paths", async () => {
|
|
689
|
+
const types = Array.from({ length: 34 }, (_, k) => `aws_t${String(k).padStart(2, "0")}`);
|
|
690
|
+
const longer = {
|
|
691
|
+
aws_t32: ["a", "b"],
|
|
692
|
+
aws_t33: ["a", "b", "c"],
|
|
693
|
+
};
|
|
694
|
+
const paths = (type) => { var _a; return (_a = longer[type]) !== null && _a !== void 0 ? _a : ["a"]; };
|
|
695
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
696
|
+
stackMetadata: [
|
|
697
|
+
{
|
|
698
|
+
overrides: Object.fromEntries([...types].reverse().map((type) => [type, paths(type)])),
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
});
|
|
702
|
+
expect(metrics(await deliveredItems(), "cli.stack.override")).toEqual([
|
|
703
|
+
...types.slice(0, 32).map((resource_type) => ({
|
|
704
|
+
value: 1,
|
|
705
|
+
resource_type,
|
|
706
|
+
override_count: 1,
|
|
707
|
+
})),
|
|
708
|
+
{ value: 2, override_count: 5, truncated: true },
|
|
709
|
+
]);
|
|
710
|
+
});
|
|
711
|
+
it("keeps the 8 largest stack groups and folds the rest with their group sizes", async () => {
|
|
712
|
+
// library version 0.k.0 is used by k + 1 stacks, each with one import
|
|
713
|
+
const stacksOfVersion = (k) => Array.from({ length: k + 1 }, () => ({
|
|
714
|
+
version: `0.${k}.0`,
|
|
715
|
+
backend: "s3",
|
|
716
|
+
imports: { aws_s3_bucket: ["id"] },
|
|
717
|
+
}));
|
|
718
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
719
|
+
stackMetadata: Array.from({ length: 10 }, (_, k) => stacksOfVersion(k)).flat(),
|
|
720
|
+
});
|
|
721
|
+
const stacks = metrics(await deliveredItems(), "cli.stack");
|
|
722
|
+
expect(stacks).toEqual([
|
|
723
|
+
...[9, 8, 7, 6, 5, 4, 3, 2].map((k) => ({
|
|
724
|
+
value: k + 1,
|
|
725
|
+
backend: "s3",
|
|
726
|
+
cloud: false,
|
|
727
|
+
library_version: `0.${k}.0`,
|
|
728
|
+
...noCounts,
|
|
729
|
+
import_count: k + 1,
|
|
730
|
+
})),
|
|
731
|
+
{ value: 3, truncated: true, ...noCounts, import_count: 3 },
|
|
732
|
+
]);
|
|
733
|
+
expect(stacks.reduce((total, s) => total + s.value, 0)).toBe(55);
|
|
734
|
+
});
|
|
735
|
+
it("bounds the stack events of a run whatever the project's shape, in the envelope of the command metric", async () => {
|
|
736
|
+
const forty = Array.from({ length: 40 }, (_, k) => k);
|
|
737
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
738
|
+
stackMetadata: Array.from({ length: 300 }, (_, i) => ({
|
|
739
|
+
version: `1.${i}.0`,
|
|
740
|
+
overrides: Object.fromEntries(forty.map((k) => [`aws_type_${k}`, ["tags"]])),
|
|
741
|
+
})),
|
|
742
|
+
requiredProviders: Array.from({ length: 300 }, () => Object.fromEntries(forty.map((k) => [`p${k}`, { source: `acme/p${k}` }]))),
|
|
743
|
+
});
|
|
744
|
+
const items = await deliveredItems();
|
|
745
|
+
const count = (name) => metrics(items, name).length;
|
|
746
|
+
const total = (name) => metrics(items, name).reduce((sum, m) => sum + m.value, 0);
|
|
747
|
+
expect([
|
|
748
|
+
count("cli.stack"),
|
|
749
|
+
count("cli.stack.provider"),
|
|
750
|
+
count("cli.stack.override"),
|
|
751
|
+
]).toEqual([9, 33, 33]);
|
|
752
|
+
expect(total("cli.stack")).toBe(300);
|
|
753
|
+
expect(total("cli.stack.provider")).toBe(300 * 40);
|
|
754
|
+
expect(count("cli.command.completed")).toBe(1);
|
|
755
|
+
expect(envelopeBodies).toHaveLength(1);
|
|
756
|
+
});
|
|
757
|
+
it("leaves the stacks to the command when its synth is nested: only the selected ones, under its name", async () => {
|
|
758
|
+
await (0, telemetry_1.startCommandTelemetry)("deploy");
|
|
759
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
760
|
+
totalTime: 42,
|
|
761
|
+
stackMetadata,
|
|
762
|
+
requiredProviders,
|
|
763
|
+
});
|
|
764
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
765
|
+
stackMetadata: stackMetadata.slice(1),
|
|
766
|
+
requiredProviders: requiredProviders.slice(1),
|
|
767
|
+
});
|
|
768
|
+
const items = await deliveredItems();
|
|
769
|
+
expect(items
|
|
770
|
+
.filter((i) => i.name.startsWith("cli.stack"))
|
|
771
|
+
.map((i) => [i.name, attributeValues(i).command, i.value])).toEqual([
|
|
772
|
+
["cli.stack", "deploy", 1],
|
|
773
|
+
["cli.stack.provider", "deploy", 1],
|
|
774
|
+
["cli.stack.provider", "deploy", 1],
|
|
775
|
+
]);
|
|
776
|
+
expect(items.some((i) => i.name === "cli.synth.duration" &&
|
|
777
|
+
attributeValues(i).command === "synth")).toBe(true);
|
|
778
|
+
});
|
|
779
|
+
it("reports the stacks of a synth run under synth", async () => {
|
|
780
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
781
|
+
await (0, telemetry_1.sendTelemetry)("synth", { stackMetadata, requiredProviders });
|
|
782
|
+
const stacks = (await deliveredItems()).filter((i) => i.name === "cli.stack");
|
|
783
|
+
expect(stacks.map((i) => attributeValues(i).command)).toEqual([
|
|
784
|
+
"synth",
|
|
785
|
+
"synth",
|
|
786
|
+
]);
|
|
787
|
+
});
|
|
788
|
+
it("reports the stacks once per process: a watch session's later deploys add only their failures", async () => {
|
|
789
|
+
await (0, telemetry_1.startCommandTelemetry)("watch");
|
|
790
|
+
await (0, telemetry_1.sendTelemetry)("deploy", { stackMetadata, requiredProviders });
|
|
791
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
792
|
+
stackMetadata,
|
|
793
|
+
requiredProviders,
|
|
794
|
+
failedStackCount: 1,
|
|
795
|
+
});
|
|
796
|
+
const items = await deliveredItems();
|
|
797
|
+
expect(metrics(items, "cli.stack")).toHaveLength(2);
|
|
798
|
+
expect(metrics(items, "cli.stack.provider")).toHaveLength(5);
|
|
799
|
+
expect(metrics(items, "cli.stack.override")).toHaveLength(3);
|
|
800
|
+
expect(metrics(items, "cli.stack.failed")).toEqual([{ value: 1 }]);
|
|
801
|
+
});
|
|
802
|
+
it("counts failed stacks and never serializes their failure messages", async () => {
|
|
803
|
+
await (0, telemetry_1.sendTelemetry)("destroy", {
|
|
804
|
+
stackMetadata,
|
|
805
|
+
requiredProviders,
|
|
806
|
+
failedStackCount: 2,
|
|
807
|
+
failedStacks: ["failed to destroy SECRET-STACK-NAME: /Users/x/state"],
|
|
808
|
+
});
|
|
809
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
810
|
+
const items = parseMetricItems(envelopeBodies);
|
|
811
|
+
const failed = items.find((i) => i.name === "cli.stack.failed");
|
|
812
|
+
expect(failed.value).toBe(2);
|
|
813
|
+
expect(failed.attributes.command.value).toBe("destroy");
|
|
814
|
+
// the failure thrown next is counted as cli.command.error, not here
|
|
815
|
+
expect(items.some((i) => i.name === "cli.command.completed")).toBe(false);
|
|
816
|
+
expect(envelopeBodies.join("\n")).not.toContain("failed to destroy");
|
|
817
|
+
expect(envelopeBodies.join("\n")).not.toContain("/Users/x");
|
|
818
|
+
});
|
|
819
|
+
it("counts no completed run and no failed stack for a run that failed before any stack did", async () => {
|
|
820
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
821
|
+
stackMetadata,
|
|
822
|
+
requiredProviders,
|
|
823
|
+
failedStackCount: 0,
|
|
824
|
+
runFailed: true,
|
|
825
|
+
});
|
|
826
|
+
const items = await deliveredItems();
|
|
827
|
+
expect(metrics(items, "cli.stack")).toHaveLength(2);
|
|
828
|
+
expect(metrics(items, "cli.stack.failed")).toEqual([]);
|
|
829
|
+
expect(items.some((i) => i.name === "cli.command.completed")).toBe(false);
|
|
830
|
+
});
|
|
831
|
+
it("never serializes stack names, resource ids or module paths", async () => {
|
|
832
|
+
await (0, telemetry_1.sendTelemetry)("deploy", {
|
|
833
|
+
language: "typescript",
|
|
834
|
+
stackMetadata,
|
|
835
|
+
requiredProviders,
|
|
836
|
+
failedStackCount: 1,
|
|
837
|
+
});
|
|
838
|
+
const items = await deliveredItems();
|
|
839
|
+
// the scan below is over two stacks, three override types, five
|
|
840
|
+
// providers and the failed count
|
|
841
|
+
expect(items.filter((i) => i.name.startsWith("cli.stack"))).toHaveLength(11);
|
|
842
|
+
const bytes = envelopeBodies.join("\n");
|
|
843
|
+
expect(bytes).not.toContain("SECRET-STACK-NAME");
|
|
844
|
+
expect(bytes).not.toContain("secret-resource-id");
|
|
845
|
+
expect(bytes).not.toContain("secret-path");
|
|
846
|
+
expect(bytes).not.toContain("tfe.corp.example.com");
|
|
847
|
+
expect(bytes).not.toContain("acme-org");
|
|
848
|
+
});
|
|
849
|
+
// the metadata is read from disk, written by whatever library version
|
|
850
|
+
// the project has
|
|
851
|
+
it("tolerates malformed metadata entries and counts only the real stacks", async () => {
|
|
852
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
853
|
+
stackMetadata: [null, "nope", { overrides: "nope", imports: [] }],
|
|
854
|
+
requiredProviders: [undefined, undefined, { aws: "nope" }],
|
|
855
|
+
});
|
|
856
|
+
const items = await deliveredItems();
|
|
857
|
+
expect(metrics(items, "cli.stack")).toEqual([
|
|
858
|
+
{ value: 1, backend: "unknown", cloud: false, ...noCounts },
|
|
859
|
+
]);
|
|
860
|
+
expect(metrics(items, "cli.stack.override")).toEqual([]);
|
|
861
|
+
expect(metrics(items, "cli.stack.provider")).toEqual([
|
|
862
|
+
{ value: 1, provider: "hashicorp/aws", binding: "generated" },
|
|
863
|
+
]);
|
|
864
|
+
expect(items.some((i) => i.name === "cli.command.completed")).toBe(true);
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
describe("attribute validation", () => {
|
|
868
|
+
beforeEach(() => {
|
|
869
|
+
initSentryWithCapturingTransport();
|
|
870
|
+
});
|
|
871
|
+
it("omits an unsupported language, read from cdktf.json at start or passed at the end", async () => {
|
|
872
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
873
|
+
language: "rust; DROP TABLE",
|
|
874
|
+
});
|
|
875
|
+
await (0, telemetry_1.startCommandTelemetry)("convert");
|
|
876
|
+
await (0, telemetry_1.sendTelemetry)("convert", { language: "cobol; DROP TABLE" });
|
|
877
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
878
|
+
const items = parseMetricItems(envelopeBodies);
|
|
879
|
+
expect(items.map((i) => i.name)).toEqual([
|
|
880
|
+
"cli.command.invoked",
|
|
881
|
+
"cli.command.completed",
|
|
882
|
+
]);
|
|
883
|
+
for (const item of items) {
|
|
884
|
+
expect(item.attributes).not.toHaveProperty("language");
|
|
885
|
+
}
|
|
886
|
+
expect(envelopeBodies.join("\n")).not.toContain("DROP TABLE");
|
|
887
|
+
});
|
|
888
|
+
it.each([
|
|
889
|
+
["synth", { synthOrigin: "watch" }, "synth_origin", "watch"],
|
|
890
|
+
["synth", { synthOrigin: "/Users/x" }, "synth_origin", undefined],
|
|
891
|
+
["init", { isRemote: true }, "is_remote", true],
|
|
892
|
+
["init", { template: "go" }, "template", "go"],
|
|
893
|
+
["convert", { numberOfProviders: 2 }, "provider_count", 2],
|
|
894
|
+
["convert", { numberOfModules: 1 }, "module_count", 1],
|
|
895
|
+
["convert", { convertedLines: 42 }, "converted_lines", 42],
|
|
896
|
+
["convert", { convertedLines: "42" }, "converted_lines", undefined],
|
|
897
|
+
["convert", { convertedLines: NaN }, "converted_lines", undefined],
|
|
898
|
+
])("%s: %j forwards %s as %j", async (command, payload, attribute, expected) => {
|
|
899
|
+
await (0, telemetry_1.sendTelemetry)(command, payload);
|
|
900
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
901
|
+
const completed = parseMetricItems(envelopeBodies).find((i) => i.name === "cli.command.completed");
|
|
902
|
+
if (expected === undefined) {
|
|
903
|
+
expect(completed.attributes).not.toHaveProperty(attribute);
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
expect(attributeValues(completed)[attribute]).toBe(expected);
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
it.each([
|
|
910
|
+
[">= 1.9.0", ">=1.9.0"],
|
|
911
|
+
["~1.8", ">=1.8.0 <1.9.0-0"],
|
|
912
|
+
["1.2.3 - 2.0.0", ">=1.2.3 <=2.0.0"],
|
|
913
|
+
[">=1.0.0 <2.0.0 || 1.2.3", ">=1.0.0 <2.0.0||1.2.3"],
|
|
914
|
+
["latest /Users/x", "invalid"],
|
|
915
|
+
[">= 1.0.0-LEAK-TV-PRERELEASE.corp.example.com", "invalid"],
|
|
916
|
+
["1.2.3-acme.internal", "invalid"],
|
|
917
|
+
["1.2.3+LEAK-TV-BUILD.johns-macbook", "invalid"],
|
|
918
|
+
[">=1.0.0 <2.0.0 || 1.2.3-LEAK-OR.host", "invalid"],
|
|
919
|
+
[">=1.0.0 " + "||1.0.0 ".repeat(10), "invalid"],
|
|
920
|
+
])("forwards the declared target %p as %p", (range, expected) => {
|
|
921
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
922
|
+
targetVersions: { terraform: range },
|
|
923
|
+
});
|
|
924
|
+
expect((0, telemetry_1.getProjectTargetAttributes)(workdir).target_terraform).toBe(expected);
|
|
925
|
+
});
|
|
926
|
+
it("reduces a backend outside the built-in kinds and override keys outside the type grammar to other", async () => {
|
|
927
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
928
|
+
stackMetadata: [
|
|
929
|
+
{
|
|
930
|
+
version: "0.21.0+build." + "x".repeat(40),
|
|
931
|
+
backend: "s3 bucket=/Users/x/state",
|
|
932
|
+
overrides: {
|
|
933
|
+
aws_s3_bucket: ["tags"],
|
|
934
|
+
terraform_remote_state: ["backend"],
|
|
935
|
+
"module.terraform-aws-modules/vpc/aws": ["providers"],
|
|
936
|
+
"resource with spaces /Users/x": ["tags"],
|
|
937
|
+
AWS_S3_Bucket: ["tags"],
|
|
938
|
+
["aws_" + "x".repeat(70)]: ["tags"],
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
{ version: "dev-/Users/x", backend: "S3" },
|
|
942
|
+
{ version: "dev-/Users/x" },
|
|
943
|
+
],
|
|
944
|
+
});
|
|
945
|
+
const items = await deliveredItems();
|
|
946
|
+
// build metadata is stripped like binary_version; a version without a
|
|
947
|
+
// MAJOR.MINOR.PATCH prefix yields no attribute at all
|
|
948
|
+
expect(metrics(items, "cli.stack").map((stack) => [
|
|
949
|
+
stack.backend,
|
|
950
|
+
stack.library_version,
|
|
951
|
+
])).toEqual([
|
|
952
|
+
["other", "0.21.0"],
|
|
953
|
+
["other", undefined],
|
|
954
|
+
["unknown", undefined],
|
|
955
|
+
]);
|
|
956
|
+
expect(metrics(items, "cli.stack.override").map((o) => [
|
|
957
|
+
o.resource_type,
|
|
958
|
+
o.override_count,
|
|
959
|
+
])).toEqual([
|
|
960
|
+
["aws_s3_bucket", 1],
|
|
961
|
+
["module.terraform-aws-modules/vpc/aws", 1],
|
|
962
|
+
["other", 3],
|
|
963
|
+
["terraform_remote_state", 1],
|
|
964
|
+
]);
|
|
965
|
+
expect(envelopeBodies.join("\n")).not.toContain("/Users/x");
|
|
966
|
+
});
|
|
967
|
+
});
|
|
968
|
+
describe("provider binding classification", () => {
|
|
969
|
+
beforeEach(() => {
|
|
970
|
+
initSentryWithCapturingTransport();
|
|
971
|
+
});
|
|
972
|
+
async function bindingOf(source) {
|
|
973
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
974
|
+
stackMetadata: [{}],
|
|
975
|
+
requiredProviders: [{ provider: { source } }],
|
|
976
|
+
});
|
|
977
|
+
return metrics(await deliveredItems(), "cli.stack.provider").map((provider) => provider.binding);
|
|
978
|
+
}
|
|
979
|
+
it.each([
|
|
980
|
+
["aws", "generated"],
|
|
981
|
+
["Hashicorp/Random", "generated"],
|
|
982
|
+
["kreuzwerker/docker", "generated"],
|
|
983
|
+
["hashicorp/google", "generated"],
|
|
984
|
+
["azurerm", "generated"],
|
|
985
|
+
["hashicorp/null", "prebuilt"],
|
|
986
|
+
["tfe.corp.example.com/acme-org/vault", "generated"],
|
|
987
|
+
// another private source is not the generated one, even though both
|
|
988
|
+
// reach the metric as "private-registry"
|
|
989
|
+
["tfe.corp.example.com/other-org/vault", "prebuilt"],
|
|
990
|
+
])("sends the required provider %s as %s for the project's terraformProviders", async (source, expected) => {
|
|
991
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
992
|
+
terraformProviders: [
|
|
993
|
+
"aws@~>5.0",
|
|
994
|
+
"hashicorp/random@3.6.0",
|
|
995
|
+
"registry.terraform.io/kreuzwerker/docker",
|
|
996
|
+
{ name: "google", source: "hashicorp/google", version: "~> 5.0" },
|
|
997
|
+
{ name: "azurerm" },
|
|
998
|
+
{ version: "1.0.0" },
|
|
999
|
+
42,
|
|
1000
|
+
"TFE.corp.example.com/acme-org/vault@~>3.0",
|
|
1001
|
+
],
|
|
1002
|
+
});
|
|
1003
|
+
expect(await bindingOf(source)).toEqual([expected]);
|
|
1004
|
+
});
|
|
1005
|
+
it("sends every provider as prebuilt when terraformProviders is not a list", async () => {
|
|
1006
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1007
|
+
terraformProviders: "aws",
|
|
1008
|
+
});
|
|
1009
|
+
expect(await bindingOf("aws")).toEqual(["prebuilt"]);
|
|
1010
|
+
});
|
|
1011
|
+
});
|
|
1012
|
+
describe("source normalization", () => {
|
|
1013
|
+
beforeEach(() => {
|
|
1014
|
+
initSentryWithCapturingTransport();
|
|
1015
|
+
});
|
|
1016
|
+
it.each([
|
|
1017
|
+
["aws", "hashicorp/aws"],
|
|
1018
|
+
["aws@~>5.0", "hashicorp/aws"],
|
|
1019
|
+
["Hashicorp/AWS@5.1.0", "hashicorp/aws"],
|
|
1020
|
+
["registry.terraform.io/hashicorp/aws", "hashicorp/aws"],
|
|
1021
|
+
["registry.opentofu.org/hashicorp/aws", "hashicorp/aws"],
|
|
1022
|
+
["tfe.leak-host.example/leak-org/aws", "private-registry"],
|
|
1023
|
+
["localhost:8080/leak-org/aws", "private-registry"],
|
|
1024
|
+
["./leak-provider", "other"],
|
|
1025
|
+
["../leak/provider", "other"],
|
|
1026
|
+
["/abs/leak/provider", "other"],
|
|
1027
|
+
["leak-a/b/c", "other"],
|
|
1028
|
+
["", "other"],
|
|
1029
|
+
["registry.terraform.io/leak-namespace", "other"],
|
|
1030
|
+
[`${"n".repeat(65)}/aws`, "other"],
|
|
1031
|
+
[`${"n".repeat(64)}/aws`, `${"n".repeat(64)}/aws`],
|
|
1032
|
+
[`${"n".repeat(64)}/${"t".repeat(64)}`, "other"],
|
|
1033
|
+
])("sends the provider source %s as %s", async (source, expected) => {
|
|
1034
|
+
await (0, telemetry_1.sendTelemetry)("get", { targets: [{ type: "provider", source }] });
|
|
1035
|
+
expect(metrics(await deliveredItems(), "cli.get.provider").map((item) => item.provider)).toEqual([expected]);
|
|
1036
|
+
expect(envelopeBodies.join("\n")).not.toContain("leak");
|
|
1037
|
+
});
|
|
1038
|
+
it.each([
|
|
1039
|
+
["terraform-aws-modules/vpc/aws", "terraform-aws-modules/vpc/aws"],
|
|
1040
|
+
["Terraform-AWS-Modules/VPC/aws", "terraform-aws-modules/vpc/aws"],
|
|
1041
|
+
// one row per fallthrough: everything the grammar rejects is "other"
|
|
1042
|
+
["Terraform-AWS-Modules/leak-vpc/aws?ref=v5.0.0", "other"],
|
|
1043
|
+
[`${"n".repeat(64)}/vpc/aws`, `${"n".repeat(64)}/vpc/aws`],
|
|
1044
|
+
[`${"n".repeat(65)}/vpc/aws`, "other"],
|
|
1045
|
+
["app.terraform.io/leak-org/vpc/aws", "private-registry"],
|
|
1046
|
+
["./modules/leak-vpc", "local"],
|
|
1047
|
+
["../shared/leak-vpc", "local"],
|
|
1048
|
+
["/abs/path/leak-vpc", "local"],
|
|
1049
|
+
["git@github.com:leak-org/repo.git", "git"],
|
|
1050
|
+
["github.com/leak-org/repo", "git"],
|
|
1051
|
+
["bitbucket.org/leak-org/repo", "git"],
|
|
1052
|
+
["https://leak-host.example/vpc.zip", "git"],
|
|
1053
|
+
["s3-eu-west-1.amazonaws.com/leak-bucket/vpc.zip", "git"],
|
|
1054
|
+
["www.googleapis.com/storage/v1/leak-bucket/vpc", "git"],
|
|
1055
|
+
// forced getters without a URL scheme behind them
|
|
1056
|
+
["git::leak-host.example/leak-org/repo.git", "git"],
|
|
1057
|
+
["hg::leak-host.example/leak-repo", "git"],
|
|
1058
|
+
["s3::leak-bucket/vpc.zip", "git"],
|
|
1059
|
+
["gcs::leak-bucket/vpc", "git"],
|
|
1060
|
+
])("sends the module source %s as %s", async (source, expected) => {
|
|
1061
|
+
await (0, telemetry_1.sendTelemetry)("get", { targets: [{ type: "module", source }] });
|
|
1062
|
+
expect(metrics(await deliveredItems(), "cli.get.module").map((item) => item.module)).toEqual([expected]);
|
|
1063
|
+
expect(envelopeBodies.join("\n")).not.toContain("leak");
|
|
1064
|
+
});
|
|
1065
|
+
it.each([
|
|
1066
|
+
[">= 1.2, < 2.0", ">= 1.2, < 2.0"],
|
|
1067
|
+
["~> 5.0", "~> 5.0"],
|
|
1068
|
+
["= 1.0", "= 1.0"],
|
|
1069
|
+
["!= 1.2.3", "!= 1.2.3"],
|
|
1070
|
+
["1.2.3", "1.2.3"],
|
|
1071
|
+
[" >= 1.0 , < 2.0 ", ">= 1.0, < 2.0"],
|
|
1072
|
+
["~>5.0,!=5.1.0", "~> 5.0, != 5.1.0"],
|
|
1073
|
+
[">= 1.0.0-leak-prerelease.corp", "invalid"],
|
|
1074
|
+
["1.2.3+leak-build.host", "invalid"],
|
|
1075
|
+
["~> 5.0 # /Users/leak", "invalid"],
|
|
1076
|
+
[">= 1.2 || < 2.0", "invalid"],
|
|
1077
|
+
// valid by the grammar, over the length a constraint may have
|
|
1078
|
+
[Array(12).fill("!= 1.0.0").join(", "), "invalid"],
|
|
1079
|
+
])("sends the provider constraint %p as %p", async (version, expected) => {
|
|
1080
|
+
await (0, telemetry_1.sendTelemetry)("synth", {
|
|
1081
|
+
stackMetadata: [{}],
|
|
1082
|
+
requiredProviders: [{ aws: { source: "aws", version } }],
|
|
1083
|
+
});
|
|
1084
|
+
expect(metrics(await deliveredItems(), "cli.stack.provider").map((provider) => provider.version_constraint)).toEqual([expected]);
|
|
1085
|
+
expect(envelopeBodies.join("\n")).not.toContain("leak");
|
|
1086
|
+
});
|
|
1087
|
+
});
|
|
1088
|
+
describe("package manager", () => {
|
|
1089
|
+
beforeEach(() => {
|
|
1090
|
+
initSentryWithCapturingTransport();
|
|
1091
|
+
});
|
|
1092
|
+
afterEach(() => {
|
|
1093
|
+
jest.dontMock("./node-package-manager");
|
|
1094
|
+
});
|
|
1095
|
+
// a copy of the module whose node detector is replaced
|
|
1096
|
+
function telemetryWithNodeDetector(detect) {
|
|
1097
|
+
let copy;
|
|
1098
|
+
jest.isolateModules(() => {
|
|
1099
|
+
jest.doMock("./node-package-manager", () => ({
|
|
1100
|
+
detectNodePackageManager: detect,
|
|
1101
|
+
}));
|
|
1102
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1103
|
+
copy = require("./telemetry");
|
|
1104
|
+
});
|
|
1105
|
+
return copy;
|
|
1106
|
+
}
|
|
1107
|
+
// one successful and one failed end, so every command metric is covered
|
|
1108
|
+
async function runMetrics(telemetry = { startCommandTelemetry: telemetry_1.startCommandTelemetry, sendTelemetry: telemetry_1.sendTelemetry }) {
|
|
1109
|
+
await telemetry.startCommandTelemetry("synth");
|
|
1110
|
+
await telemetry.sendTelemetry("synth", {});
|
|
1111
|
+
await telemetry.sendTelemetry("synth", { error: true });
|
|
1112
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1113
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1114
|
+
expect(items.map((i) => i.name)).toEqual([
|
|
1115
|
+
"cli.command.invoked",
|
|
1116
|
+
"cli.command.completed",
|
|
1117
|
+
"cli.command.error",
|
|
1118
|
+
]);
|
|
1119
|
+
return items;
|
|
1120
|
+
}
|
|
1121
|
+
it.each([
|
|
1122
|
+
["no lockfile", "npm", {}],
|
|
1123
|
+
["a pnpm lockfile", "pnpm", { "pnpm-lock.yaml": "" }],
|
|
1124
|
+
["a yarn lockfile", "yarn", { "yarn.lock": "" }],
|
|
1125
|
+
["a .yarnrc.yml", "yarn-berry", { ".yarnrc.yml": "" }],
|
|
1126
|
+
[
|
|
1127
|
+
"a declared npm",
|
|
1128
|
+
"npm",
|
|
1129
|
+
{ "package.json": '{"packageManager":"npm@10.8.2"}' },
|
|
1130
|
+
],
|
|
1131
|
+
[
|
|
1132
|
+
"a declared pnpm with a hash",
|
|
1133
|
+
"pnpm",
|
|
1134
|
+
{ "package.json": '{"packageManager":"pnpm@10.26.0+sha512.LEAK"}' },
|
|
1135
|
+
],
|
|
1136
|
+
[
|
|
1137
|
+
"a declared yarn 1",
|
|
1138
|
+
"yarn",
|
|
1139
|
+
{ "package.json": '{"packageManager":"yarn@1.22.22"}' },
|
|
1140
|
+
],
|
|
1141
|
+
[
|
|
1142
|
+
"a declared yarn 4",
|
|
1143
|
+
"yarn-berry",
|
|
1144
|
+
{ "package.json": '{"packageManager":"yarn@4.1.0"}' },
|
|
1145
|
+
],
|
|
1146
|
+
[
|
|
1147
|
+
"an unknown declared manager",
|
|
1148
|
+
"npm",
|
|
1149
|
+
{ "package.json": '{"packageManager":"bun@1.1.0-LEAK"}' },
|
|
1150
|
+
],
|
|
1151
|
+
])("reports a typescript project with %s as %p on every command metric", async (_name, expected, files) => {
|
|
1152
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1153
|
+
language: "typescript",
|
|
1154
|
+
});
|
|
1155
|
+
for (const [name, content] of Object.entries(files)) {
|
|
1156
|
+
fs.writeFileSync(path.join(workdir, name), content);
|
|
1157
|
+
}
|
|
1158
|
+
for (const item of await runMetrics()) {
|
|
1159
|
+
expect(attributeValues(item).package_manager).toBe(expected);
|
|
1160
|
+
}
|
|
1161
|
+
const bytes = envelopeBodies.join("\n");
|
|
1162
|
+
expect(bytes).not.toContain("LEAK");
|
|
1163
|
+
expect(bytes).not.toContain("10.26.0");
|
|
1164
|
+
});
|
|
1165
|
+
it.each([
|
|
1166
|
+
["python", { app: "pipenv run python main.py" }, {}, "pipenv"],
|
|
1167
|
+
["python", { app: "python3 main.py" }, {}, "pip"],
|
|
1168
|
+
["java", {}, { "build.gradle": "" }, "gradle"],
|
|
1169
|
+
["java", {}, { "pom.xml": "" }, "maven"],
|
|
1170
|
+
["csharp", {}, {}, "nuget"],
|
|
1171
|
+
["go", {}, {}, "go"],
|
|
1172
|
+
])("reports a %s project with %j and files %j as %p", async (language, config, files, expected) => {
|
|
1173
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1174
|
+
language,
|
|
1175
|
+
...config,
|
|
1176
|
+
});
|
|
1177
|
+
for (const [name, content] of Object.entries(files)) {
|
|
1178
|
+
fs.writeFileSync(path.join(workdir, name), content);
|
|
1179
|
+
}
|
|
1180
|
+
for (const item of await runMetrics()) {
|
|
1181
|
+
expect(attributeValues(item).package_manager).toBe(expected);
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
it.each([
|
|
1185
|
+
["no cdktf.json", undefined],
|
|
1186
|
+
["an unsupported language", { language: "rust" }],
|
|
1187
|
+
["no language", { app: "pipenv run python main.py" }],
|
|
1188
|
+
["a python project without an app command", { language: "python" }],
|
|
1189
|
+
])("omits the attribute with %s", async (_name, cdktfJson) => {
|
|
1190
|
+
if (cdktfJson) {
|
|
1191
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), cdktfJson);
|
|
1192
|
+
}
|
|
1193
|
+
// lockfiles alone never identify a project
|
|
1194
|
+
fs.writeFileSync(path.join(workdir, "pnpm-lock.yaml"), "");
|
|
1195
|
+
fs.writeFileSync(path.join(workdir, "build.gradle"), "");
|
|
1196
|
+
for (const item of await runMetrics()) {
|
|
1197
|
+
expect(item.attributes).not.toHaveProperty("package_manager");
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
it("keeps the value detected at start when the cwd changes before the end", async () => {
|
|
1201
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1202
|
+
language: "typescript",
|
|
1203
|
+
});
|
|
1204
|
+
fs.writeFileSync(path.join(workdir, "pnpm-lock.yaml"), "");
|
|
1205
|
+
const elsewhere = fs.mkdtempSync(path.join(os.tmpdir(), "cdktn-else-"));
|
|
1206
|
+
try {
|
|
1207
|
+
await (0, telemetry_1.startCommandTelemetry)("convert");
|
|
1208
|
+
process.chdir(elsewhere);
|
|
1209
|
+
await (0, telemetry_1.sendTelemetry)("convert", {});
|
|
1210
|
+
await (0, telemetry_1.sendTelemetry)("convert", { error: true });
|
|
1211
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1212
|
+
}
|
|
1213
|
+
finally {
|
|
1214
|
+
process.chdir(workdir);
|
|
1215
|
+
fs.removeSync(elsewhere);
|
|
1216
|
+
}
|
|
1217
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1218
|
+
expect(items).toHaveLength(3);
|
|
1219
|
+
for (const item of items) {
|
|
1220
|
+
expect(attributeValues(item).package_manager).toBe("pnpm");
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
it("forgets the value with the run", async () => {
|
|
1224
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), { language: "go" });
|
|
1225
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
1226
|
+
(0, telemetry_1.resetCommandTelemetry)();
|
|
1227
|
+
await (0, telemetry_1.sendTelemetry)("synth", {});
|
|
1228
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1229
|
+
const completed = parseMetricItems(envelopeBodies).find((i) => i.name === "cli.command.completed");
|
|
1230
|
+
expect(completed.attributes).not.toHaveProperty("package_manager");
|
|
1231
|
+
});
|
|
1232
|
+
it("omits a detector value outside the closed set", async () => {
|
|
1233
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1234
|
+
language: "typescript",
|
|
1235
|
+
});
|
|
1236
|
+
const telemetry = telemetryWithNodeDetector(() => "bun@1.1.0 /Users/x");
|
|
1237
|
+
for (const item of await runMetrics(telemetry)) {
|
|
1238
|
+
expect(item.attributes).not.toHaveProperty("package_manager");
|
|
1239
|
+
}
|
|
1240
|
+
expect(envelopeBodies.join("\n")).not.toContain("bun");
|
|
1241
|
+
});
|
|
1242
|
+
it("omits the attribute when detection throws", async () => {
|
|
1243
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1244
|
+
language: "typescript",
|
|
1245
|
+
});
|
|
1246
|
+
const telemetry = telemetryWithNodeDetector(() => {
|
|
1247
|
+
throw new Error("EACCES");
|
|
1248
|
+
});
|
|
1249
|
+
for (const item of await runMetrics(telemetry)) {
|
|
1250
|
+
expect(item.attributes).not.toHaveProperty("package_manager");
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
it("normalizes to members of the closed set only", () => {
|
|
1254
|
+
for (const name of telemetry_1.PACKAGE_MANAGERS) {
|
|
1255
|
+
expect((0, telemetry_1.normalizePackageManager)(name)).toBe(name);
|
|
1256
|
+
}
|
|
1257
|
+
for (const value of [
|
|
1258
|
+
"bun",
|
|
1259
|
+
"NPM",
|
|
1260
|
+
"pnpm@10.26.0+sha512.abc",
|
|
1261
|
+
"/usr/local/bin/npm",
|
|
1262
|
+
"",
|
|
1263
|
+
1,
|
|
1264
|
+
null,
|
|
1265
|
+
undefined,
|
|
1266
|
+
["npm"],
|
|
1267
|
+
]) {
|
|
1268
|
+
expect((0, telemetry_1.normalizePackageManager)(value)).toBeUndefined();
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
});
|
|
1272
|
+
describe("run lifecycle", () => {
|
|
1273
|
+
beforeEach(() => {
|
|
1274
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1275
|
+
language: "python",
|
|
1276
|
+
sendUsageTelemetry: true,
|
|
1277
|
+
});
|
|
1278
|
+
initSentryWithCapturingTransport();
|
|
1279
|
+
});
|
|
1280
|
+
it("counts the run once as invoked at start, even when reporting is initialized again", async () => {
|
|
1281
|
+
await (0, telemetry_1.startCommandTelemetry)("init");
|
|
1282
|
+
// init runs get, which initializes reporting a second time
|
|
1283
|
+
await (0, telemetry_1.startCommandTelemetry)("get");
|
|
1284
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1285
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1286
|
+
expect(items.map((i) => i.name)).toEqual(["cli.command.invoked"]);
|
|
1287
|
+
expect(attributeValues(items[0])).toMatchObject({
|
|
1288
|
+
command: "init",
|
|
1289
|
+
language: "python",
|
|
1290
|
+
});
|
|
1291
|
+
});
|
|
1292
|
+
it("counts only the run's own command as completed; a nested operation adds its own metrics", async () => {
|
|
1293
|
+
await (0, telemetry_1.startCommandTelemetry)("deploy");
|
|
1294
|
+
await (0, telemetry_1.sendTelemetry)("synth", { totalTime: 42, language: "python" });
|
|
1295
|
+
await (0, telemetry_1.sendTelemetry)("deploy", { language: "python" });
|
|
1296
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1297
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1298
|
+
expect(items.map((i) => [i.name, attributeValues(i).command])).toEqual([
|
|
1299
|
+
["cli.command.invoked", "deploy"],
|
|
1300
|
+
["cli.synth.duration", "synth"],
|
|
1301
|
+
["cli.command.completed", "deploy"],
|
|
1302
|
+
]);
|
|
1303
|
+
});
|
|
1304
|
+
it("counts a failed run once as error, never as completed", async () => {
|
|
1305
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
1306
|
+
await (0, telemetry_1.sendTelemetry)("synth", { error: true, errorType: "External" });
|
|
1307
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1308
|
+
expect(parseMetricItems(envelopeBodies).map((i) => i.name)).toEqual([
|
|
1309
|
+
"cli.command.invoked",
|
|
1310
|
+
"cli.command.error",
|
|
1311
|
+
]);
|
|
1312
|
+
});
|
|
1313
|
+
it("emits nothing at start when usage telemetry is off, and stays a no-op afterwards", async () => {
|
|
1314
|
+
(0, telemetry_1.setUsageTelemetryEnabled)(false);
|
|
1315
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
1316
|
+
(0, telemetry_1.setUsageTelemetryEnabled)(true);
|
|
1317
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
1318
|
+
await Sentry.flush(2000);
|
|
1319
|
+
expect(parseMetricItems(envelopeBodies)).toHaveLength(0);
|
|
1320
|
+
});
|
|
1321
|
+
});
|
|
1322
|
+
// the bundle has one copy of this module per entry point: bin/cmds/handlers.js
|
|
1323
|
+
// captures the decision and starts the run, bin/cdktn.js counts the failure
|
|
1324
|
+
describe("shared across module copies", () => {
|
|
1325
|
+
let second;
|
|
1326
|
+
beforeEach(() => {
|
|
1327
|
+
jest.isolateModules(() => {
|
|
1328
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1329
|
+
second = require("./telemetry");
|
|
1330
|
+
});
|
|
1331
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1332
|
+
language: "go",
|
|
1333
|
+
sendUsageTelemetry: true,
|
|
1334
|
+
});
|
|
1335
|
+
initSentryWithCapturingTransport();
|
|
1336
|
+
});
|
|
1337
|
+
it("observes the captured decision and targets, the started command and its language from the other copy", async () => {
|
|
1338
|
+
// the project opts out; only the decision captured by the first copy
|
|
1339
|
+
// lets the second one emit
|
|
1340
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1341
|
+
language: "go",
|
|
1342
|
+
sendUsageTelemetry: false,
|
|
1343
|
+
});
|
|
1344
|
+
(0, telemetry_1.setUsageTelemetryEnabled)(true);
|
|
1345
|
+
(0, telemetry_1.setProjectTargetAttributes)({ target_opentofu: ">=1.7.0" });
|
|
1346
|
+
await (0, telemetry_1.startCommandTelemetry)("deploy");
|
|
1347
|
+
await second.startCommandTelemetry("synth");
|
|
1348
|
+
await second.sendTelemetry("synth", { language: "go" });
|
|
1349
|
+
await second.sendTelemetry("deploy", { error: true, errorType: "Usage" });
|
|
1350
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1351
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1352
|
+
expect(items.map((i) => [i.name, attributeValues(i).command])).toEqual([
|
|
1353
|
+
["cli.command.invoked", "deploy"],
|
|
1354
|
+
["cli.command.error", "deploy"],
|
|
1355
|
+
]);
|
|
1356
|
+
expect(attributeValues(items[1])).toMatchObject({
|
|
1357
|
+
language: "go",
|
|
1358
|
+
package_manager: "go",
|
|
1359
|
+
target_opentofu: ">=1.7.0",
|
|
1360
|
+
});
|
|
1361
|
+
expect(items[1].attributes).not.toHaveProperty("target_terraform");
|
|
1362
|
+
});
|
|
1363
|
+
});
|
|
1364
|
+
describe("sendTelemetry gating", () => {
|
|
1365
|
+
it.each([
|
|
1366
|
+
{ env: undefined, captured: undefined, flag: undefined, emits: true },
|
|
1367
|
+
{ env: undefined, captured: undefined, flag: true, emits: true },
|
|
1368
|
+
{ env: undefined, captured: undefined, flag: false, emits: false },
|
|
1369
|
+
// convert chdirs into a throwaway project that opts out
|
|
1370
|
+
{ env: undefined, captured: true, flag: false, emits: true },
|
|
1371
|
+
{ env: undefined, captured: false, flag: true, emits: false },
|
|
1372
|
+
{ env: "1", captured: undefined, flag: true, emits: false },
|
|
1373
|
+
{ env: "1", captured: true, flag: true, emits: false },
|
|
1374
|
+
])("CHECKPOINT_DISABLE=$env, captured=$captured, flag=$flag -> emits $emits", async ({ env, captured, flag, emits }) => {
|
|
1375
|
+
if (flag !== undefined) {
|
|
1376
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1377
|
+
sendUsageTelemetry: flag,
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
initSentryWithCapturingTransport();
|
|
1381
|
+
(0, telemetry_1.setUsageTelemetryEnabled)(captured);
|
|
1382
|
+
if (env !== undefined) {
|
|
1383
|
+
process.env.CHECKPOINT_DISABLE = env;
|
|
1384
|
+
}
|
|
1385
|
+
await (0, telemetry_1.startCommandTelemetry)("convert");
|
|
1386
|
+
await (0, telemetry_1.sendTelemetry)("convert", {});
|
|
1387
|
+
await Sentry.flush(2000);
|
|
1388
|
+
const items = parseMetricItems(envelopeBodies);
|
|
1389
|
+
expect(items.some((i) => i.name === "cli.command.invoked")).toBe(emits);
|
|
1390
|
+
expect(items.some((i) => i.name === "cli.command.completed")).toBe(emits);
|
|
1391
|
+
if (!emits) {
|
|
1392
|
+
expect(items).toHaveLength(0);
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
});
|
|
1396
|
+
describe("cli.error from the Errors factories", () => {
|
|
1397
|
+
afterEach(() => {
|
|
1398
|
+
errors_1.Errors.setScope("unknown");
|
|
1399
|
+
});
|
|
1400
|
+
// the scope is read when the error is built, not when the factory is
|
|
1401
|
+
// created: a factory-time binding reports every error as "unknown"
|
|
1402
|
+
it("counts constructed errors by type with the command set at call time", async () => {
|
|
1403
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1404
|
+
sendUsageTelemetry: true,
|
|
1405
|
+
});
|
|
1406
|
+
initSentryWithCapturingTransport();
|
|
1407
|
+
errors_1.Errors.setScope("deploy");
|
|
1408
|
+
errors_1.Errors.Usage("no stacks selected", undefined, { stackName: "secret" });
|
|
1409
|
+
errors_1.Errors.External("terraform exited with code 1");
|
|
1410
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1411
|
+
const errors = parseMetricItems(envelopeBodies).filter((i) => i.name === "cli.error");
|
|
1412
|
+
expect(errors).toHaveLength(2);
|
|
1413
|
+
expect(errors.map((e) => e.attributes.type.value)).toEqual([
|
|
1414
|
+
"Usage",
|
|
1415
|
+
"External",
|
|
1416
|
+
]);
|
|
1417
|
+
for (const error of errors) {
|
|
1418
|
+
expect(error.attributes.command.value).toBe("deploy");
|
|
1419
|
+
expect(error.attributes).not.toHaveProperty("message");
|
|
1420
|
+
expect(error.attributes).not.toHaveProperty("stackName");
|
|
1421
|
+
}
|
|
1422
|
+
expect(JSON.stringify(errors)).not.toContain("secret");
|
|
1423
|
+
expect(JSON.stringify(errors)).not.toContain("no stacks selected");
|
|
1424
|
+
});
|
|
1425
|
+
});
|
|
1426
|
+
describe("binary attributes", () => {
|
|
1427
|
+
async function invokedAttributes(versionOutput) {
|
|
1428
|
+
(0, terraform_1.seedTerraformCliProbeForTests)(Promise.resolve(versionOutput));
|
|
1429
|
+
initSentryWithCapturingTransport();
|
|
1430
|
+
await (0, telemetry_1.startCommandTelemetry)("synth");
|
|
1431
|
+
expect(await Sentry.flush(2000)).toBe(true);
|
|
1432
|
+
return attributeValues(parseMetricItems(envelopeBodies)[0]);
|
|
1433
|
+
}
|
|
1434
|
+
it.each([
|
|
1435
|
+
["Terraform v1.10.0-alpha20250101", "terraform", "1.10.0"],
|
|
1436
|
+
[
|
|
1437
|
+
"OpenTofu v1.2.3-LEAK-HOST.corp.example.com+LEAK-BUILD/Users/x",
|
|
1438
|
+
"opentofu",
|
|
1439
|
+
"1.2.3",
|
|
1440
|
+
],
|
|
1441
|
+
])("reduces the probed version of %p to its release", async (versionOutput, binary, release) => {
|
|
1442
|
+
expect(await invokedAttributes(versionOutput)).toMatchObject({
|
|
1443
|
+
binary,
|
|
1444
|
+
binary_version: release,
|
|
1445
|
+
});
|
|
1446
|
+
expect(envelopeBodies.join("\n")).not.toContain("LEAK");
|
|
1447
|
+
});
|
|
1448
|
+
it("sends no version for an unrecognised product: a wrapper's output has no product version line", async () => {
|
|
1449
|
+
const attributes = await invokedAttributes("connected to 10.0.0.1 as LEAK-USER (wrapper 3.4.5)\nTerraform v1.9.0\n");
|
|
1450
|
+
expect(attributes.binary).toBe("unknown");
|
|
1451
|
+
expect(attributes).not.toHaveProperty("binary_version");
|
|
1452
|
+
expect(envelopeBodies.join("\n")).not.toContain("LEAK-USER");
|
|
1453
|
+
});
|
|
1454
|
+
});
|
|
1455
|
+
describe("getProjectTargetAttributes", () => {
|
|
1456
|
+
it("reads declared targets and the validation flag", () => {
|
|
1457
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), {
|
|
1458
|
+
targetVersions: { opentofu: "~1.8" },
|
|
1459
|
+
validateInstalledBinary: true,
|
|
1460
|
+
});
|
|
1461
|
+
expect((0, telemetry_1.getProjectTargetAttributes)(workdir)).toEqual({
|
|
1462
|
+
targets_declared: true,
|
|
1463
|
+
validate_installed_binary: true,
|
|
1464
|
+
target_opentofu: ">=1.8.0 <1.9.0-0",
|
|
1465
|
+
});
|
|
1466
|
+
});
|
|
1467
|
+
it.each([
|
|
1468
|
+
[{}],
|
|
1469
|
+
[{ targetVersions: "nope" }],
|
|
1470
|
+
[{ targetVersions: [] }],
|
|
1471
|
+
[undefined],
|
|
1472
|
+
])("falls back to the defaults for a cdktf.json of %j", (config) => {
|
|
1473
|
+
if (config) {
|
|
1474
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), config);
|
|
1475
|
+
}
|
|
1476
|
+
expect((0, telemetry_1.getProjectTargetAttributes)(workdir)).toEqual({
|
|
1477
|
+
targets_declared: false,
|
|
1478
|
+
validate_installed_binary: false,
|
|
1479
|
+
...DEFAULT_TARGET_VERSIONS_AS_ATTRIBUTES,
|
|
1480
|
+
});
|
|
1481
|
+
});
|
|
1482
|
+
});
|
|
1483
|
+
describe("getUsageTelemetryConsent", () => {
|
|
1484
|
+
it.each([
|
|
1485
|
+
// init templates render the flag as a string; a boolean-only check
|
|
1486
|
+
// would opt every freshly init'ed project out
|
|
1487
|
+
[{ sendUsageTelemetry: "true" }, true],
|
|
1488
|
+
[{ sendUsageTelemetry: "false" }, false],
|
|
1489
|
+
[{}, undefined],
|
|
1490
|
+
// malformed is unset, not an opt-out
|
|
1491
|
+
[{ sendUsageTelemetry: "yes" }, undefined],
|
|
1492
|
+
])("reads %j as %p", (config, expected) => {
|
|
1493
|
+
fs.writeJsonSync(path.join(workdir, "cdktf.json"), config);
|
|
1494
|
+
expect((0, telemetry_1.getUsageTelemetryConsent)(workdir)).toBe(expected);
|
|
1495
|
+
});
|
|
1496
|
+
it("returns undefined when no cdktf.json exists", () => {
|
|
1497
|
+
expect((0, telemetry_1.getUsageTelemetryConsent)(workdir)).toBeUndefined();
|
|
1498
|
+
});
|
|
1499
|
+
});
|
|
1500
|
+
});
|
|
1501
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVsZW1ldHJ5LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdGVsZW1ldHJ5LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLHFEQUF1QztBQUN2Qyw2Q0FBK0I7QUFDL0IsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUM3QiwyQ0FVcUI7QUFDckIsMkNBQTREO0FBQzVELHFDQUtrQjtBQUNsQixxRUFHa0M7QUFDbEMscUNBQWtDO0FBRWxDLE1BQU0scUNBQXFDLEdBQUc7SUFDNUMsZ0JBQWdCLEVBQUUsZ0NBQXVCLENBQUMsU0FBUztJQUNuRCxlQUFlLEVBQUUsZ0NBQXVCLENBQUMsUUFBUTtDQUNsRCxDQUFDO0FBYUYsNkVBQTZFO0FBQzdFLG9CQUFvQjtBQUNwQixTQUFTLGdCQUFnQixDQUFDLGNBQXdCO0lBQ2hELE1BQU0sS0FBSyxHQUFpQixFQUFFLENBQUM7SUFDL0IsS0FBSyxNQUFNLElBQUksSUFBSSxjQUFjLEVBQUUsQ0FBQztRQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMxQyxJQUFJLE1BQU0sQ0FBQztZQUNYLElBQUksQ0FBQztnQkFDSCxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoQyxDQUFDO1lBQUMsV0FBTSxDQUFDO2dCQUNQLFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO2dCQUNu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RCxNQUFNLENBQUMsSUFBQSxvQ0FBd0IsRUFBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzVELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNUEwtMi4wXG5pbXBvcnQgKiBhcyBTZW50cnkgZnJvbSBcIkBzZW50cnkvbm9kZVwiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzLWV4dHJhXCI7XG5pbXBvcnQgKiBhcyBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7XG4gIHNlbmRUZWxlbWV0cnksXG4gIHN0YXJ0Q29tbWFuZFRlbGVtZXRyeSxcbiAgcmVzZXRDb21tYW5kVGVsZW1ldHJ5LFxuICBnZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyxcbiAgZ2V0VXNhZ2VUZWxlbWV0cnlDb25zZW50LFxuICBub3JtYWxpemVQYWNrYWdlTWFuYWdlcixcbiAgUEFDS0FHRV9NQU5BR0VSUyxcbiAgc2V0UHJvamVjdFRhcmdldEF0dHJpYnV0ZXMsXG4gIHNldFVzYWdlVGVsZW1ldHJ5RW5hYmxlZCxcbn0gZnJvbSBcIi4vdGVsZW1ldHJ5XCI7XG5pbXBvcnQgeyBzZWVkVGVycmFmb3JtQ2xpUHJvYmVGb3JUZXN0cyB9IGZyb20gXCIuL3RlcnJhZm9ybVwiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9UQVJHRVRfVkVSU0lPTlMsXG4gIExhbmd1YWdlLFxuICBUZXJyYWZvcm1Nb2R1bGVDb25zdHJhaW50LFxuICBUZXJyYWZvcm1Qcm92aWRlckNvbnN0cmFpbnQsXG59IGZyb20gXCIuL2NvbmZpZ1wiO1xuaW1wb3J0IHtcbiAgQ29uc3RydWN0c01ha2VyTW9kdWxlVGFyZ2V0LFxuICBDb25zdHJ1Y3RzTWFrZXJQcm92aWRlclRhcmdldCxcbn0gZnJvbSBcIi4vY29uc3RydWN0LW1ha2VyLXRhcmdldFwiO1xuaW1wb3J0IHsgRXJyb3JzIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5cbmNvbnN0IERFRkFVTFRfVEFSR0VUX1ZFUlNJT05TX0FTX0FUVFJJQlVURVMgPSB7XG4gIHRhcmdldF90ZXJyYWZvcm06IERFRkFVTFRfVEFSR0VUX1ZFUlNJT05TLnRlcnJhZm9ybSxcbiAgdGFyZ2V0X29wZW50b2Z1OiBERUZBVUxUX1RBUkdFVF9WRVJTSU9OUy5vcGVudG9mdSxcbn07XG5cbi8vIEEgcmVhbCBjbGllbnQgd2l0aCBhIGNhcHR1cmluZyB0cmFuc3BvcnQgcHJvdmVzIHRoZSBtZXRyaWMgZW52ZWxvcGVcbi8vIHJlYWNoZXMgdGhlIHRyYW5zcG9ydCBhbmQgc3Vydml2ZXMgYSBib3VuZGVkIGZsdXNoOyBhIG1vY2tlZCBAc2VudHJ5L25vZGVcbi8vIHdvdWxkIHBhc3MgZXZlbiBpZiBtZXRyaWNzIHdlcmUgZHJvcHBlZCBiZWZvcmUgZXhpdC5cblxudHlwZSBNZXRyaWNJdGVtID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgdmFsdWU6IG51bWJlcjtcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgeyB2YWx1ZTogdW5rbm93bjsgdHlwZTogc3RyaW5nIH0+O1xufTtcblxuLy8gTWlycm9ycyByZWNvcmRFbnZlbG9wZSBpbiB0b29scy9zZW50cnktc2luay5tanM6IGFuIGVudmVsb3BlLWZvcm1hdCBjaGFuZ2Vcbi8vIGlzIGZpeGVkIGluIGJvdGguXG5mdW5jdGlvbiBwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzOiBzdHJpbmdbXSk6IE1ldHJpY0l0ZW1bXSB7XG4gIGNvbnN0IGl0ZW1zOiBNZXRyaWNJdGVtW10gPSBbXTtcbiAgZm9yIChjb25zdCBib2R5IG9mIGVudmVsb3BlQm9kaWVzKSB7XG4gICAgY29uc3QgbGluZXMgPSBib2R5LnNwbGl0KFwiXFxuXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgbGV0IGhlYWRlcjtcbiAgICAgIHRyeSB7XG4gICAgICAgIGhlYWRlciA9IEpTT04ucGFyc2UobGluZXNbaV0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGhlYWRlci50eXBlID09PSBcInRyYWNlX21ldHJpY1wiKSB7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBKU09OLnBhcnNlKGxpbmVzW2kgKyAxXSk7XG4gICAgICAgIGl0ZW1zLnB1c2goLi4ucGF5bG9hZC5pdGVtcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBpdGVtcztcbn1cblxuZnVuY3Rpb24gYXR0cmlidXRlVmFsdWVzKGl0ZW06IE1ldHJpY0l0ZW0pIHtcbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICBPYmplY3QuZW50cmllcyhpdGVtLmF0dHJpYnV0ZXMpLm1hcCgoW2ssIHZdKSA9PiBbaywgdi52YWx1ZV0pLFxuICApO1xufVxuXG4vLyBPbiBldmVyeSBtZXRyaWMgb2YgYSBjb21tYW5kOyB0aGUgZXhhY3Qgc2V0IGlzIHBpbm5lZCBvbmNlLCBvblxuLy8gY2xpLmNvbW1hbmQuY29tcGxldGVkLlxuY29uc3QgQ09NTUFORF9BVFRSSUJVVEVTID0gW1xuICBcImFyY2hcIixcbiAgXCJiaW5hcnlcIixcbiAgXCJiaW5hcnlfdmVyc2lvblwiLFxuICBcImNpXCIsXG4gIFwiY29tbWFuZFwiLFxuICBcImxhbmd1YWdlXCIsXG4gIFwib3NcIixcbiAgXCJwYWNrYWdlX21hbmFnZXJcIixcbiAgXCJzZXJ2ZXIuYWRkcmVzc1wiLFxuICBcInRhcmdldF9vcGVudG9mdVwiLFxuICBcInRhcmdldF90ZXJyYWZvcm1cIixcbiAgXCJ0YXJnZXRzX2RlY2xhcmVkXCIsXG4gIFwidmFsaWRhdGVfaW5zdGFsbGVkX2JpbmFyeVwiLFxuXTtcblxuLy8gRWFjaCBtZXRyaWMgb2YgdGhhdCBuYW1lIGFzIGl0cyB2YWx1ZSBwbHVzIGV4YWN0bHkgdGhlIGF0dHJpYnV0ZXMgaXQgYWRkc1xuLy8gdG8gdGhlIGNvbW1hbmQncywgc28gYHRvRXF1YWxgIGZhaWxzIG9uIGFueSBhdHRyaWJ1dGUgdGhhdCBpcyBub3QgbGlzdGVkLlxuZnVuY3Rpb24gbWV0cmljcyhpdGVtczogTWV0cmljSXRlbVtdLCBuYW1lOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10ge1xuICByZXR1cm4gaXRlbXNcbiAgICAuZmlsdGVyKChpdGVtKSA9PiBpdGVtLm5hbWUgPT09IG5hbWUpXG4gICAgLm1hcCgoaXRlbSkgPT4gKHtcbiAgICAgIHZhbHVlOiBpdGVtLnZhbHVlLFxuICAgICAgLi4uT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVWYWx1ZXMoaXRlbSkpLmZpbHRlcihcbiAgICAgICAgICAoW2tleV0pID0+XG4gICAgICAgICAgICAha2V5LnN0YXJ0c1dpdGgoXCJzZW50cnkuXCIpICYmICFDT01NQU5EX0FUVFJJQlVURVMuaW5jbHVkZXMoa2V5KSxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgfSkpO1xufVxuXG5kZXNjcmliZShcInRlbGVtZXRyeVwiLCAoKSA9PiB7XG4gIGxldCB3b3JrZGlyOiBzdHJpbmc7XG4gIGxldCBlbnZlbG9wZUJvZGllczogc3RyaW5nW107XG4gIGNvbnN0IG9yaWdpbmFsQ3dkID0gcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3Qgb3JpZ2luYWxDaGVja3BvaW50RGlzYWJsZSA9IHByb2Nlc3MuZW52LkNIRUNLUE9JTlRfRElTQUJMRTtcbiAgY29uc3Qgb3JpZ2luYWxTZW50cnlFbnZpcm9ubWVudCA9IHByb2Nlc3MuZW52LlNFTlRSWV9FTlZJUk9OTUVOVDtcblxuICBmdW5jdGlvbiBpbml0U2VudHJ5V2l0aENhcHR1cmluZ1RyYW5zcG9ydCgpIHtcbiAgICBTZW50cnkuaW5pdCh7XG4gICAgICBkc246IFwiaHR0cHM6Ly9wdWJsaWNAZXhhbXBsZS5pbnZhbGlkLzFcIixcbiAgICAgIHJlbGVhc2U6IFwiY2RrdG4tY2xpLXRlc3RcIixcbiAgICAgIGVudmlyb25tZW50OiBcInByb2R1Y3Rpb25cIixcbiAgICAgIHRyYWNlc1NhbXBsZVJhdGU6IDAsXG4gICAgICBzZXJ2ZXJOYW1lOiBcImNka3RuLWNsaVwiLFxuICAgICAgLy8gZWFjaCB0ZXN0IGluaXRzIGl0cyBvd24gY2xpZW50OyBwcm9jZXNzLWxldmVsIGludGVncmF0aW9ucyB3b3VsZFxuICAgICAgLy8gcGlsZSB1cCBsaXN0ZW5lcnMgYWNyb3NzIHRlc3RzIGFuZCBhcmUgaXJyZWxldmFudCB0byBtZXRyaWNzXG4gICAgICBkZWZhdWx0SW50ZWdyYXRpb25zOiBmYWxzZSxcbiAgICAgIHRyYW5zcG9ydDogKG9wdGlvbnMpID0+XG4gICAgICAgIFNlbnRyeS5jcmVhdGVUcmFuc3BvcnQob3B0aW9ucywgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgICBlbnZlbG9wZUJvZGllcy5wdXNoKHJlcXVlc3QuYm9keSBhcyBzdHJpbmcpO1xuICAgICAgICAgIHJldHVybiB7IHN0YXR1c0NvZGU6IDIwMCB9O1xuICAgICAgICB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGRlbGl2ZXJlZEl0ZW1zKCk6IFByb21pc2U8TWV0cmljSXRlbVtdPiB7XG4gICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcbiAgICByZXR1cm4gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcyk7XG4gIH1cblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICB3b3JrZGlyID0gZnMubWtkdGVtcFN5bmMocGF0aC5qb2luKG9zLnRtcGRpcigpLCBcImNka3RuLXRlbGVtZXRyeS1cIikpO1xuICAgIHByb2Nlc3MuY2hkaXIod29ya2Rpcik7XG4gICAgZW52ZWxvcGVCb2RpZXMgPSBbXTtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnYuQ0hFQ0tQT0lOVF9ESVNBQkxFO1xuICAgIGRlbGV0ZSBwcm9jZXNzLmVudi5TRU5UUllfRU5WSVJPTk1FTlQ7XG4gICAgLy8gdGhlIHByb2JlIGlzIHByb2Nlc3MtZ2xvYmFsIChzZWUgdGVycmFmb3JtLnRzKTsgYSBzZWVkZWQgb3V0cHV0IGtlZXBzXG4gICAgLy8gdGhlIGJpbmFyeSBhdHRyaWJ1dGVzIGluZGVwZW5kZW50IG9mIHRoZSBtYWNoaW5lIHJ1bm5pbmcgdGhlIHRlc3RzXG4gICAgc2VlZFRlcnJhZm9ybUNsaVByb2JlRm9yVGVzdHMoXG4gICAgICBQcm9taXNlLnJlc29sdmUoXCJUZXJyYWZvcm0gdjEuOS4wXFxub24gZGFyd2luX2FybTY0XFxuXCIpLFxuICAgICk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgc2V0VXNhZ2VUZWxlbWV0cnlFbmFibGVkKHVuZGVmaW5lZCk7XG4gICAgcmVzZXRDb21tYW5kVGVsZW1ldHJ5KCk7XG4gICAgc2V0UHJvamVjdFRhcmdldEF0dHJpYnV0ZXModW5kZWZpbmVkKTtcbiAgICBzZWVkVGVycmFmb3JtQ2xpUHJvYmVGb3JUZXN0cygpO1xuICAgIGF3YWl0IFNlbnRyeS5jbG9zZSgxMDAwKTtcbiAgICBwcm9jZXNzLmNoZGlyKG9yaWdpbmFsQ3dkKTtcbiAgICBmcy5yZW1vdmVTeW5jKHdvcmtkaXIpO1xuICAgIGlmIChvcmlnaW5hbENoZWNrcG9pbnREaXNhYmxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmVudi5DSEVDS1BPSU5UX0RJU0FCTEU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZW52LkNIRUNLUE9JTlRfRElTQUJMRSA9IG9yaWdpbmFsQ2hlY2twb2ludERpc2FibGU7XG4gICAgfVxuICAgIGlmIChvcmlnaW5hbFNlbnRyeUVudmlyb25tZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmVudi5TRU5UUllfRU5WSVJPTk1FTlQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZW52LlNFTlRSWV9FTlZJUk9OTUVOVCA9IG9yaWdpbmFsU2VudHJ5RW52aXJvbm1lbnQ7XG4gICAgfVxuICB9KTtcblxuICBkZXNjcmliZShcInNlbmRUZWxlbWV0cnkgZGVsaXZlcnkgKHJlYWwgY2xpZW50ICsgY2FwdHVyaW5nIHRyYW5zcG9ydClcIiwgKCkgPT4ge1xuICAgIGl0KFwic3RhbXBzIHRoZSBjb21tYW5kLCBsYW5ndWFnZSwgYmluYXJ5IGFuZCB0YXJnZXQgYXR0cmlidXRlcyBvbiBldmVyeSBjb21tYW5kIG1ldHJpY1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICBzZW5kVXNhZ2VUZWxlbWV0cnk6IHRydWUsXG4gICAgICAgIHRhcmdldFZlcnNpb25zOiB7IHRlcnJhZm9ybTogXCI+PTEuOS4wXCIsIG9wZW50b2Z1OiBcIj49MS44LjBcIiB9LFxuICAgICAgICB2YWxpZGF0ZUluc3RhbGxlZEJpbmFyeTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcblxuICAgICAgYXdhaXQgc3RhcnRDb21tYW5kVGVsZW1ldHJ5KFwic3ludGhcIik7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwic3ludGhcIiwgeyB0b3RhbFRpbWU6IDEyMzQsIGxhbmd1YWdlOiBcInR5cGVzY3JpcHRcIiB9KTtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7IGVycm9yOiB0cnVlLCBzeW50aE9yaWdpbjogXCJ3YXRjaFwiIH0pO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzKTtcbiAgICAgIGV4cGVjdChpdGVtcy5tYXAoKGkpID0+IGkubmFtZSkpLnRvRXF1YWwoW1xuICAgICAgICBcImNsaS5jb21tYW5kLmludm9rZWRcIixcbiAgICAgICAgXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIixcbiAgICAgICAgXCJjbGkuc3ludGguZHVyYXRpb25cIixcbiAgICAgICAgXCJjbGkuY29tbWFuZC5lcnJvclwiLFxuICAgICAgXSk7XG4gICAgICBjb25zdCBbaW52b2tlZCwgY29tcGxldGVkLCBkdXJhdGlvbiwgZXJyb3JdID0gaXRlbXM7XG5cbiAgICAgIGZvciAoY29uc3QgbWV0cmljIG9mIGl0ZW1zKSB7XG4gICAgICAgIGV4cGVjdChhdHRyaWJ1dGVWYWx1ZXMobWV0cmljKSkudG9NYXRjaE9iamVjdCh7XG4gICAgICAgICAgY29tbWFuZDogXCJzeW50aFwiLFxuICAgICAgICAgIG9zOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgICAgICAgIGFyY2g6IHByb2Nlc3MuYXJjaCxcbiAgICAgICAgICBiaW5hcnk6IFwidGVycmFmb3JtXCIsXG4gICAgICAgICAgYmluYXJ5X3ZlcnNpb246IFwiMS45LjBcIixcbiAgICAgICAgICB0YXJnZXRfdGVycmFmb3JtOiBcIj49MS45LjBcIixcbiAgICAgICAgICB0YXJnZXRfb3BlbnRvZnU6IFwiPj0xLjguMFwiLFxuICAgICAgICAgIHRhcmdldHNfZGVjbGFyZWQ6IHRydWUsXG4gICAgICAgICAgdmFsaWRhdGVfaW5zdGFsbGVkX2JpbmFyeTogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICAvLyB0aGUgbGFuZ3VhZ2UgY29tZXMgZnJvbSBjZGt0Zi5qc29uIGF0IHN0YXJ0IGFuZCBmcm9tIHRoZSBwYXlsb2FkXG4gICAgICAvLyBhdCB0aGUgZW5kOyB0aGUgZXJyb3IgbWV0cmljIGhhcyBubyBwYXlsb2FkIGFuZCByZXVzZXMgdGhlIHN0YXJ0IHJlYWRcbiAgICAgIGV4cGVjdChhdHRyaWJ1dGVWYWx1ZXMoaW52b2tlZCkubGFuZ3VhZ2UpLnRvQmUoXCJ0eXBlc2NyaXB0XCIpO1xuICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhjb21wbGV0ZWQpLmxhbmd1YWdlKS50b0JlKFwidHlwZXNjcmlwdFwiKTtcbiAgICAgIGV4cGVjdChkdXJhdGlvbi50eXBlKS50b0JlKFwiZGlzdHJpYnV0aW9uXCIpO1xuICAgICAgZXhwZWN0KGR1cmF0aW9uLnZhbHVlKS50b0JlKDEyMzQpO1xuICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhlcnJvcikpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgICBlcnJvcl90eXBlOiBcInVuZXhwZWN0ZWRcIixcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICBzeW50aF9vcmlnaW46IFwid2F0Y2hcIixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJ1c2VzIHRoZSB0YXJnZXQgYXR0cmlidXRlcyBjYXB0dXJlZCBhdCBjb21tYW5kIHN0YXJ0IG92ZXIgdGhlIGN1cnJlbnQgY3dkXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICB0YXJnZXRWZXJzaW9uczogeyB0ZXJyYWZvcm06IFwiPj0xLjAuMFwiIH0sXG4gICAgICB9KTtcbiAgICAgIGluaXRTZW50cnlXaXRoQ2FwdHVyaW5nVHJhbnNwb3J0KCk7XG4gICAgICBzZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyh7XG4gICAgICAgIHRhcmdldHNfZGVjbGFyZWQ6IHRydWUsXG4gICAgICAgIHZhbGlkYXRlX2luc3RhbGxlZF9iaW5hcnk6IGZhbHNlLFxuICAgICAgICB0YXJnZXRfb3BlbnRvZnU6IFwiPj0xLjcuMFwiLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcImNvbnZlcnRcIik7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiY29udmVydFwiLCB7fSk7XG4gICAgICBleHBlY3QoYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApKS50b0JlKHRydWUpO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpO1xuICAgICAgZXhwZWN0KGl0ZW1zLm1hcCgoaSkgPT4gaS5uYW1lKSkudG9FcXVhbChbXG4gICAgICAgIFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiLFxuICAgICAgICBcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiLFxuICAgICAgXSk7XG4gICAgICBmb3IgKGNvbnN0IG1ldHJpYyBvZiBpdGVtcykge1xuICAgICAgICBleHBlY3QobWV0cmljLmF0dHJpYnV0ZXMudGFyZ2V0X29wZW50b2Z1LnZhbHVlKS50b0JlKFwiPj0xLjcuMFwiKTtcbiAgICAgICAgZXhwZWN0KG1ldHJpYy5hdHRyaWJ1dGVzLnRhcmdldF90ZXJyYWZvcm0pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1wiVXNhZ2VcIiwgXCJVc2FnZVwiXSxcbiAgICAgIFtcIkV4dGVybmFsXCIsIFwiRXh0ZXJuYWxcIl0sXG4gICAgICBbXCJJbnRlcm5hbFwiLCBcIkludGVybmFsXCJdLFxuICAgICAgW1wiU29tZXRoaW5nIEVsc2VcIiwgXCJ1bmV4cGVjdGVkXCJdLFxuICAgIF0pKFxuICAgICAgXCJzdGFtcHMgZXJyb3JfdHlwZSAlcCBhcyAlcCBvbiBjbGkuY29tbWFuZC5lcnJvclwiLFxuICAgICAgYXN5bmMgKGVycm9yVHlwZSwgZXhwZWN0ZWQpID0+IHtcbiAgICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgICAgc2VuZFVzYWdlVGVsZW1ldHJ5OiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcblxuICAgICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZGVwbG95XCIsIHsgZXJyb3I6IHRydWUsIGVycm9yVHlwZSB9KTtcbiAgICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgICBjb25zdCBlcnJvciA9IHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpLmZpbmQoXG4gICAgICAgICAgKGkpID0+IGkubmFtZSA9PT0gXCJjbGkuY29tbWFuZC5lcnJvclwiLFxuICAgICAgICApITtcbiAgICAgICAgZXhwZWN0KGVycm9yLmF0dHJpYnV0ZXMuZXJyb3JfdHlwZS52YWx1ZSkudG9CZShleHBlY3RlZCk7XG4gICAgICAgIGV4cGVjdChlcnJvci5hdHRyaWJ1dGVzLmNvbW1hbmQudmFsdWUpLnRvQmUoXCJkZXBsb3lcIik7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBpdChcImZvcndhcmRzIGV4YWN0bHkgdGhlIGFsbG93LWxpc3RlZCBhdHRyaWJ1dGUgc2V0IGFuZCBub3RoaW5nIGVsc2UgZnJvbSB0aGUgcGF5bG9hZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICBzZW5kVXNhZ2VUZWxlbWV0cnk6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGluaXRTZW50cnlXaXRoQ2FwdHVyaW5nVHJhbnNwb3J0KCk7XG5cbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHtcbiAgICAgICAgdG90YWxUaW1lOiA1LFxuICAgICAgICBsYW5ndWFnZTogXCJ0eXBlc2NyaXB0XCIsXG4gICAgICAgIHN5bnRoT3JpZ2luOiBcIndhdGNoXCIsXG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IFt7IHN0YWNrTmFtZTogXCJwcm9kLXZwY1wiLCBiYWNrZW5kOiBcInMzXCIgfV0sXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzOiBbeyBhd3M6IHsgc291cmNlOiBcImF3c1wiIH0gfV0sXG4gICAgICAgIHN0YWNrTmFtZTogXCJwcm9kLXZwY1wiLFxuICAgICAgICBvdXRkaXI6IFwiL1VzZXJzL3gvc2VjcmV0XCIsXG4gICAgICAgIHJlc291cmNlczogeyBhd3M6IHsgc2VjcmV0X3Jlc291cmNlOiAzIH0gfSxcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzKTtcbiAgICAgIGNvbnN0IGludm9rZWQgPSBpdGVtcy5maW5kKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiKSE7XG4gICAgICBjb25zdCBjb21wbGV0ZWQgPSBpdGVtcy5maW5kKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIpITtcbiAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhjb21wbGV0ZWQuYXR0cmlidXRlcyk7XG4gICAgICAvLyB0aGUgc3RhcnQgbWV0cmljIGNhcnJpZXMgdGhlIGJhc2Ugc2V0OyB0aGUgZW5kLW9mLXJ1biBzY2FsYXJzIHJpZGVcbiAgICAgIC8vIG9uIGNvbXBsZXRlZCBvbmx5XG4gICAgICBleHBlY3QoT2JqZWN0LmtleXMoaW52b2tlZC5hdHRyaWJ1dGVzKS5zb3J0KCkpLnRvRXF1YWwoXG4gICAgICAgIGtleXMuZmlsdGVyKChrZXkpID0+IGtleSAhPT0gXCJzeW50aF9vcmlnaW5cIikuc29ydCgpLFxuICAgICAgKTtcbiAgICAgIC8vIHRoZSBvbmUgcGxhY2UgdGhhdCBmYWlscyB3aGVuIGFuIGF0dHJpYnV0ZSBpcyBhZGRlZDogZXh0ZW5kIGl0XG4gICAgICAvLyBkZWxpYmVyYXRlbHksIHRvZ2V0aGVyIHdpdGggdGhlIGNvbGxlY3RlZC1kYXRhIGxpc3QgaW4gdGhlIGRvY3NcbiAgICAgIGV4cGVjdChrZXlzLmZpbHRlcigoa2V5KSA9PiAha2V5LnN0YXJ0c1dpdGgoXCJzZW50cnkuXCIpKS5zb3J0KCkpLnRvRXF1YWwoW1xuICAgICAgICBcImFyY2hcIixcbiAgICAgICAgXCJiaW5hcnlcIixcbiAgICAgICAgXCJiaW5hcnlfdmVyc2lvblwiLFxuICAgICAgICBcImNpXCIsXG4gICAgICAgIFwiY29tbWFuZFwiLFxuICAgICAgICBcImxhbmd1YWdlXCIsXG4gICAgICAgIFwib3NcIixcbiAgICAgICAgXCJwYWNrYWdlX21hbmFnZXJcIixcbiAgICAgICAgLy8gc2VydmVyLmFkZHJlc3MgaXMgdGhlIGZpeGVkIHNlcnZlck5hbWUgZnJvbSBpbml0XG4gICAgICAgIFwic2VydmVyLmFkZHJlc3NcIixcbiAgICAgICAgXCJzeW50aF9vcmlnaW5cIixcbiAgICAgICAgXCJ0YXJnZXRfb3BlbnRvZnVcIixcbiAgICAgICAgXCJ0YXJnZXRfdGVycmFmb3JtXCIsXG4gICAgICAgIFwidGFyZ2V0c19kZWNsYXJlZFwiLFxuICAgICAgICBcInZhbGlkYXRlX2luc3RhbGxlZF9iaW5hcnlcIixcbiAgICAgIF0pO1xuICAgICAgLy8gc3RhbXBlZCBieSB0aGUgU0RLIGZyb20gaW5pdDsgYSBwYXRjaCBidW1wIG1heSBhZGQgbW9yZSBvZiB0aGVtXG4gICAgICBleHBlY3Qoa2V5cykudG9FcXVhbChcbiAgICAgICAgZXhwZWN0LmFycmF5Q29udGFpbmluZyhbXCJzZW50cnkucmVsZWFzZVwiLCBcInNlbnRyeS5lbnZpcm9ubWVudFwiXSksXG4gICAgICApO1xuICAgICAgY29uc3QgYnl0ZXMgPSBlbnZlbG9wZUJvZGllcy5qb2luKFwiXFxuXCIpO1xuICAgICAgZXhwZWN0KGJ5dGVzKS5ub3QudG9Db250YWluKFwicHJvZC12cGNcIik7XG4gICAgICBleHBlY3QoYnl0ZXMpLm5vdC50b0NvbnRhaW4oXCIvVXNlcnMveC9zZWNyZXRcIik7XG4gICAgICBleHBlY3QoYnl0ZXMpLm5vdC50b0NvbnRhaW4oXCJzZWNyZXRfcmVzb3VyY2VcIik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwic2VuZFRlbGVtZXRyeSBwYXlsb2FkIG1hcHBpbmdcIiwgKCkgPT4ge1xuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIHNlbmRVc2FnZVRlbGVtZXRyeTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY291bnRzIGdldCB0YXJnZXRzIHBlciBub3JtYWxpemVkIHByb3ZpZGVyL21vZHVsZSBhbmQgcHV0cyBvbmx5IHRvdGFscyBvbiB0aGUgY29tbWFuZCBtZXRyaWNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvdmlkZXIgPSAoY29uc3RyYWludDogc3RyaW5nKSA9PlxuICAgICAgICBuZXcgQ29uc3RydWN0c01ha2VyUHJvdmlkZXJUYXJnZXQoXG4gICAgICAgICAgbmV3IFRlcnJhZm9ybVByb3ZpZGVyQ29uc3RyYWludChjb25zdHJhaW50KSxcbiAgICAgICAgICBMYW5ndWFnZS5UWVBFU0NSSVBULFxuICAgICAgICApLnRyYWNraW5nUGF5bG9hZDtcbiAgICAgIGNvbnN0IG1vZHVsZSA9IChjb25zdHJhaW50OiBzdHJpbmcpID0+XG4gICAgICAgIG5ldyBDb25zdHJ1Y3RzTWFrZXJNb2R1bGVUYXJnZXQoXG4gICAgICAgICAgbmV3IFRlcnJhZm9ybU1vZHVsZUNvbnN0cmFpbnQoY29uc3RyYWludCksXG4gICAgICAgICAgTGFuZ3VhZ2UuVFlQRVNDUklQVCxcbiAgICAgICAgKS50cmFja2luZ1BheWxvYWQ7XG5cbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJnZXRcIiwge1xuICAgICAgICB0YXJnZXRzOiBbXG4gICAgICAgICAgcHJvdmlkZXIoXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8vaGFzaGljb3JwL2F3c0B+PiA1LjBcIiksXG4gICAgICAgICAgcHJvdmlkZXIoXCJIYXNoaWNvcnAvQVdTQH4+IDYuMFwiKSxcbiAgICAgICAgICBwcm92aWRlcihcIktyZXV6d2Vya2VyL0RvY2tlclwiKSxcbiAgICAgICAgICBtb2R1bGUoXCJ0ZXJyYWZvcm0tYXdzLW1vZHVsZXMvdnBjL2F3c0A1LjAuMFwiKSxcbiAgICAgICAgICBtb2R1bGUoXCIuL21vZHVsZXMvc2VjcmV0LW5hbWVcIiksXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBhd2FpdCBkZWxpdmVyZWRJdGVtcygpO1xuICAgICAgY29uc3QgdG90YWxzID0geyBwcm92aWRlcl9jb3VudDogMywgbW9kdWxlX2NvdW50OiAyIH07XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCAuLi50b3RhbHMgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLmdldC5wcm92aWRlclwiKSkudG9FcXVhbChbXG4gICAgICAgIHsgdmFsdWU6IDIsIHByb3ZpZGVyOiBcImhhc2hpY29ycC9hd3NcIiwgLi4udG90YWxzIH0sXG4gICAgICAgIHsgdmFsdWU6IDEsIHByb3ZpZGVyOiBcImtyZXV6d2Vya2VyL2RvY2tlclwiLCAuLi50b3RhbHMgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLmdldC5tb2R1bGVcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCBtb2R1bGU6IFwibG9jYWxcIiwgLi4udG90YWxzIH0sXG4gICAgICAgIHsgdmFsdWU6IDEsIG1vZHVsZTogXCJ0ZXJyYWZvcm0tYXdzLW1vZHVsZXMvdnBjL2F3c1wiLCAuLi50b3RhbHMgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KGVudmVsb3BlQm9kaWVzLmpvaW4oXCJcXG5cIikpLm5vdC50b0NvbnRhaW4oXCJzZWNyZXQtbmFtZVwiKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY291bnRzIGluaXQgcHJvdmlkZXJzIHBlciBub3JtYWxpemVkIHByb3ZpZGVyIGFuZCBwdXRzIG9ubHkgdGhlIHRvdGFsIG9uIHRoZSBjb21tYW5kIG1ldHJpY1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiaW5pdFwiLCB7XG4gICAgICAgIHByb2plY3RJZDogXCJzaG91bGQtbm90LWJlLXNlbnRcIixcbiAgICAgICAgYWRkZWRQcm92aWRlcnM6IFtcbiAgICAgICAgICBcImF3c0B+PjUuMFwiLFxuICAgICAgICAgIFwiaGFzaGljb3JwL3JhbmRvbVwiLFxuICAgICAgICAgIFwicmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9hd3NcIixcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCBwcm92aWRlcl9jb3VudDogMyB9LFxuICAgICAgXSk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuaW5pdC5wcm92aWRlclwiKSkudG9FcXVhbChbXG4gICAgICAgIHsgdmFsdWU6IDIsIHByb3ZpZGVyOiBcImhhc2hpY29ycC9hd3NcIiwgcHJvdmlkZXJfY291bnQ6IDMgfSxcbiAgICAgICAgeyB2YWx1ZTogMSwgcHJvdmlkZXI6IFwiaGFzaGljb3JwL3JhbmRvbVwiLCBwcm92aWRlcl9jb3VudDogMyB9LFxuICAgICAgXSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcInNob3VsZC1ub3QtYmUtc2VudFwiKTtcbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1xuICAgICAgICBcImdldFwiLFxuICAgICAgICAoc291cmNlczogc3RyaW5nW10pID0+ICh7XG4gICAgICAgICAgdGFyZ2V0czogc291cmNlcy5tYXAoKHNvdXJjZSkgPT4gKHsgdHlwZTogXCJwcm92aWRlclwiLCBzb3VyY2UgfSkpLFxuICAgICAgICB9KSxcbiAgICAgICAgXCJjbGkuZ2V0LnByb3ZpZGVyXCIsXG4gICAgICAgIHsgcHJvdmlkZXJfY291bnQ6IDQwLCBtb2R1bGVfY291bnQ6IDAgfSxcbiAgICAgIF0sXG4gICAgICBbXG4gICAgICAgIFwiaW5pdFwiLFxuICAgICAgICAoc291cmNlczogc3RyaW5nW10pID0+ICh7IGFkZGVkUHJvdmlkZXJzOiBzb3VyY2VzIH0pLFxuICAgICAgICBcImNsaS5pbml0LnByb3ZpZGVyXCIsXG4gICAgICAgIHsgcHJvdmlkZXJfY291bnQ6IDQwIH0sXG4gICAgICBdLFxuICAgIF0pKFxuICAgICAgXCIlcyBmb2xkcyB0aGUgcHJvdmlkZXJzIHBhc3QgMzIgaW50byBvbmUgdHJ1bmNhdGVkIGNvdW50XCIsXG4gICAgICBhc3luYyAoY29tbWFuZCwgcGF5bG9hZCwgbWV0cmljLCB0b3RhbHMpID0+IHtcbiAgICAgICAgY29uc3Qgc291cmNlcyA9IEFycmF5LmZyb20oXG4gICAgICAgICAgeyBsZW5ndGg6IDQwIH0sXG4gICAgICAgICAgKF8sIGspID0+IGBhY21lL3Ake1N0cmluZyhrKS5wYWRTdGFydCgyLCBcIjBcIil9YCxcbiAgICAgICAgKTtcblxuICAgICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KGNvbW1hbmQsIHBheWxvYWQoWy4uLnNvdXJjZXNdLnJldmVyc2UoKSkpO1xuXG4gICAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIG1ldHJpYykpLnRvRXF1YWwoW1xuICAgICAgICAgIC4uLnNvdXJjZXNcbiAgICAgICAgICAgIC5zbGljZSgwLCAzMilcbiAgICAgICAgICAgIC5tYXAoKHByb3ZpZGVyKSA9PiAoeyB2YWx1ZTogMSwgcHJvdmlkZXIsIC4uLnRvdGFscyB9KSksXG4gICAgICAgICAgeyB2YWx1ZTogOCwgdHJ1bmNhdGVkOiB0cnVlLCAuLi50b3RhbHMgfSxcbiAgICAgICAgXSk7XG4gICAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiKSkudG9FcXVhbChbXG4gICAgICAgICAgeyB2YWx1ZTogMSwgLi4udG90YWxzIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgaXQoXCJjb3VudHMgdGhlIHJ1biBhcyBjb21wbGV0ZWQgZXZlbiB3aGVuIGEgcGVyLXNvdXJjZSBtZXRyaWMgY2Fubm90IGJlIGJ1aWx0XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJnZXRcIiwge1xuICAgICAgICB0YXJnZXRzOiBbbnVsbCwgeyB0eXBlOiBcInByb3ZpZGVyXCIsIHNvdXJjZTogNyB9XSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCBwcm92aWRlcl9jb3VudDogMSwgbW9kdWxlX2NvdW50OiAwIH0sXG4gICAgICBdKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5nZXQucHJvdmlkZXJcIikpLnRvRXF1YWwoW10pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcInN0YWNrIG1ldHJpY3NcIiwgKCkgPT4ge1xuICAgIC8vIG9uZSBKU09OLXN5bnRoZXNpemVkIHN0YWNrIHRoZSB3YXkgdGhlIGxpYnJhcnkgd3JpdGVzIGl0OiBtZXRhZGF0YVxuICAgIC8vIGNhcnJpZXMgdGhlIHN0YWNrIG5hbWUgYW5kIHJlc291cmNlIGlkcyAoaW1wb3J0cy9tb3ZlZCksIG92ZXJyaWRlc1xuICAgIC8vIGFyZSBrZXllZCBieSBzY2hlbWEgdHlwZSwgbW9kdWxlIG92ZXJyaWRlcyBieSBzb3VyY2VcbiAgICBjb25zdCBzdGFja01ldGFkYXRhID0gW1xuICAgICAge1xuICAgICAgICB2ZXJzaW9uOiBcIjAuMjEuMFwiLFxuICAgICAgICBzdGFja05hbWU6IFwiU0VDUkVULVNUQUNLLU5BTUVcIixcbiAgICAgICAgYmFja2VuZDogXCJzM1wiLFxuICAgICAgICBvdmVycmlkZXM6IHtcbiAgICAgICAgICBzdGFjazogW1widGVycmFmb3JtLnJlcXVpcmVkX3ZlcnNpb25cIl0sXG4gICAgICAgICAgYXdzX3MzX2J1Y2tldDogW1widGFnc1wiLCBcInJlZ2lvblwiXSxcbiAgICAgICAgICBcIm1vZHVsZS4uLi9zZWNyZXQtcGF0aC92cGNcIjogW1wicHJvdmlkZXJzXCJdLFxuICAgICAgICB9LFxuICAgICAgICBpbXBvcnRzOiB7IGF3c19zM19idWNrZXQ6IFtcInNlY3JldC1yZXNvdXJjZS1pZFwiXSB9LFxuICAgICAgICBtb3ZlZDoge1xuICAgICAgICAgIGF3c19zM19idWNrZXQ6IFtcInNlY3JldC1yZXNvdXJjZS1pZFwiXSxcbiAgICAgICAgICBhd3NfaWFtX3JvbGU6IFtcInNlY3JldC1yZXNvdXJjZS1pZFwiXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHZlcnNpb246IFwiMC4yMS4wXCIsXG4gICAgICAgIHN0YWNrTmFtZTogXCJTRUNSRVQtU1RBQ0stTkFNRS0yXCIsXG4gICAgICAgIGJhY2tlbmQ6IFwicmVtb3RlXCIsXG4gICAgICAgIGNsb3VkOiBcInRmY1wiLFxuICAgICAgfSxcbiAgICBdO1xuICAgIGNvbnN0IHJlcXVpcmVkUHJvdmlkZXJzID0gW1xuICAgICAge1xuICAgICAgICBhd3M6IHsgc291cmNlOiBcImF3c1wiLCB2ZXJzaW9uOiBcIn4+IDUuMFwiIH0sXG4gICAgICAgIGRvY2tlcjoge1xuICAgICAgICAgIHNvdXJjZTogXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8va3JldXp3ZXJrZXIvZG9ja2VyXCIsXG4gICAgICAgICAgdmVyc2lvbjogXCIzLjAuMlwiLFxuICAgICAgICB9LFxuICAgICAgICBnb29nbGU6IHsgc291cmNlOiBcImhhc2hpY29ycC9nb29nbGVcIiwgdmVyc2lvbjogXCJ4XCIucmVwZWF0KDEwMCkgfSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHJhbmRvbTogeyBzb3VyY2U6IFwiaGFzaGljb3JwL3JhbmRvbVwiIH0sXG4gICAgICAgIHZhdWx0OiB7XG4gICAgICAgICAgc291cmNlOiBcInRmZS5jb3JwLmV4YW1wbGUuY29tL2FjbWUtb3JnL3ZhdWx0XCIsXG4gICAgICAgICAgdmVyc2lvbjogXCJ+PiAzLjBcIixcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXTtcbiAgICBjb25zdCBub0NvdW50cyA9IHsgb3ZlcnJpZGVfY291bnQ6IDAsIGltcG9ydF9jb3VudDogMCwgbW92ZWRfY291bnQ6IDAgfTtcblxuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIHNlbmRVc2FnZVRlbGVtZXRyeTogdHJ1ZSxcbiAgICAgICAgdGVycmFmb3JtUHJvdmlkZXJzOiBbXG4gICAgICAgICAgXCJhd3NAfj41LjBcIixcbiAgICAgICAgICB7IG5hbWU6IFwiZG9ja2VyXCIsIHNvdXJjZTogXCJrcmV1endlcmtlci9kb2NrZXJcIiwgdmVyc2lvbjogXCIzLjAuMlwiIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICAgIGluaXRTZW50cnlXaXRoQ2FwdHVyaW5nVHJhbnNwb3J0KCk7XG4gICAgfSk7XG5cbiAgICBpdChcImRlbGl2ZXJzIG5vIHN0YWNrLCBwcm92aWRlciBvciBvdmVycmlkZSBtZXRyaWMgd2hlbiB0aGUgcHJvamVjdCBvcHRzIG91dFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgc2VuZFVzYWdlVGVsZW1ldHJ5OiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZGVwbG95XCIsIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICBzdGFja01ldGFkYXRhLFxuICAgICAgICByZXF1aXJlZFByb3ZpZGVycyxcbiAgICAgICAgZmFpbGVkU3RhY2tDb3VudDogMCxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImNvdW50cyBzdGFja3MgYnkgYmFja2VuZCwgY2xvdWQgYW5kIGxpYnJhcnkgdmVyc2lvbiB3aXRoIHRoZWlyIGdyb3VwIHNpemVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJkZXBsb3lcIiwge1xuICAgICAgICBsYW5ndWFnZTogXCJ0eXBlc2NyaXB0XCIsXG4gICAgICAgIHN0YWNrTWV0YWRhdGEsXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzLFxuICAgICAgICBmYWlsZWRTdGFja0NvdW50OiAwLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFja1wiKSkudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogMSxcbiAgICAgICAgICBiYWNrZW5kOiBcInJlbW90ZVwiLFxuICAgICAgICAgIGNsb3VkOiB0cnVlLFxuICAgICAgICAgIGxpYnJhcnlfdmVyc2lvbjogXCIwLjIxLjBcIixcbiAgICAgICAgICAuLi5ub0NvdW50cyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIGJhY2tlbmQ6IFwiczNcIixcbiAgICAgICAgICBjbG91ZDogZmFsc2UsXG4gICAgICAgICAgbGlicmFyeV92ZXJzaW9uOiBcIjAuMjEuMFwiLFxuICAgICAgICAgIG92ZXJyaWRlX2NvdW50OiA0LFxuICAgICAgICAgIGltcG9ydF9jb3VudDogMSxcbiAgICAgICAgICBtb3ZlZF9jb3VudDogMixcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgICAgZm9yIChjb25zdCBzdGFjayBvZiBpdGVtcy5maWx0ZXIoKGkpID0+IGkubmFtZSA9PT0gXCJjbGkuc3RhY2tcIikpIHtcbiAgICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhzdGFjaykpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgICAgIGNvbW1hbmQ6IFwiZGVwbG95XCIsXG4gICAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGV4cGVjdChpdGVtcy5zb21lKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLnN0YWNrLmZhaWxlZFwiKSkudG9CZShmYWxzZSk7XG4gICAgICBleHBlY3QoaXRlbXMuc29tZSgoaSkgPT4gaS5uYW1lID09PSBcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiKSkudG9CZSh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY291bnRzIG92ZXJyaWRlcyBwZXIgcmVzb3VyY2UgdHlwZSwgcmVkdWNpbmcgbW9kdWxlIHNvdXJjZXMgdG8gdGhlaXIga2luZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwic3ludGhcIiwgeyBzdGFja01ldGFkYXRhLCByZXF1aXJlZFByb3ZpZGVycyB9KTtcblxuICAgICAgZXhwZWN0KG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCByZXNvdXJjZV90eXBlOiBcImF3c19zM19idWNrZXRcIiwgb3ZlcnJpZGVfY291bnQ6IDIgfSxcbiAgICAgICAgeyB2YWx1ZTogMSwgcmVzb3VyY2VfdHlwZTogXCJtb2R1bGUubG9jYWxcIiwgb3ZlcnJpZGVfY291bnQ6IDEgfSxcbiAgICAgICAgeyB2YWx1ZTogMSwgcmVzb3VyY2VfdHlwZTogXCJzdGFja1wiLCBvdmVycmlkZV9jb3VudDogMSB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImNvdW50cyByZXF1aXJlZCBwcm92aWRlcnMgYnkgbm9ybWFsaXplZCBzb3VyY2UsIHZhbGlkYXRlZCBjb25zdHJhaW50IGFuZCBiaW5kaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJkaWZmXCIsIHsgc3RhY2tNZXRhZGF0YSwgcmVxdWlyZWRQcm92aWRlcnMgfSk7XG5cbiAgICAgIGV4cGVjdChtZXRyaWNzKGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCksIFwiY2xpLnN0YWNrLnByb3ZpZGVyXCIpKS50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIHByb3ZpZGVyOiBcImhhc2hpY29ycC9hd3NcIixcbiAgICAgICAgICB2ZXJzaW9uX2NvbnN0cmFpbnQ6IFwifj4gNS4wXCIsXG4gICAgICAgICAgYmluZGluZzogXCJnZW5lcmF0ZWRcIixcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIHByb3ZpZGVyOiBcImhhc2hpY29ycC9nb29nbGVcIixcbiAgICAgICAgICB2ZXJzaW9uX2NvbnN0cmFpbnQ6IFwiaW52YWxpZFwiLFxuICAgICAgICAgIGJpbmRpbmc6IFwicHJlYnVpbHRcIixcbiAgICAgICAgfSxcbiAgICAgICAgeyB2YWx1ZTogMSwgcHJvdmlkZXI6IFwiaGFzaGljb3JwL3JhbmRvbVwiLCBiaW5kaW5nOiBcInByZWJ1aWx0XCIgfSxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIHByb3ZpZGVyOiBcImtyZXV6d2Vya2VyL2RvY2tlclwiLFxuICAgICAgICAgIHZlcnNpb25fY29uc3RyYWludDogXCIzLjAuMlwiLFxuICAgICAgICAgIGJpbmRpbmc6IFwiZ2VuZXJhdGVkXCIsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogMSxcbiAgICAgICAgICBwcm92aWRlcjogXCJwcml2YXRlLXJlZ2lzdHJ5XCIsXG4gICAgICAgICAgdmVyc2lvbl9jb25zdHJhaW50OiBcIn4+IDMuMFwiLFxuICAgICAgICAgIGJpbmRpbmc6IFwicHJlYnVpbHRcIixcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJjbGFzc2lmaWVzIGJpbmRpbmdzIGFnYWluc3QgdGhlIHByb2plY3QgdGhlIGNvbW1hbmQgc3RhcnRlZCBpbiwgbm90IHRoZSBjdXJyZW50IGN3ZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzdGFydENvbW1hbmRUZWxlbWV0cnkoXCJkaWZmXCIpO1xuICAgICAgY29uc3QgZWxzZXdoZXJlID0gcGF0aC5qb2luKHdvcmtkaXIsIFwiZWxzZXdoZXJlXCIpO1xuICAgICAgZnMubWtkaXJTeW5jKGVsc2V3aGVyZSk7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbihlbHNld2hlcmUsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICB0ZXJyYWZvcm1Qcm92aWRlcnM6IFtcImdvb2dsZVwiXSxcbiAgICAgIH0pO1xuICAgICAgcHJvY2Vzcy5jaGRpcihlbHNld2hlcmUpO1xuXG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZGlmZlwiLCB7IHN0YWNrTWV0YWRhdGEsIHJlcXVpcmVkUHJvdmlkZXJzIH0pO1xuXG4gICAgICBleHBlY3QoXG4gICAgICAgIG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuc3RhY2sucHJvdmlkZXJcIikubWFwKChwKSA9PiBbXG4gICAgICAgICAgcC5wcm92aWRlcixcbiAgICAgICAgICBwLmJpbmRpbmcsXG4gICAgICAgIF0pLFxuICAgICAgKS50b0VxdWFsKFtcbiAgICAgICAgW1wiaGFzaGljb3JwL2F3c1wiLCBcImdlbmVyYXRlZFwiXSxcbiAgICAgICAgW1wiaGFzaGljb3JwL2dvb2dsZVwiLCBcInByZWJ1aWx0XCJdLFxuICAgICAgICBbXCJoYXNoaWNvcnAvcmFuZG9tXCIsIFwicHJlYnVpbHRcIl0sXG4gICAgICAgIFtcImtyZXV6d2Vya2VyL2RvY2tlclwiLCBcImdlbmVyYXRlZFwiXSxcbiAgICAgICAgW1wicHJpdmF0ZS1yZWdpc3RyeVwiLCBcInByZWJ1aWx0XCJdLFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdC5lYWNoKFszLCAzMDBdKShcbiAgICAgIFwic2VuZHMgdGhlIHNhbWUgc3RhY2sgZXZlbnRzIGZvciAlZCBhbGlrZSBzdGFja3MsIHdpdGggdGhlIHN0YWNrIGNvdW50IGFzIHRoZWlyIHZhbHVlXCIsXG4gICAgICBhc3luYyAoY291bnQpID0+IHtcbiAgICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7XG4gICAgICAgICAgc3RhY2tNZXRhZGF0YTogQXJyYXkuZnJvbSh7IGxlbmd0aDogY291bnQgfSwgKF8sIGkpID0+ICh7XG4gICAgICAgICAgICB2ZXJzaW9uOiBcIjAuMjEuMFwiLFxuICAgICAgICAgICAgc3RhY2tOYW1lOiBgc3RhY2stJHtpfWAsXG4gICAgICAgICAgICBiYWNrZW5kOiBcInMzXCIsXG4gICAgICAgICAgICBvdmVycmlkZXM6IHsgYXdzX3MzX2J1Y2tldDogW1widGFnc1wiXSB9LFxuICAgICAgICAgIH0pKSxcbiAgICAgICAgICByZXF1aXJlZFByb3ZpZGVyczogQXJyYXkuZnJvbSh7IGxlbmd0aDogY291bnQgfSwgKCkgPT4gKHtcbiAgICAgICAgICAgIGF3czogeyBzb3VyY2U6IFwiYXdzXCIsIHZlcnNpb246IFwifj4gNS4wXCIgfSxcbiAgICAgICAgICAgIHJhbmRvbTogeyBzb3VyY2U6IFwiaGFzaGljb3JwL3JhbmRvbVwiIH0sXG4gICAgICAgICAgfSkpLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBpdGVtcyA9IGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCk7XG4gICAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFja1wiKSkudG9FcXVhbChbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdmFsdWU6IGNvdW50LFxuICAgICAgICAgICAgYmFja2VuZDogXCJzM1wiLFxuICAgICAgICAgICAgY2xvdWQ6IGZhbHNlLFxuICAgICAgICAgICAgbGlicmFyeV92ZXJzaW9uOiBcIjAuMjEuMFwiLFxuICAgICAgICAgICAgb3ZlcnJpZGVfY291bnQ6IGNvdW50LFxuICAgICAgICAgICAgaW1wb3J0X2NvdW50OiAwLFxuICAgICAgICAgICAgbW92ZWRfY291bnQ6IDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFjay5wcm92aWRlclwiKSkudG9FcXVhbChbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdmFsdWU6IGNvdW50LFxuICAgICAgICAgICAgcHJvdmlkZXI6IFwiaGFzaGljb3JwL2F3c1wiLFxuICAgICAgICAgICAgdmVyc2lvbl9jb25zdHJhaW50OiBcIn4+IDUuMFwiLFxuICAgICAgICAgICAgYmluZGluZzogXCJnZW5lcmF0ZWRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgdmFsdWU6IGNvdW50LCBwcm92aWRlcjogXCJoYXNoaWNvcnAvcmFuZG9tXCIsIGJpbmRpbmc6IFwicHJlYnVpbHRcIiB9LFxuICAgICAgICBdKTtcbiAgICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLnN0YWNrLm92ZXJyaWRlXCIpKS50b0VxdWFsKFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YWx1ZTogY291bnQsXG4gICAgICAgICAgICByZXNvdXJjZV90eXBlOiBcImF3c19zM19idWNrZXRcIixcbiAgICAgICAgICAgIG92ZXJyaWRlX2NvdW50OiBjb3VudCxcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGl0KFwiZ3JvdXBzIHByb3ZpZGVycyBvbiB3aGF0IGlzIHNlbnQ6IHNwZWxsaW5ncyBhbmQgcHJpdmF0ZSBob3N0cyBjb2xsYXBzZSwgY29uc3RyYWludHMgZG8gbm90XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IFt7fSwge30sIHt9XSxcbiAgICAgICAgcmVxdWlyZWRQcm92aWRlcnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhd3M6IHsgc291cmNlOiBcImF3c1wiLCB2ZXJzaW9uOiBcIn4+NS4wXCIgfSxcbiAgICAgICAgICAgIHZhdWx0OiB7IHNvdXJjZTogXCJ0ZmUubGVhay1vbmUuZXhhbXBsZS9sZWFrLW9yZy1vbmUvdmF1bHRcIiB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgYXdzOiB7IHNvdXJjZTogXCJIYXNoaWNvcnAvQVdTXCIsIHZlcnNpb246IFwifj4gNS4wXCIgfSxcbiAgICAgICAgICAgIC8vIGEgc3RhY2sgY291bnRzIG9uY2UgcGVyIGdyb3VwLCBob3dldmVyIG1hbnkgZW50cmllcyByZWFjaCBpdFxuICAgICAgICAgICAgdmF1bHQ6IHsgc291cmNlOiBcInJlZ2lzdHJ5LmxlYWstdHdvLmV4YW1wbGUvbGVhay1vcmctdHdvL3ZhdWx0XCIgfSxcbiAgICAgICAgICAgIGNvbnN1bDogeyBzb3VyY2U6IFwibWlycm9yLmxlYWstdGhyZWUuZXhhbXBsZS9sZWFrLW9yZy10d28vY29uc3VsXCIgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGF3czoge1xuICAgICAgICAgICAgICBzb3VyY2U6IFwicmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9hd3NcIixcbiAgICAgICAgICAgICAgdmVyc2lvbjogXCJ+PiA1LjBcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhd3M2OiB7IHNvdXJjZTogXCJhd3NcIiwgdmVyc2lvbjogXCJ+PiA2LjBcIiB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuc3RhY2sucHJvdmlkZXJcIikpLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDMsXG4gICAgICAgICAgcHJvdmlkZXI6IFwiaGFzaGljb3JwL2F3c1wiLFxuICAgICAgICAgIHZlcnNpb25fY29uc3RyYWludDogXCJ+PiA1LjBcIixcbiAgICAgICAgICBiaW5kaW5nOiBcImdlbmVyYXRlZFwiLFxuICAgICAgICB9LFxuICAgICAgICB7IHZhbHVlOiAyLCBwcm92aWRlcjogXCJwcml2YXRlLXJlZ2lzdHJ5XCIsIGJpbmRpbmc6IFwicHJlYnVpbHRcIiB9LFxuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDEsXG4gICAgICAgICAgcHJvdmlkZXI6IFwiaGFzaGljb3JwL2F3c1wiLFxuICAgICAgICAgIHZlcnNpb25fY29uc3RyYWludDogXCJ+PiA2LjBcIixcbiAgICAgICAgICBiaW5kaW5nOiBcImdlbmVyYXRlZFwiLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcImxlYWtcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInN1bXMgdGhlIGdyb3VwIHNpemVzIG9mIHRoZSBzdGFja3MgaW4gYSBncm91cCBhbmQgdGhlIHBhdGhzIG9mIGFuIG92ZXJyaWRlIHR5cGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YTogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGJhY2tlbmQ6IFwibG9jYWxcIixcbiAgICAgICAgICAgIG92ZXJyaWRlczogeyBhd3NfczNfYnVja2V0OiBbXCJhXCIsIFwiYlwiLCBcImNcIl0sIFwiYmFkIGtleSAxXCI6IFtcInhcIl0gfSxcbiAgICAgICAgICAgIGltcG9ydHM6IHsgYXdzX3MzX2J1Y2tldDogW1wiaWRcIl0gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGJhY2tlbmQ6IFwibG9jYWxcIixcbiAgICAgICAgICAgIG92ZXJyaWRlczoge1xuICAgICAgICAgICAgICBhd3NfczNfYnVja2V0OiBbXCJhXCJdLFxuICAgICAgICAgICAgICBcImJhZCBrZXkgMlwiOiBbXCJ4XCJdLFxuICAgICAgICAgICAgICBcImJhZCBrZXkgM1wiOiBbXCJ4XCIsIFwieVwiLCBcInpcIl0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW92ZWQ6IHsgYXdzX3MzX2J1Y2tldDogW1wiaWRcIiwgXCJpZFwiXSB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBhd2FpdCBkZWxpdmVyZWRJdGVtcygpO1xuICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLnN0YWNrXCIpKS50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAyLFxuICAgICAgICAgIGJhY2tlbmQ6IFwibG9jYWxcIixcbiAgICAgICAgICBjbG91ZDogZmFsc2UsXG4gICAgICAgICAgb3ZlcnJpZGVfY291bnQ6IDksXG4gICAgICAgICAgaW1wb3J0X2NvdW50OiAxLFxuICAgICAgICAgIG1vdmVkX2NvdW50OiAyLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAyLCByZXNvdXJjZV90eXBlOiBcImF3c19zM19idWNrZXRcIiwgb3ZlcnJpZGVfY291bnQ6IDQgfSxcbiAgICAgICAgeyB2YWx1ZTogMiwgcmVzb3VyY2VfdHlwZTogXCJvdGhlclwiLCBvdmVycmlkZV9jb3VudDogNSB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImtlZXBzIHRoZSAzMiBtb3N0IHJlcXVpcmVkIHByb3ZpZGVycyBhbmQgZm9sZHMgdGhlIHJlc3QgaW50byBvbmUgdHJ1bmNhdGVkIGNvdW50XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNvdXJjZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICB7IGxlbmd0aDogNDAgfSxcbiAgICAgICAgKF8sIGspID0+IGBhY21lL3Ake1N0cmluZyhrKS5wYWRTdGFydCgyLCBcIjBcIil9YCxcbiAgICAgICk7XG4gICAgICAvLyBwcm92aWRlciBrIGlzIHJlcXVpcmVkIGJ5IDQwIC0gayBzdGFja3NcbiAgICAgIGNvbnN0IHJlcXVpcmVkQnlTdGFjayA9IHNvdXJjZXMubWFwKChfLCBzdGFjaykgPT5cbiAgICAgICAgT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICAgIHNvdXJjZXNcbiAgICAgICAgICAgIC5zbGljZSgwLCBzb3VyY2VzLmxlbmd0aCAtIHN0YWNrKVxuICAgICAgICAgICAgLm1hcCgoc291cmNlLCBrKSA9PiBbYHAke2t9YCwgeyBzb3VyY2UgfV0pLFxuICAgICAgICApLFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YTogc291cmNlcy5tYXAoKCkgPT4gKHt9KSksXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzOiByZXF1aXJlZEJ5U3RhY2ssXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcHJvdmlkZXJzID0gbWV0cmljcyhhd2FpdCBkZWxpdmVyZWRJdGVtcygpLCBcImNsaS5zdGFjay5wcm92aWRlclwiKTtcbiAgICAgIGV4cGVjdChwcm92aWRlcnMpLnRvRXF1YWwoW1xuICAgICAgICAuLi5zb3VyY2VzLnNsaWNlKDAsIDMyKS5tYXAoKHByb3ZpZGVyLCBrKSA9PiAoe1xuICAgICAgICAgIHZhbHVlOiA0MCAtIGssXG4gICAgICAgICAgcHJvdmlkZXIsXG4gICAgICAgICAgYmluZGluZzogXCJwcmVidWlsdFwiLFxuICAgICAgICB9KSksXG4gICAgICAgIHsgdmFsdWU6IDM2LCB0cnVuY2F0ZWQ6IHRydWUgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KHByb3ZpZGVycy5yZWR1Y2UoKHRvdGFsLCBwKSA9PiB0b3RhbCArIHAudmFsdWUsIDApKS50b0JlKDgyMCk7XG4gICAgfSk7XG5cbiAgICBpdChcImtlZXBzIHRoZSBmaXJzdCAzMiBvdmVycmlkZSB0eXBlcyBieSBuYW1lIG9uIGEgdGllIGFuZCBmb2xkcyB0aGUgcmVzdCB3aXRoIHRoZWlyIHBhdGhzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR5cGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgeyBsZW5ndGg6IDM0IH0sXG4gICAgICAgIChfLCBrKSA9PiBgYXdzX3Qke1N0cmluZyhrKS5wYWRTdGFydCgyLCBcIjBcIil9YCxcbiAgICAgICk7XG4gICAgICBjb25zdCBsb25nZXI6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHtcbiAgICAgICAgYXdzX3QzMjogW1wiYVwiLCBcImJcIl0sXG4gICAgICAgIGF3c190MzM6IFtcImFcIiwgXCJiXCIsIFwiY1wiXSxcbiAgICAgIH07XG4gICAgICBjb25zdCBwYXRocyA9ICh0eXBlOiBzdHJpbmcpID0+IGxvbmdlclt0eXBlXSA/PyBbXCJhXCJdO1xuXG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwic3ludGhcIiwge1xuICAgICAgICBzdGFja01ldGFkYXRhOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgb3ZlcnJpZGVzOiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgICAgICAgIFsuLi50eXBlc10ucmV2ZXJzZSgpLm1hcCgodHlwZSkgPT4gW3R5cGUsIHBhdGhzKHR5cGUpXSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIikpLnRvRXF1YWwoW1xuICAgICAgICAuLi50eXBlcy5zbGljZSgwLCAzMikubWFwKChyZXNvdXJjZV90eXBlKSA9PiAoe1xuICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgIHJlc291cmNlX3R5cGUsXG4gICAgICAgICAgb3ZlcnJpZGVfY291bnQ6IDEsXG4gICAgICAgIH0pKSxcbiAgICAgICAgeyB2YWx1ZTogMiwgb3ZlcnJpZGVfY291bnQ6IDUsIHRydW5jYXRlZDogdHJ1ZSB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImtlZXBzIHRoZSA4IGxhcmdlc3Qgc3RhY2sgZ3JvdXBzIGFuZCBmb2xkcyB0aGUgcmVzdCB3aXRoIHRoZWlyIGdyb3VwIHNpemVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIGxpYnJhcnkgdmVyc2lvbiAwLmsuMCBpcyB1c2VkIGJ5IGsgKyAxIHN0YWNrcywgZWFjaCB3aXRoIG9uZSBpbXBvcnRcbiAgICAgIGNvbnN0IHN0YWNrc09mVmVyc2lvbiA9IChrOiBudW1iZXIpID0+XG4gICAgICAgIEFycmF5LmZyb20oeyBsZW5ndGg6IGsgKyAxIH0sICgpID0+ICh7XG4gICAgICAgICAgdmVyc2lvbjogYDAuJHtrfS4wYCxcbiAgICAgICAgICBiYWNrZW5kOiBcInMzXCIsXG4gICAgICAgICAgaW1wb3J0czogeyBhd3NfczNfYnVja2V0OiBbXCJpZFwiXSB9LFxuICAgICAgICB9KSk7XG5cbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IEFycmF5LmZyb20oeyBsZW5ndGg6IDEwIH0sIChfLCBrKSA9PlxuICAgICAgICAgIHN0YWNrc09mVmVyc2lvbihrKSxcbiAgICAgICAgKS5mbGF0KCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc3RhY2tzID0gbWV0cmljcyhhd2FpdCBkZWxpdmVyZWRJdGVtcygpLCBcImNsaS5zdGFja1wiKTtcbiAgICAgIGV4cGVjdChzdGFja3MpLnRvRXF1YWwoW1xuICAgICAgICAuLi5bOSwgOCwgNywgNiwgNSwgNCwgMywgMl0ubWFwKChrKSA9PiAoe1xuICAgICAgICAgIHZhbHVlOiBrICsgMSxcbiAgICAgICAgICBiYWNrZW5kOiBcInMzXCIsXG4gICAgICAgICAgY2xvdWQ6IGZhbHNlLFxuICAgICAgICAgIGxpYnJhcnlfdmVyc2lvbjogYDAuJHtrfS4wYCxcbiAgICAgICAgICAuLi5ub0NvdW50cyxcbiAgICAgICAgICBpbXBvcnRfY291bnQ6IGsgKyAxLFxuICAgICAgICB9KSksXG4gICAgICAgIHsgdmFsdWU6IDMsIHRydW5jYXRlZDogdHJ1ZSwgLi4ubm9Db3VudHMsIGltcG9ydF9jb3VudDogMyB9LFxuICAgICAgXSk7XG4gICAgICBleHBlY3Qoc3RhY2tzLnJlZHVjZSgodG90YWwsIHMpID0+IHRvdGFsICsgcy52YWx1ZSwgMCkpLnRvQmUoNTUpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJib3VuZHMgdGhlIHN0YWNrIGV2ZW50cyBvZiBhIHJ1biB3aGF0ZXZlciB0aGUgcHJvamVjdCdzIHNoYXBlLCBpbiB0aGUgZW52ZWxvcGUgb2YgdGhlIGNvbW1hbmQgbWV0cmljXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZvcnR5ID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogNDAgfSwgKF8sIGspID0+IGspO1xuXG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZGVwbG95XCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YTogQXJyYXkuZnJvbSh7IGxlbmd0aDogMzAwIH0sIChfLCBpKSA9PiAoe1xuICAgICAgICAgIHZlcnNpb246IGAxLiR7aX0uMGAsXG4gICAgICAgICAgb3ZlcnJpZGVzOiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgICAgICBmb3J0eS5tYXAoKGspID0+IFtgYXdzX3R5cGVfJHtrfWAsIFtcInRhZ3NcIl1dKSxcbiAgICAgICAgICApLFxuICAgICAgICB9KSksXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzOiBBcnJheS5mcm9tKHsgbGVuZ3RoOiAzMDAgfSwgKCkgPT5cbiAgICAgICAgICBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgICAgICBmb3J0eS5tYXAoKGspID0+IFtgcCR7a31gLCB7IHNvdXJjZTogYGFjbWUvcCR7a31gIH1dKSxcbiAgICAgICAgICApLFxuICAgICAgICApLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgIGNvbnN0IGNvdW50ID0gKG5hbWU6IHN0cmluZykgPT4gbWV0cmljcyhpdGVtcywgbmFtZSkubGVuZ3RoO1xuICAgICAgY29uc3QgdG90YWwgPSAobmFtZTogc3RyaW5nKSA9PlxuICAgICAgICBtZXRyaWNzKGl0ZW1zLCBuYW1lKS5yZWR1Y2UoKHN1bSwgbSkgPT4gc3VtICsgbS52YWx1ZSwgMCk7XG4gICAgICBleHBlY3QoW1xuICAgICAgICBjb3VudChcImNsaS5zdGFja1wiKSxcbiAgICAgICAgY291bnQoXCJjbGkuc3RhY2sucHJvdmlkZXJcIiksXG4gICAgICAgIGNvdW50KFwiY2xpLnN0YWNrLm92ZXJyaWRlXCIpLFxuICAgICAgXSkudG9FcXVhbChbOSwgMzMsIDMzXSk7XG4gICAgICBleHBlY3QodG90YWwoXCJjbGkuc3RhY2tcIikpLnRvQmUoMzAwKTtcbiAgICAgIGV4cGVjdCh0b3RhbChcImNsaS5zdGFjay5wcm92aWRlclwiKSkudG9CZSgzMDAgKiA0MCk7XG4gICAgICBleHBlY3QoY291bnQoXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIikpLnRvQmUoMSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMpLnRvSGF2ZUxlbmd0aCgxKTtcbiAgICB9KTtcblxuICAgIGl0KFwibGVhdmVzIHRoZSBzdGFja3MgdG8gdGhlIGNvbW1hbmQgd2hlbiBpdHMgc3ludGggaXMgbmVzdGVkOiBvbmx5IHRoZSBzZWxlY3RlZCBvbmVzLCB1bmRlciBpdHMgbmFtZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzdGFydENvbW1hbmRUZWxlbWV0cnkoXCJkZXBsb3lcIik7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwic3ludGhcIiwge1xuICAgICAgICB0b3RhbFRpbWU6IDQyLFxuICAgICAgICBzdGFja01ldGFkYXRhLFxuICAgICAgICByZXF1aXJlZFByb3ZpZGVycyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IHN0YWNrTWV0YWRhdGEuc2xpY2UoMSksXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzOiByZXF1aXJlZFByb3ZpZGVycy5zbGljZSgxKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIGl0ZW1zXG4gICAgICAgICAgLmZpbHRlcigoaSkgPT4gaS5uYW1lLnN0YXJ0c1dpdGgoXCJjbGkuc3RhY2tcIikpXG4gICAgICAgICAgLm1hcCgoaSkgPT4gW2kubmFtZSwgYXR0cmlidXRlVmFsdWVzKGkpLmNvbW1hbmQsIGkudmFsdWVdKSxcbiAgICAgICkudG9FcXVhbChbXG4gICAgICAgIFtcImNsaS5zdGFja1wiLCBcImRlcGxveVwiLCAxXSxcbiAgICAgICAgW1wiY2xpLnN0YWNrLnByb3ZpZGVyXCIsIFwiZGVwbG95XCIsIDFdLFxuICAgICAgICBbXCJjbGkuc3RhY2sucHJvdmlkZXJcIiwgXCJkZXBsb3lcIiwgMV0sXG4gICAgICBdKTtcbiAgICAgIGV4cGVjdChcbiAgICAgICAgaXRlbXMuc29tZShcbiAgICAgICAgICAoaSkgPT5cbiAgICAgICAgICAgIGkubmFtZSA9PT0gXCJjbGkuc3ludGguZHVyYXRpb25cIiAmJlxuICAgICAgICAgICAgYXR0cmlidXRlVmFsdWVzKGkpLmNvbW1hbmQgPT09IFwic3ludGhcIixcbiAgICAgICAgKSxcbiAgICAgICkudG9CZSh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KFwicmVwb3J0cyB0aGUgc3RhY2tzIG9mIGEgc3ludGggcnVuIHVuZGVyIHN5bnRoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHsgc3RhY2tNZXRhZGF0YSwgcmVxdWlyZWRQcm92aWRlcnMgfSk7XG5cbiAgICAgIGNvbnN0IHN0YWNrcyA9IChhd2FpdCBkZWxpdmVyZWRJdGVtcygpKS5maWx0ZXIoXG4gICAgICAgIChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLnN0YWNrXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KHN0YWNrcy5tYXAoKGkpID0+IGF0dHJpYnV0ZVZhbHVlcyhpKS5jb21tYW5kKSkudG9FcXVhbChbXG4gICAgICAgIFwic3ludGhcIixcbiAgICAgICAgXCJzeW50aFwiLFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcInJlcG9ydHMgdGhlIHN0YWNrcyBvbmNlIHBlciBwcm9jZXNzOiBhIHdhdGNoIHNlc3Npb24ncyBsYXRlciBkZXBsb3lzIGFkZCBvbmx5IHRoZWlyIGZhaWx1cmVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcIndhdGNoXCIpO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7IHN0YWNrTWV0YWRhdGEsIHJlcXVpcmVkUHJvdmlkZXJzIH0pO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGEsXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzLFxuICAgICAgICBmYWlsZWRTdGFja0NvdW50OiAxLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFja1wiKSkudG9IYXZlTGVuZ3RoKDIpO1xuICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLnN0YWNrLnByb3ZpZGVyXCIpKS50b0hhdmVMZW5ndGgoNSk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIikpLnRvSGF2ZUxlbmd0aCgzKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFjay5mYWlsZWRcIikpLnRvRXF1YWwoW3sgdmFsdWU6IDEgfV0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJjb3VudHMgZmFpbGVkIHN0YWNrcyBhbmQgbmV2ZXIgc2VyaWFsaXplcyB0aGVpciBmYWlsdXJlIG1lc3NhZ2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJkZXN0cm95XCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YSxcbiAgICAgICAgcmVxdWlyZWRQcm92aWRlcnMsXG4gICAgICAgIGZhaWxlZFN0YWNrQ291bnQ6IDIsXG4gICAgICAgIGZhaWxlZFN0YWNrczogW1wiZmFpbGVkIHRvIGRlc3Ryb3kgU0VDUkVULVNUQUNLLU5BTUU6IC9Vc2Vycy94L3N0YXRlXCJdLFxuICAgICAgfSk7XG4gICAgICBleHBlY3QoYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApKS50b0JlKHRydWUpO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpO1xuICAgICAgY29uc3QgZmFpbGVkID0gaXRlbXMuZmluZCgoaSkgPT4gaS5uYW1lID09PSBcImNsaS5zdGFjay5mYWlsZWRcIikhO1xuICAgICAgZXhwZWN0KGZhaWxlZC52YWx1ZSkudG9CZSgyKTtcbiAgICAgIGV4cGVjdChmYWlsZWQuYXR0cmlidXRlcy5jb21tYW5kLnZhbHVlKS50b0JlKFwiZGVzdHJveVwiKTtcbiAgICAgIC8vIHRoZSBmYWlsdXJlIHRocm93biBuZXh0IGlzIGNvdW50ZWQgYXMgY2xpLmNvbW1hbmQuZXJyb3IsIG5vdCBoZXJlXG4gICAgICBleHBlY3QoaXRlbXMuc29tZSgoaSkgPT4gaS5uYW1lID09PSBcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiKSkudG9CZShmYWxzZSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcImZhaWxlZCB0byBkZXN0cm95XCIpO1xuICAgICAgZXhwZWN0KGVudmVsb3BlQm9kaWVzLmpvaW4oXCJcXG5cIikpLm5vdC50b0NvbnRhaW4oXCIvVXNlcnMveFwiKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY291bnRzIG5vIGNvbXBsZXRlZCBydW4gYW5kIG5vIGZhaWxlZCBzdGFjayBmb3IgYSBydW4gdGhhdCBmYWlsZWQgYmVmb3JlIGFueSBzdGFjayBkaWRcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGEsXG4gICAgICAgIHJlcXVpcmVkUHJvdmlkZXJzLFxuICAgICAgICBmYWlsZWRTdGFja0NvdW50OiAwLFxuICAgICAgICBydW5GYWlsZWQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBhd2FpdCBkZWxpdmVyZWRJdGVtcygpO1xuICAgICAgZXhwZWN0KG1ldHJpY3MoaXRlbXMsIFwiY2xpLnN0YWNrXCIpKS50b0hhdmVMZW5ndGgoMik7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuc3RhY2suZmFpbGVkXCIpKS50b0VxdWFsKFtdKTtcbiAgICAgIGV4cGVjdChpdGVtcy5zb21lKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIpKS50b0JlKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KFwibmV2ZXIgc2VyaWFsaXplcyBzdGFjayBuYW1lcywgcmVzb3VyY2UgaWRzIG9yIG1vZHVsZSBwYXRoc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZGVwbG95XCIsIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgICBzdGFja01ldGFkYXRhLFxuICAgICAgICByZXF1aXJlZFByb3ZpZGVycyxcbiAgICAgICAgZmFpbGVkU3RhY2tDb3VudDogMSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCk7XG4gICAgICAvLyB0aGUgc2NhbiBiZWxvdyBpcyBvdmVyIHR3byBzdGFja3MsIHRocmVlIG92ZXJyaWRlIHR5cGVzLCBmaXZlXG4gICAgICAvLyBwcm92aWRlcnMgYW5kIHRoZSBmYWlsZWQgY291bnRcbiAgICAgIGV4cGVjdChpdGVtcy5maWx0ZXIoKGkpID0+IGkubmFtZS5zdGFydHNXaXRoKFwiY2xpLnN0YWNrXCIpKSkudG9IYXZlTGVuZ3RoKFxuICAgICAgICAxMSxcbiAgICAgICk7XG4gICAgICBjb25zdCBieXRlcyA9IGVudmVsb3BlQm9kaWVzLmpvaW4oXCJcXG5cIik7XG4gICAgICBleHBlY3QoYnl0ZXMpLm5vdC50b0NvbnRhaW4oXCJTRUNSRVQtU1RBQ0stTkFNRVwiKTtcbiAgICAgIGV4cGVjdChieXRlcykubm90LnRvQ29udGFpbihcInNlY3JldC1yZXNvdXJjZS1pZFwiKTtcbiAgICAgIGV4cGVjdChieXRlcykubm90LnRvQ29udGFpbihcInNlY3JldC1wYXRoXCIpO1xuICAgICAgZXhwZWN0KGJ5dGVzKS5ub3QudG9Db250YWluKFwidGZlLmNvcnAuZXhhbXBsZS5jb21cIik7XG4gICAgICBleHBlY3QoYnl0ZXMpLm5vdC50b0NvbnRhaW4oXCJhY21lLW9yZ1wiKTtcbiAgICB9KTtcblxuICAgIC8vIHRoZSBtZXRhZGF0YSBpcyByZWFkIGZyb20gZGlzaywgd3JpdHRlbiBieSB3aGF0ZXZlciBsaWJyYXJ5IHZlcnNpb25cbiAgICAvLyB0aGUgcHJvamVjdCBoYXNcbiAgICBpdChcInRvbGVyYXRlcyBtYWxmb3JtZWQgbWV0YWRhdGEgZW50cmllcyBhbmQgY291bnRzIG9ubHkgdGhlIHJlYWwgc3RhY2tzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IFtudWxsLCBcIm5vcGVcIiwgeyBvdmVycmlkZXM6IFwibm9wZVwiLCBpbXBvcnRzOiBbXSB9XSxcbiAgICAgICAgcmVxdWlyZWRQcm92aWRlcnM6IFt1bmRlZmluZWQsIHVuZGVmaW5lZCwgeyBhd3M6IFwibm9wZVwiIH1dLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFja1wiKSkudG9FcXVhbChbXG4gICAgICAgIHsgdmFsdWU6IDEsIGJhY2tlbmQ6IFwidW5rbm93blwiLCBjbG91ZDogZmFsc2UsIC4uLm5vQ291bnRzIH0sXG4gICAgICBdKTtcbiAgICAgIGV4cGVjdChtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFjay5vdmVycmlkZVwiKSkudG9FcXVhbChbXSk7XG4gICAgICBleHBlY3QobWV0cmljcyhpdGVtcywgXCJjbGkuc3RhY2sucHJvdmlkZXJcIikpLnRvRXF1YWwoW1xuICAgICAgICB7IHZhbHVlOiAxLCBwcm92aWRlcjogXCJoYXNoaWNvcnAvYXdzXCIsIGJpbmRpbmc6IFwiZ2VuZXJhdGVkXCIgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KGl0ZW1zLnNvbWUoKGkpID0+IGkubmFtZSA9PT0gXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIikpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiYXR0cmlidXRlIHZhbGlkYXRpb25cIiwgKCkgPT4ge1xuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwib21pdHMgYW4gdW5zdXBwb3J0ZWQgbGFuZ3VhZ2UsIHJlYWQgZnJvbSBjZGt0Zi5qc29uIGF0IHN0YXJ0IG9yIHBhc3NlZCBhdCB0aGUgZW5kXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICBsYW5ndWFnZTogXCJydXN0OyBEUk9QIFRBQkxFXCIsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgc3RhcnRDb21tYW5kVGVsZW1ldHJ5KFwiY29udmVydFwiKTtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJjb252ZXJ0XCIsIHsgbGFuZ3VhZ2U6IFwiY29ib2w7IERST1AgVEFCTEVcIiB9KTtcbiAgICAgIGV4cGVjdChhd2FpdCBTZW50cnkuZmx1c2goMjAwMCkpLnRvQmUodHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcyk7XG4gICAgICBleHBlY3QoaXRlbXMubWFwKChpKSA9PiBpLm5hbWUpKS50b0VxdWFsKFtcbiAgICAgICAgXCJjbGkuY29tbWFuZC5pbnZva2VkXCIsXG4gICAgICAgIFwiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIsXG4gICAgICBdKTtcbiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICBleHBlY3QoaXRlbS5hdHRyaWJ1dGVzKS5ub3QudG9IYXZlUHJvcGVydHkoXCJsYW5ndWFnZVwiKTtcbiAgICAgIH1cbiAgICAgIGV4cGVjdChlbnZlbG9wZUJvZGllcy5qb2luKFwiXFxuXCIpKS5ub3QudG9Db250YWluKFwiRFJPUCBUQUJMRVwiKTtcbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1wic3ludGhcIiwgeyBzeW50aE9yaWdpbjogXCJ3YXRjaFwiIH0sIFwic3ludGhfb3JpZ2luXCIsIFwid2F0Y2hcIl0sXG4gICAgICBbXCJzeW50aFwiLCB7IHN5bnRoT3JpZ2luOiBcIi9Vc2Vycy94XCIgfSwgXCJzeW50aF9vcmlnaW5cIiwgdW5kZWZpbmVkXSxcbiAgICAgIFtcImluaXRcIiwgeyBpc1JlbW90ZTogdHJ1ZSB9LCBcImlzX3JlbW90ZVwiLCB0cnVlXSxcbiAgICAgIFtcImluaXRcIiwgeyB0ZW1wbGF0ZTogXCJnb1wiIH0sIFwidGVtcGxhdGVcIiwgXCJnb1wiXSxcbiAgICAgIFtcImNvbnZlcnRcIiwgeyBudW1iZXJPZlByb3ZpZGVyczogMiB9LCBcInByb3ZpZGVyX2NvdW50XCIsIDJdLFxuICAgICAgW1wiY29udmVydFwiLCB7IG51bWJlck9mTW9kdWxlczogMSB9LCBcIm1vZHVsZV9jb3VudFwiLCAxXSxcbiAgICAgIFtcImNvbnZlcnRcIiwgeyBjb252ZXJ0ZWRMaW5lczogNDIgfSwgXCJjb252ZXJ0ZWRfbGluZXNcIiwgNDJdLFxuICAgICAgW1wiY29udmVydFwiLCB7IGNvbnZlcnRlZExpbmVzOiBcIjQyXCIgfSwgXCJjb252ZXJ0ZWRfbGluZXNcIiwgdW5kZWZpbmVkXSxcbiAgICAgIFtcImNvbnZlcnRcIiwgeyBjb252ZXJ0ZWRMaW5lczogTmFOIH0sIFwiY29udmVydGVkX2xpbmVzXCIsIHVuZGVmaW5lZF0sXG4gICAgXSkoXG4gICAgICBcIiVzOiAlaiBmb3J3YXJkcyAlcyBhcyAlalwiLFxuICAgICAgYXN5bmMgKGNvbW1hbmQsIHBheWxvYWQsIGF0dHJpYnV0ZSwgZXhwZWN0ZWQpID0+IHtcbiAgICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShjb21tYW5kLCBwYXlsb2FkKTtcbiAgICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgICBjb25zdCBjb21wbGV0ZWQgPSBwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzKS5maW5kKFxuICAgICAgICAgIChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIsXG4gICAgICAgICkhO1xuICAgICAgICBpZiAoZXhwZWN0ZWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGV4cGVjdChjb21wbGV0ZWQuYXR0cmlidXRlcykubm90LnRvSGF2ZVByb3BlcnR5KGF0dHJpYnV0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhjb21wbGV0ZWQpW2F0dHJpYnV0ZV0pLnRvQmUoZXhwZWN0ZWQpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBpdC5lYWNoKFtcbiAgICAgIFtcIj49IDEuOS4wXCIsIFwiPj0xLjkuMFwiXSxcbiAgICAgIFtcIn4xLjhcIiwgXCI+PTEuOC4wIDwxLjkuMC0wXCJdLFxuICAgICAgW1wiMS4yLjMgLSAyLjAuMFwiLCBcIj49MS4yLjMgPD0yLjAuMFwiXSxcbiAgICAgIFtcIj49MS4wLjAgPDIuMC4wIHx8IDEuMi4zXCIsIFwiPj0xLjAuMCA8Mi4wLjB8fDEuMi4zXCJdLFxuICAgICAgW1wibGF0ZXN0IC9Vc2Vycy94XCIsIFwiaW52YWxpZFwiXSxcbiAgICAgIFtcIj49IDEuMC4wLUxFQUstVFYtUFJFUkVMRUFTRS5jb3JwLmV4YW1wbGUuY29tXCIsIFwiaW52YWxpZFwiXSxcbiAgICAgIFtcIjEuMi4zLWFjbWUuaW50ZXJuYWxcIiwgXCJpbnZhbGlkXCJdLFxuICAgICAgW1wiMS4yLjMrTEVBSy1UVi1CVUlMRC5qb2hucy1tYWNib29rXCIsIFwiaW52YWxpZFwiXSxcbiAgICAgIFtcIj49MS4wLjAgPDIuMC4wIHx8IDEuMi4zLUxFQUstT1IuaG9zdFwiLCBcImludmFsaWRcIl0sXG4gICAgICBbXCI+PTEuMC4wIFwiICsgXCJ8fDEuMC4wIFwiLnJlcGVhdCgxMCksIFwiaW52YWxpZFwiXSxcbiAgICBdKShcImZvcndhcmRzIHRoZSBkZWNsYXJlZCB0YXJnZXQgJXAgYXMgJXBcIiwgKHJhbmdlLCBleHBlY3RlZCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIHRhcmdldFZlcnNpb25zOiB7IHRlcnJhZm9ybTogcmFuZ2UgfSxcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KGdldFByb2plY3RUYXJnZXRBdHRyaWJ1dGVzKHdvcmtkaXIpLnRhcmdldF90ZXJyYWZvcm0pLnRvQmUoXG4gICAgICAgIGV4cGVjdGVkLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KFwicmVkdWNlcyBhIGJhY2tlbmQgb3V0c2lkZSB0aGUgYnVpbHQtaW4ga2luZHMgYW5kIG92ZXJyaWRlIGtleXMgb3V0c2lkZSB0aGUgdHlwZSBncmFtbWFyIHRvIG90aGVyXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7XG4gICAgICAgIHN0YWNrTWV0YWRhdGE6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2ZXJzaW9uOiBcIjAuMjEuMCtidWlsZC5cIiArIFwieFwiLnJlcGVhdCg0MCksXG4gICAgICAgICAgICBiYWNrZW5kOiBcInMzIGJ1Y2tldD0vVXNlcnMveC9zdGF0ZVwiLFxuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7XG4gICAgICAgICAgICAgIGF3c19zM19idWNrZXQ6IFtcInRhZ3NcIl0sXG4gICAgICAgICAgICAgIHRlcnJhZm9ybV9yZW1vdGVfc3RhdGU6IFtcImJhY2tlbmRcIl0sXG4gICAgICAgICAgICAgIFwibW9kdWxlLnRlcnJhZm9ybS1hd3MtbW9kdWxlcy92cGMvYXdzXCI6IFtcInByb3ZpZGVyc1wiXSxcbiAgICAgICAgICAgICAgXCJyZXNvdXJjZSB3aXRoIHNwYWNlcyAvVXNlcnMveFwiOiBbXCJ0YWdzXCJdLFxuICAgICAgICAgICAgICBBV1NfUzNfQnVja2V0OiBbXCJ0YWdzXCJdLFxuICAgICAgICAgICAgICBbXCJhd3NfXCIgKyBcInhcIi5yZXBlYXQoNzApXTogW1widGFnc1wiXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IHZlcnNpb246IFwiZGV2LS9Vc2Vycy94XCIsIGJhY2tlbmQ6IFwiUzNcIiB9LFxuICAgICAgICAgIHsgdmVyc2lvbjogXCJkZXYtL1VzZXJzL3hcIiB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gYXdhaXQgZGVsaXZlcmVkSXRlbXMoKTtcbiAgICAgIC8vIGJ1aWxkIG1ldGFkYXRhIGlzIHN0cmlwcGVkIGxpa2UgYmluYXJ5X3ZlcnNpb247IGEgdmVyc2lvbiB3aXRob3V0IGFcbiAgICAgIC8vIE1BSk9SLk1JTk9SLlBBVENIIHByZWZpeCB5aWVsZHMgbm8gYXR0cmlidXRlIGF0IGFsbFxuICAgICAgZXhwZWN0KFxuICAgICAgICBtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFja1wiKS5tYXAoKHN0YWNrKSA9PiBbXG4gICAgICAgICAgc3RhY2suYmFja2VuZCxcbiAgICAgICAgICBzdGFjay5saWJyYXJ5X3ZlcnNpb24sXG4gICAgICAgIF0pLFxuICAgICAgKS50b0VxdWFsKFtcbiAgICAgICAgW1wib3RoZXJcIiwgXCIwLjIxLjBcIl0sXG4gICAgICAgIFtcIm90aGVyXCIsIHVuZGVmaW5lZF0sXG4gICAgICAgIFtcInVua25vd25cIiwgdW5kZWZpbmVkXSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KFxuICAgICAgICBtZXRyaWNzKGl0ZW1zLCBcImNsaS5zdGFjay5vdmVycmlkZVwiKS5tYXAoKG8pID0+IFtcbiAgICAgICAgICBvLnJlc291cmNlX3R5cGUsXG4gICAgICAgICAgby5vdmVycmlkZV9jb3VudCxcbiAgICAgICAgXSksXG4gICAgICApLnRvRXF1YWwoW1xuICAgICAgICBbXCJhd3NfczNfYnVja2V0XCIsIDFdLFxuICAgICAgICBbXCJtb2R1bGUudGVycmFmb3JtLWF3cy1tb2R1bGVzL3ZwYy9hd3NcIiwgMV0sXG4gICAgICAgIFtcIm90aGVyXCIsIDNdLFxuICAgICAgICBbXCJ0ZXJyYWZvcm1fcmVtb3RlX3N0YXRlXCIsIDFdLFxuICAgICAgXSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcIi9Vc2Vycy94XCIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcInByb3ZpZGVyIGJpbmRpbmcgY2xhc3NpZmljYXRpb25cIiwgKCkgPT4ge1xuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcbiAgICB9KTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGJpbmRpbmdPZihzb3VyY2U6IHN0cmluZykge1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YTogW3t9XSxcbiAgICAgICAgcmVxdWlyZWRQcm92aWRlcnM6IFt7IHByb3ZpZGVyOiB7IHNvdXJjZSB9IH1dLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbWV0cmljcyhhd2FpdCBkZWxpdmVyZWRJdGVtcygpLCBcImNsaS5zdGFjay5wcm92aWRlclwiKS5tYXAoXG4gICAgICAgIChwcm92aWRlcikgPT4gcHJvdmlkZXIuYmluZGluZyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaXQuZWFjaChbXG4gICAgICBbXCJhd3NcIiwgXCJnZW5lcmF0ZWRcIl0sXG4gICAgICBbXCJIYXNoaWNvcnAvUmFuZG9tXCIsIFwiZ2VuZXJhdGVkXCJdLFxuICAgICAgW1wia3JldXp3ZXJrZXIvZG9ja2VyXCIsIFwiZ2VuZXJhdGVkXCJdLFxuICAgICAgW1wiaGFzaGljb3JwL2dvb2dsZVwiLCBcImdlbmVyYXRlZFwiXSxcbiAgICAgIFtcImF6dXJlcm1cIiwgXCJnZW5lcmF0ZWRcIl0sXG4gICAgICBbXCJoYXNoaWNvcnAvbnVsbFwiLCBcInByZWJ1aWx0XCJdLFxuICAgICAgW1widGZlLmNvcnAuZXhhbXBsZS5jb20vYWNtZS1vcmcvdmF1bHRcIiwgXCJnZW5lcmF0ZWRcIl0sXG4gICAgICAvLyBhbm90aGVyIHByaXZhdGUgc291cmNlIGlzIG5vdCB0aGUgZ2VuZXJhdGVkIG9uZSwgZXZlbiB0aG91Z2ggYm90aFxuICAgICAgLy8gcmVhY2ggdGhlIG1ldHJpYyBhcyBcInByaXZhdGUtcmVnaXN0cnlcIlxuICAgICAgW1widGZlLmNvcnAuZXhhbXBsZS5jb20vb3RoZXItb3JnL3ZhdWx0XCIsIFwicHJlYnVpbHRcIl0sXG4gICAgXSkoXG4gICAgICBcInNlbmRzIHRoZSByZXF1aXJlZCBwcm92aWRlciAlcyBhcyAlcyBmb3IgdGhlIHByb2plY3QncyB0ZXJyYWZvcm1Qcm92aWRlcnNcIixcbiAgICAgIGFzeW5jIChzb3VyY2UsIGV4cGVjdGVkKSA9PiB7XG4gICAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICAgIHRlcnJhZm9ybVByb3ZpZGVyczogW1xuICAgICAgICAgICAgXCJhd3NAfj41LjBcIixcbiAgICAgICAgICAgIFwiaGFzaGljb3JwL3JhbmRvbUAzLjYuMFwiLFxuICAgICAgICAgICAgXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8va3JldXp3ZXJrZXIvZG9ja2VyXCIsXG4gICAgICAgICAgICB7IG5hbWU6IFwiZ29vZ2xlXCIsIHNvdXJjZTogXCJoYXNoaWNvcnAvZ29vZ2xlXCIsIHZlcnNpb246IFwifj4gNS4wXCIgfSxcbiAgICAgICAgICAgIHsgbmFtZTogXCJhenVyZXJtXCIgfSxcbiAgICAgICAgICAgIHsgdmVyc2lvbjogXCIxLjAuMFwiIH0sXG4gICAgICAgICAgICA0MixcbiAgICAgICAgICAgIFwiVEZFLmNvcnAuZXhhbXBsZS5jb20vYWNtZS1vcmcvdmF1bHRAfj4zLjBcIixcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICBleHBlY3QoYXdhaXQgYmluZGluZ09mKHNvdXJjZSkpLnRvRXF1YWwoW2V4cGVjdGVkXSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBpdChcInNlbmRzIGV2ZXJ5IHByb3ZpZGVyIGFzIHByZWJ1aWx0IHdoZW4gdGVycmFmb3JtUHJvdmlkZXJzIGlzIG5vdCBhIGxpc3RcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIHRlcnJhZm9ybVByb3ZpZGVyczogXCJhd3NcIixcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoYXdhaXQgYmluZGluZ09mKFwiYXdzXCIpKS50b0VxdWFsKFtcInByZWJ1aWx0XCJdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJzb3VyY2Ugbm9ybWFsaXphdGlvblwiLCAoKSA9PiB7XG4gICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICBpbml0U2VudHJ5V2l0aENhcHR1cmluZ1RyYW5zcG9ydCgpO1xuICAgIH0pO1xuXG4gICAgaXQuZWFjaChbXG4gICAgICBbXCJhd3NcIiwgXCJoYXNoaWNvcnAvYXdzXCJdLFxuICAgICAgW1wiYXdzQH4+NS4wXCIsIFwiaGFzaGljb3JwL2F3c1wiXSxcbiAgICAgIFtcIkhhc2hpY29ycC9BV1NANS4xLjBcIiwgXCJoYXNoaWNvcnAvYXdzXCJdLFxuICAgICAgW1wicmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9hd3NcIiwgXCJoYXNoaWNvcnAvYXdzXCJdLFxuICAgICAgW1wicmVnaXN0cnkub3BlbnRvZnUub3JnL2hhc2hpY29ycC9hd3NcIiwgXCJoYXNoaWNvcnAvYXdzXCJdLFxuICAgICAgW1widGZlLmxlYWstaG9zdC5leGFtcGxlL2xlYWstb3JnL2F3c1wiLCBcInByaXZhdGUtcmVnaXN0cnlcIl0sXG4gICAgICBbXCJsb2NhbGhvc3Q6ODA4MC9sZWFrLW9yZy9hd3NcIiwgXCJwcml2YXRlLXJlZ2lzdHJ5XCJdLFxuICAgICAgW1wiLi9sZWFrLXByb3ZpZGVyXCIsIFwib3RoZXJcIl0sXG4gICAgICBbXCIuLi9sZWFrL3Byb3ZpZGVyXCIsIFwib3RoZXJcIl0sXG4gICAgICBbXCIvYWJzL2xlYWsvcHJvdmlkZXJcIiwgXCJvdGhlclwiXSxcbiAgICAgIFtcImxlYWstYS9iL2NcIiwgXCJvdGhlclwiXSxcbiAgICAgIFtcIlwiLCBcIm90aGVyXCJdLFxuICAgICAgW1wicmVnaXN0cnkudGVycmFmb3JtLmlvL2xlYWstbmFtZXNwYWNlXCIsIFwib3RoZXJcIl0sXG4gICAgICBbYCR7XCJuXCIucmVwZWF0KDY1KX0vYXdzYCwgXCJvdGhlclwiXSxcbiAgICAgIFtgJHtcIm5cIi5yZXBlYXQoNjQpfS9hd3NgLCBgJHtcIm5cIi5yZXBlYXQoNjQpfS9hd3NgXSxcbiAgICAgIFtgJHtcIm5cIi5yZXBlYXQoNjQpfS8ke1widFwiLnJlcGVhdCg2NCl9YCwgXCJvdGhlclwiXSxcbiAgICBdKShcInNlbmRzIHRoZSBwcm92aWRlciBzb3VyY2UgJXMgYXMgJXNcIiwgYXN5bmMgKHNvdXJjZSwgZXhwZWN0ZWQpID0+IHtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJnZXRcIiwgeyB0YXJnZXRzOiBbeyB0eXBlOiBcInByb3ZpZGVyXCIsIHNvdXJjZSB9XSB9KTtcblxuICAgICAgZXhwZWN0KFxuICAgICAgICBtZXRyaWNzKGF3YWl0IGRlbGl2ZXJlZEl0ZW1zKCksIFwiY2xpLmdldC5wcm92aWRlclwiKS5tYXAoXG4gICAgICAgICAgKGl0ZW0pID0+IGl0ZW0ucHJvdmlkZXIsXG4gICAgICAgICksXG4gICAgICApLnRvRXF1YWwoW2V4cGVjdGVkXSk7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcImxlYWtcIik7XG4gICAgfSk7XG5cbiAgICBpdC5lYWNoKFtcbiAgICAgIFtcInRlcnJhZm9ybS1hd3MtbW9kdWxlcy92cGMvYXdzXCIsIFwidGVycmFmb3JtLWF3cy1tb2R1bGVzL3ZwYy9hd3NcIl0sXG4gICAgICBbXCJUZXJyYWZvcm0tQVdTLU1vZHVsZXMvVlBDL2F3c1wiLCBcInRlcnJhZm9ybS1hd3MtbW9kdWxlcy92cGMvYXdzXCJdLFxuICAgICAgLy8gb25lIHJvdyBwZXIgZmFsbHRocm91Z2g6IGV2ZXJ5dGhpbmcgdGhlIGdyYW1tYXIgcmVqZWN0cyBpcyBcIm90aGVyXCJcbiAgICAgIFtcIlRlcnJhZm9ybS1BV1MtTW9kdWxlcy9sZWFrLXZwYy9hd3M/cmVmPXY1LjAuMFwiLCBcIm90aGVyXCJdLFxuICAgICAgW2Ake1wiblwiLnJlcGVhdCg2NCl9L3ZwYy9hd3NgLCBgJHtcIm5cIi5yZXBlYXQoNjQpfS92cGMvYXdzYF0sXG4gICAgICBbYCR7XCJuXCIucmVwZWF0KDY1KX0vdnBjL2F3c2AsIFwib3RoZXJcIl0sXG4gICAgICBbXCJhcHAudGVycmFmb3JtLmlvL2xlYWstb3JnL3ZwYy9hd3NcIiwgXCJwcml2YXRlLXJlZ2lzdHJ5XCJdLFxuICAgICAgW1wiLi9tb2R1bGVzL2xlYWstdnBjXCIsIFwibG9jYWxcIl0sXG4gICAgICBbXCIuLi9zaGFyZWQvbGVhay12cGNcIiwgXCJsb2NhbFwiXSxcbiAgICAgIFtcIi9hYnMvcGF0aC9sZWFrLXZwY1wiLCBcImxvY2FsXCJdLFxuICAgICAgW1wiZ2l0QGdpdGh1Yi5jb206bGVhay1vcmcvcmVwby5naXRcIiwgXCJnaXRcIl0sXG4gICAgICBbXCJnaXRodWIuY29tL2xlYWstb3JnL3JlcG9cIiwgXCJnaXRcIl0sXG4gICAgICBbXCJiaXRidWNrZXQub3JnL2xlYWstb3JnL3JlcG9cIiwgXCJnaXRcIl0sXG4gICAgICBbXCJodHRwczovL2xlYWstaG9zdC5leGFtcGxlL3ZwYy56aXBcIiwgXCJnaXRcIl0sXG4gICAgICBbXCJzMy1ldS13ZXN0LTEuYW1hem9uYXdzLmNvbS9sZWFrLWJ1Y2tldC92cGMuemlwXCIsIFwiZ2l0XCJdLFxuICAgICAgW1wid3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvbGVhay1idWNrZXQvdnBjXCIsIFwiZ2l0XCJdLFxuICAgICAgLy8gZm9yY2VkIGdldHRlcnMgd2l0aG91dCBhIFVSTCBzY2hlbWUgYmVoaW5kIHRoZW1cbiAgICAgIFtcImdpdDo6bGVhay1ob3N0LmV4YW1wbGUvbGVhay1vcmcvcmVwby5naXRcIiwgXCJnaXRcIl0sXG4gICAgICBbXCJoZzo6bGVhay1ob3N0LmV4YW1wbGUvbGVhay1yZXBvXCIsIFwiZ2l0XCJdLFxuICAgICAgW1wiczM6OmxlYWstYnVja2V0L3ZwYy56aXBcIiwgXCJnaXRcIl0sXG4gICAgICBbXCJnY3M6OmxlYWstYnVja2V0L3ZwY1wiLCBcImdpdFwiXSxcbiAgICBdKShcInNlbmRzIHRoZSBtb2R1bGUgc291cmNlICVzIGFzICVzXCIsIGFzeW5jIChzb3VyY2UsIGV4cGVjdGVkKSA9PiB7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiZ2V0XCIsIHsgdGFyZ2V0czogW3sgdHlwZTogXCJtb2R1bGVcIiwgc291cmNlIH1dIH0pO1xuXG4gICAgICBleHBlY3QoXG4gICAgICAgIG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuZ2V0Lm1vZHVsZVwiKS5tYXAoXG4gICAgICAgICAgKGl0ZW0pID0+IGl0ZW0ubW9kdWxlLFxuICAgICAgICApLFxuICAgICAgKS50b0VxdWFsKFtleHBlY3RlZF0pO1xuICAgICAgZXhwZWN0KGVudmVsb3BlQm9kaWVzLmpvaW4oXCJcXG5cIikpLm5vdC50b0NvbnRhaW4oXCJsZWFrXCIpO1xuICAgIH0pO1xuXG4gICAgaXQuZWFjaChbXG4gICAgICBbXCI+PSAxLjIsIDwgMi4wXCIsIFwiPj0gMS4yLCA8IDIuMFwiXSxcbiAgICAgIFtcIn4+IDUuMFwiLCBcIn4+IDUuMFwiXSxcbiAgICAgIFtcIj0gMS4wXCIsIFwiPSAxLjBcIl0sXG4gICAgICBbXCIhPSAxLjIuM1wiLCBcIiE9IDEuMi4zXCJdLFxuICAgICAgW1wiMS4yLjNcIiwgXCIxLjIuM1wiXSxcbiAgICAgIFtcIiAgPj0gMS4wICwgIDwgMi4wICBcIiwgXCI+PSAxLjAsIDwgMi4wXCJdLFxuICAgICAgW1wifj41LjAsIT01LjEuMFwiLCBcIn4+IDUuMCwgIT0gNS4xLjBcIl0sXG4gICAgICBbXCI+PSAxLjAuMC1sZWFrLXByZXJlbGVhc2UuY29ycFwiLCBcImludmFsaWRcIl0sXG4gICAgICBbXCIxLjIuMytsZWFrLWJ1aWxkLmhvc3RcIiwgXCJpbnZhbGlkXCJdLFxuICAgICAgW1wifj4gNS4wICMgL1VzZXJzL2xlYWtcIiwgXCJpbnZhbGlkXCJdLFxuICAgICAgW1wiPj0gMS4yIHx8IDwgMi4wXCIsIFwiaW52YWxpZFwiXSxcbiAgICAgIC8vIHZhbGlkIGJ5IHRoZSBncmFtbWFyLCBvdmVyIHRoZSBsZW5ndGggYSBjb25zdHJhaW50IG1heSBoYXZlXG4gICAgICBbQXJyYXkoMTIpLmZpbGwoXCIhPSAxLjAuMFwiKS5qb2luKFwiLCBcIiksIFwiaW52YWxpZFwiXSxcbiAgICBdKShcInNlbmRzIHRoZSBwcm92aWRlciBjb25zdHJhaW50ICVwIGFzICVwXCIsIGFzeW5jICh2ZXJzaW9uLCBleHBlY3RlZCkgPT4ge1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHtcbiAgICAgICAgc3RhY2tNZXRhZGF0YTogW3t9XSxcbiAgICAgICAgcmVxdWlyZWRQcm92aWRlcnM6IFt7IGF3czogeyBzb3VyY2U6IFwiYXdzXCIsIHZlcnNpb24gfSB9XSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoXG4gICAgICAgIG1ldHJpY3MoYXdhaXQgZGVsaXZlcmVkSXRlbXMoKSwgXCJjbGkuc3RhY2sucHJvdmlkZXJcIikubWFwKFxuICAgICAgICAgIChwcm92aWRlcikgPT4gcHJvdmlkZXIudmVyc2lvbl9jb25zdHJhaW50LFxuICAgICAgICApLFxuICAgICAgKS50b0VxdWFsKFtleHBlY3RlZF0pO1xuICAgICAgZXhwZWN0KGVudmVsb3BlQm9kaWVzLmpvaW4oXCJcXG5cIikpLm5vdC50b0NvbnRhaW4oXCJsZWFrXCIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcInBhY2thZ2UgbWFuYWdlclwiLCAoKSA9PiB7XG4gICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICBpbml0U2VudHJ5V2l0aENhcHR1cmluZ1RyYW5zcG9ydCgpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIGplc3QuZG9udE1vY2soXCIuL25vZGUtcGFja2FnZS1tYW5hZ2VyXCIpO1xuICAgIH0pO1xuXG4gICAgLy8gYSBjb3B5IG9mIHRoZSBtb2R1bGUgd2hvc2Ugbm9kZSBkZXRlY3RvciBpcyByZXBsYWNlZFxuICAgIGZ1bmN0aW9uIHRlbGVtZXRyeVdpdGhOb2RlRGV0ZWN0b3IoZGV0ZWN0OiAoKSA9PiBzdHJpbmcpIHtcbiAgICAgIGxldCBjb3B5ITogdHlwZW9mIGltcG9ydChcIi4vdGVsZW1ldHJ5XCIpO1xuICAgICAgamVzdC5pc29sYXRlTW9kdWxlcygoKSA9PiB7XG4gICAgICAgIGplc3QuZG9Nb2NrKFwiLi9ub2RlLXBhY2thZ2UtbWFuYWdlclwiLCAoKSA9PiAoe1xuICAgICAgICAgIGRldGVjdE5vZGVQYWNrYWdlTWFuYWdlcjogZGV0ZWN0LFxuICAgICAgICB9KSk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICAgIGNvcHkgPSByZXF1aXJlKFwiLi90ZWxlbWV0cnlcIik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBjb3B5O1xuICAgIH1cblxuICAgIC8vIG9uZSBzdWNjZXNzZnVsIGFuZCBvbmUgZmFpbGVkIGVuZCwgc28gZXZlcnkgY29tbWFuZCBtZXRyaWMgaXMgY292ZXJlZFxuICAgIGFzeW5jIGZ1bmN0aW9uIHJ1bk1ldHJpY3MoXG4gICAgICB0ZWxlbWV0cnk6IFBpY2s8XG4gICAgICAgIHR5cGVvZiBpbXBvcnQoXCIuL3RlbGVtZXRyeVwiKSxcbiAgICAgICAgXCJzdGFydENvbW1hbmRUZWxlbWV0cnlcIiB8IFwic2VuZFRlbGVtZXRyeVwiXG4gICAgICA+ID0geyBzdGFydENvbW1hbmRUZWxlbWV0cnksIHNlbmRUZWxlbWV0cnkgfSxcbiAgICApOiBQcm9taXNlPE1ldHJpY0l0ZW1bXT4ge1xuICAgICAgYXdhaXQgdGVsZW1ldHJ5LnN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgYXdhaXQgdGVsZW1ldHJ5LnNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7fSk7XG4gICAgICBhd2FpdCB0ZWxlbWV0cnkuc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHsgZXJyb3I6IHRydWUgfSk7XG4gICAgICBleHBlY3QoYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApKS50b0JlKHRydWUpO1xuXG4gICAgICBjb25zdCBpdGVtcyA9IHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpO1xuICAgICAgZXhwZWN0KGl0ZW1zLm1hcCgoaSkgPT4gaS5uYW1lKSkudG9FcXVhbChbXG4gICAgICAgIFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiLFxuICAgICAgICBcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiLFxuICAgICAgICBcImNsaS5jb21tYW5kLmVycm9yXCIsXG4gICAgICBdKTtcbiAgICAgIHJldHVybiBpdGVtcztcbiAgICB9XG5cbiAgICBpdC5lYWNoKFtcbiAgICAgIFtcIm5vIGxvY2tmaWxlXCIsIFwibnBtXCIsIHt9XSxcbiAgICAgIFtcImEgcG5wbSBsb2NrZmlsZVwiLCBcInBucG1cIiwgeyBcInBucG0tbG9jay55YW1sXCI6IFwiXCIgfV0sXG4gICAgICBbXCJhIHlhcm4gbG9ja2ZpbGVcIiwgXCJ5YXJuXCIsIHsgXCJ5YXJuLmxvY2tcIjogXCJcIiB9XSxcbiAgICAgIFtcImEgLnlhcm5yYy55bWxcIiwgXCJ5YXJuLWJlcnJ5XCIsIHsgXCIueWFybnJjLnltbFwiOiBcIlwiIH1dLFxuICAgICAgW1xuICAgICAgICBcImEgZGVjbGFyZWQgbnBtXCIsXG4gICAgICAgIFwibnBtXCIsXG4gICAgICAgIHsgXCJwYWNrYWdlLmpzb25cIjogJ3tcInBhY2thZ2VNYW5hZ2VyXCI6XCJucG1AMTAuOC4yXCJ9JyB9LFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAgXCJhIGRlY2xhcmVkIHBucG0gd2l0aCBhIGhhc2hcIixcbiAgICAgICAgXCJwbnBtXCIsXG4gICAgICAgIHsgXCJwYWNrYWdlLmpzb25cIjogJ3tcInBhY2thZ2VNYW5hZ2VyXCI6XCJwbnBtQDEwLjI2LjArc2hhNTEyLkxFQUtcIn0nIH0sXG4gICAgICBdLFxuICAgICAgW1xuICAgICAgICBcImEgZGVjbGFyZWQgeWFybiAxXCIsXG4gICAgICAgIFwieWFyblwiLFxuICAgICAgICB7IFwicGFja2FnZS5qc29uXCI6ICd7XCJwYWNrYWdlTWFuYWdlclwiOlwieWFybkAxLjIyLjIyXCJ9JyB9LFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAgXCJhIGRlY2xhcmVkIHlhcm4gNFwiLFxuICAgICAgICBcInlhcm4tYmVycnlcIixcbiAgICAgICAgeyBcInBhY2thZ2UuanNvblwiOiAne1wicGFja2FnZU1hbmFnZXJcIjpcInlhcm5ANC4xLjBcIn0nIH0sXG4gICAgICBdLFxuICAgICAgW1xuICAgICAgICBcImFuIHVua25vd24gZGVjbGFyZWQgbWFuYWdlclwiLFxuICAgICAgICBcIm5wbVwiLFxuICAgICAgICB7IFwicGFja2FnZS5qc29uXCI6ICd7XCJwYWNrYWdlTWFuYWdlclwiOlwiYnVuQDEuMS4wLUxFQUtcIn0nIH0sXG4gICAgICBdLFxuICAgIF0pKFxuICAgICAgXCJyZXBvcnRzIGEgdHlwZXNjcmlwdCBwcm9qZWN0IHdpdGggJXMgYXMgJXAgb24gZXZlcnkgY29tbWFuZCBtZXRyaWNcIixcbiAgICAgIGFzeW5jIChfbmFtZSwgZXhwZWN0ZWQsIGZpbGVzKSA9PiB7XG4gICAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICAgIGxhbmd1YWdlOiBcInR5cGVzY3JpcHRcIixcbiAgICAgICAgfSk7XG4gICAgICAgIGZvciAoY29uc3QgW25hbWUsIGNvbnRlbnRdIG9mIE9iamVjdC5lbnRyaWVzKGZpbGVzKSkge1xuICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHdvcmtkaXIsIG5hbWUpLCBjb250ZW50IGFzIHN0cmluZyk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXdhaXQgcnVuTWV0cmljcygpKSB7XG4gICAgICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhpdGVtKS5wYWNrYWdlX21hbmFnZXIpLnRvQmUoZXhwZWN0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJ5dGVzID0gZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKTtcbiAgICAgICAgZXhwZWN0KGJ5dGVzKS5ub3QudG9Db250YWluKFwiTEVBS1wiKTtcbiAgICAgICAgZXhwZWN0KGJ5dGVzKS5ub3QudG9Db250YWluKFwiMTAuMjYuMFwiKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1wicHl0aG9uXCIsIHsgYXBwOiBcInBpcGVudiBydW4gcHl0aG9uIG1haW4ucHlcIiB9LCB7fSwgXCJwaXBlbnZcIl0sXG4gICAgICBbXCJweXRob25cIiwgeyBhcHA6IFwicHl0aG9uMyBtYWluLnB5XCIgfSwge30sIFwicGlwXCJdLFxuICAgICAgW1wiamF2YVwiLCB7fSwgeyBcImJ1aWxkLmdyYWRsZVwiOiBcIlwiIH0sIFwiZ3JhZGxlXCJdLFxuICAgICAgW1wiamF2YVwiLCB7fSwgeyBcInBvbS54bWxcIjogXCJcIiB9LCBcIm1hdmVuXCJdLFxuICAgICAgW1wiY3NoYXJwXCIsIHt9LCB7fSwgXCJudWdldFwiXSxcbiAgICAgIFtcImdvXCIsIHt9LCB7fSwgXCJnb1wiXSxcbiAgICBdKShcbiAgICAgIFwicmVwb3J0cyBhICVzIHByb2plY3Qgd2l0aCAlaiBhbmQgZmlsZXMgJWogYXMgJXBcIixcbiAgICAgIGFzeW5jIChsYW5ndWFnZSwgY29uZmlnLCBmaWxlcywgZXhwZWN0ZWQpID0+IHtcbiAgICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgICAgbGFuZ3VhZ2UsXG4gICAgICAgICAgLi4uY29uZmlnLFxuICAgICAgICB9KTtcbiAgICAgICAgZm9yIChjb25zdCBbbmFtZSwgY29udGVudF0gb2YgT2JqZWN0LmVudHJpZXMoZmlsZXMpKSB7XG4gICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4od29ya2RpciwgbmFtZSksIGNvbnRlbnQgYXMgc3RyaW5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhd2FpdCBydW5NZXRyaWNzKCkpIHtcbiAgICAgICAgICBleHBlY3QoYXR0cmlidXRlVmFsdWVzKGl0ZW0pLnBhY2thZ2VfbWFuYWdlcikudG9CZShleHBlY3RlZCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1wibm8gY2RrdGYuanNvblwiLCB1bmRlZmluZWRdLFxuICAgICAgW1wiYW4gdW5zdXBwb3J0ZWQgbGFuZ3VhZ2VcIiwgeyBsYW5ndWFnZTogXCJydXN0XCIgfV0sXG4gICAgICBbXCJubyBsYW5ndWFnZVwiLCB7IGFwcDogXCJwaXBlbnYgcnVuIHB5dGhvbiBtYWluLnB5XCIgfV0sXG4gICAgICBbXCJhIHB5dGhvbiBwcm9qZWN0IHdpdGhvdXQgYW4gYXBwIGNvbW1hbmRcIiwgeyBsYW5ndWFnZTogXCJweXRob25cIiB9XSxcbiAgICBdKShcIm9taXRzIHRoZSBhdHRyaWJ1dGUgd2l0aCAlc1wiLCBhc3luYyAoX25hbWUsIGNka3RmSnNvbikgPT4ge1xuICAgICAgaWYgKGNka3RmSnNvbikge1xuICAgICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIGNka3RmSnNvbik7XG4gICAgICB9XG4gICAgICAvLyBsb2NrZmlsZXMgYWxvbmUgbmV2ZXIgaWRlbnRpZnkgYSBwcm9qZWN0XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbih3b3JrZGlyLCBcInBucG0tbG9jay55YW1sXCIpLCBcIlwiKTtcbiAgICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiYnVpbGQuZ3JhZGxlXCIpLCBcIlwiKTtcblxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGF3YWl0IHJ1bk1ldHJpY3MoKSkge1xuICAgICAgICBleHBlY3QoaXRlbS5hdHRyaWJ1dGVzKS5ub3QudG9IYXZlUHJvcGVydHkoXCJwYWNrYWdlX21hbmFnZXJcIik7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdChcImtlZXBzIHRoZSB2YWx1ZSBkZXRlY3RlZCBhdCBzdGFydCB3aGVuIHRoZSBjd2QgY2hhbmdlcyBiZWZvcmUgdGhlIGVuZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgfSk7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbih3b3JrZGlyLCBcInBucG0tbG9jay55YW1sXCIpLCBcIlwiKTtcbiAgICAgIGNvbnN0IGVsc2V3aGVyZSA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJjZGt0bi1lbHNlLVwiKSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcImNvbnZlcnRcIik7XG4gICAgICAgIHByb2Nlc3MuY2hkaXIoZWxzZXdoZXJlKTtcbiAgICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImNvbnZlcnRcIiwge30pO1xuICAgICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwiY29udmVydFwiLCB7IGVycm9yOiB0cnVlIH0pO1xuICAgICAgICBleHBlY3QoYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApKS50b0JlKHRydWUpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgcHJvY2Vzcy5jaGRpcih3b3JrZGlyKTtcbiAgICAgICAgZnMucmVtb3ZlU3luYyhlbHNld2hlcmUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpdGVtcyA9IHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpO1xuICAgICAgZXhwZWN0KGl0ZW1zKS50b0hhdmVMZW5ndGgoMyk7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhpdGVtKS5wYWNrYWdlX21hbmFnZXIpLnRvQmUoXCJwbnBtXCIpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoXCJmb3JnZXRzIHRoZSB2YWx1ZSB3aXRoIHRoZSBydW5cIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7IGxhbmd1YWdlOiBcImdvXCIgfSk7XG5cbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgcmVzZXRDb21tYW5kVGVsZW1ldHJ5KCk7XG4gICAgICBhd2FpdCBzZW5kVGVsZW1ldHJ5KFwic3ludGhcIiwge30pO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgY29uc3QgY29tcGxldGVkID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcykuZmluZChcbiAgICAgICAgKGkpID0+IGkubmFtZSA9PT0gXCJjbGkuY29tbWFuZC5jb21wbGV0ZWRcIixcbiAgICAgICkhO1xuICAgICAgZXhwZWN0KGNvbXBsZXRlZC5hdHRyaWJ1dGVzKS5ub3QudG9IYXZlUHJvcGVydHkoXCJwYWNrYWdlX21hbmFnZXJcIik7XG4gICAgfSk7XG5cbiAgICBpdChcIm9taXRzIGEgZGV0ZWN0b3IgdmFsdWUgb3V0c2lkZSB0aGUgY2xvc2VkIHNldFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB0ZWxlbWV0cnkgPSB0ZWxlbWV0cnlXaXRoTm9kZURldGVjdG9yKCgpID0+IFwiYnVuQDEuMS4wIC9Vc2Vycy94XCIpO1xuXG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXdhaXQgcnVuTWV0cmljcyh0ZWxlbWV0cnkpKSB7XG4gICAgICAgIGV4cGVjdChpdGVtLmF0dHJpYnV0ZXMpLm5vdC50b0hhdmVQcm9wZXJ0eShcInBhY2thZ2VfbWFuYWdlclwiKTtcbiAgICAgIH1cbiAgICAgIGV4cGVjdChlbnZlbG9wZUJvZGllcy5qb2luKFwiXFxuXCIpKS5ub3QudG9Db250YWluKFwiYnVuXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJvbWl0cyB0aGUgYXR0cmlidXRlIHdoZW4gZGV0ZWN0aW9uIHRocm93c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwidHlwZXNjcmlwdFwiLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB0ZWxlbWV0cnkgPSB0ZWxlbWV0cnlXaXRoTm9kZURldGVjdG9yKCgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRUFDQ0VTXCIpO1xuICAgICAgfSk7XG5cbiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhd2FpdCBydW5NZXRyaWNzKHRlbGVtZXRyeSkpIHtcbiAgICAgICAgZXhwZWN0KGl0ZW0uYXR0cmlidXRlcykubm90LnRvSGF2ZVByb3BlcnR5KFwicGFja2FnZV9tYW5hZ2VyXCIpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoXCJub3JtYWxpemVzIHRvIG1lbWJlcnMgb2YgdGhlIGNsb3NlZCBzZXQgb25seVwiLCAoKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgUEFDS0FHRV9NQU5BR0VSUykge1xuICAgICAgICBleHBlY3Qobm9ybWFsaXplUGFja2FnZU1hbmFnZXIobmFtZSkpLnRvQmUobmFtZSk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIFtcbiAgICAgICAgXCJidW5cIixcbiAgICAgICAgXCJOUE1cIixcbiAgICAgICAgXCJwbnBtQDEwLjI2LjArc2hhNTEyLmFiY1wiLFxuICAgICAgICBcIi91c3IvbG9jYWwvYmluL25wbVwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICAxLFxuICAgICAgICBudWxsLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIFtcIm5wbVwiXSxcbiAgICAgIF0pIHtcbiAgICAgICAgZXhwZWN0KG5vcm1hbGl6ZVBhY2thZ2VNYW5hZ2VyKHZhbHVlKSkudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcInJ1biBsaWZlY3ljbGVcIiwgKCkgPT4ge1xuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIGxhbmd1YWdlOiBcInB5dGhvblwiLFxuICAgICAgICBzZW5kVXNhZ2VUZWxlbWV0cnk6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGluaXRTZW50cnlXaXRoQ2FwdHVyaW5nVHJhbnNwb3J0KCk7XG4gICAgfSk7XG5cbiAgICBpdChcImNvdW50cyB0aGUgcnVuIG9uY2UgYXMgaW52b2tlZCBhdCBzdGFydCwgZXZlbiB3aGVuIHJlcG9ydGluZyBpcyBpbml0aWFsaXplZCBhZ2FpblwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBzdGFydENvbW1hbmRUZWxlbWV0cnkoXCJpbml0XCIpO1xuICAgICAgLy8gaW5pdCBydW5zIGdldCwgd2hpY2ggaW5pdGlhbGl6ZXMgcmVwb3J0aW5nIGEgc2Vjb25kIHRpbWVcbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcImdldFwiKTtcbiAgICAgIGV4cGVjdChhd2FpdCBTZW50cnkuZmx1c2goMjAwMCkpLnRvQmUodHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcyk7XG4gICAgICBleHBlY3QoaXRlbXMubWFwKChpKSA9PiBpLm5hbWUpKS50b0VxdWFsKFtcImNsaS5jb21tYW5kLmludm9rZWRcIl0pO1xuICAgICAgZXhwZWN0KGF0dHJpYnV0ZVZhbHVlcyhpdGVtc1swXSkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgICBjb21tYW5kOiBcImluaXRcIixcbiAgICAgICAgbGFuZ3VhZ2U6IFwicHl0aG9uXCIsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KFwiY291bnRzIG9ubHkgdGhlIHJ1bidzIG93biBjb21tYW5kIGFzIGNvbXBsZXRlZDsgYSBuZXN0ZWQgb3BlcmF0aW9uIGFkZHMgaXRzIG93biBtZXRyaWNzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcImRlcGxveVwiKTtcbiAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7IHRvdGFsVGltZTogNDIsIGxhbmd1YWdlOiBcInB5dGhvblwiIH0pO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7IGxhbmd1YWdlOiBcInB5dGhvblwiIH0pO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgY29uc3QgaXRlbXMgPSBwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzKTtcbiAgICAgIGV4cGVjdChpdGVtcy5tYXAoKGkpID0+IFtpLm5hbWUsIGF0dHJpYnV0ZVZhbHVlcyhpKS5jb21tYW5kXSkpLnRvRXF1YWwoW1xuICAgICAgICBbXCJjbGkuY29tbWFuZC5pbnZva2VkXCIsIFwiZGVwbG95XCJdLFxuICAgICAgICBbXCJjbGkuc3ludGguZHVyYXRpb25cIiwgXCJzeW50aFwiXSxcbiAgICAgICAgW1wiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIsIFwiZGVwbG95XCJdLFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImNvdW50cyBhIGZhaWxlZCBydW4gb25jZSBhcyBlcnJvciwgbmV2ZXIgYXMgY29tcGxldGVkXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgYXdhaXQgc2VuZFRlbGVtZXRyeShcInN5bnRoXCIsIHsgZXJyb3I6IHRydWUsIGVycm9yVHlwZTogXCJFeHRlcm5hbFwiIH0pO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgZXhwZWN0KHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpLm1hcCgoaSkgPT4gaS5uYW1lKSkudG9FcXVhbChbXG4gICAgICAgIFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiLFxuICAgICAgICBcImNsaS5jb21tYW5kLmVycm9yXCIsXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZW1pdHMgbm90aGluZyBhdCBzdGFydCB3aGVuIHVzYWdlIHRlbGVtZXRyeSBpcyBvZmYsIGFuZCBzdGF5cyBhIG5vLW9wIGFmdGVyd2FyZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgc2V0VXNhZ2VUZWxlbWV0cnlFbmFibGVkKGZhbHNlKTtcblxuICAgICAgYXdhaXQgc3RhcnRDb21tYW5kVGVsZW1ldHJ5KFwic3ludGhcIik7XG4gICAgICBzZXRVc2FnZVRlbGVtZXRyeUVuYWJsZWQodHJ1ZSk7XG4gICAgICBhd2FpdCBzdGFydENvbW1hbmRUZWxlbWV0cnkoXCJzeW50aFwiKTtcbiAgICAgIGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKTtcblxuICAgICAgZXhwZWN0KHBhcnNlTWV0cmljSXRlbXMoZW52ZWxvcGVCb2RpZXMpKS50b0hhdmVMZW5ndGgoMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZSBidW5kbGUgaGFzIG9uZSBjb3B5IG9mIHRoaXMgbW9kdWxlIHBlciBlbnRyeSBwb2ludDogYmluL2NtZHMvaGFuZGxlcnMuanNcbiAgLy8gY2FwdHVyZXMgdGhlIGRlY2lzaW9uIGFuZCBzdGFydHMgdGhlIHJ1biwgYmluL2Nka3RuLmpzIGNvdW50cyB0aGUgZmFpbHVyZVxuICBkZXNjcmliZShcInNoYXJlZCBhY3Jvc3MgbW9kdWxlIGNvcGllc1wiLCAoKSA9PiB7XG4gICAgdHlwZSBUZWxlbWV0cnkgPSB0eXBlb2YgaW1wb3J0KFwiLi90ZWxlbWV0cnlcIik7XG4gICAgbGV0IHNlY29uZDogVGVsZW1ldHJ5O1xuXG4gICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICBqZXN0Lmlzb2xhdGVNb2R1bGVzKCgpID0+IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICAgICAgc2Vjb25kID0gcmVxdWlyZShcIi4vdGVsZW1ldHJ5XCIpO1xuICAgICAgfSk7XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwiZ29cIixcbiAgICAgICAgc2VuZFVzYWdlVGVsZW1ldHJ5OiB0cnVlLFxuICAgICAgfSk7XG4gICAgICBpbml0U2VudHJ5V2l0aENhcHR1cmluZ1RyYW5zcG9ydCgpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJvYnNlcnZlcyB0aGUgY2FwdHVyZWQgZGVjaXNpb24gYW5kIHRhcmdldHMsIHRoZSBzdGFydGVkIGNvbW1hbmQgYW5kIGl0cyBsYW5ndWFnZSBmcm9tIHRoZSBvdGhlciBjb3B5XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIHRoZSBwcm9qZWN0IG9wdHMgb3V0OyBvbmx5IHRoZSBkZWNpc2lvbiBjYXB0dXJlZCBieSB0aGUgZmlyc3QgY29weVxuICAgICAgLy8gbGV0cyB0aGUgc2Vjb25kIG9uZSBlbWl0XG4gICAgICBmcy53cml0ZUpzb25TeW5jKHBhdGguam9pbih3b3JrZGlyLCBcImNka3RmLmpzb25cIiksIHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwiZ29cIixcbiAgICAgICAgc2VuZFVzYWdlVGVsZW1ldHJ5OiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgc2V0VXNhZ2VUZWxlbWV0cnlFbmFibGVkKHRydWUpO1xuICAgICAgc2V0UHJvamVjdFRhcmdldEF0dHJpYnV0ZXMoeyB0YXJnZXRfb3BlbnRvZnU6IFwiPj0xLjcuMFwiIH0pO1xuICAgICAgYXdhaXQgc3RhcnRDb21tYW5kVGVsZW1ldHJ5KFwiZGVwbG95XCIpO1xuICAgICAgYXdhaXQgc2Vjb25kLnN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcInN5bnRoXCIpO1xuICAgICAgYXdhaXQgc2Vjb25kLnNlbmRUZWxlbWV0cnkoXCJzeW50aFwiLCB7IGxhbmd1YWdlOiBcImdvXCIgfSk7XG4gICAgICBhd2FpdCBzZWNvbmQuc2VuZFRlbGVtZXRyeShcImRlcGxveVwiLCB7IGVycm9yOiB0cnVlLCBlcnJvclR5cGU6IFwiVXNhZ2VcIiB9KTtcbiAgICAgIGV4cGVjdChhd2FpdCBTZW50cnkuZmx1c2goMjAwMCkpLnRvQmUodHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGl0ZW1zID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcyk7XG4gICAgICBleHBlY3QoaXRlbXMubWFwKChpKSA9PiBbaS5uYW1lLCBhdHRyaWJ1dGVWYWx1ZXMoaSkuY29tbWFuZF0pKS50b0VxdWFsKFtcbiAgICAgICAgW1wiY2xpLmNvbW1hbmQuaW52b2tlZFwiLCBcImRlcGxveVwiXSxcbiAgICAgICAgW1wiY2xpLmNvbW1hbmQuZXJyb3JcIiwgXCJkZXBsb3lcIl0sXG4gICAgICBdKTtcbiAgICAgIGV4cGVjdChhdHRyaWJ1dGVWYWx1ZXMoaXRlbXNbMV0pKS50b01hdGNoT2JqZWN0KHtcbiAgICAgICAgbGFuZ3VhZ2U6IFwiZ29cIixcbiAgICAgICAgcGFja2FnZV9tYW5hZ2VyOiBcImdvXCIsXG4gICAgICAgIHRhcmdldF9vcGVudG9mdTogXCI+PTEuNy4wXCIsXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChpdGVtc1sxXS5hdHRyaWJ1dGVzKS5ub3QudG9IYXZlUHJvcGVydHkoXCJ0YXJnZXRfdGVycmFmb3JtXCIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcInNlbmRUZWxlbWV0cnkgZ2F0aW5nXCIsICgpID0+IHtcbiAgICBpdC5lYWNoKFtcbiAgICAgIHsgZW52OiB1bmRlZmluZWQsIGNhcHR1cmVkOiB1bmRlZmluZWQsIGZsYWc6IHVuZGVmaW5lZCwgZW1pdHM6IHRydWUgfSxcbiAgICAgIHsgZW52OiB1bmRlZmluZWQsIGNhcHR1cmVkOiB1bmRlZmluZWQsIGZsYWc6IHRydWUsIGVtaXRzOiB0cnVlIH0sXG4gICAgICB7IGVudjogdW5kZWZpbmVkLCBjYXB0dXJlZDogdW5kZWZpbmVkLCBmbGFnOiBmYWxzZSwgZW1pdHM6IGZhbHNlIH0sXG4gICAgICAvLyBjb252ZXJ0IGNoZGlycyBpbnRvIGEgdGhyb3dhd2F5IHByb2plY3QgdGhhdCBvcHRzIG91dFxuICAgICAgeyBlbnY6IHVuZGVmaW5lZCwgY2FwdHVyZWQ6IHRydWUsIGZsYWc6IGZhbHNlLCBlbWl0czogdHJ1ZSB9LFxuICAgICAgeyBlbnY6IHVuZGVmaW5lZCwgY2FwdHVyZWQ6IGZhbHNlLCBmbGFnOiB0cnVlLCBlbWl0czogZmFsc2UgfSxcbiAgICAgIHsgZW52OiBcIjFcIiwgY2FwdHVyZWQ6IHVuZGVmaW5lZCwgZmxhZzogdHJ1ZSwgZW1pdHM6IGZhbHNlIH0sXG4gICAgICB7IGVudjogXCIxXCIsIGNhcHR1cmVkOiB0cnVlLCBmbGFnOiB0cnVlLCBlbWl0czogZmFsc2UgfSxcbiAgICBdKShcbiAgICAgIFwiQ0hFQ0tQT0lOVF9ESVNBQkxFPSRlbnYsIGNhcHR1cmVkPSRjYXB0dXJlZCwgZmxhZz0kZmxhZyAtPiBlbWl0cyAkZW1pdHNcIixcbiAgICAgIGFzeW5jICh7IGVudiwgY2FwdHVyZWQsIGZsYWcsIGVtaXRzIH0pID0+IHtcbiAgICAgICAgaWYgKGZsYWcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICAgICAgc2VuZFVzYWdlVGVsZW1ldHJ5OiBmbGFnLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGluaXRTZW50cnlXaXRoQ2FwdHVyaW5nVHJhbnNwb3J0KCk7XG4gICAgICAgIHNldFVzYWdlVGVsZW1ldHJ5RW5hYmxlZChjYXB0dXJlZCk7XG4gICAgICAgIGlmIChlbnYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHByb2Nlc3MuZW52LkNIRUNLUE9JTlRfRElTQUJMRSA9IGVudjtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHN0YXJ0Q29tbWFuZFRlbGVtZXRyeShcImNvbnZlcnRcIik7XG4gICAgICAgIGF3YWl0IHNlbmRUZWxlbWV0cnkoXCJjb252ZXJ0XCIsIHt9KTtcbiAgICAgICAgYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApO1xuXG4gICAgICAgIGNvbnN0IGl0ZW1zID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcyk7XG4gICAgICAgIGV4cGVjdChpdGVtcy5zb21lKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiKSkudG9CZShlbWl0cyk7XG4gICAgICAgIGV4cGVjdChpdGVtcy5zb21lKChpKSA9PiBpLm5hbWUgPT09IFwiY2xpLmNvbW1hbmQuY29tcGxldGVkXCIpKS50b0JlKFxuICAgICAgICAgIGVtaXRzLFxuICAgICAgICApO1xuICAgICAgICBpZiAoIWVtaXRzKSB7XG4gICAgICAgICAgZXhwZWN0KGl0ZW1zKS50b0hhdmVMZW5ndGgoMCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJjbGkuZXJyb3IgZnJvbSB0aGUgRXJyb3JzIGZhY3Rvcmllc1wiLCAoKSA9PiB7XG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIEVycm9ycy5zZXRTY29wZShcInVua25vd25cIik7XG4gICAgfSk7XG5cbiAgICAvLyB0aGUgc2NvcGUgaXMgcmVhZCB3aGVuIHRoZSBlcnJvciBpcyBidWlsdCwgbm90IHdoZW4gdGhlIGZhY3RvcnkgaXNcbiAgICAvLyBjcmVhdGVkOiBhIGZhY3RvcnktdGltZSBiaW5kaW5nIHJlcG9ydHMgZXZlcnkgZXJyb3IgYXMgXCJ1bmtub3duXCJcbiAgICBpdChcImNvdW50cyBjb25zdHJ1Y3RlZCBlcnJvcnMgYnkgdHlwZSB3aXRoIHRoZSBjb21tYW5kIHNldCBhdCBjYWxsIHRpbWVcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCB7XG4gICAgICAgIHNlbmRVc2FnZVRlbGVtZXRyeTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgaW5pdFNlbnRyeVdpdGhDYXB0dXJpbmdUcmFuc3BvcnQoKTtcblxuICAgICAgRXJyb3JzLnNldFNjb3BlKFwiZGVwbG95XCIpO1xuICAgICAgRXJyb3JzLlVzYWdlKFwibm8gc3RhY2tzIHNlbGVjdGVkXCIsIHVuZGVmaW5lZCwgeyBzdGFja05hbWU6IFwic2VjcmV0XCIgfSk7XG4gICAgICBFcnJvcnMuRXh0ZXJuYWwoXCJ0ZXJyYWZvcm0gZXhpdGVkIHdpdGggY29kZSAxXCIpO1xuICAgICAgZXhwZWN0KGF3YWl0IFNlbnRyeS5mbHVzaCgyMDAwKSkudG9CZSh0cnVlKTtcblxuICAgICAgY29uc3QgZXJyb3JzID0gcGFyc2VNZXRyaWNJdGVtcyhlbnZlbG9wZUJvZGllcykuZmlsdGVyKFxuICAgICAgICAoaSkgPT4gaS5uYW1lID09PSBcImNsaS5lcnJvclwiLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgyKTtcbiAgICAgIGV4cGVjdChlcnJvcnMubWFwKChlKSA9PiBlLmF0dHJpYnV0ZXMudHlwZS52YWx1ZSkpLnRvRXF1YWwoW1xuICAgICAgICBcIlVzYWdlXCIsXG4gICAgICAgIFwiRXh0ZXJuYWxcIixcbiAgICAgIF0pO1xuICAgICAgZm9yIChjb25zdCBlcnJvciBvZiBlcnJvcnMpIHtcbiAgICAgICAgZXhwZWN0KGVycm9yLmF0dHJpYnV0ZXMuY29tbWFuZC52YWx1ZSkudG9CZShcImRlcGxveVwiKTtcbiAgICAgICAgZXhwZWN0KGVycm9yLmF0dHJpYnV0ZXMpLm5vdC50b0hhdmVQcm9wZXJ0eShcIm1lc3NhZ2VcIik7XG4gICAgICAgIGV4cGVjdChlcnJvci5hdHRyaWJ1dGVzKS5ub3QudG9IYXZlUHJvcGVydHkoXCJzdGFja05hbWVcIik7XG4gICAgICB9XG4gICAgICBleHBlY3QoSlNPTi5zdHJpbmdpZnkoZXJyb3JzKSkubm90LnRvQ29udGFpbihcInNlY3JldFwiKTtcbiAgICAgIGV4cGVjdChKU09OLnN0cmluZ2lmeShlcnJvcnMpKS5ub3QudG9Db250YWluKFwibm8gc3RhY2tzIHNlbGVjdGVkXCIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcImJpbmFyeSBhdHRyaWJ1dGVzXCIsICgpID0+IHtcbiAgICBhc3luYyBmdW5jdGlvbiBpbnZva2VkQXR0cmlidXRlcyh2ZXJzaW9uT3V0cHV0OiBzdHJpbmcpIHtcbiAgICAgIHNlZWRUZXJyYWZvcm1DbGlQcm9iZUZvclRlc3RzKFByb21pc2UucmVzb2x2ZSh2ZXJzaW9uT3V0cHV0KSk7XG4gICAgICBpbml0U2VudHJ5V2l0aENhcHR1cmluZ1RyYW5zcG9ydCgpO1xuICAgICAgYXdhaXQgc3RhcnRDb21tYW5kVGVsZW1ldHJ5KFwic3ludGhcIik7XG4gICAgICBleHBlY3QoYXdhaXQgU2VudHJ5LmZsdXNoKDIwMDApKS50b0JlKHRydWUpO1xuICAgICAgcmV0dXJuIGF0dHJpYnV0ZVZhbHVlcyhwYXJzZU1ldHJpY0l0ZW1zKGVudmVsb3BlQm9kaWVzKVswXSk7XG4gICAgfVxuXG4gICAgaXQuZWFjaChbXG4gICAgICBbXCJUZXJyYWZvcm0gdjEuMTAuMC1hbHBoYTIwMjUwMTAxXCIsIFwidGVycmFmb3JtXCIsIFwiMS4xMC4wXCJdLFxuICAgICAgW1xuICAgICAgICBcIk9wZW5Ub2Z1IHYxLjIuMy1MRUFLLUhPU1QuY29ycC5leGFtcGxlLmNvbStMRUFLLUJVSUxEL1VzZXJzL3hcIixcbiAgICAgICAgXCJvcGVudG9mdVwiLFxuICAgICAgICBcIjEuMi4zXCIsXG4gICAgICBdLFxuICAgIF0pKFxuICAgICAgXCJyZWR1Y2VzIHRoZSBwcm9iZWQgdmVyc2lvbiBvZiAlcCB0byBpdHMgcmVsZWFzZVwiLFxuICAgICAgYXN5bmMgKHZlcnNpb25PdXRwdXQsIGJpbmFyeSwgcmVsZWFzZSkgPT4ge1xuICAgICAgICBleHBlY3QoYXdhaXQgaW52b2tlZEF0dHJpYnV0ZXModmVyc2lvbk91dHB1dCkpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgICAgIGJpbmFyeSxcbiAgICAgICAgICBiaW5hcnlfdmVyc2lvbjogcmVsZWFzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGV4cGVjdChlbnZlbG9wZUJvZGllcy5qb2luKFwiXFxuXCIpKS5ub3QudG9Db250YWluKFwiTEVBS1wiKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGl0KFwic2VuZHMgbm8gdmVyc2lvbiBmb3IgYW4gdW5yZWNvZ25pc2VkIHByb2R1Y3Q6IGEgd3JhcHBlcidzIG91dHB1dCBoYXMgbm8gcHJvZHVjdCB2ZXJzaW9uIGxpbmVcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGF3YWl0IGludm9rZWRBdHRyaWJ1dGVzKFxuICAgICAgICBcImNvbm5lY3RlZCB0byAxMC4wLjAuMSBhcyBMRUFLLVVTRVIgKHdyYXBwZXIgMy40LjUpXFxuVGVycmFmb3JtIHYxLjkuMFxcblwiLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChhdHRyaWJ1dGVzLmJpbmFyeSkudG9CZShcInVua25vd25cIik7XG4gICAgICBleHBlY3QoYXR0cmlidXRlcykubm90LnRvSGF2ZVByb3BlcnR5KFwiYmluYXJ5X3ZlcnNpb25cIik7XG4gICAgICBleHBlY3QoZW52ZWxvcGVCb2RpZXMuam9pbihcIlxcblwiKSkubm90LnRvQ29udGFpbihcIkxFQUstVVNFUlwiKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJnZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlc1wiLCAoKSA9PiB7XG4gICAgaXQoXCJyZWFkcyBkZWNsYXJlZCB0YXJnZXRzIGFuZCB0aGUgdmFsaWRhdGlvbiBmbGFnXCIsICgpID0+IHtcbiAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwge1xuICAgICAgICB0YXJnZXRWZXJzaW9uczogeyBvcGVudG9mdTogXCJ+MS44XCIgfSxcbiAgICAgICAgdmFsaWRhdGVJbnN0YWxsZWRCaW5hcnk6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChnZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyh3b3JrZGlyKSkudG9FcXVhbCh7XG4gICAgICAgIHRhcmdldHNfZGVjbGFyZWQ6IHRydWUsXG4gICAgICAgIHZhbGlkYXRlX2luc3RhbGxlZF9iaW5hcnk6IHRydWUsXG4gICAgICAgIHRhcmdldF9vcGVudG9mdTogXCI+PTEuOC4wIDwxLjkuMC0wXCIsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW3t9XSxcbiAgICAgIFt7IHRhcmdldFZlcnNpb25zOiBcIm5vcGVcIiB9XSxcbiAgICAgIFt7IHRhcmdldFZlcnNpb25zOiBbXSB9XSxcbiAgICAgIFt1bmRlZmluZWRdLFxuICAgIF0pKFwiZmFsbHMgYmFjayB0byB0aGUgZGVmYXVsdHMgZm9yIGEgY2RrdGYuanNvbiBvZiAlalwiLCAoY29uZmlnKSA9PiB7XG4gICAgICBpZiAoY29uZmlnKSB7XG4gICAgICAgIGZzLndyaXRlSnNvblN5bmMocGF0aC5qb2luKHdvcmtkaXIsIFwiY2RrdGYuanNvblwiKSwgY29uZmlnKTtcbiAgICAgIH1cbiAgICAgIGV4cGVjdChnZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyh3b3JrZGlyKSkudG9FcXVhbCh7XG4gICAgICAgIHRhcmdldHNfZGVjbGFyZWQ6IGZhbHNlLFxuICAgICAgICB2YWxpZGF0ZV9pbnN0YWxsZWRfYmluYXJ5OiBmYWxzZSxcbiAgICAgICAgLi4uREVGQVVMVF9UQVJHRVRfVkVSU0lPTlNfQVNfQVRUUklCVVRFUyxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcImdldFVzYWdlVGVsZW1ldHJ5Q29uc2VudFwiLCAoKSA9PiB7XG4gICAgaXQuZWFjaChbXG4gICAgICAvLyBpbml0IHRlbXBsYXRlcyByZW5kZXIgdGhlIGZsYWcgYXMgYSBzdHJpbmc7IGEgYm9vbGVhbi1vbmx5IGNoZWNrXG4gICAgICAvLyB3b3VsZCBvcHQgZXZlcnkgZnJlc2hseSBpbml0J2VkIHByb2plY3Qgb3V0XG4gICAgICBbeyBzZW5kVXNhZ2VUZWxlbWV0cnk6IFwidHJ1ZVwiIH0sIHRydWVdLFxuICAgICAgW3sgc2VuZFVzYWdlVGVsZW1ldHJ5OiBcImZhbHNlXCIgfSwgZmFsc2VdLFxuICAgICAgW3t9LCB1bmRlZmluZWRdLFxuICAgICAgLy8gbWFsZm9ybWVkIGlzIHVuc2V0LCBub3QgYW4gb3B0LW91dFxuICAgICAgW3sgc2VuZFVzYWdlVGVsZW1ldHJ5OiBcInllc1wiIH0sIHVuZGVmaW5lZF0sXG4gICAgXSkoXCJyZWFkcyAlaiBhcyAlcFwiLCAoY29uZmlnLCBleHBlY3RlZCkgPT4ge1xuICAgICAgZnMud3JpdGVKc29uU3luYyhwYXRoLmpvaW4od29ya2RpciwgXCJjZGt0Zi5qc29uXCIpLCBjb25maWcpO1xuICAgICAgZXhwZWN0KGdldFVzYWdlVGVsZW1ldHJ5Q29uc2VudCh3b3JrZGlyKSkudG9CZShleHBlY3RlZCk7XG4gICAgfSk7XG5cbiAgICBpdChcInJldHVybnMgdW5kZWZpbmVkIHdoZW4gbm8gY2RrdGYuanNvbiBleGlzdHNcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KGdldFVzYWdlVGVsZW1ldHJ5Q29uc2VudCh3b3JrZGlyKSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|