aws-cdk
Version:
AWS CDK Toolkit CLI, the command line tool for CDK apps
1,691 lines • 301 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CdkToolkit = exports.AssetBuildTime = void 0;
exports.displayFlagsMessage = displayFlagsMessage;
const node_crypto_1 = require("node:crypto");
const path = __importStar(require("node:path"));
const node_util_1 = require("node:util");
const cxapi = __importStar(require("@aws-cdk/cloud-assembly-api"));
const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema");
const toolkit_lib_1 = require("@aws-cdk/toolkit-lib");
const chalk_1 = __importDefault(require("chalk"));
const chokidar = __importStar(require("chokidar"));
const handler_js_1 = require("chokidar/handler.js");
const fs = __importStar(require("fs-extra"));
const io_host_1 = require("./io-host");
const user_configuration_1 = require("./user-configuration");
const api_private_1 = require("../../lib/api-private");
const api_1 = require("../api");
const bootstrap_1 = require("../api/bootstrap");
const cloud_assembly_1 = require("../api/cloud-assembly");
const deploy_private_1 = require("../api/deploy-private");
const refactor_1 = require("../api/refactor");
const deploy_1 = require("../commands/deploy");
const list_stacks_1 = require("../commands/list-stacks");
const migrate_1 = require("../commands/migrate");
const cxapp_1 = require("../cxapp");
const util_1 = require("../util");
const collect_telemetry_1 = require("./telemetry/collect-telemetry");
const error_1 = require("./telemetry/error");
const messages_1 = require("./telemetry/messages");
const operations_1 = require("../commands/flags/operations");
// Must use a require() otherwise esbuild complains about calling a namespace
// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/consistent-type-imports
const pLimit = require('p-limit');
/**
* File events that we care about from chokidar.
* In chokidar v4, EventName includes additional events like 'error', 'raw', 'ready', 'all'
* that we need to filter out in the 'all' handler.
*/
const FILE_EVENTS = [handler_js_1.EVENTS.ADD, handler_js_1.EVENTS.ADD_DIR, handler_js_1.EVENTS.CHANGE, handler_js_1.EVENTS.UNLINK, handler_js_1.EVENTS.UNLINK_DIR];
/**
* Type guard to check if an event is a file event we should process.
*/
function isFileEvent(event) {
return FILE_EVENTS.includes(event);
}
/**
* When to build assets
*/
var AssetBuildTime;
(function (AssetBuildTime) {
/**
* Build all assets before deploying the first stack
*
* This is intended for expensive Docker image builds; so that if the Docker image build
* fails, no stacks are unnecessarily deployed (with the attendant wait time).
*/
AssetBuildTime["ALL_BEFORE_DEPLOY"] = "all-before-deploy";
/**
* Build assets just-in-time, before publishing
*/
AssetBuildTime["JUST_IN_TIME"] = "just-in-time";
})(AssetBuildTime || (exports.AssetBuildTime = AssetBuildTime = {}));
/**
* Custom implementation of the public Toolkit to integrate with the legacy CdkToolkit
*
* This overwrites how an sdkProvider is acquired
* in favor of the one provided directly to CdkToolkit.
*/
class InternalToolkit extends toolkit_lib_1.Toolkit {
_sdkProvider;
constructor(sdkProvider, options) {
super(options);
this._sdkProvider = sdkProvider;
}
/**
* Access to the AWS SDK
* @internal
*/
async sdkProvider(_action) {
return this._sdkProvider;
}
}
/**
* Toolkit logic
*
* The toolkit runs the `cloudExecutable` to obtain a cloud assembly and
* deploys applies them to `cloudFormation`.
*/
class CdkToolkit {
props;
ioHost;
toolkitStackName;
toolkit;
constructor(props) {
this.props = props;
this.ioHost = props.ioHost ?? io_host_1.CliIoHost.instance();
this.toolkitStackName = props.toolkitStackName ?? api_1.DEFAULT_TOOLKIT_STACK_NAME;
// We don't have the toolkit check unstable features. Instead, the error
// messages the CLI give are slightly different, and so they need to be checked
// separately. Instead, the Toolkit we use has all unstable features automatically
// enabled.
const iPromiseUnstablenessIsCheckedByTheCli = {
'publish-assets': true,
'diagnose': true,
'flags': true,
'orphan': true,
'refactor': true,
'validate': true,
};
this.toolkit = new InternalToolkit(props.sdkProvider, {
assemblyFailureAt: this.validateMetadataFailAt(),
color: true,
emojis: true,
ioHost: this.ioHost,
toolkitStackName: this.toolkitStackName,
unstableFeatures: Object.keys(iPromiseUnstablenessIsCheckedByTheCli),
});
}
async metadata(stackName, json) {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const _formatter = __addDisposableResource(env_1, this.ioHost.once(api_private_1.IO.CDK_TOOLKIT_I2901, (msg) => ({
action: 'metadata',
message: (0, util_1.serializeStructure)(msg.data.stacks[0]?.metadata ?? {}, json),
})), false);
await this.toolkit.list(this.props.cloudExecutable, {
stacks: {
patterns: [stackName],
strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE,
expand: cloud_assembly_1.ExpandStackSelection.NONE,
},
});
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
async acknowledge(noticeId) {
const issueNumber = Number(noticeId);
if (!Number.isInteger(issueNumber)) {
throw new toolkit_lib_1.ToolkitError('InvalidAcknowledgementId', `Invalid notice ID '${noticeId}': 'cdk acknowledge' only accepts numeric notice IDs (e.g. 'cdk acknowledge 12345'). ` +
'Scoped construct warnings such as \'@aws-cdk/aws-ecs:minHealthyPercent\' are acknowledged in code with ' +
'Annotations.of(scope).acknowledgeWarning(\'<id>\').');
}
const acks = new Set(this.props.configuration.context.get('acknowledged-issue-numbers') ?? []);
acks.add(issueNumber);
this.props.configuration.context.set('acknowledged-issue-numbers', Array.from(acks));
await this.props.configuration.saveContext();
}
async cliTelemetryStatus(args) {
const canCollect = (0, collect_telemetry_1.canCollectTelemetry)(args, this.props.configuration.context);
if (canCollect) {
await this.ioHost.asIoHelper().defaults.info('CLI Telemetry is enabled. See https://docs.aws.amazon.com/cdk/v2/guide/cli-telemetry.html for ways to disable.');
}
else {
await this.ioHost.asIoHelper().defaults.info('CLI Telemetry is disabled. See https://docs.aws.amazon.com/cdk/v2/guide/cli-telemetry.html for ways to enable.');
}
}
async cliTelemetry(enable) {
this.props.configuration.context.set('cli-telemetry', enable);
await this.props.configuration.saveContext();
await this.ioHost.asIoHelper().defaults.info(`Telemetry ${enable ? 'enabled' : 'disabled'}`);
}
async diff(options) {
const assembly = await this.assembly();
const stacks = await this.selectTopLevelOrMatchingStacks(assembly, options.stackNames, options.exclusively);
await this.validateStacks(assembly, stacks);
const strict = !!options.strict;
const contextLines = options.contextLines || 3;
const quiet = options.quiet || false;
let diffs = 0;
const parameterMap = buildParameterMap(options.parameters);
if (options.templatePath !== undefined) {
// Compare single stack against fixed template
if (stacks.stackCount !== 1) {
throw new toolkit_lib_1.ToolkitError('SingleStackRequired', 'Can only select one stack when comparing to fixed template. Use --exclusively to avoid selecting multiple stacks.');
}
if (!(await fs.pathExists(options.templatePath))) {
throw new toolkit_lib_1.ToolkitError('TemplateNotFound', `There is no file at ${options.templatePath}`);
}
if (options.importExistingResources) {
throw new toolkit_lib_1.ToolkitError('ImportWithTemplatePath', 'Can only use --import-existing-resources flag when comparing against deployed stacks.');
}
const template = (0, util_1.deserializeStructure)(await fs.readFile(options.templatePath, { encoding: 'utf-8' }));
const formatter = new api_1.DiffFormatter({
templateInfo: {
oldTemplate: template,
newTemplate: stacks.firstStack,
},
});
if (options.securityOnly) {
const securityDiff = formatter.formatSecurityDiff({ quiet });
// Warn, count, and display the diff only if the reported changes are broadening permissions
if (securityDiff.permissionChangeType === toolkit_lib_1.PermissionChangeType.BROADENING) {
await this.ioHost.asIoHelper().defaults.warn('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n');
await this.ioHost.asIoHelper().defaults.info(securityDiff.formattedDiff);
diffs += securityDiff.numStacksWithChanges;
}
}
else {
const diff = formatter.formatStackDiff({
strict,
contextLines,
quiet,
});
diffs = diff.numStacksWithChanges;
await this.ioHost.asIoHelper().defaults.info(diff.formattedDiff);
}
}
else {
const allMappings = options.includeMoves
? await (0, refactor_1.mappingsByEnvironment)(stacks.stackArtifacts, this.props.sdkProvider, true)
: [];
// Compare N stacks against deployed templates
for (const stack of stacks.stackArtifacts) {
const templateWithNestedStacks = await this.props.deployments.readCurrentTemplateWithNestedStacks(stack, options.compareAgainstProcessedTemplate);
const currentTemplate = templateWithNestedStacks.deployedRootTemplate;
const nestedStacks = templateWithNestedStacks.nestedStacks;
const environment = await this.props.deployments.resolveEnvironment(stack);
const migrator = new api_1.ResourceMigrator({
deployments: this.props.deployments,
ioHelper: (0, api_private_1.asIoHelper)(this.ioHost, 'diff'),
});
const resourcesToImport = await migrator.tryGetResources(environment);
if (resourcesToImport) {
(0, api_1.removeNonImportResources)(stack);
}
const changeSet = (options.method !== 'template')
? (await this.tryCreateDiffChangeSet(stack, options, parameterMap, resourcesToImport, quiet))?.changeSet
: undefined;
const mappings = allMappings.find(m => m.environment.region === stack.environment.region && m.environment.account === stack.environment.account)?.mappings ?? {};
const formatter = new api_1.DiffFormatter({
templateInfo: {
oldTemplate: currentTemplate,
newTemplate: stack,
changeSet,
isImport: !!resourcesToImport,
nestedStacks,
mappings,
environment,
},
});
if (options.securityOnly) {
const securityDiff = formatter.formatSecurityDiff({ quiet });
// Warn, count, and display the diff only if the reported changes are broadening permissions
if (securityDiff.permissionChangeType === toolkit_lib_1.PermissionChangeType.BROADENING) {
await this.ioHost.asIoHelper().defaults.warn('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n');
await this.ioHost.asIoHelper().defaults.info(securityDiff.formattedDiff);
diffs += securityDiff.numStacksWithChanges;
}
}
else {
const diff = formatter.formatStackDiff({
strict,
contextLines,
quiet,
});
await this.ioHost.asIoHelper().defaults.info(diff.formattedDiff);
diffs += diff.numStacksWithChanges;
}
}
}
await this.ioHost.asIoHelper().defaults.info((0, node_util_1.format)('\n✨ Number of stacks with differences: %s\n', diffs));
return diffs && options.fail ? 1 : 0;
}
/**
* Try to create a diff changeset for the given stack.
* Returns undefined if the stack cannot be accessed and changeSetOnly is not set.
*/
async tryCreateDiffChangeSet(stack, options, parameterMap, resourcesToImport, quiet) {
try {
// we don't actually need to know if the stack exists here
// we just use this to flush our any permissions issues and drop the result
void await this.props.deployments.stackExists({
stack,
deployName: stack.stackName,
tryLookupRole: true,
});
}
catch (e) {
if (options.method === 'change-set') {
throw toolkit_lib_1.ToolkitError.withCause('DescribeStacksFailed', `Could not access stack '${stack.stackName}'. Please check your permissions or use '--method=auto' to allow falling back to a template diff.`, e);
}
await this.ioHost.asIoHelper().defaults.debug((0, util_1.formatErrorMessage)(e));
if (!quiet) {
await this.ioHost.asIoHelper().defaults.info(`Could not access stack '${stack.stackName}', falling back to template diff. Use '--method=change-set' to fail instead. Run with -v to see the reason.\n`);
}
return undefined;
}
return api_private_1.cfnApi.createDiffChangeSet((0, api_private_1.asIoHelper)(this.ioHost, 'diff'), {
stack,
uuid: (0, node_crypto_1.randomUUID)(),
deployments: this.props.deployments,
sdkProvider: this.props.sdkProvider,
parameters: Object.assign({}, parameterMap['*'], parameterMap[stack.stackName]),
resourcesToImport,
importExistingResources: options.importExistingResources,
failOnError: options.method === 'change-set',
});
}
async deploy(options) {
const env_2 = { stack: [], error: void 0, hasError: false };
try {
if (options.watch) {
return this.watch(options);
}
// set progress from options, this includes user and app config
if (options.progress) {
this.ioHost.stackProgress = options.progress;
}
// the ioHost uses this internally to determine if a confirmation
// is actually needed, so it needs the same value we determine here.
const requireApproval = options.requireApproval ?? cloud_assembly_schema_1.RequireApproval.BROADENING;
this.ioHost.requireDeployApproval = requireApproval;
// toolkit-lib emits the approval request (I5060) without mentioning
// `--require-approval`. The CLI owns that flag, so it adds the framing here.
// Both deploy paths resolve through this host, so one listener covers both.
// Method-scoped (`using`): `deploy()` can run repeatedly (watch mode), and
// each run must register a rewrite for its own `requireApproval` value.
const _approvalFraming = __addDisposableResource(env_2, this.ioHost.rewrite(api_private_1.IO.CDK_TOOLKIT_I5060, (msg) => {
const updateTypeText = msg.data.permissionChangeType !== toolkit_lib_1.PermissionChangeType.NONE
? 'security-sensitive updates'
: 'updates';
return `Stack includes ${updateTypeText} and "--require-approval" is set to '${requireApproval}'.\nDo you wish to deploy these changes?`;
}), false);
// execute-change-set is a new flow that we can just delegate to toolkit-lib
if (options.deploymentMethod?.method === 'execute-change-set') {
await this.toolkit.deploy(this.props.cloudExecutable, {
deploymentMethod: options.deploymentMethod,
stacks: {
patterns: options.selector.patterns,
strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE,
expand: cloud_assembly_1.ExpandStackSelection.NONE,
},
roleArn: options.roleArn,
forceDeployment: options.force,
rollback: options.rollback,
reuseAssets: options.reuseAssets,
concurrency: options.concurrency,
traceLogs: options.traceLogs,
notificationArns: options.notificationArns,
tags: options.tags,
outputsFile: options.outputsFile,
assetParallelism: options.assetParallelism,
assetBuildConcurrency: options.assetBuildConcurrency,
assetBuildTime: options.assetBuildTime,
parameters: undefined, // parameters are only set during change set creation, so this is explicitly unset because change set already exists
});
return;
}
const startSynthTime = new Date().getTime();
const assembly = await this.assembly(options.cacheCloudAssembly);
const stackCollection = await assembly.selectStacksV2(options.selector);
await this.validateStacks(assembly, stackCollection);
const elapsedSynthTime = new Date().getTime() - startSynthTime;
await this.ioHost.asIoHelper().defaults.info(`\n✨ Synthesis time: ${(0, util_1.formatTime)(elapsedSynthTime)}s\n`);
if (stackCollection.stackCount === 0) {
await this.ioHost.asIoHelper().defaults.error('This app contains no stacks');
return;
}
const migrator = new api_1.ResourceMigrator({
deployments: this.props.deployments,
ioHelper: (0, api_private_1.asIoHelper)(this.ioHost, 'deploy'),
});
await migrator.tryMigrateResources(stackCollection, {
toolkitStackName: this.toolkitStackName,
...options,
});
if (options.deploymentMethod?.method === 'hotswap') {
await this.ioHost.asIoHelper().defaults.warn('⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments');
await this.ioHost.asIoHelper().defaults.warn('⚠️ They should only be used for development - never use them for your production Stacks!\n');
}
const stacks = stackCollection.stackArtifacts;
const assetBuildTime = options.assetBuildTime ?? AssetBuildTime.ALL_BEFORE_DEPLOY;
const prebuildAssets = assetBuildTime === AssetBuildTime.ALL_BEFORE_DEPLOY;
const concurrency = options.concurrency || 1;
if (concurrency > 1) {
// the "bar" progress output doesn't support concurrency, fall back to "events"
if (this.ioHost.stackProgress === deploy_1.StackActivityProgress.BAR) {
this.ioHost.stackProgress = deploy_1.StackActivityProgress.EVENTS;
}
// ...but only warn if the user explicitly requested "bar" progress
if (options.progress === deploy_1.StackActivityProgress.BAR) {
await this.ioHost.asIoHelper().defaults.warn('⚠️ The --concurrency flag does not support --progress "bar". Switching to "events".');
}
}
const stacksAndTheirAssetManifests = stacks.flatMap((stack) => [
stack,
...stack.dependencies.filter(x => cxapi.AssetManifestArtifact.isAssetManifestArtifact(x)),
]);
const workGraph = new api_1.WorkGraphBuilder((0, api_private_1.asIoHelper)(this.ioHost, 'deploy'), prebuildAssets).build(stacksAndTheirAssetManifests);
// Unless we are running with '--force', skip already published assets
if (!options.force) {
await this.removePublishedAssets(workGraph, options);
}
const graphConcurrency = {
'stack': concurrency,
'asset-build': (options.assetParallelism ?? true) ? options.assetBuildConcurrency ?? 1 : 1, // This will be CPU-bound/memory bound, mostly matters for Docker builds
'asset-publish': (options.assetParallelism ?? true) ? 8 : 1, // This will be I/O-bound, 8 in parallel seems reasonable
'marker': 1,
};
const deploymentActions = new WorkGraphDeploymentActions(this.props.deployments, this.ioHost, this, {
roleArn: options.roleArn,
force: options.force,
stackCount: stackCollection.stackCount,
notificationArns: options.notificationArns,
deploymentMethod: options.deploymentMethod,
toolkitStackName: this.toolkitStackName,
reuseAssets: options.reuseAssets,
tags: options.tags,
parameters: options.parameters,
usePreviousParameters: options.usePreviousParameters,
rollback: options.rollback,
concurrency,
requireApproval,
assetParallelism: options.assetParallelism,
extraUserAgent: options.extraUserAgent,
cloudWatchLogMonitor: options.cloudWatchLogMonitor,
sdkProvider: this.props.sdkProvider,
express: options.express,
});
const startDeployTime = Date.now();
await workGraph.doParallel(graphConcurrency, deploymentActions);
if (options.outputsFile) {
// If an outputs file has been specified, create the file path and write stack outputs to it once.
// Outputs are written after all stacks have been deployed. If a stack deployment fails,
// all of the outputs from successfully deployed stacks before the failure will still be written.
await deploymentActions.writeOutputs(options.outputsFile);
}
// Add a timer on the COMMAND span for the full deployment wait time (not the same as the sum of all DEPLOY
// spans because of parallelism).
this.ioHost.telemetry?.commandSpan?.addTimer('totalDeployTime', Date.now() - startDeployTime);
await this.ioHost.asIoHelper().defaults.info(`\n✨ Total time: ${(0, util_1.formatTime)(Date.now() - startSynthTime)}s\n`);
}
catch (e_2) {
env_2.error = e_2;
env_2.hasError = true;
}
finally {
__disposeResources(env_2);
}
}
/**
* Detect infrastructure drift for the given stack(s)
*/
async drift(options) {
const driftResults = await this.toolkit.drift(this.props.cloudExecutable, {
stacks: options.selector,
});
const totalDrifts = Object.values(driftResults).reduce((total, current) => total + (current.numResourcesWithDrift ?? 0), 0);
return totalDrifts > 0 && options.fail ? 1 : 0;
}
/**
* Validate synthesized templates against policy rules
*/
async validate(options) {
// Implicitly switch 'debug' mode to true; more stack traces = more useful.
this.props.cloudExecutable.switchOnDebugging();
// `watch` is a CLI-only flag; strip it before crossing into toolkit-lib so
// it does not leak into the library's validate action.
const { watch, ...validateOptions } = options;
if (watch) {
return this.validateWatch(validateOptions);
}
const result = await this.toolkit.validate(this.props.cloudExecutable, validateOptions);
return result.conclusion === 'failure' ? 1 : 0;
}
/**
* Continuously validate the project, re-synthesizing and re-validating on
* every file change. Never deploys.
*
* The files to observe are configured with the "watch" key of `cdk.json`,
* exactly like `cdk deploy --watch`.
*/
async validateWatch(options) {
const rootDir = path.dirname(path.resolve(user_configuration_1.PROJECT_CONFIG));
const watchSettings = this.props.configuration.settings.get(['watch']);
if (!watchSettings) {
throw new toolkit_lib_1.ToolkitError('WatchConfigMissing', "Cannot use '--watch' without specifying at least one directory to monitor. " +
'Make sure to add a "watch" key to your cdk.json');
}
const include = this.patternsArrayForWatch(watchSettings.include, {
defaultPattern: '**',
returnDefaultIfEmpty: true,
});
// Pass the user's excludes explicitly; toolkit-lib always appends the
// outdir, dot-file, and node_modules excludes on top of these.
const exclude = this.patternsArrayForWatch(watchSettings.exclude, {
defaultPattern: '',
returnDefaultIfEmpty: false,
});
const watcher = await this.toolkit.watchValidate(this.props.cloudExecutable.uncachedSource(), {
...options,
watchDir: rootDir,
include,
exclude,
});
return watcher.waitForEnd();
}
/**
* Diagnose errors
*/
async diagnose(options) {
// Implicitly switch 'debug' mode to true; more stack traces = more useful.
this.props.cloudExecutable.switchOnDebugging();
const results = await this.toolkit.diagnose(this.props.cloudExecutable, options);
if (results.stacks.some(s => s.result.type !== 'no-problem')) {
return 1;
}
return 0;
}
/**
* Roll back the given stack or stacks.
*/
async rollback(options) {
const startSynthTime = new Date().getTime();
const assembly = await this.assembly();
const stackCollection = await assembly.selectStacksV2(options.selector);
await this.validateStacks(assembly, stackCollection);
const elapsedSynthTime = new Date().getTime() - startSynthTime;
await this.ioHost.asIoHelper().defaults.info(`\n✨ Synthesis time: ${(0, util_1.formatTime)(elapsedSynthTime)}s\n`);
if (stackCollection.stackCount === 0) {
await this.ioHost.asIoHelper().defaults.error('No stacks selected');
return;
}
let anyRollbackable = false;
for (const stack of stackCollection.stackArtifacts) {
await this.ioHost.asIoHelper().defaults.info('Rolling back %s', chalk_1.default.bold(stack.displayName));
const startRollbackTime = new Date().getTime();
try {
const result = await this.props.deployments.rollbackStack({
stack,
roleArn: options.roleArn,
toolkitStackName: options.toolkitStackName,
orphanFailedResources: options.force,
validateBootstrapStackVersion: options.validateBootstrapStackVersion,
orphanLogicalIds: options.orphanLogicalIds,
});
if (!result.notInRollbackableState) {
anyRollbackable = true;
}
const elapsedRollbackTime = new Date().getTime() - startRollbackTime;
await this.ioHost.asIoHelper().defaults.info(`\n✨ Rollback time: ${(0, util_1.formatTime)(elapsedRollbackTime).toString()}s\n`);
}
catch (e) {
await this.ioHost.asIoHelper().defaults.error('\n ❌ %s failed: %s', chalk_1.default.bold(stack.displayName), (0, util_1.formatErrorMessage)(e));
throw new toolkit_lib_1.ToolkitError('RollbackFailed', 'Rollback failed (use --force to orphan failing resources)');
}
}
if (!anyRollbackable) {
throw new toolkit_lib_1.ToolkitError('NoRollbackableStacks', 'No stacks were in a state that could be rolled back');
}
}
async publishAssets(options) {
await this.toolkit.publishAssets(this.props.cloudExecutable, options);
}
async watch(options) {
const rootDir = path.dirname(path.resolve(user_configuration_1.PROJECT_CONFIG));
const ioHelper = (0, api_private_1.asIoHelper)(this.ioHost, 'watch');
await this.ioHost.asIoHelper().defaults.debug("root directory used for 'watch' is: %s", rootDir);
const watchSettings = this.props.configuration.settings.get(['watch']);
if (!watchSettings) {
throw new toolkit_lib_1.ToolkitError('WatchConfigMissing', "Cannot use the 'watch' command without specifying at least one directory to monitor. " +
'Make sure to add a "watch" key to your cdk.json');
}
// For the "include" subkey under the "watch" key, the behavior is:
// 1. No "watch" setting? We error out.
// 2. "watch" setting without an "include" key? We default to observing "./**".
// 3. "watch" setting with an empty "include" key? We default to observing "./**".
// 4. Non-empty "include" key? Just use the "include" key.
// Note: We use '**' as the default pattern (not rootDir) because chokidar reports
// file paths relative to cwd, and the ignored function uses picomatch which expects
// glob patterns, not absolute paths.
const watchIncludes = this.patternsArrayForWatch(watchSettings.include, {
defaultPattern: '**',
returnDefaultIfEmpty: true,
});
await this.ioHost.asIoHelper().defaults.debug("'include' patterns for 'watch': %s", watchIncludes);
// For the "exclude" subkey under the "watch" key,
// the behavior is to add some default excludes in addition to the ones specified by the user:
// 1. The CDK output directory.
// 2. Any file whose name starts with a dot.
// 3. Any directory's content whose name starts with a dot.
// 4. Any node_modules and its content (even if it's not a JS/TS project, you might be using a local aws-cli package)
const outputDir = this.props.configuration.settings.get(['output']);
const watchExcludes = this.patternsArrayForWatch(watchSettings.exclude, {
defaultPattern: '',
returnDefaultIfEmpty: false,
}).concat(`${outputDir}/**`, '**/.*', '**/.*/**', '**/node_modules/**');
await this.ioHost.asIoHelper().defaults.debug("'exclude' patterns for 'watch': %s", watchExcludes);
// Since 'cdk deploy' is a relatively slow operation for a 'watch' process,
// introduce a concurrency latch that tracks the state.
// This way, if file change events arrive when a 'cdk deploy' is still executing,
// we will batch them, and trigger another 'cdk deploy' after the current one finishes,
// making sure 'cdk deploy's always execute one at a time.
// Here's a diagram showing the state transitions:
// -------------- -------- file changed -------------- file changed -------------- file changed
// | | ready event | | ------------------> | | ------------------> | | --------------|
// | pre-ready | -------------> | open | | deploying | | queued | |
// | | | | <------------------ | | <------------------ | | <-------------|
// -------------- -------- 'cdk deploy' done -------------- 'cdk deploy' done --------------
let latch = 'pre-ready';
const cloudWatchLogMonitor = options.traceLogs ? new api_1.CloudWatchLogEventMonitor({
ioHelper,
}) : undefined;
const deployAndWatch = async () => {
latch = 'deploying';
await cloudWatchLogMonitor?.deactivate();
await this.invokeDeployFromWatch(options, cloudWatchLogMonitor);
// If latch is still 'deploying' after the 'await', that's fine,
// but if it's 'queued', that means we need to deploy again
while (latch === 'queued') {
// TypeScript doesn't realize latch can change between 'awaits',
// and thinks the above 'while' condition is always 'false' without the cast
latch = 'deploying';
await this.ioHost.asIoHelper().defaults.info("Detected file changes during deployment. Invoking 'cdk deploy' again");
await this.invokeDeployFromWatch(options, cloudWatchLogMonitor);
}
latch = 'open';
await cloudWatchLogMonitor?.activate();
};
// Create ignore matcher for chokidar v4 compatibility
// Chokidar v4 removed glob pattern support, so we use picomatch to filter files
// We pass rootDir because chokidar v4 passes absolute paths to the ignored callback
const shouldIgnore = (0, api_private_1.createIgnoreMatcher)({
include: watchIncludes,
exclude: watchExcludes,
rootDir,
});
chokidar
.watch('.', {
ignored: shouldIgnore,
cwd: rootDir,
})
.on('ready', async () => {
latch = 'open';
await this.ioHost.asIoHelper().defaults.debug("'watch' received the 'ready' event. From now on, all file changes will trigger a deployment");
await this.ioHost.asIoHelper().defaults.info("Triggering initial 'cdk deploy'");
await deployAndWatch();
})
.on('all', async (event, filePath) => {
if (!isFileEvent(event)) {
return; // Ignore non-file events like 'error', 'raw', 'ready', 'all'
}
if (latch === 'pre-ready') {
await this.ioHost.asIoHelper().defaults.info(`'watch' is observing ${event === 'addDir' ? 'directory' : 'the file'} '%s' for changes`, filePath);
}
else if (latch === 'open') {
await this.ioHost.asIoHelper().defaults.info("Detected change to '%s' (type: %s). Triggering 'cdk deploy'", filePath, event);
await deployAndWatch();
}
else {
// this means latch is either 'deploying' or 'queued'
latch = 'queued';
await this.ioHost.asIoHelper().defaults.info("Detected change to '%s' (type: %s) while 'cdk deploy' is still running. " +
'Will queue for another deployment after this one finishes', filePath, event);
}
});
}
async orphan(options) {
await this.toolkit.orphan(this.props.cloudExecutable, {
constructPaths: options.constructPath,
roleArn: options.roleArn,
toolkitStackName: options.toolkitStackName,
});
}
async import(options) {
const assembly = await this.assembly();
const stacks = await assembly.selectStacksV2(options.selector);
await this.validateStacks(assembly, stacks);
// set progress from options, this includes user and app config
if (options.progress) {
this.ioHost.stackProgress = options.progress;
}
if (stacks.stackCount > 1) {
throw new toolkit_lib_1.ToolkitError('AmbiguousStackSelection', `Stack selection is ambiguous, please choose a specific stack for import [${stacks.stackArtifacts.map((x) => x.id).join(', ')}]`);
}
if (!process.stdout.isTTY && !options.resourceMappingFile && !options.resourceMappingInline) {
throw new toolkit_lib_1.ToolkitError('ResourceMappingRequired', '--resource-mapping or --resource-mapping-inline is required when input is not a terminal');
}
const stack = stacks.stackArtifacts[0];
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.bold(stack.displayName));
const resourceImporter = new api_1.ResourceImporter(stack, {
deployments: this.props.deployments,
ioHelper: (0, api_private_1.asIoHelper)(this.ioHost, 'import'),
});
const { additions, hasNonAdditions, diffFormatter } = await resourceImporter.discoverImportableResources(options.force);
// If there are non-addition changes (e.g. after orphan, hardcoded refs differ from Fn::GetAtt),
// warn the user and ask for confirmation unless --force was given.
if (hasNonAdditions && !options.force) {
const ioHelper = this.ioHost.asIoHelper();
await ioHelper.defaults.info(`The following resources have pending updates that will be reconciled with a ${chalk_1.default.blueBright('cdk deploy')} after import:`);
const { formattedDiff } = diffFormatter.formatStackDiff();
await ioHelper.defaults.info(formattedDiff);
const confirmed = await ioHelper.requestResponse(api_private_1.IO.CDK_TOOLKIT_I7010.req('Perform import?', { motivation: 'Confirm import with pending drift' }));
if (!confirmed) {
throw new toolkit_lib_1.AbortError('ImportAborted', 'Import cancelled');
}
}
if (additions.length === 0) {
await this.ioHost.asIoHelper().defaults.warn('%s: no new resources compared to the currently deployed stack, skipping import.', chalk_1.default.bold(stack.displayName));
return;
}
// Prepare a mapping of physical resources to CDK constructs
let actualImport;
if (options.resourceMappingInline) {
actualImport = await resourceImporter.loadResourceIdentifiers(additions, options.resourceMappingInline);
}
else if (options.resourceMappingFile) {
actualImport = await resourceImporter.loadResourceIdentifiersFromFile(additions, options.resourceMappingFile);
}
else {
actualImport = await resourceImporter.askForResourceIdentifiers(additions);
}
if (actualImport.importResources.length === 0) {
await this.ioHost.asIoHelper().defaults.warn('No resources selected for import.');
return;
}
// If "--create-resource-mapping" option was passed, write the resource mapping to the given file and exit
if (options.recordResourceMapping) {
const outputFile = options.recordResourceMapping;
fs.ensureFileSync(outputFile);
await fs.writeJson(outputFile, actualImport.resourceMap, {
spaces: 2,
encoding: 'utf8',
});
await this.ioHost.asIoHelper().defaults.info('%s: mapping file written.', outputFile);
return;
}
// Following are the same semantics we apply with respect to Notification ARNs (dictated by the SDK)
//
// - undefined => cdk ignores it, as if it wasn't supported (allows external management).
// - []: => cdk manages it, and the user wants to wipe it out.
// - ['arn-1'] => cdk manages it, and the user wants to set it to ['arn-1'].
const notificationArns = (!!options.notificationArns || !!stack.notificationArns)
? (options.notificationArns ?? []).concat(stack.notificationArns ?? [])
: undefined;
for (const notificationArn of notificationArns ?? []) {
if (!(0, util_1.validateSnsTopicArn)(notificationArn)) {
throw new toolkit_lib_1.ToolkitError('InvalidSnsTopicArn', `Notification arn ${notificationArn} is not a valid arn for an SNS topic`);
}
}
// Import the resources according to the given mapping
await this.ioHost.asIoHelper().defaults.info('%s: importing resources into stack...', chalk_1.default.bold(stack.displayName));
const tags = (0, api_private_1.tagsForStack)(stack);
await resourceImporter.importResourcesFromMap(actualImport, {
roleArn: options.roleArn,
tags,
deploymentMethod: options.deploymentMethod,
usePreviousParameters: true,
rollback: options.rollback,
notificationArns,
});
// Notify user of next steps
if (actualImport.importResources.length < additions.length) {
await this.ioHost.asIoHelper().defaults.warn(`Some resources were skipped. Run another ${chalk_1.default.blueBright('cdk import')} or a ${chalk_1.default.blueBright('cdk deploy')} to bring the stack up-to-date with your CDK app definition.`);
}
else if (hasNonAdditions) {
// After orphan→import, the deployed template still has hardcoded values that differ from
// the synth'd template's Fn::GetAtt/Ref intrinsics. A deploy updates the template to match the CDK app.
if (options.force) {
await this.ioHost.asIoHelper().defaults.info(`Import complete. Run ${chalk_1.default.blueBright('cdk deploy')} to update the stack to match your CDK app.`);
}
else {
const deployNow = await this.ioHost.asIoHelper().requestResponse(api_private_1.IO.CDK_TOOLKIT_I7010.req(`Finish with a ${chalk_1.default.blueBright('cdk deploy')} now?`, { motivation: 'Update stack to match CDK app after import' }));
if (deployNow) {
await this.deploy({
// The import selector is exact (no expansion); the follow-up deploy
// historically expands to upstream dependencies like a plain deploy.
selector: { ...options.selector, expand: cloud_assembly_1.ExpandStackSelection.UPSTREAM },
toolkitStackName: options.toolkitStackName,
roleArn: options.roleArn,
deploymentMethod: options.deploymentMethod,
});
}
else {
await this.ioHost.asIoHelper().defaults.info(`Import complete. Remember to run ${chalk_1.default.blueBright('cdk deploy')} to update the stack to match your CDK app.`);
}
}
}
else {
await this.ioHost.asIoHelper().defaults.info(`Import operation complete. We recommend you run a ${chalk_1.default.blueBright('drift detection')} operation ` +
'to confirm your CDK app resource definitions are up-to-date. Read more here: ' +
chalk_1.default.underline.blueBright('https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html'));
}
}
// The destroy action runs through toolkit-lib.
// Suppress its new status messages to keep the output as it was before.
async destroy(options) {
const env_3 = { stack: [], error: void 0, hasError: false };
try {
// Keep the "deployed" wording when a destroy runs as part of a deploy.
const action = options.fromDeploy ? 'deploy' : 'destroy';
if ((options.concurrency || 1) > 1 && this.ioHost.stackProgress === deploy_1.StackActivityProgress.BAR) {
this.ioHost.stackProgress = deploy_1.StackActivityProgress.EVENTS;
}
// The success line was `info` in the historical `cdk destroy`, not `result`.
const _successLevel = __addDisposableResource(env_3, this.ioHost.on(api_private_1.IO.CDK_TOOLKIT_I7900, () => ({ level: 'info' })), false); // ✅ <stack>: destroyed
// toolkit-lib logs a declined confirmation (E7010) and returns gracefully.
// The CLI surfaces a decline as a non-zero, soft exit instead: throwing from
// the listener both suppresses the log and aborts the command (the top-level
// renders `AbortError` as "Deletion cancelled").
const _declineAborts = __addDisposableResource(env_3, this.ioHost.on(api_private_1.IO.CDK_TOOLKIT_E7010, () => {
throw new toolkit_lib_1.AbortError('DestroyAborted', 'Deletion cancelled');
}), false);
const _forceConfirms = __addDisposableResource(env_3, options.force ? this.ioHost.respondOnce(api_private_1.IO.CDK_TOOLKIT_I7010, true) : undefined, false);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - `_destroyWithAction` is private; the CLI sets the action label.
await this.toolkit._destroyWithAction(this.props.cloudExecutable, action, {
stacks: options.selector,
roleArn: options.roleArn,
concurrency: options.concurrency,
express: options.express,
});
}
catch (e_3) {
env_3.error = e_3;
env_3.hasError = true;
}
finally {
__disposeResources(env_3);
}
}
// cdk ls stdout is the stack listing only. Suppress the info status lines synthesis emits next
// to it: the synth-time line (I1000) and the dependency-expansion note (I1002).
async list(selectors, options = {}) {
const env_4 = { stack: [], error: void 0, hasError: false };
try {
// One-shot: disposes itself when the listing (I2901) is emitted; the
// `using` covers the case where `list` throws before that happens.
const _formatter = __addDisposableResource(env_4, this.ioHost.rewriteOnce(api_private_1.IO.CDK_TOOLKIT_I2901, (msg) => (0, list_stacks_1.formatStackList)(msg.data.stacks, options)), false);
await this.toolkit.list(this.props.cloudExecutable, {
stacks: selectors.length > 0 ? (0, cloud_assembly_1.selectWithUpstream)(...selectors) : undefined,
});
return 0; // exit-code
}
catch (e_4) {
env_4.error = e_4;
env_4.hasError = true;
}
finally {
__disposeResources(env_4);
}
}
/**
* Synthesize the given set of stacks (called when the user runs 'cdk synth')
*
* INPUT: Stack names can be supplied using a glob filter. If no stacks are
* given, all stacks from the application are implicitly selected.
*
* OUTPUT: If more than one stack ends up being selected, an output directory
* should be supplied, where the templates will be written.
*/
async synth(options) {
const stackNames = options.stackNames;
const exclusively = options.exclusively ?? false;
const quiet = options.quiet ?? false;
const autoValidate = options.autoValidate ?? false;
const json = options.json ?? false;
const assembly = await this.assembly();
const stacks = await this.selectTopLevelOrMatchingStacks(assembly, stackNames, exclusively);
const autoValidateStacks = autoValidate
? assembly.selectStacksForValidation()
: new cloud_assembly_1.StackCollection(assembly, []);
await this.validateStacks(assembly, stacks.concat(autoValidateStacks));
// if we have a single stack, print it to STDOUT
if (stacks.stackCount === 1) {
if (!quiet) {
await printSerializedObject(this.ioHost.asIoHelper(), (0, util_1.obscureTemplate)(stacks.firstStack.template), json);
}
// In CI mode, non-error messages go to stdout. When we just printed the
// template to stdout, skip the flags message to preserve the contract that
// `cdk synth` output is valid YAML. When quiet (no template printed) or
// non-CI (flags go to stderr), it's safe to show.
if (quiet || !this.ioHost.isCI) {
await displayFlagsMessage(this.ioHost.asIoHelper(), this.toolkit, this.props.cloudExecutable);
}
return undefined;
}
// not outputting template to stdout, let's explain things to the user a little bit...
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green(`Successfully synthesized to ${chalk_1.default.blue(path.resolve(stacks.assembly.directory))}`));
await this.ioHost.asIoHelper().defaults.info(`Supply a stack id (${stacks.stackArtifacts.map((s) => chalk_1.default.green(s.hierarchicalId)).join(', ')}) to display its template.`);
await displayFlagsMessage(this.ioHost.asIoHelper(), this.toolkit, this.props.cloudExecutable);
return undefined;
}
/**
* Bootstrap the CDK Toolkit stack in the accounts used by the specified stack(s).
*
* @param userEnvironmentSpecs - environment names that need to have toolkit support
* provisioned, as a glob filter. If none is provided, all stacks are implicitly selected.
* @param options - The name, role ARN, bootstrapping parameters, etc. to be used for the CDK Toolkit stack.
*/
async bootstrap(userEnvironmentSpecs, options) {
const bootstrapper = new bootstrap_1.Bootstrapper(options.source, (0, api_private_1.asIoHelper)(this.ioHost, 'bootstrap'));
// If there is an '--app' argument and an environment looks like a glob, we
// select the environments from the app. Otherwise, use what the user said.
const environments = await this.defineEnvironments(userEnvironmentSpecs);
const limit = pLimit(20);
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
await Promise.all(environments.map((environment) => limit(async () => {
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green(' ⏳ Bootstrapping environment %s...'), chalk_1.default.blue(environment.name));
try {
const result = await bootstrapper.bootstrapEnvironment(environment, this.props.sdkProvider, options);
const message = result.noOp
? '✅ Environment %s bootstrapped (no changes).'
: '✅ Environment %s bootstrapped.';
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green(message), chalk_1.default.blue(environment.name));
if (options.express) {
const warning = (0, api_private_1.formatExpressStabilizationWarning)(result.stabilizingResources, 'bootstrap');
if (warning) {
await this.ioHost.asIoHelper().notify(api_private_1.IO.CDK_TOOLKIT_W9902.msg(warning));
}
}
}
catch (e) {
await this.ioHost.asIoHelper().defaults.error(' ❌ Environment %s failed bootstrapping: %s', chalk_1.default.blue(environment.name), e);
throw e;
}
})));
}
/**
* Garbage collects assets from a CDK app's environment
* @param options - Options for Garbage Collection
*/
async garbageCollect(userEnvironmentSpecs, options) {
const environments = await this.defineEnvironments(userEnvironmentSpecs);
for (const environment of environments) {
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green(' ⏳ Garbage Collecting environment %s...'), chalk_1.default.blue(environment.name));
const gc = new api_1.GarbageCollector({
sdkProvider: this.props.sdkProvider,
ioHelper: (0, api_private_1.asIoHelper)(this.ioHost, 'gc'),
resolvedEnvironment: environment,
bootstrapStackName: options.bootstrapStackName,
rollbackBufferDays: options.rollbackBufferDays,
createdBufferDays: options.createdBufferDays,
action: options.action ?? 'full',
type: options.type ?? 'all',
confirm: options.confirm ?? true,
});
await gc.garbageCollect();
}
}
async defineEnvironments(userEnvironmentSpecs) {
// By default, glob for everything
const environmentSpecs = userEnvironmentSpecs.length > 0 ? [...userEnvironmentSpecs] : ['**'];
// Partition into globs and non-globs (this will mutate environmentSpecs).
const globSpecs = (0, util_1.partition)(environmentSpecs, cxapp_1.looksLikeGlob);
if (globSpecs.length > 0 && !this.props.cloudExecutable.hasApp) {
if (userEnvironmentSpecs.length > 0) {
// User did request this glob
throw new toolkit_lib_1.ToolkitError('InvalidEnvironmentGlob', `'${globSpecs}' is not an environment name. Specify an environment name like 'aws://123456789012/us-east-1', or run in a directory with 'cdk.json' to use wildcards.`);
}
else {
// User did not request anything
throw new toolkit_lib_1.ToolkitError('EnvironmentRequired', "Specify an environment name like 'aws://123456789012/us-east-1', or run in a directory with 'cdk.json'.");
}
}
const environments = [...(0, cxapp_1.environmentsFromDescriptors)(environmentSpecs)];
// If there is an '--app' argument, select the environments from the app.
if (this.props.cloudExecutable.hasApp) {
const assembly = await this.assembly();
const allStacks = await assembly.selectStacksV2(cloud_assembly_1.ALL_STACKS);
environments.push(...(await (0, cxapp_1.globEnvironmentsFromStacks)(allStacks, globSpecs, this.props.sdkProvider)));
}
return environments;
}
/**
* Migrates a CloudFormation stack/template to a CDK app
* @param options - Options for CDK app creation
*/
async migrate(options) {
await this.ioHost.asIoHelper().defaults.warn('This command is an experimental feature.');
const language = options.language?.toLowerCase() ?? 'typescript';
const environment = (0, migrate_1.setEnvironment)(options.account, options.region);
let generateTemplateOutput;
let cfn;
let templateToDelete;
try {
// if neither fromPath nor fromStack is provided, generate a template using cloudformation
const scanType = (0, migrate_1.parseSourceOptions)(options.fromPath, options.fromStack, options.stackName).source;
if (scanType == migrate_1.TemplateSourceOptions.SCAN) {
generateTemplateOutput = await (0, migrate_1.generateTemplate)({
stackName: options.stackName,
filters: options.filter,
fromScan: options.fromScan,
sdkProvider: this.props.sdkProvider,
environment: environment,
ioHelper: this.ioHost.asIoHelper(),
});
templateToDelete = generateTemplateOutput.templateId;
}
else if (scanType == migrate_1.TemplateSourceOptions.PATH) {
const templateBody = (0, migrate_1.readFromPath)(options.fromPath);
const parsedTemplate = (0, util_1.deserializeStructure)(templateBody);
const templateId = parsedTemplate.Metadata?.AWSToolsMetrics?.IaC_Generator?.toString();
if (templateId) {
// if we have a template id, we can call describe generated template to get the resource identifiers
// resource metadata, and template source to generate the template
cfn = new migrate_1.CfnTemplateGeneratorProvider(await (0, migrate_1.buildCfnClient)(this.props.sdkProvider, environment), this.ioHost.asIoHelper());
const generatedTemplateSummary = await cfn.describeGeneratedTemplate(templateId);
generateTemplateOutput = (0, migrate_1.buildGeneratedTemplateOutput)(generatedTemplateSummary, templateBody, generatedTemplateSummary.GeneratedTemplateId);
}
else {
generateTemplateOutput = {
migrateJson: {
templateBody: templateBody,
source: 'localfile',
},
};
}
}
else if (scanType == migrate_1.TemplateSourceOptions.STACK) {
const template = await (0, migrate_1.readFromStack)(options.stackName, this.props.sdkProvider, environment);
if (!template) {
throw new toolkit_lib_1.ToolkitError('StackTemplateNotFound', `No template found for stack-name: ${options.stackName}`);
}
generateTemplateOutput = {
migrateJson: {
templateBody: template,
source: options.stackName,
},
};
}
else {
// We shouldn't ever get here, but just in case.
throw new toolkit_lib_1.ToolkitError('InvalidSourceOption', `Invalid source option provided: ${scanType}`);
}
const stack = (0, migrate_1.generateStack)(generateTemplateOutput.migrateJson.templateBody, options.stackName, language);
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green(' ⏳ Generating CDK app for %s...'), chalk_1.default.blue(options.stackName));
await (0, migrate_1.generateCdkApp)(this.ioHost.asIoHelper(), options.stackName, stack, language, options.outputPath, options.compress);
if (generateTemplateOutput) {
(0, migrate_1.writeMigrateJsonFile)(options.outputPath, options.stackName, generateTemplateOutput.migrateJson);
}
if ((0, migrate_1.isThereAWarning)(generateTemplateOutput)) {
await this.ioHost.asIoHelper().defaults.warn(' ⚠️ Some resources could not be migrated completely. Please review the README.md file for more information.');
(0, migrate_1.appendWarningsToReadme)(`${path.join(options.outputPath ?? process.cwd(), options.stackName)}/README.md`, generateTemplateOutput.resources);
}
}
catch (e) {
await this.ioHost.asIoHelper().defaults.error(' ❌ Migrate failed for `%s`: %s', options.stackName, e.message);
throw e;
}
finally {
if (templateToDelete) {
if (!cfn) {
cfn = new migrate_1.CfnTemplateGeneratorProvider(await (0, migrate_1.buildCfnClient)(this.props.sdkProvider, environment), this.ioHost.asIoHelper());
}
if (!process.env.MIGRATE_INTEG_TEST) {
await cfn.deleteGeneratedTemplate(templateToDelete);
}
}
}
}
async refactor(options) {
if (options.revert && !options.overrideFile) {
throw new toolkit_lib_1.ToolkitError('RevertRequiresOverrideFile', 'The --revert option can only be used with the --override-file option.');
}
try {
await this.toolkit.refactor(this.props.cloudExecutable, {
dryRun: options.dryRun,
stacks: options.stacks ?? cloud_assembly_1.ALL_STACKS,
force: options.force,
additionalStackNames: options.additionalStackNames,
overrides: readOverrides(options.overrideFile, options.revert),
roleArn: options.roleArn,
});
}
catch (e) {
await this.ioHost.asIoHelper().defaults.error(e.message);
throw e;
}
return 0;
function readOverrides(filePath, revert = false) {
if (filePath == null) {
return [];
}
if (!fs.pathExistsSync(filePath)) {
throw new toolkit_lib_1.ToolkitError('MappingFileNotFound', `The mapping file ${filePath} does not exist`);
}
const groups = (0, refactor_1.parseMappingGroups)(fs.readFileSync(filePath).toString('utf-8'));
return revert
? groups.map((group) => ({
...group,
resources: Object.fromEntries(Object.entries(group.resources ?? {}).map(([src, dst]) => [dst, src])),
}))
: groups;
}
}
/**
* Select the stacks that `synth` and `diff` operate on
*
* With patterns: match them (failing if nothing matches), expanding to
* upstream dependencies unless `exclusively` is set. Without patterns: all
* top-level stacks, exactly — the historic default selection never expands
* to dependencies, regardless of `exclusively`. A stage-only app has no
* top-level stacks, which selects nothing and is not an error — but an app
* without any stacks at all still is. No single selection strategy covers
* this combination: `MAIN_ASSEMBLY` rejects stage-only apps (as
* `deploy --all` must keep doing) and `ALL_STACKS` would wrongly include
* the stacks inside stages.
*/
async selectTopLevelOrMatchingStacks(assembly, patterns, exclusively) {
if (patterns.length > 0) {
return assembly.selectStacksV2((0, cloud_assembly_1.mustMatch)(exclusively ? (0, cloud_assembly_1.selectExact)(...patterns) : (0, cloud_assembly_1.selectWithUpstream)(...patterns)));
}
if (assembly.cloudAssembly.stacks.length > 0) {
return assembly.selectStacksV2((0, cloud_assembly_1.selectAllTopLevel)(cloud_assembly_1.ExpandStackSelection.NONE));
}
// Stage-only app: nothing to select, which is not an error. An app
// without any stacks at all still is: this selection throws
// 'This app contains no stacks' in that case.
await assembly.selectStacksV2(cloud_assembly_1.ALL_STACKS);
return new cloud_assembly_1.StackCollection(assembly, []);
}
/**
* Validate the stacks for errors and warnings according to the CLI's current settings
*/
async validateStacks(assembly, stacks) {
const failAt = this.validateMetadataFailAt();
await (0, api_private_1.throwIfValidationFailures)(assembly, stacks, failAt, this.ioHost.asIoHelper());
}
validateMetadataFailAt() {
let failAt = 'error';
if (this.props.ignoreErrors) {
failAt = 'none';
}
if (this.props.strict) {
failAt = 'warn';
}
return failAt;
}
/**
* Converts the toolkit's `CloudExecutable` into `StackAssembly`.
*
* @param cacheCloudAssembly - to cache the assembly, defaults to `true`
* @returns the converted `StackAssembly`
*/
assembly(cacheCloudAssembly = true) {
return this.props.cloudExecutable.synthesize(cacheCloudAssembly);
}
patternsArrayForWatch(patterns, options) {
const patternsArray = patterns !== undefined ? (Array.isArray(patterns) ? patterns : [patterns]) : [];
return patternsArray.length > 0 ? patternsArray : options.returnDefaultIfEmpty ? [options.defaultPattern] : [];
}
async invokeDeployFromWatch(options, cloudWatchLogMonitor) {
const deployOptions = {
...options,
requireApproval: cloud_assembly_schema_1.RequireApproval.NEVER,
// if 'watch' is called by invoking 'cdk deploy --watch',
// we need to make sure to not call 'deploy' with 'watch' again,
// as that would lead to a cycle
watch: false,
cloudWatchLogMonitor,
cacheCloudAssembly: false,
extraUserAgent: `cdk-watch/hotswap-${options.deploymentMethod?.method === 'hotswap' ? 'on' : 'off'}`,
concurrency: options.concurrency,
};
try {
await this.deploy(deployOptions);
}
catch {
// just continue - deploy will show the error
}
}
/**
* Remove the asset publishing and building from the work graph for assets that are already in place
*/
async removePublishedAssets(graph, options) {
await graph.removeUnnecessaryAssets(assetNode => this.props.deployments.isSingleAssetPublished(assetNode.assetManifest, assetNode.asset, {
stack: assetNode.parentStack,
roleArn: options.roleArn,
stackName: assetNode.parentStack.stackName,
}));
}
}
exports.CdkToolkit = CdkToolkit;
__decorate([
(0, io_host_1.suppressMessages)(api_private_1.IO.CDK_TOOLKIT_I1001, // Starting Synthesis (trace)
api_private_1.IO.CDK_TOOLKIT_I1000)
], CdkToolkit.prototype, "metadata", null);
__decorate([
(0, io_host_1.suppressMessages)(api_private_1.IO.CDK_TOOLKIT_I1001, // Starting Synthesis (trace)
api_private_1.IO.CDK_TOOLKIT_I1000, // ✨ Synthesis time (info)
api_private_1.IO.CDK_TOOLKIT_I7101, // Starting Destroy (trace)
api_private_1.IO.CDK_TOOLKIT_I7001, // per-stack Destroy time (trace)
api_private_1.IO.CDK_TOOLKIT_I7000)
], CdkToolkit.prototype, "destroy", null);
__decorate([
(0, io_host_1.suppressMessages)(api_private_1.IO.CDK_TOOLKIT_I1000, api_private_1.IO.CDK_TOOLKIT_I1002)
], CdkToolkit.prototype, "list", null);
/**
* Print a serialized object (YAML or JSON) to stdout.
*/
async function printSerializedObject(ioHelper, obj, json) {
await ioHelper.defaults.result((0, util_1.serializeStructure)(obj, json));
}
function buildParameterMap(parameters) {
const parameterMap = { '*': {} };
for (const key in parameters) {
if (parameters.hasOwnProperty(key)) {
const [stack, parameter] = key.split(':', 2);
if (!parameter) {
parameterMap['*'][stack] = parameters[key];
}
else {
if (!parameterMap[stack]) {
parameterMap[stack] = {};
}
parameterMap[stack][parameter] = parameters[key];
}
}
}
return parameterMap;
}
/**
* Ask the user for a yes/no confirmation
*
* Automatically fail the confirmation in case we're in a situation where the confirmation
* cannot be interactively obtained from a human at the keyboard.
*/
async function askUserConfirmation(ioHost, req, abortErrorCode, abortMessage) {
await ioHost.withCorkedLogging(async () => {
// The IoHost returns the answer rather than aborting; abort here on decline.
const confirmed = await ioHost.asIoHelper().requestResponse(req);
if (!confirmed) {
throw new toolkit_lib_1.AbortError(abortErrorCode, abortMessage);
}
});
}
/**
* Display a warning if there are flags that are different from the recommended value
*
* This happens if both of the following are true:
*
* - The user didn't configure the value
* - The default value for the flag (unconfiguredBehavesLike) is different from the recommended value
*/
async function displayFlagsMessage(ioHost, toolkit, cloudExecutable) {
const flags = await toolkit.flags(cloudExecutable);
// The "unconfiguredBehavesLike" information got added later. If none of the flags have this information,
// we don't have enough information to reliably display this information without scaring users, so don't do anything.
if (flags.every(flag => flag.unconfiguredBehavesLike === undefined)) {
return;
}
const unconfiguredFlags = operations_1.FlagOperations.filterNeedsAttention(flags);
const numUnconfigured = unconfiguredFlags.length;
if (numUnconfigured > 0) {
await ioHost.defaults.warn(`${numUnconfigured} feature flags are not configured. Run 'cdk flags --unstable=flags' to learn more.`);
}
}
/**
* This class implements the callbacks for the parallel work graph executions.
*
* All this code used to be inlined into CdkToolkit#deploy(), but it was getting
* too much to live in there.
*/
class WorkGraphDeploymentActions {
deployments;
ioHost;
stackOperations;
options;
stackOutputs = {};
assetSpans = {};
stackCounter = 1;
constructor(deployments, ioHost, stackOperations, options) {
this.deployments = deployments;
this.ioHost = ioHost;
this.stackOperations = stackOperations;
this.options = options;
}
async marker(markerNode) {
// For assets, emit IoHost messages that have been defined to start and end asset spans, which will lead to events in telemetry.
switch (markerNode.marker.type) {
case 'start-asset': {
const assetSpan = await this.obtainSpan(markerNode.marker.asset);
// Count the asset type, both on the asset-specific span and on the global COMMAND span.
if (markerNode.marker.asset.type === 'file') {
this.ioHost.telemetry?.commandSpan?.incCounter('fileAsset');
assetSpan.incCounter('fileAsset');
}
else if (markerNode.marker.asset.type === 'docker') {
this.ioHost.telemetry?.commandSpan?.incCounter('dockerAsset');
assetSpan.incCounter('dockerAsset');
}
break;
}
case 'end-asset': {
const assetSpan = await this.obtainSpan(markerNode.marker.asset);
await assetSpan.end({});
break;
}
}
}
async obtainSpan(assetEntry) {
const span = this.assetSpans[assetEntry.id.assetId];
if (span) {
return span;
}
const assetSpan = await this.ioHost.asIoHelper().span(messages_1.CLI_PRIVATE_SPAN.ASSET).begin({});
this.assetSpans[assetEntry.id.assetId] = assetSpan;
return assetSpan;
}
async buildAsset(assetNode) {
const env_5 = { stack: [], error: void 0, hasError: false };
try {
// Measure asset build time. Both on the global COMMAND span as well as on the asset-specific span.
// (parallelism may cause SUM(buildAssetST) >= totalDeployTime) on the COMMAND span, indicate with [S]ub[T]ask suffix).
const _invokeTimer = __addDisposableResource(env_5, this.ioHost.telemetry?.commandSpan?.startTimer('buildAssetST'), false);
const _assetTimer = __addDisposableResource(env_5, (await this.obtainSpan(assetNode.asset)).startTimer('buildAsset'), false);
await this.deployments.buildSingleAsset(assetNode.assetManifestArtifact, assetNode.assetManifest, assetNode.asset, {
stack: assetNode.parentStack,
roleArn: this.options.roleArn,
stackName: assetNode.parentStack.stackName,
});
}
catch (e_5) {
env_5.error = e_5;
env_5.hasError = true;
}
finally {
__disposeResources(env_5);
}
}
async publishAsset(assetNode) {
const env_6 = { stack: [], error: void 0, hasError: false };
try {
// Measure asset publish time. Both on the global COMMAND span as well as on the asset-specific span.
// (parallelism may cause SUM(publishAssetST) >= totalDeployTime) on the COMMAND span, indicate with [S]ub[T]ask suffix).
const _invokeTimer = __addDisposableResource(env_6, this.ioHost.telemetry?.commandSpan?.startTimer('publishAssetST'), false);
const _assetTimer = __addDisposableResource(env_6, (await this.obtainSpan(assetNode.asset)).startTimer('publishAsset'), false);
await this.deployments.publishSingleAsset(assetNode.assetManifest, assetNode.asset, {
stack: assetNode.parentStack,
roleArn: this.options.roleArn,
stackName: assetNode.parentStack.stackName,
forcePublish: this.options.force,
});
}
catch (e_6) {
env_6.error = e_6;
env_6.hasError = true;
}
finally {
__disposeResources(env_6);
}
}
async deployStack(stackNode) {
// Counter for totalDeployedStacks, to match 'totalDeployTime' timer on the COMMAND span.
this.ioHost.telemetry?.commandSpan?.incCounter('totalDeployedStacks');
const stack = stackNode.stack;
if (this.options.stackCount !== 1) {
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.bold(stack.displayName));
}
if (!stack.environment) {
// eslint-disable-next-line @stylistic/max-len
throw new toolkit_lib_1.ToolkitError('MissingEnvironment', `Stack ${stack.displayName} does not define an environment, and AWS credentials could not be obtained from standard locations or no region was configured.`);
}
const resourceCount = Object.keys(stack.template.Resources || {}).length;
if (resourceCount === 0) {
// The generated stack has no resources
if (!(await this.deployments.stackExists({ stack }))) {
await this.ioHost.asIoHelper().defaults.warn('%s: stack has no resources, skipping deployment.', chalk_1.default.bold(stack.displayName));
}
else {
await this.ioHost.asIoHelper().defaults.warn('%s: stack has no resources, deleting existing stack.', chalk_1.default.bold(stack.displayName));
await this.stackOperations.destroy({
selector: (0, cloud_assembly_1.selectExact)(stack.hierarchicalId),
force: true,
roleArn: this.options.roleArn,
fromDeploy: true,
});
}
return;
}
// Following are the same semantics we apply with respect to Notification ARNs (dictated by the SDK)
//
// - undefined => cdk ignores it, as if it wasn't supported (allows external management).
// - []: => cdk manages it, and the user wants to wipe it out.
// - ['arn-1'] => cdk manages it, and the user wants to set it to ['arn-1'].
const notificationArns = (!!this.options.notificationArns || !!stack.notificationArns)
? (this.options.notificationArns ?? []).concat(stack.notificationArns ?? [])
: undefined;
for (const notificationArn of notificationArns ?? []) {
if (!(0, util_1.validateSnsTopicArn)(notificationArn)) {
throw new toolkit_lib_1.ToolkitError('InvalidSnsTopicArn', `Notification arn ${notificationArn} is not a valid arn for an SNS topic`);
}
}
const parameterMap = buildParameterMap(this.options.parameters);
// Deploy options that are shared between change set creation and execution
const sharedDeployOptions = {
stack,
deployName: stack.stackName,
roleArn: this.options.roleArn,
toolkitStackName: this.options.toolkitStackName,
reuseAssets: this.options.reuseAssets,
tags: (this.options.tags?.length ? this.options.tags : (0, api_private_1.tagsForStack)(stack)),
forceDeployment: this.options.force,
parameters: Object.assign({}, parameterMap['*'], parameterMap[stack.stackName]),
usePreviousParameters: this.options.usePreviousParameters,
rollback: this.options.rollback,
notificationArns,
extraUserAgent: this.options.extraUserAgent,
assetParallelism: this.options.assetParallelism,
express: this.options.express,
};
// When using change-set method, always create the change set upfront.
// This gives us an accurate diff for approval and avoids creating it twice.
// For non-executing deployments (prepare-change-set), this is the final result.
const prepareResult = (0, deploy_private_1.isChangeSetDeployment)(this.options.deploymentMethod)
? await this.deployments.prepareStack({
...sharedDeployOptions,
deploymentMethod: this.options.deploymentMethod,
willExecuteChangeSet: (0, deploy_private_1.isExecutingChangeSetDeployment)(this.options.deploymentMethod),
})
: undefined;
// Also skip the approval flow when the prepared change set is a no-op —
// there is nothing for the user to approve. Outputs, stack ARN, and
// timings are still emitted via the normal no-op deploy path below.
if (this.options.requireApproval !== cloud_assembly_schema_1.RequireApproval.NEVER && !prepareResult?.noOp) {
const currentTemplate = await this.deployments.readCurrentTemplate(stack);
const formatter = new api_1.DiffFormatter({
templateInfo: {
oldTemplate: currentTemplate,
newTemplate: stack,
changeSet: prepareResult?.changeSet,
},
});
const securityDiff = formatter.formatSecurityDiff();
if (requiresApproval(this.options.requireApproval, securityDiff.permissionChangeType)) {
const hasSecurityChanges = securityDiff.permissionChangeType !== toolkit_lib_1.PermissionChangeType.NONE;
// Bare-fact motivation. The I5060 listener registered in `deploy()` adds
// the `--require-approval` framing for terminal users.
const motivation = hasSecurityChanges
? 'Stack includes security-sensitive updates'
: 'Stack includes updates';
const diffOutput = hasSecurityChanges ? securityDiff.formattedDiff : formatter.formatStackDiff().formattedDiff;
await this.ioHost.asIoHelper().defaults.info(diffOutput);
try {
await askUserConfirmation(this.ioHost, api_private_1.IO.CDK_TOOLKIT_I5060.req(`${motivation}. Do you wish to deploy these changes?`, {
motivation,
concurrency: this.options.concurrency,
permissionChangeType: securityDiff.permissionChangeType,
templateDiffs: formatter.diffs,
}), 'DeployAborted', 'Deployment cancelled');
}
catch (e) {
if (prepareResult?.changeSet?.ChangeSetName) {
await this.deployments.cleanupChangeSet(stack, prepareResult.changeSet.ChangeSetName);
}
throw e;
}
}
}
const stackIndex = this.stackCounter++;
await this.ioHost.asIoHelper().defaults.info(`${chalk_1.default.bold(stack.displayName)}: deploying... [${stackIndex}/${this.options.stackCount}]`);
const startDeployTime = new Date().getTime();
// There is already a startDeployTime constant, but that does not work with telemetry.
// We should integrate the two in the future
const deploySpan = await this.ioHost.asIoHelper().span(messages_1.CLI_PRIVATE_SPAN.DEPLOY).begin({});
deploySpan.incCounter('resources', resourceCount);
this.ioHost.telemetry?.commandSpan?.incCounter('totalDeployedResources', resourceCount);
let error;
let elapsedDeployTime = 0;
try {
// The prepare result is final if the change set was empty (noOp) or
// the deployment method is non-executing (prepare-change-set).
const prepareIsFinal = prepareResult && (prepareResult.noOp || (0, deploy_private_1.isNonExecutingChangeSetDeployment)(this.options.deploymentMethod));
let deployResult = prepareIsFinal ? prepareResult : undefined;
// Start with user config for rollback,
// but it might change if we encounter a failed state.
let rollback = this.options.rollback;
// We limit the loop to 2 iterations max as defensive programming.
// Should not be possible to happen.
let iteration = 0;
while (!deployResult) {
if (++iteration > 2) {
throw new toolkit_lib_1.ToolkitError('DeployLoopUnstable', 'This loop should have stabilized in 2 iterations, but didn\'t. If you are seeing this error, please report it at https://github.com/aws/aws-cdk/issues/new/choose');
}
const r = await this.deployments.deployStack({
...sharedDeployOptions,
// On the first iteration, execute the prepared change set.
// On retries (after rollback), create a new change set since the old one is gone.
deploymentMethod: iteration === 1 && (0, deploy_private_1.isExecutingChangeSetDeployment)(this.options.deploymentMethod)
? (0, deploy_private_1.toExecuteChangeSetDeployment)(this.options.deploymentMethod)
: this.options.deploymentMethod,
rollback,
});
switch (r.type) {
case 'did-deploy-stack':
deployResult = r;
break;
case 'failpaused-need-rollback-first': {
const motivation = r.reason === 'replacement'
? `Stack is in a paused fail state (${r.status}) and change includes a replacement which cannot be deployed with "--no-rollback"`
: `Stack is in a paused fail state (${r.status}) and command line arguments do not include "--no-rollback"`;
if (this.options.force) {
await this.ioHost.asIoHelper().defaults.warn(`${motivation}. Rolling back first (--force).`);
}
else {
await askUserConfirmation(this.ioHost, api_private_1.IO.CDK_TOOLKIT_I5050.req(`${motivation}. Roll back first and then proceed with deployment`, {
motivation,
concurrency: this.options.concurrency,
}), 'RollbackAborted', 'Rollback cancelled');
}
// Perform a rollback
await this.stackOperations.rollback({
selector: (0, cloud_assembly_1.selectExact)(stack.hierarchicalId),
toolkitStackName: this.options.toolkitStackName,
force: this.options.force,
});
// Go around through the 'while' loop again but switch rollback to true.
rollback = true;
break;
}
case 'replacement-requires-rollback': {
const motivation = 'Change includes a replacement which cannot be deployed with "--no-rollback"';
if (this.options.force) {
await this.ioHost.asIoHelper().defaults.warn(`${motivation}. Proceeding with deployment with rollback enabled (--force).`);
}
else {
await askUserConfirmation(this.ioHost, api_private_1.IO.CDK_TOOLKIT_I5050.req(`${motivation}. Perform a deployment with rollback enabled`, {
concurrency: this.options.concurrency,
motivation,
}), 'ReplacementRollbackAborted', 'Rollback cancelled');
}
// Go around through the 'while' loop again but switch rollback to true.
rollback = true;
break;
}
default:
throw new toolkit_lib_1.ToolkitError('UnexpectedDeployResult', `Unexpected result type from deployStack: ${JSON.stringify(r)}. If you are seeing this error, please report it at https://github.com/aws/aws-cdk/issues/new/choose`);
}
}
const message = deployResult.noOp
? '✅ %s (no changes)'
: '✅ %s';
await this.ioHost.asIoHelper().defaults.info(chalk_1.default.green('\n' + message), stack.displayName);
elapsedDeployTime = new Date().getTime() - startDeployTime;
await this.ioHost.asIoHelper().defaults.info(`\n✨ Deployment time: ${(0, util_1.formatTime)(elapsedDeployTime)}s\n`);
if (this.options.express) {
const warning = (0, api_private_1.formatExpressStabilizationWarning)(deployResult.stabilizingResources, 'deploy');
if (warning) {
await this.ioHost.asIoHelper().notify(api_private_1.IO.CDK_TOOLKIT_W5902.msg(warning));
}
}
if (Object.keys(deployResult.outputs).length > 0) {
await this.ioHost.asIoHelper().defaults.info('Outputs:');
this.stackOutputs[stack.stackName] = deployResult.outputs;
}
for (const name of Object.keys(deployResult.outputs).sort()) {
const value = deployResult.outputs[name];
await this.ioHost.asIoHelper().defaults.info(`${chalk_1.default.cyan(stack.id)}.${chalk_1.default.cyan(name)} = ${chalk_1.default.underline(chalk_1.default.cyan(value))}`);
}
await this.ioHost.asIoHelper().defaults.info('Stack ARN:');
await this.ioHost.asIoHelper().defaults.result(deployResult.stackArn);
}
catch (e) {
// It has to be exactly this string because an integration test tests for
// "bold(stackname) failed: ResourceNotReady: <error>"
const code = toolkit_lib_1.ToolkitError.isToolkitError(e) ? e.name : 'DeployStackFailed'; // Formerly 'DeployFailed'
const newMessage = [`❌ ${chalk_1.default.bold(stack.stackName)} failed:`, ...(e.name ? [`${e.name}:`] : []), e.message].join(' ');
const wrappedError = new toolkit_lib_1.ToolkitError(code, newMessage);
error = {
name: (0, error_1.cdkCliErrorName)(wrappedError),
};
throw wrappedError;
}
finally {
await deploySpan.end({ error });
if (this.options.cloudWatchLogMonitor) {
const foundLogGroupsResult = await (0, api_1.findCloudWatchLogGroups)(this.options.sdkProvider, (0, api_private_1.asIoHelper)(this.ioHost, 'deploy'), stack);
this.options.cloudWatchLogMonitor.addLogGroups(foundLogGroupsResult.env, foundLogGroupsResult.sdk, foundLogGroupsResult.logGroupNames);
}
}
}
async writeOutputs(outputsFile) {
fs.ensureFileSync(outputsFile);
await fs.writeJson(outputsFile, this.stackOutputs, {
spaces: 2,
encoding: 'utf8',
});
}
}
/**
* Determine if manual approval is required or not. Requires approval for
* - RequireApproval.ANYCHANGE
* - RequireApproval.BROADENING and the changes are indeed broadening permissions
*/
function requiresApproval(requireApproval, permissionChangeType) {
return requireApproval === cloud_assembly_schema_1.RequireApproval.ANYCHANGE ||
requireApproval === cloud_assembly_schema_1.RequireApproval.BROADENING && permissionChangeType === toolkit_lib_1.PermissionChangeType.BROADENING;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLXRvb2xraXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjZGstdG9vbGtpdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbXBFQSxrREFlQztBQWxxRUQsNkNBQXlDO0FBQ3pDLGdEQUFrQztBQUNsQyx5Q0FBbUM7QUFFbkMsbUVBQXFEO0FBQ3JELDBFQUFpRTtBQUVqRSxzREFBK0Y7QUFDL0Ysa0RBQTBCO0FBQzFCLG1EQUFxQztBQUNyQyxvREFBNkQ7QUFDN0QsNkNBQStCO0FBQy9CLHVDQUF3RDtBQUV4RCw2REFBc0Q7QUFFdEQsdURBQWdLO0FBRWhLLGdDQVdnQjtBQUdoQixnREFBZ0Q7QUFFaEQsMERBQXlKO0FBQ3pKLDBEQUErSjtBQUUvSiw4Q0FBNEU7QUFFNUUsK0NBQTJEO0FBQzNELHlEQUEwRDtBQUUxRCxpREFlNkI7QUFFN0Isb0NBQWtHO0FBQ2xHLGtDQVFpQjtBQUNqQixxRUFBb0U7QUFDcEUsNkNBQW9EO0FBRXBELG1EQUF3RDtBQUV4RCw2REFBOEQ7QUFFOUQsNkVBQTZFO0FBQzdFLDRHQUE0RztBQUM1RyxNQUFNLE1BQU0sR0FBNkIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBRTVEOzs7O0dBSUc7QUFDSCxNQUFNLFdBQVcsR0FBRyxDQUFDLG1CQUFNLENBQUMsR0FBRyxFQUFFLG1CQUFNLENBQUMsT0FBTyxFQUFFLG1CQUFNLENBQUMsTUFBTSxFQUFFLG1CQUFNLENBQUMsTUFBTSxFQUFFLG1CQUFNLENBQUMsVUFBVSxDQUFVLENBQUM7QUFHM0c7O0dBRUc7QUFDSCxTQUFTLFdBQVcsQ0FBQyxLQUFnQjtJQUNuQyxPQUFRLFdBQWlDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzVELENBQUM7QUF5REQ7O0dBRUc7QUFD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RUFDeEIsb0JBQW9CLENBQUMsR0FBRyxFQUN4QixvQkFBb0IsQ0FBQyxhQUFhLENBQ25DLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsWUFBWSxDQUFDLFdBQW1CO1FBQzNDLEVBQUUsQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDL0IsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sRUFBRSxDQUFDO1lBQ1QsUUFBUSxFQUFFLE1BQU07U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsZ0JBQWdCLENBQUMsZUFBZ0MsRUFBRSxvQkFBMEM7SUFDcEcsT0FBTyxlQUFlLEtBQUssdUNBQWUsQ0FBQyxTQUFTO1FBQ2xELGVBQWUsS0FBSyx1Q0FBZSxDQUFDLFVBQVUsSUFBSSxvQkFBb0IsS0FBSyxrQ0FBb0IsQ0FBQyxVQUFVLENBQUM7QUFDL0csQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBmb3JtYXQgfSBmcm9tICdub2RlOnV0aWwnO1xuaW1wb3J0IHR5cGUgeyBJTWFuaWZlc3RFbnRyeSB9IGZyb20gJ0Bhd3MtY2RrL2Nkay1hc3NldHMtbGliJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LWFwaSc7XG5pbXBvcnQgeyBSZXF1aXJlQXBwcm92YWwgfSBmcm9tICdAYXdzLWNkay9jbG91ZC1hc3NlbWJseS1zY2hlbWEnO1xuaW1wb3J0IHR5cGUgeyBDb25maXJtYXRpb25SZXF1ZXN0LCBEZXBsb3ltZW50TWV0aG9kLCBEaWFnbm9zZU9wdGlvbnMsIFB1Ymxpc2hBc3NldHNPcHRpb25zLCBTdGFja1NlbGVjdG9yLCBUb29sa2l0QWN0aW9uLCBUb29sa2l0T3B0aW9ucywgVW5zdGFibGVGZWF0dXJlLCBWYWxpZGF0ZU9wdGlvbnMgfSBmcm9tICdAYXdzLWNkay90b29sa2l0LWxpYic7XG5pbXBvcnQgeyBQZXJtaXNzaW9uQ2hhbmdlVHlwZSwgVG9vbGtpdCwgVG9vbGtpdEVycm9yLCBBYm9ydEVycm9yIH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCAqIGFzIGNob2tpZGFyIGZyb20gJ2Nob2tpZGFyJztcbmltcG9ydCB7IHR5cGUgRXZlbnROYW1lLCBFVkVOVFMgfSBmcm9tICdjaG9raWRhci9oYW5kbGVyLmpzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IENsaUlvSG9zdCwgc3VwcHJlc3NNZXNzYWdlcyB9IGZyb20gJy4vaW8taG9zdCc7XG5pbXBvcnQgdHlwZSB7IENvbmZpZ3VyYXRpb24gfSBmcm9tICcuL3VzZXItY29uZmlndXJhdGlvbic7XG5pbXBvcnQgeyBQUk9KRUNUX0NPTkZJRyB9IGZyb20gJy4vdXNlci1jb25maWd1cmF0aW9uJztcbmltcG9ydCB0eXBlIHsgQWN0aW9uTGVzc1JlcXVlc3QsIElNZXNzYWdlU3BhbiwgSW9IZWxwZXIgfSBmcm9tICcuLi8uLi9saWIvYXBpLXByaXZhdGUnO1xuaW1wb3J0IHsgYXNJb0hlbHBlciwgY2ZuQXBpLCBjcmVhdGVJZ25vcmVNYXRjaGVyLCBmb3JtYXRFeHByZXNzU3RhYmlsaXphdGlvbldhcm5pbmcsIElPLCB0YWdzRm9yU3RhY2ssIHRocm93SWZWYWxpZGF0aW9uRmFpbHVyZXMgfSBmcm9tICcuLi8uLi9saWIvYXBpLXByaXZhdGUnO1xuaW1wb3J0IHR5cGUgeyBBc3NldEJ1aWxkTm9kZSwgQXNzZXRQdWJsaXNoTm9kZSwgQ29uY3VycmVuY3ksIE1hcmtlck5vZGUsIFN0YWNrTm9kZSwgV29ya0dyYXBoLCBXb3JrR3JhcGhBY3Rpb25zIH0gZnJvbSAnLi4vYXBpJztcbmltcG9ydCB7XG4gIENsb3VkV2F0Y2hMb2dFdmVudE1vbml0b3IsXG4gIERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FLFxuICBEaWZmRm9ybWF0dGVyLFxuICBmaW5kQ2xvdWRXYXRjaExvZ0dyb3VwcyxcbiAgR2FyYmFnZUNvbGxlY3RvcixcbiAgcmVtb3ZlTm9uSW1wb3J0UmVzb3VyY2VzLFxuICBSZXNvdXJjZUltcG9ydGVyLFxuICBSZXNvdXJjZU1pZ3JhdG9yLFxuICBTdGFja1NlbGVjdGlvblN0cmF0ZWd5LFxuICBXb3JrR3JhcGhCdWlsZGVyLFxufSBmcm9tICcuLi9hcGknO1xuaW1wb3J0IHR5cGUgeyBTZGtQcm92aWRlciB9IGZyb20gJy4uL2FwaS9hd3MtYXV0aCc7XG5pbXBvcnQgdHlwZSB7IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyB9IGZyb20gJy4uL2FwaS9ib290c3RyYXAnO1xuaW1wb3J0IHsgQm9vdHN0cmFwcGVyIH0gZnJvbSAnLi4vYXBpL2Jvb3RzdHJhcCc7XG5pbXBvcnQgdHlwZSB7IFN0YWNrQXNzZW1ibHkgfSBmcm9tICcuLi9hcGkvY2xvdWQtYXNzZW1ibHknO1xuaW1wb3J0IHsgQUxMX1NUQUNLUywgRXhwYW5kU3RhY2tTZWxlY3Rpb24sIG11c3RNYXRjaCwgc2VsZWN0QWxsVG9wTGV2ZWwsIHNlbGVjdEV4YWN0LCBzZWxlY3RXaXRoVXBzdHJlYW0sIFN0YWNrQ29sbGVjdGlvbiB9IGZyb20gJy4uL2FwaS9jbG91ZC1hc3NlbWJseSc7XG5pbXBvcnQgeyBpc0NoYW5nZVNldERlcGxveW1lbnQsIGlzRXhlY3V0aW5nQ2hhbmdlU2V0RGVwbG95bWVudCwgaXNOb25FeGVjdXRpbmdDaGFuZ2VTZXREZXBsb3ltZW50LCB0b0V4ZWN1dGVDaGFuZ2VTZXREZXBsb3ltZW50IH0gZnJvbSAnLi4vYXBpL2RlcGxveS1wcml2YXRlJztcbmltcG9ydCB0eXBlIHsgRGVwbG95bWVudHMsIFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdCB9IGZyb20gJy4uL2FwaS9kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBtYXBwaW5nc0J5RW52aXJvbm1lbnQsIHBhcnNlTWFwcGluZ0dyb3VwcyB9IGZyb20gJy4uL2FwaS9yZWZhY3Rvcic7XG5pbXBvcnQgeyB0eXBlIFRhZyB9IGZyb20gJy4uL2FwaS90YWdzJztcbmltcG9ydCB7IFN0YWNrQWN0aXZpdHlQcm9ncmVzcyB9IGZyb20gJy4uL2NvbW1hbmRzL2RlcGxveSc7XG5pbXBvcnQgeyBmb3JtYXRTdGFja0xpc3QgfSBmcm9tICcuLi9jb21tYW5kcy9saXN0LXN0YWNrcyc7XG5pbXBvcnQgdHlwZSB7IEZyb21TY2FuLCBHZW5lcmF0ZVRlbXBsYXRlT3V0cHV0IH0gZnJvbSAnLi4vY29tbWFuZHMvbWlncmF0ZSc7XG5pbXBvcnQge1xuICBhcHBlbmRXYXJuaW5nc1RvUmVhZG1lLFxuICBidWlsZENmbkNsaWVudCxcbiAgYnVpbGRHZW5lcmF0ZWRUZW1wbGF0ZU91dHB1dCxcbiAgQ2ZuVGVtcGxhdGVHZW5lcmF0b3JQcm92aWRlcixcbiAgZ2VuZXJhdGVDZGtBcHAsXG4gIGdlbmVyYXRlU3RhY2ssXG4gIGdlbmVyYXRlVGVtcGxhdGUsXG4gIGlzVGhlcmVBV2FybmluZyxcbiAgcGFyc2VTb3VyY2VPcHRpb25zLFxuICByZWFkRnJvbVBhdGgsXG4gIHJlYWRGcm9tU3RhY2ssXG4gIHNldEVudmlyb25tZW50LFxuICBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMsXG4gIHdyaXRlTWlncmF0ZUpzb25GaWxlLFxufSBmcm9tICcuLi9jb21tYW5kcy9taWdyYXRlJztcbmltcG9ydCB0eXBlIHsgQ2xvdWRFeGVjdXRhYmxlIH0gZnJvbSAnLi4vY3hhcHAnO1xuaW1wb3J0IHsgZW52aXJvbm1lbnRzRnJvbURlc2NyaXB0b3JzLCBnbG9iRW52aXJvbm1lbnRzRnJvbVN0YWNrcywgbG9va3NMaWtlR2xvYiB9IGZyb20gJy4uL2N4YXBwJztcbmltcG9ydCB7XG4gIGRlc2VyaWFsaXplU3RydWN0dXJlLFxuICBmb3JtYXRFcnJvck1lc3NhZ2UsXG4gIGZvcm1hdFRpbWUsXG4gIG9ic2N1cmVUZW1wbGF0ZSxcbiAgcGFydGl0aW9uLFxuICBzZXJpYWxpemVTdHJ1Y3R1cmUsXG4gIHZhbGlkYXRlU25zVG9waWNBcm4sXG59IGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHsgY2FuQ29sbGVjdFRlbGVtZXRyeSB9IGZyb20gJy4vdGVsZW1ldHJ5L2NvbGxlY3QtdGVsZW1ldHJ5JztcbmltcG9ydCB7IGNka0NsaUVycm9yTmFtZSB9IGZyb20gJy4vdGVsZW1ldHJ5L2Vycm9yJztcbmltcG9ydCB0eXBlIHsgRXZlbnRSZXN1bHQgfSBmcm9tICcuL3RlbGVtZXRyeS9tZXNzYWdlcyc7XG5pbXBvcnQgeyBDTElfUFJJVkFURV9TUEFOIH0gZnJvbSAnLi90ZWxlbWV0cnkvbWVzc2FnZXMnO1xuaW1wb3J0IHR5cGUgeyBFcnJvckRldGFpbHMgfSBmcm9tICcuL3RlbGVtZXRyeS9zY2hlbWEnO1xuaW1wb3J0IHsgRmxhZ09wZXJhdGlvbnMgfSBmcm9tICcuLi9jb21tYW5kcy9mbGFncy9vcGVyYXRpb25zJztcblxuLy8gTXVzdCB1c2UgYSByZXF1aXJlKCkgb3RoZXJ3aXNlIGVzYnVpbGQgY29tcGxhaW5zIGFib3V0IGNhbGxpbmcgYSBuYW1lc3BhY2Vcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLEB0eXBlc2NyaXB0LWVzbGludC9jb25zaXN0ZW50LXR5cGUtaW1wb3J0c1xuY29uc3QgcExpbWl0OiB0eXBlb2YgaW1wb3J0KCdwLWxpbWl0JykgPSByZXF1aXJlKCdwLWxpbWl0Jyk7XG5cbi8qKlxuICogRmlsZSBldmVudHMgdGhhdCB3ZSBjYXJlIGFib3V0IGZyb20gY2hva2lkYXIuXG4gKiBJbiBjaG9raWRhciB2NCwgRXZlbnROYW1lIGluY2x1ZGVzIGFkZGl0aW9uYWwgZXZlbnRzIGxpa2UgJ2Vycm9yJywgJ3JhdycsICdyZWFkeScsICdhbGwnXG4gKiB0aGF0IHdlIG5lZWQgdG8gZmlsdGVyIG91dCBpbiB0aGUgJ2FsbCcgaGFuZGxlci5cbiAqL1xuY29uc3QgRklMRV9FVkVOVFMgPSBbRVZFTlRTLkFERCwgRVZFTlRTLkFERF9ESVIsIEVWRU5UUy5DSEFOR0UsIEVWRU5UUy5VTkxJTkssIEVWRU5UUy5VTkxJTktfRElSXSBhcyBjb25zdDtcbnR5cGUgRmlsZUV2ZW50ID0gdHlwZW9mIEZJTEVfRVZFTlRTW251bWJlcl07XG5cbi8qKlxuICogVHlwZSBndWFyZCB0byBjaGVjayBpZiBhbiBldmVudCBpcyBhIGZpbGUgZXZlbnQgd2Ugc2hvdWxkIHByb2Nlc3MuXG4gKi9cbmZ1bmN0aW9uIGlzRmlsZUV2ZW50KGV2ZW50OiBFdmVudE5hbWUpOiBldmVudCBpcyBGaWxlRXZlbnQge1xuICByZXR1cm4gKEZJTEVfRVZFTlRTIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyhldmVudCk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2RrVG9vbGtpdFByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBDbG91ZCBFeGVjdXRhYmxlXG4gICAqL1xuICBjbG91ZEV4ZWN1dGFibGU6IENsb3VkRXhlY3V0YWJsZTtcblxuICAvKipcbiAgICogVGhlIHByb3Zpc2lvbmluZyBlbmdpbmUgdXNlZCB0byBhcHBseSBjaGFuZ2VzIHRvIHRoZSBjbG91ZFxuICAgKi9cbiAgZGVwbG95bWVudHM6IERlcGxveW1lbnRzO1xuXG4gIC8qKlxuICAgKiBUaGUgQ2xpSW9Ib3N0IHRoYXQncyB1c2VkIGZvciBJL08gb3BlcmF0aW9uc1xuICAgKi9cbiAgaW9Ib3N0PzogQ2xpSW9Ib3N0O1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSB0b29sa2l0IHN0YWNrIHRvIHVzZS9kZXBsb3lcbiAgICpcbiAgICogQGRlZmF1bHQgQ0RLVG9vbGtpdFxuICAgKi9cbiAgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBiZSB2ZXJib3NlXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICB2ZXJib3NlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRG9uJ3Qgc3RvcCBvbiBlcnJvciBtZXRhZGF0YVxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgaWdub3JlRXJyb3JzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVHJlYXQgd2FybmluZ3MgaW4gbWV0YWRhdGEgYXMgZXJyb3JzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBzdHJpY3Q/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uIChzZXR0aW5ncyBhbmQgY29udGV4dClcbiAgICovXG4gIGNvbmZpZ3VyYXRpb246IENvbmZpZ3VyYXRpb247XG5cbiAgLyoqXG4gICAqIEFXUyBvYmplY3QgKHVzZWQgYnkgc3ludGhlc2l6ZXIgYW5kIGNvbnRleHRwcm92aWRlcilcbiAgICovXG4gIHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcbn1cblxuLyoqXG4gKiBXaGVuIHRvIGJ1aWxkIGFzc2V0c1xuICovXG5leHBvcnQgZW51bSBBc3NldEJ1aWxkVGltZSB7XG4gIC8qKlxuICAgKiBCdWlsZCBhbGwgYXNzZXRzIGJlZm9yZSBkZXBsb3lpbmcgdGhlIGZpcnN0IHN0YWNrXG4gICAqXG4gICAqIFRoaXMgaXMgaW50ZW5kZWQgZm9yIGV4cGVuc2l2ZSBEb2NrZXIgaW1hZ2UgYnVpbGRzOyBzbyB0aGF0IGlmIHRoZSBEb2NrZXIgaW1hZ2UgYnVpbGRcbiAgICogZmFpbHMsIG5vIHN0YWNrcyBhcmUgdW5uZWNlc3NhcmlseSBkZXBsb3llZCAod2l0aCB0aGUgYXR0ZW5kYW50IHdhaXQgdGltZSkuXG4gICAqL1xuICBBTExfQkVGT1JFX0RFUExPWSA9ICdhbGwtYmVmb3JlLWRlcGxveScsXG5cbiAgLyoqXG4gICAqIEJ1aWxkIGFzc2V0cyBqdXN0LWluLXRpbWUsIGJlZm9yZSBwdWJsaXNoaW5nXG4gICAqL1xuICBKVVNUX0lOX1RJTUUgPSAnanVzdC1pbi10aW1lJyxcbn1cblxuLyoqXG4gKiBDdXN0b20gaW1wbGVtZW50YXRpb24gb2YgdGhlIHB1YmxpYyBUb29sa2l0IHRvIGludGVncmF0ZSB3aXRoIHRoZSBsZWdhY3kgQ2RrVG9vbGtpdFxuICpcbiAqIFRoaXMgb3ZlcndyaXRlcyBob3cgYW4gc2RrUHJvdmlkZXIgaXMgYWNxdWlyZWRcbiAqIGluIGZhdm9yIG9mIHRoZSBvbmUgcHJvdmlkZWQgZGlyZWN0bHkgdG8gQ2RrVG9vbGtpdC5cbiAqL1xuY2xhc3MgSW50ZXJuYWxUb29sa2l0IGV4dGVuZHMgVG9vbGtpdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Nka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlciwgb3B0aW9uczogT21pdDxUb29sa2l0T3B0aW9ucywgJ3Nka0NvbmZpZyc+KSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG4gICAgdGhpcy5fc2RrUHJvdmlkZXIgPSBzZGtQcm92aWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBY2Nlc3MgdG8gdGhlIEFXUyBTREtcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgc2RrUHJvdmlkZXIoX2FjdGlvbjogVG9vbGtpdEFjdGlvbik6IFByb21pc2U8U2RrUHJvdmlkZXI+IHtcbiAgICByZXR1cm4gdGhpcy5fc2RrUHJvdmlkZXI7XG4gIH1cbn1cblxuLyoqXG4gKiBUb29sa2l0IGxvZ2ljXG4gKlxuICogVGhlIHRvb2xraXQgcnVucyB0aGUgYGNsb3VkRXhlY3V0YWJsZWAgdG8gb2J0YWluIGEgY2xvdWQgYXNzZW1ibHkgYW5kXG4gKiBkZXBsb3lzIGFwcGxpZXMgdGhlbSB0byBgY2xvdWRGb3JtYXRpb25gLlxuICovXG5leHBvcnQgY2xhc3MgQ2RrVG9vbGtpdCB7XG4gIHByaXZhdGUgaW9Ib3N0OiBDbGlJb0hvc3Q7XG4gIHByaXZhdGUgdG9vbGtpdFN0YWNrTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHRvb2xraXQ6IEludGVybmFsVG9vbGtpdDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBDZGtUb29sa2l0UHJvcHMpIHtcbiAgICB0aGlzLmlvSG9zdCA9IHByb3BzLmlvSG9zdCA/PyBDbGlJb0hvc3QuaW5zdGFuY2UoKTtcbiAgICB0aGlzLnRvb2xraXRTdGFja05hbWUgPSBwcm9wcy50b29sa2l0U3RhY2tOYW1lID8/IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FO1xuXG4gICAgLy8gV2UgZG9uJ3QgaGF2ZSB0aGUgdG9vbGtpdCBjaGVjayB1bnN0YWJsZSBmZWF0dXJlcy4gSW5zdGVhZCwgdGhlIGVycm9yXG4gICAgLy8gbWVzc2FnZXMgdGhlIENMSSBnaXZlIGFyZSBzbGlnaHRseSBkaWZmZXJlbnQsIGFuZCBzbyB0aGV5IG5lZWQgdG8gYmUgY2hlY2tlZFxuICAgIC8vIHNlcGFyYXRlbHkuIEluc3RlYWQsIHRoZSBUb29sa2l0IHdlIHVzZSBoYXMgYWxsIHVuc3RhYmxlIGZlYXR1cmVzIGF1dG9tYXRpY2FsbHlcbiAgICAvLyBlbmFibGVkLlxuICAgIGNvbnN0IGlQcm9taXNlVW5zdGFibGVuZXNzSXNDaGVja2VkQnlUaGVDbGk6IFJlY29yZDxVbnN0YWJsZUZlYXR1cmUsIHRydWU+ID0ge1xuICAgICAgJ3B1Ymxpc2gtYXNzZXRzJzogdHJ1ZSxcbiAgICAgICdkaWFnbm9zZSc6IHRydWUsXG4gICAgICAnZmxhZ3MnOiB0cnVlLFxuICAgICAgJ29ycGhhbic6IHRydWUsXG4gICAgICAncmVmYWN0b3InOiB0cnVlLFxuICAgICAgJ3ZhbGlkYXRlJzogdHJ1ZSxcbiAgICB9O1xuXG4gICAgdGhpcy50b29sa2l0ID0gbmV3IEludGVybmFsVG9vbGtpdChwcm9wcy5zZGtQcm92aWRlciwge1xuICAgICAgYXNzZW1ibHlGYWlsdXJlQXQ6IHRoaXMudmFsaWRhdGVNZXRhZGF0YUZhaWxBdCgpLFxuICAgICAgY29sb3I6IHRydWUsXG4gICAgICBlbW9qaXM6IHRydWUsXG4gICAgICBpb0hvc3Q6IHRoaXMuaW9Ib3N0LFxuICAgICAgdG9vbGtpdFN0YWNrTmFtZTogdGhpcy50b29sa2l0U3RhY2tOYW1lLFxuICAgICAgdW5zdGFibGVGZWF0dXJlczogT2JqZWN0LmtleXMoaVByb21pc2VVbnN0YWJsZW5lc3NJc0NoZWNrZWRCeVRoZUNsaSkgYXMgVW5zdGFibGVGZWF0dXJlW10sXG4gICAgfSk7XG4gIH1cblxuICBAc3VwcHJlc3NNZXNzYWdlcyhcbiAgICBJTy5DREtfVE9PTEtJVF9JMTAwMSwgLy8gU3RhcnRpbmcgU3ludGhlc2lzICh0cmFjZSlcbiAgICBJTy5DREtfVE9PTEtJVF9JMTAwMCwgLy8g4pyoIFN5bnRoZXNpcyB0aW1lIChpbmZvKVxuICApXG4gIHB1YmxpYyBhc3luYyBtZXRhZGF0YShzdGFja05hbWU6IHN0cmluZywganNvbjogYm9vbGVhbikge1xuICAgIHVzaW5nIF9mb3JtYXR0ZXIgPSB0aGlzLmlvSG9zdC5vbmNlKFxuICAgICAgSU8uQ0RLX1RPT0xLSVRfSTI5MDEsXG4gICAgICAobXNnKSA9PiAoe1xuICAgICAgICBhY3Rpb246ICdtZXRhZGF0YScsXG4gICAgICAgIG1lc3NhZ2U6IHNlcmlhbGl6ZVN0cnVjdHVyZShtc2cuZGF0YS5zdGFja3NbMF0/Lm1ldGFkYXRhID8/IHt9LCBqc29uKSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBhd2FpdCB0aGlzLnRvb2xraXQubGlzdCh0aGlzLnByb3BzLmNsb3VkRXhlY3V0YWJsZSwge1xuICAgICAgc3RhY2tzOiB7XG4gICAgICAgIHBhdHRlcm5zOiBbc3RhY2tOYW1lXSxcbiAgICAgICAgc3RyYXRlZ3k6IFN0YWNrU2VsZWN0aW9uU3RyYXRlZ3kuUEFUVEVSTl9NVVNUX01BVENIX1NJTkdMRSxcbiAgICAgICAgZXhwYW5kOiBFeHBhbmRTdGFja1NlbGVjdGlvbi5OT05FLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBhY2tub3dsZWRnZShub3RpY2VJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgaXNzdWVOdW1iZXIgPSBOdW1iZXIobm90aWNlSWQpO1xuICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihpc3N1ZU51bWJlcikpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoXG4gICAgICAgICdJbnZhbGlkQWNrbm93bGVkZ2VtZW50SWQnLFxuICAgICAgICBgSW52YWxpZCBub3RpY2UgSUQgJyR7bm90aWNlSWR9JzogJ2NkayBhY2tub3dsZWRnZScgb25seSBhY2NlcHRzIG51bWVyaWMgbm90aWNlIElEcyAoZS5nLiAnY2RrIGFja25vd2xlZGdlIDEyMzQ1JykuIGAgK1xuICAgICAgICAnU2NvcGVkIGNvbnN0cnVjdCB3YXJuaW5ncyBzdWNoIGFzIFxcJ0Bhd3MtY2RrL2F3cy1lY3M6bWluSGVhbHRoeVBlcmNlbnRcXCcgYXJlIGFja25vd2xlZGdlZCBpbiBjb2RlIHdpdGggJyArXG4gICAgICAgICdBbm5vdGF0aW9ucy5vZihzY29wZSkuYWNrbm93bGVkZ2VXYXJuaW5nKFxcJzxpZD5cXCcpLicsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGFja3MgPSBuZXcgU2V0KHRoaXMucHJvcHMuY29uZmlndXJhdGlvbi5jb250ZXh0LmdldCgnYWNrbm93bGVkZ2VkLWlzc3VlLW51bWJlcnMnKSA/PyBbXSk7XG4gICAgYWNrcy5hZGQoaXNzdWVOdW1iZXIpO1xuICAgIHRoaXMucHJvcHMuY29uZmlndXJhdGlvbi5jb250ZXh0LnNldCgnYWNrbm93bGVkZ2VkLWlzc3VlLW51bWJlcnMnLCBBcnJheS5mcm9tKGFja3MpKTtcbiAgICBhd2FpdCB0aGlzLnByb3BzLmNvbmZpZ3VyYXRpb24uc2F2ZUNvbnRleHQoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjbGlUZWxlbWV0cnlTdGF0dXMoYXJnczogYW55KSB7XG4gICAgY29uc3QgY2FuQ29sbGVjdCA9IGNhbkNvbGxlY3RUZWxlbWV0cnkoYXJncywgdGhpcy5wcm9wcy5jb25maWd1cmF0aW9uLmNvbnRleHQpO1xuICAgIGlmIChjYW5Db2xsZWN0KSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbygnQ0xJIFRlbGVtZXRyeSBpcyBlbmFibGVkLiBTZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay92Mi9ndWlkZS9jbGktdGVsZW1ldHJ5Lmh0bWwgZm9yIHdheXMgdG8gZGlzYWJsZS4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oJ0NMSSBUZWxlbWV0cnkgaXMgZGlzYWJsZWQuIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL3YyL2d1aWRlL2NsaS10ZWxlbWV0cnkuaHRtbCBmb3Igd2F5cyB0byBlbmFibGUuJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGNsaVRlbGVtZXRyeShlbmFibGU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnByb3BzLmNvbmZpZ3VyYXRpb24uY29udGV4dC5zZXQoJ2NsaS10ZWxlbWV0cnknLCBlbmFibGUpO1xuICAgIGF3YWl0IHRoaXMucHJvcHMuY29uZmlndXJhdGlvbi5zYXZlQ29udGV4dCgpO1xuICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKGBUZWxlbWV0cnkgJHtlbmFibGUgPyAnZW5hYmxlZCcgOiAnZGlzYWJsZWQnfWApO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGRpZmYob3B0aW9uczogRGlmZk9wdGlvbnMpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGFzc2VtYmx5ID0gYXdhaXQgdGhpcy5hc3NlbWJseSgpO1xuICAgIGNvbnN0IHN0YWNrcyA9IGF3YWl0IHRoaXMuc2VsZWN0VG9wTGV2ZWxPck1hdGNoaW5nU3RhY2tzKGFzc2VtYmx5LCBvcHRpb25zLnN0YWNrTmFtZXMsIG9wdGlvbnMuZXhjbHVzaXZlbHkpO1xuICAgIGF3YWl0IHRoaXMudmFsaWRhdGVTdGFja3MoYXNzZW1ibHksIHN0YWNrcyk7XG5cbiAgICBjb25zdCBzdHJpY3QgPSAhIW9wdGlvbnMuc3RyaWN0O1xuICAgIGNvbnN0IGNvbnRleHRMaW5lcyA9IG9wdGlvbnMuY29udGV4dExpbmVzIHx8IDM7XG4gICAgY29uc3QgcXVpZXQgPSBvcHRpb25zLnF1aWV0IHx8IGZhbHNlO1xuXG4gICAgbGV0IGRpZmZzID0gMDtcbiAgICBjb25zdCBwYXJhbWV0ZXJNYXAgPSBidWlsZFBhcmFtZXRlck1hcChvcHRpb25zLnBhcmFtZXRlcnMpO1xuXG4gICAgaWYgKG9wdGlvbnMudGVtcGxhdGVQYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIENvbXBhcmUgc2luZ2xlIHN0YWNrIGFnYWluc3QgZml4ZWQgdGVtcGxhdGVcbiAgICAgIGlmIChzdGFja3Muc3RhY2tDb3VudCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgICAgICdTaW5nbGVTdGFja1JlcXVpcmVkJyxcbiAgICAgICAgICAnQ2FuIG9ubHkgc2VsZWN0IG9uZSBzdGFjayB3aGVuIGNvbXBhcmluZyB0byBmaXhlZCB0ZW1wbGF0ZS4gVXNlIC0tZXhjbHVzaXZlbHkgdG8gYXZvaWQgc2VsZWN0aW5nIG11bHRpcGxlIHN0YWNrcy4nLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAoIShhd2FpdCBmcy5wYXRoRXhpc3RzKG9wdGlvbnMudGVtcGxhdGVQYXRoKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignVGVtcGxhdGVOb3RGb3VuZCcsIGBUaGVyZSBpcyBubyBmaWxlIGF0ICR7b3B0aW9ucy50ZW1wbGF0ZVBhdGh9YCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLmltcG9ydEV4aXN0aW5nUmVzb3VyY2VzKSB7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoXG4gICAgICAgICAgJ0ltcG9ydFdpdGhUZW1wbGF0ZVBhdGgnLFxuICAgICAgICAgICdDYW4gb25seSB1c2UgLS1pbXBvcnQtZXhpc3RpbmctcmVzb3VyY2VzIGZsYWcgd2hlbiBjb21wYXJpbmcgYWdhaW5zdCBkZXBsb3llZCBzdGFja3MuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBkZXNlcmlhbGl6ZVN0cnVjdHVyZShhd2FpdCBmcy5yZWFkRmlsZShvcHRpb25zLnRlbXBsYXRlUGF0aCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KSk7XG4gICAgICBjb25zdCBmb3JtYXR0ZXIgPSBuZXcgRGlmZkZvcm1hdHRlcih7XG4gICAgICAgIHRlbXBsYXRlSW5mbzoge1xuICAgICAgICAgIG9sZFRlbXBsYXRlOiB0ZW1wbGF0ZSxcbiAgICAgICAgICBuZXdUZW1wbGF0ZTogc3RhY2tzLmZpcnN0U3RhY2ssXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKG9wdGlvbnMuc2VjdXJpdHlPbmx5KSB7XG4gICAgICAgIGNvbnN0IHNlY3VyaXR5RGlmZiA9IGZvcm1hdHRlci5mb3JtYXRTZWN1cml0eURpZmYoeyBxdWlldCB9KTtcbiAgICAgICAgLy8gV2FybiwgY291bnQsIGFuZCBkaXNwbGF5IHRoZSBkaWZmIG9ubHkgaWYgdGhlIHJlcG9ydGVkIGNoYW5nZXMgYXJlIGJyb2FkZW5pbmcgcGVybWlzc2lvbnNcbiAgICAgICAgaWYgKHNlY3VyaXR5RGlmZi5wZXJtaXNzaW9uQ2hhbmdlVHlwZSA9PT0gUGVybWlzc2lvbkNoYW5nZVR5cGUuQlJPQURFTklORykge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy53YXJuKCdUaGlzIGRlcGxveW1lbnQgd2lsbCBtYWtlIHBvdGVudGlhbGx5IHNlbnNpdGl2ZSBjaGFuZ2VzIGFjY29yZGluZyB0byB5b3VyIGN1cnJlbnQgc2VjdXJpdHkgYXBwcm92YWwgbGV2ZWwuXFxuUGxlYXNlIGNvbmZpcm0geW91IGludGVuZCB0byBtYWtlIHRoZSBmb2xsb3dpbmcgbW9kaWZpY2F0aW9uczpcXG4nKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhzZWN1cml0eURpZmYuZm9ybWF0dGVkRGlmZik7XG4gICAgICAgICAgZGlmZnMgKz0gc2VjdXJpdHlEaWZmLm51bVN0YWNrc1dpdGhDaGFuZ2VzO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkaWZmID0gZm9ybWF0dGVyLmZvcm1hdFN0YWNrRGlmZih7XG4gICAgICAgICAgc3RyaWN0LFxuICAgICAgICAgIGNvbnRleHRMaW5lcyxcbiAgICAgICAgICBxdWlldCxcbiAgICAgICAgfSk7XG4gICAgICAgIGRpZmZzID0gZGlmZi5udW1TdGFja3NXaXRoQ2hhbmdlcztcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oZGlmZi5mb3JtYXR0ZWREaWZmKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYWxsTWFwcGluZ3MgPSBvcHRpb25zLmluY2x1ZGVNb3Zlc1xuICAgICAgICA/IGF3YWl0IG1hcHBpbmdzQnlFbnZpcm9ubWVudChzdGFja3Muc3RhY2tBcnRpZmFjdHMsIHRoaXMucHJvcHMuc2RrUHJvdmlkZXIsIHRydWUpXG4gICAgICAgIDogW107XG5cbiAgICAgIC8vIENvbXBhcmUgTiBzdGFja3MgYWdhaW5zdCBkZXBsb3llZCB0ZW1wbGF0ZXNcbiAgICAgIGZvciAoY29uc3Qgc3RhY2sgb2Ygc3RhY2tzLnN0YWNrQXJ0aWZhY3RzKSB7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlV2l0aE5lc3RlZFN0YWNrcyA9IGF3YWl0IHRoaXMucHJvcHMuZGVwbG95bWVudHMucmVhZEN1cnJlbnRUZW1wbGF0ZVdpdGhOZXN0ZWRTdGFja3MoXG4gICAgICAgICAgc3RhY2ssXG4gICAgICAgICAgb3B0aW9ucy5jb21wYXJlQWdhaW5zdFByb2Nlc3NlZFRlbXBsYXRlLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjdXJyZW50VGVtcGxhdGUgPSB0ZW1wbGF0ZVdpdGhOZXN0ZWRTdGFja3MuZGVwbG95ZWRSb290VGVtcGxhdGU7XG4gICAgICAgIGNvbnN0IG5lc3RlZFN0YWNrcyA9IHRlbXBsYXRlV2l0aE5lc3RlZFN0YWNrcy5uZXN0ZWRTdGFja3M7XG5cbiAgICAgICAgY29uc3QgZW52aXJvbm1lbnQgPSBhd2FpdCB0aGlzLnByb3BzLmRlcGxveW1lbnRzLnJlc29sdmVFbnZpcm9ubWVudChzdGFjayk7XG5cbiAgICAgICAgY29uc3QgbWlncmF0b3IgPSBuZXcgUmVzb3VyY2VNaWdyYXRvcih7XG4gICAgICAgICAgZGVwbG95bWVudHM6IHRoaXMucHJvcHMuZGVwbG95bWVudHMsXG4gICAgICAgICAgaW9IZWxwZXI6IGFzSW9IZWxwZXIodGhpcy5pb0hvc3QsICdkaWZmJyksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCByZXNvdXJjZXNUb0ltcG9ydCA9IGF3YWl0IG1pZ3JhdG9yLnRyeUdldFJlc291cmNlcyhlbnZpcm9ubWVudCk7XG4gICAgICAgIGlmIChyZXNvdXJjZXNUb0ltcG9ydCkge1xuICAgICAgICAgIHJlbW92ZU5vbkltcG9ydFJlc291cmNlcyhzdGFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjaGFuZ2VTZXQgPSAob3B0aW9ucy5tZXRob2QgIT09ICd0ZW1wbGF0ZScpXG4gICAgICAgICAgPyAoYXdhaXQgdGhpcy50cnlDcmVhdGVEaWZmQ2hhbmdlU2V0KHN0YWNrLCBvcHRpb25zLCBwYXJhbWV0ZXJNYXAsIHJlc291cmNlc1RvSW1wb3J0LCBxdWlldCkpPy5jaGFuZ2VTZXRcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICBjb25zdCBtYXBwaW5ncyA9IGFsbE1hcHBpbmdzLmZpbmQobSA9PlxuICAgICAgICAgIG0uZW52aXJvbm1lbnQucmVnaW9uID09PSBzdGFjay5lbnZpcm9ubWVudC5yZWdpb24gJiYgbS5lbnZpcm9ubWVudC5hY2NvdW50ID09PSBzdGFjay5lbnZpcm9ubWVudC5hY2NvdW50LFxuICAgICAgICApPy5tYXBwaW5ncyA/PyB7fTtcblxuICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPSBuZXcgRGlmZkZvcm1hdHRlcih7XG4gICAgICAgICAgdGVtcGxhdGVJbmZvOiB7XG4gICAgICAgICAgICBvbGRUZW1wbGF0ZTogY3VycmVudFRlbXBsYXRlLFxuICAgICAgICAgICAgbmV3VGVtcGxhdGU6IHN0YWNrLFxuICAgICAgICAgICAgY2hhbmdlU2V0LFxuICAgICAgICAgICAgaXNJbXBvcnQ6ICEhcmVzb3VyY2VzVG9JbXBvcnQsXG4gICAgICAgICAgICBuZXN0ZWRTdGFja3MsXG4gICAgICAgICAgICBtYXBwaW5ncyxcbiAgICAgICAgICAgIGVudmlyb25tZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChvcHRpb25zLnNlY3VyaXR5T25seSkge1xuICAgICAgICAgIGNvbnN0IHNlY3VyaXR5RGlmZiA9IGZvcm1hdHRlci5mb3JtYXRTZWN1cml0eURpZmYoeyBxdWlldCB9KTtcbiAgICAgICAgICAvLyBXYXJuLCBjb3VudCwgYW5kIGRpc3BsYXkgdGhlIGRpZmYgb25seSBpZiB0aGUgcmVwb3J0ZWQgY2hhbmdlcyBhcmUgYnJvYWRlbmluZyBwZXJtaXNzaW9uc1xuICAgICAgICAgIGlmIChzZWN1cml0eURpZmYucGVybWlzc2lvbkNoYW5nZVR5cGUgPT09IFBlcm1pc3Npb25DaGFuZ2VUeXBlLkJST0FERU5JTkcpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy53YXJuKCdUaGlzIGRlcGxveW1lbnQgd2lsbCBtYWtlIHBvdGVudGlhbGx5IHNlbnNpdGl2ZSBjaGFuZ2VzIGFjY29yZGluZyB0byB5b3VyIGN1cnJlbnQgc2VjdXJpdHkgYXBwcm92YWwgbGV2ZWwuXFxuUGxlYXNlIGNvbmZpcm0geW91IGludGVuZCB0byBtYWtlIHRoZSBmb2xsb3dpbmcgbW9kaWZpY2F0aW9uczpcXG4nKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKHNlY3VyaXR5RGlmZi5mb3JtYXR0ZWREaWZmKTtcbiAgICAgICAgICAgIGRpZmZzICs9IHNlY3VyaXR5RGlmZi5udW1TdGFja3NXaXRoQ2hhbmdlcztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgZGlmZiA9IGZvcm1hdHRlci5mb3JtYXRTdGFja0RpZmYoe1xuICAgICAgICAgICAgc3RyaWN0LFxuICAgICAgICAgICAgY29udGV4dExpbmVzLFxuICAgICAgICAgICAgcXVpZXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oZGlmZi5mb3JtYXR0ZWREaWZmKTtcbiAgICAgICAgICBkaWZmcyArPSBkaWZmLm51bVN0YWNrc1dpdGhDaGFuZ2VzO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oZm9ybWF0KCdcXG7inKggIE51bWJlciBvZiBzdGFja3Mgd2l0aCBkaWZmZXJlbmNlczogJXNcXG4nLCBkaWZmcykpO1xuXG4gICAgcmV0dXJuIGRpZmZzICYmIG9wdGlvbnMuZmFpbCA/IDEgOiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyeSB0byBjcmVhdGUgYSBkaWZmIGNoYW5nZXNldCBmb3IgdGhlIGdpdmVuIHN0YWNrLlxuICAgKiBSZXR1cm5zIHVuZGVmaW5lZCBpZiB0aGUgc3RhY2sgY2Fubm90IGJlIGFjY2Vzc2VkIGFuZCBjaGFuZ2VTZXRPbmx5IGlzIG5vdCBzZXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHRyeUNyZWF0ZURpZmZDaGFuZ2VTZXQoXG4gICAgc3RhY2s6IGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCxcbiAgICBvcHRpb25zOiBEaWZmT3B0aW9ucyxcbiAgICBwYXJhbWV0ZXJNYXA6IHsgW25hbWU6IHN0cmluZ106IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9IH0sXG4gICAgcmVzb3VyY2VzVG9JbXBvcnQ6IEF3YWl0ZWQ8UmV0dXJuVHlwZTxSZXNvdXJjZU1pZ3JhdG9yWyd0cnlHZXRSZXNvdXJjZXMnXT4+LFxuICAgIHF1aWV0OiBib29sZWFuLFxuICApIHtcbiAgICB0cnkge1xuICAgICAgLy8gd2UgZG9uJ3QgYWN0dWFsbHkgbmVlZCB0byBrbm93IGlmIHRoZSBzdGFjayBleGlzdHMgaGVyZVxuICAgICAgLy8gd2UganVzdCB1c2UgdGhpcyB0byBmbHVzaCBvdXIgYW55IHBlcm1pc3Npb25zIGlzc3VlcyBhbmQgZHJvcCB0aGUgcmVzdWx0XG4gICAgICB2b2lkIGF3YWl0IHRoaXMucHJvcHMuZGVwbG95bWVudHMuc3RhY2tFeGlzdHMoe1xuICAgICAgICBzdGFjayxcbiAgICAgICAgZGVwbG95TmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICB0cnlMb29rdXBSb2xlOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAob3B0aW9ucy5tZXRob2QgPT09ICdjaGFuZ2Utc2V0Jykge1xuICAgICAgICB0aHJvdyBUb29sa2l0RXJyb3Iud2l0aENhdXNlKCdEZXNjcmliZVN0YWNrc0ZhaWxlZCcsIGBDb3VsZCBub3QgYWNjZXNzIHN0YWNrICcke3N0YWNrLnN0YWNrTmFtZX0nLiBQbGVhc2UgY2hlY2sgeW91ciBwZXJtaXNzaW9ucyBvciB1c2UgJy0tbWV0aG9kPWF1dG8nIHRvIGFsbG93IGZhbGxpbmcgYmFjayB0byBhIHRlbXBsYXRlIGRpZmYuYCwgZSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuZGVidWcoZm9ybWF0RXJyb3JNZXNzYWdlKGUpKTtcbiAgICAgIGlmICghcXVpZXQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oXG4gICAgICAgICAgYENvdWxkIG5vdCBhY2Nlc3Mgc3RhY2sgJyR7c3RhY2suc3RhY2tOYW1lfScsIGZhbGxpbmcgYmFjayB0byB0ZW1wbGF0ZSBkaWZmLiBVc2UgJy0tbWV0aG9kPWNoYW5nZS1zZXQnIHRvIGZhaWwgaW5zdGVhZC4gUnVuIHdpdGggLXYgdG8gc2VlIHRoZSByZWFzb24uXFxuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNmbkFwaS5jcmVhdGVEaWZmQ2hhbmdlU2V0KGFzSW9IZWxwZXIodGhpcy5pb0hvc3QsICdkaWZmJyksIHtcbiAgICAgIHN0YWNrLFxuICAgICAgdXVpZDogcmFuZG9tVVVJRCgpLFxuICAgICAgZGVwbG95bWVudHM6IHRoaXMucHJvcHMuZGVwbG95bWVudHMsXG4gICAgICBzZGtQcm92aWRlcjogdGhpcy5wcm9wcy5zZGtQcm92aWRlcixcbiAgICAgIHBhcmFtZXRlcnM6IE9iamVjdC5hc3NpZ24oe30sIHBhcmFtZXRlck1hcFsnKiddLCBwYXJhbWV0ZXJNYXBbc3RhY2suc3RhY2tOYW1lXSksXG4gICAgICByZXNvdXJjZXNUb0ltcG9ydCxcbiAgICAgIGltcG9ydEV4aXN0aW5nUmVzb3VyY2VzOiBvcHRpb25zLmltcG9ydEV4aXN0aW5nUmVzb3VyY2VzLFxuICAgICAgZmFpbE9uRXJyb3I6IG9wdGlvbnMubWV0aG9kID09PSAnY2hhbmdlLXNldCcsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVwbG95KG9wdGlvbnM6IERlcGxveU9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy53YXRjaCkge1xuICAgICAgcmV0dXJuIHRoaXMud2F0Y2gob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8gc2V0IHByb2dyZXNzIGZyb20gb3B0aW9ucywgdGhpcyBpbmNsdWRlcyB1c2VyIGFuZCBhcHAgY29uZmlnXG4gICAgaWYgKG9wdGlvbnMucHJvZ3Jlc3MpIHtcbiAgICAgIHRoaXMuaW9Ib3N0LnN0YWNrUHJvZ3Jlc3MgPSBvcHRpb25zLnByb2dyZXNzO1xuICAgIH1cblxuICAgIC8vIHRoZSBpb0hvc3QgdXNlcyB0aGlzIGludGVybmFsbHkgdG8gZGV0ZXJtaW5lIGlmIGEgY29uZmlybWF0aW9uXG4gICAgLy8gaXMgYWN0dWFsbHkgbmVlZGVkLCBzbyBpdCBuZWVkcyB0aGUgc2FtZSB2YWx1ZSB3ZSBkZXRlcm1pbmUgaGVyZS5cbiAgICBjb25zdCByZXF1aXJlQXBwcm92YWwgPSBvcHRpb25zLnJlcXVpcmVBcHByb3ZhbCA/PyBSZXF1aXJlQXBwcm92YWwuQlJPQURFTklORztcbiAgICB0aGlzLmlvSG9zdC5yZXF1aXJlRGVwbG95QXBwcm92YWwgPSByZXF1aXJlQXBwcm92YWw7XG5cbiAgICAvLyB0b29sa2l0LWxpYiBlbWl0cyB0aGUgYXBwcm92YWwgcmVxdWVzdCAoSTUwNjApIHdpdGhvdXQgbWVudGlvbmluZ1xuICAgIC8vIGAtLXJlcXVpcmUtYXBwcm92YWxgLiBUaGUgQ0xJIG93bnMgdGhhdCBmbGFnLCBzbyBpdCBhZGRzIHRoZSBmcmFtaW5nIGhlcmUuXG4gICAgLy8gQm90aCBkZXBsb3kgcGF0aHMgcmVzb2x2ZSB0aHJvdWdoIHRoaXMgaG9zdCwgc28gb25lIGxpc3RlbmVyIGNvdmVycyBib3RoLlxuICAgIC8vIE1ldGhvZC1zY29wZWQgKGB1c2luZ2ApOiBgZGVwbG95KClgIGNhbiBydW4gcmVwZWF0ZWRseSAod2F0Y2ggbW9kZSksIGFuZFxuICAgIC8vIGVhY2ggcnVuIG11c3QgcmVnaXN0ZXIgYSByZXdyaXRlIGZvciBpdHMgb3duIGByZXF1aXJlQXBwcm92YWxgIHZhbHVlLlxuICAgIHVzaW5nIF9hcHByb3ZhbEZyYW1pbmcgPSB0aGlzLmlvSG9zdC5yZXdyaXRlKElPLkNES19UT09MS0lUX0k1MDYwLCAobXNnKSA9PiB7XG4gICAgICBjb25zdCB1cGRhdGVUeXBlVGV4dCA9IG1zZy5kYXRhLnBlcm1pc3Npb25DaGFuZ2VUeXBlICE9PSBQZXJtaXNzaW9uQ2hhbmdlVHlwZS5OT05FXG4gICAgICAgID8gJ3NlY3VyaXR5LXNlbnNpdGl2ZSB1cGRhdGVzJ1xuICAgICAgICA6ICd1cGRhdGVzJztcbiAgICAgIHJldHVybiBgU3RhY2sgaW5jbHVkZXMgJHt1cGRhdGVUeXBlVGV4dH0gYW5kIFwiLS1yZXF1aXJlLWFwcHJvdmFsXCIgaXMgc2V0IHRvICcke3JlcXVpcmVBcHByb3ZhbH0nLlxcbkRvIHlvdSB3aXNoIHRvIGRlcGxveSB0aGVzZSBjaGFuZ2VzP2A7XG4gICAgfSk7XG5cbiAgICAvLyBleGVjdXRlLWNoYW5nZS1zZXQgaXMgYSBuZXcgZmxvdyB0aGF0IHdlIGNhbiBqdXN0IGRlbGVnYXRlIHRvIHRvb2xraXQtbGliXG4gICAgaWYgKG9wdGlvbnMuZGVwbG95bWVudE1ldGhvZD8ubWV0aG9kID09PSAnZXhlY3V0ZS1jaGFuZ2Utc2V0Jykge1xuICAgICAgYXdhaXQgdGhpcy50b29sa2l0LmRlcGxveSh0aGlzLnByb3BzLmNsb3VkRXhlY3V0YWJsZSwge1xuICAgICAgICBkZXBsb3ltZW50TWV0aG9kOiBvcHRpb25zLmRlcGxveW1lbnRNZXRob2QsXG4gICAgICAgIHN0YWNrczoge1xuICAgICAgICAgIHBhdHRlcm5zOiBvcHRpb25zLnNlbGVjdG9yLnBhdHRlcm5zLFxuICAgICAgICAgIHN0cmF0ZWd5OiBTdGFja1NlbGVjdGlvblN0cmF0ZWd5LlBBVFRFUk5fTVVTVF9NQVRDSF9TSU5HTEUsXG4gICAgICAgICAgZXhwYW5kOiBFeHBhbmRTdGFja1NlbGVjdGlvbi5OT05FLFxuICAgICAgICB9LFxuICAgICAgICByb2xlQXJuOiBvcHRpb25zLnJvbGVBcm4sXG4gICAgICAgIGZvcmNlRGVwbG95bWVudDogb3B0aW9ucy5mb3JjZSxcbiAgICAgICAgcm9sbGJhY2s6IG9wdGlvbnMucm9sbGJhY2ssXG4gICAgICAgIHJldXNlQXNzZXRzOiBvcHRpb25zLnJldXNlQXNzZXRzLFxuICAgICAgICBjb25jdXJyZW5jeTogb3B0aW9ucy5jb25jdXJyZW5jeSxcbiAgICAgICAgdHJhY2VMb2dzOiBvcHRpb25zLnRyYWNlTG9ncyxcbiAgICAgICAgbm90aWZpY2F0aW9uQXJuczogb3B0aW9ucy5ub3RpZmljYXRpb25Bcm5zLFxuICAgICAgICB0YWdzOiBvcHRpb25zLnRhZ3MsXG4gICAgICAgIG91dHB1dHNGaWxlOiBvcHRpb25zLm91dHB1dHNGaWxlLFxuICAgICAgICBhc3NldFBhcmFsbGVsaXNtOiBvcHRpb25zLmFzc2V0UGFyYWxsZWxpc20sXG4gICAgICAgIGFzc2V0QnVpbGRDb25jdXJyZW5jeTogb3B0aW9ucy5hc3NldEJ1aWxkQ29uY3VycmVuY3ksXG4gICAgICAgIGFzc2V0QnVpbGRUaW1lOiBvcHRpb25zLmFzc2V0QnVpbGRUaW1lLFxuICAgICAgICBwYXJhbWV0ZXJzOiB1bmRlZmluZWQsIC8vIHBhcmFtZXRlcnMgYXJlIG9ubHkgc2V0IGR1cmluZyBjaGFuZ2Ugc2V0IGNyZWF0aW9uLCBzbyB0aGlzIGlzIGV4cGxpY2l0bHkgdW5zZXQgYmVjYXVzZSBjaGFuZ2Ugc2V0IGFscmVhZHkgZXhpc3RzXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydFN5bnRoVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGFzc2VtYmx5ID0gYXdhaXQgdGhpcy5hc3NlbWJseShvcHRpb25zLmNhY2hlQ2xvdWRBc3NlbWJseSk7XG4gICAgY29uc3Qgc3RhY2tDb2xsZWN0aW9uID0gYXdhaXQgYXNzZW1ibHkuc2VsZWN0U3RhY2tzVjIob3B0aW9ucy5zZWxlY3Rvcik7XG4gICAgYXdhaXQgdGhpcy52YWxpZGF0ZVN0YWNrcyhhc3NlbWJseSwgc3RhY2tDb2xsZWN0aW9uKTtcbiAgICBjb25zdCBlbGFwc2VkU3ludGhUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSBzdGFydFN5bnRoVGltZTtcbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgXFxu4pyoICBTeW50aGVzaXMgdGltZTogJHtmb3JtYXRUaW1lKGVsYXBzZWRTeW50aFRpbWUpfXNcXG5gKTtcblxuICAgIGlmIChzdGFja0NvbGxlY3Rpb24uc3RhY2tDb3VudCA9PT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmVycm9yKCdUaGlzIGFwcCBjb250YWlucyBubyBzdGFja3MnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBtaWdyYXRvciA9IG5ldyBSZXNvdXJjZU1pZ3JhdG9yKHtcbiAgICAgIGRlcGxveW1lbnRzOiB0aGlzLnByb3BzLmRlcGxveW1lbnRzLFxuICAgICAgaW9IZWxwZXI6IGFzSW9IZWxwZXIodGhpcy5pb0hvc3QsICdkZXBsb3knKSxcbiAgICB9KTtcbiAgICBhd2FpdCBtaWdyYXRvci50cnlNaWdyYXRlUmVzb3VyY2VzKHN0YWNrQ29sbGVjdGlvbiwge1xuICAgICAgdG9vbGtpdFN0YWNrTmFtZTogdGhpcy50b29sa2l0U3RhY2tOYW1lLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KTtcblxuICAgIGlmIChvcHRpb25zLmRlcGxveW1lbnRNZXRob2Q/Lm1ldGhvZCA9PT0gJ2hvdHN3YXAnKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMud2FybihcbiAgICAgICAgJ+KaoO+4jyBUaGUgLS1ob3Rzd2FwIGFuZCAtLWhvdHN3YXAtZmFsbGJhY2sgZmxhZ3MgZGVsaWJlcmF0ZWx5IGludHJvZHVjZSBDbG91ZEZvcm1hdGlvbiBkcmlmdCB0byBzcGVlZCB1cCBkZXBsb3ltZW50cycsXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oJ+KaoO+4jyBUaGV5IHNob3VsZCBvbmx5IGJlIHVzZWQgZm9yIGRldmVsb3BtZW50IC0gbmV2ZXIgdXNlIHRoZW0gZm9yIHlvdXIgcHJvZHVjdGlvbiBTdGFja3MhXFxuJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RhY2tzID0gc3RhY2tDb2xsZWN0aW9uLnN0YWNrQXJ0aWZhY3RzO1xuXG4gICAgY29uc3QgYXNzZXRCdWlsZFRpbWUgPSBvcHRpb25zLmFzc2V0QnVpbGRUaW1lID8/IEFzc2V0QnVpbGRUaW1lLkFMTF9CRUZPUkVfREVQTE9ZO1xuICAgIGNvbnN0IHByZWJ1aWxkQXNzZXRzID0gYXNzZXRCdWlsZFRpbWUgPT09IEFzc2V0QnVpbGRUaW1lLkFMTF9CRUZPUkVfREVQTE9ZO1xuICAgIGNvbnN0IGNvbmN1cnJlbmN5ID0gb3B0aW9ucy5jb25jdXJyZW5jeSB8fCAxO1xuICAgIGlmIChjb25jdXJyZW5jeSA+IDEpIHtcbiAgICAgIC8vIHRoZSBcImJhclwiIHByb2dyZXNzIG91dHB1dCBkb2Vzbid0IHN1cHBvcnQgY29uY3VycmVuY3ksIGZhbGwgYmFjayB0byBcImV2ZW50c1wiXG4gICAgICBpZiAodGhpcy5pb0hvc3Quc3RhY2tQcm9ncmVzcyA9PT0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJBUikge1xuICAgICAgICB0aGlzLmlvSG9zdC5zdGFja1Byb2dyZXNzID0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkVWRU5UUztcbiAgICAgIH1cblxuICAgICAgLy8gLi4uYnV0IG9ubHkgd2FybiBpZiB0aGUgdXNlciBleHBsaWNpdGx5IHJlcXVlc3RlZCBcImJhclwiIHByb2dyZXNzXG4gICAgICBpZiAob3B0aW9ucy5wcm9ncmVzcyA9PT0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJBUikge1xuICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMud2Fybign4pqg77iPIFRoZSAtLWNvbmN1cnJlbmN5IGZsYWcgZG9lcyBub3Qgc3VwcG9ydCAtLXByb2dyZXNzIFwiYmFyXCIuIFN3aXRjaGluZyB0byBcImV2ZW50c1wiLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHN0YWNrc0FuZFRoZWlyQXNzZXRNYW5pZmVzdHMgPSBzdGFja3MuZmxhdE1hcCgoc3RhY2spID0+IFtcbiAgICAgIHN0YWNrLFxuICAgICAgLi4uc3RhY2suZGVwZW5kZW5jaWVzLmZpbHRlcih4ID0+IGN4YXBpLkFzc2V0TWFuaWZlc3RBcnRpZmFjdC5pc0Fzc2V0TWFuaWZlc3RBcnRpZmFjdCh4KSksXG4gICAgXSk7XG4gICAgY29uc3Qgd29ya0dyYXBoID0gbmV3IFdvcmtHcmFwaEJ1aWxkZXIoXG4gICAgICBhc0lvSGVscGVyKHRoaXMuaW9Ib3N0LCAnZGVwbG95JyksXG4gICAgICBwcmVidWlsZEFzc2V0cyxcbiAgICApLmJ1aWxkKHN0YWNrc0FuZFRoZWlyQXNzZXRNYW5pZmVzdHMpO1xuXG4gICAgLy8gVW5sZXNzIHdlIGFyZSBydW5uaW5nIHdpdGggJy0tZm9yY2UnLCBza2lwIGFscmVhZHkgcHVibGlzaGVkIGFzc2V0c1xuICAgIGlmICghb3B0aW9ucy5mb3JjZSkge1xuICAgICAgYXdhaXQgdGhpcy5yZW1vdmVQdWJsaXNoZWRBc3NldHMod29ya0dyYXBoLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBjb25zdCBncmFwaENvbmN1cnJlbmN5OiBDb25jdXJyZW5jeSA9IHtcbiAgICAgICdzdGFjayc6IGNvbmN1cnJlbmN5LFxuICAgICAgJ2Fzc2V0LWJ1aWxkJzogKG9wdGlvbnMuYXNzZXRQYXJhbGxlbGlzbSA/PyB0cnVlKSA/IG9wdGlvbnMuYXNzZXRCdWlsZENvbmN1cnJlbmN5ID8/IDEgOiAxLCAvLyBUaGlzIHdpbGwgYmUgQ1BVLWJvdW5kL21lbW9yeSBib3VuZCwgbW9zdGx5IG1hdHRlcnMgZm9yIERvY2tlciBidWlsZHNcbiAgICAgICdhc3NldC1wdWJsaXNoJzogKG9wdGlvbnMuYXNzZXRQYXJhbGxlbGlzbSA/PyB0cnVlKSA/IDggOiAxLCAvLyBUaGlzIHdpbGwgYmUgSS9PLWJvdW5kLCA4IGluIHBhcmFsbGVsIHNlZW1zIHJlYXNvbmFibGVcbiAgICAgICdtYXJrZXInOiAxLFxuICAgIH07XG5cbiAgICBjb25zdCBkZXBsb3ltZW50QWN0aW9ucyA9IG5ldyBXb3JrR3JhcGhEZXBsb3ltZW50QWN0aW9ucyh0aGlzLnByb3BzLmRlcGxveW1lbnRzLCB0aGlzLmlvSG9zdCwgdGhpcywge1xuICAgICAgcm9sZUFybjogb3B0aW9ucy5yb2xlQXJuLFxuICAgICAgZm9yY2U6IG9wdGlvbnMuZm9yY2UsXG4gICAgICBzdGFja0NvdW50OiBzdGFja0NvbGxlY3Rpb24uc3RhY2tDb3VudCxcbiAgICAgIG5vdGlmaWNhdGlvbkFybnM6IG9wdGlvbnMubm90aWZpY2F0aW9uQXJucyxcbiAgICAgIGRlcGxveW1lbnRNZXRob2Q6IG9wdGlvbnMuZGVwbG95bWVudE1ldGhvZCxcbiAgICAgIHRvb2xraXRTdGFja05hbWU6IHRoaXMudG9vbGtpdFN0YWNrTmFtZSxcbiAgICAgIHJldXNlQXNzZXRzOiBvcHRpb25zLnJldXNlQXNzZXRzLFxuICAgICAgdGFnczogb3B0aW9ucy50YWdzLFxuICAgICAgcGFyYW1ldGVyczogb3B0aW9ucy5wYXJhbWV0ZXJzLFxuICAgICAgdXNlUHJldmlvdXNQYXJhbWV0ZXJzOiBvcHRpb25zLnVzZVByZXZpb3VzUGFyYW1ldGVycyxcbiAgICAgIHJvbGxiYWNrOiBvcHRpb25zLnJvbGxiYWNrLFxuICAgICAgY29uY3VycmVuY3ksXG4gICAgICByZXF1aXJlQXBwcm92YWwsXG4gICAgICBhc3NldFBhcmFsbGVsaXNtOiBvcHRpb25zLmFzc2V0UGFyYWxsZWxpc20sXG4gICAgICBleHRyYVVzZXJBZ2VudDogb3B0aW9ucy5leHRyYVVzZXJBZ2VudCxcbiAgICAgIGNsb3VkV2F0Y2hMb2dNb25pdG9yOiBvcHRpb25zLmNsb3VkV2F0Y2hMb2dNb25pdG9yLFxuICAgICAgc2RrUHJvdmlkZXI6IHRoaXMucHJvcHMuc2RrUHJvdmlkZXIsXG4gICAgICBleHByZXNzOiBvcHRpb25zLmV4cHJlc3MsXG4gICAgfSk7XG5cbiAgICBjb25zdCBzdGFydERlcGxveVRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgYXdhaXQgd29ya0dyYXBoLmRvUGFyYWxsZWwoZ3JhcGhDb25jdXJyZW5jeSwgZGVwbG95bWVudEFjdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnMub3V0cHV0c0ZpbGUpIHtcbiAgICAgIC8vIElmIGFuIG91dHB1dHMgZmlsZSBoYXMgYmVlbiBzcGVjaWZpZWQsIGNyZWF0ZSB0aGUgZmlsZSBwYXRoIGFuZCB3cml0ZSBzdGFjayBvdXRwdXRzIHRvIGl0IG9uY2UuXG4gICAgICAvLyBPdXRwdXRzIGFyZSB3cml0dGVuIGFmdGVyIGFsbCBzdGFja3MgaGF2ZSBiZWVuIGRlcGxveWVkLiBJZiBhIHN0YWNrIGRlcGxveW1lbnQgZmFpbHMsXG4gICAgICAvLyBhbGwgb2YgdGhlIG91dHB1dHMgZnJvbSBzdWNjZXNzZnVsbHkgZGVwbG95ZWQgc3RhY2tzIGJlZm9yZSB0aGUgZmFpbHVyZSB3aWxsIHN0aWxsIGJlIHdyaXR0ZW4uXG4gICAgICBhd2FpdCBkZXBsb3ltZW50QWN0aW9ucy53cml0ZU91dHB1dHMob3B0aW9ucy5vdXRwdXRzRmlsZSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGEgdGltZXIgb24gdGhlIENPTU1BTkQgc3BhbiBmb3IgdGhlIGZ1bGwgZGVwbG95bWVudCB3YWl0IHRpbWUgKG5vdCB0aGUgc2FtZSBhcyB0aGUgc3VtIG9mIGFsbCBERVBMT1lcbiAgICAvLyBzcGFucyBiZWNhdXNlIG9mIHBhcmFsbGVsaXNtKS5cbiAgICB0aGlzLmlvSG9zdC50ZWxlbWV0cnk/LmNvbW1hbmRTcGFuPy5hZGRUaW1lcigndG90YWxEZXBsb3lUaW1lJywgRGF0ZS5ub3coKSAtIHN0YXJ0RGVwbG95VGltZSk7XG5cbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgXFxu4pyoICBUb3RhbCB0aW1lOiAke2Zvcm1hdFRpbWUoRGF0ZS5ub3coKSAtIHN0YXJ0U3ludGhUaW1lKX1zXFxuYCk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IGluZnJhc3RydWN0dXJlIGRyaWZ0IGZvciB0aGUgZ2l2ZW4gc3RhY2socylcbiAgICovXG4gIHB1YmxpYyBhc3luYyBkcmlmdChvcHRpb25zOiBEcmlmdE9wdGlvbnMpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGRyaWZ0UmVzdWx0cyA9IGF3YWl0IHRoaXMudG9vbGtpdC5kcmlmdCh0aGlzLnByb3BzLmNsb3VkRXhlY3V0YWJsZSwge1xuICAgICAgc3RhY2tzOiBvcHRpb25zLnNlbGVjdG9yLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdG90YWxEcmlmdHMgPSBPYmplY3QudmFsdWVzKGRyaWZ0UmVzdWx0cykucmVkdWNlKCh0b3RhbCwgY3VycmVudCkgPT4gdG90YWwgKyAoY3VycmVudC5udW1SZXNvdXJjZXNXaXRoRHJpZnQgPz8gMCksIDApO1xuICAgIHJldHVybiB0b3RhbERyaWZ0cyA+IDAgJiYgb3B0aW9ucy5mYWlsID8gMSA6IDA7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgc3ludGhlc2l6ZWQgdGVtcGxhdGVzIGFnYWluc3QgcG9saWN5IHJ1bGVzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUob3B0aW9uczogQ2xpVmFsaWRhdGVPcHRpb25zKTogUHJvbWlzZTxudW1iZXIgfCB2b2lkPiB7XG4gICAgLy8gSW1wbGljaXRseSBzd2l0Y2ggJ2RlYnVnJyBtb2RlIHRvIHRydWU7IG1vcmUgc3RhY2sgdHJhY2VzID0gbW9yZSB1c2VmdWwuXG4gICAgdGhpcy5wcm9wcy5jbG91ZEV4ZWN1dGFibGUuc3dpdGNoT25EZWJ1Z2dpbmcoKTtcblxuICAgIC8vIGB3YXRjaGAgaXMgYSBDTEktb25seSBmbGFnOyBzdHJpcCBpdCBiZWZvcmUgY3Jvc3NpbmcgaW50byB0b29sa2l0LWxpYiBzb1xuICAgIC8vIGl0IGRvZXMgbm90IGxlYWsgaW50byB0aGUgbGlicmFyeSdzIHZhbGlkYXRlIGFjdGlvbi5cbiAgICBjb25zdCB7IHdhdGNoLCAuLi52YWxpZGF0ZU9wdGlvbnMgfSA9IG9wdGlvbnM7XG5cbiAgICBpZiAod2F0Y2gpIHtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlV2F0Y2godmFsaWRhdGVPcHRpb25zKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnRvb2xraXQudmFsaWRhdGUodGhpcy5wcm9wcy5jbG91ZEV4ZWN1dGFibGUsIHZhbGlkYXRlT3B0aW9ucyk7XG4gICAgcmV0dXJuIHJlc3VsdC5jb25jbHVzaW9uID09PSAnZmFpbHVyZScgPyAxIDogMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb250aW51b3VzbHkgdmFsaWRhdGUgdGhlIHByb2plY3QsIHJlLXN5bnRoZXNpemluZyBhbmQgcmUtdmFsaWRhdGluZyBvblxuICAgKiBldmVyeSBmaWxlIGNoYW5nZS4gTmV2ZXIgZGVwbG95cy5cbiAgICpcbiAgICogVGhlIGZpbGVzIHRvIG9ic2VydmUgYXJlIGNvbmZpZ3VyZWQgd2l0aCB0aGUgXCJ3YXRjaFwiIGtleSBvZiBgY2RrLmpzb25gLFxuICAgKiBleGFjdGx5IGxpa2UgYGNkayBkZXBsb3kgLS13YXRjaGAuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHZhbGlkYXRlV2F0Y2gob3B0aW9uczogVmFsaWRhdGVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgcm9vdERpciA9IHBhdGguZGlybmFtZShwYXRoLnJlc29sdmUoUFJPSkVDVF9DT05GSUcpKTtcblxuICAgIGNvbnN0IHdhdGNoU2V0dGluZ3M6IHsgaW5jbHVkZT86IHN0cmluZyB8IHN0cmluZ1tdOyBleGNsdWRlPzogc3RyaW5nIHwgc3RyaW5nW10gfSB8IHVuZGVmaW5lZCA9XG4gICAgICB0aGlzLnByb3BzLmNvbmZpZ3VyYXRpb24uc2V0dGluZ3MuZ2V0KFsnd2F0Y2gnXSk7XG4gICAgaWYgKCF3YXRjaFNldHRpbmdzKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgICAnV2F0Y2hDb25maWdNaXNzaW5nJyxcbiAgICAgICAgXCJDYW5ub3QgdXNlICctLXdhdGNoJyB3aXRob3V0IHNwZWNpZnlpbmcgYXQgbGVhc3Qgb25lIGRpcmVjdG9yeSB0byBtb25pdG9yLiBcIiArXG4gICAgICAgICdNYWtlIHN1cmUgdG8gYWRkIGEgXCJ3YXRjaFwiIGtleSB0byB5b3VyIGNkay5qc29uJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgaW5jbHVkZSA9IHRoaXMucGF0dGVybnNBcnJheUZvcldhdGNoKHdhdGNoU2V0dGluZ3MuaW5jbHVkZSwge1xuICAgICAgZGVmYXVsdFBhdHRlcm46ICcqKicsXG4gICAgICByZXR1cm5EZWZhdWx0SWZFbXB0eTogdHJ1ZSxcbiAgICB9KTtcbiAgICAvLyBQYXNzIHRoZSB1c2VyJ3MgZXhjbHVkZXMgZXhwbGljaXRseTsgdG9vbGtpdC1saWIgYWx3YXlzIGFwcGVuZHMgdGhlXG4gICAgLy8gb3V0ZGlyLCBkb3QtZmlsZSwgYW5kIG5vZGVfbW9kdWxlcyBleGNsdWRlcyBvbiB0b3Agb2YgdGhlc2UuXG4gICAgY29uc3QgZXhjbHVkZSA9IHRoaXMucGF0dGVybnNBcnJheUZvcldhdGNoKHdhdGNoU2V0dGluZ3MuZXhjbHVkZSwge1xuICAgICAgZGVmYXVsdFBhdHRlcm46ICcnLFxuICAgICAgcmV0dXJuRGVmYXVsdElmRW1wdHk6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgd2F0Y2hlciA9IGF3YWl0IHRoaXMudG9vbGtpdC53YXRjaFZhbGlkYXRlKHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLnVuY2FjaGVkU291cmNlKCksIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICB3YXRjaERpcjogcm9vdERpcixcbiAgICAgIGluY2x1ZGUsXG4gICAgICBleGNsdWRlLFxuICAgIH0pO1xuICAgIHJldHVybiB3YXRjaGVyLndhaXRGb3JFbmQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaWFnbm9zZSBlcnJvcnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBkaWFnbm9zZShvcHRpb25zOiBEaWFnbm9zZU9wdGlvbnMpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIC8vIEltcGxpY2l0bHkgc3dpdGNoICdkZWJ1ZycgbW9kZSB0byB0cnVlOyBtb3JlIHN0YWNrIHRyYWNlcyA9IG1vcmUgdXNlZnVsLlxuICAgIHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLnN3aXRjaE9uRGVidWdnaW5nKCk7XG5cbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy50b29sa2l0LmRpYWdub3NlKHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLCBvcHRpb25zKTtcblxuICAgIGlmIChyZXN1bHRzLnN0YWNrcy5zb21lKHMgPT4gcy5yZXN1bHQudHlwZSAhPT0gJ25vLXByb2JsZW0nKSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFJvbGwgYmFjayB0aGUgZ2l2ZW4gc3RhY2sgb3Igc3RhY2tzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJvbGxiYWNrKG9wdGlvbnM6IFJvbGxiYWNrT3B0aW9ucykge1xuICAgIGNvbnN0IHN0YXJ0U3ludGhUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgYXNzZW1ibHkgPSBhd2FpdCB0aGlzLmFzc2VtYmx5KCk7XG4gICAgY29uc3Qgc3RhY2tDb2xsZWN0aW9uID0gYXdhaXQgYXNzZW1ibHkuc2VsZWN0U3RhY2tzVjIob3B0aW9ucy5zZWxlY3Rvcik7XG4gICAgYXdhaXQgdGhpcy52YWxpZGF0ZVN0YWNrcyhhc3NlbWJseSwgc3RhY2tDb2xsZWN0aW9uKTtcbiAgICBjb25zdCBlbGFwc2VkU3ludGhUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSBzdGFydFN5bnRoVGltZTtcbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgXFxu4pyoICBTeW50aGVzaXMgdGltZTogJHtmb3JtYXRUaW1lKGVsYXBzZWRTeW50aFRpbWUpfXNcXG5gKTtcblxuICAgIGlmIChzdGFja0NvbGxlY3Rpb24uc3RhY2tDb3VudCA9PT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmVycm9yKCdObyBzdGFja3Mgc2VsZWN0ZWQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgYW55Um9sbGJhY2thYmxlID0gZmFsc2U7XG5cbiAgICBmb3IgKGNvbnN0IHN0YWNrIG9mIHN0YWNrQ29sbGVjdGlvbi5zdGFja0FydGlmYWN0cykge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oJ1JvbGxpbmcgYmFjayAlcycsIGNoYWxrLmJvbGQoc3RhY2suZGlzcGxheU5hbWUpKTtcbiAgICAgIGNvbnN0IHN0YXJ0Um9sbGJhY2tUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnByb3BzLmRlcGxveW1lbnRzLnJvbGxiYWNrU3RhY2soe1xuICAgICAgICAgIHN0YWNrLFxuICAgICAgICAgIHJvbGVBcm46IG9wdGlvbnMucm9sZUFybixcbiAgICAgICAgICB0b29sa2l0U3RhY2tOYW1lOiBvcHRpb25zLnRvb2xraXRTdGFja05hbWUsXG4gICAgICAgICAgb3JwaGFuRmFpbGVkUmVzb3VyY2VzOiBvcHRpb25zLmZvcmNlLFxuICAgICAgICAgIHZhbGlkYXRlQm9vdHN0cmFwU3RhY2tWZXJzaW9uOiBvcHRpb25zLnZhbGlkYXRlQm9vdHN0cmFwU3RhY2tWZXJzaW9uLFxuICAgICAgICAgIG9ycGhhbkxvZ2ljYWxJZHM6IG9wdGlvbnMub3JwaGFuTG9naWNhbElkcyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghcmVzdWx0Lm5vdEluUm9sbGJhY2thYmxlU3RhdGUpIHtcbiAgICAgICAgICBhbnlSb2xsYmFja2FibGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVsYXBzZWRSb2xsYmFja1RpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHN0YXJ0Um9sbGJhY2tUaW1lO1xuICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgXFxu4pyoICBSb2xsYmFjayB0aW1lOiAke2Zvcm1hdFRpbWUoZWxhcHNlZFJvbGxiYWNrVGltZSkudG9TdHJpbmcoKX1zXFxuYCk7XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmVycm9yKCdcXG4g4p2MICAlcyBmYWlsZWQ6ICVzJywgY2hhbGsuYm9sZChzdGFjay5kaXNwbGF5TmFtZSksIGZvcm1hdEVycm9yTWVzc2FnZShlKSk7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1JvbGxiYWNrRmFpbGVkJywgJ1JvbGxiYWNrIGZhaWxlZCAodXNlIC0tZm9yY2UgdG8gb3JwaGFuIGZhaWxpbmcgcmVzb3VyY2VzKScpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWFueVJvbGxiYWNrYWJsZSkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignTm9Sb2xsYmFja2FibGVTdGFja3MnLCAnTm8gc3RhY2tzIHdlcmUgaW4gYSBzdGF0ZSB0aGF0IGNvdWxkIGJlIHJvbGxlZCBiYWNrJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHB1Ymxpc2hBc3NldHMob3B0aW9uczogUHVibGlzaEFzc2V0c09wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnRvb2xraXQucHVibGlzaEFzc2V0cyh0aGlzLnByb3BzLmNsb3VkRXhlY3V0YWJsZSwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgd2F0Y2gob3B0aW9uczogV2F0Y2hPcHRpb25zKSB7XG4gICAgY29uc3Qgcm9vdERpciA9IHBhdGguZGlybmFtZShwYXRoLnJlc29sdmUoUFJPSkVDVF9DT05GSUcpKTtcbiAgICBjb25zdCBpb0hlbHBlciA9IGFzSW9IZWxwZXIodGhpcy5pb0hvc3QsICd3YXRjaCcpO1xuICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5kZWJ1ZyhcInJvb3QgZGlyZWN0b3J5IHVzZWQgZm9yICd3YXRjaCcgaXM6ICVzXCIsIHJvb3REaXIpO1xuXG4gICAgY29uc3Qgd2F0Y2hTZXR0aW5nczogeyBpbmNsdWRlPzogc3RyaW5nIHwgc3RyaW5nW107IGV4Y2x1ZGU6IHN0cmluZyB8IHN0cmluZ1tdIH0gfCB1bmRlZmluZWQgPVxuICAgICAgdGhpcy5wcm9wcy5jb25maWd1cmF0aW9uLnNldHRpbmdzLmdldChbJ3dhdGNoJ10pO1xuICAgIGlmICghd2F0Y2hTZXR0aW5ncykge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgJ1dhdGNoQ29uZmlnTWlzc2luZycsXG4gICAgICAgIFwiQ2Fubm90IHVzZSB0aGUgJ3dhdGNoJyBjb21tYW5kIHdpdGhvdXQgc3BlY2lmeWluZyBhdCBsZWFzdCBvbmUgZGlyZWN0b3J5IHRvIG1vbml0b3IuIFwiICtcbiAgICAgICAgJ01ha2Ugc3VyZSB0byBhZGQgYSBcIndhdGNoXCIga2V5IHRvIHlvdXIgY2RrLmpzb24nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgdGhlIFwiaW5jbHVkZVwiIHN1YmtleSB1bmRlciB0aGUgXCJ3YXRjaFwiIGtleSwgdGhlIGJlaGF2aW9yIGlzOlxuICAgIC8vIDEuIE5vIFwid2F0Y2hcIiBzZXR0aW5nPyBXZSBlcnJvciBvdXQuXG4gICAgLy8gMi4gXCJ3YXRjaFwiIHNldHRpbmcgd2l0aG91dCBhbiBcImluY2x1ZGVcIiBrZXk/IFdlIGRlZmF1bHQgdG8gb2JzZXJ2aW5nIFwiLi8qKlwiLlxuICAgIC8vIDMuIFwid2F0Y2hcIiBzZXR0aW5nIHdpdGggYW4gZW1wdHkgXCJpbmNsdWRlXCIga2V5PyBXZSBkZWZhdWx0IHRvIG9ic2VydmluZyBcIi4vKipcIi5cbiAgICAvLyA0LiBOb24tZW1wdHkgXCJpbmNsdWRlXCIga2V5PyBKdXN0IHVzZSB0aGUgXCJpbmNsdWRlXCIga2V5LlxuICAgIC8vIE5vdGU6IFdlIHVzZSAnKionIGFzIHRoZSBkZWZhdWx0IHBhdHRlcm4gKG5vdCByb290RGlyKSBiZWNhdXNlIGNob2tpZGFyIHJlcG9ydHNcbiAgICAvLyBmaWxlIHBhdGhzIHJlbGF0aXZlIHRvIGN3ZCwgYW5kIHRoZSBpZ25vcmVkIGZ1bmN0aW9uIHVzZXMgcGljb21hdGNoIHdoaWNoIGV4cGVjdHNcbiAgICAvLyBnbG9iIHBhdHRlcm5zLCBub3QgYWJzb2x1dGUgcGF0aHMuXG4gICAgY29uc3Qgd2F0Y2hJbmNsdWRlcyA9IHRoaXMucGF0dGVybnNBcnJheUZvcldhdGNoKHdhdGNoU2V0dGluZ3MuaW5jbHVkZSwge1xuICAgICAgZGVmYXVsdFBhdHRlcm46ICcqKicsXG4gICAgICByZXR1cm5EZWZhdWx0SWZFbXB0eTogdHJ1ZSxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuZGVidWcoXCInaW5jbHVkZScgcGF0dGVybnMgZm9yICd3YXRjaCc6ICVzXCIsIHdhdGNoSW5jbHVkZXMpO1xuXG4gICAgLy8gRm9yIHRoZSBcImV4Y2x1ZGVcIiBzdWJrZXkgdW5kZXIgdGhlIFwid2F0Y2hcIiBrZXksXG4gICAgLy8gdGhlIGJlaGF2aW9yIGlzIHRvIGFkZCBzb21lIGRlZmF1bHQgZXhjbHVkZXMgaW4gYWRkaXRpb24gdG8gdGhlIG9uZXMgc3BlY2lmaWVkIGJ5IHRoZSB1c2VyOlxuICAgIC8vIDEuIFRoZSBDREsgb3V0cHV0IGRpcmVjdG9yeS5cbiAgICAvLyAyLiBBbnkgZmlsZSB3aG9zZSBuYW1lIHN0YXJ0cyB3aXRoIGEgZG90LlxuICAgIC8vIDMuIEFueSBkaXJlY3RvcnkncyBjb250ZW50IHdob3NlIG5hbWUgc3RhcnRzIHdpdGggYSBkb3QuXG4gICAgLy8gNC4gQW55IG5vZGVfbW9kdWxlcyBhbmQgaXRzIGNvbnRlbnQgKGV2ZW4gaWYgaXQncyBub3QgYSBKUy9UUyBwcm9qZWN0LCB5b3UgbWlnaHQgYmUgdXNpbmcgYSBsb2NhbCBhd3MtY2xpIHBhY2thZ2UpXG4gICAgY29uc3Qgb3V0cHV0RGlyID0gdGhpcy5wcm9wcy5jb25maWd1cmF0aW9uLnNldHRpbmdzLmdldChbJ291dHB1dCddKTtcbiAgICBjb25zdCB3YXRjaEV4Y2x1ZGVzID0gdGhpcy5wYXR0ZXJuc0FycmF5Rm9yV2F0Y2god2F0Y2hTZXR0aW5ncy5leGNsdWRlLCB7XG4gICAgICBkZWZhdWx0UGF0dGVybjogJycsXG4gICAgICByZXR1cm5EZWZhdWx0SWZFbXB0eTogZmFsc2UsXG4gICAgfSkuY29uY2F0KGAke291dHB1dERpcn0vKipgLCAnKiovLionLCAnKiovLiovKionLCAnKiovbm9kZV9tb2R1bGVzLyoqJyk7XG4gICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmRlYnVnKFwiJ2V4Y2x1ZGUnIHBhdHRlcm5zIGZvciAnd2F0Y2gnOiAlc1wiLCB3YXRjaEV4Y2x1ZGVzKTtcblxuICAgIC8vIFNpbmNlICdjZGsgZGVwbG95JyBpcyBhIHJlbGF0aXZlbHkgc2xvdyBvcGVyYXRpb24gZm9yIGEgJ3dhdGNoJyBwcm9jZXNzLFxuICAgIC8vIGludHJvZHVjZSBhIGNvbmN1cnJlbmN5IGxhdGNoIHRoYXQgdHJhY2tzIHRoZSBzdGF0ZS5cbiAgICAvLyBUaGlzIHdheSwgaWYgZmlsZSBjaGFuZ2UgZXZlbnRzIGFycml2ZSB3aGVuIGEgJ2NkayBkZXBsb3knIGlzIHN0aWxsIGV4ZWN1dGluZyxcbiAgICAvLyB3ZSB3aWxsIGJhdGNoIHRoZW0sIGFuZCB0cmlnZ2VyIGFub3RoZXIgJ2NkayBkZXBsb3knIGFmdGVyIHRoZSBjdXJyZW50IG9uZSBmaW5pc2hlcyxcbiAgICAvLyBtYWtpbmcgc3VyZSAnY2RrIGRlcGxveSdzICBhbHdheXMgZXhlY3V0ZSBvbmUgYXQgYSB0aW1lLlxuICAgIC8vIEhlcmUncyBhIGRpYWdyYW0gc2hvd2luZyB0aGUgc3RhdGUgdHJhbnNpdGlvbnM6XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0gICAgICAgICAgICAgICAgLS0tLS0tLS0gICAgZmlsZSBjaGFuZ2VkICAgICAtLS0tLS0tLS0tLS0tLSAgICBmaWxlIGNoYW5nZWQgICAgIC0tLS0tLS0tLS0tLS0tICBmaWxlIGNoYW5nZWRcbiAgICAvLyB8ICAgICAgICAgICAgfCAgcmVhZHkgZXZlbnQgICB8ICAgICAgfCAtLS0tLS0tLS0tLS0tLS0tLS0+IHwgICAgICAgICAgICB8IC0tLS0tLS0tLS0tLS0tLS0tLT4gfCAgICAgICAgICAgIHwgLS0tLS0tLS0tLS0tLS18XG4gICAgLy8gfCBwcmUtcmVhZHkgIHwgLS0tLS0tLS0tLS0tLT4gfCBvcGVuIHwgICAgICAgICAgICAgICAgICAgICB8IGRlcGxveWluZyAgfCAgICAgICAgICAgICAgICAgICAgIHwgICBxdWV1ZWQgICB8ICAgICAgICAgICAgICAgfFxuICAgIC8vIHwgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwgICAgICB8IDwtLS0tLS0tLS0tLS0tLS0tLS0gfCAgICAgICAgICAgIHwgPC0tLS0tLS0tLS0tLS0tLS0tLSB8ICAgICAgICAgICAgfCA8LS0tLS0tLS0tLS0tLXxcbiAgICAvLyAtLS0tLS0tLS0tLS0tLSAgICAgICAgICAgICAgICAtLS0tLS0tLSAgJ2NkayBkZXBsb3knIGRvbmUgIC0tLS0tLS0tLS0tLS0tICAnY2RrIGRlcGxveScgZG9uZSAgLS0tLS0tLS0tLS0tLS1cbiAgICBsZXQgbGF0Y2g6ICdwcmUtcmVhZHknIHwgJ29wZW4nIHwgJ2RlcGxveWluZycgfCAncXVldWVkJyA9ICdwcmUtcmVhZHknO1xuXG4gICAgY29uc3QgY2xvdWRXYXRjaExvZ01vbml0b3IgPSBvcHRpb25zLnRyYWNlTG9ncyA/IG5ldyBDbG91ZFdhdGNoTG9nRXZlbnRNb25pdG9yKHtcbiAgICAgIGlvSGVscGVyLFxuICAgIH0pIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGRlcGxveUFuZFdhdGNoID0gYXN5bmMgKCkgPT4ge1xuICAgICAgbGF0Y2ggPSAnZGVwbG95aW5nJztcbiAgICAgIGF3YWl0IGNsb3VkV2F0Y2hMb2dNb25pdG9yPy5kZWFjdGl2YXRlKCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW52b2tlRGVwbG95RnJvbVdhdGNoKG9wdGlvbnMsIGNsb3VkV2F0Y2hMb2dNb25pdG9yKTtcblxuICAgICAgLy8gSWYgbGF0Y2ggaXMgc3RpbGwgJ2RlcGxveWluZycgYWZ0ZXIgdGhlICdhd2FpdCcsIHRoYXQncyBmaW5lLFxuICAgICAgLy8gYnV0IGlmIGl0J3MgJ3F1ZXVlZCcsIHRoYXQgbWVhbnMgd2UgbmVlZCB0byBkZXBsb3kgYWdhaW5cbiAgICAgIHdoaWxlICgobGF0Y2ggYXMgJ2RlcGxveWluZycgfCAncXVldWVkJykgPT09ICdxdWV1ZWQnKSB7XG4gICAgICAgIC8vIFR5cGVTY3JpcHQgZG9lc24ndCByZWFsaXplIGxhdGNoIGNhbiBjaGFuZ2UgYmV0d2VlbiAnYXdhaXRzJyxcbiAgICAgICAgLy8gYW5kIHRoaW5rcyB0aGUgYWJvdmUgJ3doaWxlJyBjb25kaXRpb24gaXMgYWx3YXlzICdmYWxzZScgd2l0aG91dCB0aGUgY2FzdFxuICAgICAgICBsYXRjaCA9ICdkZXBsb3lpbmcnO1xuICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhcIkRldGVjdGVkIGZpbGUgY2hhbmdlcyBkdXJpbmcgZGVwbG95bWVudC4gSW52b2tpbmcgJ2NkayBkZXBsb3knIGFnYWluXCIpO1xuICAgICAgICBhd2FpdCB0aGlzLmludm9rZURlcGxveUZyb21XYXRjaChvcHRpb25zLCBjbG91ZFdhdGNoTG9nTW9uaXRvcik7XG4gICAgICB9XG4gICAgICBsYXRjaCA9ICdvcGVuJztcbiAgICAgIGF3YWl0IGNsb3VkV2F0Y2hMb2dNb25pdG9yPy5hY3RpdmF0ZSgpO1xuICAgIH07XG5cbiAgICAvLyBDcmVhdGUgaWdub3JlIG1hdGNoZXIgZm9yIGNob2tpZGFyIHY0IGNvbXBhdGliaWxpdHlcbiAgICAvLyBDaG9raWRhciB2NCByZW1vdmVkIGdsb2IgcGF0dGVybiBzdXBwb3J0LCBzbyB3ZSB1c2UgcGljb21hdGNoIHRvIGZpbHRlciBmaWxlc1xuICAgIC8vIFdlIHBhc3Mgcm9vdERpciBiZWNhdXNlIGNob2tpZGFyIHY0IHBhc3NlcyBhYnNvbHV0ZSBwYXRocyB0byB0aGUgaWdub3JlZCBjYWxsYmFja1xuICAgIGNvbnN0IHNob3VsZElnbm9yZSA9IGNyZWF0ZUlnbm9yZU1hdGNoZXIoe1xuICAgICAgaW5jbHVkZTogd2F0Y2hJbmNsdWRlcyxcbiAgICAgIGV4Y2x1ZGU6IHdhdGNoRXhjbHVkZXMsXG4gICAgICByb290RGlyLFxuICAgIH0pO1xuXG4gICAgY2hva2lkYXJcbiAgICAgIC53YXRjaCgnLicsIHtcbiAgICAgICAgaWdub3JlZDogc2hvdWxkSWdub3JlLFxuICAgICAgICBjd2Q6IHJvb3REaXIsXG4gICAgICB9KVxuICAgICAgLm9uKCdyZWFkeScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbGF0Y2ggPSAnb3Blbic7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5kZWJ1ZyhcIid3YXRjaCcgcmVjZWl2ZWQgdGhlICdyZWFkeScgZXZlbnQuIEZyb20gbm93IG9uLCBhbGwgZmlsZSBjaGFuZ2VzIHdpbGwgdHJpZ2dlciBhIGRlcGxveW1lbnRcIik7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKFwiVHJpZ2dlcmluZyBpbml0aWFsICdjZGsgZGVwbG95J1wiKTtcbiAgICAgICAgYXdhaXQgZGVwbG95QW5kV2F0Y2goKTtcbiAgICAgIH0pXG4gICAgICAub24oJ2FsbCcsIGFzeW5jIChldmVudDogRXZlbnROYW1lLCBmaWxlUGF0aD86IHN0cmluZykgPT4ge1xuICAgICAgICBpZiAoIWlzRmlsZUV2ZW50KGV2ZW50KSkge1xuICAgICAgICAgIHJldHVybjsgLy8gSWdub3JlIG5vbi1maWxlIGV2ZW50cyBsaWtlICdlcnJvcicsICdyYXcnLCAncmVhZHknLCAnYWxsJ1xuICAgICAgICB9XG4gICAgICAgIGlmIChsYXRjaCA9PT0gJ3ByZS1yZWFkeScpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgJ3dhdGNoJyBpcyBvYnNlcnZpbmcgJHtldmVudCA9PT0gJ2FkZERpcicgPyAnZGlyZWN0b3J5JyA6ICd0aGUgZmlsZSd9ICclcycgZm9yIGNoYW5nZXNgLCBmaWxlUGF0aCk7XG4gICAgICAgIH0gZWxzZSBpZiAobGF0Y2ggPT09ICdvcGVuJykge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKFwiRGV0ZWN0ZWQgY2hhbmdlIHRvICclcycgKHR5cGU6ICVzKS4gVHJpZ2dlcmluZyAnY2RrIGRlcGxveSdcIiwgZmlsZVBhdGgsIGV2ZW50KTtcbiAgICAgICAgICBhd2FpdCBkZXBsb3lBbmRXYXRjaCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHRoaXMgbWVhbnMgbGF0Y2ggaXMgZWl0aGVyICdkZXBsb3lpbmcnIG9yICdxdWV1ZWQnXG4gICAgICAgICAgbGF0Y2ggPSAncXVldWVkJztcbiAgICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhcbiAgICAgICAgICAgIFwiRGV0ZWN0ZWQgY2hhbmdlIHRvICclcycgKHR5cGU6ICVzKSB3aGlsZSAnY2RrIGRlcGxveScgaXMgc3RpbGwgcnVubmluZy4gXCIgK1xuICAgICAgICAgICAgJ1dpbGwgcXVldWUgZm9yIGFub3RoZXIgZGVwbG95bWVudCBhZnRlciB0aGlzIG9uZSBmaW5pc2hlcycsXG4gICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIG9ycGhhbihvcHRpb25zOiBPcnBoYW5PcHRpb25zKSB7XG4gICAgYXdhaXQgdGhpcy50b29sa2l0Lm9ycGhhbih0aGlzLnByb3BzLmNsb3VkRXhlY3V0YWJsZSwge1xuICAgICAgY29uc3RydWN0UGF0aHM6IG9wdGlvbnMuY29uc3RydWN0UGF0aCxcbiAgICAgIHJvbGVBcm46IG9wdGlvbnMucm9sZUFybixcbiAgICAgIHRvb2xraXRTdGFja05hbWU6IG9wdGlvbnMudG9vbGtpdFN0YWNrTmFtZSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBpbXBvcnQob3B0aW9uczogSW1wb3J0T3B0aW9ucykge1xuICAgIGNvbnN0IGFzc2VtYmx5ID0gYXdhaXQgdGhpcy5hc3NlbWJseSgpO1xuICAgIGNvbnN0IHN0YWNrcyA9IGF3YWl0IGFzc2VtYmx5LnNlbGVjdFN0YWNrc1YyKG9wdGlvbnMuc2VsZWN0b3IpO1xuICAgIGF3YWl0IHRoaXMudmFsaWRhdGVTdGFja3MoYXNzZW1ibHksIHN0YWNrcyk7XG5cbiAgICAvLyBzZXQgcHJvZ3Jlc3MgZnJvbSBvcHRpb25zLCB0aGlzIGluY2x1ZGVzIHVzZXIgYW5kIGFwcCBjb25maWdcbiAgICBpZiAob3B0aW9ucy5wcm9ncmVzcykge1xuICAgICAgdGhpcy5pb0hvc3Quc3RhY2tQcm9ncmVzcyA9IG9wdGlvbnMucHJvZ3Jlc3M7XG4gICAgfVxuXG4gICAgaWYgKHN0YWNrcy5zdGFja0NvdW50ID4gMSkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgJ0FtYmlndW91c1N0YWNrU2VsZWN0aW9uJyxcbiAgICAgICAgYFN0YWNrIHNlbGVjdGlvbiBpcyBhbWJpZ3VvdXMsIHBsZWFzZSBjaG9vc2UgYSBzcGVjaWZpYyBzdGFjayBmb3IgaW1wb3J0IFske3N0YWNrcy5zdGFja0FydGlmYWN0cy5tYXAoKHgpID0+IHguaWQpLmpvaW4oJywgJyl9XWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICghcHJvY2Vzcy5zdGRvdXQuaXNUVFkgJiYgIW9wdGlvbnMucmVzb3VyY2VNYXBwaW5nRmlsZSAmJiAhb3B0aW9ucy5yZXNvdXJjZU1hcHBpbmdJbmxpbmUpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1Jlc291cmNlTWFwcGluZ1JlcXVpcmVkJywgJy0tcmVzb3VyY2UtbWFwcGluZyBvciAtLXJlc291cmNlLW1hcHBpbmctaW5saW5lIGlzIHJlcXVpcmVkIHdoZW4gaW5wdXQgaXMgbm90IGEgdGVybWluYWwnKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFjayA9IHN0YWNrcy5zdGFja0FydGlmYWN0c1swXTtcblxuICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKGNoYWxrLmJvbGQoc3RhY2suZGlzcGxheU5hbWUpKTtcblxuICAgIGNvbnN0IHJlc291cmNlSW1wb3J0ZXIgPSBuZXcgUmVzb3VyY2VJbXBvcnRlcihzdGFjaywge1xuICAgICAgZGVwbG95bWVudHM6IHRoaXMucHJvcHMuZGVwbG95bWVudHMsXG4gICAgICBpb0hlbHBlcjogYXNJb0hlbHBlcih0aGlzLmlvSG9zdCwgJ2ltcG9ydCcpLFxuICAgIH0pO1xuICAgIGNvbnN0IHsgYWRkaXRpb25zLCBoYXNOb25BZGRpdGlvbnMsIGRpZmZGb3JtYXR0ZXIgfSA9IGF3YWl0IHJlc291cmNlSW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKG9wdGlvbnMuZm9yY2UpO1xuXG4gICAgLy8gSWYgdGhlcmUgYXJlIG5vbi1hZGRpdGlvbiBjaGFuZ2VzIChlLmcuIGFmdGVyIG9ycGhhbiwgaGFyZGNvZGVkIHJlZnMgZGlmZmVyIGZyb20gRm46OkdldEF0dCksXG4gICAgLy8gd2FybiB0aGUgdXNlciBhbmQgYXNrIGZvciBjb25maXJtYXRpb24gdW5sZXNzIC0tZm9yY2Ugd2FzIGdpdmVuLlxuICAgIGlmIChoYXNOb25BZGRpdGlvbnMgJiYgIW9wdGlvbnMuZm9yY2UpIHtcbiAgICAgIGNvbnN0IGlvSGVscGVyID0gdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpO1xuICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbyhcbiAgICAgICAgYFRoZSBmb2xsb3dpbmcgcmVzb3VyY2VzIGhhdmUgcGVuZGluZyB1cGRhdGVzIHRoYXQgd2lsbCBiZSByZWNvbmNpbGVkIHdpdGggYSAke2NoYWxrLmJsdWVCcmlnaHQoJ2NkayBkZXBsb3knKX0gYWZ0ZXIgaW1wb3J0OmAsXG4gICAgICApO1xuICAgICAgY29uc3QgeyBmb3JtYXR0ZWREaWZmIH0gPSBkaWZmRm9ybWF0dGVyLmZvcm1hdFN0YWNrRGlmZigpO1xuICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbyhmb3JtYXR0ZWREaWZmKTtcbiAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IGF3YWl0IGlvSGVscGVyLnJlcXVlc3RSZXNwb25zZShJTy5DREtfVE9PTEtJVF9JNzAxMC5yZXEoJ1BlcmZvcm0gaW1wb3J0PycsIHsgbW90aXZhdGlvbjogJ0NvbmZpcm0gaW1wb3J0IHdpdGggcGVuZGluZyBkcmlmdCcgfSkpO1xuICAgICAgaWYgKCFjb25maXJtZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEFib3J0RXJyb3IoJ0ltcG9ydEFib3J0ZWQnLCAnSW1wb3J0IGNhbmNlbGxlZCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChhZGRpdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMud2FybihcbiAgICAgICAgJyVzOiBubyBuZXcgcmVzb3VyY2VzIGNvbXBhcmVkIHRvIHRoZSBjdXJyZW50bHkgZGVwbG95ZWQgc3RhY2ssIHNraXBwaW5nIGltcG9ydC4nLFxuICAgICAgICBjaGFsay5ib2xkKHN0YWNrLmRpc3BsYXlOYW1lKSxcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJlcGFyZSBhIG1hcHBpbmcgb2YgcGh5c2ljYWwgcmVzb3VyY2VzIHRvIENESyBjb25zdHJ1Y3RzXG4gICAgbGV0IGFjdHVhbEltcG9ydDogQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiByZXNvdXJjZUltcG9ydGVyLmFza0ZvclJlc291cmNlSWRlbnRpZmllcnM+PjtcbiAgICBpZiAob3B0aW9ucy5yZXNvdXJjZU1hcHBpbmdJbmxpbmUpIHtcbiAgICAgIGFjdHVhbEltcG9ydCA9IGF3YWl0IHJlc291cmNlSW1wb3J0ZXIubG9hZFJlc291cmNlSWRlbnRpZmllcnMoYWRkaXRpb25zLCBvcHRpb25zLnJlc291cmNlTWFwcGluZ0lubGluZSk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnJlc291cmNlTWFwcGluZ0ZpbGUpIHtcbiAgICAgIGFjdHVhbEltcG9ydCA9IGF3YWl0IHJlc291cmNlSW1wb3J0ZXIubG9hZFJlc291cmNlSWRlbnRpZmllcnNGcm9tRmlsZShhZGRpdGlvbnMsIG9wdGlvbnMucmVzb3VyY2VNYXBwaW5nRmlsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFjdHVhbEltcG9ydCA9IGF3YWl0IHJlc291cmNlSW1wb3J0ZXIuYXNrRm9yUmVzb3VyY2VJZGVudGlmaWVycyhhZGRpdGlvbnMpO1xuICAgIH1cblxuICAgIGlmIChhY3R1YWxJbXBvcnQuaW1wb3J0UmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oJ05vIHJlc291cmNlcyBzZWxlY3RlZCBmb3IgaW1wb3J0LicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIFwiLS1jcmVhdGUtcmVzb3VyY2UtbWFwcGluZ1wiIG9wdGlvbiB3YXMgcGFzc2VkLCB3cml0ZSB0aGUgcmVzb3VyY2UgbWFwcGluZyB0byB0aGUgZ2l2ZW4gZmlsZSBhbmQgZXhpdFxuICAgIGlmIChvcHRpb25zLnJlY29yZFJlc291cmNlTWFwcGluZykge1xuICAgICAgY29uc3Qgb3V0cHV0RmlsZSA9IG9wdGlvbnMucmVjb3JkUmVzb3VyY2VNYXBwaW5nO1xuICAgICAgZnMuZW5zdXJlRmlsZVN5bmMob3V0cHV0RmlsZSk7XG4gICAgICBhd2FpdCBmcy53cml0ZUpzb24ob3V0cHV0RmlsZSwgYWN0dWFsSW1wb3J0LnJlc291cmNlTWFwLCB7XG4gICAgICAgIHNwYWNlczogMixcbiAgICAgICAgZW5jb2Rpbmc6ICd1dGY4JyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oJyVzOiBtYXBwaW5nIGZpbGUgd3JpdHRlbi4nLCBvdXRwdXRGaWxlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGb2xsb3dpbmcgYXJlIHRoZSBzYW1lIHNlbWFudGljcyB3ZSBhcHBseSB3aXRoIHJlc3BlY3QgdG8gTm90aWZpY2F0aW9uIEFSTnMgKGRpY3RhdGVkIGJ5IHRoZSBTREspXG4gICAgLy9cbiAgICAvLyAgLSB1bmRlZmluZWQgID0+ICBjZGsgaWdub3JlcyBpdCwgYXMgaWYgaXQgd2Fzbid0IHN1cHBvcnRlZCAoYWxsb3dzIGV4dGVybmFsIG1hbmFnZW1lbnQpLlxuICAgIC8vICAtIFtdOiAgICAgICAgPT4gIGNkayBtYW5hZ2VzIGl0LCBhbmQgdGhlIHVzZXIgd2FudHMgdG8gd2lwZSBpdCBvdXQuXG4gICAgLy8gIC0gWydhcm4tMSddICA9PiAgY2RrIG1hbmFnZXMgaXQsIGFuZCB0aGUgdXNlciB3YW50cyB0byBzZXQgaXQgdG8gWydhcm4tMSddLlxuICAgIGNvbnN0IG5vdGlmaWNhdGlvbkFybnMgPSAoISFvcHRpb25zLm5vdGlmaWNhdGlvbkFybnMgfHwgISFzdGFjay5ub3RpZmljYXRpb25Bcm5zKVxuICAgICAgPyAob3B0aW9ucy5ub3RpZmljYXRpb25Bcm5zID8/IFtdKS5jb25jYXQoc3RhY2subm90aWZpY2F0aW9uQXJucyA/PyBbXSlcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgZm9yIChjb25zdCBub3RpZmljYXRpb25Bcm4gb2Ygbm90aWZpY2F0aW9uQXJucyA/PyBbXSkge1xuICAgICAgaWYgKCF2YWxpZGF0ZVNuc1RvcGljQXJuKG5vdGlmaWNhdGlvbkFybikpIHtcbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignSW52YWxpZFNuc1RvcGljQXJuJywgYE5vdGlmaWNhdGlvbiBhcm4gJHtub3RpZmljYXRpb25Bcm59IGlzIG5vdCBhIHZhbGlkIGFybiBmb3IgYW4gU05TIHRvcGljYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW1wb3J0IHRoZSByZXNvdXJjZXMgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBtYXBwaW5nXG4gICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oJyVzOiBpbXBvcnRpbmcgcmVzb3VyY2VzIGludG8gc3RhY2suLi4nLCBjaGFsay5ib2xkKHN0YWNrLmRpc3BsYXlOYW1lKSk7XG4gICAgY29uc3QgdGFncyA9IHRhZ3NGb3JTdGFjayhzdGFjayk7XG4gICAgYXdhaXQgcmVzb3VyY2VJbXBvcnRlci5pbXBvcnRSZXNvdXJjZXNGcm9tTWFwKGFjdHVhbEltcG9ydCwge1xuICAgICAgcm9sZUFybjogb3B0aW9ucy5yb2xlQXJuLFxuICAgICAgdGFncyxcbiAgICAgIGRlcGxveW1lbnRNZXRob2Q6IG9wdGlvbnMuZGVwbG95bWVudE1ldGhvZCxcbiAgICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgICAgIHJvbGxiYWNrOiBvcHRpb25zLnJvbGxiYWNrLFxuICAgICAgbm90aWZpY2F0aW9uQXJucyxcbiAgICB9KTtcblxuICAgIC8vIE5vdGlmeSB1c2VyIG9mIG5leHQgc3RlcHNcbiAgICBpZiAoYWN0dWFsSW1wb3J0LmltcG9ydFJlc291cmNlcy5sZW5ndGggPCBhZGRpdGlvbnMubGVuZ3RoKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMud2FybihcbiAgICAgICAgYFNvbWUgcmVzb3VyY2VzIHdlcmUgc2tpcHBlZC4gUnVuIGFub3RoZXIgJHtjaGFsay5ibHVlQnJpZ2h0KCdjZGsgaW1wb3J0Jyl9IG9yIGEgJHtjaGFsay5ibHVlQnJpZ2h0KCdjZGsgZGVwbG95Jyl9IHRvIGJyaW5nIHRoZSBzdGFjayB1cC10by1kYXRlIHdpdGggeW91ciBDREsgYXBwIGRlZmluaXRpb24uYCxcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChoYXNOb25BZGRpdGlvbnMpIHtcbiAgICAgIC8vIEFmdGVyIG9ycGhhbuKGkmltcG9ydCwgdGhlIGRlcGxveWVkIHRlbXBsYXRlIHN0aWxsIGhhcyBoYXJkY29kZWQgdmFsdWVzIHRoYXQgZGlmZmVyIGZyb21cbiAgICAgIC8vIHRoZSBzeW50aCdkIHRlbXBsYXRlJ3MgRm46OkdldEF0dC9SZWYgaW50cmluc2ljcy4gQSBkZXBsb3kgdXBkYXRlcyB0aGUgdGVtcGxhdGUgdG8gbWF0Y2ggdGhlIENESyBhcHAuXG4gICAgICBpZiAob3B0aW9ucy5mb3JjZSkge1xuICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhcbiAgICAgICAgICBgSW1wb3J0IGNvbXBsZXRlLiBSdW4gJHtjaGFsay5ibHVlQnJpZ2h0KCdjZGsgZGVwbG95Jyl9IHRvIHVwZGF0ZSB0aGUgc3RhY2sgdG8gbWF0Y2ggeW91ciBDREsgYXBwLmAsXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkZXBsb3lOb3cgPSBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkucmVxdWVzdFJlc3BvbnNlKFxuICAgICAgICAgIElPLkNES19UT09MS0lUX0k3MDEwLnJlcShgRmluaXNoIHdpdGggYSAke2NoYWxrLmJsdWVCcmlnaHQoJ2NkayBkZXBsb3knKX0gbm93P2AsIHsgbW90aXZhdGlvbjogJ1VwZGF0ZSBzdGFjayB0byBtYXRjaCBDREsgYXBwIGFmdGVyIGltcG9ydCcgfSksXG4gICAgICAgICk7XG4gICAgICAgIGlmIChkZXBsb3lOb3cpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmRlcGxveSh7XG4gICAgICAgICAgICAvLyBUaGUgaW1wb3J0IHNlbGVjdG9yIGlzIGV4YWN0IChubyBleHBhbnNpb24pOyB0aGUgZm9sbG93LXVwIGRlcGxveVxuICAgICAgICAgICAgLy8gaGlzdG9yaWNhbGx5IGV4cGFuZHMgdG8gdXBzdHJlYW0gZGVwZW5kZW5jaWVzIGxpa2UgYSBwbGFpbiBkZXBsb3kuXG4gICAgICAgICAgICBzZWxlY3RvcjogeyAuLi5vcHRpb25zLnNlbGVjdG9yLCBleHBhbmQ6IEV4cGFuZFN0YWNrU2VsZWN0aW9uLlVQU1RSRUFNIH0sXG4gICAgICAgICAgICB0b29sa2l0U3RhY2tOYW1lOiBvcHRpb25zLnRvb2xraXRTdGFja05hbWUsXG4gICAgICAgICAgICByb2xlQXJuOiBvcHRpb25zLnJvbGVBcm4sXG4gICAgICAgICAgICBkZXBsb3ltZW50TWV0aG9kOiBvcHRpb25zLmRlcGxveW1lbnRNZXRob2QsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oXG4gICAgICAgICAgICBgSW1wb3J0IGNvbXBsZXRlLiBSZW1lbWJlciB0byBydW4gJHtjaGFsay5ibHVlQnJpZ2h0KCdjZGsgZGVwbG95Jyl9IHRvIHVwZGF0ZSB0aGUgc3RhY2sgdG8gbWF0Y2ggeW91ciBDREsgYXBwLmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhcbiAgICAgICAgYEltcG9ydCBvcGVyYXRpb24gY29tcGxldGUuIFdlIHJlY29tbWVuZCB5b3UgcnVuIGEgJHtjaGFsay5ibHVlQnJpZ2h0KCdkcmlmdCBkZXRlY3Rpb24nKX0gb3BlcmF0aW9uIGAgK1xuICAgICAgICAndG8gY29uZmlybSB5b3VyIENESyBhcHAgcmVzb3VyY2UgZGVmaW5pdGlvbnMgYXJlIHVwLXRvLWRhdGUuIFJlYWQgbW9yZSBoZXJlOiAnICtcbiAgICAgICAgY2hhbGsudW5kZXJsaW5lLmJsdWVCcmlnaHQoXG4gICAgICAgICAgJ2h0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2RldGVjdC1kcmlmdC1zdGFjay5odG1sJyxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gVGhlIGRlc3Ryb3kgYWN0aW9uIHJ1bnMgdGhyb3VnaCB0b29sa2l0LWxpYi5cbiAgLy8gU3VwcHJlc3MgaXRzIG5ldyBzdGF0dXMgbWVzc2FnZXMgdG8ga2VlcCB0aGUgb3V0cHV0IGFzIGl0IHdhcyBiZWZvcmUuXG4gIEBzdXBwcmVzc01lc3NhZ2VzKFxuICAgIElPLkNES19UT09MS0lUX0kxMDAxLCAvLyBTdGFydGluZyBTeW50aGVzaXMgKHRyYWNlKVxuICAgIElPLkNES19UT09MS0lUX0kxMDAwLCAvLyDinKggU3ludGhlc2lzIHRpbWUgKGluZm8pXG4gICAgSU8uQ0RLX1RPT0xLSVRfSTcxMDEsIC8vIFN0YXJ0aW5nIERlc3Ryb3kgKHRyYWNlKVxuICAgIElPLkNES19UT09MS0lUX0k3MDAxLCAvLyBwZXItc3RhY2sgRGVzdHJveSB0aW1lICh0cmFjZSlcbiAgICBJTy5DREtfVE9PTEtJVF9JNzAwMCwgLy8g4pyoIERlc3Ryb3kgdGltZSAoaW5mbylcbiAgKVxuICBwdWJsaWMgYXN5bmMgZGVzdHJveShvcHRpb25zOiBEZXN0cm95T3B0aW9ucykge1xuICAgIC8vIEtlZXAgdGhlIFwiZGVwbG95ZWRcIiB3b3JkaW5nIHdoZW4gYSBkZXN0cm95IHJ1bnMgYXMgcGFydCBvZiBhIGRlcGxveS5cbiAgICBjb25zdCBhY3Rpb24gPSBvcHRpb25zLmZyb21EZXBsb3kgPyAnZGVwbG95JyA6ICdkZXN0cm95JztcblxuICAgIGlmICgob3B0aW9ucy5jb25jdXJyZW5jeSB8fCAxKSA+IDEgJiYgdGhpcy5pb0hvc3Quc3RhY2tQcm9ncmVzcyA9PT0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJBUikge1xuICAgICAgdGhpcy5pb0hvc3Quc3RhY2tQcm9ncmVzcyA9IFN0YWNrQWN0aXZpdHlQcm9ncmVzcy5FVkVOVFM7XG4gICAgfVxuXG4gICAgLy8gVGhlIHN1Y2Nlc3MgbGluZSB3YXMgYGluZm9gIGluIHRoZSBoaXN0b3JpY2FsIGBjZGsgZGVzdHJveWAsIG5vdCBgcmVzdWx0YC5cbiAgICB1c2luZyBfc3VjY2Vzc0xldmVsID0gdGhpcy5pb0hvc3Qub24oSU8uQ0RLX1RPT0xLSVRfSTc5MDAsICgpID0+ICh7IGxldmVsOiAnaW5mbycgfSkpOyAvLyDinIUgPHN0YWNrPjogZGVzdHJveWVkXG5cbiAgICAvLyB0b29sa2l0LWxpYiBsb2dzIGEgZGVjbGluZWQgY29uZmlybWF0aW9uIChFNzAxMCkgYW5kIHJldHVybnMgZ3JhY2VmdWxseS5cbiAgICAvLyBUaGUgQ0xJIHN1cmZhY2VzIGEgZGVjbGluZSBhcyBhIG5vbi16ZXJvLCBzb2Z0IGV4aXQgaW5zdGVhZDogdGhyb3dpbmcgZnJvbVxuICAgIC8vIHRoZSBsaXN0ZW5lciBib3RoIHN1cHByZXNzZXMgdGhlIGxvZyBhbmQgYWJvcnRzIHRoZSBjb21tYW5kICh0aGUgdG9wLWxldmVsXG4gICAgLy8gcmVuZGVycyBgQWJvcnRFcnJvcmAgYXMgXCJEZWxldGlvbiBjYW5jZWxsZWRcIikuXG4gICAgdXNpbmcgX2RlY2xpbmVBYm9ydHMgPSB0aGlzLmlvSG9zdC5vbihJTy5DREtfVE9PTEtJVF9FNzAxMCwgKCkgPT4ge1xuICAgICAgdGhyb3cgbmV3IEFib3J0RXJyb3IoJ0Rlc3Ryb3lBYm9ydGVkJywgJ0RlbGV0aW9uIGNhbmNlbGxlZCcpO1xuICAgIH0pO1xuXG4gICAgdXNpbmcgX2ZvcmNlQ29uZmlybXMgPSBvcHRpb25zLmZvcmNlID8gdGhpcy5pb0hvc3QucmVzcG9uZE9uY2UoSU8uQ0RLX1RPT0xLSVRfSTcwMTAsIHRydWUpIDogdW5kZWZpbmVkO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgIC8vIEB0cy1pZ25vcmUgLSBgX2Rlc3Ryb3lXaXRoQWN0aW9uYCBpcyBwcml2YXRlOyB0aGUgQ0xJIHNldHMgdGhlIGFjdGlvbiBsYWJlbC5cbiAgICBhd2FpdCB0aGlzLnRvb2xraXQuX2Rlc3Ryb3lXaXRoQWN0aW9uKHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLCBhY3Rpb24sIHtcbiAgICAgIHN0YWNrczogb3B0aW9ucy5zZWxlY3RvcixcbiAgICAgIHJvbGVBcm46IG9wdGlvbnMucm9sZUFybixcbiAgICAgIGNvbmN1cnJlbmN5OiBvcHRpb25zLmNvbmN1cnJlbmN5LFxuICAgICAgZXhwcmVzczogb3B0aW9ucy5leHByZXNzLFxuICAgIH0pO1xuICB9XG5cbiAgLy8gY2RrIGxzIHN0ZG91dCBpcyB0aGUgc3RhY2sgbGlzdGluZyBvbmx5LiBTdXBwcmVzcyB0aGUgaW5mbyBzdGF0dXMgbGluZXMgc3ludGhlc2lzIGVtaXRzIG5leHRcbiAgLy8gdG8gaXQ6IHRoZSBzeW50aC10aW1lIGxpbmUgKEkxMDAwKSBhbmQgdGhlIGRlcGVuZGVuY3ktZXhwYW5zaW9uIG5vdGUgKEkxMDAyKS5cbiAgQHN1cHByZXNzTWVzc2FnZXMoSU8uQ0RLX1RPT0xLSVRfSTEwMDAsIElPLkNES19UT09MS0lUX0kxMDAyKVxuICBwdWJsaWMgYXN5bmMgbGlzdChcbiAgICBzZWxlY3RvcnM6IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IHsgbG9uZz86IGJvb2xlYW47IGpzb24/OiBib29sZWFuOyBzaG93RGVwcz86IGJvb2xlYW4gfSA9IHt9LFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIC8vIE9uZS1zaG90OiBkaXNwb3NlcyBpdHNlbGYgd2hlbiB0aGUgbGlzdGluZyAoSTI5MDEpIGlzIGVtaXR0ZWQ7IHRoZVxuICAgIC8vIGB1c2luZ2AgY292ZXJzIHRoZSBjYXNlIHdoZXJlIGBsaXN0YCB0aHJvd3MgYmVmb3JlIHRoYXQgaGFwcGVucy5cbiAgICB1c2luZyBfZm9ybWF0dGVyID0gdGhpcy5pb0hvc3QucmV3cml0ZU9uY2UoSU8uQ0RLX1RPT0xLSVRfSTI5MDEsIChtc2cpID0+IGZvcm1hdFN0YWNrTGlzdChtc2cuZGF0YS5zdGFja3MsIG9wdGlvbnMpKTtcblxuICAgIGF3YWl0IHRoaXMudG9vbGtpdC5saXN0KHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLCB7XG4gICAgICBzdGFja3M6IHNlbGVjdG9ycy5sZW5ndGggPiAwID8gc2VsZWN0V2l0aFVwc3RyZWFtKC4uLnNlbGVjdG9ycykgOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gMDsgLy8gZXhpdC1jb2RlXG4gIH1cblxuICAvKipcbiAgICogU3ludGhlc2l6ZSB0aGUgZ2l2ZW4gc2V0IG9mIHN0YWNrcyAoY2FsbGVkIHdoZW4gdGhlIHVzZXIgcnVucyAnY2RrIHN5bnRoJylcbiAgICpcbiAgICogSU5QVVQ6IFN0YWNrIG5hbWVzIGNhbiBiZSBzdXBwbGllZCB1c2luZyBhIGdsb2IgZmlsdGVyLiBJZiBubyBzdGFja3MgYXJlXG4gICAqIGdpdmVuLCBhbGwgc3RhY2tzIGZyb20gdGhlIGFwcGxpY2F0aW9uIGFyZSBpbXBsaWNpdGx5IHNlbGVjdGVkLlxuICAgKlxuICAgKiBPVVRQVVQ6IElmIG1vcmUgdGhhbiBvbmUgc3RhY2sgZW5kcyB1cCBiZWluZyBzZWxlY3RlZCwgYW4gb3V0cHV0IGRpcmVjdG9yeVxuICAgKiBzaG91bGQgYmUgc3VwcGxpZWQsIHdoZXJlIHRoZSB0ZW1wbGF0ZXMgd2lsbCBiZSB3cml0dGVuLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHN5bnRoKG9wdGlvbnM6IFN5bnRoT3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3Qgc3RhY2tOYW1lcyA9IG9wdGlvbnMuc3RhY2tOYW1lcztcbiAgICBjb25zdCBleGNsdXNpdmVseSA9IG9wdGlvbnMuZXhjbHVzaXZlbHkgPz8gZmFsc2U7XG4gICAgY29uc3QgcXVpZXQgPSBvcHRpb25zLnF1aWV0ID8/IGZhbHNlO1xuICAgIGNvbnN0IGF1dG9WYWxpZGF0ZSA9IG9wdGlvbnMuYXV0b1ZhbGlkYXRlID8/IGZhbHNlO1xuICAgIGNvbnN0IGpzb24gPSBvcHRpb25zLmpzb24gPz8gZmFsc2U7XG5cbiAgICBjb25zdCBhc3NlbWJseSA9IGF3YWl0IHRoaXMuYXNzZW1ibHkoKTtcbiAgICBjb25zdCBzdGFja3MgPSBhd2FpdCB0aGlzLnNlbGVjdFRvcExldmVsT3JNYXRjaGluZ1N0YWNrcyhhc3NlbWJseSwgc3RhY2tOYW1lcywgZXhjbHVzaXZlbHkpO1xuXG4gICAgY29uc3QgYXV0b1ZhbGlkYXRlU3RhY2tzID0gYXV0b1ZhbGlkYXRlXG4gICAgICA/IGFzc2VtYmx5LnNlbGVjdFN0YWNrc0ZvclZhbGlkYXRpb24oKVxuICAgICAgOiBuZXcgU3RhY2tDb2xsZWN0aW9uKGFzc2VtYmx5LCBbXSk7XG5cbiAgICBhd2FpdCB0aGlzLnZhbGlkYXRlU3RhY2tzKGFzc2VtYmx5LCBzdGFja3MuY29uY2F0KGF1dG9WYWxpZGF0ZVN0YWNrcykpO1xuXG4gICAgLy8gaWYgd2UgaGF2ZSBhIHNpbmdsZSBzdGFjaywgcHJpbnQgaXQgdG8gU1RET1VUXG4gICAgaWYgKHN0YWNrcy5zdGFja0NvdW50ID09PSAxKSB7XG4gICAgICBpZiAoIXF1aWV0KSB7XG4gICAgICAgIGF3YWl0IHByaW50U2VyaWFsaXplZE9iamVjdCh0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCksIG9ic2N1cmVUZW1wbGF0ZShzdGFja3MuZmlyc3RTdGFjay50ZW1wbGF0ZSksIGpzb24pO1xuICAgICAgfVxuXG4gICAgICAvLyBJbiBDSSBtb2RlLCBub24tZXJyb3IgbWVzc2FnZXMgZ28gdG8gc3Rkb3V0LiBXaGVuIHdlIGp1c3QgcHJpbnRlZCB0aGVcbiAgICAgIC8vIHRlbXBsYXRlIHRvIHN0ZG91dCwgc2tpcCB0aGUgZmxhZ3MgbWVzc2FnZSB0byBwcmVzZXJ2ZSB0aGUgY29udHJhY3QgdGhhdFxuICAgICAgLy8gYGNkayBzeW50aGAgb3V0cHV0IGlzIHZhbGlkIFlBTUwuIFdoZW4gcXVpZXQgKG5vIHRlbXBsYXRlIHByaW50ZWQpIG9yXG4gICAgICAvLyBub24tQ0kgKGZsYWdzIGdvIHRvIHN0ZGVyciksIGl0J3Mgc2FmZSB0byBzaG93LlxuICAgICAgaWYgKHF1aWV0IHx8ICF0aGlzLmlvSG9zdC5pc0NJKSB7XG4gICAgICAgIGF3YWl0IGRpc3BsYXlGbGFnc01lc3NhZ2UodGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLCB0aGlzLnRvb2xraXQsIHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gbm90IG91dHB1dHRpbmcgdGVtcGxhdGUgdG8gc3Rkb3V0LCBsZXQncyBleHBsYWluIHRoaW5ncyB0byB0aGUgdXNlciBhIGxpdHRsZSBiaXQuLi5cbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhjaGFsay5ncmVlbihgU3VjY2Vzc2Z1bGx5IHN5bnRoZXNpemVkIHRvICR7Y2hhbGsuYmx1ZShwYXRoLnJlc29sdmUoc3RhY2tzLmFzc2VtYmx5LmRpcmVjdG9yeSkpfWApKTtcbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhcbiAgICAgIGBTdXBwbHkgYSBzdGFjayBpZCAoJHtzdGFja3Muc3RhY2tBcnRpZmFjdHMubWFwKChzKSA9PiBjaGFsay5ncmVlbihzLmhpZXJhcmNoaWNhbElkKSkuam9pbignLCAnKX0pIHRvIGRpc3BsYXkgaXRzIHRlbXBsYXRlLmAsXG4gICAgKTtcblxuICAgIGF3YWl0IGRpc3BsYXlGbGFnc01lc3NhZ2UodGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLCB0aGlzLnRvb2xraXQsIHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEJvb3RzdHJhcCB0aGUgQ0RLIFRvb2xraXQgc3RhY2sgaW4gdGhlIGFjY291bnRzIHVzZWQgYnkgdGhlIHNwZWNpZmllZCBzdGFjayhzKS5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJFbnZpcm9ubWVudFNwZWNzIC0gZW52aXJvbm1lbnQgbmFtZXMgdGhhdCBuZWVkIHRvIGhhdmUgdG9vbGtpdCBzdXBwb3J0XG4gICAqICAgICAgICAgICAgIHByb3Zpc2lvbmVkLCBhcyBhIGdsb2IgZmlsdGVyLiBJZiBub25lIGlzIHByb3ZpZGVkLCBhbGwgc3RhY2tzIGFyZSBpbXBsaWNpdGx5IHNlbGVjdGVkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBuYW1lLCByb2xlIEFSTiwgYm9vdHN0cmFwcGluZyBwYXJhbWV0ZXJzLCBldGMuIHRvIGJlIHVzZWQgZm9yIHRoZSBDREsgVG9vbGtpdCBzdGFjay5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBib290c3RyYXAoXG4gICAgdXNlckVudmlyb25tZW50U3BlY3M6IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYm9vdHN0cmFwcGVyID0gbmV3IEJvb3RzdHJhcHBlcihvcHRpb25zLnNvdXJjZSwgYXNJb0hlbHBlcih0aGlzLmlvSG9zdCwgJ2Jvb3RzdHJhcCcpKTtcbiAgICAvLyBJZiB0aGVyZSBpcyBhbiAnLS1hcHAnIGFyZ3VtZW50IGFuZCBhbiBlbnZpcm9ubWVudCBsb29rcyBsaWtlIGEgZ2xvYiwgd2VcbiAgICAvLyBzZWxlY3QgdGhlIGVudmlyb25tZW50cyBmcm9tIHRoZSBhcHAuIE90aGVyd2lzZSwgdXNlIHdoYXQgdGhlIHVzZXIgc2FpZC5cblxuICAgIGNvbnN0IGVudmlyb25tZW50cyA9IGF3YWl0IHRoaXMuZGVmaW5lRW52aXJvbm1lbnRzKHVzZXJFbnZpcm9ubWVudFNwZWNzKTtcblxuICAgIGNvbnN0IGxpbWl0ID0gcExpbWl0KDIwKTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICAgIGF3YWl0IFByb21pc2UuYWxsKGVudmlyb25tZW50cy5tYXAoKGVudmlyb25tZW50KSA9PiBsaW1pdChhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhjaGFsay5ncmVlbignIOKPsyAgQm9vdHN0cmFwcGluZyBlbnZpcm9ubWVudCAlcy4uLicpLCBjaGFsay5ibHVlKGVudmlyb25tZW50Lm5hbWUpKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnZpcm9ubWVudCwgdGhpcy5wcm9wcy5zZGtQcm92aWRlciwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSByZXN1bHQubm9PcFxuICAgICAgICAgID8gJ+KchSAgRW52aXJvbm1lbnQgJXMgYm9vdHN0cmFwcGVkIChubyBjaGFuZ2VzKS4nXG4gICAgICAgICAgOiAn4pyFICBFbnZpcm9ubWVudCAlcyBib290c3RyYXBwZWQuJztcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oY2hhbGsuZ3JlZW4obWVzc2FnZSksIGNoYWxrLmJsdWUoZW52aXJvbm1lbnQubmFtZSkpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmV4cHJlc3MpIHtcbiAgICAgICAgICBjb25zdCB3YXJuaW5nID0gZm9ybWF0RXhwcmVzc1N0YWJpbGl6YXRpb25XYXJuaW5nKHJlc3VsdC5zdGFiaWxpemluZ1Jlc291cmNlcywgJ2Jvb3RzdHJhcCcpO1xuICAgICAgICAgIGlmICh3YXJuaW5nKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkubm90aWZ5KElPLkNES19UT09MS0lUX1c5OTAyLm1zZyh3YXJuaW5nKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5lcnJvcignIOKdjCAgRW52aXJvbm1lbnQgJXMgZmFpbGVkIGJvb3RzdHJhcHBpbmc6ICVzJywgY2hhbGsuYmx1ZShlbnZpcm9ubWVudC5uYW1lKSwgZSk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHYXJiYWdlIGNvbGxlY3RzIGFzc2V0cyBmcm9tIGEgQ0RLIGFwcCdzIGVudmlyb25tZW50XG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyBmb3IgR2FyYmFnZSBDb2xsZWN0aW9uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2FyYmFnZUNvbGxlY3QodXNlckVudmlyb25tZW50U3BlY3M6IHN0cmluZ1tdLCBvcHRpb25zOiBHYXJiYWdlQ29sbGVjdGlvbk9wdGlvbnMpIHtcbiAgICBjb25zdCBlbnZpcm9ubWVudHMgPSBhd2FpdCB0aGlzLmRlZmluZUVudmlyb25tZW50cyh1c2VyRW52aXJvbm1lbnRTcGVjcyk7XG5cbiAgICBmb3IgKGNvbnN0IGVudmlyb25tZW50IG9mIGVudmlyb25tZW50cykge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oY2hhbGsuZ3JlZW4oJyDij7MgIEdhcmJhZ2UgQ29sbGVjdGluZyBlbnZpcm9ubWVudCAlcy4uLicpLCBjaGFsay5ibHVlKGVudmlyb25tZW50Lm5hbWUpKTtcbiAgICAgIGNvbnN0IGdjID0gbmV3IEdhcmJhZ2VDb2xsZWN0b3Ioe1xuICAgICAgICBzZGtQcm92aWRlcjogdGhpcy5wcm9wcy5zZGtQcm92aWRlcixcbiAgICAgICAgaW9IZWxwZXI6IGFzSW9IZWxwZXIodGhpcy5pb0hvc3QsICdnYycpLFxuICAgICAgICByZXNvbHZlZEVudmlyb25tZW50OiBlbnZpcm9ubWVudCxcbiAgICAgICAgYm9vdHN0cmFwU3RhY2tOYW1lOiBvcHRpb25zLmJvb3RzdHJhcFN0YWNrTmFtZSxcbiAgICAgICAgcm9sbGJhY2tCdWZmZXJEYXlzOiBvcHRpb25zLnJvbGxiYWNrQnVmZmVyRGF5cyxcbiAgICAgICAgY3JlYXRlZEJ1ZmZlckRheXM6IG9wdGlvbnMuY3JlYXRlZEJ1ZmZlckRheXMsXG4gICAgICAgIGFjdGlvbjogb3B0aW9ucy5hY3Rpb24gPz8gJ2Z1bGwnLFxuICAgICAgICB0eXBlOiBvcHRpb25zLnR5cGUgPz8gJ2FsbCcsXG4gICAgICAgIGNvbmZpcm06IG9wdGlvbnMuY29uZmlybSA/PyB0cnVlLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCBnYy5nYXJiYWdlQ29sbGVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVmaW5lRW52aXJvbm1lbnRzKHVzZXJFbnZpcm9ubWVudFNwZWNzOiBzdHJpbmdbXSk6IFByb21pc2U8Y3hhcGkuRW52aXJvbm1lbnRbXT4ge1xuICAgIC8vIEJ5IGRlZmF1bHQsIGdsb2IgZm9yIGV2ZXJ5dGhpbmdcbiAgICBjb25zdCBlbnZpcm9ubWVudFNwZWNzID0gdXNlckVudmlyb25tZW50U3BlY3MubGVuZ3RoID4gMCA/IFsuLi51c2VyRW52aXJvbm1lbnRTcGVjc10gOiBbJyoqJ107XG5cbiAgICAvLyBQYXJ0aXRpb24gaW50byBnbG9icyBhbmQgbm9uLWdsb2JzICh0aGlzIHdpbGwgbXV0YXRlIGVudmlyb25tZW50U3BlY3MpLlxuICAgIGNvbnN0IGdsb2JTcGVjcyA9IHBhcnRpdGlvbihlbnZpcm9ubWVudFNwZWNzLCBsb29rc0xpa2VHbG9iKTtcbiAgICBpZiAoZ2xvYlNwZWNzLmxlbmd0aCA+IDAgJiYgIXRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLmhhc0FwcCkge1xuICAgICAgaWYgKHVzZXJFbnZpcm9ubWVudFNwZWNzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgLy8gVXNlciBkaWQgcmVxdWVzdCB0aGlzIGdsb2JcbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgICAnSW52YWxpZEVudmlyb25tZW50R2xvYicsXG4gICAgICAgICAgYCcke2dsb2JTcGVjc30nIGlzIG5vdCBhbiBlbnZpcm9ubWVudCBuYW1lLiBTcGVjaWZ5IGFuIGVudmlyb25tZW50IG5hbWUgbGlrZSAnYXdzOi8vMTIzNDU2Nzg5MDEyL3VzLWVhc3QtMScsIG9yIHJ1biBpbiBhIGRpcmVjdG9yeSB3aXRoICdjZGsuanNvbicgdG8gdXNlIHdpbGRjYXJkcy5gLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVXNlciBkaWQgbm90IHJlcXVlc3QgYW55dGhpbmdcbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgICAnRW52aXJvbm1lbnRSZXF1aXJlZCcsXG4gICAgICAgICAgXCJTcGVjaWZ5IGFuIGVudmlyb25tZW50IG5hbWUgbGlrZSAnYXdzOi8vMTIzNDU2Nzg5MDEyL3VzLWVhc3QtMScsIG9yIHJ1biBpbiBhIGRpcmVjdG9yeSB3aXRoICdjZGsuanNvbicuXCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZW52aXJvbm1lbnRzOiBjeGFwaS5FbnZpcm9ubWVudFtdID0gWy4uLmVudmlyb25tZW50c0Zyb21EZXNjcmlwdG9ycyhlbnZpcm9ubWVudFNwZWNzKV07XG5cbiAgICAvLyBJZiB0aGVyZSBpcyBhbiAnLS1hcHAnIGFyZ3VtZW50LCBzZWxlY3QgdGhlIGVudmlyb25tZW50cyBmcm9tIHRoZSBhcHAuXG4gICAgaWYgKHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLmhhc0FwcCkge1xuICAgICAgY29uc3QgYXNzZW1ibHkgPSBhd2FpdCB0aGlzLmFzc2VtYmx5KCk7XG4gICAgICBjb25zdCBhbGxTdGFja3MgPSBhd2FpdCBhc3NlbWJseS5zZWxlY3RTdGFja3NWMihBTExfU1RBQ0tTKTtcbiAgICAgIGVudmlyb25tZW50cy5wdXNoKFxuICAgICAgICAuLi4oYXdhaXQgZ2xvYkVudmlyb25tZW50c0Zyb21TdGFja3MoYWxsU3RhY2tzLCBnbG9iU3BlY3MsIHRoaXMucHJvcHMuc2RrUHJvdmlkZXIpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVudmlyb25tZW50cztcbiAgfVxuXG4gIC8qKlxuICAgKiBNaWdyYXRlcyBhIENsb3VkRm9ybWF0aW9uIHN0YWNrL3RlbXBsYXRlIHRvIGEgQ0RLIGFwcFxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgZm9yIENESyBhcHAgY3JlYXRpb25cbiAgICovXG4gIHB1YmxpYyBhc3luYyBtaWdyYXRlKG9wdGlvbnM6IE1pZ3JhdGVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oJ1RoaXMgY29tbWFuZCBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZS4nKTtcbiAgICBjb25zdCBsYW5ndWFnZSA9IG9wdGlvbnMubGFuZ3VhZ2U/LnRvTG93ZXJDYXNlKCkgPz8gJ3R5cGVzY3JpcHQnO1xuICAgIGNvbnN0IGVudmlyb25tZW50ID0gc2V0RW52aXJvbm1lbnQob3B0aW9ucy5hY2NvdW50LCBvcHRpb25zLnJlZ2lvbik7XG4gICAgbGV0IGdlbmVyYXRlVGVtcGxhdGVPdXRwdXQ6IEdlbmVyYXRlVGVtcGxhdGVPdXRwdXQgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGNmbjogQ2ZuVGVtcGxhdGVHZW5lcmF0b3JQcm92aWRlciB8IHVuZGVmaW5lZDtcbiAgICBsZXQgdGVtcGxhdGVUb0RlbGV0ZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGlmIG5laXRoZXIgZnJvbVBhdGggbm9yIGZyb21TdGFjayBpcyBwcm92aWRlZCwgZ2VuZXJhdGUgYSB0ZW1wbGF0ZSB1c2luZyBjbG91ZGZvcm1hdGlvblxuICAgICAgY29uc3Qgc2NhblR5cGUgPSBwYXJzZVNvdXJjZU9wdGlvbnMob3B0aW9ucy5mcm9tUGF0aCwgb3B0aW9ucy5mcm9tU3RhY2ssIG9wdGlvbnMuc3RhY2tOYW1lKS5zb3VyY2U7XG4gICAgICBpZiAoc2NhblR5cGUgPT0gVGVtcGxhdGVTb3VyY2VPcHRpb25zLlNDQU4pIHtcbiAgICAgICAgZ2VuZXJhdGVUZW1wbGF0ZU91dHB1dCA9IGF3YWl0IGdlbmVyYXRlVGVtcGxhdGUoe1xuICAgICAgICAgIHN0YWNrTmFtZTogb3B0aW9ucy5zdGFja05hbWUsXG4gICAgICAgICAgZmlsdGVyczogb3B0aW9ucy5maWx0ZXIsXG4gICAgICAgICAgZnJvbVNjYW46IG9wdGlvbnMuZnJvbVNjYW4sXG4gICAgICAgICAgc2RrUHJvdmlkZXI6IHRoaXMucHJvcHMuc2RrUHJvdmlkZXIsXG4gICAgICAgICAgZW52aXJvbm1lbnQ6IGVudmlyb25tZW50LFxuICAgICAgICAgIGlvSGVscGVyOiB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCksXG4gICAgICAgIH0pO1xuICAgICAgICB0ZW1wbGF0ZVRvRGVsZXRlID0gZ2VuZXJhdGVUZW1wbGF0ZU91dHB1dC50ZW1wbGF0ZUlkO1xuICAgICAgfSBlbHNlIGlmIChzY2FuVHlwZSA9PSBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMuUEFUSCkge1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZUJvZHkgPSByZWFkRnJvbVBhdGgob3B0aW9ucy5mcm9tUGF0aCEpO1xuXG4gICAgICAgIGNvbnN0IHBhcnNlZFRlbXBsYXRlID0gZGVzZXJpYWxpemVTdHJ1Y3R1cmUodGVtcGxhdGVCb2R5KTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGVJZCA9IHBhcnNlZFRlbXBsYXRlLk1ldGFkYXRhPy5BV1NUb29sc01ldHJpY3M/LklhQ19HZW5lcmF0b3I/LnRvU3RyaW5nKCk7XG4gICAgICAgIGlmICh0ZW1wbGF0ZUlkKSB7XG4gICAgICAgICAgLy8gaWYgd2UgaGF2ZSBhIHRlbXBsYXRlIGlkLCB3ZSBjYW4gY2FsbCBkZXNjcmliZSBnZW5lcmF0ZWQgdGVtcGxhdGUgdG8gZ2V0IHRoZSByZXNvdXJjZSBpZGVudGlmaWVyc1xuICAgICAgICAgIC8vIHJlc291cmNlIG1ldGFkYXRhLCBhbmQgdGVtcGxhdGUgc291cmNlIHRvIGdlbmVyYXRlIHRoZSB0ZW1wbGF0ZVxuICAgICAgICAgIGNmbiA9IG5ldyBDZm5UZW1wbGF0ZUdlbmVyYXRvclByb3ZpZGVyKGF3YWl0IGJ1aWxkQ2ZuQ2xpZW50KHRoaXMucHJvcHMuc2RrUHJvdmlkZXIsIGVudmlyb25tZW50KSwgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpKTtcbiAgICAgICAgICBjb25zdCBnZW5lcmF0ZWRUZW1wbGF0ZVN1bW1hcnkgPSBhd2FpdCBjZm4uZGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZUlkKTtcbiAgICAgICAgICBnZW5lcmF0ZVRlbXBsYXRlT3V0cHV0ID0gYnVpbGRHZW5lcmF0ZWRUZW1wbGF0ZU91dHB1dChcbiAgICAgICAgICAgIGdlbmVyYXRlZFRlbXBsYXRlU3VtbWFyeSxcbiAgICAgICAgICAgIHRlbXBsYXRlQm9keSxcbiAgICAgICAgICAgIGdlbmVyYXRlZFRlbXBsYXRlU3VtbWFyeS5HZW5lcmF0ZWRUZW1wbGF0ZUlkISxcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGdlbmVyYXRlVGVtcGxhdGVPdXRwdXQgPSB7XG4gICAgICAgICAgICBtaWdyYXRlSnNvbjoge1xuICAgICAgICAgICAgICB0ZW1wbGF0ZUJvZHk6IHRlbXBsYXRlQm9keSxcbiAgICAgICAgICAgICAgc291cmNlOiAnbG9jYWxmaWxlJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChzY2FuVHlwZSA9PSBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMuU1RBQ0spIHtcbiAgICAgICAgY29uc3QgdGVtcGxhdGUgPSBhd2FpdCByZWFkRnJvbVN0YWNrKG9wdGlvbnMuc3RhY2tOYW1lLCB0aGlzLnByb3BzLnNka1Byb3ZpZGVyLCBlbnZpcm9ubWVudCk7XG4gICAgICAgIGlmICghdGVtcGxhdGUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdTdGFja1RlbXBsYXRlTm90Rm91bmQnLCBgTm8gdGVtcGxhdGUgZm91bmQgZm9yIHN0YWNrLW5hbWU6ICR7b3B0aW9ucy5zdGFja05hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhdGVUZW1wbGF0ZU91dHB1dCA9IHtcbiAgICAgICAgICBtaWdyYXRlSnNvbjoge1xuICAgICAgICAgICAgdGVtcGxhdGVCb2R5OiB0ZW1wbGF0ZSxcbiAgICAgICAgICAgIHNvdXJjZTogb3B0aW9ucy5zdGFja05hbWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlIHNob3VsZG4ndCBldmVyIGdldCBoZXJlLCBidXQganVzdCBpbiBjYXNlLlxuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdJbnZhbGlkU291cmNlT3B0aW9uJywgYEludmFsaWQgc291cmNlIG9wdGlvbiBwcm92aWRlZDogJHtzY2FuVHlwZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN0YWNrID0gZ2VuZXJhdGVTdGFjayhnZW5lcmF0ZVRlbXBsYXRlT3V0cHV0Lm1pZ3JhdGVKc29uLnRlbXBsYXRlQm9keSwgb3B0aW9ucy5zdGFja05hbWUsIGxhbmd1YWdlKTtcbiAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKGNoYWxrLmdyZWVuKCcg4o+zICBHZW5lcmF0aW5nIENESyBhcHAgZm9yICVzLi4uJyksIGNoYWxrLmJsdWUob3B0aW9ucy5zdGFja05hbWUpKTtcbiAgICAgIGF3YWl0IGdlbmVyYXRlQ2RrQXBwKHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKSwgb3B0aW9ucy5zdGFja05hbWUsIHN0YWNrISwgbGFuZ3VhZ2UsIG9wdGlvbnMub3V0cHV0UGF0aCwgb3B0aW9ucy5jb21wcmVzcyk7XG4gICAgICBpZiAoZ2VuZXJhdGVUZW1wbGF0ZU91dHB1dCkge1xuICAgICAgICB3cml0ZU1pZ3JhdGVKc29uRmlsZShvcHRpb25zLm91dHB1dFBhdGgsIG9wdGlvbnMuc3RhY2tOYW1lLCBnZW5lcmF0ZVRlbXBsYXRlT3V0cHV0Lm1pZ3JhdGVKc29uKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1RoZXJlQVdhcm5pbmcoZ2VuZXJhdGVUZW1wbGF0ZU91dHB1dCkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oXG4gICAgICAgICAgJyDimqDvuI8gIFNvbWUgcmVzb3VyY2VzIGNvdWxkIG5vdCBiZSBtaWdyYXRlZCBjb21wbGV0ZWx5LiBQbGVhc2UgcmV2aWV3IHRoZSBSRUFETUUubWQgZmlsZSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4nLFxuICAgICAgICApO1xuICAgICAgICBhcHBlbmRXYXJuaW5nc1RvUmVhZG1lKFxuICAgICAgICAgIGAke3BhdGguam9pbihvcHRpb25zLm91dHB1dFBhdGggPz8gcHJvY2Vzcy5jd2QoKSwgb3B0aW9ucy5zdGFja05hbWUpfS9SRUFETUUubWRgLFxuICAgICAgICAgIGdlbmVyYXRlVGVtcGxhdGVPdXRwdXQucmVzb3VyY2VzISxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuZXJyb3IoJyDinYwgIE1pZ3JhdGUgZmFpbGVkIGZvciBgJXNgOiAlcycsIG9wdGlvbnMuc3RhY2tOYW1lLCAoZSBhcyBFcnJvcikubWVzc2FnZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAodGVtcGxhdGVUb0RlbGV0ZSkge1xuICAgICAgICBpZiAoIWNmbikge1xuICAgICAgICAgIGNmbiA9IG5ldyBDZm5UZW1wbGF0ZUdlbmVyYXRvclByb3ZpZGVyKGF3YWl0IGJ1aWxkQ2ZuQ2xpZW50KHRoaXMucHJvcHMuc2RrUHJvdmlkZXIsIGVudmlyb25tZW50KSwgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXByb2Nlc3MuZW52Lk1JR1JBVEVfSU5URUdfVEVTVCkge1xuICAgICAgICAgIGF3YWl0IGNmbi5kZWxldGVHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZVRvRGVsZXRlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZWZhY3RvcihvcHRpb25zOiBSZWZhY3Rvck9wdGlvbnMpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGlmIChvcHRpb25zLnJldmVydCAmJiAhb3B0aW9ucy5vdmVycmlkZUZpbGUpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1JldmVydFJlcXVpcmVzT3ZlcnJpZGVGaWxlJywgJ1RoZSAtLXJldmVydCBvcHRpb24gY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHRoZSAtLW92ZXJyaWRlLWZpbGUgb3B0aW9uLicpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnRvb2xraXQucmVmYWN0b3IodGhpcy5wcm9wcy5jbG91ZEV4ZWN1dGFibGUsIHtcbiAgICAgICAgZHJ5UnVuOiBvcHRpb25zLmRyeVJ1bixcbiAgICAgICAgc3RhY2tzOiBvcHRpb25zLnN0YWNrcyA/PyBBTExfU1RBQ0tTLFxuICAgICAgICBmb3JjZTogb3B0aW9ucy5mb3JjZSxcbiAgICAgICAgYWRkaXRpb25hbFN0YWNrTmFtZXM6IG9wdGlvbnMuYWRkaXRpb25hbFN0YWNrTmFtZXMsXG4gICAgICAgIG92ZXJyaWRlczogcmVhZE92ZXJyaWRlcyhvcHRpb25zLm92ZXJyaWRlRmlsZSwgb3B0aW9ucy5yZXZlcnQpLFxuICAgICAgICByb2xlQXJuOiBvcHRpb25zLnJvbGVBcm4sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuZXJyb3IoKGUgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcblxuICAgIGZ1bmN0aW9uIHJlYWRPdmVycmlkZXMoZmlsZVBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCwgcmV2ZXJ0OiBib29sZWFuID0gZmFsc2UpIHtcbiAgICAgIGlmIChmaWxlUGF0aCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmICghZnMucGF0aEV4aXN0c1N5bmMoZmlsZVBhdGgpKSB7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ01hcHBpbmdGaWxlTm90Rm91bmQnLCBgVGhlIG1hcHBpbmcgZmlsZSAke2ZpbGVQYXRofSBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgfVxuICAgICAgY29uc3QgZ3JvdXBzID0gcGFyc2VNYXBwaW5nR3JvdXBzKGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCkudG9TdHJpbmcoJ3V0Zi04JykpO1xuXG4gICAgICByZXR1cm4gcmV2ZXJ0XG4gICAgICAgID8gZ3JvdXBzLm1hcCgoZ3JvdXApID0+ICh7XG4gICAgICAgICAgLi4uZ3JvdXAsXG4gICAgICAgICAgcmVzb3VyY2VzOiBPYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXMoZ3JvdXAucmVzb3VyY2VzID8/IHt9KS5tYXAoKFtzcmMsIGRzdF0pID0+IFtkc3QsIHNyY10pKSxcbiAgICAgICAgfSkpXG4gICAgICAgIDogZ3JvdXBzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZWxlY3QgdGhlIHN0YWNrcyB0aGF0IGBzeW50aGAgYW5kIGBkaWZmYCBvcGVyYXRlIG9uXG4gICAqXG4gICAqIFdpdGggcGF0dGVybnM6IG1hdGNoIHRoZW0gKGZhaWxpbmcgaWYgbm90aGluZyBtYXRjaGVzKSwgZXhwYW5kaW5nIHRvXG4gICAqIHVwc3RyZWFtIGRlcGVuZGVuY2llcyB1bmxlc3MgYGV4Y2x1c2l2ZWx5YCBpcyBzZXQuIFdpdGhvdXQgcGF0dGVybnM6IGFsbFxuICAgKiB0b3AtbGV2ZWwgc3RhY2tzLCBleGFjdGx5IOKAlCB0aGUgaGlzdG9yaWMgZGVmYXVsdCBzZWxlY3Rpb24gbmV2ZXIgZXhwYW5kc1xuICAgKiB0byBkZXBlbmRlbmNpZXMsIHJlZ2FyZGxlc3Mgb2YgYGV4Y2x1c2l2ZWx5YC4gQSBzdGFnZS1vbmx5IGFwcCBoYXMgbm9cbiAgICogdG9wLWxldmVsIHN0YWNrcywgd2hpY2ggc2VsZWN0cyBub3RoaW5nIGFuZCBpcyBub3QgYW4gZXJyb3Ig4oCUIGJ1dCBhbiBhcHBcbiAgICogd2l0aG91dCBhbnkgc3RhY2tzIGF0IGFsbCBzdGlsbCBpcy4gTm8gc2luZ2xlIHNlbGVjdGlvbiBzdHJhdGVneSBjb3ZlcnNcbiAgICogdGhpcyBjb21iaW5hdGlvbjogYE1BSU5fQVNTRU1CTFlgIHJlamVjdHMgc3RhZ2Utb25seSBhcHBzIChhc1xuICAgKiBgZGVwbG95IC0tYWxsYCBtdXN0IGtlZXAgZG9pbmcpIGFuZCBgQUxMX1NUQUNLU2Agd291bGQgd3JvbmdseSBpbmNsdWRlXG4gICAqIHRoZSBzdGFja3MgaW5zaWRlIHN0YWdlcy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2VsZWN0VG9wTGV2ZWxPck1hdGNoaW5nU3RhY2tzKFxuICAgIGFzc2VtYmx5OiBTdGFja0Fzc2VtYmx5LFxuICAgIHBhdHRlcm5zOiBzdHJpbmdbXSxcbiAgICBleGNsdXNpdmVseT86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8U3RhY2tDb2xsZWN0aW9uPiB7XG4gICAgaWYgKHBhdHRlcm5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBhc3NlbWJseS5zZWxlY3RTdGFja3NWMihcbiAgICAgICAgbXVzdE1hdGNoKGV4Y2x1c2l2ZWx5ID8gc2VsZWN0RXhhY3QoLi4ucGF0dGVybnMpIDogc2VsZWN0V2l0aFVwc3RyZWFtKC4uLnBhdHRlcm5zKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChhc3NlbWJseS5jbG91ZEFzc2VtYmx5LnN0YWNrcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gYXNzZW1ibHkuc2VsZWN0U3RhY2tzVjIoc2VsZWN0QWxsVG9wTGV2ZWwoRXhwYW5kU3RhY2tTZWxlY3Rpb24uTk9ORSkpO1xuICAgIH1cblxuICAgIC8vIFN0YWdlLW9ubHkgYXBwOiBub3RoaW5nIHRvIHNlbGVjdCwgd2hpY2ggaXMgbm90IGFuIGVycm9yLiBBbiBhcHBcbiAgICAvLyB3aXRob3V0IGFueSBzdGFja3MgYXQgYWxsIHN0aWxsIGlzOiB0aGlzIHNlbGVjdGlvbiB0aHJvd3NcbiAgICAvLyAnVGhpcyBhcHAgY29udGFpbnMgbm8gc3RhY2tzJyBpbiB0aGF0IGNhc2UuXG4gICAgYXdhaXQgYXNzZW1ibHkuc2VsZWN0U3RhY2tzVjIoQUxMX1NUQUNLUyk7XG4gICAgcmV0dXJuIG5ldyBTdGFja0NvbGxlY3Rpb24oYXNzZW1ibHksIFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgc3RhY2tzIGZvciBlcnJvcnMgYW5kIHdhcm5pbmdzIGFjY29yZGluZyB0byB0aGUgQ0xJJ3MgY3VycmVudCBzZXR0aW5nc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB2YWxpZGF0ZVN0YWNrcyhhc3NlbWJseTogU3RhY2tBc3NlbWJseSwgc3RhY2tzOiBTdGFja0NvbGxlY3Rpb24pIHtcbiAgICBjb25zdCBmYWlsQXQgPSB0aGlzLnZhbGlkYXRlTWV0YWRhdGFGYWlsQXQoKTtcbiAgICBhd2FpdCB0aHJvd0lmVmFsaWRhdGlvbkZhaWx1cmVzKGFzc2VtYmx5LCBzdGFja3MsIGZhaWxBdCwgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpKTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVNZXRhZGF0YUZhaWxBdCgpOiAnd2FybicgfCAnZXJyb3InIHwgJ25vbmUnIHtcbiAgICBsZXQgZmFpbEF0OiAnd2FybicgfCAnZXJyb3InIHwgJ25vbmUnID0gJ2Vycm9yJztcbiAgICBpZiAodGhpcy5wcm9wcy5pZ25vcmVFcnJvcnMpIHtcbiAgICAgIGZhaWxBdCA9ICdub25lJztcbiAgICB9XG4gICAgaWYgKHRoaXMucHJvcHMuc3RyaWN0KSB7XG4gICAgICBmYWlsQXQgPSAnd2Fybic7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhaWxBdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyB0aGUgdG9vbGtpdCdzIGBDbG91ZEV4ZWN1dGFibGVgIGludG8gYFN0YWNrQXNzZW1ibHlgLlxuICAgKlxuICAgKiBAcGFyYW0gY2FjaGVDbG91ZEFzc2VtYmx5IC0gdG8gY2FjaGUgdGhlIGFzc2VtYmx5LCBkZWZhdWx0cyB0byBgdHJ1ZWBcbiAgICogQHJldHVybnMgdGhlIGNvbnZlcnRlZCBgU3RhY2tBc3NlbWJseWBcbiAgICovXG4gIHB1YmxpYyBhc3NlbWJseShjYWNoZUNsb3VkQXNzZW1ibHk6IGJvb2xlYW4gPSB0cnVlKTogUHJvbWlzZTxTdGFja0Fzc2VtYmx5PiB7XG4gICAgcmV0dXJuIHRoaXMucHJvcHMuY2xvdWRFeGVjdXRhYmxlLnN5bnRoZXNpemUoY2FjaGVDbG91ZEFzc2VtYmx5KTtcbiAgfVxuXG4gIHByaXZhdGUgcGF0dGVybnNBcnJheUZvcldhdGNoKFxuICAgIHBhdHRlcm5zOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiB7IGRlZmF1bHRQYXR0ZXJuOiBzdHJpbmc7IHJldHVybkRlZmF1bHRJZkVtcHR5OiBib29sZWFuIH0sXG4gICk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXR0ZXJuc0FycmF5OiBzdHJpbmdbXSA9IHBhdHRlcm5zICE9PSB1bmRlZmluZWQgPyAoQXJyYXkuaXNBcnJheShwYXR0ZXJucykgPyBwYXR0ZXJucyA6IFtwYXR0ZXJuc10pIDogW107XG4gICAgcmV0dXJuIHBhdHRlcm5zQXJyYXkubGVuZ3RoID4gMCA/IHBhdHRlcm5zQXJyYXkgOiBvcHRpb25zLnJldHVybkRlZmF1bHRJZkVtcHR5ID8gW29wdGlvbnMuZGVmYXVsdFBhdHRlcm5dIDogW107XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGludm9rZURlcGxveUZyb21XYXRjaChcbiAgICBvcHRpb25zOiBXYXRjaE9wdGlvbnMsXG4gICAgY2xvdWRXYXRjaExvZ01vbml0b3I/OiBDbG91ZFdhdGNoTG9nRXZlbnRNb25pdG9yLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBkZXBsb3lPcHRpb25zOiBEZXBsb3lPcHRpb25zID0ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHJlcXVpcmVBcHByb3ZhbDogUmVxdWlyZUFwcHJvdmFsLk5FVkVSLFxuICAgICAgLy8gaWYgJ3dhdGNoJyBpcyBjYWxsZWQgYnkgaW52b2tpbmcgJ2NkayBkZXBsb3kgLS13YXRjaCcsXG4gICAgICAvLyB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0byBub3QgY2FsbCAnZGVwbG95JyB3aXRoICd3YXRjaCcgYWdhaW4sXG4gICAgICAvLyBhcyB0aGF0IHdvdWxkIGxlYWQgdG8gYSBjeWNsZVxuICAgICAgd2F0Y2g6IGZhbHNlLFxuICAgICAgY2xvdWRXYXRjaExvZ01vbml0b3IsXG4gICAgICBjYWNoZUNsb3VkQXNzZW1ibHk6IGZhbHNlLFxuICAgICAgZXh0cmFVc2VyQWdlbnQ6IGBjZGstd2F0Y2gvaG90c3dhcC0ke29wdGlvbnMuZGVwbG95bWVudE1ldGhvZD8ubWV0aG9kID09PSAnaG90c3dhcCcgPyAnb24nIDogJ29mZid9YCxcbiAgICAgIGNvbmN1cnJlbmN5OiBvcHRpb25zLmNvbmN1cnJlbmN5LFxuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5kZXBsb3koZGVwbG95T3B0aW9ucyk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBqdXN0IGNvbnRpbnVlIC0gZGVwbG95IHdpbGwgc2hvdyB0aGUgZXJyb3JcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIHRoZSBhc3NldCBwdWJsaXNoaW5nIGFuZCBidWlsZGluZyBmcm9tIHRoZSB3b3JrIGdyYXBoIGZvciBhc3NldHMgdGhhdCBhcmUgYWxyZWFkeSBpbiBwbGFjZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZW1vdmVQdWJsaXNoZWRBc3NldHMoZ3JhcGg6IFdvcmtHcmFwaCwgb3B0aW9uczogRGVwbG95T3B0aW9ucykge1xuICAgIGF3YWl0IGdyYXBoLnJlbW92ZVVubmVjZXNzYXJ5QXNzZXRzKGFzc2V0Tm9kZSA9PiB0aGlzLnByb3BzLmRlcGxveW1lbnRzLmlzU2luZ2xlQXNzZXRQdWJsaXNoZWQoYXNzZXROb2RlLmFzc2V0TWFuaWZlc3QsIGFzc2V0Tm9kZS5hc3NldCwge1xuICAgICAgc3RhY2s6IGFzc2V0Tm9kZS5wYXJlbnRTdGFjayxcbiAgICAgIHJvbGVBcm46IG9wdGlvbnMucm9sZUFybixcbiAgICAgIHN0YWNrTmFtZTogYXNzZXROb2RlLnBhcmVudFN0YWNrLnN0YWNrTmFtZSxcbiAgICB9KSk7XG4gIH1cbn1cblxuLyoqXG4gKiBQcmludCBhIHNlcmlhbGl6ZWQgb2JqZWN0IChZQU1MIG9yIEpTT04pIHRvIHN0ZG91dC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcHJpbnRTZXJpYWxpemVkT2JqZWN0KGlvSGVscGVyOiBJb0hlbHBlciwgb2JqOiBhbnksIGpzb246IGJvb2xlYW4pIHtcbiAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMucmVzdWx0KHNlcmlhbGl6ZVN0cnVjdHVyZShvYmosIGpzb24pKTtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgc3ludGggY29tbWFuZFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN5bnRoT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTdGFjayBuYW1lcyB0byBzeW50aGVzaXplXG4gICAqL1xuICByZWFkb25seSBzdGFja05hbWVzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogT25seSBzZWxlY3QgdGhlIGdpdmVuIHN0YWNrcywgd2l0aG91dCBleHBhbmRpbmcgdG8gdGhlaXIgdXBzdHJlYW0gZGVwZW5kZW5jaWVzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBleGNsdXNpdmVseT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIERvIG5vdCBwcmludCB0aGUgdGVtcGxhdGUgdG8gc3Rkb3V0XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWxseSB2YWxpZGF0ZSBzdGFja3MgdGhhdCBoYXZlIHRoZSBgdmFsaWRhdGVPblN5bnRoYCBmbGFnIHNldFxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b1ZhbGlkYXRlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogUHJpbnQgdGhlIHRlbXBsYXRlIGFzIEpTT04gaW5zdGVhZCBvZiBZQU1MXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBqc29uPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgZGlmZiBjb21tYW5kXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGlmZk9wdGlvbnMge1xuICAvKipcbiAgICogU3RhY2sgbmFtZXMgdG8gZGlmZlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhY2tOYW1lczogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHRvb2xraXQgc3RhY2ssIGlmIG5vdCB0aGUgZGVmYXVsdCBuYW1lXG4gICAqXG4gICAqIEBkZWZhdWx0ICdDREtUb29sa2l0J1xuICAgKi9cbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogT25seSBzZWxlY3QgdGhlIGdpdmVuIHN0YWNrXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBleGNsdXNpdmVseT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFVzZWQgYSB0ZW1wbGF0ZSBmcm9tIGRpc2sgaW5zdGVhZCBvZiBmcm9tIHRoZSBzZXJ2ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgVXNlIGZyb20gdGhlIHNlcnZlclxuICAgKi9cbiAgcmVhZG9ubHkgdGVtcGxhdGVQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTdHJpY3QgZGlmZiBtb2RlXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBzdHJpY3Q/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBIb3cgbWFueSBsaW5lcyBvZiBjb250ZXh0IHRvIHNob3cgaW4gdGhlIGRpZmZcbiAgICpcbiAgICogQGRlZmF1bHQgM1xuICAgKi9cbiAgcmVhZG9ubHkgY29udGV4dExpbmVzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGZhaWwgd2l0aCBleGl0IGNvZGUgMSBpbiBjYXNlIG9mIGRpZmZcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGZhaWw/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBPbmx5IHJ1biBkaWZmIG9uIGJyb2FkZW5lZCBzZWN1cml0eSBjaGFuZ2VzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eU9ubHk/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJ1biB0aGUgZGlmZiBhZ2FpbnN0IHRoZSB0ZW1wbGF0ZSBhZnRlciB0aGUgQ2xvdWRGb3JtYXRpb24gVHJhbnNmb3JtcyBpbnNpZGUgaXQgaGF2ZSBiZWVuIGV4ZWN1dGVkXG4gICAqIChhcyBvcHBvc2VkIHRvIHRoZSBvcmlnaW5hbCB0ZW1wbGF0ZSwgdGhlIGRlZmF1bHQsIHdoaWNoIGNvbnRhaW5zIHRoZSB1bnByb2Nlc3NlZCBUcmFuc2Zvcm1zKS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNvbXBhcmVBZ2FpbnN0UHJvY2Vzc2VkVGVtcGxhdGU/OiBib29sZWFuO1xuXG4gIC8qXG4gICAqIFJ1biBkaWZmIGluIHF1aWV0IG1vZGUgd2l0aG91dCBwcmludGluZyB0aGUgZGlmZiBzdGF0dXNlc1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIHBhcmFtZXRlcnMgZm9yIENsb3VkRm9ybWF0aW9uIGF0IGRpZmYgdGltZSwgdXNlZCB0byBjcmVhdGUgYSBjaGFuZ2Ugc2V0XG4gICAqIEBkZWZhdWx0IHt9XG4gICAqL1xuICByZWFkb25seSBwYXJhbWV0ZXJzPzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH07XG5cbiAgLyoqXG4gICAqIEhvdyB0byBjb21wdXRlIHRoZSBkaWZmLlxuICAgKiAtICdjaGFuZ2Utc2V0JzogYWx3YXlzIHVzZSBhIGNoYW5nZXNldCwgZmFpbCBpZiBpdCBjYW5ub3QgYmUgY3JlYXRlZFxuICAgKiAtICd0ZW1wbGF0ZSc6IHNraXAgY2hhbmdlc2V0LCBjb21wYXJlIHRlbXBsYXRlcyBkaXJlY3RseVxuICAgKiAtICdhdXRvJzogdHJ5IGNoYW5nZXNldCwgZmFsbCBiYWNrIHRvIHRlbXBsYXRlIG9uIGZhaWx1cmVcbiAgICpcbiAgICogQGRlZmF1bHQgJ2F1dG8nXG4gICAqL1xuICByZWFkb25seSBtZXRob2Q/OiAnYXV0bycgfCAnY2hhbmdlLXNldCcgfCAndGVtcGxhdGUnO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgY2hhbmdlIHNldCBpbXBvcnRzIHJlc291cmNlcyB0aGF0IGFscmVhZHkgZXhpc3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBpbXBvcnRFeGlzdGluZ1Jlc291cmNlcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gaW5jbHVkZSByZXNvdXJjZSBtb3ZlcyBpbiB0aGUgZGlmZlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5jbHVkZU1vdmVzPzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIENmbkRlcGxveU9wdGlvbnMge1xuICAvKipcbiAgICogQ3JpdGVyaWEgZm9yIHNlbGVjdGluZyBzdGFja3MgdG8gZGVwbG95XG4gICAqL1xuICBzZWxlY3RvcjogU3RhY2tTZWxlY3RvcjtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgdG9vbGtpdCBzdGFjayB0byB1c2UvZGVwbG95XG4gICAqXG4gICAqIEBkZWZhdWx0IENES1Rvb2xraXRcbiAgICovXG4gIHRvb2xraXRTdGFja05hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJvbGUgdG8gcGFzcyB0byBDbG91ZEZvcm1hdGlvbiBmb3IgZGVwbG95bWVudFxuICAgKi9cbiAgcm9sZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogRGVwbG95bWVudCBtZXRob2RcbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveW1lbnRNZXRob2Q/OiBEZXBsb3ltZW50TWV0aG9kO1xuXG4gIC8qKlxuICAgKiBEaXNwbGF5IG1vZGUgZm9yIHN0YWNrIGRlcGxveW1lbnQgcHJvZ3Jlc3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJhciAtIHN0YWNrIGV2ZW50cyB3aWxsIGJlIGRpc3BsYXllZCBmb3JcbiAgICogICB0aGUgcmVzb3VyY2UgY3VycmVudGx5IGJlaW5nIGRlcGxveWVkLlxuICAgKi9cbiAgcHJvZ3Jlc3M/OiBTdGFja0FjdGl2aXR5UHJvZ3Jlc3M7XG5cbiAgLyoqXG4gICAqIFJvbGxiYWNrIGZhaWxlZCBkZXBsb3ltZW50c1xuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSByb2xsYmFjaz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIHZhbGlkYXRlIGNvbW1hbmRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbGlWYWxpZGF0ZU9wdGlvbnMgZXh0ZW5kcyBWYWxpZGF0ZU9wdGlvbnMge1xuICAvKipcbiAgICogQ29udGludW91c2x5IG9ic2VydmUgdGhlIHByb2plY3QgZmlsZXMsIGFuZCByZS12YWxpZGF0ZSBhdXRvbWF0aWNhbGx5IHdoZW4gY2hhbmdlcyBhcmUgZGV0ZWN0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHdhdGNoPzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIFdhdGNoT3B0aW9ucyBleHRlbmRzIE9taXQ8Q2ZuRGVwbG95T3B0aW9ucywgJ2V4ZWN1dGUnPiB7XG4gIC8qKlxuICAgKiBSZXVzZSB0aGUgYXNzZXRzIHdpdGggdGhlIGdpdmVuIGFzc2V0IElEc1xuICAgKi9cbiAgcmV1c2VBc3NldHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQWx3YXlzIGRlcGxveSwgZXZlbiBpZiB0ZW1wbGF0ZXMgYXJlIGlkZW50aWNhbC5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGZvcmNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGV4dHJhIHN0cmluZyB0byBhcHBlbmQgdG8gdGhlIFVzZXItQWdlbnQgaGVhZGVyIHdoZW4gcGVyZm9ybWluZyBBV1MgU0RLIGNhbGxzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vdGhpbmcgZXh0cmEgaXMgYXBwZW5kZWQgdG8gdGhlIFVzZXItQWdlbnQgaGVhZGVyXG4gICAqL1xuICByZWFkb25seSBleHRyYVVzZXJBZ2VudD86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBzaG93IENsb3VkV2F0Y2ggbG9ncyBmb3IgaG90c3dhcHBlZCByZXNvdXJjZXNcbiAgICogbG9jYWxseSBpbiB0aGUgdXNlcnMgdGVybWluYWxcbiAgICpcbiAgICogQGRlZmF1bHQgLSBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgdHJhY2VMb2dzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2Ygc2ltdWx0YW5lb3VzIGRlcGxveW1lbnRzIChkZXBlbmRlbmN5IHBlcm1pdHRpbmcpIHRvIGV4ZWN1dGUuXG4gICAqIFRoZSBkZWZhdWx0IGlzICcxJywgd2hpY2ggZXhlY3V0ZXMgYWxsIGRlcGxveW1lbnRzIHNlcmlhbGx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBjb25jdXJyZW5jeT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBsb3lPcHRpb25zIGV4dGVuZHMgQ2ZuRGVwbG95T3B0aW9ucywgV2F0Y2hPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFSTnMgb2YgU05TIHRvcGljcyB0aGF0IENsb3VkRm9ybWF0aW9uIHdpbGwgbm90aWZ5IHdpdGggc3RhY2sgcmVsYXRlZCBldmVudHNcbiAgICovXG4gIG5vdGlmaWNhdGlvbkFybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogV2hhdCBraW5kIG9mIHNlY3VyaXR5IGNoYW5nZXMgcmVxdWlyZSBhcHByb3ZhbFxuICAgKlxuICAgKiBAZGVmYXVsdCBSZXF1aXJlQXBwcm92YWwuQnJvYWRlbmluZ1xuICAgKi9cbiAgcmVxdWlyZUFwcHJvdmFsPzogUmVxdWlyZUFwcHJvdmFsO1xuXG4gIC8qKlxuICAgKiBUYWdzIHRvIHBhc3MgdG8gQ2xvdWRGb3JtYXRpb24gZm9yIGRlcGxveW1lbnRcbiAgICovXG4gIHRhZ3M/OiBUYWdbXTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBwYXJhbWV0ZXJzIGZvciBDbG91ZEZvcm1hdGlvbiBhdCBkZXBsb3kgdGltZVxuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgcGFyYW1ldGVycz86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9O1xuXG4gIC8qKlxuICAgKiBVc2UgcHJldmlvdXMgdmFsdWVzIGZvciB1bnNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIElmIG5vdCBzZXQsIGFsbCBwYXJhbWV0ZXJzIG11c3QgYmUgc3BlY2lmaWVkIGZvciBldmVyeSBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICB1c2VQcmV2aW91c1BhcmFtZXRlcnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQYXRoIHRvIGZpbGUgd2hlcmUgc3RhY2sgb3V0cHV0cyB3aWxsIGJlIHdyaXR0ZW4gYWZ0ZXIgYSBzdWNjZXNzZnVsIGRlcGxveSBhcyBKU09OXG4gICAqIEBkZWZhdWx0IC0gT3V0cHV0cyBhcmUgbm90IHdyaXR0ZW4gdG8gYW55IGZpbGVcbiAgICovXG4gIG91dHB1dHNGaWxlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHdlIGFyZSBvbiBhIENJIHN5c3RlbVxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgY2k/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgJ2RlcGxveScgY29tbWFuZCBzaG91bGQgYWN0dWFsbHkgZGVsZWdhdGUgdG8gdGhlICd3YXRjaCcgY29tbWFuZC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHdhdGNoPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB3ZSBzaG91bGQgY2FjaGUgdGhlIENsb3VkIEFzc2VtYmx5IGFmdGVyIHRoZSBmaXJzdCB0aW1lIGl0IGhhcyBiZWVuIHN5bnRoZXNpemVkLlxuICAgKiBUaGUgZGVmYXVsdCBpcyAndHJ1ZScsIHdlIG9ubHkgZG9uJ3Qgd2FudCB0byBkbyBpdCBpbiBjYXNlIHRoZSBkZXBsb3ltZW50IGlzIHRyaWdnZXJlZCBieVxuICAgKiAnY2RrIHdhdGNoJy5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FjaGVDbG91ZEFzc2VtYmx5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQWxsb3dzIGFkZGluZyBDbG91ZFdhdGNoIGxvZyBncm91cHMgdG8gdGhlIGxvZyBtb25pdG9yIHZpYVxuICAgKiBjbG91ZFdhdGNoTG9nTW9uaXRvci5zZXRMb2dHcm91cHMoKTtcbiAgICpcbiAgICogQGRlZmF1bHQgLSBub3QgbW9uaXRvcmluZyBDbG91ZFdhdGNoIGxvZ3NcbiAgICovXG4gIHJlYWRvbmx5IGNsb3VkV2F0Y2hMb2dNb25pdG9yPzogQ2xvdWRXYXRjaExvZ0V2ZW50TW9uaXRvcjtcblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2Ygc2ltdWx0YW5lb3VzIGRlcGxveW1lbnRzIChkZXBlbmRlbmN5IHBlcm1pdHRpbmcpIHRvIGV4ZWN1dGUuXG4gICAqIFRoZSBkZWZhdWx0IGlzICcxJywgd2hpY2ggZXhlY3V0ZXMgYWxsIGRlcGxveW1lbnRzIHNlcmlhbGx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBjb25jdXJyZW5jeT86IG51bWJlcjtcblxuICAvKipcbiAgICogQnVpbGQvcHVibGlzaCBhc3NldHMgZm9yIGEgc2luZ2xlIHN0YWNrIGluIHBhcmFsbGVsXG4gICAqXG4gICAqIEluZGVwZW5kZW50IG9mIHdoZXRoZXIgc3RhY2tzIGFyZSBiZWluZyBkb25lIGluIHBhcmFsbGVsIG9yIG5vLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBhc3NldFBhcmFsbGVsaXNtPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgYXNzZXQgYnVpbGRzIHRvIHJ1biBpbiBwYXJhbGxlbFxuICAgKlxuICAgKiBUaGlzIHNldHRpbmcgb25seSBoYXMgYW4gZWZmZWN0IGlmIGBhc3NldFBhcmFsbGVsaXNtYCBpcyBzZXQgdG8gYHRydWVgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBhc3NldEJ1aWxkQ29uY3VycmVuY3k/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFdoZW4gdG8gYnVpbGQgYXNzZXRzXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IGlzIHRoZSBEb2NrZXItZnJpZW5kbHkgZGVmYXVsdC5cbiAgICpcbiAgICogQGRlZmF1bHQgQXNzZXRCdWlsZFRpbWUuQUxMX0JFRk9SRV9ERVBMT1lcbiAgICovXG4gIHJlYWRvbmx5IGFzc2V0QnVpbGRUaW1lPzogQXNzZXRCdWlsZFRpbWU7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gdXNlIENsb3VkRm9ybWF0aW9uIGV4cHJlc3MgbW9kZSBmb3IgdGhlIGN1cnJlbnQgZGVwbG95bWVudFxuICAgKi9cbiAgcmVhZG9ubHkgZXhwcmVzcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUm9sbGJhY2tPcHRpb25zIHtcbiAgLyoqXG4gICAqIENyaXRlcmlhIGZvciBzZWxlY3Rpbmcgc3RhY2tzIHRvIGRlcGxveVxuICAgKi9cbiAgcmVhZG9ubHkgc2VsZWN0b3I6IFN0YWNrU2VsZWN0b3I7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHRvb2xraXQgc3RhY2sgdG8gdXNlL2RlcGxveVxuICAgKlxuICAgKiBAZGVmYXVsdCBDREtUb29sa2l0XG4gICAqL1xuICByZWFkb25seSB0b29sa2l0U3RhY2tOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSb2xlIHRvIHBhc3MgdG8gQ2xvdWRGb3JtYXRpb24gZm9yIGRlcGxveW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBEZWZhdWx0IHN0YWNrIHJvbGVcbiAgICovXG4gIHJlYWRvbmx5IHJvbGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZm9yY2UgdGhlIHJvbGxiYWNrIG9yIG5vdFxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZm9yY2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBMb2dpY2FsIElEcyBvZiByZXNvdXJjZXMgdG8gb3JwaGFuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gb3JwaGFuaW5nXG4gICAqL1xuICByZWFkb25seSBvcnBoYW5Mb2dpY2FsSWRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gdmFsaWRhdGUgdGhlIHZlcnNpb24gb2YgdGhlIGJvb3RzdHJhcCBzdGFjayBwZXJtaXNzaW9uc1xuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB2YWxpZGF0ZUJvb3RzdHJhcFN0YWNrVmVyc2lvbj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3JwaGFuT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNvbnN0cnVjdFBhdGg6IHN0cmluZ1tdO1xuICByZWFkb25seSByb2xlQXJuPzogc3RyaW5nO1xuICByZWFkb25seSB0b29sa2l0U3RhY2tOYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEltcG9ydE9wdGlvbnMgZXh0ZW5kcyBDZm5EZXBsb3lPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFSTnMgb2YgU05TIHRvcGljcyB0aGF0IENsb3VkRm9ybWF0aW9uIHdpbGwgbm90aWZ5IHdpdGggc3RhY2sgcmVsYXRlZCBldmVudHMuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgc2VtYW50aWNzIGFwcGx5IChkaWN0YXRlZCBieSB0aGUgU0RLKTpcbiAgICpcbiAgICogIC0gdW5kZWZpbmVkICA9PiAgY2RrIGlnbm9yZXMgaXQsIGFzIGlmIGl0IHdhc24ndCBzdXBwb3J0ZWQgKGFsbG93cyBleHRlcm5hbCBtYW5hZ2VtZW50KS5cbiAgICogIC0gW106ICAgICAgICA9PiAgY2RrIG1hbmFnZXMgaXQsIGFuZCB0aGUgdXNlciB3YW50cyB0byB3aXBlIGl0IG91dC5cbiAgICogIC0gWydhcm4tMSddICA9PiAgY2RrIG1hbmFnZXMgaXQsIGFuZCB0aGUgdXNlciB3YW50cyB0byBzZXQgaXQgdG8gWydhcm4tMSddLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIG5vdGlmaWNhdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmaWNhdGlvbkFybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQnVpbGQgYSBwaHlzaWNhbCByZXNvdXJjZSBtYXBwaW5nIGFuZCB3cml0ZSBpdCB0byB0aGUgZ2l2ZW4gZmlsZSwgd2l0aG91dCBwZXJmb3JtaW5nIHRoZSBhY3R1YWwgaW1wb3J0IG9wZXJhdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGZpbGVcbiAgICovXG5cbiAgcmVhZG9ubHkgcmVjb3JkUmVzb3VyY2VNYXBwaW5nPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBQYXRoIHRvIGEgZmlsZSB3aXRoIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBtYXBwaW5nIHRvIENESyBjb25zdHJ1Y3RzIGluIEpTT04gZm9ybWF0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWFwcGluZyBmaWxlXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZU1hcHBpbmdGaWxlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBJbmxpbmUgSlNPTiBzdHJpbmcgd2l0aCB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgbWFwcGluZ1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGlubGluZSBtYXBwaW5nXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZU1hcHBpbmdJbmxpbmU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFsbG93IG5vbi1hZGRpdGlvbiBjaGFuZ2VzIHRvIHRoZSB0ZW1wbGF0ZVxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZm9yY2U/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERlc3Ryb3lPcHRpb25zIHtcbiAgLyoqXG4gICAqIENyaXRlcmlhIGZvciBzZWxlY3Rpbmcgc3RhY2tzIHRvIGRlcGxveVxuICAgKi9cbiAgc2VsZWN0b3I6IFN0YWNrU2VsZWN0b3I7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gc2tpcCBwcm9tcHRpbmcgZm9yIGNvbmZpcm1hdGlvblxuICAgKi9cbiAgZm9yY2U6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBhcm4gb2YgdGhlIElBTSByb2xlIHRvIHVzZVxuICAgKi9cbiAgcm9sZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgZGVzdHJveSByZXF1ZXN0IGNhbWUgZnJvbSBhIGRlcGxveS5cbiAgICovXG4gIGZyb21EZXBsb3k/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBNYXhpbXVtIG51bWJlciBvZiBzaW11bHRhbmVvdXMgZGVzdHJveXMgKGRlcGVuZGVuY3kgcGVybWl0dGluZykgdG8gZXhlY3V0ZS5cbiAgICovXG4gIGNvbmN1cnJlbmN5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHVzZSBDbG91ZEZvcm1hdGlvbiBleHByZXNzIG1vZGUgdG8gZGVsZXRlIHRoZSBzdGFjayhzKVxuICAgKi9cbiAgZXhwcmVzcz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIGdhcmJhZ2UgY29sbGVjdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdhcmJhZ2VDb2xsZWN0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgYWN0aW9uIHRvIHBlcmZvcm0uXG4gICAqXG4gICAqIEBkZWZhdWx0ICdmdWxsJ1xuICAgKi9cbiAgcmVhZG9ubHkgYWN0aW9uOiAncHJpbnQnIHwgJ3RhZycgfCAnZGVsZXRlLXRhZ2dlZCcgfCAnZnVsbCc7XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIHRoZSBhc3NldHMgdG8gYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0ICdhbGwnXG4gICAqL1xuICByZWFkb25seSB0eXBlOiAnczMnIHwgJ2VjcicgfCAnYWxsJztcblxuICAvKipcbiAgICogRWxhcHNlZCB0aW1lIGJldHdlZW4gYW4gYXNzZXQgYmVpbmcgbWFya2VkIGFzIGlzb2xhdGVkIGFuZCBhY3R1YWxseSBkZWxldGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAwXG4gICAqL1xuICByZWFkb25seSByb2xsYmFja0J1ZmZlckRheXM6IG51bWJlcjtcblxuICAvKipcbiAgICogUmVmdXNlIGRlbGV0aW9uIG9mIGFueSBhc3NldHMgeW91bmdlciB0aGFuIHRoaXMgbnVtYmVyIG9mIGRheXMuXG4gICAqL1xuICByZWFkb25seSBjcmVhdGVkQnVmZmVyRGF5czogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgc3RhY2sgbmFtZSBvZiB0aGUgYm9vdHN0cmFwIHN0YWNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCBERUZBVUxUX1RPT0xLSVRfU1RBQ0tfTkFNRVxuICAgKi9cbiAgcmVhZG9ubHkgYm9vdHN0cmFwU3RhY2tOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTa2lwcyB0aGUgcHJvbXB0IGJlZm9yZSBhY3R1YWwgZGVsZXRpb24gYmVnaW5zXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjb25maXJtPzogYm9vbGVhbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0ZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG5hbWUgYXNzaWduZWQgdG8gdGhlIGdlbmVyYXRlZCBzdGFjay4gVGhpcyBpcyBhbHNvIHVzZWQgdG8gZ2V0XG4gICAqIHRoZSBzdGFjayBmcm9tIHRoZSB1c2VyJ3MgYWNjb3VudCBpZiBgLS1mcm9tLXN0YWNrYCBpcyB1c2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhY2tOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0YXJnZXQgbGFuZ3VhZ2UgZm9yIHRoZSBnZW5lcmF0ZWQgdGhlIENESyBhcHAuXG4gICAqXG4gICAqIEBkZWZhdWx0IHR5cGVzY3JpcHRcbiAgICovXG4gIHJlYWRvbmx5IGxhbmd1YWdlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbG9jYWwgcGF0aCBvZiB0aGUgdGVtcGxhdGUgdXNlZCB0byBnZW5lcmF0ZSB0aGUgQ0RLIGFwcC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBMb2NhbCBwYXRoIGlzIG5vdCB1c2VkIGZvciB0aGUgdGVtcGxhdGUgc291cmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgZnJvbVBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZ2V0IHRoZSB0ZW1wbGF0ZSBmcm9tIGFuIGV4aXN0aW5nIENsb3VkRm9ybWF0aW9uIHN0YWNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZnJvbVN0YWNrPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIG91dHB1dCBwYXRoIGF0IHdoaWNoIHRvIGNyZWF0ZSB0aGUgQ0RLIGFwcC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUaGUgY3VycmVudCBkaXJlY3RvcnlcbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dFBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhY2NvdW50IGZyb20gd2hpY2ggdG8gcmV0cmlldmUgdGhlIHRlbXBsYXRlIG9mIHRoZSBDbG91ZEZvcm1hdGlvbiBzdGFjay5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBVc2VzIHRoZSBhY2NvdW50IGZvciB0aGUgY3JlZGVudGlhbHMgaW4gdXNlIGJ5IHRoZSB1c2VyLlxuICAgKi9cbiAgcmVhZG9ubHkgYWNjb3VudD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJlZ2lvbiBmcm9tIHdoaWNoIHRvIHJldHJpZXZlIHRoZSB0ZW1wbGF0ZSBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gc3RhY2suXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVXNlcyB0aGUgZGVmYXVsdCByZWdpb24gZm9yIHRoZSBjcmVkZW50aWFscyBpbiB1c2UgYnkgdGhlIHVzZXIuXG4gICAqL1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEZpbHRlcmluZyBjcml0ZXJpYSB1c2VkIHRvIHNlbGVjdCB0aGUgcmVzb3VyY2VzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBnZW5lcmF0ZWQgQ0RLIGFwcC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJbmNsdWRlIGFsbCByZXNvdXJjZXNcbiAgICovXG4gIHJlYWRvbmx5IGZpbHRlcj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGluaXRpYXRlIGEgbmV3IGFjY291bnQgc2NhbiBmb3IgZ2VuZXJhdGluZyB0aGUgQ0RLIGFwcC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGZyb21TY2FuPzogRnJvbVNjYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gemlwIHRoZSBnZW5lcmF0ZWQgY2RrIGFwcCBmb2xkZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjb21wcmVzcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVmYWN0b3JPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gb25seSBzaG93IHRoZSBwcm9wb3NlZCByZWZhY3Rvciwgd2l0aG91dCBhcHBseWluZyBpdFxuICAgKi9cbiAgcmVhZG9ubHkgZHJ5UnVuOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgYWJzb2x1dGUgcGF0aCB0byBhIGZpbGUgdGhhdCBjb250YWlucyBvdmVycmlkZXMgdG8gdGhlIG1hcHBpbmdzXG4gICAqIGNvbXB1dGVkIGJ5IHRoZSBDTEkuIFRoaXMgZmlsZSBzaG91bGQgY29udGFpbiBhIEpTT04gb2JqZWN0IHdpdGhcbiAgICogdGhlIGZvbGxvd2luZyBmb3JtYXQ6XG4gICAqXG4gICAqICAgICB7XG4gICAqICAgICAgIFwiZW52aXJvbm1lbnRzXCI6IFtcbiAgICogICAgICAgICB7XG4gICAqICAgICAgICAgICBcImFjY291bnRcIjogXCIxMjM0NTY3ODkwMTJcIixcbiAgICogICAgICAgICAgIFwicmVnaW9uXCI6IFwidXMtZWFzdC0xXCIsXG4gICAqICAgICAgICAgICBcInJlc291cmNlc1wiOiB7XG4gICAqICAgICAgICAgICAgIFwiRm9vLk9sZE5hbWVcIjogXCJCYXIuTmV3TmFtZVwiLFxuICAgKiAgICAgICAgICAgfVxuICAgKiAgICAgICAgIH0sXG4gICAqICAgICAgIF1cbiAgICogICAgIH1cbiAgICpcbiAgICogd2hlcmUgbWFwcGluZ3MgYXJlIGdyb3VwZWQgYnkgZW52aXJvbm1lbnQuIFRoZSBgcmVzb3VyY2VzYCBvYmplY3QgY29udGFpbnNcbiAgICogYSBtYXBwaW5nIHdoZXJlIGVhY2gga2V5IGlzIHRoZSBzb3VyY2UgbG9jYXRpb24gYW5kIHRoZSB2YWx1ZSBpcyB0aGVcbiAgICogZGVzdGluYXRpb24gbG9jYXRpb24uIExvY2F0aW9ucyBtdXN0IGJlIGluIHRoZSBmb3JtYXQgYFN0YWNrTmFtZS5Mb2dpY2FsSWRgLlxuICAgKiBUaGUgc291cmNlIG11c3QgcmVmZXIgdG8gYSBsb2NhdGlvbiB3aGVyZSB0aGVyZSBpcyBhIHJlc291cmNlIGN1cnJlbnRseVxuICAgKiBkZXBsb3llZCwgd2hpbGUgdGhlIGRlc3RpbmF0aW9uIG11c3QgcmVmZXIgdG8gYSBsb2NhdGlvbiB0aGF0IGlzIG5vdCBhbHJlYWR5XG4gICAqIG9jY3VwaWVkIGJ5IGFueSByZXNvdXJjZS5cbiAgICovXG4gIG92ZXJyaWRlRmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogTW9kaWZpZXMgdGhlIGJlaGF2aW9yIG9mIHRoZSBgb3ZlcnJpZGVGaWxlYCBvcHRpb24gYnkgc3dhcHBpbmcgc291cmNlIGFuZFxuICAgKiBkZXN0aW5hdGlvbiBsb2NhdGlvbnMuIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IHdhbnQgdG8gdW5kbyBhIHJlZmFjdG9yXG4gICAqIHRoYXQgd2FzIHByZXZpb3VzbHkgYXBwbGllZC5cbiAgICovXG4gIHJldmVydD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZG8gdGhlIHJlZmFjdG9yIHdpdGhvdXQgcHJvbXB0aW5nIHRoZSB1c2VyIGZvciBjb25maXJtYXRpb24uXG4gICAqL1xuICBmb3JjZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIENyaXRlcmlhIGZvciBzZWxlY3Rpbmcgc3RhY2tzIHRvIGNvbXBhcmUgd2l0aCB0aGUgZGVwbG95ZWQgc3RhY2tzIGluIHRoZVxuICAgKiB0YXJnZXQgZW52aXJvbm1lbnQuXG4gICAqL1xuICBzdGFja3M/OiBTdGFja1NlbGVjdG9yO1xuXG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgbmFtZXMgb2YgYWRkaXRpb25hbCBkZXBsb3llZCBzdGFja3MgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGNvbXBhcmlzb24uXG4gICAqL1xuICBhZGRpdGlvbmFsU3RhY2tOYW1lcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBSb2xlIHRvIGFzc3VtZSBpbiB0aGUgdGFyZ2V0IGVudmlyb25tZW50IGJlZm9yZSBwZXJmb3JtaW5nIHRoZSByZWZhY3Rvci5cbiAgICovXG4gIHJvbGVBcm4/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIGRyaWZ0IGNvbW1hbmRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEcmlmdE9wdGlvbnMge1xuICAvKipcbiAgICogQ3JpdGVyaWEgZm9yIHNlbGVjdGluZyBzdGFja3MgdG8gZGV0ZWN0IGRyaWZ0IG9uXG4gICAqL1xuICByZWFkb25seSBzZWxlY3RvcjogU3RhY2tTZWxlY3RvcjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBmYWlsIHdpdGggZXhpdCBjb2RlIDEgaWYgZHJpZnQgaXMgZGV0ZWN0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGZhaWw/OiBib29sZWFuO1xufVxuXG5mdW5jdGlvbiBidWlsZFBhcmFtZXRlck1hcChcbiAgcGFyYW1ldGVyczpcbiAgICB8IHtcbiAgICAgIFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHwgdW5kZWZpbmVkLFxuKTogeyBbbmFtZTogc3RyaW5nXTogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH0gfSB7XG4gIGNvbnN0IHBhcmFtZXRlck1hcDoge1xuICAgIFtuYW1lOiBzdHJpbmddOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWQgfTtcbiAgfSA9IHsgJyonOiB7fSB9O1xuICBmb3IgKGNvbnN0IGtleSBpbiBwYXJhbWV0ZXJzKSB7XG4gICAgaWYgKHBhcmFtZXRlcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgY29uc3QgW3N0YWNrLCBwYXJhbWV0ZXJdID0ga2V5LnNwbGl0KCc6JywgMik7XG4gICAgICBpZiAoIXBhcmFtZXRlcikge1xuICAgICAgICBwYXJhbWV0ZXJNYXBbJyonXVtzdGFja10gPSBwYXJhbWV0ZXJzW2tleV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIXBhcmFtZXRlck1hcFtzdGFja10pIHtcbiAgICAgICAgICBwYXJhbWV0ZXJNYXBbc3RhY2tdID0ge307XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1ldGVyTWFwW3N0YWNrXVtwYXJhbWV0ZXJdID0gcGFyYW1ldGVyc1trZXldO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwYXJhbWV0ZXJNYXA7XG59XG5cbi8qKlxuICogQXNrIHRoZSB1c2VyIGZvciBhIHllcy9ubyBjb25maXJtYXRpb25cbiAqXG4gKiBBdXRvbWF0aWNhbGx5IGZhaWwgdGhlIGNvbmZpcm1hdGlvbiBpbiBjYXNlIHdlJ3JlIGluIGEgc2l0dWF0aW9uIHdoZXJlIHRoZSBjb25maXJtYXRpb25cbiAqIGNhbm5vdCBiZSBpbnRlcmFjdGl2ZWx5IG9idGFpbmVkIGZyb20gYSBodW1hbiBhdCB0aGUga2V5Ym9hcmQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFza1VzZXJDb25maXJtYXRpb24oXG4gIGlvSG9zdDogQ2xpSW9Ib3N0LFxuICByZXE6IEFjdGlvbkxlc3NSZXF1ZXN0PENvbmZpcm1hdGlvblJlcXVlc3QsIGJvb2xlYW4+LFxuICBhYm9ydEVycm9yQ29kZTogc3RyaW5nLFxuICBhYm9ydE1lc3NhZ2U6IHN0cmluZyxcbikge1xuICBhd2FpdCBpb0hvc3Qud2l0aENvcmtlZExvZ2dpbmcoYXN5bmMgKCkgPT4ge1xuICAgIC8vIFRoZSBJb0hvc3QgcmV0dXJucyB0aGUgYW5zd2VyIHJhdGhlciB0aGFuIGFib3J0aW5nOyBhYm9ydCBoZXJlIG9uIGRlY2xpbmUuXG4gICAgY29uc3QgY29uZmlybWVkID0gYXdhaXQgaW9Ib3N0LmFzSW9IZWxwZXIoKS5yZXF1ZXN0UmVzcG9uc2UocmVxKTtcbiAgICBpZiAoIWNvbmZpcm1lZCkge1xuICAgICAgdGhyb3cgbmV3IEFib3J0RXJyb3IoYWJvcnRFcnJvckNvZGUsIGFib3J0TWVzc2FnZSk7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKiBEaXNwbGF5IGEgd2FybmluZyBpZiB0aGVyZSBhcmUgZmxhZ3MgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlIHJlY29tbWVuZGVkIHZhbHVlXG4gKlxuICogVGhpcyBoYXBwZW5zIGlmIGJvdGggb2YgdGhlIGZvbGxvd2luZyBhcmUgdHJ1ZTpcbiAqXG4gKiAtIFRoZSB1c2VyIGRpZG4ndCBjb25maWd1cmUgdGhlIHZhbHVlXG4gKiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgZmxhZyAodW5jb25maWd1cmVkQmVoYXZlc0xpa2UpIGlzIGRpZmZlcmVudCBmcm9tIHRoZSByZWNvbW1lbmRlZCB2YWx1ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGlzcGxheUZsYWdzTWVzc2FnZShpb0hvc3Q6IElvSGVscGVyLCB0b29sa2l0OiBJbnRlcm5hbFRvb2xraXQsIGNsb3VkRXhlY3V0YWJsZTogQ2xvdWRFeGVjdXRhYmxlKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGZsYWdzID0gYXdhaXQgdG9vbGtpdC5mbGFncyhjbG91ZEV4ZWN1dGFibGUpO1xuXG4gIC8vIFRoZSBcInVuY29uZmlndXJlZEJlaGF2ZXNMaWtlXCIgaW5mb3JtYXRpb24gZ290IGFkZGVkIGxhdGVyLiBJZiBub25lIG9mIHRoZSBmbGFncyBoYXZlIHRoaXMgaW5mb3JtYXRpb24sXG4gIC8vIHdlIGRvbid0IGhhdmUgZW5vdWdoIGluZm9ybWF0aW9uIHRvIHJlbGlhYmx5IGRpc3BsYXkgdGhpcyBpbmZvcm1hdGlvbiB3aXRob3V0IHNjYXJpbmcgdXNlcnMsIHNvIGRvbid0IGRvIGFueXRoaW5nLlxuICBpZiAoZmxhZ3MuZXZlcnkoZmxhZyA9PiBmbGFnLnVuY29uZmlndXJlZEJlaGF2ZXNMaWtlID09PSB1bmRlZmluZWQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgdW5jb25maWd1cmVkRmxhZ3MgPSBGbGFnT3BlcmF0aW9ucy5maWx0ZXJOZWVkc0F0dGVudGlvbihmbGFncyk7XG4gIGNvbnN0IG51bVVuY29uZmlndXJlZCA9IHVuY29uZmlndXJlZEZsYWdzLmxlbmd0aDtcblxuICBpZiAobnVtVW5jb25maWd1cmVkID4gMCkge1xuICAgIGF3YWl0IGlvSG9zdC5kZWZhdWx0cy53YXJuKGAke251bVVuY29uZmlndXJlZH0gZmVhdHVyZSBmbGFncyBhcmUgbm90IGNvbmZpZ3VyZWQuIFJ1biAnY2RrIGZsYWdzIC0tdW5zdGFibGU9ZmxhZ3MnIHRvIGxlYXJuIG1vcmUuYCk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFdvcmtHcmFwaERlcGxveW1lbnRBY3Rpb25zT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHJvbGVBcm4/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZvcmNlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3RhY2tDb3VudD86IG51bWJlcjtcbiAgcmVhZG9ubHkgbm90aWZpY2F0aW9uQXJucz86IHN0cmluZ1tdO1xuICByZWFkb25seSBkZXBsb3ltZW50TWV0aG9kPzogRGVwbG95bWVudE1ldGhvZDtcbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcmV1c2VBc3NldHM/OiBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgdGFncz86IFRhZ1tdO1xuICByZWFkb25seSBwYXJhbWV0ZXJzPzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH07XG4gIHJlYWRvbmx5IHVzZVByZXZpb3VzUGFyYW1ldGVycz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJvbGxiYWNrPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZXh0cmFVc2VyQWdlbnQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFzc2V0UGFyYWxsZWxpc20/OiBib29sZWFuO1xuICByZWFkb25seSByZXF1aXJlQXBwcm92YWw6IFJlcXVpcmVBcHByb3ZhbDtcbiAgcmVhZG9ubHkgY29uY3VycmVuY3k6IG51bWJlcjtcbiAgcmVhZG9ubHkgY2xvdWRXYXRjaExvZ01vbml0b3I/OiBDbG91ZFdhdGNoTG9nRXZlbnRNb25pdG9yO1xuICByZWFkb25seSBzZGtQcm92aWRlcjogU2RrUHJvdmlkZXI7XG4gIHJlYWRvbmx5IGV4cHJlc3M/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRoaXMgY2xhc3MgaW1wbGVtZW50cyB0aGUgY2FsbGJhY2tzIGZvciB0aGUgcGFyYWxsZWwgd29yayBncmFwaCBleGVjdXRpb25zLlxuICpcbiAqIEFsbCB0aGlzIGNvZGUgdXNlZCB0byBiZSBpbmxpbmVkIGludG8gQ2RrVG9vbGtpdCNkZXBsb3koKSwgYnV0IGl0IHdhcyBnZXR0aW5nXG4gKiB0b28gbXVjaCB0byBsaXZlIGluIHRoZXJlLlxuICovXG5jbGFzcyBXb3JrR3JhcGhEZXBsb3ltZW50QWN0aW9ucyBpbXBsZW1lbnRzIFdvcmtHcmFwaEFjdGlvbnMge1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YWNrT3V0cHV0czogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IGFzc2V0U3BhbnM6IFJlY29yZDxzdHJpbmcsIElNZXNzYWdlU3BhbjxFdmVudFJlc3VsdD4+ID0ge307XG4gIHByaXZhdGUgc3RhY2tDb3VudGVyID0gMTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlcGxveW1lbnRzOiBEZXBsb3ltZW50cyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGlvSG9zdDogQ2xpSW9Ib3N0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc3RhY2tPcGVyYXRpb25zOiBQaWNrPENka1Rvb2xraXQsICdkZXN0cm95JyB8ICdyb2xsYmFjayc+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogV29ya0dyYXBoRGVwbG95bWVudEFjdGlvbnNPcHRpb25zLFxuICApIHtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBtYXJrZXIobWFya2VyTm9kZTogTWFya2VyTm9kZSkge1xuICAgIC8vIEZvciBhc3NldHMsIGVtaXQgSW9Ib3N0IG1lc3NhZ2VzIHRoYXQgaGF2ZSBiZWVuIGRlZmluZWQgdG8gc3RhcnQgYW5kIGVuZCBhc3NldCBzcGFucywgd2hpY2ggd2lsbCBsZWFkIHRvIGV2ZW50cyBpbiB0ZWxlbWV0cnkuXG4gICAgc3dpdGNoIChtYXJrZXJOb2RlLm1hcmtlci50eXBlKSB7XG4gICAgICBjYXNlICdzdGFydC1hc3NldCc6IHtcbiAgICAgICAgY29uc3QgYXNzZXRTcGFuID0gYXdhaXQgdGhpcy5vYnRhaW5TcGFuKG1hcmtlck5vZGUubWFya2VyLmFzc2V0KTtcblxuICAgICAgICAvLyBDb3VudCB0aGUgYXNzZXQgdHlwZSwgYm90aCBvbiB0aGUgYXNzZXQtc3BlY2lmaWMgc3BhbiBhbmQgb24gdGhlIGdsb2JhbCBDT01NQU5EIHNwYW4uXG4gICAgICAgIGlmIChtYXJrZXJOb2RlLm1hcmtlci5hc3NldC50eXBlID09PSAnZmlsZScpIHtcbiAgICAgICAgICB0aGlzLmlvSG9zdC50ZWxlbWV0cnk/LmNvbW1hbmRTcGFuPy5pbmNDb3VudGVyKCdmaWxlQXNzZXQnKTtcbiAgICAgICAgICBhc3NldFNwYW4uaW5jQ291bnRlcignZmlsZUFzc2V0Jyk7XG4gICAgICAgIH0gZWxzZSBpZiAobWFya2VyTm9kZS5tYXJrZXIuYXNzZXQudHlwZSA9PT0gJ2RvY2tlcicpIHtcbiAgICAgICAgICB0aGlzLmlvSG9zdC50ZWxlbWV0cnk/LmNvbW1hbmRTcGFuPy5pbmNDb3VudGVyKCdkb2NrZXJBc3NldCcpO1xuICAgICAgICAgIGFzc2V0U3Bhbi5pbmNDb3VudGVyKCdkb2NrZXJBc3NldCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdlbmQtYXNzZXQnOiB7XG4gICAgICAgIGNvbnN0IGFzc2V0U3BhbiA9IGF3YWl0IHRoaXMub2J0YWluU3BhbihtYXJrZXJOb2RlLm1hcmtlci5hc3NldCk7XG4gICAgICAgIGF3YWl0IGFzc2V0U3Bhbi5lbmQoe30pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIG9idGFpblNwYW4oYXNzZXRFbnRyeTogSU1hbmlmZXN0RW50cnkpOiBQcm9taXNlPElNZXNzYWdlU3BhbjxFdmVudFJlc3VsdD4+IHtcbiAgICBjb25zdCBzcGFuID0gdGhpcy5hc3NldFNwYW5zW2Fzc2V0RW50cnkuaWQuYXNzZXRJZF07XG4gICAgaWYgKHNwYW4pIHtcbiAgICAgIHJldHVybiBzcGFuO1xuICAgIH1cbiAgICBjb25zdCBhc3NldFNwYW4gPSBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuc3BhbihDTElfUFJJVkFURV9TUEFOLkFTU0VUKS5iZWdpbih7fSk7XG4gICAgdGhpcy5hc3NldFNwYW5zW2Fzc2V0RW50cnkuaWQuYXNzZXRJZF0gPSBhc3NldFNwYW47XG4gICAgcmV0dXJuIGFzc2V0U3BhbjtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBidWlsZEFzc2V0KGFzc2V0Tm9kZTogQXNzZXRCdWlsZE5vZGUpIHtcbiAgICAvLyBNZWFzdXJlIGFzc2V0IGJ1aWxkIHRpbWUuIEJvdGggb24gdGhlIGdsb2JhbCBDT01NQU5EIHNwYW4gYXMgd2VsbCBhcyBvbiB0aGUgYXNzZXQtc3BlY2lmaWMgc3Bhbi5cbiAgICAvLyAocGFyYWxsZWxpc20gbWF5IGNhdXNlIFNVTShidWlsZEFzc2V0U1QpID49IHRvdGFsRGVwbG95VGltZSkgb24gdGhlIENPTU1BTkQgc3BhbiwgaW5kaWNhdGUgd2l0aCBbU111YltUXWFzayBzdWZmaXgpLlxuICAgIHVzaW5nIF9pbnZva2VUaW1lciA9IHRoaXMuaW9Ib3N0LnRlbGVtZXRyeT8uY29tbWFuZFNwYW4/LnN0YXJ0VGltZXIoJ2J1aWxkQXNzZXRTVCcpO1xuICAgIHVzaW5nIF9hc3NldFRpbWVyID0gKGF3YWl0IHRoaXMub2J0YWluU3Bhbihhc3NldE5vZGUuYXNzZXQpKS5zdGFydFRpbWVyKCdidWlsZEFzc2V0Jyk7XG5cbiAgICBhd2FpdCB0aGlzLmRlcGxveW1lbnRzLmJ1aWxkU2luZ2xlQXNzZXQoXG4gICAgICBhc3NldE5vZGUuYXNzZXRNYW5pZmVzdEFydGlmYWN0LFxuICAgICAgYXNzZXROb2RlLmFzc2V0TWFuaWZlc3QsXG4gICAgICBhc3NldE5vZGUuYXNzZXQsXG4gICAgICB7XG4gICAgICAgIHN0YWNrOiBhc3NldE5vZGUucGFyZW50U3RhY2ssXG4gICAgICAgIHJvbGVBcm46IHRoaXMub3B0aW9ucy5yb2xlQXJuLFxuICAgICAgICBzdGFja05hbWU6IGFzc2V0Tm9kZS5wYXJlbnRTdGFjay5zdGFja05hbWUsXG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcHVibGlzaEFzc2V0KGFzc2V0Tm9kZTogQXNzZXRQdWJsaXNoTm9kZSkge1xuICAgIC8vIE1lYXN1cmUgYXNzZXQgcHVibGlzaCB0aW1lLiBCb3RoIG9uIHRoZSBnbG9iYWwgQ09NTUFORCBzcGFuIGFzIHdlbGwgYXMgb24gdGhlIGFzc2V0LXNwZWNpZmljIHNwYW4uXG4gICAgLy8gKHBhcmFsbGVsaXNtIG1heSBjYXVzZSBTVU0ocHVibGlzaEFzc2V0U1QpID49IHRvdGFsRGVwbG95VGltZSkgb24gdGhlIENPTU1BTkQgc3BhbiwgaW5kaWNhdGUgd2l0aCBbU111YltUXWFzayBzdWZmaXgpLlxuICAgIHVzaW5nIF9pbnZva2VUaW1lciA9IHRoaXMuaW9Ib3N0LnRlbGVtZXRyeT8uY29tbWFuZFNwYW4/LnN0YXJ0VGltZXIoJ3B1Ymxpc2hBc3NldFNUJyk7XG4gICAgdXNpbmcgX2Fzc2V0VGltZXIgPSAoYXdhaXQgdGhpcy5vYnRhaW5TcGFuKGFzc2V0Tm9kZS5hc3NldCkpLnN0YXJ0VGltZXIoJ3B1Ymxpc2hBc3NldCcpO1xuXG4gICAgYXdhaXQgdGhpcy5kZXBsb3ltZW50cy5wdWJsaXNoU2luZ2xlQXNzZXQoYXNzZXROb2RlLmFzc2V0TWFuaWZlc3QsIGFzc2V0Tm9kZS5hc3NldCwge1xuICAgICAgc3RhY2s6IGFzc2V0Tm9kZS5wYXJlbnRTdGFjayxcbiAgICAgIHJvbGVBcm46IHRoaXMub3B0aW9ucy5yb2xlQXJuLFxuICAgICAgc3RhY2tOYW1lOiBhc3NldE5vZGUucGFyZW50U3RhY2suc3RhY2tOYW1lLFxuICAgICAgZm9yY2VQdWJsaXNoOiB0aGlzLm9wdGlvbnMuZm9yY2UsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVwbG95U3RhY2soc3RhY2tOb2RlOiBTdGFja05vZGUpIHtcbiAgICAvLyBDb3VudGVyIGZvciB0b3RhbERlcGxveWVkU3RhY2tzLCB0byBtYXRjaCAndG90YWxEZXBsb3lUaW1lJyB0aW1lciBvbiB0aGUgQ09NTUFORCBzcGFuLlxuICAgIHRoaXMuaW9Ib3N0LnRlbGVtZXRyeT8uY29tbWFuZFNwYW4/LmluY0NvdW50ZXIoJ3RvdGFsRGVwbG95ZWRTdGFja3MnKTtcblxuICAgIGNvbnN0IHN0YWNrID0gc3RhY2tOb2RlLnN0YWNrO1xuICAgIGlmICh0aGlzLm9wdGlvbnMuc3RhY2tDb3VudCAhPT0gMSkge1xuICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oY2hhbGsuYm9sZChzdGFjay5kaXNwbGF5TmFtZSkpO1xuICAgIH1cblxuICAgIGlmICghc3RhY2suZW52aXJvbm1lbnQpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAc3R5bGlzdGljL21heC1sZW5cbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoXG4gICAgICAgICdNaXNzaW5nRW52aXJvbm1lbnQnLFxuICAgICAgICBgU3RhY2sgJHtzdGFjay5kaXNwbGF5TmFtZX0gZG9lcyBub3QgZGVmaW5lIGFuIGVudmlyb25tZW50LCBhbmQgQVdTIGNyZWRlbnRpYWxzIGNvdWxkIG5vdCBiZSBvYnRhaW5lZCBmcm9tIHN0YW5kYXJkIGxvY2F0aW9ucyBvciBubyByZWdpb24gd2FzIGNvbmZpZ3VyZWQuYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb3VyY2VDb3VudCA9IE9iamVjdC5rZXlzKHN0YWNrLnRlbXBsYXRlLlJlc291cmNlcyB8fCB7fSkubGVuZ3RoO1xuICAgIGlmIChyZXNvdXJjZUNvdW50ID09PSAwKSB7XG4gICAgICAvLyBUaGUgZ2VuZXJhdGVkIHN0YWNrIGhhcyBubyByZXNvdXJjZXNcbiAgICAgIGlmICghKGF3YWl0IHRoaXMuZGVwbG95bWVudHMuc3RhY2tFeGlzdHMoeyBzdGFjayB9KSkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oJyVzOiBzdGFjayBoYXMgbm8gcmVzb3VyY2VzLCBza2lwcGluZyBkZXBsb3ltZW50LicsIGNoYWxrLmJvbGQoc3RhY2suZGlzcGxheU5hbWUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy53YXJuKCclczogc3RhY2sgaGFzIG5vIHJlc291cmNlcywgZGVsZXRpbmcgZXhpc3Rpbmcgc3RhY2suJywgY2hhbGsuYm9sZChzdGFjay5kaXNwbGF5TmFtZSkpO1xuICAgICAgICBhd2FpdCB0aGlzLnN0YWNrT3BlcmF0aW9ucy5kZXN0cm95KHtcbiAgICAgICAgICBzZWxlY3Rvcjogc2VsZWN0RXhhY3Qoc3RhY2suaGllcmFyY2hpY2FsSWQpLFxuICAgICAgICAgIGZvcmNlOiB0cnVlLFxuICAgICAgICAgIHJvbGVBcm46IHRoaXMub3B0aW9ucy5yb2xlQXJuLFxuICAgICAgICAgIGZyb21EZXBsb3k6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEZvbGxvd2luZyBhcmUgdGhlIHNhbWUgc2VtYW50aWNzIHdlIGFwcGx5IHdpdGggcmVzcGVjdCB0byBOb3RpZmljYXRpb24gQVJOcyAoZGljdGF0ZWQgYnkgdGhlIFNESylcbiAgICAvL1xuICAgIC8vICAtIHVuZGVmaW5lZCAgPT4gIGNkayBpZ25vcmVzIGl0LCBhcyBpZiBpdCB3YXNuJ3Qgc3VwcG9ydGVkIChhbGxvd3MgZXh0ZXJuYWwgbWFuYWdlbWVudCkuXG4gICAgLy8gIC0gW106ICAgICAgICA9PiAgY2RrIG1hbmFnZXMgaXQsIGFuZCB0aGUgdXNlciB3YW50cyB0byB3aXBlIGl0IG91dC5cbiAgICAvLyAgLSBbJ2Fybi0xJ10gID0+ICBjZGsgbWFuYWdlcyBpdCwgYW5kIHRoZSB1c2VyIHdhbnRzIHRvIHNldCBpdCB0byBbJ2Fybi0xJ10uXG4gICAgY29uc3Qgbm90aWZpY2F0aW9uQXJucyA9ICghIXRoaXMub3B0aW9ucy5ub3RpZmljYXRpb25Bcm5zIHx8ICEhc3RhY2subm90aWZpY2F0aW9uQXJucylcbiAgICAgID8gKHRoaXMub3B0aW9ucy5ub3RpZmljYXRpb25Bcm5zID8/IFtdKS5jb25jYXQoc3RhY2subm90aWZpY2F0aW9uQXJucyA/PyBbXSlcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgZm9yIChjb25zdCBub3RpZmljYXRpb25Bcm4gb2Ygbm90aWZpY2F0aW9uQXJucyA/PyBbXSkge1xuICAgICAgaWYgKCF2YWxpZGF0ZVNuc1RvcGljQXJuKG5vdGlmaWNhdGlvbkFybikpIHtcbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignSW52YWxpZFNuc1RvcGljQXJuJywgYE5vdGlmaWNhdGlvbiBhcm4gJHtub3RpZmljYXRpb25Bcm59IGlzIG5vdCBhIHZhbGlkIGFybiBmb3IgYW4gU05TIHRvcGljYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcGFyYW1ldGVyTWFwID0gYnVpbGRQYXJhbWV0ZXJNYXAodGhpcy5vcHRpb25zLnBhcmFtZXRlcnMpO1xuXG4gICAgLy8gRGVwbG95IG9wdGlvbnMgdGhhdCBhcmUgc2hhcmVkIGJldHdlZW4gY2hhbmdlIHNldCBjcmVhdGlvbiBhbmQgZXhlY3V0aW9uXG4gICAgY29uc3Qgc2hhcmVkRGVwbG95T3B0aW9ucyA9IHtcbiAgICAgIHN0YWNrLFxuICAgICAgZGVwbG95TmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgcm9sZUFybjogdGhpcy5vcHRpb25zLnJvbGVBcm4sXG4gICAgICB0b29sa2l0U3RhY2tOYW1lOiB0aGlzLm9wdGlvbnMudG9vbGtpdFN0YWNrTmFtZSxcbiAgICAgIHJldXNlQXNzZXRzOiB0aGlzLm9wdGlvbnMucmV1c2VBc3NldHMsXG4gICAgICB0YWdzOiAodGhpcy5vcHRpb25zLnRhZ3M/Lmxlbmd0aCA/IHRoaXMub3B0aW9ucy50YWdzIDogdGFnc0ZvclN0YWNrKHN0YWNrKSksXG4gICAgICBmb3JjZURlcGxveW1lbnQ6IHRoaXMub3B0aW9ucy5mb3JjZSxcbiAgICAgIHBhcmFtZXRlcnM6IE9iamVjdC5hc3NpZ24oe30sIHBhcmFtZXRlck1hcFsnKiddLCBwYXJhbWV0ZXJNYXBbc3RhY2suc3RhY2tOYW1lXSksXG4gICAgICB1c2VQcmV2aW91c1BhcmFtZXRlcnM6IHRoaXMub3B0aW9ucy51c2VQcmV2aW91c1BhcmFtZXRlcnMsXG4gICAgICByb2xsYmFjazogdGhpcy5vcHRpb25zLnJvbGxiYWNrLFxuICAgICAgbm90aWZpY2F0aW9uQXJucyxcbiAgICAgIGV4dHJhVXNlckFnZW50OiB0aGlzLm9wdGlvbnMuZXh0cmFVc2VyQWdlbnQsXG4gICAgICBhc3NldFBhcmFsbGVsaXNtOiB0aGlzLm9wdGlvbnMuYXNzZXRQYXJhbGxlbGlzbSxcbiAgICAgIGV4cHJlc3M6IHRoaXMub3B0aW9ucy5leHByZXNzLFxuICAgIH07XG5cbiAgICAvLyBXaGVuIHVzaW5nIGNoYW5nZS1zZXQgbWV0aG9kLCBhbHdheXMgY3JlYXRlIHRoZSBjaGFuZ2Ugc2V0IHVwZnJvbnQuXG4gICAgLy8gVGhpcyBnaXZlcyB1cyBhbiBhY2N1cmF0ZSBkaWZmIGZvciBhcHByb3ZhbCBhbmQgYXZvaWRzIGNyZWF0aW5nIGl0IHR3aWNlLlxuICAgIC8vIEZvciBub24tZXhlY3V0aW5nIGRlcGxveW1lbnRzIChwcmVwYXJlLWNoYW5nZS1zZXQpLCB0aGlzIGlzIHRoZSBmaW5hbCByZXN1bHQuXG4gICAgY29uc3QgcHJlcGFyZVJlc3VsdCA9IGlzQ2hhbmdlU2V0RGVwbG95bWVudCh0aGlzLm9wdGlvbnMuZGVwbG95bWVudE1ldGhvZClcbiAgICAgID8gYXdhaXQgdGhpcy5kZXBsb3ltZW50cy5wcmVwYXJlU3RhY2soe1xuICAgICAgICAuLi5zaGFyZWREZXBsb3lPcHRpb25zLFxuICAgICAgICBkZXBsb3ltZW50TWV0aG9kOiB0aGlzLm9wdGlvbnMuZGVwbG95bWVudE1ldGhvZCxcbiAgICAgICAgd2lsbEV4ZWN1dGVDaGFuZ2VTZXQ6IGlzRXhlY3V0aW5nQ2hhbmdlU2V0RGVwbG95bWVudCh0aGlzLm9wdGlvbnMuZGVwbG95bWVudE1ldGhvZCksXG4gICAgICB9KVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyBBbHNvIHNraXAgdGhlIGFwcHJvdmFsIGZsb3cgd2hlbiB0aGUgcHJlcGFyZWQgY2hhbmdlIHNldCBpcyBhIG5vLW9wIOKAlFxuICAgIC8vIHRoZXJlIGlzIG5vdGhpbmcgZm9yIHRoZSB1c2VyIHRvIGFwcHJvdmUuIE91dHB1dHMsIHN0YWNrIEFSTiwgYW5kXG4gICAgLy8gdGltaW5ncyBhcmUgc3RpbGwgZW1pdHRlZCB2aWEgdGhlIG5vcm1hbCBuby1vcCBkZXBsb3kgcGF0aCBiZWxvdy5cbiAgICBpZiAodGhpcy5vcHRpb25zLnJlcXVpcmVBcHByb3ZhbCAhPT0gUmVxdWlyZUFwcHJvdmFsLk5FVkVSICYmICFwcmVwYXJlUmVzdWx0Py5ub09wKSB7XG4gICAgICBjb25zdCBjdXJyZW50VGVtcGxhdGUgPSBhd2FpdCB0aGlzLmRlcGxveW1lbnRzLnJlYWRDdXJyZW50VGVtcGxhdGUoc3RhY2spO1xuICAgICAgY29uc3QgZm9ybWF0dGVyID0gbmV3IERpZmZGb3JtYXR0ZXIoe1xuICAgICAgICB0ZW1wbGF0ZUluZm86IHtcbiAgICAgICAgICBvbGRUZW1wbGF0ZTogY3VycmVudFRlbXBsYXRlLFxuICAgICAgICAgIG5ld1RlbXBsYXRlOiBzdGFjayxcbiAgICAgICAgICBjaGFuZ2VTZXQ6IHByZXBhcmVSZXN1bHQ/LmNoYW5nZVNldCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2VjdXJpdHlEaWZmID0gZm9ybWF0dGVyLmZvcm1hdFNlY3VyaXR5RGlmZigpO1xuICAgICAgaWYgKHJlcXVpcmVzQXBwcm92YWwodGhpcy5vcHRpb25zLnJlcXVpcmVBcHByb3ZhbCwgc2VjdXJpdHlEaWZmLnBlcm1pc3Npb25DaGFuZ2VUeXBlKSkge1xuICAgICAgICBjb25zdCBoYXNTZWN1cml0eUNoYW5nZXMgPSBzZWN1cml0eURpZmYucGVybWlzc2lvbkNoYW5nZVR5cGUgIT09IFBlcm1pc3Npb25DaGFuZ2VUeXBlLk5PTkU7XG4gICAgICAgIC8vIEJhcmUtZmFjdCBtb3RpdmF0aW9uLiBUaGUgSTUwNjAgbGlzdGVuZXIgcmVnaXN0ZXJlZCBpbiBgZGVwbG95KClgIGFkZHNcbiAgICAgICAgLy8gdGhlIGAtLXJlcXVpcmUtYXBwcm92YWxgIGZyYW1pbmcgZm9yIHRlcm1pbmFsIHVzZXJzLlxuICAgICAgICBjb25zdCBtb3RpdmF0aW9uID0gaGFzU2VjdXJpdHlDaGFuZ2VzXG4gICAgICAgICAgPyAnU3RhY2sgaW5jbHVkZXMgc2VjdXJpdHktc2Vuc2l0aXZlIHVwZGF0ZXMnXG4gICAgICAgICAgOiAnU3RhY2sgaW5jbHVkZXMgdXBkYXRlcyc7XG4gICAgICAgIGNvbnN0IGRpZmZPdXRwdXQgPSBoYXNTZWN1cml0eUNoYW5nZXMgPyBzZWN1cml0eURpZmYuZm9ybWF0dGVkRGlmZiA6IGZvcm1hdHRlci5mb3JtYXRTdGFja0RpZmYoKS5mb3JtYXR0ZWREaWZmO1xuICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhkaWZmT3V0cHV0KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGFza1VzZXJDb25maXJtYXRpb24oXG4gICAgICAgICAgICB0aGlzLmlvSG9zdCxcbiAgICAgICAgICAgIElPLkNES19UT09MS0lUX0k1MDYwLnJlcShgJHttb3RpdmF0aW9ufS4gRG8geW91IHdpc2ggdG8gZGVwbG95IHRoZXNlIGNoYW5nZXM/YCwge1xuICAgICAgICAgICAgICBtb3RpdmF0aW9uLFxuICAgICAgICAgICAgICBjb25jdXJyZW5jeTogdGhpcy5vcHRpb25zLmNvbmN1cnJlbmN5LFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uQ2hhbmdlVHlwZTogc2VjdXJpdHlEaWZmLnBlcm1pc3Npb25DaGFuZ2VUeXBlLFxuICAgICAgICAgICAgICB0ZW1wbGF0ZURpZmZzOiBmb3JtYXR0ZXIuZGlmZnMsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICdEZXBsb3lBYm9ydGVkJyxcbiAgICAgICAgICAgICdEZXBsb3ltZW50IGNhbmNlbGxlZCcsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChwcmVwYXJlUmVzdWx0Py5jaGFuZ2VTZXQ/LkNoYW5nZVNldE5hbWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZGVwbG95bWVudHMuY2xlYW51cENoYW5nZVNldChzdGFjaywgcHJlcGFyZVJlc3VsdC5jaGFuZ2VTZXQuQ2hhbmdlU2V0TmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzdGFja0luZGV4ID0gdGhpcy5zdGFja0NvdW50ZXIrKztcbiAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgJHtjaGFsay5ib2xkKHN0YWNrLmRpc3BsYXlOYW1lKX06IGRlcGxveWluZy4uLiBbJHtzdGFja0luZGV4fS8ke3RoaXMub3B0aW9ucy5zdGFja0NvdW50fV1gKTtcbiAgICBjb25zdCBzdGFydERlcGxveVRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIC8vIFRoZXJlIGlzIGFscmVhZHkgYSBzdGFydERlcGxveVRpbWUgY29uc3RhbnQsIGJ1dCB0aGF0IGRvZXMgbm90IHdvcmsgd2l0aCB0ZWxlbWV0cnkuXG4gICAgLy8gV2Ugc2hvdWxkIGludGVncmF0ZSB0aGUgdHdvIGluIHRoZSBmdXR1cmVcbiAgICBjb25zdCBkZXBsb3lTcGFuID0gYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLnNwYW4oQ0xJX1BSSVZBVEVfU1BBTi5ERVBMT1kpLmJlZ2luKHt9KTtcbiAgICBkZXBsb3lTcGFuLmluY0NvdW50ZXIoJ3Jlc291cmNlcycsIHJlc291cmNlQ291bnQpO1xuICAgIHRoaXMuaW9Ib3N0LnRlbGVtZXRyeT8uY29tbWFuZFNwYW4/LmluY0NvdW50ZXIoJ3RvdGFsRGVwbG95ZWRSZXNvdXJjZXMnLCByZXNvdXJjZUNvdW50KTtcbiAgICBsZXQgZXJyb3I6IEVycm9yRGV0YWlscyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgZWxhcHNlZERlcGxveVRpbWUgPSAwO1xuICAgIHRyeSB7XG4gICAgICAvLyBUaGUgcHJlcGFyZSByZXN1bHQgaXMgZmluYWwgaWYgdGhlIGNoYW5nZSBzZXQgd2FzIGVtcHR5IChub09wKSBvclxuICAgICAgLy8gdGhlIGRlcGxveW1lbnQgbWV0aG9kIGlzIG5vbi1leGVjdXRpbmcgKHByZXBhcmUtY2hhbmdlLXNldCkuXG4gICAgICBjb25zdCBwcmVwYXJlSXNGaW5hbCA9IHByZXBhcmVSZXN1bHQgJiYgKHByZXBhcmVSZXN1bHQubm9PcCB8fCBpc05vbkV4ZWN1dGluZ0NoYW5nZVNldERlcGxveW1lbnQodGhpcy5vcHRpb25zLmRlcGxveW1lbnRNZXRob2QpKTtcbiAgICAgIGxldCBkZXBsb3lSZXN1bHQ6IFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdCB8IHVuZGVmaW5lZCA9IHByZXBhcmVJc0ZpbmFsID8gcHJlcGFyZVJlc3VsdCA6IHVuZGVmaW5lZDtcblxuICAgICAgLy8gU3RhcnQgd2l0aCB1c2VyIGNvbmZpZyBmb3Igcm9sbGJhY2ssXG4gICAgICAvLyBidXQgaXQgbWlnaHQgY2hhbmdlIGlmIHdlIGVuY291bnRlciBhIGZhaWxlZCBzdGF0ZS5cbiAgICAgIGxldCByb2xsYmFjayA9IHRoaXMub3B0aW9ucy5yb2xsYmFjaztcblxuICAgICAgLy8gV2UgbGltaXQgdGhlIGxvb3AgdG8gMiBpdGVyYXRpb25zIG1heCBhcyBkZWZlbnNpdmUgcHJvZ3JhbW1pbmcuXG4gICAgICAvLyBTaG91bGQgbm90IGJlIHBvc3NpYmxlIHRvIGhhcHBlbi5cbiAgICAgIGxldCBpdGVyYXRpb24gPSAwO1xuICAgICAgd2hpbGUgKCFkZXBsb3lSZXN1bHQpIHtcbiAgICAgICAgaWYgKCsraXRlcmF0aW9uID4gMikge1xuICAgICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0RlcGxveUxvb3BVbnN0YWJsZScsICdUaGlzIGxvb3Agc2hvdWxkIGhhdmUgc3RhYmlsaXplZCBpbiAyIGl0ZXJhdGlvbnMsIGJ1dCBkaWRuXFwndC4gSWYgeW91IGFyZSBzZWVpbmcgdGhpcyBlcnJvciwgcGxlYXNlIHJlcG9ydCBpdCBhdCBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzL25ldy9jaG9vc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHIgPSBhd2FpdCB0aGlzLmRlcGxveW1lbnRzLmRlcGxveVN0YWNrKHtcbiAgICAgICAgICAuLi5zaGFyZWREZXBsb3lPcHRpb25zLFxuICAgICAgICAgIC8vIE9uIHRoZSBmaXJzdCBpdGVyYXRpb24sIGV4ZWN1dGUgdGhlIHByZXBhcmVkIGNoYW5nZSBzZXQuXG4gICAgICAgICAgLy8gT24gcmV0cmllcyAoYWZ0ZXIgcm9sbGJhY2spLCBjcmVhdGUgYSBuZXcgY2hhbmdlIHNldCBzaW5jZSB0aGUgb2xkIG9uZSBpcyBnb25lLlxuICAgICAgICAgIGRlcGxveW1lbnRNZXRob2Q6IGl0ZXJhdGlvbiA9PT0gMSAmJiBpc0V4ZWN1dGluZ0NoYW5nZVNldERlcGxveW1lbnQodGhpcy5vcHRpb25zLmRlcGxveW1lbnRNZXRob2QpXG4gICAgICAgICAgICA/IHRvRXhlY3V0ZUNoYW5nZVNldERlcGxveW1lbnQodGhpcy5vcHRpb25zLmRlcGxveW1lbnRNZXRob2QpXG4gICAgICAgICAgICA6IHRoaXMub3B0aW9ucy5kZXBsb3ltZW50TWV0aG9kLFxuICAgICAgICAgIHJvbGxiYWNrLFxuICAgICAgICB9KTtcblxuICAgICAgICBzd2l0Y2ggKHIudHlwZSkge1xuICAgICAgICAgIGNhc2UgJ2RpZC1kZXBsb3ktc3RhY2snOlxuICAgICAgICAgICAgZGVwbG95UmVzdWx0ID0gcjtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnZmFpbHBhdXNlZC1uZWVkLXJvbGxiYWNrLWZpcnN0Jzoge1xuICAgICAgICAgICAgY29uc3QgbW90aXZhdGlvbiA9IHIucmVhc29uID09PSAncmVwbGFjZW1lbnQnXG4gICAgICAgICAgICAgID8gYFN0YWNrIGlzIGluIGEgcGF1c2VkIGZhaWwgc3RhdGUgKCR7ci5zdGF0dXN9KSBhbmQgY2hhbmdlIGluY2x1ZGVzIGEgcmVwbGFjZW1lbnQgd2hpY2ggY2Fubm90IGJlIGRlcGxveWVkIHdpdGggXCItLW5vLXJvbGxiYWNrXCJgXG4gICAgICAgICAgICAgIDogYFN0YWNrIGlzIGluIGEgcGF1c2VkIGZhaWwgc3RhdGUgKCR7ci5zdGF0dXN9KSBhbmQgY29tbWFuZCBsaW5lIGFyZ3VtZW50cyBkbyBub3QgaW5jbHVkZSBcIi0tbm8tcm9sbGJhY2tcImA7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZm9yY2UpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oYCR7bW90aXZhdGlvbn0uIFJvbGxpbmcgYmFjayBmaXJzdCAoLS1mb3JjZSkuYCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhd2FpdCBhc2tVc2VyQ29uZmlybWF0aW9uKFxuICAgICAgICAgICAgICAgIHRoaXMuaW9Ib3N0LFxuICAgICAgICAgICAgICAgIElPLkNES19UT09MS0lUX0k1MDUwLnJlcShgJHttb3RpdmF0aW9ufS4gUm9sbCBiYWNrIGZpcnN0IGFuZCB0aGVuIHByb2NlZWQgd2l0aCBkZXBsb3ltZW50YCwge1xuICAgICAgICAgICAgICAgICAgbW90aXZhdGlvbixcbiAgICAgICAgICAgICAgICAgIGNvbmN1cnJlbmN5OiB0aGlzLm9wdGlvbnMuY29uY3VycmVuY3ksXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgJ1JvbGxiYWNrQWJvcnRlZCcsXG4gICAgICAgICAgICAgICAgJ1JvbGxiYWNrIGNhbmNlbGxlZCcsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBlcmZvcm0gYSByb2xsYmFja1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGFja09wZXJhdGlvbnMucm9sbGJhY2soe1xuICAgICAgICAgICAgICBzZWxlY3Rvcjogc2VsZWN0RXhhY3Qoc3RhY2suaGllcmFyY2hpY2FsSWQpLFxuICAgICAgICAgICAgICB0b29sa2l0U3RhY2tOYW1lOiB0aGlzLm9wdGlvbnMudG9vbGtpdFN0YWNrTmFtZSxcbiAgICAgICAgICAgICAgZm9yY2U6IHRoaXMub3B0aW9ucy5mb3JjZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBHbyBhcm91bmQgdGhyb3VnaCB0aGUgJ3doaWxlJyBsb29wIGFnYWluIGJ1dCBzd2l0Y2ggcm9sbGJhY2sgdG8gdHJ1ZS5cbiAgICAgICAgICAgIHJvbGxiYWNrID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3JlcGxhY2VtZW50LXJlcXVpcmVzLXJvbGxiYWNrJzoge1xuICAgICAgICAgICAgY29uc3QgbW90aXZhdGlvbiA9ICdDaGFuZ2UgaW5jbHVkZXMgYSByZXBsYWNlbWVudCB3aGljaCBjYW5ub3QgYmUgZGVwbG95ZWQgd2l0aCBcIi0tbm8tcm9sbGJhY2tcIic7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZm9yY2UpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLndhcm4oYCR7bW90aXZhdGlvbn0uIFByb2NlZWRpbmcgd2l0aCBkZXBsb3ltZW50IHdpdGggcm9sbGJhY2sgZW5hYmxlZCAoLS1mb3JjZSkuYCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhd2FpdCBhc2tVc2VyQ29uZmlybWF0aW9uKFxuICAgICAgICAgICAgICAgIHRoaXMuaW9Ib3N0LFxuICAgICAgICAgICAgICAgIElPLkNES19UT09MS0lUX0k1MDUwLnJlcShgJHttb3RpdmF0aW9ufS4gUGVyZm9ybSBhIGRlcGxveW1lbnQgd2l0aCByb2xsYmFjayBlbmFibGVkYCwge1xuICAgICAgICAgICAgICAgICAgY29uY3VycmVuY3k6IHRoaXMub3B0aW9ucy5jb25jdXJyZW5jeSxcbiAgICAgICAgICAgICAgICAgIG1vdGl2YXRpb24sXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgJ1JlcGxhY2VtZW50Um9sbGJhY2tBYm9ydGVkJyxcbiAgICAgICAgICAgICAgICAnUm9sbGJhY2sgY2FuY2VsbGVkJyxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gR28gYXJvdW5kIHRocm91Z2ggdGhlICd3aGlsZScgbG9vcCBhZ2FpbiBidXQgc3dpdGNoIHJvbGxiYWNrIHRvIHRydWUuXG4gICAgICAgICAgICByb2xsYmFjayA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignVW5leHBlY3RlZERlcGxveVJlc3VsdCcsIGBVbmV4cGVjdGVkIHJlc3VsdCB0eXBlIGZyb20gZGVwbG95U3RhY2s6ICR7SlNPTi5zdHJpbmdpZnkocil9LiBJZiB5b3UgYXJlIHNlZWluZyB0aGlzIGVycm9yLCBwbGVhc2UgcmVwb3J0IGl0IGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvbmV3L2Nob29zZWApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBkZXBsb3lSZXN1bHQubm9PcFxuICAgICAgICA/ICfinIUgICVzIChubyBjaGFuZ2VzKSdcbiAgICAgICAgOiAn4pyFICAlcyc7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKGNoYWxrLmdyZWVuKCdcXG4nICsgbWVzc2FnZSksIHN0YWNrLmRpc3BsYXlOYW1lKTtcbiAgICAgIGVsYXBzZWREZXBsb3lUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSBzdGFydERlcGxveVRpbWU7XG4gICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkuZGVmYXVsdHMuaW5mbyhgXFxu4pyoICBEZXBsb3ltZW50IHRpbWU6ICR7Zm9ybWF0VGltZShlbGFwc2VkRGVwbG95VGltZSl9c1xcbmApO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmV4cHJlc3MpIHtcbiAgICAgICAgY29uc3Qgd2FybmluZyA9IGZvcm1hdEV4cHJlc3NTdGFiaWxpemF0aW9uV2FybmluZyhkZXBsb3lSZXN1bHQuc3RhYmlsaXppbmdSZXNvdXJjZXMsICdkZXBsb3knKTtcbiAgICAgICAgaWYgKHdhcm5pbmcpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmlvSG9zdC5hc0lvSGVscGVyKCkubm90aWZ5KElPLkNES19UT09MS0lUX1c1OTAyLm1zZyh3YXJuaW5nKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKE9iamVjdC5rZXlzKGRlcGxveVJlc3VsdC5vdXRwdXRzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKCdPdXRwdXRzOicpO1xuXG4gICAgICAgIHRoaXMuc3RhY2tPdXRwdXRzW3N0YWNrLnN0YWNrTmFtZV0gPSBkZXBsb3lSZXN1bHQub3V0cHV0cztcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKGRlcGxveVJlc3VsdC5vdXRwdXRzKS5zb3J0KCkpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBkZXBsb3lSZXN1bHQub3V0cHV0c1tuYW1lXTtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hvc3QuYXNJb0hlbHBlcigpLmRlZmF1bHRzLmluZm8oYCR7Y2hhbGsuY3lhbihzdGFjay5pZCl9LiR7Y2hhbGsuY3lhbihuYW1lKX0gPSAke2NoYWxrLnVuZGVybGluZShjaGFsay5jeWFuKHZhbHVlKSl9YCk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5pbmZvKCdTdGFjayBBUk46Jyk7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9Ib3N0LmFzSW9IZWxwZXIoKS5kZWZhdWx0cy5yZXN1bHQoZGVwbG95UmVzdWx0LnN0YWNrQXJuKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIEl0IGhhcyB0byBiZSBleGFjdGx5IHRoaXMgc3RyaW5nIGJlY2F1c2UgYW4gaW50ZWdyYXRpb24gdGVzdCB0ZXN0cyBmb3JcbiAgICAgIC8vIFwiYm9sZChzdGFja25hbWUpIGZhaWxlZDogUmVzb3VyY2VOb3RSZWFkeTogPGVycm9yPlwiXG4gICAgICBjb25zdCBjb2RlID0gVG9vbGtpdEVycm9yLmlzVG9vbGtpdEVycm9yKGUpID8gZS5uYW1lIDogJ0RlcGxveVN0YWNrRmFpbGVkJzsgLy8gRm9ybWVybHkgJ0RlcGxveUZhaWxlZCdcbiAgICAgIGNvbnN0IG5ld01lc3NhZ2UgPSBbYOKdjCAgJHtjaGFsay5ib2xkKHN0YWNrLnN0YWNrTmFtZSl9IGZhaWxlZDpgLCAuLi4oZS5uYW1lID8gW2Ake2UubmFtZX06YF0gOiBbXSksIGUubWVzc2FnZV0uam9pbignICcpO1xuICAgICAgY29uc3Qgd3JhcHBlZEVycm9yID0gbmV3IFRvb2xraXRFcnJvcihjb2RlLCBuZXdNZXNzYWdlKTtcblxuICAgICAgZXJyb3IgPSB7XG4gICAgICAgIG5hbWU6IGNka0NsaUVycm9yTmFtZSh3cmFwcGVkRXJyb3IpLFxuICAgICAgfTtcblxuICAgICAgdGhyb3cgd3JhcHBlZEVycm9yO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBkZXBsb3lTcGFuLmVuZCh7IGVycm9yIH0pO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmNsb3VkV2F0Y2hMb2dNb25pdG9yKSB7XG4gICAgICAgIGNvbnN0IGZvdW5kTG9nR3JvdXBzUmVzdWx0ID0gYXdhaXQgZmluZENsb3VkV2F0Y2hMb2dHcm91cHModGhpcy5vcHRpb25zLnNka1Byb3ZpZGVyLCBhc0lvSGVscGVyKHRoaXMuaW9Ib3N0LCAnZGVwbG95JyksIHN0YWNrKTtcbiAgICAgICAgdGhpcy5vcHRpb25zLmNsb3VkV2F0Y2hMb2dNb25pdG9yLmFkZExvZ0dyb3VwcyhcbiAgICAgICAgICBmb3VuZExvZ0dyb3Vwc1Jlc3VsdC5lbnYsXG4gICAgICAgICAgZm91bmRMb2dHcm91cHNSZXN1bHQuc2RrLFxuICAgICAgICAgIGZvdW5kTG9nR3JvdXBzUmVzdWx0LmxvZ0dyb3VwTmFtZXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHdyaXRlT3V0cHV0cyhvdXRwdXRzRmlsZTogc3RyaW5nKSB7XG4gICAgZnMuZW5zdXJlRmlsZVN5bmMob3V0cHV0c0ZpbGUpO1xuICAgIGF3YWl0IGZzLndyaXRlSnNvbihvdXRwdXRzRmlsZSwgdGhpcy5zdGFja091dHB1dHMsIHtcbiAgICAgIHNwYWNlczogMixcbiAgICAgIGVuY29kaW5nOiAndXRmOCcsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgbWFudWFsIGFwcHJvdmFsIGlzIHJlcXVpcmVkIG9yIG5vdC4gUmVxdWlyZXMgYXBwcm92YWwgZm9yXG4gKiAtIFJlcXVpcmVBcHByb3ZhbC5BTllDSEFOR0VcbiAqIC0gUmVxdWlyZUFwcHJvdmFsLkJST0FERU5JTkcgYW5kIHRoZSBjaGFuZ2VzIGFyZSBpbmRlZWQgYnJvYWRlbmluZyBwZXJtaXNzaW9uc1xuICovXG5mdW5jdGlvbiByZXF1aXJlc0FwcHJvdmFsKHJlcXVpcmVBcHByb3ZhbDogUmVxdWlyZUFwcHJvdmFsLCBwZXJtaXNzaW9uQ2hhbmdlVHlwZTogUGVybWlzc2lvbkNoYW5nZVR5cGUpIHtcbiAgcmV0dXJuIHJlcXVpcmVBcHByb3ZhbCA9PT0gUmVxdWlyZUFwcHJvdmFsLkFOWUNIQU5HRSB8fFxuICAgIHJlcXVpcmVBcHByb3ZhbCA9PT0gUmVxdWlyZUFwcHJvdmFsLkJST0FERU5JTkcgJiYgcGVybWlzc2lvbkNoYW5nZVR5cGUgPT09IFBlcm1pc3Npb25DaGFuZ2VUeXBlLkJST0FERU5JTkc7XG59XG5cbiJdfQ==