1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.AwsImpl = exports.costSnapshot = exports.requestAwsPrices = exports.awsPrice = exports.createResponseQueueImpl = exports.awsPacker = exports.getAccountId = exports.collectGarbage = exports.clearLastGc = exports.cleanup = exports.deleteResources = exports.deleteRole = exports.initialize = exports.logUrl = exports.createLayer = exports.ensureRole = exports.ensureRoleRaw = exports.createAwsApis = exports.quietly = exports.carefully = exports.AwsMetrics = exports.defaults = exports.defaultGcWorker = void 0;
|
4 | const aws_sdk_1 = require("aws-sdk");
|
5 | const crypto_1 = require("crypto");
|
6 | const fs_extra_1 = require("fs-extra");
|
7 | const https = require("https");
|
8 | const util_1 = require("util");
|
9 | const webpack_merge_1 = require("webpack-merge");
|
10 | const cache_1 = require("../cache");
|
11 | const cost_1 = require("../cost");
|
12 | const error_1 = require("../error");
|
13 | const faast_1 = require("../faast");
|
14 | const log_1 = require("../log");
|
15 | const packer_1 = require("../packer");
|
16 | const provider_1 = require("../provider");
|
17 | const serialize_1 = require("../serialize");
|
18 | const shared_1 = require("../shared");
|
19 | const throttle_1 = require("../throttle");
|
20 | const awsNpm = require("./aws-npm");
|
21 | const aws_queue_1 = require("./aws-queue");
|
22 | const aws_shared_1 = require("./aws-shared");
|
23 | const awsTrampoline = require("./aws-trampoline");
|
24 | exports.defaultGcWorker = (0, throttle_1.throttle)({ concurrency: 5, rate: 5, burst: 2 }, async (work, services) => {
|
25 | switch (work.type) {
|
26 | case "SetLogRetention":
|
27 | if (await carefully(services.cloudwatch.putRetentionPolicy({
|
28 | logGroupName: work.logGroupName,
|
29 | retentionInDays: work.retentionInDays || 1
|
30 | }))) {
|
31 | log_1.log.gc(`Added retention policy %O`, work);
|
32 | }
|
33 | break;
|
34 | case "DeleteResources":
|
35 | await deleteResources(work.resources, services, log_1.log.gc);
|
36 | break;
|
37 | case "DeleteLayerVersion":
|
38 | if (await carefully(services.lambda.deleteLayerVersion({
|
39 | LayerName: work.LayerName,
|
40 | VersionNumber: work.VersionNumber
|
41 | }))) {
|
42 | log_1.log.gc(`deleted layer %O`, work);
|
43 | }
|
44 | break;
|
45 | }
|
46 | });
|
47 | exports.defaults = {
|
48 | ...provider_1.commonDefaults,
|
49 | region: "us-west-2",
|
50 | RoleName: "faast-cached-lambda-role",
|
51 | memorySize: 1728,
|
52 | awsLambdaOptions: {},
|
53 | awsConfig: {},
|
54 | _gcWorker: exports.defaultGcWorker
|
55 | };
|
56 | class AwsMetrics {
|
57 | constructor() {
|
58 | this.outboundBytes = 0;
|
59 | this.sns64kRequests = 0;
|
60 | this.sqs64kRequests = 0;
|
61 | }
|
62 | }
|
63 | exports.AwsMetrics = AwsMetrics;
|
64 | async function carefully(arg) {
|
65 | try {
|
66 | return await arg.promise();
|
67 | }
|
68 | catch (err) {
|
69 | log_1.log.warn(err);
|
70 | return;
|
71 | }
|
72 | }
|
73 | exports.carefully = carefully;
|
74 | async function quietly(arg) {
|
75 | try {
|
76 | return await arg.promise();
|
77 | }
|
78 | catch (err) {
|
79 | return;
|
80 | }
|
81 | }
|
82 | exports.quietly = quietly;
|
83 | exports.createAwsApis = (0, throttle_1.throttle)({ concurrency: 1 }, async (region, awsConfig = {}) => {
|
84 | const logger = log_1.log.awssdk.enabled ? { log: log_1.log.awssdk } : undefined;
|
85 | const common = {
|
86 | maxRetries: 6,
|
87 | correctClockSkew: true,
|
88 | logger,
|
89 | ...awsConfig,
|
90 | region
|
91 | };
|
92 | const agent = new https.Agent({ keepAlive: true, maxSockets: 1000, timeout: 0 });
|
93 | const services = {
|
94 | iam: new aws_sdk_1.IAM({ apiVersion: "2010-05-08", ...common }),
|
95 | lambda: new aws_sdk_1.Lambda({ apiVersion: "2015-03-31", ...common }),
|
96 | // Special Lambda instance with configuration optimized for
|
97 | // invocations.
|
98 | lambda2: new aws_sdk_1.Lambda({
|
99 | apiVersion: "2015-03-31",
|
100 | ...common,
|
101 | // Retries are handled by faast.js, not the sdk.
|
102 | maxRetries: 0,
|
103 | // The default 120s timeout is too short, especially for https
|
104 | // mode.
|
105 | httpOptions: { timeout: 0, agent }
|
106 | }),
|
107 | cloudwatch: new aws_sdk_1.CloudWatchLogs({ apiVersion: "2014-03-28", ...common }),
|
108 | sqs: new aws_sdk_1.SQS({ apiVersion: "2012-11-05", ...common }),
|
109 | sns: new aws_sdk_1.SNS({ apiVersion: "2010-03-31", ...common }),
|
110 | pricing: new aws_sdk_1.Pricing({ region: "us-east-1", ...common }),
|
111 | sts: new aws_sdk_1.STS({ apiVersion: "2011-06-15", ...common }),
|
112 | s3: new aws_sdk_1.S3({ apiVersion: "2006-03-01", ...common })
|
113 | };
|
114 | return services;
|
115 | });
|
116 | async function ensureRoleRaw(RoleName, services, createRole) {
|
117 | const { iam } = services;
|
118 | log_1.log.info(`Checking for cached lambda role`);
|
119 | try {
|
120 | const response = await iam.getRole({ RoleName }).promise();
|
121 | return response.Role;
|
122 | }
|
123 | catch (err) {
|
124 | if (!createRole) {
|
125 | throw new error_1.FaastError(err, `could not find role "${RoleName}"`);
|
126 | }
|
127 | }
|
128 | log_1.log.info(`Creating default role "${RoleName}" for faast trampoline function`);
|
129 | const AssumeRolePolicyDocument = JSON.stringify({
|
130 | Version: "2012-10-17",
|
131 | Statement: [
|
132 | {
|
133 | Principal: { Service: "lambda.amazonaws.com" },
|
134 | Action: "sts:AssumeRole",
|
135 | Effect: "Allow"
|
136 | }
|
137 | ]
|
138 | });
|
139 | const roleParams = {
|
140 | AssumeRolePolicyDocument,
|
141 | RoleName,
|
142 | Description: "role for lambda functions created by faast",
|
143 | MaxSessionDuration: 3600
|
144 | };
|
145 | log_1.log.info(`Calling createRole`);
|
146 | const PolicyArn = "arn:aws:iam::aws:policy/AdministratorAccess";
|
147 | try {
|
148 | const roleResponse = await iam.createRole(roleParams).promise();
|
149 | log_1.log.info(`Attaching administrator role policy`);
|
150 | await iam.attachRolePolicy({ RoleName, PolicyArn }).promise();
|
151 | return roleResponse.Role;
|
152 | }
|
153 | catch (err) {
|
154 | if (err.code === "EntityAlreadyExists") {
|
155 | await (0, shared_1.sleep)(5000);
|
156 | const roleResponse = await iam.getRole({ RoleName }).promise();
|
157 | await iam.attachRolePolicy({ RoleName, PolicyArn }).promise();
|
158 | return roleResponse.Role;
|
159 | }
|
160 | throw new error_1.FaastError(err, `failed to create role "${RoleName}"`);
|
161 | }
|
162 | }
|
163 | exports.ensureRoleRaw = ensureRoleRaw;
|
164 | exports.ensureRole = (0, throttle_1.throttle)({ concurrency: 1, rate: 2, memoize: true, retry: 12 }, ensureRoleRaw);
|
165 | const ResponseQueueId = awsTrampoline.INVOCATION_TEST_QUEUE;
|
166 | const emptyFcall = { callId: "0", modulePath: "", name: "", args: "", ResponseQueueId };
|
167 | async function createLayer(lambda, packageJson, useDependencyCaching, FunctionName, region, retentionInDays, awsLambdaOptions) {
|
168 | if (!packageJson) {
|
169 | return;
|
170 | }
|
171 | log_1.log.info(`Building node_modules`);
|
172 | const packageJsonContents = typeof packageJson === "string"
|
173 | ? (await (0, fs_extra_1.readFile)(packageJson)).toString()
|
174 | : JSON.stringify(packageJson);
|
175 | let LayerName;
|
176 | if (useDependencyCaching) {
|
177 | const hasher = (0, crypto_1.createHash)("sha256");
|
178 | hasher.update(packageJsonContents);
|
179 | hasher.update(JSON.stringify(awsLambdaOptions.Architectures ?? ""));
|
180 | const cacheKey = hasher.digest("hex");
|
181 | LayerName = `faast-${cacheKey}`;
|
182 | const layers = await quietly(lambda.listLayerVersions({ LayerName }));
|
183 | if (layers?.LayerVersions?.length ?? 0 > 0) {
|
184 | const [{ Version, LayerVersionArn, CreatedDate }] = layers?.LayerVersions ?? [];
|
185 | if (!(0, shared_1.hasExpired)(CreatedDate, retentionInDays) && Version && LayerVersionArn) {
|
186 | return { Version, LayerVersionArn, LayerName };
|
187 | }
|
188 | }
|
189 | }
|
190 | else {
|
191 | LayerName = FunctionName;
|
192 | }
|
193 | try {
|
194 | const faastModule = await (0, faast_1.faastAws)(awsNpm, {
|
195 | region,
|
196 | timeout: 300,
|
197 | memorySize: 2048,
|
198 | mode: "https",
|
199 | gc: "off",
|
200 | maxRetries: 0,
|
201 | webpackOptions: {
|
202 | externals: []
|
203 | },
|
204 | awsLambdaOptions
|
205 | });
|
206 | try {
|
207 | const installArgs = {
|
208 | packageJsonContents,
|
209 | LayerName,
|
210 | FunctionName,
|
211 | region,
|
212 | retentionInDays
|
213 | };
|
214 | const { installLog, layerInfo } = await faastModule.functions.npmInstall(installArgs);
|
215 | log_1.log.info(installLog);
|
216 | return layerInfo;
|
217 | }
|
218 | finally {
|
219 | await faastModule.cleanup();
|
220 | }
|
221 | }
|
222 | catch (err) {
|
223 | throw new error_1.FaastError(err, "failed to create lambda layer from packageJson");
|
224 | }
|
225 | }
|
226 | exports.createLayer = createLayer;
|
227 | function logUrl(state) {
|
228 | const { region, FunctionName } = state.resources;
|
229 | return (0, aws_shared_1.getLogUrl)(region, FunctionName);
|
230 | }
|
231 | exports.logUrl = logUrl;
|
232 | exports.initialize = (0, throttle_1.throttle)({ concurrency: Infinity, rate: 2 }, async (fModule, nonce, options) => {
|
233 | const { region, timeout, memorySize, env, concurrency, mode } = options;
|
234 | if (concurrency > 100 && mode !== "queue") {
|
235 | log_1.log.warn(`Consider using queue mode for higher levels of concurrency:`);
|
236 | log_1.log.warn(`https://faastjs.org/docs/api/faastjs.commonoptions.mode`);
|
237 | }
|
238 | log_1.log.info(`Creating AWS APIs`);
|
239 | const services = await (0, exports.createAwsApis)(region, options.awsConfig);
|
240 | const { lambda } = services;
|
241 | const FunctionName = `faast-${nonce}`;
|
242 | const { packageJson, useDependencyCaching, description } = options;
|
243 | async function createFunctionRequest(Code, Role, responseQueueArn, layerInfo) {
|
244 | const { Layers = [], ...rest } = options.awsLambdaOptions;
|
245 | if (layerInfo) {
|
246 | Layers.push(layerInfo.LayerVersionArn);
|
247 | }
|
248 | const request = {
|
249 | FunctionName,
|
250 | Role,
|
251 | Runtime: "nodejs14.x",
|
252 | Handler: "index.trampoline",
|
253 | Code,
|
254 | Description: "faast trampoline function",
|
255 | Timeout: timeout,
|
256 | MemorySize: memorySize,
|
257 | Environment: { Variables: env },
|
258 | Layers,
|
259 | ...rest
|
260 | };
|
261 | log_1.log.info(`createFunctionRequest: %O`, request);
|
262 | let func;
|
263 | try {
|
264 | func = await lambda.createFunction(request).promise();
|
265 | await (0, throttle_1.retryOp)(2, () => lambda.waitFor("functionActive", { FunctionName }).promise());
|
266 | }
|
267 | catch (err) {
|
268 | if (err?.message?.match(/Function already exist/)) {
|
269 | func = (await lambda.getFunction({ FunctionName }).promise())
|
270 | .Configuration;
|
271 | }
|
272 | else {
|
273 | throw new error_1.FaastError(err, "Create function failure");
|
274 | }
|
275 | }
|
276 | log_1.log.info(`Created function ${func.FunctionName}, FunctionArn: ${func.FunctionArn} [${description}]`);
|
277 | log_1.log.minimal(`Created function ${func.FunctionName} [${description}]`);
|
278 | try {
|
279 | const config = await (0, throttle_1.retryOp)((err, n) => n < 5 && err?.message?.match(/destination ARN.*is invalid/), () => lambda
|
280 | .putFunctionEventInvokeConfig({
|
281 | FunctionName,
|
282 | MaximumRetryAttempts: 0,
|
283 | MaximumEventAgeInSeconds: 21600,
|
284 | DestinationConfig: {
|
285 | OnFailure: { Destination: responseQueueArn }
|
286 | }
|
287 | })
|
288 | .promise());
|
289 | log_1.log.info(`Function event invocation config: %O`, config);
|
290 | }
|
291 | catch (err) {
|
292 | throw new error_1.FaastError(err, "putFunctionEventInvokeConfig failure");
|
293 | }
|
294 | return func;
|
295 | }
|
296 | const { wrapperVerbose } = options.debugOptions;
|
297 | async function createCodeBundle() {
|
298 | const { timeout, childProcess, mode } = options;
|
299 | const hasLambdaTimeoutBug = mode !== "queue" && timeout >= 180;
|
300 | const childProcessTimeoutMs = hasLambdaTimeoutBug && childProcess ? (timeout - 5) * 1000 : 0;
|
301 | const childProcessMemoryLimitMb = options.childProcessMemoryMb;
|
302 | const wrapperOptions = {
|
303 | wrapperVerbose,
|
304 | childProcessTimeoutMs,
|
305 | childProcessMemoryLimitMb
|
306 | };
|
307 | const bundle = awsPacker(fModule, options, wrapperOptions, FunctionName);
|
308 | return { ZipFile: await (0, shared_1.streamToBuffer)((await bundle).archive) };
|
309 | }
|
310 | const { RoleName } = options;
|
311 | const state = {
|
312 | resources: {
|
313 | FunctionName,
|
314 | RoleName,
|
315 | region,
|
316 | logGroupName: (0, aws_shared_1.getLogGroupName)(FunctionName)
|
317 | },
|
318 | services,
|
319 | metrics: new AwsMetrics(),
|
320 | options
|
321 | };
|
322 | const { gc, retentionInDays, _gcWorker: gcWorker } = options;
|
323 | if (gc === "auto" || gc === "force") {
|
324 | log_1.log.gc(`Starting garbage collector`);
|
325 | state.gcPromise = collectGarbage(gcWorker, services, region, retentionInDays, gc).catch(err => {
|
326 | log_1.log.gc(`Garbage collection error: ${err}`);
|
327 | return "skipped";
|
328 | });
|
329 | }
|
330 | try {
|
331 | log_1.log.info(`Creating lambda function`);
|
332 | const rolePromise = (0, exports.ensureRole)(RoleName, services, RoleName === exports.defaults.RoleName);
|
333 | const responseQueuePromise = createResponseQueueImpl(state, FunctionName);
|
334 | const pricingPromise = (0, exports.requestAwsPrices)(services.pricing, region);
|
335 | const codeBundlePromise = createCodeBundle();
|
336 | // Ensure role exists before creating lambda layer, which also needs the role.
|
337 | const role = await rolePromise;
|
338 | const layerPromise = createLayer(services.lambda, packageJson, useDependencyCaching, FunctionName, region, retentionInDays, options.awsLambdaOptions);
|
339 | const codeBundle = await codeBundlePromise;
|
340 | const responseQueueArn = await responseQueuePromise;
|
341 | const layer = await layerPromise;
|
342 | if (layer) {
|
343 | state.resources.layer = layer;
|
344 | }
|
345 | let lambdaFnArn;
|
346 | const retryable = [
|
347 | /role/,
|
348 | /KMS Exception/,
|
349 | /internal service error/,
|
350 | /Layer version/
|
351 | ];
|
352 | const shouldRetry = (err, n) => n < 5 && !!retryable.find(regex => err?.message?.match(regex));
|
353 | await (0, throttle_1.retryOp)(shouldRetry, async () => {
|
354 | try {
|
355 | const lambdaFn = await createFunctionRequest(codeBundle, role.Arn, responseQueueArn, layer);
|
356 | lambdaFnArn = lambdaFn.FunctionArn;
|
357 | // If the role for the lambda function was created
|
358 | // recently, test that the role works by invoking the
|
359 | // function. If an exception occurs, the function is
|
360 | // deleted and re-deployed. Empirically, this is the way
|
361 | // to ensure successful lambda creation when an IAM role
|
362 | // is recently created.
|
363 | if (Date.now() - role.CreateDate.getTime() < 300 * 1000) {
|
364 | const { metrics } = state;
|
365 | const fn = FunctionName;
|
366 | const never = new Promise(_ => { });
|
367 | await (0, throttle_1.retryOp)(1, () => invokeHttps(lambda, fn, emptyFcall, metrics, never));
|
368 | }
|
369 | }
|
370 | catch (err) {
|
371 | /* istanbul ignore next */ {
|
372 | await lambda
|
373 | .deleteFunction({ FunctionName })
|
374 | .promise()
|
375 | .catch(_ => { });
|
376 | throw new error_1.FaastError(err, `New lambda function ${FunctionName} failed invocation test`);
|
377 | }
|
378 | }
|
379 | });
|
380 | const { mode } = options;
|
381 | if (mode === "queue") {
|
382 | await createRequestQueueImpl(state, FunctionName, lambdaFnArn);
|
383 | }
|
384 | await pricingPromise;
|
385 | log_1.log.info(`Lambda function initialization complete.`);
|
386 | return state;
|
387 | }
|
388 | catch (err) {
|
389 | try {
|
390 | await cleanup(state, {
|
391 | deleteResources: true,
|
392 | deleteCaches: false,
|
393 | gcTimeout: 30
|
394 | });
|
395 | }
|
396 | catch { }
|
397 | throw new error_1.FaastError({ cause: err, name: error_1.FaastErrorNames.ECREATE }, "failed to initialize cloud function");
|
398 | }
|
399 | });
|
400 | async function invoke(state, call, cancel) {
|
401 | const { metrics, services, resources, options } = state;
|
402 | switch (options.mode) {
|
403 | case "auto":
|
404 | case "https":
|
405 | const { lambda2 } = services;
|
406 | const { FunctionName } = resources;
|
407 | await invokeHttps(lambda2, FunctionName, call, metrics, cancel);
|
408 | return;
|
409 | case "queue":
|
410 | const { sns } = services;
|
411 | const { RequestTopicArn } = resources;
|
412 | try {
|
413 | await (0, aws_queue_1.publishFunctionCallMessage)(sns, RequestTopicArn, call, metrics);
|
414 | }
|
415 | catch (err) {
|
416 | throw new error_1.FaastError(err, `invoke sns error ${(0, util_1.inspect)(call, undefined, 9)}`);
|
417 | }
|
418 | return;
|
419 | }
|
420 | }
|
421 | function poll(state, cancel) {
|
422 | return (0, aws_queue_1.receiveMessages)(state.services.sqs, state.resources.ResponseQueueUrl, state.metrics, cancel);
|
423 | }
|
424 | function responseQueueId(state) {
|
425 | return state.resources.ResponseQueueUrl;
|
426 | }
|
427 | async function invokeHttps(lambda, FunctionName, message, metrics, cancel) {
|
428 | const request = {
|
429 | FunctionName,
|
430 | Payload: (0, serialize_1.serialize)(message),
|
431 | LogType: "None"
|
432 | };
|
433 | const awsRequest = lambda.invoke(request);
|
434 | const rawResponse = await Promise.race([awsRequest.promise(), cancel]);
|
435 | if (!rawResponse) {
|
436 | log_1.log.info(`cancelling lambda invoke`);
|
437 | awsRequest.abort();
|
438 | return;
|
439 | }
|
440 | metrics.outboundBytes += (0, shared_1.computeHttpResponseBytes)(rawResponse.$response.httpResponse.headers);
|
441 | if (rawResponse.LogResult) {
|
442 | log_1.log.info(Buffer.from(rawResponse.LogResult, "base64").toString());
|
443 | }
|
444 | if (rawResponse.FunctionError) {
|
445 | const error = (0, aws_queue_1.processAwsErrorMessage)(rawResponse.Payload);
|
446 | throw error;
|
447 | }
|
448 | }
|
449 | async function deleteRole(RoleName, iam) {
|
450 | const policies = await carefully(iam.listAttachedRolePolicies({ RoleName }));
|
451 | const AttachedPolicies = policies?.AttachedPolicies ?? [];
|
452 | await Promise.all(AttachedPolicies.map(p => p.PolicyArn).map(PolicyArn => carefully(iam.detachRolePolicy({ RoleName, PolicyArn }))));
|
453 | const rolePolicyListResponse = await carefully(iam.listRolePolicies({ RoleName }));
|
454 | const RolePolicies = rolePolicyListResponse?.PolicyNames ?? [];
|
455 | await Promise.all(RolePolicies.map(PolicyName => carefully(iam.deleteRolePolicy({ RoleName, PolicyName }))));
|
456 | await carefully(iam.deleteRole({ RoleName }));
|
457 | }
|
458 | exports.deleteRole = deleteRole;
|
459 | async function deleteResources(resources, services, output = log_1.log.info) {
|
460 | const { FunctionName, RoleName, region, RequestTopicArn, ResponseQueueUrl, ResponseQueueArn, SNSLambdaSubscriptionArn, logGroupName, layer, Bucket, ...rest } = resources;
|
461 | const _exhaustiveCheck = {};
|
462 | const { lambda, sqs, sns, iam, s3, cloudwatch } = services;
|
463 | if (SNSLambdaSubscriptionArn) {
|
464 | if (await quietly(sns.unsubscribe({ SubscriptionArn: SNSLambdaSubscriptionArn }))) {
|
465 | output(`Deleted request queue subscription to lambda`);
|
466 | }
|
467 | }
|
468 | if (RoleName) {
|
469 | await deleteRole(RoleName, iam);
|
470 | }
|
471 | if (RequestTopicArn) {
|
472 | if (await quietly(sns.deleteTopic({ TopicArn: RequestTopicArn }))) {
|
473 | output(`Deleted request queue topic: ${RequestTopicArn}`);
|
474 | }
|
475 | }
|
476 | if (ResponseQueueUrl) {
|
477 | if (await quietly(sqs.deleteQueue({ QueueUrl: ResponseQueueUrl }))) {
|
478 | output(`Deleted response queue: ${ResponseQueueUrl}`);
|
479 | }
|
480 | }
|
481 | if (layer) {
|
482 | if (await quietly(lambda.deleteLayerVersion({
|
483 | LayerName: layer.LayerName,
|
484 | VersionNumber: layer.Version
|
485 | }))) {
|
486 | output(`Deleted lambda layer: ${layer.LayerName}:${layer.Version}`);
|
487 | }
|
488 | }
|
489 | if (Bucket) {
|
490 | const objects = await quietly(s3.listObjectsV2({ Bucket, Prefix: "faast-" }));
|
491 | if (objects) {
|
492 | const keys = (objects.Contents || []).map(elem => ({ Key: elem.Key }));
|
493 | if (await quietly(s3.deleteObjects({ Bucket, Delete: { Objects: keys } }))) {
|
494 | output(`Deleted s3 objects: ${keys.length} objects in bucket ${Bucket}`);
|
495 | }
|
496 | }
|
497 | if (await quietly(s3.deleteBucket({ Bucket }))) {
|
498 | output(`Deleted s3 bucket: ${Bucket}`);
|
499 | }
|
500 | }
|
501 | if (FunctionName) {
|
502 | if (await quietly(lambda.deleteFunction({ FunctionName }))) {
|
503 | output(`Deleted function: ${FunctionName}`);
|
504 | }
|
505 | }
|
506 | if (logGroupName) {
|
507 | if (await quietly(cloudwatch.deleteLogGroup({ logGroupName }))) {
|
508 | output(`Deleted log group: ${logGroupName}`);
|
509 | }
|
510 | }
|
511 | }
|
512 | exports.deleteResources = deleteResources;
|
513 | async function addLogRetentionPolicy(FunctionName, cloudwatch) {
|
514 | const logGroupName = (0, aws_shared_1.getLogGroupName)(FunctionName);
|
515 | const response = await quietly(cloudwatch.putRetentionPolicy({ logGroupName, retentionInDays: 1 }));
|
516 | if (response !== undefined) {
|
517 | log_1.log.info(`Added 1 day retention policy to log group ${logGroupName}`);
|
518 | }
|
519 | }
|
520 | async function cleanup(state, options) {
|
521 | log_1.log.info(`aws cleanup starting.`);
|
522 | if (state.gcPromise) {
|
523 | log_1.log.info(`Waiting for garbage collection...`);
|
524 | await state.gcPromise;
|
525 | log_1.log.info(`Garbage collection done.`);
|
526 | }
|
527 | if (options.deleteResources) {
|
528 | log_1.log.info(`Cleaning up infrastructure for ${state.resources.FunctionName}...`);
|
529 | await addLogRetentionPolicy(state.resources.FunctionName, state.services.cloudwatch);
|
530 | // Don't delete cached role. It may be in use by other instances of
|
531 | // faast. Don't delete logs. They are often useful. By default log
|
532 | // stream retention will be 1 day, and gc will clean out the log group
|
533 | // after the streams are expired. Don't delete a lambda layer that is
|
534 | // used to cache packages.
|
535 | const { logGroupName, RoleName, layer, ...rest } = state.resources;
|
536 | await deleteResources(rest, state.services);
|
537 | if (!state.options.useDependencyCaching || options.deleteCaches) {
|
538 | await deleteResources({ layer }, state.services);
|
539 | }
|
540 | }
|
541 | log_1.log.info(`aws cleanup done.`);
|
542 | }
|
543 | exports.cleanup = cleanup;
|
544 | const logGroupNameRegexp = new RegExp(`^/aws/lambda/(faast-${shared_1.uuidv4Pattern})$`);
|
545 | function functionNameFromLogGroup(logGroupName) {
|
546 | const match = logGroupName.match(logGroupNameRegexp);
|
547 | return match && match[1];
|
548 | }
|
549 | let lastGc;
|
550 | function clearLastGc() {
|
551 | lastGc = undefined;
|
552 | }
|
553 | exports.clearLastGc = clearLastGc;
|
554 | function forEachPage(description, request, process) {
|
555 | const throttlePaging = (0, throttle_1.throttle)({ concurrency: 1, rate: 1 }, async () => { });
|
556 | return new Promise((resolve, reject) => {
|
557 | request.eachPage((err, page, done) => {
|
558 | if (err) {
|
559 | log_1.log.warn(`GC: Error when listing ${description}: ${err}`);
|
560 | reject(err);
|
561 | return false;
|
562 | }
|
563 | if (page === null) {
|
564 | resolve();
|
565 | }
|
566 | else {
|
567 | process(page).then(() => throttlePaging().then(done));
|
568 | }
|
569 | return true;
|
570 | });
|
571 | });
|
572 | }
|
573 | async function collectGarbage(executor, services, region, retentionInDays, mode) {
|
574 | if (executor === exports.defaultGcWorker) {
|
575 | if (mode === "auto") {
|
576 | if (lastGc && Date.now() <= lastGc + 3600 * 1000) {
|
577 | return "skipped";
|
578 | }
|
579 | const gcEntry = await cache_1.caches.awsGc.get("gc");
|
580 | if (gcEntry) {
|
581 | try {
|
582 | const lastGcPersistent = JSON.parse(gcEntry.toString());
|
583 | if (lastGcPersistent &&
|
584 | typeof lastGcPersistent === "number" &&
|
585 | Date.now() <= lastGcPersistent + 3600 * 1000) {
|
586 | lastGc = lastGcPersistent;
|
587 | return "skipped";
|
588 | }
|
589 | }
|
590 | catch (err) {
|
591 | log_1.log.warn(err);
|
592 | }
|
593 | }
|
594 | }
|
595 | lastGc = Date.now();
|
596 | cache_1.caches.awsGc.set("gc", lastGc.toString());
|
597 | }
|
598 | const promises = [];
|
599 | function scheduleWork(work) {
|
600 | if (executor === exports.defaultGcWorker) {
|
601 | log_1.log.gc(`Scheduling work pushing promise: %O`, work);
|
602 | }
|
603 | promises.push(executor(work, services));
|
604 | }
|
605 | const functionsWithLogGroups = new Set();
|
606 | const logGroupRequest = services.cloudwatch.describeLogGroups({
|
607 | logGroupNamePrefix: "/aws/lambda/faast-"
|
608 | });
|
609 | const accountId = await getAccountId(services.sts);
|
610 | await forEachPage("log groups", logGroupRequest, async ({ logGroups = [] }) => {
|
611 | logGroups.forEach(g => {
|
612 | const FunctionName = functionNameFromLogGroup(g.logGroupName);
|
613 | functionsWithLogGroups.add(FunctionName);
|
614 | });
|
615 | log_1.log.gc(`Log groups size: ${logGroups.length}`);
|
616 | garbageCollectLogGroups(logGroups, retentionInDays, region, accountId, scheduleWork);
|
617 | });
|
618 | const listFunctionsRequest = services.lambda.listFunctions();
|
619 | await forEachPage("lambda functions", listFunctionsRequest, async ({ Functions = [] }) => {
|
620 | const fnPattern = new RegExp(`^faast-${shared_1.uuidv4Pattern}$`);
|
621 | const funcs = (Functions || [])
|
622 | .filter(fn => fn.FunctionName.match(fnPattern))
|
623 | .filter(fn => !functionsWithLogGroups.has(fn.FunctionName))
|
624 | .filter(fn => (0, shared_1.hasExpired)(fn.LastModified, retentionInDays))
|
625 | .map(fn => fn.FunctionName);
|
626 | deleteGarbageFunctions(region, accountId, funcs, scheduleWork);
|
627 | });
|
628 | // Collect Lambda Layers
|
629 | const layersRequest = services.lambda.listLayers({
|
630 | CompatibleRuntime: "nodejs"
|
631 | });
|
632 | await forEachPage("Lambda Layers", layersRequest, async ({ Layers = [] }) => {
|
633 | for (const layer of Layers) {
|
634 | if (layer.LayerName.match(/^faast-/)) {
|
635 | const layerVersionRequest = services.lambda.listLayerVersions({
|
636 | LayerName: layer.LayerName,
|
637 | CompatibleRuntime: "nodejs"
|
638 | });
|
639 | await forEachPage("Lambda Layer Versions", layerVersionRequest, async ({ LayerVersions = [] }) => {
|
640 | LayerVersions.forEach(layerVersion => {
|
641 | if ((0, shared_1.hasExpired)(layerVersion.CreatedDate, retentionInDays)) {
|
642 | scheduleWork({
|
643 | type: "DeleteLayerVersion",
|
644 | LayerName: layer.LayerName,
|
645 | VersionNumber: layerVersion.Version
|
646 | });
|
647 | }
|
648 | });
|
649 | });
|
650 | }
|
651 | }
|
652 | });
|
653 | log_1.log.gc(`Awaiting ${promises.length} scheduled work promises`);
|
654 | await Promise.all(promises);
|
655 | return "done";
|
656 | }
|
657 | exports.collectGarbage = collectGarbage;
|
658 | async function getAccountId(sts) {
|
659 | const response = await sts.getCallerIdentity().promise();
|
660 | const { Account, Arn, UserId } = response;
|
661 | log_1.log.info(`Account ID: %O`, { Account, Arn, UserId });
|
662 | return response.Account;
|
663 | }
|
664 | exports.getAccountId = getAccountId;
|
665 | function garbageCollectLogGroups(logGroups, retentionInDays, region, accountId, scheduleWork) {
|
666 | const logGroupsMissingRetentionPolicy = logGroups.filter(g => g.retentionInDays === undefined);
|
667 | log_1.log.gc(`Log groups missing retention: ${logGroupsMissingRetentionPolicy.length}`);
|
668 | logGroupsMissingRetentionPolicy.forEach(g => {
|
669 | scheduleWork({
|
670 | type: "SetLogRetention",
|
671 | logGroupName: g.logGroupName,
|
672 | retentionInDays
|
673 | });
|
674 | });
|
675 | const garbageFunctions = logGroups
|
676 | .filter(g => (0, shared_1.hasExpired)(g.creationTime, retentionInDays))
|
677 | .map(g => functionNameFromLogGroup(g.logGroupName))
|
678 | .filter(shared_1.defined);
|
679 | deleteGarbageFunctions(region, accountId, garbageFunctions, scheduleWork);
|
680 | }
|
681 | function deleteGarbageFunctions(region, accountId, garbageFunctions, scheduleWork) {
|
682 | garbageFunctions.forEach(FunctionName => {
|
683 | const resources = {
|
684 | FunctionName,
|
685 | region,
|
686 | RoleName: "",
|
687 | RequestTopicArn: getSNSTopicArn(region, accountId, FunctionName),
|
688 | ResponseQueueUrl: getResponseQueueUrl(region, accountId, FunctionName),
|
689 | logGroupName: (0, aws_shared_1.getLogGroupName)(FunctionName),
|
690 | Bucket: FunctionName
|
691 | };
|
692 | scheduleWork({ type: "DeleteResources", resources });
|
693 | });
|
694 | }
|
695 | async function awsPacker(functionModule, options, wrapperOptions, FunctionName) {
|
696 | return (0, packer_1.packer)(awsTrampoline, functionModule, {
|
697 | ...options,
|
698 | webpackOptions: (0, webpack_merge_1.default)(options.webpackOptions ?? {}, {
|
699 | externals: [new RegExp("^aws-sdk/?")]
|
700 | })
|
701 | }, wrapperOptions, FunctionName);
|
702 | }
|
703 | exports.awsPacker = awsPacker;
|
704 | function getSNSTopicName(FunctionName) {
|
705 | return `${FunctionName}-Requests`;
|
706 | }
|
707 | function getSNSTopicArn(region, accountId, FunctionName) {
|
708 | const TopicName = getSNSTopicName(FunctionName);
|
709 | return `arn:aws:sns:${region}:${accountId}:${TopicName}`;
|
710 | }
|
711 | function getSQSName(FunctionName) {
|
712 | return `${FunctionName}-Responses`;
|
713 | }
|
714 | function getResponseQueueUrl(region, accountId, FunctionName) {
|
715 | const queueName = getSQSName(FunctionName);
|
716 | return `https://sqs.${region}.amazonaws.com/${accountId}/${queueName}`;
|
717 | }
|
718 | function createRequestQueueImpl(state, FunctionName, FunctionArn) {
|
719 | const { sns, lambda } = state.services;
|
720 | const { resources } = state;
|
721 | log_1.log.info(`Creating SNS request topic`);
|
722 | const createTopicPromise = (0, aws_queue_1.createSNSTopic)(sns, getSNSTopicName(FunctionName));
|
723 | const assignRequestTopicArnPromise = createTopicPromise.then(topic => (resources.RequestTopicArn = topic));
|
724 | const addPermissionsPromise = createTopicPromise.then(topic => {
|
725 | log_1.log.info(`Adding SNS invoke permissions to function`);
|
726 | return addSnsInvokePermissionsToFunction(FunctionName, topic, lambda);
|
727 | });
|
728 | const subscribePromise = createTopicPromise.then(topic => {
|
729 | log_1.log.info(`Subscribing SNS to invoke lambda function`);
|
730 | return sns
|
731 | .subscribe({
|
732 | TopicArn: topic,
|
733 | Protocol: "lambda",
|
734 | Endpoint: FunctionArn
|
735 | })
|
736 | .promise();
|
737 | });
|
738 | const assignSNSResponsePromise = subscribePromise.then(snsResponse => (resources.SNSLambdaSubscriptionArn = snsResponse.SubscriptionArn));
|
739 | return Promise.all([
|
740 | createTopicPromise,
|
741 | assignRequestTopicArnPromise,
|
742 | addPermissionsPromise,
|
743 | subscribePromise,
|
744 | assignSNSResponsePromise
|
745 | ]);
|
746 | }
|
747 | async function createResponseQueueImpl(state, FunctionName) {
|
748 | const { sqs } = state.services;
|
749 | const { resources } = state;
|
750 | log_1.log.info(`Creating SQS response queue`);
|
751 | const { QueueUrl, QueueArn } = await (0, aws_queue_1.createSQSQueue)(getSQSName(FunctionName), 60, sqs);
|
752 | resources.ResponseQueueUrl = QueueUrl;
|
753 | resources.ResponseQueueArn = QueueArn;
|
754 | log_1.log.info(`Created response queue`);
|
755 | return QueueArn;
|
756 | }
|
757 | exports.createResponseQueueImpl = createResponseQueueImpl;
|
758 | function addSnsInvokePermissionsToFunction(FunctionName, RequestTopicArn, lambda) {
|
759 | return lambda
|
760 | .addPermission({
|
761 | FunctionName,
|
762 | Action: "lambda:InvokeFunction",
|
763 | Principal: "sns.amazonaws.com",
|
764 | StatementId: `${FunctionName}-Invoke`,
|
765 | SourceArn: RequestTopicArn
|
766 | })
|
767 | .promise()
|
768 | .catch(err => {
|
769 | if (err.match(/already exists/)) {
|
770 | }
|
771 | else {
|
772 | throw err;
|
773 | }
|
774 | });
|
775 | }
|
776 | const locations = {
|
777 | "us-east-1": "US East (N. Virginia)",
|
778 | "us-east-2": "US East (Ohio)",
|
779 | "us-west-1": "US West (N. California)",
|
780 | "us-west-2": "US West (Oregon)",
|
781 | "ca-central-1": "Canada (Central)",
|
782 | "eu-central-1": "EU (Frankfurt)",
|
783 | "eu-west-1": "EU (Ireland)",
|
784 | "eu-west-2": "EU (London)",
|
785 | "eu-west-3": "EU (Paris)",
|
786 | "ap-northeast-1": "Asia Pacific (Tokyo)",
|
787 | "ap-northeast-2": "Asia Pacific (Seoul)",
|
788 | "ap-northeast-3": "Asia Pacific (Osaka-Local)",
|
789 | "ap-southeast-1": "Asia Pacific (Singapore)",
|
790 | "ap-southeast-2": "Asia Pacific (Sydney)",
|
791 | "ap-south-1": "Asia Pacific (Mumbai)",
|
792 | "sa-east-1": "South America (São Paulo)"
|
793 | };
|
794 | exports.awsPrice = (0, throttle_1.throttle)({ concurrency: 6, rate: 5, memoize: true, cache: cache_1.caches.awsPrices }, async (pricing, ServiceCode, filter) => {
|
795 | try {
|
796 | function first(obj) {
|
797 | return obj[Object.keys(obj)[0]];
|
798 | }
|
799 | function extractPrice(obj) {
|
800 | const prices = Object.keys(obj.priceDimensions).map(key => Number(obj.priceDimensions[key].pricePerUnit.USD));
|
801 | return Math.max(...prices);
|
802 | }
|
803 | const priceResult = await pricing
|
804 | .getProducts({
|
805 | ServiceCode,
|
806 | Filters: Object.keys(filter).map(key => ({
|
807 | Field: key,
|
808 | Type: "TERM_MATCH",
|
809 | Value: filter[key]
|
810 | }))
|
811 | })
|
812 | .promise();
|
813 | if (priceResult.PriceList.length > 1) {
|
814 | log_1.log.warn(`Price query returned more than one product '${ServiceCode}' ($O)`, filter);
|
815 | priceResult.PriceList.forEach(p => log_1.log.warn(`%O`, p));
|
816 | }
|
817 | const pList = priceResult.PriceList[0];
|
818 | const price = extractPrice(first(pList.terms.OnDemand));
|
819 | return price;
|
820 | }
|
821 | catch (err) {
|
822 | /* istanbul ignore next */
|
823 | {
|
824 | const { message: m } = err;
|
825 | if (!m.match(/Rate exceeded/) &&
|
826 | !m.match(/EPROTO/) &&
|
827 | !m.match(/socket hang up/)) {
|
828 | log_1.log.warn(`Could not get AWS pricing for '${ServiceCode}' (%O)`, filter);
|
829 | log_1.log.warn(err);
|
830 | }
|
831 | throw new error_1.FaastError(err, `failed to get AWS pricing for "${ServiceCode}"`);
|
832 | }
|
833 | }
|
834 | });
|
835 | const requestAwsPrices = async (pricing, region) => {
|
836 | const location = locations[region];
|
837 | /* istanbul ignore next */
|
838 | return {
|
839 | lambdaPerRequest: await (0, exports.awsPrice)(pricing, "AWSLambda", {
|
840 | location,
|
841 | group: "AWS-Lambda-Requests"
|
842 | }).catch(_ => 0.0000002),
|
843 | lambdaPerGbSecond: await (0, exports.awsPrice)(pricing, "AWSLambda", {
|
844 | location,
|
845 | group: "AWS-Lambda-Duration"
|
846 | }).catch(_ => 0.00001667),
|
847 | snsPer64kPublish: await (0, exports.awsPrice)(pricing, "AmazonSNS", {
|
848 | location,
|
849 | group: "SNS-Requests-Tier1"
|
850 | }).catch(_ => 0.5 / 1e6),
|
851 | sqsPer64kRequest: await (0, exports.awsPrice)(pricing, "AWSQueueService", {
|
852 | location,
|
853 | group: "SQS-APIRequest-Tier1",
|
854 | queueType: "Standard"
|
855 | }).catch(_ => 0.4 / 1e6),
|
856 | dataOutPerGb: await (0, exports.awsPrice)(pricing, "AWSDataTransfer", {
|
857 | fromLocation: location,
|
858 | transferType: "AWS Outbound"
|
859 | }).catch(_ => 0.09),
|
860 | logsIngestedPerGb: await (0, exports.awsPrice)(pricing, "AmazonCloudWatch", {
|
861 | location,
|
862 | group: "Ingested Logs",
|
863 | groupDescription: "Existing system, application, and custom log files"
|
864 | }).catch(_ => 0.5)
|
865 | };
|
866 | };
|
867 | exports.requestAwsPrices = requestAwsPrices;
|
868 | async function costSnapshot(state, stats) {
|
869 | const { region } = state.resources;
|
870 | const prices = await (0, exports.requestAwsPrices)(state.services.pricing, region);
|
871 | const costMetrics = [];
|
872 | const { memorySize = exports.defaults.memorySize } = state.options;
|
873 | const billedTimeStats = stats.estimatedBilledTime;
|
874 | const seconds = (billedTimeStats.mean / 1000) * billedTimeStats.samples || 0;
|
875 | const provisionedGb = memorySize / 1024;
|
876 | const functionCallDuration = new cost_1.CostMetric({
|
877 | name: "functionCallDuration",
|
878 | pricing: prices.lambdaPerGbSecond * provisionedGb,
|
879 | unit: "second",
|
880 | measured: seconds,
|
881 | comment: `https://aws.amazon.com/lambda/pricing (rate = ${prices.lambdaPerGbSecond.toFixed(8)}/(GB*second) * ${provisionedGb} GB = ${(prices.lambdaPerGbSecond * provisionedGb).toFixed(8)}/second)`
|
882 | });
|
883 | costMetrics.push(functionCallDuration);
|
884 | const functionCallRequests = new cost_1.CostMetric({
|
885 | name: "functionCallRequests",
|
886 | pricing: prices.lambdaPerRequest,
|
887 | measured: stats.invocations,
|
888 | unit: "request",
|
889 | comment: "https://aws.amazon.com/lambda/pricing"
|
890 | });
|
891 | costMetrics.push(functionCallRequests);
|
892 | const { metrics } = state;
|
893 | const outboundDataTransfer = new cost_1.CostMetric({
|
894 | name: "outboundDataTransfer",
|
895 | pricing: prices.dataOutPerGb,
|
896 | measured: metrics.outboundBytes / 2 ** 30,
|
897 | unit: "GB",
|
898 | comment: "https://aws.amazon.com/ec2/pricing/on-demand/#Data_Transfer"
|
899 | });
|
900 | costMetrics.push(outboundDataTransfer);
|
901 | const sqs = new cost_1.CostMetric({
|
902 | name: "sqs",
|
903 | pricing: prices.sqsPer64kRequest,
|
904 | measured: metrics.sqs64kRequests,
|
905 | unit: "request",
|
906 | comment: "https://aws.amazon.com/sqs/pricing"
|
907 | });
|
908 | costMetrics.push(sqs);
|
909 | const sns = new cost_1.CostMetric({
|
910 | name: "sns",
|
911 | pricing: prices.snsPer64kPublish,
|
912 | measured: metrics.sns64kRequests,
|
913 | unit: "request",
|
914 | comment: "https://aws.amazon.com/sns/pricing"
|
915 | });
|
916 | costMetrics.push(sns);
|
917 | const logIngestion = new cost_1.CostMetric({
|
918 | name: "logIngestion",
|
919 | pricing: prices.logsIngestedPerGb,
|
920 | measured: 0,
|
921 | unit: "GB",
|
922 | comment: "https://aws.amazon.com/cloudwatch/pricing/ - Log ingestion costs not currently included.",
|
923 | informationalOnly: true
|
924 | });
|
925 | costMetrics.push(logIngestion);
|
926 | return new cost_1.CostSnapshot("aws", state.options, stats, costMetrics);
|
927 | }
|
928 | exports.costSnapshot = costSnapshot;
|
929 | exports.AwsImpl = {
|
930 | name: "aws",
|
931 | initialize: exports.initialize,
|
932 | defaults: exports.defaults,
|
933 | cleanup,
|
934 | costSnapshot,
|
935 | logUrl,
|
936 | invoke,
|
937 | poll,
|
938 | responseQueueId
|
939 | };
|
940 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWZhYXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2F3cy9hd3MtZmFhc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUNBV2lCO0FBRWpCLG1DQUFvQztBQUNwQyx1Q0FBb0M7QUFDcEMsK0JBQStCO0FBQy9CLCtCQUErQjtBQUMvQixpREFBa0M7QUFDbEMsb0NBQWtDO0FBQ2xDLGtDQUFtRDtBQUNuRCxvQ0FBdUQ7QUFDdkQsb0NBQW9DO0FBQ3BDLGdDQUE2QjtBQUM3QixzQ0FBaUQ7QUFDakQsMENBUXFCO0FBQ3JCLDRDQUF5QztBQUN6QyxzQ0FPbUI7QUFDbkIsMENBQWdEO0FBRWhELG9DQUFvQztBQUVwQywyQ0FNcUI7QUFDckIsNkNBQTBEO0FBQzFELGtEQUFrRDtBQUVyQyxRQUFBLGVBQWUsR0FBRyxJQUFBLG1CQUFRLEVBQ25DLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFDckMsS0FBSyxFQUFFLElBQWUsRUFBRSxRQUFxQixFQUFFLEVBQUU7SUFDN0MsUUFBUSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ2YsS0FBSyxpQkFBaUI7WUFDbEIsSUFDSSxNQUFNLFNBQVMsQ0FDWCxRQUFRLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDO2dCQUNuQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7Z0JBQy9CLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZSxJQUFJLENBQUM7YUFDN0MsQ0FBQyxDQUNMLEVBQ0g7Z0JBQ0UsU0FBRyxDQUFDLEVBQUUsQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUM3QztZQUNELE1BQU07UUFDVixLQUFLLGlCQUFpQjtZQUNsQixNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxTQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEQsTUFBTTtR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LE9BQU8sRUFBRSxvQ0FBb0M7S0FDaEQsQ0FBQyxDQUFDO0lBQ0gsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUV0QixNQUFNLEdBQUcsR0FBZSxJQUFJLGlCQUFVLENBQUM7UUFDbkMsSUFBSSxFQUFFLEtBQUs7UUFDWCxPQUFPLEVBQUUsTUFBTSxDQUFDLGdCQUFnQjtRQUNoQyxRQUFRLEVBQUUsT0FBTyxDQUFDLGNBQWM7UUFDaEMsSUFBSSxFQUFFLFNBQVM7UUFDZixPQUFPLEVBQUUsb0NBQW9DO0tBQ2hELENBQUMsQ0FBQztJQUNILFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFdEIsTUFBTSxZQUFZLEdBQWUsSUFBSSxpQkFBVSxDQUFDO1FBQzVDLElBQUksRUFBRSxjQUFjO1FBQ3BCLE9BQU8sRUFBRSxNQUFNLENBQUMsaUJBQWlCO1FBQ2pDLFFBQVEsRUFBRSxDQUFDO1FBQ1gsSUFBSSxFQUFFLElBQUk7UUFDVixPQUFPLEVBQ0gsMEZBQTBGO1FBQzlGLGlCQUFpQixFQUFFLElBQUk7S0FDMUIsQ0FBQyxDQUFDO0lBQ0gsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUUvQixPQUFPLElBQUksbUJBQVksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFDdEUsQ0FBQztBQXpFRCxvQ0F5RUM7QUFFWSxRQUFBLE9BQU8sR0FBdUM7SUFDdkQsSUFBSSxFQUFFLEtBQUs7SUFDWCxVQUFVLEVBQVYsa0JBQVU7SUFDVixRQUFRLEVBQVIsZ0JBQVE7SUFDUixPQUFPO0lBQ1AsWUFBWTtJQUNaLE1BQU07SUFDTixNQUFNO0lBQ04sSUFBSTtJQUNKLGVBQWU7Q0FDbEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQVdTRXJyb3IsXG4gICAgQ2xvdWRXYXRjaExvZ3MsXG4gICAgSUFNLFxuICAgIExhbWJkYSxcbiAgICBQcmljaW5nLFxuICAgIFJlcXVlc3QsXG4gICAgUzMsXG4gICAgU05TLFxuICAgIFNRUyxcbiAgICBTVFNcbn0gZnJvbSBcImF3cy1zZGtcIjtcbmltcG9ydCB7IENvbmZpZ3VyYXRpb25PcHRpb25zIH0gZnJvbSBcImF3cy1zZGsvbGliL2NvbmZpZy1iYXNlXCI7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gXCJodHRwc1wiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgbWVyZ2UgZnJvbSBcIndlYnBhY2stbWVyZ2VcIjtcbmltcG9ydCB7IGNhY2hlcyB9IGZyb20gXCIuLi9jYWNoZVwiO1xuaW1wb3J0IHsgQ29zdE1ldHJpYywgQ29zdFNuYXBzaG90IH0gZnJvbSBcIi4uL2Nvc3RcIjtcbmltcG9ydCB7IEZhYXN0RXJyb3IsIEZhYXN0RXJyb3JOYW1lcyB9IGZyb20gXCIuLi9lcnJvclwiO1xuaW1wb3J0IHsgZmFhc3RBd3MgfSBmcm9tIFwiLi4vZmFhc3RcIjtcbmltcG9ydCB7IGxvZyB9IGZyb20gXCIuLi9sb2dcIjtcbmltcG9ydCB7IHBhY2tlciwgUGFja2VyUmVzdWx0IH0gZnJvbSBcIi4uL3BhY2tlclwiO1xuaW1wb3J0IHtcbiAgICBDbGVhbnVwT3B0aW9ucyxcbiAgICBjb21tb25EZWZhdWx0cyxcbiAgICBDb21tb25PcHRpb25zLFxuICAgIEZ1bmN0aW9uU3RhdHMsXG4gICAgUG9sbFJlc3VsdCxcbiAgICBQcm92aWRlckltcGwsXG4gICAgVVVJRFxufSBmcm9tIFwiLi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IHNlcmlhbGl6ZSB9IGZyb20gXCIuLi9zZXJpYWxpemVcIjtcbmltcG9ydCB7XG4gICAgY29tcHV0ZUh0dHBSZXNwb25zZUJ5dGVzLFxuICAgIGRlZmluZWQsXG4gICAgaGFzRXhwaXJlZCxcbiAgICBzbGVlcCxcbiAgICBzdHJlYW1Ub0J1ZmZlcixcbiAgICB1dWlkdjRQYXR0ZXJuXG59IGZyb20gXCIuLi9zaGFyZWRcIjtcbmltcG9ydCB7IHJldHJ5T3AsIHRocm90dGxlIH0gZnJvbSBcIi4uL3Rocm90dGxlXCI7XG5pbXBvcnQgeyBGdW5jdGlvbkNhbGwsIFdyYXBwZXJPcHRpb25zIH0gZnJvbSBcIi4uL3dyYXBwZXJcIjtcbmltcG9ydCAqIGFzIGF3c05wbSBmcm9tIFwiLi9hd3MtbnBtXCI7XG5pbXBvcnQgeyBBd3NMYXllckluZm8gfSBmcm9tIFwiLi9hd3MtbnBtXCI7XG5pbXBvcnQge1xuICAgIGNyZWF0ZVNOU1RvcGljLFxuICAgIGNyZWF0ZVNRU1F1ZXVlLFxuICAgIHByb2Nlc3NBd3NFcnJvck1lc3NhZ2UsXG4gICAgcHVibGlzaEZ1bmN0aW9uQ2FsbE1lc3NhZ2UsXG4gICAgcmVjZWl2ZU1lc3NhZ2VzXG59IGZyb20gXCIuL2F3cy1xdWV1ZVwiO1xuaW1wb3J0IHsgZ2V0TG9nR3JvdXBOYW1lLCBnZXRMb2dVcmwgfSBmcm9tIFwiLi9hd3Mtc2hhcmVkXCI7XG5pbXBvcnQgKiBhcyBhd3NUcmFtcG9saW5lIGZyb20gXCIuL2F3cy10cmFtcG9saW5lXCI7XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0R2NXb3JrZXIgPSB0aHJvdHRsZShcbiAgICB7IGNvbmN1cnJlbmN5OiA1LCByYXRlOiA1LCBidXJzdDogMiB9LFxuICAgIGFzeW5jICh3b3JrOiBBd3NHY1dvcmssIHNlcnZpY2VzOiBBd3NTZXJ2aWNlcykgPT4ge1xuICAgICAgICBzd2l0Y2ggKHdvcmsudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBcIlNldExvZ1JldGVudGlvblwiOlxuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgY2FyZWZ1bGx5KFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VydmljZXMuY2xvdWR3YXRjaC5wdXRSZXRlbnRpb25Qb2xpY3koe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ0dyb3VwTmFtZTogd29yay5sb2dHcm91cE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiB3b3JrLnJldGVudGlvbkluRGF5cyB8fCAxXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgQWRkZWQgcmV0ZW50aW9uIHBvbGljeSAlT2AsIHdvcmspO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJEZWxldGVSZXNvdXJjZXNcIjpcbiAgICAgICAgICAgICAgICBhd2FpdCBkZWxldGVSZXNvdXJjZXMod29yay5yZXNvdXJjZXMsIHNlcnZpY2VzLCBsb2cuZ2MpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIkRlbGV0ZUxheWVyVmVyc2lvblwiOlxuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgY2FyZWZ1bGx5KFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VydmljZXMubGFtYmRhLmRlbGV0ZUxheWVyVmVyc2lvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF5ZXJOYW1lOiB3b3JrLkxheWVyTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBWZXJzaW9uTnVtYmVyOiB3b3JrLlZlcnNpb25OdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nLmdjKGBkZWxldGVkIGxheWVyICVPYCwgd29yayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuKTtcblxuLyoqXG4gKiBBV1Mtc3BlY2lmaWMgb3B0aW9ucyBmb3Ige0BsaW5rIGZhYXN0QXdzfS5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBd3NPcHRpb25zIGV4dGVuZHMgQ29tbW9uT3B0aW9ucyB7XG4gICAgLyoqXG4gICAgICogVGhlIHJlZ2lvbiB0byBjcmVhdGUgcmVzb3VyY2VzIGluLiBHYXJiYWdlIGNvbGxlY3Rpb24gaXMgYWxzbyBsaW1pdGVkIHRvXG4gICAgICogdGhpcyByZWdpb24uIERlZmF1bHQ6IGBcInVzLXdlc3QtMlwiYC5cbiAgICAgKi9cbiAgICByZWdpb24/OiBBd3NSZWdpb247XG4gICAgLyoqXG4gICAgICogVGhlIHJvbGUgdGhhdCB0aGUgbGFtYmRhIGZ1bmN0aW9uIHdpbGwgYXNzdW1lIHdoZW4gZXhlY3V0aW5nIHVzZXIgY29kZS5cbiAgICAgKiBEZWZhdWx0OiBgXCJmYWFzdC1jYWNoZWQtbGFtYmRhLXJvbGVcImAuIFJhcmVseSB1c2VkLlxuICAgICAqIEByZW1hcmtzXG4gICAgICogV2hlbiBhIGxhbWJkYSBleGVjdXRlcywgaXQgZmlyc3QgYXNzdW1lcyBhblxuICAgICAqIHtAbGluayBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9sYW1iZGEtaW50cm8tZXhlY3V0aW9uLXJvbGUuaHRtbCB8IGV4ZWN1dGlvbiByb2xlfVxuICAgICAqIHRvIGdyYW50IGFjY2VzcyB0byByZXNvdXJjZXMuXG4gICAgICpcbiAgICAgKiBCeSBkZWZhdWx0LCBmYWFzdC5qcyBjcmVhdGVzIHRoaXMgZXhlY3V0aW9uIHJvbGUgZm9yIHlvdSBhbmQgbGVhdmVzIGl0XG4gICAgICogcGVybWFuZW50bHkgaW4geW91ciBhY2NvdW50ICh0aGUgcm9sZSBpcyBzaGFyZWQgYWNyb3NzIGFsbCBsYW1iZGFcbiAgICAgKiBmdW5jdGlvbnMgY3JlYXRlZCBieSBmYWFzdC5qcykuIEJ5IGRlZmF1bHQsIGZhYXN0LmpzIGdyYW50cyBhZG1pbmlzdHJhdG9yXG4gICAgICogcHJpdmlsZWdlcyB0byB0aGlzIHJvbGUgc28geW91ciBjb2RlIGNhbiBwZXJmb3JtIGFueSBBV1Mgb3BlcmF0aW9uIGl0XG4gICAgICogcmVxdWlyZXMuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuXG4gICAgICoge0BsaW5rIGh0dHBzOi8vY29uc29sZS5hd3MuYW1hem9uLmNvbS9pYW0vaG9tZSMvcm9sZXMgfCBjcmVhdGUgYSBjdXN0b20gcm9sZX1cbiAgICAgKiB0aGF0IHNwZWNpZmllcyBtb3JlIGxpbWl0ZWQgcGVybWlzc2lvbnMgaWYgeW91IHByZWZlciBub3QgdG8gZ3JhbnRcbiAgICAgKiBhZG1pbmlzdHJhdG9yIHByaXZpbGVnZXMuIEFueSByb2xlIHlvdSBhc3NpZ24gZm9yIGZhYXN0LmpzIG1vZHVsZXMgbmVlZHNcbiAgICAgKiBhdCBsZWFzdCB0aGUgZm9sbG93aW5nIHBlcm1pc3Npb25zOlxuICAgICAqXG4gICAgICogLSBFeGVjdXRpb24gUm9sZTpcbiAgICAgKiBgYGBqc29uXG4gICAgICogICB7XG4gICAgICogICAgICAgXCJWZXJzaW9uXCI6IFwiMjAxMi0xMC0xN1wiLFxuICAgICAqICAgICAgIFwiU3RhdGVtZW50XCI6IFtcbiAgICAgKiAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgXCJFZmZlY3RcIjogXCJBbGxvd1wiLFxuICAgICAqICAgICAgICAgICAgICAgXCJBY3Rpb25cIjogW1wibG9nczoqXCJdLFxuICAgICAqICAgICAgICAgICAgICAgXCJSZXNvdXJjZVwiOiBcImFybjphd3M6bG9nczoqOio6bG9nLWdyb3VwOmZhYXN0LSpcIlxuICAgICAqICAgICAgICAgICB9LFxuICAgICAqICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICBcIkVmZmVjdFwiOiBcIkFsbG93XCIsXG4gICAgICogICAgICAgICAgICAgICBcIkFjdGlvblwiOiBbXCJzcXM6KlwiXSxcbiAgICAgKiAgICAgICAgICAgICAgIFwiUmVzb3VyY2VcIjogXCJhcm46YXdzOnNxczoqOio6ZmFhc3QtKlwiXG4gICAgICogICAgICAgICAgIH1cbiAgICAgKiAgICAgICBdXG4gICAgICogICB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiAtIFRydXN0IHJlbGF0aW9uc2hpcCAoYWxzbyBrbm93biBhcyBgQXNzdW1lUm9sZVBvbGljeURvY3VtZW50YCBpbiB0aGUgQVdTXG4gICAgICogICBTREspOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiAgIHtcbiAgICAgKiAgICAgXCJWZXJzaW9uXCI6IFwiMjAxMi0xMC0xN1wiLFxuICAgICAqICAgICBcIlN0YXRlbWVudFwiOiBbXG4gICAgICogICAgICAge1xuICAgICAqICAgICAgICAgXCJFZmZlY3RcIjogXCJBbGxvd1wiLFxuICAgICAqICAgICAgICAgXCJQcmluY2lwYWxcIjoge1xuICAgICAqICAgICAgICAgICBcIlNlcnZpY2VcIjogXCJsYW1iZGEuYW1hem9uYXdzLmNvbVwiXG4gICAgICogICAgICAgICB9LFxuICAgICAqICAgICAgICAgXCJBY3Rpb25cIjogXCJzdHM6QXNzdW1lUm9sZVwiXG4gICAgICogICAgICAgfVxuICAgICAqICAgICBdXG4gICAgICogICB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKi9cbiAgICBSb2xlTmFtZT86IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBBZGRpdGlvbmFsIG9wdGlvbnMgdG8gcGFzcyB0byBBV1MgTGFtYmRhIGNyZWF0aW9uLiBTZWVcbiAgICAgKiB7QGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvZGcvQVBJX0NyZWF0ZUZ1bmN0aW9uLmh0bWwgfCBDcmVhdGVGdW5jdGlvbn0uXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBJZiB5b3UgbmVlZCBzcGVjaWFsaXplZCBvcHRpb25zLCB5b3UgY2FuIHBhc3MgdGhlbSB0byB0aGUgQVdTIExhbWJkYSBTREtcbiAgICAgKiBkaXJlY3RseS4gTm90ZSB0aGF0IGlmIHlvdSBvdmVycmlkZSBhbnkgc2V0dGluZ3Mgc2V0IGJ5IGZhYXN0LmpzLCB5b3UgbWF5XG4gICAgICogY2F1c2UgZmFhc3QuanMgdG8gbm90IHdvcms6XG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogICBjb25zdCByZXF1ZXN0OiBhd3MuTGFtYmRhLkNyZWF0ZUZ1bmN0aW9uUmVxdWVzdCA9IHtcbiAgICAgKiAgICAgICBGdW5jdGlvbk5hbWUsXG4gICAgICogICAgICAgUm9sZSxcbiAgICAgKiAgICAgICBSdW50aW1lOiBcIm5vZGVqczE0LnhcIixcbiAgICAgKiAgICAgICBIYW5kbGVyOiBcImluZGV4LnRyYW1wb2xpbmVcIixcbiAgICAgKiAgICAgICBDb2RlLFxuICAgICAqICAgICAgIERlc2NyaXB0aW9uOiBcImZhYXN0IHRyYW1wb2xpbmUgZnVuY3Rpb25cIixcbiAgICAgKiAgICAgICBUaW1lb3V0LFxuICAgICAqICAgICAgIE1lbW9yeVNpemUsXG4gICAgICogICAgICAgLi4uYXdzTGFtYmRhT3B0aW9uc1xuICAgICAqICAgfTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhd3NMYW1iZGFPcHRpb25zPzogUGFydGlhbDxMYW1iZGEuQ3JlYXRlRnVuY3Rpb25SZXF1ZXN0PjtcblxuICAgIC8qKlxuICAgICAqIEFkZGl0aW9uYWwgb3B0aW9ucyB0byBwYXNzIHRvIGFsbCBBV1Mgc2VydmljZXMuIFNlZVxuICAgICAqIHtAbGluayBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sIHwgQVdTLkNvbmZpZ30uXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBJZiB5b3UgbmVlZCB0byBzcGVjaWZ5IEFXUyBvcHRpb25zIHN1Y2ggYXMgY3JlZGVudGlhbHMsIHlvdSBjYW4gcGFzcyBzZXRcbiAgICAgKiB0aGVzZSBvcHRpb25zIGhlcmUuIE5vdGUgdGhhdCBmYWFzdC5qcyB3aWxsIG92ZXJyaWRlIHNvbWUgb3B0aW9ucyBldmVuIGlmXG4gICAgICogdGhleSBhcmUgc3BlY2lmaWVkIGhlcmUsIHNwZWNpZmljYWxseSB0aGUgb3B0aW9ucyB1c2VkIHRvIGNyZWF0ZSB0aGVcbiAgICAgKiBgTGFtYmRhYCBzZXJ2aWNlLCB0byBlbnN1cmUgdGhleSBhbGxvdyBmb3IgZmFhc3QgdG8gZnVuY3Rpb24gY29ycmVjdGx5LlxuICAgICAqIE9wdGlvbnMgc2V0IGluIHtAbGluayBDb21tb25PcHRpb25zfSBvdmVycmlkZSB0aG9zZSBzZXQgaGVyZS5cbiAgICAgKlxuICAgICAqIEV4YW1wbGUgb2YgcGFzc2luZyBpbiBjcmVkZW50aWFsczpcbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAgIGNvbnN0IGNyZWRlbnRpYWxzID0geyBhY2Nlc3NLZXlJZCwgc2VjcmV0QWNjZXNzS2V5IH07XG4gICAgICogICBjb25zdCBtID0gYXdhaXQgZmFhc3RBd3MoZnVuY3MsIHsgY3JlZGVudGlhbHMgfSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXdzQ29uZmlnPzogQ29uZmlndXJhdGlvbk9wdGlvbnM7XG5cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX2djV29ya2VyPzogKHdvcms6IEF3c0djV29yaywgc2VydmljZXM6IEF3c1NlcnZpY2VzKSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgbGV0IGRlZmF1bHRzOiBSZXF1aXJlZDxBd3NPcHRpb25zPiA9IHtcbiAgICAuLi5jb21tb25EZWZhdWx0cyxcbiAgICByZWdpb246IFwidXMtd2VzdC0yXCIsXG4gICAgUm9sZU5hbWU6IFwiZmFhc3QtY2FjaGVkLWxhbWJkYS1yb2xlXCIsXG4gICAgbWVtb3J5U2l6ZTogMTcyOCxcbiAgICBhd3NMYW1iZGFPcHRpb25zOiB7fSxcbiAgICBhd3NDb25maWc6IHt9LFxuICAgIF9nY1dvcmtlcjogZGVmYXVsdEdjV29ya2VyXG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEF3c1ByaWNlcyB7XG4gICAgbGFtYmRhUGVyUmVxdWVzdDogbnVtYmVyO1xuICAgIGxhbWJkYVBlckdiU2Vjb25kOiBudW1iZXI7XG4gICAgc25zUGVyNjRrUHVibGlzaDogbnVtYmVyO1xuICAgIHNxc1BlcjY0a1JlcXVlc3Q6IG51bWJlcjtcbiAgICBkYXRhT3V0UGVyR2I6IG51bWJlcjtcbiAgICBsb2dzSW5nZXN0ZWRQZXJHYjogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgQXdzTWV0cmljcyB7XG4gICAgb3V0Ym91bmRCeXRlcyA9IDA7XG4gICAgc25zNjRrUmVxdWVzdHMgPSAwO1xuICAgIHNxczY0a1JlcXVlc3RzID0gMDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBd3NSZXNvdXJjZXMge1xuICAgIEZ1bmN0aW9uTmFtZTogc3RyaW5nO1xuICAgIFJvbGVOYW1lOiBzdHJpbmc7XG4gICAgcmVnaW9uOiBBd3NSZWdpb247XG4gICAgUmVzcG9uc2VRdWV1ZVVybD86IHN0cmluZztcbiAgICBSZXNwb25zZVF1ZXVlQXJuPzogc3RyaW5nO1xuICAgIFJlcXVlc3RUb3BpY0Fybj86IHN0cmluZztcbiAgICBTTlNMYW1iZGFTdWJzY3JpcHRpb25Bcm4/OiBzdHJpbmc7XG4gICAgbG9nR3JvdXBOYW1lOiBzdHJpbmc7XG4gICAgbGF5ZXI/OiBBd3NMYXllckluZm87XG4gICAgQnVja2V0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF3c1NlcnZpY2VzIHtcbiAgICByZWFkb25seSBsYW1iZGE6IExhbWJkYTtcbiAgICByZWFkb25seSBsYW1iZGEyOiBMYW1iZGE7IC8vIFNwZWNpYWwgTGFtYmRhIGluc3RhbmNlIGNvbmZpZ3VyZWQgZm9yIGludm9jYXRpb25zLlxuICAgIHJlYWRvbmx5IGNsb3Vkd2F0Y2g6IENsb3VkV2F0Y2hMb2dzO1xuICAgIHJlYWRvbmx5IGlhbTogSUFNO1xuICAgIHJlYWRvbmx5IHNxczogU1FTO1xuICAgIHJlYWRvbmx5IHNuczogU05TO1xuICAgIHJlYWRvbmx5IHByaWNpbmc6IFByaWNpbmc7XG4gICAgcmVhZG9ubHkgc3RzOiBTVFM7XG4gICAgcmVhZG9ubHkgczM6IFMzO1xufVxuXG4vKipcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBd3NTdGF0ZSB7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHJlc291cmNlczogQXdzUmVzb3VyY2VzO1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBzZXJ2aWNlczogQXdzU2VydmljZXM7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIG9wdGlvbnM6IFJlcXVpcmVkPEF3c09wdGlvbnM+O1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBtZXRyaWNzOiBBd3NNZXRyaWNzO1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBnY1Byb21pc2U/OiBQcm9taXNlPFwiZG9uZVwiIHwgXCJza2lwcGVkXCI+O1xufVxuXG5leHBvcnQgdHlwZSBBd3NHY1dvcmsgPVxuICAgIHwge1xuICAgICAgICAgIHR5cGU6IFwiU2V0TG9nUmV0ZW50aW9uXCI7XG4gICAgICAgICAgbG9nR3JvdXBOYW1lOiBzdHJpbmc7XG4gICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiBudW1iZXI7XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgICAgdHlwZTogXCJEZWxldGVSZXNvdXJjZXNcIjtcbiAgICAgICAgICByZXNvdXJjZXM6IEF3c1Jlc291cmNlcztcbiAgICAgIH1cbiAgICB8IHtcbiAgICAgICAgICB0eXBlOiBcIkRlbGV0ZUxheWVyVmVyc2lvblwiO1xuICAgICAgICAgIExheWVyTmFtZTogc3RyaW5nO1xuICAgICAgICAgIFZlcnNpb25OdW1iZXI6IG51bWJlcjtcbiAgICAgIH07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjYXJlZnVsbHk8VT4oYXJnOiBSZXF1ZXN0PFUsIEFXU0Vycm9yPikge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBhcmcucHJvbWlzZSgpO1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIGxvZy53YXJuKGVycik7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBxdWlldGx5PFU+KGFyZzogUmVxdWVzdDxVLCBBV1NFcnJvcj4pIHtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgYXJnLnByb21pc2UoKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxufVxuXG5leHBvcnQgY29uc3QgY3JlYXRlQXdzQXBpcyA9IHRocm90dGxlKFxuICAgIHsgY29uY3VycmVuY3k6IDEgfSxcbiAgICBhc3luYyAocmVnaW9uOiBBd3NSZWdpb24sIGF3c0NvbmZpZzogQ29uZmlndXJhdGlvbk9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCBsb2dnZXIgPSBsb2cuYXdzc2RrLmVuYWJsZWQgPyB7IGxvZzogbG9nLmF3c3NkayB9IDogdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBjb21tb246IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgbWF4UmV0cmllczogNixcbiAgICAgICAgICAgIGNvcnJlY3RDbG9ja1NrZXc6IHRydWUsXG4gICAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgICAuLi5hd3NDb25maWcsXG4gICAgICAgICAgICByZWdpb25cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgYWdlbnQgPSBuZXcgaHR0cHMuQWdlbnQoeyBrZWVwQWxpdmU6IHRydWUsIG1heFNvY2tldHM6IDEwMDAsIHRpbWVvdXQ6IDAgfSk7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VzOiBBd3NTZXJ2aWNlcyA9IHtcbiAgICAgICAgICAgIGlhbTogbmV3IElBTSh7IGFwaVZlcnNpb246IFwiMjAxMC0wNS0wOFwiLCAuLi5jb21tb24gfSksXG4gICAgICAgICAgICBsYW1iZGE6IG5ldyBMYW1iZGEoeyBhcGlWZXJzaW9uOiBcIjIwMTUtMDMtMzFcIiwgLi4uY29tbW9uIH0pLFxuICAgICAgICAgICAgLy8gU3BlY2lhbCBMYW1iZGEgaW5zdGFuY2Ugd2l0aCBjb25maWd1cmF0aW9uIG9wdGltaXplZCBmb3JcbiAgICAgICAgICAgIC8vIGludm9jYXRpb25zLlxuICAgICAgICAgICAgbGFtYmRhMjogbmV3IExhbWJkYSh7XG4gICAgICAgICAgICAgICAgYXBpVmVyc2lvbjogXCIyMDE1LTAzLTMxXCIsXG4gICAgICAgICAgICAgICAgLi4uY29tbW9uLFxuICAgICAgICAgICAgICAgIC8vIFJldHJpZXMgYXJlIGhhbmRsZWQgYnkgZmFhc3QuanMsIG5vdCB0aGUgc2RrLlxuICAgICAgICAgICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgMTIwcyB0aW1lb3V0IGlzIHRvbyBzaG9ydCwgZXNwZWNpYWxseSBmb3IgaHR0cHNcbiAgICAgICAgICAgICAgICAvLyBtb2RlLlxuICAgICAgICAgICAgICAgIGh0dHBPcHRpb25zOiB7IHRpbWVvdXQ6IDAsIGFnZW50IH1cbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgY2xvdWR3YXRjaDogbmV3IENsb3VkV2F0Y2hMb2dzKHsgYXBpVmVyc2lvbjogXCIyMDE0LTAzLTI4XCIsIC4uLmNvbW1vbiB9KSxcbiAgICAgICAgICAgIHNxczogbmV3IFNRUyh7IGFwaVZlcnNpb246IFwiMjAxMi0xMS0wNVwiLCAuLi5jb21tb24gfSksXG4gICAgICAgICAgICBzbnM6IG5ldyBTTlMoeyBhcGlWZXJzaW9uOiBcIjIwMTAtMDMtMzFcIiwgLi4uY29tbW9uIH0pLFxuICAgICAgICAgICAgcHJpY2luZzogbmV3IFByaWNpbmcoeyByZWdpb246IFwidXMtZWFzdC0xXCIsIC4uLmNvbW1vbiB9KSxcbiAgICAgICAgICAgIHN0czogbmV3IFNUUyh7IGFwaVZlcnNpb246IFwiMjAxMS0wNi0xNVwiLCAuLi5jb21tb24gfSksXG4gICAgICAgICAgICBzMzogbmV3IFMzKHsgYXBpVmVyc2lvbjogXCIyMDA2LTAzLTAxXCIsIC4uLmNvbW1vbiB9KVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gc2VydmljZXM7XG4gICAgfVxuKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuc3VyZVJvbGVSYXcoXG4gICAgUm9sZU5hbWU6IHN0cmluZyxcbiAgICBzZXJ2aWNlczogQXdzU2VydmljZXMsXG4gICAgY3JlYXRlUm9sZTogYm9vbGVhblxuKSB7XG4gICAgY29uc3QgeyBpYW0gfSA9IHNlcnZpY2VzO1xuICAgIGxvZy5pbmZvKGBDaGVja2luZyBmb3IgY2FjaGVkIGxhbWJkYSByb2xlYCk7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBpYW0uZ2V0Um9sZSh7IFJvbGVOYW1lIH0pLnByb21pc2UoKTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLlJvbGU7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgaWYgKCFjcmVhdGVSb2xlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIGBjb3VsZCBub3QgZmluZCByb2xlIFwiJHtSb2xlTmFtZX1cImApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBkZWZhdWx0IHJvbGUgXCIke1JvbGVOYW1lfVwiIGZvciBmYWFzdCB0cmFtcG9saW5lIGZ1bmN0aW9uYCk7XG4gICAgY29uc3QgQXNzdW1lUm9sZVBvbGljeURvY3VtZW50ID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBWZXJzaW9uOiBcIjIwMTItMTAtMTdcIixcbiAgICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgUHJpbmNpcGFsOiB7IFNlcnZpY2U6IFwibGFtYmRhLmFtYXpvbmF3cy5jb21cIiB9LFxuICAgICAgICAgICAgICAgIEFjdGlvbjogXCJzdHM6QXNzdW1lUm9sZVwiLFxuICAgICAgICAgICAgICAgIEVmZmVjdDogXCJBbGxvd1wiXG4gICAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBjb25zdCByb2xlUGFyYW1zOiBJQU0uQ3JlYXRlUm9sZVJlcXVlc3QgPSB7XG4gICAgICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudCxcbiAgICAgICAgUm9sZU5hbWUsXG4gICAgICAgIERlc2NyaXB0aW9uOiBcInJvbGUgZm9yIGxhbWJkYSBmdW5jdGlvbnMgY3JlYXRlZCBieSBmYWFzdFwiLFxuICAgICAgICBNYXhTZXNzaW9uRHVyYXRpb246IDM2MDBcbiAgICB9O1xuICAgIGxvZy5pbmZvKGBDYWxsaW5nIGNyZWF0ZVJvbGVgKTtcbiAgICBjb25zdCBQb2xpY3lBcm4gPSBcImFybjphd3M6aWFtOjphd3M6cG9saWN5L0FkbWluaXN0cmF0b3JBY2Nlc3NcIjtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCByb2xlUmVzcG9uc2UgPSBhd2FpdCBpYW0uY3JlYXRlUm9sZShyb2xlUGFyYW1zKS5wcm9taXNlKCk7XG4gICAgICAgIGxvZy5pbmZvKGBBdHRhY2hpbmcgYWRtaW5pc3RyYXRvciByb2xlIHBvbGljeWApO1xuICAgICAgICBhd2FpdCBpYW0uYXR0YWNoUm9sZVBvbGljeSh7IFJvbGVOYW1lLCBQb2xpY3lBcm4gfSkucHJvbWlzZSgpO1xuICAgICAgICByZXR1cm4gcm9sZVJlc3BvbnNlLlJvbGU7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSBcIkVudGl0eUFscmVhZHlFeGlzdHNcIikge1xuICAgICAgICAgICAgYXdhaXQgc2xlZXAoNTAwMCk7XG4gICAgICAgICAgICBjb25zdCByb2xlUmVzcG9uc2UgPSBhd2FpdCBpYW0uZ2V0Um9sZSh7IFJvbGVOYW1lIH0pLnByb21pc2UoKTtcbiAgICAgICAgICAgIGF3YWl0IGlhbS5hdHRhY2hSb2xlUG9saWN5KHsgUm9sZU5hbWUsIFBvbGljeUFybiB9KS5wcm9taXNlKCk7XG4gICAgICAgICAgICByZXR1cm4gcm9sZVJlc3BvbnNlLlJvbGU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoZXJyLCBgZmFpbGVkIHRvIGNyZWF0ZSByb2xlIFwiJHtSb2xlTmFtZX1cImApO1xuICAgIH1cbn1cblxuZXhwb3J0IGNvbnN0IGVuc3VyZVJvbGUgPSB0aHJvdHRsZShcbiAgICB7IGNvbmN1cnJlbmN5OiAxLCByYXRlOiAyLCBtZW1vaXplOiB0cnVlLCByZXRyeTogMTIgfSxcbiAgICBlbnN1cmVSb2xlUmF3XG4pO1xuXG5jb25zdCBSZXNwb25zZVF1ZXVlSWQgPSBhd3NUcmFtcG9saW5lLklOVk9DQVRJT05fVEVTVF9RVUVVRTtcbmNvbnN0IGVtcHR5RmNhbGwgPSB7IGNhbGxJZDogXCIwXCIsIG1vZHVsZVBhdGg6IFwiXCIsIG5hbWU6IFwiXCIsIGFyZ3M6IFwiXCIsIFJlc3BvbnNlUXVldWVJZCB9O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlTGF5ZXIoXG4gICAgbGFtYmRhOiBMYW1iZGEsXG4gICAgcGFja2FnZUpzb246IHN0cmluZyB8IG9iamVjdCB8IHVuZGVmaW5lZCxcbiAgICB1c2VEZXBlbmRlbmN5Q2FjaGluZzogYm9vbGVhbixcbiAgICBGdW5jdGlvbk5hbWU6IHN0cmluZyxcbiAgICByZWdpb246IEF3c1JlZ2lvbixcbiAgICByZXRlbnRpb25JbkRheXM6IG51bWJlcixcbiAgICBhd3NMYW1iZGFPcHRpb25zOiBQYXJ0aWFsPExhbWJkYS5DcmVhdGVGdW5jdGlvblJlcXVlc3Q+XG4pOiBQcm9taXNlPEF3c0xheWVySW5mbyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICghcGFja2FnZUpzb24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsb2cuaW5mbyhgQnVpbGRpbmcgbm9kZV9tb2R1bGVzYCk7XG5cbiAgICBjb25zdCBwYWNrYWdlSnNvbkNvbnRlbnRzID1cbiAgICAgICAgdHlwZW9mIHBhY2thZ2VKc29uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICA/IChhd2FpdCByZWFkRmlsZShwYWNrYWdlSnNvbikpLnRvU3RyaW5nKClcbiAgICAgICAgICAgIDogSlNPTi5zdHJpbmdpZnkocGFja2FnZUpzb24pO1xuXG4gICAgbGV0IExheWVyTmFtZTtcbiAgICBpZiAodXNlRGVwZW5kZW5jeUNhY2hpbmcpIHtcbiAgICAgICAgY29uc3QgaGFzaGVyID0gY3JlYXRlSGFzaChcInNoYTI1NlwiKTtcbiAgICAgICAgaGFzaGVyLnVwZGF0ZShwYWNrYWdlSnNvbkNvbnRlbnRzKTtcbiAgICAgICAgaGFzaGVyLnVwZGF0ZShKU09OLnN0cmluZ2lmeShhd3NMYW1iZGFPcHRpb25zLkFyY2hpdGVjdHVyZXMgPz8gXCJcIikpO1xuICAgICAgICBjb25zdCBjYWNoZUtleSA9IGhhc2hlci5kaWdlc3QoXCJoZXhcIik7XG4gICAgICAgIExheWVyTmFtZSA9IGBmYWFzdC0ke2NhY2hlS2V5fWA7XG4gICAgICAgIGNvbnN0IGxheWVycyA9IGF3YWl0IHF1aWV0bHkobGFtYmRhLmxpc3RMYXllclZlcnNpb25zKHsgTGF5ZXJOYW1lIH0pKTtcbiAgICAgICAgaWYgKGxheWVycz8uTGF5ZXJWZXJzaW9ucz8ubGVuZ3RoID8/IDAgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBbeyBWZXJzaW9uLCBMYXllclZlcnNpb25Bcm4sIENyZWF0ZWREYXRlIH1dID1cbiAgICAgICAgICAgICAgICBsYXllcnM/LkxheWVyVmVyc2lvbnMgPz8gW107XG4gICAgICAgICAgICBpZiAoIWhhc0V4cGlyZWQoQ3JlYXRlZERhdGUsIHJldGVudGlvbkluRGF5cykgJiYgVmVyc2lvbiAmJiBMYXllclZlcnNpb25Bcm4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBWZXJzaW9uLCBMYXllclZlcnNpb25Bcm4sIExheWVyTmFtZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgTGF5ZXJOYW1lID0gRnVuY3Rpb25OYW1lO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGZhYXN0TW9kdWxlID0gYXdhaXQgZmFhc3RBd3MoYXdzTnBtLCB7XG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICB0aW1lb3V0OiAzMDAsXG4gICAgICAgICAgICBtZW1vcnlTaXplOiAyMDQ4LFxuICAgICAgICAgICAgbW9kZTogXCJodHRwc1wiLFxuICAgICAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgICAgICBtYXhSZXRyaWVzOiAwLFxuICAgICAgICAgICAgd2VicGFja09wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBleHRlcm5hbHM6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYXdzTGFtYmRhT3B0aW9uc1xuICAgICAgICB9KTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbGxBcmdzOiBhd3NOcG0uTnBtSW5zdGFsbEFyZ3MgPSB7XG4gICAgICAgICAgICAgICAgcGFja2FnZUpzb25Db250ZW50cyxcbiAgICAgICAgICAgICAgICBMYXllck5hbWUsXG4gICAgICAgICAgICAgICAgRnVuY3Rpb25OYW1lLFxuICAgICAgICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICAgICAgICByZXRlbnRpb25JbkRheXNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB7IGluc3RhbGxMb2csIGxheWVySW5mbyB9ID0gYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLm5wbUluc3RhbGwoXG4gICAgICAgICAgICAgICAgaW5zdGFsbEFyZ3NcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsb2cuaW5mbyhpbnN0YWxsTG9nKTtcbiAgICAgICAgICAgIHJldHVybiBsYXllckluZm87XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5jbGVhbnVwKCk7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwiZmFpbGVkIHRvIGNyZWF0ZSBsYW1iZGEgbGF5ZXIgZnJvbSBwYWNrYWdlSnNvblwiKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dVcmwoc3RhdGU6IEF3c1N0YXRlKSB7XG4gICAgY29uc3QgeyByZWdpb24sIEZ1bmN0aW9uTmFtZSB9ID0gc3RhdGUucmVzb3VyY2VzO1xuICAgIHJldHVybiBnZXRMb2dVcmwocmVnaW9uLCBGdW5jdGlvbk5hbWUpO1xufVxuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZSA9IHRocm90dGxlKFxuICAgIHsgY29uY3VycmVuY3k6IEluZmluaXR5LCByYXRlOiAyIH0sXG4gICAgYXN5bmMgKGZNb2R1bGU6IHN0cmluZywgbm9uY2U6IFVVSUQsIG9wdGlvbnM6IFJlcXVpcmVkPEF3c09wdGlvbnM+KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgcmVnaW9uLCB0aW1lb3V0LCBtZW1vcnlTaXplLCBlbnYsIGNvbmN1cnJlbmN5LCBtb2RlIH0gPSBvcHRpb25zO1xuICAgICAgICBpZiAoY29uY3VycmVuY3kgPiAxMDAgJiYgbW9kZSAhPT0gXCJxdWV1ZVwiKSB7XG4gICAgICAgICAgICBsb2cud2FybihgQ29uc2lkZXIgdXNpbmcgcXVldWUgbW9kZSBmb3IgaGlnaGVyIGxldmVscyBvZiBjb25jdXJyZW5jeTpgKTtcbiAgICAgICAgICAgIGxvZy53YXJuKGBodHRwczovL2ZhYXN0anMub3JnL2RvY3MvYXBpL2ZhYXN0anMuY29tbW9ub3B0aW9ucy5tb2RlYCk7XG4gICAgICAgIH1cbiAgICAgICAgbG9nLmluZm8oYENyZWF0aW5nIEFXUyBBUElzYCk7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgY3JlYXRlQXdzQXBpcyhyZWdpb24sIG9wdGlvbnMuYXdzQ29uZmlnKTtcbiAgICAgICAgY29uc3QgeyBsYW1iZGEgfSA9IHNlcnZpY2VzO1xuICAgICAgICBjb25zdCBGdW5jdGlvbk5hbWUgPSBgZmFhc3QtJHtub25jZX1gO1xuICAgICAgICBjb25zdCB7IHBhY2thZ2VKc29uLCB1c2VEZXBlbmRlbmN5Q2FjaGluZywgZGVzY3JpcHRpb24gfSA9IG9wdGlvbnM7XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlRnVuY3Rpb25SZXF1ZXN0KFxuICAgICAgICAgICAgQ29kZTogTGFtYmRhLkZ1bmN0aW9uQ29kZSxcbiAgICAgICAgICAgIFJvbGU6IHN0cmluZyxcbiAgICAgICAgICAgIHJlc3BvbnNlUXVldWVBcm46IHN0cmluZyxcbiAgICAgICAgICAgIGxheWVySW5mbz86IEF3c0xheWVySW5mb1xuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IHsgTGF5ZXJzID0gW10sIC4uLnJlc3QgfSA9IG9wdGlvbnMuYXdzTGFtYmRhT3B0aW9ucztcbiAgICAgICAgICAgIGlmIChsYXllckluZm8pIHtcbiAgICAgICAgICAgICAgICBMYXllcnMucHVzaChsYXllckluZm8uTGF5ZXJWZXJzaW9uQXJuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3Q6IExhbWJkYS5DcmVhdGVGdW5jdGlvblJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgICAgRnVuY3Rpb25OYW1lLFxuICAgICAgICAgICAgICAgIFJvbGUsXG4gICAgICAgICAgICAgICAgUnVudGltZTogXCJub2RlanMxNC54XCIsXG4gICAgICAgICAgICAgICAgSGFuZGxlcjogXCJpbmRleC50cmFtcG9saW5lXCIsXG4gICAgICAgICAgICAgICAgQ29kZSxcbiAgICAgICAgICAgICAgICBEZXNjcmlwdGlvbjogXCJmYWFzdCB0cmFtcG9saW5lIGZ1bmN0aW9uXCIsXG4gICAgICAgICAgICAgICAgVGltZW91dDogdGltZW91dCxcbiAgICAgICAgICAgICAgICBNZW1vcnlTaXplOiBtZW1vcnlTaXplLFxuICAgICAgICAgICAgICAgIEVudmlyb25tZW50OiB7IFZhcmlhYmxlczogZW52IH0sXG4gICAgICAgICAgICAgICAgTGF5ZXJzLFxuICAgICAgICAgICAgICAgIC4uLnJlc3RcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsb2cuaW5mbyhgY3JlYXRlRnVuY3Rpb25SZXF1ZXN0OiAlT2AsIHJlcXVlc3QpO1xuICAgICAgICAgICAgbGV0IGZ1bmM7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGZ1bmMgPSBhd2FpdCBsYW1iZGEuY3JlYXRlRnVuY3Rpb24ocmVxdWVzdCkucHJvbWlzZSgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHJldHJ5T3AoMiwgKCkgPT5cbiAgICAgICAgICAgICAgICAgICAgbGFtYmRhLndhaXRGb3IoXCJmdW5jdGlvbkFjdGl2ZVwiLCB7IEZ1bmN0aW9uTmFtZSB9KS5wcm9taXNlKClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyPy5tZXNzYWdlPy5tYXRjaCgvRnVuY3Rpb24gYWxyZWFkeSBleGlzdC8pKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMgPSAoYXdhaXQgbGFtYmRhLmdldEZ1bmN0aW9uKHsgRnVuY3Rpb25OYW1lIH0pLnByb21pc2UoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5Db25maWd1cmF0aW9uITtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwiQ3JlYXRlIGZ1bmN0aW9uIGZhaWx1cmVcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9nLmluZm8oXG4gICAgICAgICAgICAgICAgYENyZWF0ZWQgZnVuY3Rpb24gJHtmdW5jLkZ1bmN0aW9uTmFtZX0sIEZ1bmN0aW9uQXJuOiAke2Z1bmMuRnVuY3Rpb25Bcm59IFske2Rlc2NyaXB0aW9ufV1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbG9nLm1pbmltYWwoYENyZWF0ZWQgZnVuY3Rpb24gJHtmdW5jLkZ1bmN0aW9uTmFtZX0gWyR7ZGVzY3JpcHRpb259XWApO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25maWcgPSBhd2FpdCByZXRyeU9wKFxuICAgICAgICAgICAgICAgICAgICAoZXJyLCBuKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgbiA8IDUgJiYgZXJyPy5tZXNzYWdlPy5tYXRjaCgvZGVzdGluYXRpb24gQVJOLippcyBpbnZhbGlkLyksXG4gICAgICAgICAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBsYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucHV0RnVuY3Rpb25FdmVudEludm9rZUNvbmZpZyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF4aW11bVJldHJ5QXR0ZW1wdHM6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1heGltdW1FdmVudEFnZUluU2Vjb25kczogMjE2MDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlc3RpbmF0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPbkZhaWx1cmU6IHsgRGVzdGluYXRpb246IHJlc3BvbnNlUXVldWVBcm4gfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucHJvbWlzZSgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBsb2cuaW5mbyhgRnVuY3Rpb24gZXZlbnQgaW52b2NhdGlvbiBjb25maWc6ICVPYCwgY29uZmlnKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoZXJyLCBcInB1dEZ1bmN0aW9uRXZlbnRJbnZva2VDb25maWcgZmFpbHVyZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmdW5jO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgd3JhcHBlclZlcmJvc2UgfSA9IG9wdGlvbnMuZGVidWdPcHRpb25zO1xuICAgICAgICBhc3luYyBmdW5jdGlvbiBjcmVhdGVDb2RlQnVuZGxlKCkge1xuICAgICAgICAgICAgY29uc3QgeyB0aW1lb3V0LCBjaGlsZFByb2Nlc3MsIG1vZGUgfSA9IG9wdGlvbnM7XG4gICAgICAgICAgICBjb25zdCBoYXNMYW1iZGFUaW1lb3V0QnVnID0gbW9kZSAhPT0gXCJxdWV1ZVwiICYmIHRpbWVvdXQgPj0gMTgwO1xuICAgICAgICAgICAgY29uc3QgY2hpbGRQcm9jZXNzVGltZW91dE1zID1cbiAgICAgICAgICAgICAgICBoYXNMYW1iZGFUaW1lb3V0QnVnICYmIGNoaWxkUHJvY2VzcyA/ICh0aW1lb3V0IC0gNSkgKiAxMDAwIDogMDtcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkUHJvY2Vzc01lbW9yeUxpbWl0TWIgPSBvcHRpb25zLmNoaWxkUHJvY2Vzc01lbW9yeU1iO1xuICAgICAgICAgICAgY29uc3Qgd3JhcHBlck9wdGlvbnM6IFdyYXBwZXJPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIHdyYXBwZXJWZXJib3NlLFxuICAgICAgICAgICAgICAgIGNoaWxkUHJvY2Vzc1RpbWVvdXRNcyxcbiAgICAgICAgICAgICAgICBjaGlsZFByb2Nlc3NNZW1vcnlMaW1pdE1iXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgYnVuZGxlID0gYXdzUGFja2VyKGZNb2R1bGUsIG9wdGlvbnMsIHdyYXBwZXJPcHRpb25zLCBGdW5jdGlvbk5hbWUpO1xuICAgICAgICAgICAgcmV0dXJuIHsgWmlwRmlsZTogYXdhaXQgc3RyZWFtVG9CdWZmZXIoKGF3YWl0IGJ1bmRsZSkuYXJjaGl2ZSkgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgUm9sZU5hbWUgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHN0YXRlOiBBd3NTdGF0ZSA9IHtcbiAgICAgICAgICAgIHJlc291cmNlczoge1xuICAgICAgICAgICAgICAgIEZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgICAgICBSb2xlTmFtZSxcbiAgICAgICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICAgICAgbG9nR3JvdXBOYW1lOiBnZXRMb2dHcm91cE5hbWUoRnVuY3Rpb25OYW1lKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlcnZpY2VzLFxuICAgICAgICAgICAgbWV0cmljczogbmV3IEF3c01ldHJpY3MoKSxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB7IGdjLCByZXRlbnRpb25JbkRheXMsIF9nY1dvcmtlcjogZ2NXb3JrZXIgfSA9IG9wdGlvbnM7XG4gICAgICAgIGlmIChnYyA9PT0gXCJhdXRvXCIgfHwgZ2MgPT09IFwiZm9yY2VcIikge1xuICAgICAgICAgICAgbG9nLmdjKGBTdGFydGluZyBnYXJiYWdlIGNvbGxlY3RvcmApO1xuICAgICAgICAgICAgc3RhdGUuZ2NQcm9taXNlID0gY29sbGVjdEdhcmJhZ2UoXG4gICAgICAgICAgICAgICAgZ2NXb3JrZXIsXG4gICAgICAgICAgICAgICAgc2VydmljZXMsXG4gICAgICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgICAgIHJldGVudGlvbkluRGF5cyxcbiAgICAgICAgICAgICAgICBnY1xuICAgICAgICAgICAgKS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgICAgIGxvZy5nYyhgR2FyYmFnZSBjb2xsZWN0aW9uIGVycm9yOiAke2Vycn1gKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJza2lwcGVkXCIgYXMgY29uc3Q7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgbGFtYmRhIGZ1bmN0aW9uYCk7XG4gICAgICAgICAgICBjb25zdCByb2xlUHJvbWlzZSA9IGVuc3VyZVJvbGUoXG4gICAgICAgICAgICAgICAgUm9sZU5hbWUsXG4gICAgICAgICAgICAgICAgc2VydmljZXMsXG4gICAgICAgICAgICAgICAgUm9sZU5hbWUgPT09IGRlZmF1bHRzLlJvbGVOYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2VRdWV1ZVByb21pc2UgPSBjcmVhdGVSZXNwb25zZVF1ZXVlSW1wbChzdGF0ZSwgRnVuY3Rpb25OYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHByaWNpbmdQcm9taXNlID0gcmVxdWVzdEF3c1ByaWNlcyhzZXJ2aWNlcy5wcmljaW5nLCByZWdpb24pO1xuICAgICAgICAgICAgY29uc3QgY29kZUJ1bmRsZVByb21pc2UgPSBjcmVhdGVDb2RlQnVuZGxlKCk7XG4gICAgICAgICAgICAvLyBFbnN1cmUgcm9sZSBleGlzdHMgYmVmb3JlIGNyZWF0aW5nIGxhbWJkYSBsYXllciwgd2hpY2ggYWxzbyBuZWVkcyB0aGUgcm9sZS5cbiAgICAgICAgICAgIGNvbnN0IHJvbGUgPSBhd2FpdCByb2xlUHJvbWlzZTtcbiAgICAgICAgICAgIGNvbnN0IGxheWVyUHJvbWlzZSA9IGNyZWF0ZUxheWVyKFxuICAgICAgICAgICAgICAgIHNlcnZpY2VzLmxhbWJkYSxcbiAgICAgICAgICAgICAgICBwYWNrYWdlSnNvbixcbiAgICAgICAgICAgICAgICB1c2VEZXBlbmRlbmN5Q2FjaGluZyxcbiAgICAgICAgICAgICAgICBGdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgICAgIHJldGVudGlvbkluRGF5cyxcbiAgICAgICAgICAgICAgICBvcHRpb25zLmF3c0xhbWJkYU9wdGlvbnNcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNvbnN0IGNvZGVCdW5kbGUgPSBhd2FpdCBjb2RlQnVuZGxlUHJvbWlzZTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlUXVldWVBcm4gPSBhd2FpdCByZXNwb25zZVF1ZXVlUHJvbWlzZTtcbiAgICAgICAgICAgIGNvbnN0IGxheWVyID0gYXdhaXQgbGF5ZXJQcm9taXNlO1xuICAgICAgICAgICAgaWYgKGxheWVyKSB7XG4gICAgICAgICAgICAgICAgc3RhdGUucmVzb3VyY2VzLmxheWVyID0gbGF5ZXI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBsYW1iZGFGbkFybiE6IHN0cmluZztcbiAgICAgICAgICAgIGNvbnN0IHJldHJ5YWJsZSA9IFtcbiAgICAgICAgICAgICAgICAvcm9sZS8sXG4gICAgICAgICAgICAgICAgL0tNUyBFeGNlcHRpb24vLFxuICAgICAgICAgICAgICAgIC9pbnRlcm5hbCBzZXJ2aWNlIGVycm9yLyxcbiAgICAgICAgICAgICAgICAvTGF5ZXIgdmVyc2lvbi9cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zdCBzaG91bGRSZXRyeSA9IChlcnI6IEVycm9yLCBuOiBudW1iZXIpID0+XG4gICAgICAgICAgICAgICAgbiA8IDUgJiYgISFyZXRyeWFibGUuZmluZChyZWdleCA9PiBlcnI/Lm1lc3NhZ2U/Lm1hdGNoKHJlZ2V4KSk7XG5cbiAgICAgICAgICAgIGF3YWl0IHJldHJ5T3Aoc2hvdWxkUmV0cnksIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYW1iZGFGbiA9IGF3YWl0IGNyZWF0ZUZ1bmN0aW9uUmVxdWVzdChcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVCdW5kbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICByb2xlLkFybixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlUXVldWVBcm4sXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXllclxuICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIGxhbWJkYUZuQXJuID0gbGFtYmRhRm4uRnVuY3Rpb25Bcm4hO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSByb2xlIGZvciB0aGUgbGFtYmRhIGZ1bmN0aW9uIHdhcyBjcmVhdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlY2VudGx5LCB0ZXN0IHRoYXQgdGhlIHJvbGUgd29ya3MgYnkgaW52b2tpbmcgdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIGZ1bmN0aW9uLiBJZiBhbiBleGNlcHRpb24gb2NjdXJzLCB0aGUgZnVuY3Rpb24gaXNcbiAgICAgICAgICAgICAgICAgICAgLy8gZGVsZXRlZCBhbmQgcmUtZGVwbG95ZWQuIEVtcGlyaWNhbGx5LCB0aGlzIGlzIHRoZSB3YXlcbiAgICAgICAgICAgICAgICAgICAgLy8gdG8gZW5zdXJlIHN1Y2Nlc3NmdWwgbGFtYmRhIGNyZWF0aW9uIHdoZW4gYW4gSUFNIHJvbGVcbiAgICAgICAgICAgICAgICAgICAgLy8gaXMgcmVjZW50bHkgY3JlYXRlZC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKERhdGUubm93KCkgLSByb2xlLkNyZWF0ZURhdGUuZ2V0VGltZSgpIDwgMzAwICogMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBtZXRyaWNzIH0gPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZuID0gRnVuY3Rpb25OYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV2ZXIgPSBuZXcgUHJvbWlzZTx2b2lkPihfID0+IHt9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHJldHJ5T3AoMSwgKCkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnZva2VIdHRwcyhsYW1iZGEsIGZuLCBlbXB0eUZjYWxsLCBtZXRyaWNzLCBuZXZlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBsYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVsZXRlRnVuY3Rpb24oeyBGdW5jdGlvbk5hbWUgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucHJvbWlzZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKF8gPT4ge30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOZXcgbGFtYmRhIGZ1bmN0aW9uICR7RnVuY3Rpb25OYW1lfSBmYWlsZWQgaW52b2NhdGlvbiB0ZXN0YFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCB7IG1vZGUgfSA9IG9wdGlvbnM7XG4gICAgICAgICAgICBpZiAobW9kZSA9PT0gXCJxdWV1ZVwiKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlUmVxdWVzdFF1ZXVlSW1wbChzdGF0ZSwgRnVuY3Rpb25OYW1lLCBsYW1iZGFGbkFybik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBwcmljaW5nUHJvbWlzZTtcbiAgICAgICAgICAgIGxvZy5pbmZvKGBMYW1iZGEgZnVuY3Rpb24gaW5pdGlhbGl6YXRpb24gY29tcGxldGUuYCk7XG4gICAgICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGNsZWFudXAoc3RhdGUsIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlUmVzb3VyY2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBkZWxldGVDYWNoZXM6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBnY1RpbWVvdXQ6IDMwXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIHt9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihcbiAgICAgICAgICAgICAgICB7IGNhdXNlOiBlcnIsIG5hbWU6IEZhYXN0RXJyb3JOYW1lcy5FQ1JFQVRFIH0sXG4gICAgICAgICAgICAgICAgXCJmYWlsZWQgdG8gaW5pdGlhbGl6ZSBjbG91ZCBmdW5jdGlvblwiXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuKTtcblxuYXN5bmMgZnVuY3Rpb24gaW52b2tlKFxuICAgIHN0YXRlOiBBd3NTdGF0ZSxcbiAgICBjYWxsOiBGdW5jdGlvbkNhbGwsXG4gICAgY2FuY2VsOiBQcm9taXNlPHZvaWQ+XG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IG1ldHJpY3MsIHNlcnZpY2VzLCByZXNvdXJjZXMsIG9wdGlvbnMgfSA9IHN0YXRlO1xuICAgIHN3aXRjaCAob3B0aW9ucy5tb2RlKSB7XG4gICAgICAgIGNhc2UgXCJhdXRvXCI6XG4gICAgICAgIGNhc2UgXCJodHRwc1wiOlxuICAgICAgICAgICAgY29uc3QgeyBsYW1iZGEyIH0gPSBzZXJ2aWNlcztcbiAgICAgICAgICAgIGNvbnN0IHsgRnVuY3Rpb25OYW1lIH0gPSByZXNvdXJjZXM7XG4gICAgICAgICAgICBhd2FpdCBpbnZva2VIdHRwcyhsYW1iZGEyLCBGdW5jdGlvbk5hbWUsIGNhbGwsIG1ldHJpY3MsIGNhbmNlbCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJxdWV1ZVwiOlxuICAgICAgICAgICAgY29uc3QgeyBzbnMgfSA9IHNlcnZpY2VzO1xuICAgICAgICAgICAgY29uc3QgeyBSZXF1ZXN0VG9waWNBcm4gfSA9IHJlc291cmNlcztcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgcHVibGlzaEZ1bmN0aW9uQ2FsbE1lc3NhZ2Uoc25zLCBSZXF1ZXN0VG9waWNBcm4hLCBjYWxsLCBtZXRyaWNzKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgYGludm9rZSBzbnMgZXJyb3IgJHtpbnNwZWN0KGNhbGwsIHVuZGVmaW5lZCwgOSl9YFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwb2xsKHN0YXRlOiBBd3NTdGF0ZSwgY2FuY2VsOiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTxQb2xsUmVzdWx0PiB7XG4gICAgcmV0dXJuIHJlY2VpdmVNZXNzYWdlcyhcbiAgICAgICAgc3RhdGUuc2VydmljZXMuc3FzLFxuICAgICAgICBzdGF0ZS5yZXNvdXJjZXMuUmVzcG9uc2VRdWV1ZVVybCEsXG4gICAgICAgIHN0YXRlLm1ldHJpY3MsXG4gICAgICAgIGNhbmNlbFxuICAgICk7XG59XG5cbmZ1bmN0aW9uIHJlc3BvbnNlUXVldWVJZChzdGF0ZTogQXdzU3RhdGUpOiBzdHJpbmcge1xuICAgIHJldHVybiBzdGF0ZS5yZXNvdXJjZXMuUmVzcG9uc2VRdWV1ZVVybCE7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGludm9rZUh0dHBzKFxuICAgIGxhbWJkYTogTGFtYmRhLFxuICAgIEZ1bmN0aW9uTmFtZTogc3RyaW5nLFxuICAgIG1lc3NhZ2U6IEZ1bmN0aW9uQ2FsbCxcbiAgICBtZXRyaWNzOiBBd3NNZXRyaWNzLFxuICAgIGNhbmNlbDogUHJvbWlzZTx2b2lkPlxuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVxdWVzdDogTGFtYmRhLkludm9jYXRpb25SZXF1ZXN0ID0ge1xuICAgICAgICBGdW5jdGlvbk5hbWUsXG4gICAgICAgIFBheWxvYWQ6IHNlcmlhbGl6ZShtZXNzYWdlKSxcbiAgICAgICAgTG9nVHlwZTogXCJOb25lXCJcbiAgICB9O1xuICAgIGNvbnN0IGF3c1JlcXVlc3QgPSBsYW1iZGEuaW52b2tlKHJlcXVlc3QpO1xuICAgIGNvbnN0IHJhd1Jlc3BvbnNlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFthd3NSZXF1ZXN0LnByb21pc2UoKSwgY2FuY2VsXSk7XG4gICAgaWYgKCFyYXdSZXNwb25zZSkge1xuICAgICAgICBsb2cuaW5mbyhgY2FuY2VsbGluZyBsYW1iZGEgaW52b2tlYCk7XG4gICAgICAgIGF3c1JlcXVlc3QuYWJvcnQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBtZXRyaWNzLm91dGJvdW5kQnl0ZXMgKz0gY29tcHV0ZUh0dHBSZXNwb25zZUJ5dGVzKFxuICAgICAgICByYXdSZXNwb25zZS4kcmVzcG9uc2UuaHR0cFJlc3BvbnNlLmhlYWRlcnNcbiAgICApO1xuXG4gICAgaWYgKHJhd1Jlc3BvbnNlLkxvZ1Jlc3VsdCkge1xuICAgICAgICBsb2cuaW5mbyhCdWZmZXIuZnJvbShyYXdSZXNwb25zZS5Mb2dSZXN1bHQhLCBcImJhc2U2NFwiKS50b1N0cmluZygpKTtcbiAgICB9XG5cbiAgICBpZiAocmF3UmVzcG9uc2UuRnVuY3Rpb25FcnJvcikge1xuICAgICAgICBjb25zdCBlcnJvciA9IHByb2Nlc3NBd3NFcnJvck1lc3NhZ2UocmF3UmVzcG9uc2UuUGF5bG9hZCBhcyBzdHJpbmcpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVSb2xlKFJvbGVOYW1lOiBzdHJpbmcsIGlhbTogSUFNKSB7XG4gICAgY29uc3QgcG9saWNpZXMgPSBhd2FpdCBjYXJlZnVsbHkoaWFtLmxpc3RBdHRhY2hlZFJvbGVQb2xpY2llcyh7IFJvbGVOYW1lIH0pKTtcbiAgICBjb25zdCBBdHRhY2hlZFBvbGljaWVzID0gcG9saWNpZXM/LkF0dGFjaGVkUG9saWNpZXMgPz8gW107XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIEF0dGFjaGVkUG9saWNpZXMubWFwKHAgPT4gcC5Qb2xpY3lBcm4hKS5tYXAoUG9saWN5QXJuID0+XG4gICAgICAgICAgICBjYXJlZnVsbHkoaWFtLmRldGFjaFJvbGVQb2xpY3koeyBSb2xlTmFtZSwgUG9saWN5QXJuIH0pKVxuICAgICAgICApXG4gICAgKTtcbiAgICBjb25zdCByb2xlUG9saWN5TGlzdFJlc3BvbnNlID0gYXdhaXQgY2FyZWZ1bGx5KGlhbS5saXN0Um9sZVBvbGljaWVzKHsgUm9sZU5hbWUgfSkpO1xuICAgIGNvbnN0IFJvbGVQb2xpY2llcyA9IHJvbGVQb2xpY3lMaXN0UmVzcG9uc2U/LlBvbGljeU5hbWVzID8/IFtdO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBSb2xlUG9saWNpZXMubWFwKFBvbGljeU5hbWUgPT5cbiAgICAgICAgICAgIGNhcmVmdWxseShpYW0uZGVsZXRlUm9sZVBvbGljeSh7IFJvbGVOYW1lLCBQb2xpY3lOYW1lIH0pKVxuICAgICAgICApXG4gICAgKTtcbiAgICBhd2FpdCBjYXJlZnVsbHkoaWFtLmRlbGV0ZVJvbGUoeyBSb2xlTmFtZSB9KSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVSZXNvdXJjZXMoXG4gICAgcmVzb3VyY2VzOiBQYXJ0aWFsPEF3c1Jlc291cmNlcz4sXG4gICAgc2VydmljZXM6IEF3c1NlcnZpY2VzLFxuICAgIG91dHB1dDogKG1zZzogc3RyaW5nKSA9PiB2b2lkID0gbG9nLmluZm9cbikge1xuICAgIGNvbnN0IHtcbiAgICAgICAgRnVuY3Rpb25OYW1lLFxuICAgICAgICBSb2xlTmFtZSxcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBSZXF1ZXN0VG9waWNBcm4sXG4gICAgICAgIFJlc3BvbnNlUXVldWVVcmwsXG4gICAgICAgIFJlc3BvbnNlUXVldWVBcm4sXG4gICAgICAgIFNOU0xhbWJkYVN1YnNjcmlwdGlvbkFybixcbiAgICAgICAgbG9nR3JvdXBOYW1lLFxuICAgICAgICBsYXllcixcbiAgICAgICAgQnVja2V0LFxuICAgICAgICAuLi5yZXN0XG4gICAgfSA9IHJlc291cmNlcztcbiAgICBjb25zdCBfZXhoYXVzdGl2ZUNoZWNrOiBSZXF1aXJlZDx0eXBlb2YgcmVzdD4gPSB7fTtcblxuICAgIGNvbnN0IHsgbGFtYmRhLCBzcXMsIHNucywgaWFtLCBzMywgY2xvdWR3YXRjaCB9ID0gc2VydmljZXM7XG4gICAgaWYgKFNOU0xhbWJkYVN1YnNjcmlwdGlvbkFybikge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBhd2FpdCBxdWlldGx5KHNucy51bnN1YnNjcmliZSh7IFN1YnNjcmlwdGlvbkFybjogU05TTGFtYmRhU3Vic2NyaXB0aW9uQXJuIH0pKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIG91dHB1dChgRGVsZXRlZCByZXF1ZXN0IHF1ZXVlIHN1YnNjcmlwdGlvbiB0byBsYW1iZGFgKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoUm9sZU5hbWUpIHtcbiAgICAgICAgYXdhaXQgZGVsZXRlUm9sZShSb2xlTmFtZSwgaWFtKTtcbiAgICB9XG4gICAgaWYgKFJlcXVlc3RUb3BpY0Fybikge1xuICAgICAgICBpZiAoYXdhaXQgcXVpZXRseShzbnMuZGVsZXRlVG9waWMoeyBUb3BpY0FybjogUmVxdWVzdFRvcGljQXJuIH0pKSkge1xuICAgICAgICAgICAgb3V0cHV0KGBEZWxldGVkIHJlcXVlc3QgcXVldWUgdG9waWM6ICR7UmVxdWVzdFRvcGljQXJufWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChSZXNwb25zZVF1ZXVlVXJsKSB7XG4gICAgICAgIGlmIChhd2FpdCBxdWlldGx5KHNxcy5kZWxldGVRdWV1ZSh7IFF1ZXVlVXJsOiBSZXNwb25zZVF1ZXVlVXJsIH0pKSkge1xuICAgICAgICAgICAgb3V0cHV0KGBEZWxldGVkIHJlc3BvbnNlIHF1ZXVlOiAke1Jlc3BvbnNlUXVldWVVcmx9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxheWVyKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGF3YWl0IHF1aWV0bHkoXG4gICAgICAgICAgICAgICAgbGFtYmRhLmRlbGV0ZUxheWVyVmVyc2lvbih7XG4gICAgICAgICAgICAgICAgICAgIExheWVyTmFtZTogbGF5ZXIuTGF5ZXJOYW1lLFxuICAgICAgICAgICAgICAgICAgICBWZXJzaW9uTnVtYmVyOiBsYXllci5WZXJzaW9uXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBvdXRwdXQoYERlbGV0ZWQgbGFtYmRhIGxheWVyOiAke2xheWVyLkxheWVyTmFtZX06JHtsYXllci5WZXJzaW9ufWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChCdWNrZXQpIHtcbiAgICAgICAgY29uc3Qgb2JqZWN0cyA9IGF3YWl0IHF1aWV0bHkoczMubGlzdE9iamVjdHNWMih7IEJ1Y2tldCwgUHJlZml4OiBcImZhYXN0LVwiIH0pKTtcbiAgICAgICAgaWYgKG9iamVjdHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGtleXMgPSAob2JqZWN0cy5Db250ZW50cyB8fCBbXSkubWFwKGVsZW0gPT4gKHsgS2V5OiBlbGVtLktleSEgfSkpO1xuICAgICAgICAgICAgaWYgKGF3YWl0IHF1aWV0bHkoczMuZGVsZXRlT2JqZWN0cyh7IEJ1Y2tldCwgRGVsZXRlOiB7IE9iamVjdHM6IGtleXMgfSB9KSkpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQoYERlbGV0ZWQgczMgb2JqZWN0czogJHtrZXlzLmxlbmd0aH0gb2JqZWN0cyBpbiBidWNrZXQgJHtCdWNrZXR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF3YWl0IHF1aWV0bHkoczMuZGVsZXRlQnVja2V0KHsgQnVja2V0IH0pKSkge1xuICAgICAgICAgICAgb3V0cHV0KGBEZWxldGVkIHMzIGJ1Y2tldDogJHtCdWNrZXR9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKEZ1bmN0aW9uTmFtZSkge1xuICAgICAgICBpZiAoYXdhaXQgcXVpZXRseShsYW1iZGEuZGVsZXRlRnVuY3Rpb24oeyBGdW5jdGlvbk5hbWUgfSkpKSB7XG4gICAgICAgICAgICBvdXRwdXQoYERlbGV0ZWQgZnVuY3Rpb246ICR7RnVuY3Rpb25OYW1lfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChsb2dHcm91cE5hbWUpIHtcbiAgICAgICAgaWYgKGF3YWl0IHF1aWV0bHkoY2xvdWR3YXRjaC5kZWxldGVMb2dHcm91cCh7IGxvZ0dyb3VwTmFtZSB9KSkpIHtcbiAgICAgICAgICAgIG91dHB1dChgRGVsZXRlZCBsb2cgZ3JvdXA6ICR7bG9nR3JvdXBOYW1lfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBhZGRMb2dSZXRlbnRpb25Qb2xpY3koRnVuY3Rpb25OYW1lOiBzdHJpbmcsIGNsb3Vkd2F0Y2g6IENsb3VkV2F0Y2hMb2dzKSB7XG4gICAgY29uc3QgbG9nR3JvdXBOYW1lID0gZ2V0TG9nR3JvdXBOYW1lKEZ1bmN0aW9uTmFtZSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBxdWlldGx5KFxuICAgICAgICBjbG91ZHdhdGNoLnB1dFJldGVudGlvblBvbGljeSh7IGxvZ0dyb3VwTmFtZSwgcmV0ZW50aW9uSW5EYXlzOiAxIH0pXG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsb2cuaW5mbyhgQWRkZWQgMSBkYXkgcmV0ZW50aW9uIHBvbGljeSB0byBsb2cgZ3JvdXAgJHtsb2dHcm91cE5hbWV9YCk7XG4gICAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xlYW51cChzdGF0ZTogQXdzU3RhdGUsIG9wdGlvbnM6IFJlcXVpcmVkPENsZWFudXBPcHRpb25zPikge1xuICAgIGxvZy5pbmZvKGBhd3MgY2xlYW51cCBzdGFydGluZy5gKTtcbiAgICBpZiAoc3RhdGUuZ2NQcm9taXNlKSB7XG4gICAgICAgIGxvZy5pbmZvKGBXYWl0aW5nIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24uLi5gKTtcbiAgICAgICAgYXdhaXQgc3RhdGUuZ2NQcm9taXNlO1xuICAgICAgICBsb2cuaW5mbyhgR2FyYmFnZSBjb2xsZWN0aW9uIGRvbmUuYCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZGVsZXRlUmVzb3VyY2VzKSB7XG4gICAgICAgIGxvZy5pbmZvKGBDbGVhbmluZyB1cCBpbmZyYXN0cnVjdHVyZSBmb3IgJHtzdGF0ZS5yZXNvdXJjZXMuRnVuY3Rpb25OYW1lfS4uLmApO1xuICAgICAgICBhd2FpdCBhZGRMb2dSZXRlbnRpb25Qb2xpY3koXG4gICAgICAgICAgICBzdGF0ZS5yZXNvdXJjZXMuRnVuY3Rpb25OYW1lLFxuICAgICAgICAgICAgc3RhdGUuc2VydmljZXMuY2xvdWR3YXRjaFxuICAgICAgICApO1xuICAgICAgICAvLyBEb24ndCBkZWxldGUgY2FjaGVkIHJvbGUuIEl0IG1heSBiZSBpbiB1c2UgYnkgb3RoZXIgaW5zdGFuY2VzIG9mXG4gICAgICAgIC8vIGZhYXN0LiBEb24ndCBkZWxldGUgbG9ncy4gVGhleSBhcmUgb2Z0ZW4gdXNlZnVsLiBCeSBkZWZhdWx0IGxvZ1xuICAgICAgICAvLyBzdHJlYW0gcmV0ZW50aW9uIHdpbGwgYmUgMSBkYXksIGFuZCBnYyB3aWxsIGNsZWFuIG91dCB0aGUgbG9nIGdyb3VwXG4gICAgICAgIC8vIGFmdGVyIHRoZSBzdHJlYW1zIGFyZSBleHBpcmVkLiBEb24ndCBkZWxldGUgYSBsYW1iZGEgbGF5ZXIgdGhhdCBpc1xuICAgICAgICAvLyB1c2VkIHRvIGNhY2hlIHBhY2thZ2VzLlxuICAgICAgICBjb25zdCB7IGxvZ0dyb3VwTmFtZSwgUm9sZU5hbWUsIGxheWVyLCAuLi5yZXN0IH0gPSBzdGF0ZS5yZXNvdXJjZXM7XG4gICAgICAgIGF3YWl0IGRlbGV0ZVJlc291cmNlcyhyZXN0LCBzdGF0ZS5zZXJ2aWNlcyk7XG4gICAgICAgIGlmICghc3RhdGUub3B0aW9ucy51c2VEZXBlbmRlbmN5Q2FjaGluZyB8fCBvcHRpb25zLmRlbGV0ZUNhY2hlcykge1xuICAgICAgICAgICAgYXdhaXQgZGVsZXRlUmVzb3VyY2VzKHsgbGF5ZXIgfSwgc3RhdGUuc2VydmljZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGxvZy5pbmZvKGBhd3MgY2xlYW51cCBkb25lLmApO1xufVxuXG5jb25zdCBsb2dHcm91cE5hbWVSZWdleHAgPSBuZXcgUmVnRXhwKGBeL2F3cy9sYW1iZGEvKGZhYXN0LSR7dXVpZHY0UGF0dGVybn0pJGApO1xuXG5mdW5jdGlvbiBmdW5jdGlvbk5hbWVGcm9tTG9nR3JvdXAobG9nR3JvdXBOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBtYXRjaCA9IGxvZ0dyb3VwTmFtZS5tYXRjaChsb2dHcm91cE5hbWVSZWdleHApO1xuICAgIHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXTtcbn1cblxubGV0IGxhc3RHYzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJMYXN0R2MoKSB7XG4gICAgbGFzdEdjID0gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBmb3JFYWNoUGFnZTxSPihcbiAgICBkZXNjcmlwdGlvbjogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IFJlcXVlc3Q8UiwgQVdTRXJyb3I+LFxuICAgIHByb2Nlc3M6IChwYWdlOiBSKSA9PiBQcm9taXNlPHZvaWQ+XG4pIHtcbiAgICBjb25zdCB0aHJvdHRsZVBhZ2luZyA9IHRocm90dGxlKHsgY29uY3VycmVuY3k6IDEsIHJhdGU6IDEgfSwgYXN5bmMgKCkgPT4ge30pO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHJlcXVlc3QuZWFjaFBhZ2UoKGVyciwgcGFnZSwgZG9uZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIGxvZy53YXJuKGBHQzogRXJyb3Igd2hlbiBsaXN0aW5nICR7ZGVzY3JpcHRpb259OiAke2Vycn1gKTtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFnZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcHJvY2VzcyhwYWdlKS50aGVuKCgpID0+IHRocm90dGxlUGFnaW5nKCkudGhlbihkb25lKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb2xsZWN0R2FyYmFnZShcbiAgICBleGVjdXRvcjogdHlwZW9mIGRlZmF1bHRHY1dvcmtlcixcbiAgICBzZXJ2aWNlczogQXdzU2VydmljZXMsXG4gICAgcmVnaW9uOiBBd3NSZWdpb24sXG4gICAgcmV0ZW50aW9uSW5EYXlzOiBudW1iZXIsXG4gICAgbW9kZTogXCJhdXRvXCIgfCBcImZvcmNlXCJcbik6IFByb21pc2U8XCJkb25lXCIgfCBcInNraXBwZWRcIj4ge1xuICAgIGlmIChleGVjdXRvciA9PT0gZGVmYXVsdEdjV29ya2VyKSB7XG4gICAgICAgIGlmIChtb2RlID09PSBcImF1dG9cIikge1xuICAgICAgICAgICAgaWYgKGxhc3RHYyAmJiBEYXRlLm5vdygpIDw9IGxhc3RHYyArIDM2MDAgKiAxMDAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwic2tpcHBlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZ2NFbnRyeSA9IGF3YWl0IGNhY2hlcy5hd3NHYy5nZXQoXCJnY1wiKTtcbiAgICAgICAgICAgIGlmIChnY0VudHJ5KSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFzdEdjUGVyc2lzdGVudCA9IEpTT04ucGFyc2UoZ2NFbnRyeS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEdjUGVyc2lzdGVudCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGxhc3RHY1BlcnNpc3RlbnQgPT09IFwibnVtYmVyXCIgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIERhdGUubm93KCkgPD0gbGFzdEdjUGVyc2lzdGVudCArIDM2MDAgKiAxMDAwXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEdjID0gbGFzdEdjUGVyc2lzdGVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInNraXBwZWRcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGxhc3RHYyA9IERhdGUubm93KCk7XG4gICAgICAgIGNhY2hlcy5hd3NHYy5zZXQoXCJnY1wiLCBsYXN0R2MudG9TdHJpbmcoKSk7XG4gICAgfVxuICAgIGNvbnN0IHByb21pc2VzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgICBmdW5jdGlvbiBzY2hlZHVsZVdvcmsod29yazogQXdzR2NXb3JrKSB7XG4gICAgICAgIGlmIChleGVjdXRvciA9PT0gZGVmYXVsdEdjV29ya2VyKSB7XG4gICAgICAgICAgICBsb2cuZ2MoYFNjaGVkdWxpbmcgd29yayBwdXNoaW5nIHByb21pc2U6ICVPYCwgd29yayk7XG4gICAgICAgIH1cbiAgICAgICAgcHJvbWlzZXMucHVzaChleGVjdXRvcih3b3JrLCBzZXJ2aWNlcykpO1xuICAgIH1cbiAgICBjb25zdCBmdW5jdGlvbnNXaXRoTG9nR3JvdXBzID0gbmV3IFNldCgpO1xuXG4gICAgY29uc3QgbG9nR3JvdXBSZXF1ZXN0ID0gc2VydmljZXMuY2xvdWR3YXRjaC5kZXNjcmliZUxvZ0dyb3Vwcyh7XG4gICAgICAgIGxvZ0dyb3VwTmFtZVByZWZpeDogXCIvYXdzL2xhbWJkYS9mYWFzdC1cIlxuICAgIH0pO1xuICAgIGNvbnN0IGFjY291bnRJZCA9IGF3YWl0IGdldEFjY291bnRJZChzZXJ2aWNlcy5zdHMpO1xuICAgIGF3YWl0IGZvckVhY2hQYWdlKFwibG9nIGdyb3Vwc1wiLCBsb2dHcm91cFJlcXVlc3QsIGFzeW5jICh7IGxvZ0dyb3VwcyA9IFtdIH0pID0+IHtcbiAgICAgICAgbG9nR3JvdXBzLmZvckVhY2goZyA9PiB7XG4gICAgICAgICAgICBjb25zdCBGdW5jdGlvbk5hbWUgPSBmdW5jdGlvbk5hbWVGcm9tTG9nR3JvdXAoZy5sb2dHcm91cE5hbWUhKTtcbiAgICAgICAgICAgIGZ1bmN0aW9uc1dpdGhMb2dHcm91cHMuYWRkKEZ1bmN0aW9uTmFtZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxvZy5nYyhgTG9nIGdyb3VwcyBzaXplOiAke2xvZ0dyb3Vwcy5sZW5ndGh9YCk7XG5cbiAgICAgICAgZ2FyYmFnZUNvbGxlY3RMb2dHcm91cHMoXG4gICAgICAgICAgICBsb2dHcm91cHMsXG4gICAgICAgICAgICByZXRlbnRpb25JbkRheXMsXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICBhY2NvdW50SWQsXG4gICAgICAgICAgICBzY2hlZHVsZVdvcmtcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGxpc3RGdW5jdGlvbnNSZXF1ZXN0ID0gc2VydmljZXMubGFtYmRhLmxpc3RGdW5jdGlvbnMoKTtcbiAgICBhd2FpdCBmb3JFYWNoUGFnZShcbiAgICAgICAgXCJsYW1iZGEgZnVuY3Rpb25zXCIsXG4gICAgICAgIGxpc3RGdW5jdGlvbnNSZXF1ZXN0LFxuICAgICAgICBhc3luYyAoeyBGdW5jdGlvbnMgPSBbXSB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmblBhdHRlcm4gPSBuZXcgUmVnRXhwKGBeZmFhc3QtJHt1dWlkdjRQYXR0ZXJufSRgKTtcbiAgICAgICAgICAgIGNvbnN0IGZ1bmNzID0gKEZ1bmN0aW9ucyB8fCBbXSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKGZuID0+IGZuLkZ1bmN0aW9uTmFtZSEubWF0Y2goZm5QYXR0ZXJuKSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKGZuID0+ICFmdW5jdGlvbnNXaXRoTG9nR3JvdXBzLmhhcyhmbi5GdW5jdGlvbk5hbWUpKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoZm4gPT4gaGFzRXhwaXJlZChmbi5MYXN0TW9kaWZpZWQsIHJldGVudGlvbkluRGF5cykpXG4gICAgICAgICAgICAgICAgLm1hcChmbiA9PiBmbi5GdW5jdGlvbk5hbWUhKTtcbiAgICAgICAgICAgIGRlbGV0ZUdhcmJhZ2VGdW5jdGlvbnMocmVnaW9uLCBhY2NvdW50SWQsIGZ1bmNzLCBzY2hlZHVsZVdvcmspO1xuICAgICAgICB9XG4gICAgKTtcblxuICAgIC8vIENvbGxlY3QgTGFtYmRhIExheWVyc1xuICAgIGNvbnN0IGxheWVyc1JlcXVlc3QgPSBzZXJ2aWNlcy5sYW1iZGEubGlzdExheWVycyh7XG4gICAgICAgIENvbXBhdGlibGVSdW50aW1lOiBcIm5vZGVqc1wiXG4gICAgfSk7XG4gICAgYXdhaXQgZm9yRWFjaFBhZ2UoXCJMYW1iZGEgTGF5ZXJzXCIsIGxheWVyc1JlcXVlc3QsIGFzeW5jICh7IExheWVycyA9IFtdIH0pID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBsYXllciBvZiBMYXllcnMpIHtcbiAgICAgICAgICAgIGlmIChsYXllci5MYXllck5hbWUhLm1hdGNoKC9eZmFhc3QtLykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsYXllclZlcnNpb25SZXF1ZXN0ID0gc2VydmljZXMubGFtYmRhLmxpc3RMYXllclZlcnNpb25zKHtcbiAgICAgICAgICAgICAgICAgICAgTGF5ZXJOYW1lOiBsYXllci5MYXllck5hbWUhLFxuICAgICAgICAgICAgICAgICAgICBDb21wYXRpYmxlUnVudGltZTogXCJub2RlanNcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGF3YWl0IGZvckVhY2hQYWdlKFxuICAgICAgICAgICAgICAgICAgICBcIkxhbWJkYSBMYXllciBWZXJzaW9uc1wiLFxuICAgICAgICAgICAgICAgICAgICBsYXllclZlcnNpb25SZXF1ZXN0LFxuICAgICAgICAgICAgICAgICAgICBhc3luYyAoeyBMYXllclZlcnNpb25zID0gW10gfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgTGF5ZXJWZXJzaW9ucy5mb3JFYWNoKGxheWVyVmVyc2lvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhc0V4cGlyZWQobGF5ZXJWZXJzaW9uLkNyZWF0ZWREYXRlLCByZXRlbnRpb25JbkRheXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjaGVkdWxlV29yayh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIkRlbGV0ZUxheWVyVmVyc2lvblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF5ZXJOYW1lOiBsYXllci5MYXllck5hbWUhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmVyc2lvbk51bWJlcjogbGF5ZXJWZXJzaW9uLlZlcnNpb24hXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGxvZy5nYyhgQXdhaXRpbmcgJHtwcm9taXNlcy5sZW5ndGh9IHNjaGVkdWxlZCB3b3JrIHByb21pc2VzYCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgIHJldHVybiBcImRvbmVcIjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFjY291bnRJZChzdHM6IFNUUykge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgc3RzLmdldENhbGxlcklkZW50aXR5KCkucHJvbWlzZSgpO1xuICAgIGNvbnN0IHsgQWNjb3VudCwgQXJuLCBVc2VySWQgfSA9IHJlc3BvbnNlO1xuICAgIGxvZy5pbmZvKGBBY2NvdW50IElEOiAlT2AsIHsgQWNjb3VudCwgQXJuLCBVc2VySWQgfSk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLkFjY291bnQhO1xufVxuXG5mdW5jdGlvbiBnYXJiYWdlQ29sbGVjdExvZ0dyb3VwcyhcbiAgICBsb2dHcm91cHM6IENsb3VkV2F0Y2hMb2dzLkxvZ0dyb3VwW10sXG4gICAgcmV0ZW50aW9uSW5EYXlzOiBudW1iZXIsXG4gICAgcmVnaW9uOiBBd3NSZWdpb24sXG4gICAgYWNjb3VudElkOiBzdHJpbmcsXG4gICAgc2NoZWR1bGVXb3JrOiAod29yazogQXdzR2NXb3JrKSA9PiB2b2lkXG4pIHtcbiAgICBjb25zdCBsb2dHcm91cHNNaXNzaW5nUmV0ZW50aW9uUG9saWN5ID0gbG9nR3JvdXBzLmZpbHRlcihcbiAgICAgICAgZyA9PiBnLnJldGVudGlvbkluRGF5cyA9PT0gdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGxvZy5nYyhgTG9nIGdyb3VwcyBtaXNzaW5nIHJldGVudGlvbjogJHtsb2dHcm91cHNNaXNzaW5nUmV0ZW50aW9uUG9saWN5Lmxlbmd0aH1gKTtcblxuICAgIGxvZ0dyb3Vwc01pc3NpbmdSZXRlbnRpb25Qb2xpY3kuZm9yRWFjaChnID0+IHtcbiAgICAgICAgc2NoZWR1bGVXb3JrKHtcbiAgICAgICAgICAgIHR5cGU6IFwiU2V0TG9nUmV0ZW50aW9uXCIsXG4gICAgICAgICAgICBsb2dHcm91cE5hbWU6IGcubG9nR3JvdXBOYW1lISxcbiAgICAgICAgICAgIHJldGVudGlvbkluRGF5c1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGdhcmJhZ2VGdW5jdGlvbnMgPSBsb2dHcm91cHNcbiAgICAgICAgLmZpbHRlcihnID0+IGhhc0V4cGlyZWQoZy5jcmVhdGlvblRpbWUsIHJldGVudGlvbkluRGF5cykpXG4gICAgICAgIC5tYXAoZyA9PiBmdW5jdGlvbk5hbWVGcm9tTG9nR3JvdXAoZy5sb2dHcm91cE5hbWUhKSlcbiAgICAgICAgLmZpbHRlcihkZWZpbmVkKTtcblxuICAgIGRlbGV0ZUdhcmJhZ2VGdW5jdGlvbnMocmVnaW9uLCBhY2NvdW50SWQsIGdhcmJhZ2VGdW5jdGlvbnMsIHNjaGVkdWxlV29yayk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZUdhcmJhZ2VGdW5jdGlvbnMoXG4gICAgcmVnaW9uOiBBd3NSZWdpb24sXG4gICAgYWNjb3VudElkOiBzdHJpbmcsXG4gICAgZ2FyYmFnZUZ1bmN0aW9uczogc3RyaW5nW10sXG4gICAgc2NoZWR1bGVXb3JrOiAod29yazogQXdzR2NXb3JrKSA9PiB2b2lkXG4pIHtcbiAgICBnYXJiYWdlRnVuY3Rpb25zLmZvckVhY2goRnVuY3Rpb25OYW1lID0+IHtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VzOiBBd3NSZXNvdXJjZXMgPSB7XG4gICAgICAgICAgICBGdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICBSb2xlTmFtZTogXCJcIixcbiAgICAgICAgICAgIFJlcXVlc3RUb3BpY0FybjogZ2V0U05TVG9waWNBcm4ocmVnaW9uLCBhY2NvdW50SWQsIEZ1bmN0aW9uTmFtZSksXG4gICAgICAgICAgICBSZXNwb25zZVF1ZXVlVXJsOiBnZXRSZXNwb25zZVF1ZXVlVXJsKHJlZ2lvbiwgYWNjb3VudElkLCBGdW5jdGlvbk5hbWUpLFxuICAgICAgICAgICAgbG9nR3JvdXBOYW1lOiBnZXRMb2dHcm91cE5hbWUoRnVuY3Rpb25OYW1lKSxcbiAgICAgICAgICAgIEJ1Y2tldDogRnVuY3Rpb25OYW1lXG4gICAgICAgIH07XG4gICAgICAgIHNjaGVkdWxlV29yayh7IHR5cGU6IFwiRGVsZXRlUmVzb3VyY2VzXCIsIHJlc291cmNlcyB9KTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF3c1BhY2tlcihcbiAgICBmdW5jdGlvbk1vZHVsZTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnMsXG4gICAgd3JhcHBlck9wdGlvbnM6IFdyYXBwZXJPcHRpb25zLFxuICAgIEZ1bmN0aW9uTmFtZTogc3RyaW5nXG4pOiBQcm9taXNlPFBhY2tlclJlc3VsdD4ge1xuICAgIHJldHVybiBwYWNrZXIoXG4gICAgICAgIGF3c1RyYW1wb2xpbmUsXG4gICAgICAgIGZ1bmN0aW9uTW9kdWxlLFxuICAgICAgICB7XG4gICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgd2VicGFja09wdGlvbnM6IG1lcmdlKG9wdGlvbnMud2VicGFja09wdGlvbnMgPz8ge30sIHtcbiAgICAgICAgICAgICAgICBleHRlcm5hbHM6IFtuZXcgUmVnRXhwKFwiXmF3cy1zZGsvP1wiKV1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0sXG4gICAgICAgIHdyYXBwZXJPcHRpb25zLFxuICAgICAgICBGdW5jdGlvbk5hbWVcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXRTTlNUb3BpY05hbWUoRnVuY3Rpb25OYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYCR7RnVuY3Rpb25OYW1lfS1SZXF1ZXN0c2A7XG59XG5cbmZ1bmN0aW9uIGdldFNOU1RvcGljQXJuKHJlZ2lvbjogQXdzUmVnaW9uLCBhY2NvdW50SWQ6IHN0cmluZywgRnVuY3Rpb25OYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBUb3BpY05hbWUgPSBnZXRTTlNUb3BpY05hbWUoRnVuY3Rpb25OYW1lKTtcbiAgICByZXR1cm4gYGFybjphd3M6c25zOiR7cmVnaW9ufToke2FjY291bnRJZH06JHtUb3BpY05hbWV9YDtcbn1cblxuZnVuY3Rpb24gZ2V0U1FTTmFtZShGdW5jdGlvbk5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBgJHtGdW5jdGlvbk5hbWV9LVJlc3BvbnNlc2A7XG59XG5cbmZ1bmN0aW9uIGdldFJlc3BvbnNlUXVldWVVcmwocmVnaW9uOiBBd3NSZWdpb24sIGFjY291bnRJZDogc3RyaW5nLCBGdW5jdGlvbk5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IHF1ZXVlTmFtZSA9IGdldFNRU05hbWUoRnVuY3Rpb25OYW1lKTtcbiAgICByZXR1cm4gYGh0dHBzOi8vc3FzLiR7cmVnaW9ufS5hbWF6b25hd3MuY29tLyR7YWNjb3VudElkfS8ke3F1ZXVlTmFtZX1gO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVSZXF1ZXN0UXVldWVJbXBsKFxuICAgIHN0YXRlOiBBd3NTdGF0ZSxcbiAgICBGdW5jdGlvbk5hbWU6IHN0cmluZyxcbiAgICBGdW5jdGlvbkFybjogc3RyaW5nXG4pIHtcbiAgICBjb25zdCB7IHNucywgbGFtYmRhIH0gPSBzdGF0ZS5zZXJ2aWNlcztcbiAgICBjb25zdCB7IHJlc291cmNlcyB9ID0gc3RhdGU7XG5cbiAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgU05TIHJlcXVlc3QgdG9waWNgKTtcbiAgICBjb25zdCBjcmVhdGVUb3BpY1Byb21pc2UgPSBjcmVhdGVTTlNUb3BpYyhzbnMsIGdldFNOU1RvcGljTmFtZShGdW5jdGlvbk5hbWUpKTtcblxuICAgIGNvbnN0IGFzc2lnblJlcXVlc3RUb3BpY0FyblByb21pc2UgPSBjcmVhdGVUb3BpY1Byb21pc2UudGhlbihcbiAgICAgICAgdG9waWMgPT4gKHJlc291cmNlcy5SZXF1ZXN0VG9waWNBcm4gPSB0b3BpYylcbiAgICApO1xuXG4gICAgY29uc3QgYWRkUGVybWlzc2lvbnNQcm9taXNlID0gY3JlYXRlVG9waWNQcm9taXNlLnRoZW4odG9waWMgPT4ge1xuICAgICAgICBsb2cuaW5mbyhgQWRkaW5nIFNOUyBpbnZva2UgcGVybWlzc2lvbnMgdG8gZnVuY3Rpb25gKTtcbiAgICAgICAgcmV0dXJuIGFkZFNuc0ludm9rZVBlcm1pc3Npb25zVG9GdW5jdGlvbihGdW5jdGlvbk5hbWUsIHRvcGljLCBsYW1iZGEpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgc3Vic2NyaWJlUHJvbWlzZSA9IGNyZWF0ZVRvcGljUHJvbWlzZS50aGVuKHRvcGljID0+IHtcbiAgICAgICAgbG9nLmluZm8oYFN1YnNjcmliaW5nIFNOUyB0byBpbnZva2UgbGFtYmRhIGZ1bmN0aW9uYCk7XG4gICAgICAgIHJldHVybiBzbnNcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgICAgICAgIFRvcGljQXJuOiB0b3BpYyxcbiAgICAgICAgICAgICAgICBQcm90b2NvbDogXCJsYW1iZGFcIixcbiAgICAgICAgICAgICAgICBFbmRwb2ludDogRnVuY3Rpb25Bcm5cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucHJvbWlzZSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgYXNzaWduU05TUmVzcG9uc2VQcm9taXNlID0gc3Vic2NyaWJlUHJvbWlzZS50aGVuKFxuICAgICAgICBzbnNSZXNwb25zZSA9PiAocmVzb3VyY2VzLlNOU0xhbWJkYVN1YnNjcmlwdGlvbkFybiA9IHNuc1Jlc3BvbnNlLlN1YnNjcmlwdGlvbkFybiEpXG4gICAgKTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChbXG4gICAgICAgIGNyZWF0ZVRvcGljUHJvbWlzZSxcbiAgICAgICAgYXNzaWduUmVxdWVzdFRvcGljQXJuUHJvbWlzZSxcbiAgICAgICAgYWRkUGVybWlzc2lvbnNQcm9taXNlLFxuICAgICAgICBzdWJzY3JpYmVQcm9taXNlLFxuICAgICAgICBhc3NpZ25TTlNSZXNwb25zZVByb21pc2VcbiAgICBdKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVJlc3BvbnNlUXVldWVJbXBsKHN0YXRlOiBBd3NTdGF0ZSwgRnVuY3Rpb25OYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCB7IHNxcyB9ID0gc3RhdGUuc2VydmljZXM7XG4gICAgY29uc3QgeyByZXNvdXJjZXMgfSA9IHN0YXRlO1xuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBTUVMgcmVzcG9uc2UgcXVldWVgKTtcbiAgICBjb25zdCB7IFF1ZXVlVXJsLCBRdWV1ZUFybiB9ID0gYXdhaXQgY3JlYXRlU1FTUXVldWUoXG4gICAgICAgIGdldFNRU05hbWUoRnVuY3Rpb25OYW1lKSxcbiAgICAgICAgNjAsXG4gICAgICAgIHNxc1xuICAgICk7XG4gICAgcmVzb3VyY2VzLlJlc3BvbnNlUXVldWVVcmwgPSBRdWV1ZVVybDtcbiAgICByZXNvdXJjZXMuUmVzcG9uc2VRdWV1ZUFybiA9IFF1ZXVlQXJuO1xuICAgIGxvZy5pbmZvKGBDcmVhdGVkIHJlc3BvbnNlIHF1ZXVlYCk7XG4gICAgcmV0dXJuIFF1ZXVlQXJuITtcbn1cblxuZnVuY3Rpb24gYWRkU25zSW52b2tlUGVybWlzc2lvbnNUb0Z1bmN0aW9uKFxuICAgIEZ1bmN0aW9uTmFtZTogc3RyaW5nLFxuICAgIFJlcXVlc3RUb3BpY0Fybjogc3RyaW5nLFxuICAgIGxhbWJkYTogTGFtYmRhXG4pIHtcbiAgICByZXR1cm4gbGFtYmRhXG4gICAgICAgIC5hZGRQZXJtaXNzaW9uKHtcbiAgICAgICAgICAgIEZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgIEFjdGlvbjogXCJsYW1iZGE6SW52b2tlRnVuY3Rpb25cIixcbiAgICAgICAgICAgIFByaW5jaXBhbDogXCJzbnMuYW1hem9uYXdzLmNvbVwiLFxuICAgICAgICAgICAgU3RhdGVtZW50SWQ6IGAke0Z1bmN0aW9uTmFtZX0tSW52b2tlYCxcbiAgICAgICAgICAgIFNvdXJjZUFybjogUmVxdWVzdFRvcGljQXJuXG4gICAgICAgIH0pXG4gICAgICAgIC5wcm9taXNlKClcbiAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyLm1hdGNoKC9hbHJlYWR5IGV4aXN0cy8pKSB7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG59XG5cbi8qKlxuICogVmFsaWQgQVdTXG4gKiB7QGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0VDMi9sYXRlc3QvVXNlckd1aWRlL3VzaW5nLXJlZ2lvbnMtYXZhaWxhYmlsaXR5LXpvbmVzLmh0bWwgfCByZWdpb25zfS5cbiAqIE5vdCBhbGwgb2YgdGhlc2UgcmVnaW9ucyBoYXZlIExhbWJkYSBzdXBwb3J0LlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgdHlwZSBBd3NSZWdpb24gPVxuICAgIHwgXCJ1cy1lYXN0LTFcIlxuICAgIHwgXCJ1cy1lYXN0LTJcIlxuICAgIHwgXCJ1cy13ZXN0LTFcIlxuICAgIHwgXCJ1cy13ZXN0LTJcIlxuICAgIHwgXCJjYS1jZW50cmFsLTFcIlxuICAgIHwgXCJldS1jZW50cmFsLTFcIlxuICAgIHwgXCJldS13ZXN0LTFcIlxuICAgIHwgXCJldS13ZXN0LTJcIlxuICAgIHwgXCJldS13ZXN0LTNcIlxuICAgIHwgXCJhcC1ub3J0aGVhc3QtMVwiXG4gICAgfCBcImFwLW5vcnRoZWFzdC0yXCJcbiAgICB8IFwiYXAtbm9ydGhlYXN0LTNcIlxuICAgIHwgXCJhcC1zb3V0aGVhc3QtMVwiXG4gICAgfCBcImFwLXNvdXRoZWFzdC0yXCJcbiAgICB8IFwiYXAtc291dGgtMVwiXG4gICAgfCBcInNhLWVhc3QtMVwiO1xuXG5jb25zdCBsb2NhdGlvbnMgPSB7XG4gICAgXCJ1cy1lYXN0LTFcIjogXCJVUyBFYXN0IChOLiBWaXJnaW5pYSlcIixcbiAgICBcInVzLWVhc3QtMlwiOiBcIlVTIEVhc3QgKE9oaW8pXCIsXG4gICAgXCJ1cy13ZXN0LTFcIjogXCJVUyBXZXN0IChOLiBDYWxpZm9ybmlhKVwiLFxuICAgIFwidXMtd2VzdC0yXCI6IFwiVVMgV2VzdCAoT3JlZ29uKVwiLFxuICAgIFwiY2EtY2VudHJhbC0xXCI6IFwiQ2FuYWRhIChDZW50cmFsKVwiLFxuICAgIFwiZXUtY2VudHJhbC0xXCI6IFwiRVUgKEZyYW5rZnVydClcIixcbiAgICBcImV1LXdlc3QtMVwiOiBcIkVVIChJcmVsYW5kKVwiLFxuICAgIFwiZXUtd2VzdC0yXCI6IFwiRVUgKExvbmRvbilcIixcbiAgICBcImV1LXdlc3QtM1wiOiBcIkVVIChQYXJpcylcIixcbiAgICBcImFwLW5vcnRoZWFzdC0xXCI6IFwiQXNpYSBQYWNpZmljIChUb2t5bylcIixcbiAgICBcImFwLW5vcnRoZWFzdC0yXCI6IFwiQXNpYSBQYWNpZmljIChTZW91bClcIixcbiAgICBcImFwLW5vcnRoZWFzdC0zXCI6IFwiQXNpYSBQYWNpZmljIChPc2FrYS1Mb2NhbClcIixcbiAgICBcImFwLXNvdXRoZWFzdC0xXCI6IFwiQXNpYSBQYWNpZmljIChTaW5nYXBvcmUpXCIsXG4gICAgXCJhcC1zb3V0aGVhc3QtMlwiOiBcIkFzaWEgUGFjaWZpYyAoU3lkbmV5KVwiLFxuICAgIFwiYXAtc291dGgtMVwiOiBcIkFzaWEgUGFjaWZpYyAoTXVtYmFpKVwiLFxuICAgIFwic2EtZWFzdC0xXCI6IFwiU291dGggQW1lcmljYSAoU8OjbyBQYXVsbylcIlxufTtcblxuZXhwb3J0IGNvbnN0IGF3c1ByaWNlID0gdGhyb3R0bGUoXG4gICAgeyBjb25jdXJyZW5jeTogNiwgcmF0ZTogNSwgbWVtb2l6ZTogdHJ1ZSwgY2FjaGU6IGNhY2hlcy5hd3NQcmljZXMgfSxcbiAgICBhc3luYyAocHJpY2luZzogUHJpY2luZywgU2VydmljZUNvZGU6IHN0cmluZywgZmlsdGVyOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBmaXJzdChvYmo6IGFueSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmpbT2JqZWN0LmtleXMob2JqKVswXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBleHRyYWN0UHJpY2Uob2JqOiBhbnkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwcmljZXMgPSBPYmplY3Qua2V5cyhvYmoucHJpY2VEaW1lbnNpb25zKS5tYXAoa2V5ID0+XG4gICAgICAgICAgICAgICAgICAgIE51bWJlcihvYmoucHJpY2VEaW1lbnNpb25zW2tleV0ucHJpY2VQZXJVbml0LlVTRClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCguLi5wcmljZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcHJpY2VSZXN1bHQgPSBhd2FpdCBwcmljaW5nXG4gICAgICAgICAgICAgICAgLmdldFByb2R1Y3RzKHtcbiAgICAgICAgICAgICAgICAgICAgU2VydmljZUNvZGUsXG4gICAgICAgICAgICAgICAgICAgIEZpbHRlcnM6IE9iamVjdC5rZXlzKGZpbHRlcikubWFwKGtleSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgRmllbGQ6IGtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFR5cGU6IFwiVEVSTV9NQVRDSFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgVmFsdWU6IGZpbHRlcltrZXldXG4gICAgICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnByb21pc2UoKTtcbiAgICAgICAgICAgIGlmIChwcmljZVJlc3VsdC5QcmljZUxpc3QhLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgICAgICAgYFByaWNlIHF1ZXJ5IHJldHVybmVkIG1vcmUgdGhhbiBvbmUgcHJvZHVjdCAnJHtTZXJ2aWNlQ29kZX0nICgkTylgLFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHByaWNlUmVzdWx0LlByaWNlTGlzdCEuZm9yRWFjaChwID0+IGxvZy53YXJuKGAlT2AsIHApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBMaXN0OiBhbnkgPSBwcmljZVJlc3VsdC5QcmljZUxpc3QhWzBdO1xuICAgICAgICAgICAgY29uc3QgcHJpY2UgPSBleHRyYWN0UHJpY2UoZmlyc3QocExpc3QudGVybXMuT25EZW1hbmQpKTtcbiAgICAgICAgICAgIHJldHVybiBwcmljZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgbWVzc2FnZTogbSB9ID0gZXJyO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgIW0ubWF0Y2goL1JhdGUgZXhjZWVkZWQvKSAmJlxuICAgICAgICAgICAgICAgICAgICAhbS5tYXRjaCgvRVBST1RPLykgJiZcbiAgICAgICAgICAgICAgICAgICAgIW0ubWF0Y2goL3NvY2tldCBoYW5nIHVwLylcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4oXG4gICAgICAgICAgICAgICAgICAgICAgICBgQ291bGQgbm90IGdldCBBV1MgcHJpY2luZyBmb3IgJyR7U2VydmljZUNvZGV9JyAoJU8pYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlclxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBsb2cud2FybihlcnIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICBgZmFpbGVkIHRvIGdldCBBV1MgcHJpY2luZyBmb3IgXCIke1NlcnZpY2VDb2RlfVwiYFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4pO1xuXG5leHBvcnQgY29uc3QgcmVxdWVzdEF3c1ByaWNlcyA9IGFzeW5jIChcbiAgICBwcmljaW5nOiBQcmljaW5nLFxuICAgIHJlZ2lvbjogQXdzUmVnaW9uXG4pOiBQcm9taXNlPEF3c1ByaWNlcz4gPT4ge1xuICAgIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25zW3JlZ2lvbl07XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGFtYmRhUGVyUmVxdWVzdDogYXdhaXQgYXdzUHJpY2UocHJpY2luZywgXCJBV1NMYW1iZGFcIiwge1xuICAgICAgICAgICAgbG9jYXRpb24sXG4gICAgICAgICAgICBncm91cDogXCJBV1MtTGFtYmRhLVJlcXVlc3RzXCJcbiAgICAgICAgfSkuY2F0Y2goXyA9PiAwLjAwMDAwMDIpLFxuICAgICAgICBsYW1iZGFQZXJHYlNlY29uZDogYXdhaXQgYXdzUHJpY2UocHJpY2luZywgXCJBV1NMYW1iZGFcIiwge1xuICAgICAgICAgICAgbG9jYXRpb24sXG4gICAgICAgICAgICBncm91cDogXCJBV1MtTGFtYmRhLUR1cmF0aW9uXCJcbiAgICAgICAgfSkuY2F0Y2goXyA9PiAwLjAwMDAxNjY3KSxcbiAgICAgICAgc25zUGVyNjRrUHVibGlzaDogYXdhaXQgYXdzUHJpY2UocHJpY2luZywgXCJBbWF6b25TTlNcIiwge1xuICAgICAgICAgICAgbG9jYXRpb24sXG4gICAgICAgICAgICBncm91cDogXCJTTlMtUmVxdWVzdHMtVGllcjFcIlxuICAgICAgICB9KS5jYXRjaChfID0+IDAuNSAvIDFlNiksXG4gICAgICAgIHNxc1BlcjY0a1JlcXVlc3Q6IGF3YWl0IGF3c1ByaWNlKHByaWNpbmcsIFwiQVdTUXVldWVTZXJ2aWNlXCIsIHtcbiAgICAgICAgICAgIGxvY2F0aW9uLFxuICAgICAgICAgICAgZ3JvdXA6IFwiU1FTLUFQSVJlcXVlc3QtVGllcjFcIixcbiAgICAgICAgICAgIHF1ZXVlVHlwZTogXCJTdGFuZGFyZFwiXG4gICAgICAgIH0pLmNhdGNoKF8gPT4gMC40IC8gMWU2KSxcbiAgICAgICAgZGF0YU91dFBlckdiOiBhd2FpdCBhd3NQcmljZShwcmljaW5nLCBcIkFXU0RhdGFUcmFuc2ZlclwiLCB7XG4gICAgICAgICAgICBmcm9tTG9jYXRpb246IGxvY2F0aW9uLFxuICAgICAgICAgICAgdHJhbnNmZXJUeXBlOiBcIkFXUyBPdXRib3VuZFwiXG4gICAgICAgIH0pLmNhdGNoKF8gPT4gMC4wOSksXG4gICAgICAgIGxvZ3NJbmdlc3RlZFBlckdiOiBhd2FpdCBhd3NQcmljZShwcmljaW5nLCBcIkFtYXpvbkNsb3VkV2F0Y2hcIiwge1xuICAgICAgICAgICAgbG9jYXRpb24sXG4gICAgICAgICAgICBncm91cDogXCJJbmdlc3RlZCBMb2dzXCIsXG4gICAgICAgICAgICBncm91cERlc2NyaXB0aW9uOiBcIkV4aXN0aW5nIHN5c3RlbSwgYXBwbGljYXRpb24sIGFuZCBjdXN0b20gbG9nIGZpbGVzXCJcbiAgICAgICAgfSkuY2F0Y2goXyA9PiAwLjUpXG4gICAgfTtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3N0U25hcHNob3QoXG4gICAgc3RhdGU6IEF3c1N0YXRlLFxuICAgIHN0YXRzOiBGdW5jdGlvblN0YXRzXG4pOiBQcm9taXNlPENvc3RTbmFwc2hvdD4ge1xuICAgIGNvbnN0IHsgcmVnaW9uIH0gPSBzdGF0ZS5yZXNvdXJjZXM7XG4gICAgY29uc3QgcHJpY2VzID0gYXdhaXQgcmVxdWVzdEF3c1ByaWNlcyhzdGF0ZS5zZXJ2aWNlcy5wcmljaW5nLCByZWdpb24pO1xuICAgIGNvbnN0IGNvc3RNZXRyaWNzOiBDb3N0TWV0cmljW10gPSBbXTtcbiAgICBjb25zdCB7IG1lbW9yeVNpemUgPSBkZWZhdWx0cy5tZW1vcnlTaXplIH0gPSBzdGF0ZS5vcHRpb25zO1xuICAgIGNvbnN0IGJpbGxlZFRpbWVTdGF0cyA9IHN0YXRzLmVzdGltYXRlZEJpbGxlZFRpbWU7XG4gICAgY29uc3Qgc2Vjb25kcyA9IChiaWxsZWRUaW1lU3RhdHMubWVhbiAvIDEwMDApICogYmlsbGVkVGltZVN0YXRzLnNhbXBsZXMgfHwgMDtcbiAgICBjb25zdCBwcm92aXNpb25lZEdiID0gbWVtb3J5U2l6ZSAvIDEwMjQ7XG4gICAgY29uc3QgZnVuY3Rpb25DYWxsRHVyYXRpb24gPSBuZXcgQ29zdE1ldHJpYyh7XG4gICAgICAgIG5hbWU6IFwiZnVuY3Rpb25DYWxsRHVyYXRpb25cIixcbiAgICAgICAgcHJpY2luZzogcHJpY2VzLmxhbWJkYVBlckdiU2Vjb25kICogcHJvdmlzaW9uZWRHYixcbiAgICAgICAgdW5pdDogXCJzZWNvbmRcIixcbiAgICAgICAgbWVhc3VyZWQ6IHNlY29uZHMsXG4gICAgICAgIGNvbW1lbnQ6IGBodHRwczovL2F3cy5hbWF6b24uY29tL2xhbWJkYS9wcmljaW5nIChyYXRlID0gJHtwcmljZXMubGFtYmRhUGVyR2JTZWNvbmQudG9GaXhlZChcbiAgICAgICAgICAgIDhcbiAgICAgICAgKX0vKEdCKnNlY29uZCkgKiAke3Byb3Zpc2lvbmVkR2J9IEdCID0gJHsoXG4gICAgICAgICAgICBwcmljZXMubGFtYmRhUGVyR2JTZWNvbmQgKiBwcm92aXNpb25lZEdiXG4gICAgICAgICkudG9GaXhlZCg4KX0vc2Vjb25kKWBcbiAgICB9KTtcbiAgICBjb3N0TWV0cmljcy5wdXNoKGZ1bmN0aW9uQ2FsbER1cmF0aW9uKTtcblxuICAgIGNvbnN0IGZ1bmN0aW9uQ2FsbFJlcXVlc3RzID0gbmV3IENvc3RNZXRyaWMoe1xuICAgICAgICBuYW1lOiBcImZ1bmN0aW9uQ2FsbFJlcXVlc3RzXCIsXG4gICAgICAgIHByaWNpbmc6IHByaWNlcy5sYW1iZGFQZXJSZXF1ZXN0LFxuICAgICAgICBtZWFzdXJlZDogc3RhdHMuaW52b2NhdGlvbnMsXG4gICAgICAgIHVuaXQ6IFwicmVxdWVzdFwiLFxuICAgICAgICBjb21tZW50OiBcImh0dHBzOi8vYXdzLmFtYXpvbi5jb20vbGFtYmRhL3ByaWNpbmdcIlxuICAgIH0pO1xuICAgIGNvc3RNZXRyaWNzLnB1c2goZnVuY3Rpb25DYWxsUmVxdWVzdHMpO1xuXG4gICAgY29uc3QgeyBtZXRyaWNzIH0gPSBzdGF0ZTtcbiAgICBjb25zdCBvdXRib3VuZERhdGFUcmFuc2ZlciA9IG5ldyBDb3N0TWV0cmljKHtcbiAgICAgICAgbmFtZTogXCJvdXRib3VuZERhdGFUcmFuc2ZlclwiLFxuICAgICAgICBwcmljaW5nOiBwcmljZXMuZGF0YU91dFBlckdiLFxuICAgICAgICBtZWFzdXJlZDogbWV0cmljcy5vdXRib3VuZEJ5dGVzIC8gMiAqKiAzMCxcbiAgICAgICAgdW5pdDogXCJHQlwiLFxuICAgICAgICBjb21tZW50OiBcImh0dHBzOi8vYXdzLmFtYXpvbi5jb20vZWMyL3ByaWNpbmcvb24tZGVtYW5kLyNEYXRhX1RyYW5zZmVyXCJcbiAgICB9KTtcbiAgICBjb3N0TWV0cmljcy5wdXNoKG91dGJvdW5kRGF0YVRyYW5zZmVyKTtcblxuICAgIGNvbnN0IHNxczogQ29zdE1ldHJpYyA9IG5ldyBDb3N0TWV0cmljKHtcbiAgICAgICAgbmFtZTogXCJzcXNcIixcbiAgICAgICAgcHJpY2luZzogcHJpY2VzLnNxc1BlcjY0a1JlcXVlc3QsXG4gICAgICAgIG1lYXN1cmVkOiBtZXRyaWNzLnNxczY0a1JlcXVlc3RzLFxuICAgICAgICB1bml0OiBcInJlcXVlc3RcIixcbiAgICAgICAgY29tbWVudDogXCJodHRwczovL2F3cy5hbWF6b24uY29tL3Nxcy9wcmljaW5nXCJcbiAgICB9KTtcbiAgICBjb3N0TWV0cmljcy5wdXNoKHNxcyk7XG5cbiAgICBjb25zdCBzbnM6IENvc3RNZXRyaWMgPSBuZXcgQ29zdE1ldHJpYyh7XG4gICAgICAgIG5hbWU6IFwic25zXCIsXG4gICAgICAgIHByaWNpbmc6IHByaWNlcy5zbnNQZXI2NGtQdWJsaXNoLFxuICAgICAgICBtZWFzdXJlZDogbWV0cmljcy5zbnM2NGtSZXF1ZXN0cyxcbiAgICAgICAgdW5pdDogXCJyZXF1ZXN0XCIsXG4gICAgICAgIGNvbW1lbnQ6IFwiaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9zbnMvcHJpY2luZ1wiXG4gICAgfSk7XG4gICAgY29zdE1ldHJpY3MucHVzaChzbnMpO1xuXG4gICAgY29uc3QgbG9nSW5nZXN0aW9uOiBDb3N0TWV0cmljID0gbmV3IENvc3RNZXRyaWMoe1xuICAgICAgICBuYW1lOiBcImxvZ0luZ2VzdGlvblwiLFxuICAgICAgICBwcmljaW5nOiBwcmljZXMubG9nc0luZ2VzdGVkUGVyR2IsXG4gICAgICAgIG1lYXN1cmVkOiAwLFxuICAgICAgICB1bml0OiBcIkdCXCIsXG4gICAgICAgIGNvbW1lbnQ6XG4gICAgICAgICAgICBcImh0dHBzOi8vYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9wcmljaW5nLyAtIExvZyBpbmdlc3Rpb24gY29zdHMgbm90IGN1cnJlbnRseSBpbmNsdWRlZC5cIixcbiAgICAgICAgaW5mb3JtYXRpb25hbE9ubHk6IHRydWVcbiAgICB9KTtcbiAgICBjb3N0TWV0cmljcy5wdXNoKGxvZ0luZ2VzdGlvbik7XG5cbiAgICByZXR1cm4gbmV3IENvc3RTbmFwc2hvdChcImF3c1wiLCBzdGF0ZS5vcHRpb25zLCBzdGF0cywgY29zdE1ldHJpY3MpO1xufVxuXG5leHBvcnQgY29uc3QgQXdzSW1wbDogUHJvdmlkZXJJbXBsPEF3c09wdGlvbnMsIEF3c1N0YXRlPiA9IHtcbiAgICBuYW1lOiBcImF3c1wiLFxuICAgIGluaXRpYWxpemUsXG4gICAgZGVmYXVsdHMsXG4gICAgY2xlYW51cCxcbiAgICBjb3N0U25hcHNob3QsXG4gICAgbG9nVXJsLFxuICAgIGludm9rZSxcbiAgICBwb2xsLFxuICAgIHJlc3BvbnNlUXVldWVJZFxufTtcbiJdfQ== |
\ | No newline at end of file |