UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

421 lines 47.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Settings = exports.Context = exports.Configuration = exports.Command = exports.TRANSIENT_CONTEXT_KEY = exports.USER_DEFAULTS = exports.PROJECT_CONTEXT = exports.PROJECT_CONFIG = void 0; const os = require("os"); const fs_path = require("path"); const fs = require("fs-extra"); const logging_1 = require("./logging"); const util = require("./util"); exports.PROJECT_CONFIG = 'cdk.json'; exports.PROJECT_CONTEXT = 'cdk.context.json'; exports.USER_DEFAULTS = '~/.cdk.json'; /** * If a context value is an object with this key set to a truthy value, it won't be saved to cdk.context.json */ exports.TRANSIENT_CONTEXT_KEY = '$dontSaveContext'; const CONTEXT_KEY = 'context'; var Command; (function (Command) { Command["LS"] = "ls"; Command["LIST"] = "list"; Command["DIFF"] = "diff"; Command["BOOTSTRAP"] = "bootstrap"; Command["DEPLOY"] = "deploy"; Command["DESTROY"] = "destroy"; Command["SYNTHESIZE"] = "synthesize"; Command["SYNTH"] = "synth"; Command["METADATA"] = "metadata"; Command["INIT"] = "init"; Command["VERSION"] = "version"; Command["WATCH"] = "watch"; })(Command || (exports.Command = Command = {})); const BUNDLING_COMMANDS = [ Command.DEPLOY, Command.DIFF, Command.SYNTH, Command.SYNTHESIZE, Command.WATCH, ]; /** * All sources of settings combined */ class Configuration { constructor(props = {}) { this.props = props; this.settings = new Settings(); this.context = new Context(); this.defaultConfig = new Settings({ versionReporting: true, assetMetadata: true, pathMetadata: true, output: 'cdk.out', }); this.loaded = false; this.commandLineArguments = props.commandLineArguments ? Settings.fromCommandLineArguments(props.commandLineArguments) : new Settings(); this.commandLineContext = this.commandLineArguments.subSettings([CONTEXT_KEY]).makeReadOnly(); } get projectConfig() { if (!this._projectConfig) { throw new Error('#load has not been called yet!'); } return this._projectConfig; } get projectContext() { if (!this._projectContext) { throw new Error('#load has not been called yet!'); } return this._projectContext; } /** * Load all config */ async load() { const userConfig = await loadAndLog(exports.USER_DEFAULTS); this._projectConfig = await loadAndLog(exports.PROJECT_CONFIG); this._projectContext = await loadAndLog(exports.PROJECT_CONTEXT); const readUserContext = this.props.readUserContext ?? true; if (userConfig.get(['build'])) { throw new Error('The `build` key cannot be specified in the user config (~/.cdk.json), specify it in the project config (cdk.json) instead'); } const contextSources = [ this.commandLineContext, this.projectConfig.subSettings([CONTEXT_KEY]).makeReadOnly(), this.projectContext, ]; if (readUserContext) { contextSources.push(userConfig.subSettings([CONTEXT_KEY]).makeReadOnly()); } this.context = new Context(...contextSources); // Build settings from what's left this.settings = this.defaultConfig .merge(userConfig) .merge(this.projectConfig) .merge(this.commandLineArguments) .makeReadOnly(); (0, logging_1.debug)('merged settings:', this.settings.all); this.loaded = true; return this; } /** * Save the project context */ async saveContext() { if (!this.loaded) { return this; } // Avoid overwriting files with nothing await this.projectContext.save(exports.PROJECT_CONTEXT); return this; } } exports.Configuration = Configuration; async function loadAndLog(fileName) { const ret = new Settings(); await ret.load(fileName); if (!ret.empty) { (0, logging_1.debug)(fileName + ':', JSON.stringify(ret.all, undefined, 2)); } return ret; } /** * Class that supports overlaying property bags * * Reads come from the first property bag that can has the given key, * writes go to the first property bag that is not readonly. A write * will remove the value from all property bags after the first * writable one. */ class Context { constructor(...bags) { this.bags = bags.length > 0 ? bags : [new Settings()]; } get keys() { return Object.keys(this.all); } has(key) { return this.keys.indexOf(key) > -1; } get all() { let ret = new Settings(); // In reverse order so keys to the left overwrite keys to the right of them for (const bag of [...this.bags].reverse()) { ret = ret.merge(bag); } return ret.all; } get(key) { for (const bag of this.bags) { const v = bag.get([key]); if (v !== undefined) { return v; } } return undefined; } set(key, value) { for (const bag of this.bags) { if (bag.readOnly) { continue; } // All bags past the first one have the value erased bag.set([key], value); value = undefined; } } unset(key) { this.set(key, undefined); } clear() { for (const key of this.keys) { this.unset(key); } } } exports.Context = Context; /** * A single bag of settings */ class Settings { /** * Parse Settings out of CLI arguments. * * CLI arguments in must be accessed in the CLI code via * `configuration.settings.get(['argName'])` instead of via `args.argName`. * * The advantage is that they can be configured via `cdk.json` and * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object * can only be specified on the command line. * * @param argv the received CLI arguments. * @returns a new Settings object. */ static fromCommandLineArguments(argv) { const context = this.parseStringContextListToObject(argv); const tags = this.parseStringTagsListToObject(expectStringList(argv.tags)); // Determine bundling stacks let bundlingStacks; if (BUNDLING_COMMANDS.includes(argv._[0])) { // If we deploy, diff, synth or watch a list of stacks exclusively we skip // bundling for all other stacks. bundlingStacks = argv.exclusively ? argv.STACKS ?? ['**'] : ['**']; } else { // Skip bundling for all stacks bundlingStacks = []; } return new Settings({ app: argv.app, browser: argv.browser, build: argv.build, context, debug: argv.debug, tags, language: argv.language, pathMetadata: argv.pathMetadata, assetMetadata: argv.assetMetadata, profile: argv.profile, plugin: argv.plugin, requireApproval: argv.requireApproval, toolkitStackName: argv.toolkitStackName, toolkitBucket: { bucketName: argv.bootstrapBucketName, kmsKeyId: argv.bootstrapKmsKeyId, }, versionReporting: argv.versionReporting, staging: argv.staging, output: argv.output, outputsFile: argv.outputsFile, progress: argv.progress, bundlingStacks, lookups: argv.lookups, rollback: argv.rollback, notices: argv.notices, assetParallelism: argv['asset-parallelism'], assetPrebuild: argv['asset-prebuild'], }); } static mergeAll(...settings) { let ret = new Settings(); for (const setting of settings) { ret = ret.merge(setting); } return ret; } static parseStringContextListToObject(argv) { const context = {}; for (const assignment of (argv.context || [])) { const parts = assignment.split(/=(.*)/, 2); if (parts.length === 2) { (0, logging_1.debug)('CLI argument context: %s=%s', parts[0], parts[1]); if (parts[0].match(/^aws:.+/)) { throw new Error(`User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`); } context[parts[0]] = parts[1]; } else { (0, logging_1.warning)('Context argument is not an assignment (key=value): %s', assignment); } } return context; } /** * Parse tags out of arguments * * Return undefined if no tags were provided, return an empty array if only empty * strings were provided */ static parseStringTagsListToObject(argTags) { if (argTags === undefined) { return undefined; } if (argTags.length === 0) { return undefined; } const nonEmptyTags = argTags.filter(t => t !== ''); if (nonEmptyTags.length === 0) { return []; } const tags = []; for (const assignment of nonEmptyTags) { const parts = assignment.split(/=(.*)/, 2); if (parts.length === 2) { (0, logging_1.debug)('CLI argument tags: %s=%s', parts[0], parts[1]); tags.push({ Key: parts[0], Value: parts[1], }); } else { (0, logging_1.warning)('Tags argument is not an assignment (key=value): %s', assignment); } } return tags.length > 0 ? tags : undefined; } constructor(settings = {}, readOnly = false) { this.settings = settings; this.readOnly = readOnly; } async load(fileName) { if (this.readOnly) { throw new Error(`Can't load ${fileName}: settings object is readonly`); } this.settings = {}; const expanded = expandHomeDir(fileName); if (await fs.pathExists(expanded)) { this.settings = await fs.readJson(expanded); } // See https://github.com/aws/aws-cdk/issues/59 this.prohibitContextKey('default-account', fileName); this.prohibitContextKey('default-region', fileName); this.warnAboutContextKey('aws:', fileName); return this; } async save(fileName) { const expanded = expandHomeDir(fileName); await fs.writeJson(expanded, stripTransientValues(this.settings), { spaces: 2 }); return this; } get all() { return this.get([]); } merge(other) { return new Settings(util.deepMerge(this.settings, other.settings)); } subSettings(keyPrefix) { return new Settings(this.get(keyPrefix) || {}, false); } makeReadOnly() { return new Settings(this.settings, true); } clear() { if (this.readOnly) { throw new Error('Cannot clear(): settings are readonly'); } this.settings = {}; } get empty() { return Object.keys(this.settings).length === 0; } get(path) { return util.deepClone(util.deepGet(this.settings, path)); } set(path, value) { if (this.readOnly) { throw new Error(`Can't set ${path}: settings object is readonly`); } if (path.length === 0) { // deepSet can't handle this case this.settings = value; } else { util.deepSet(this.settings, path, value); } return this; } unset(path) { this.set(path, undefined); } prohibitContextKey(key, fileName) { if (!this.settings.context) { return; } if (key in this.settings.context) { // eslint-disable-next-line max-len throw new Error(`The 'context.${key}' key was found in ${fs_path.resolve(fileName)}, but it is no longer supported. Please remove it.`); } } warnAboutContextKey(prefix, fileName) { if (!this.settings.context) { return; } for (const contextKey of Object.keys(this.settings.context)) { if (contextKey.startsWith(prefix)) { // eslint-disable-next-line max-len (0, logging_1.warning)(`A reserved context key ('context.${prefix}') key was found in ${fs_path.resolve(fileName)}, it might cause surprising behavior and should be removed.`); } } } } exports.Settings = Settings; function expandHomeDir(x) { if (x.startsWith('~')) { return fs_path.join(os.homedir(), x.slice(1)); } return x; } /** * Return all context value that are not transient context values */ function stripTransientValues(obj) { const ret = {}; for (const [key, value] of Object.entries(obj)) { if (!isTransientValue(value)) { ret[key] = value; } } return ret; } /** * Return whether the given value is a transient context value * * Values that are objects with a magic key set to a truthy value are considered transient. */ function isTransientValue(value) { return typeof value === 'object' && value !== null && value[exports.TRANSIENT_CONTEXT_KEY]; } function expectStringList(x) { if (x === undefined) { return undefined; } if (!Array.isArray(x)) { throw new Error(`Expected array, got '${x}'`); } const nonStrings = x.filter(e => typeof e !== 'string'); if (nonStrings.length > 0) { throw new Error(`Expected list of strings, found ${nonStrings}`); } return x; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5QkFBeUI7QUFDekIsZ0NBQWdDO0FBQ2hDLCtCQUErQjtBQUUvQix1Q0FBMkM7QUFDM0MsK0JBQStCO0FBSWxCLFFBQUEsY0FBYyxHQUFHLFVBQVUsQ0FBQztBQUM1QixRQUFBLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQztBQUNyQyxRQUFBLGFBQWEsR0FBRyxhQUFhLENBQUM7QUFFM0M7O0dBRUc7QUFDVSxRQUFBLHFCQUFxQixHQUFHLGtCQUFrQixDQUFDO0FBRXhELE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQztBQUU5QixJQUFZLE9BYVg7QUFiRCxXQUFZLE9BQU87SUFDakIsb0JBQVMsQ0FBQTtJQUNULHdCQUFhLENBQUE7SUFDYix3QkFBYSxDQUFBO0lBQ2Isa0NBQXVCLENBQUE7SUFDdkIsNEJBQWlCLENBQUE7SUFDakIsOEJBQW1CLENBQUE7SUFDbkIsb0NBQXlCLENBQUE7SUFDekIsMEJBQWUsQ0FBQTtJQUNmLGdDQUFxQixDQUFBO0lBQ3JCLHdCQUFhLENBQUE7SUFDYiw4QkFBbUIsQ0FBQTtJQUNuQiwwQkFBZSxDQUFBO0FBQ2pCLENBQUMsRUFiVyxPQUFPLHVCQUFQLE9BQU8sUUFhbEI7QUFFRCxNQUFNLGlCQUFpQixHQUFHO0lBQ3hCLE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLElBQUk7SUFDWixPQUFPLENBQUMsS0FBSztJQUNiLE9BQU8sQ0FBQyxVQUFVO0lBQ2xCLE9BQU8sQ0FBQyxLQUFLO0NBQ2QsQ0FBQztBQTBCRjs7R0FFRztBQUNILE1BQWEsYUFBYTtJQWlCeEIsWUFBNkIsUUFBNEIsRUFBRTtRQUE5QixVQUFLLEdBQUwsS0FBSyxDQUF5QjtRQWhCcEQsYUFBUSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7UUFDMUIsWUFBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFF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SUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUMvQztJQUNELE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQztJQUN4RCxJQUFJLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLFVBQVUsRUFBRSxDQUFDLENBQUM7S0FDbEU7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBmc19wYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi9jZGstdG9vbGtpdCc7XG5pbXBvcnQgeyBkZWJ1Zywgd2FybmluZyB9IGZyb20gJy4vbG9nZ2luZyc7XG5pbXBvcnQgKiBhcyB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCB0eXBlIFNldHRpbmdzTWFwID0ge1trZXk6IHN0cmluZ106IGFueX07XG5cbmV4cG9ydCBjb25zdCBQUk9KRUNUX0NPTkZJRyA9ICdjZGsuanNvbic7XG5leHBvcnQgY29uc3QgUFJPSkVDVF9DT05URVhUID0gJ2Nkay5jb250ZXh0Lmpzb24nO1xuZXhwb3J0IGNvbnN0IFVTRVJfREVGQVVMVFMgPSAnfi8uY2RrLmpzb24nO1xuXG4vKipcbiAqIElmIGEgY29udGV4dCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCB0aGlzIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUsIGl0IHdvbid0IGJlIHNhdmVkIHRvIGNkay5jb250ZXh0Lmpzb25cbiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TSUVOVF9DT05URVhUX0tFWSA9ICckZG9udFNhdmVDb250ZXh0JztcblxuY29uc3QgQ09OVEVYVF9LRVkgPSAnY29udGV4dCc7XG5cbmV4cG9ydCBlbnVtIENvbW1hbmQge1xuICBMUyA9ICdscycsXG4gIExJU1QgPSAnbGlzdCcsXG4gIERJRkYgPSAnZGlmZicsXG4gIEJPT1RTVFJBUCA9ICdib290c3RyYXAnLFxuICBERVBMT1kgPSAnZGVwbG95JyxcbiAgREVTVFJPWSA9ICdkZXN0cm95JyxcbiAgU1lOVEhFU0laRSA9ICdzeW50aGVzaXplJyxcbiAgU1lOVEggPSAnc3ludGgnLFxuICBNRVRBREFUQSA9ICdtZXRhZGF0YScsXG4gIElOSVQgPSAnaW5pdCcsXG4gIFZFUlNJT04gPSAndmVyc2lvbicsXG4gIFdBVENIID0gJ3dhdGNoJyxcbn1cblxuY29uc3QgQlVORExJTkdfQ09NTUFORFMgPSBbXG4gIENvbW1hbmQuREVQTE9ZLFxuICBDb21tYW5kLkRJRkYsXG4gIENvbW1hbmQuU1lOVEgsXG4gIENvbW1hbmQuU1lOVEhFU0laRSxcbiAgQ29tbWFuZC5XQVRDSCxcbl07XG5cbmV4cG9ydCB0eXBlIEFyZ3VtZW50cyA9IHtcbiAgcmVhZG9ubHkgXzogW0NvbW1hbmQsIC4uLnN0cmluZ1tdXTtcbiAgcmVhZG9ubHkgZXhjbHVzaXZlbHk/OiBib29sZWFuO1xuICByZWFkb25seSBTVEFDS1M/OiBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgbG9va3Vwcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IFtuYW1lOiBzdHJpbmddOiB1bmtub3duO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDb25maWd1cmF0aW9uUHJvcHMge1xuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBwYXNzZWQgdmlhIGNvbW1hbmQgbGluZSBhcmd1bWVudHNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb3RoaW5nIHBhc3NlZFxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZExpbmVBcmd1bWVudHM/OiBBcmd1bWVudHM7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRvIHVzZSBjb250ZXh0IGZyb20gYC5jZGsuanNvbmAgaW4gdXNlciBob21lIGRpcmVjdG9yeVxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSByZWFkVXNlckNvbnRleHQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEFsbCBzb3VyY2VzIG9mIHNldHRpbmdzIGNvbWJpbmVkXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25maWd1cmF0aW9uIHtcbiAgcHVibGljIHNldHRpbmdzID0gbmV3IFNldHRpbmdzKCk7XG4gIHB1YmxpYyBjb250ZXh0ID0gbmV3IENvbnRleHQoKTtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdENvbmZpZyA9IG5ldyBTZXR0aW5ncyh7XG4gICAgdmVyc2lvblJlcG9ydGluZzogdHJ1ZSxcbiAgICBhc3NldE1ldGFkYXRhOiB0cnVlLFxuICAgIHBhdGhNZXRhZGF0YTogdHJ1ZSxcbiAgICBvdXRwdXQ6ICdjZGsub3V0JyxcbiAgfSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kTGluZUFyZ3VtZW50czogU2V0dGluZ3M7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZExpbmVDb250ZXh0OiBTZXR0aW5ncztcbiAgcHJpdmF0ZSBfcHJvamVjdENvbmZpZz86IFNldHRpbmdzO1xuICBwcml2YXRlIF9wcm9qZWN0Q29udGV4dD86IFNldHRpbmdzO1xuICBwcml2YXRlIGxvYWRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IENvbmZpZ3VyYXRpb25Qcm9wcyA9IHt9KSB7XG4gICAgdGhpcy5jb21tYW5kTGluZUFyZ3VtZW50cyA9IHByb3BzLmNvbW1hbmRMaW5lQXJndW1lbnRzXG4gICAgICA/IFNldHRpbmdzLmZyb21Db21tYW5kTGluZUFyZ3VtZW50cyhwcm9wcy5jb21tYW5kTGluZUFyZ3VtZW50cylcbiAgICAgIDogbmV3IFNldHRpbmdzKCk7XG4gICAgdGhpcy5jb21tYW5kTGluZUNvbnRleHQgPSB0aGlzLmNvbW1hbmRMaW5lQXJndW1lbnRzLnN1YlNldHRpbmdzKFtDT05URVhUX0tFWV0pLm1ha2VSZWFkT25seSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgcHJvamVjdENvbmZpZygpIHtcbiAgICBpZiAoIXRoaXMuX3Byb2plY3RDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignI2xvYWQgaGFzIG5vdCBiZWVuIGNhbGxlZCB5ZXQhJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9wcm9qZWN0Q29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgcHJvamVjdENvbnRleHQoKSB7XG4gICAgaWYgKCF0aGlzLl9wcm9qZWN0Q29udGV4dCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCcjbG9hZCBoYXMgbm90IGJlZW4gY2FsbGVkIHlldCEnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3Byb2plY3RDb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgYWxsIGNvbmZpZ1xuICAgKi9cbiAgcHVibGljIGFzeW5jIGxvYWQoKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgY29uc3QgdXNlckNvbmZpZyA9IGF3YWl0IGxvYWRBbmRMb2coVVNFUl9ERUZBVUxUUyk7XG4gICAgdGhpcy5fcHJvamVjdENvbmZpZyA9IGF3YWl0IGxvYWRBbmRMb2coUFJPSkVDVF9DT05GSUcpO1xuICAgIHRoaXMuX3Byb2plY3RDb250ZXh0ID0gYXdhaXQgbG9hZEFuZExvZyhQUk9KRUNUX0NPTlRFWFQpO1xuXG4gICAgY29uc3QgcmVhZFVzZXJDb250ZXh0ID0gdGhpcy5wcm9wcy5yZWFkVXNlckNvbnRleHQgPz8gdHJ1ZTtcblxuICAgIGlmICh1c2VyQ29uZmlnLmdldChbJ2J1aWxkJ10pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBgYnVpbGRgIGtleSBjYW5ub3QgYmUgc3BlY2lmaWVkIGluIHRoZSB1c2VyIGNvbmZpZyAofi8uY2RrLmpzb24pLCBzcGVjaWZ5IGl0IGluIHRoZSBwcm9qZWN0IGNvbmZpZyAoY2RrLmpzb24pIGluc3RlYWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb250ZXh0U291cmNlcyA9IFtcbiAgICAgIHRoaXMuY29tbWFuZExpbmVDb250ZXh0LFxuICAgICAgdGhpcy5wcm9qZWN0Q29uZmlnLnN1YlNldHRpbmdzKFtDT05URVhUX0tFWV0pLm1ha2VSZWFkT25seSgpLFxuICAgICAgdGhpcy5wcm9qZWN0Q29udGV4dCxcbiAgICBdO1xuICAgIGlmIChyZWFkVXNlckNvbnRleHQpIHtcbiAgICAgIGNvbnRleHRTb3VyY2VzLnB1c2godXNlckNvbmZpZy5zdWJTZXR0aW5ncyhbQ09OVEVYVF9LRVldKS5tYWtlUmVhZE9ubHkoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5jb250ZXh0ID0gbmV3IENvbnRleHQoLi4uY29udGV4dFNvdXJjZXMpO1xuXG4gICAgLy8gQnVpbGQgc2V0dGluZ3MgZnJvbSB3aGF0J3MgbGVmdFxuICAgIHRoaXMuc2V0dGluZ3MgPSB0aGlzLmRlZmF1bHRDb25maWdcbiAgICAgIC5tZXJnZSh1c2VyQ29uZmlnKVxuICAgICAgLm1lcmdlKHRoaXMucHJvamVjdENvbmZpZylcbiAgICAgIC5tZXJnZSh0aGlzLmNvbW1hbmRMaW5lQXJndW1lbnRzKVxuICAgICAgLm1ha2VSZWFkT25seSgpO1xuXG4gICAgZGVidWcoJ21lcmdlZCBzZXR0aW5nczonLCB0aGlzLnNldHRpbmdzLmFsbCk7XG5cbiAgICB0aGlzLmxvYWRlZCA9IHRydWU7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlIHRoZSBwcm9qZWN0IGNvbnRleHRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzYXZlQ29udGV4dCgpOiBQcm9taXNlPHRoaXM+IHtcbiAgICBpZiAoIXRoaXMubG9hZGVkKSB7IHJldHVybiB0aGlzOyB9IC8vIEF2b2lkIG92ZXJ3cml0aW5nIGZpbGVzIHdpdGggbm90aGluZ1xuXG4gICAgYXdhaXQgdGhpcy5wcm9qZWN0Q29udGV4dC5zYXZlKFBST0pFQ1RfQ09OVEVYVCk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBsb2FkQW5kTG9nKGZpbGVOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFNldHRpbmdzPiB7XG4gIGNvbnN0IHJldCA9IG5ldyBTZXR0aW5ncygpO1xuICBhd2FpdCByZXQubG9hZChmaWxlTmFtZSk7XG4gIGlmICghcmV0LmVtcHR5KSB7XG4gICAgZGVidWcoZmlsZU5hbWUgKyAnOicsIEpTT04uc3RyaW5naWZ5KHJldC5hbGwsIHVuZGVmaW5lZCwgMikpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ2xhc3MgdGhhdCBzdXBwb3J0cyBvdmVybGF5aW5nIHByb3BlcnR5IGJhZ3NcbiAqXG4gKiBSZWFkcyBjb21lIGZyb20gdGhlIGZpcnN0IHByb3BlcnR5IGJhZyB0aGF0IGNhbiBoYXMgdGhlIGdpdmVuIGtleSxcbiAqIHdyaXRlcyBnbyB0byB0aGUgZmlyc3QgcHJvcGVydHkgYmFnIHRoYXQgaXMgbm90IHJlYWRvbmx5LiBBIHdyaXRlXG4gKiB3aWxsIHJlbW92ZSB0aGUgdmFsdWUgZnJvbSBhbGwgcHJvcGVydHkgYmFncyBhZnRlciB0aGUgZmlyc3RcbiAqIHdyaXRhYmxlIG9uZS5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRleHQge1xuICBwcml2YXRlIHJlYWRvbmx5IGJhZ3M6IFNldHRpbmdzW107XG5cbiAgY29uc3RydWN0b3IoLi4uYmFnczogU2V0dGluZ3NbXSkge1xuICAgIHRoaXMuYmFncyA9IGJhZ3MubGVuZ3RoID4gMCA/IGJhZ3MgOiBbbmV3IFNldHRpbmdzKCldO1xuICB9XG5cbiAgcHVibGljIGdldCBrZXlzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5hbGwpO1xuICB9XG5cbiAgcHVibGljIGhhcyhrZXk6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmtleXMuaW5kZXhPZihrZXkpID4gLTE7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFsbCgpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgbGV0IHJldCA9IG5ldyBTZXR0aW5ncygpO1xuXG4gICAgLy8gSW4gcmV2ZXJzZSBvcmRlciBzbyBrZXlzIHRvIHRoZSBsZWZ0IG92ZXJ3cml0ZSBrZXlzIHRvIHRoZSByaWdodCBvZiB0aGVtXG4gICAgZm9yIChjb25zdCBiYWcgb2YgWy4uLnRoaXMuYmFnc10ucmV2ZXJzZSgpKSB7XG4gICAgICByZXQgPSByZXQubWVyZ2UoYmFnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0LmFsbDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQoa2V5OiBzdHJpbmcpOiBhbnkge1xuICAgIGZvciAoY29uc3QgYmFnIG9mIHRoaXMuYmFncykge1xuICAgICAgY29uc3QgdiA9IGJhZy5nZXQoW2tleV0pO1xuICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdjsgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIHNldChrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGZvciAoY29uc3QgYmFnIG9mIHRoaXMuYmFncykge1xuICAgICAgaWYgKGJhZy5yZWFkT25seSkgeyBjb250aW51ZTsgfVxuXG4gICAgICAvLyBBbGwgYmFncyBwYXN0IHRoZSBmaXJzdCBvbmUgaGF2ZSB0aGUgdmFsdWUgZXJhc2VkXG4gICAgICBiYWcuc2V0KFtrZXldLCB2YWx1ZSk7XG4gICAgICB2YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgdW5zZXQoa2V5OiBzdHJpbmcpIHtcbiAgICB0aGlzLnNldChrZXksIHVuZGVmaW5lZCk7XG4gIH1cblxuICBwdWJsaWMgY2xlYXIoKSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy5rZXlzKSB7XG4gICAgICB0aGlzLnVuc2V0KGtleSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQSBzaW5nbGUgYmFnIG9mIHNldHRpbmdzXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXR0aW5ncyB7XG5cbiAgLyoqXG4gICAqIFBhcnNlIFNldHRpbmdzIG91dCBvZiBDTEkgYXJndW1lbnRzLlxuICAgKlxuICAgKiBDTEkgYXJndW1lbnRzIGluIG11c3QgYmUgYWNjZXNzZWQgaW4gdGhlIENMSSBjb2RlIHZpYVxuICAgKiBgY29uZmlndXJhdGlvbi5zZXR0aW5ncy5nZXQoWydhcmdOYW1lJ10pYCBpbnN0ZWFkIG9mIHZpYSBgYXJncy5hcmdOYW1lYC5cbiAgICpcbiAgICogVGhlIGFkdmFudGFnZSBpcyB0aGF0IHRoZXkgY2FuIGJlIGNvbmZpZ3VyZWQgdmlhIGBjZGsuanNvbmAgYW5kXG4gICAqIGAkSE9NRS8uY2RrLmpzb25gLiBBcmd1bWVudHMgbm90IGxpc3RlZCBiZWxvdyBhbmQgYWNjZXNzZWQgdmlhIHRoaXMgb2JqZWN0XG4gICAqIGNhbiBvbmx5IGJlIHNwZWNpZmllZCBvbiB0aGUgY29tbWFuZCBsaW5lLlxuICAgKlxuICAgKiBAcGFyYW0gYXJndiB0aGUgcmVjZWl2ZWQgQ0xJIGFyZ3VtZW50cy5cbiAgICogQHJldHVybnMgYSBuZXcgU2V0dGluZ3Mgb2JqZWN0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tQ29tbWFuZExpbmVBcmd1bWVudHMoYXJndjogQXJndW1lbnRzKTogU2V0dGluZ3Mge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLnBhcnNlU3RyaW5nQ29udGV4dExpc3RUb09iamVjdChhcmd2KTtcbiAgICBjb25zdCB0YWdzID0gdGhpcy5wYXJzZVN0cmluZ1RhZ3NMaXN0VG9PYmplY3QoZXhwZWN0U3RyaW5nTGlzdChhcmd2LnRhZ3MpKTtcblxuICAgIC8vIERldGVybWluZSBidW5kbGluZyBzdGFja3NcbiAgICBsZXQgYnVuZGxpbmdTdGFja3M6IHN0cmluZ1tdO1xuICAgIGlmIChCVU5ETElOR19DT01NQU5EUy5pbmNsdWRlcyhhcmd2Ll9bMF0pKSB7XG4gICAgLy8gSWYgd2UgZGVwbG95LCBkaWZmLCBzeW50aCBvciB3YXRjaCBhIGxpc3Qgb2Ygc3RhY2tzIGV4Y2x1c2l2ZWx5IHdlIHNraXBcbiAgICAvLyBidW5kbGluZyBmb3IgYWxsIG90aGVyIHN0YWNrcy5cbiAgICAgIGJ1bmRsaW5nU3RhY2tzID0gYXJndi5leGNsdXNpdmVseVxuICAgICAgICA/IGFyZ3YuU1RBQ0tTID8/IFsnKionXVxuICAgICAgICA6IFsnKionXTtcbiAgICB9IGVsc2UgeyAvLyBTa2lwIGJ1bmRsaW5nIGZvciBhbGwgc3RhY2tzXG4gICAgICBidW5kbGluZ1N0YWNrcyA9IFtdO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgU2V0dGluZ3Moe1xuICAgICAgYXBwOiBhcmd2LmFwcCxcbiAgICAgIGJyb3dzZXI6IGFyZ3YuYnJvd3NlcixcbiAgICAgIGJ1aWxkOiBhcmd2LmJ1aWxkLFxuICAgICAgY29udGV4dCxcbiAgICAgIGRlYnVnOiBhcmd2LmRlYnVnLFxuICAgICAgdGFncyxcbiAgICAgIGxhbmd1YWdlOiBhcmd2Lmxhbmd1YWdlLFxuICAgICAgcGF0aE1ldGFkYXRhOiBhcmd2LnBhdGhNZXRhZGF0YSxcbiAgICAgIGFzc2V0TWV0YWRhdGE6IGFyZ3YuYXNzZXRNZXRhZGF0YSxcbiAgICAgIHByb2ZpbGU6IGFyZ3YucHJvZmlsZSxcbiAgICAgIHBsdWdpbjogYXJndi5wbHVnaW4sXG4gICAgICByZXF1aXJlQXBwcm92YWw6IGFyZ3YucmVxdWlyZUFwcHJvdmFsLFxuICAgICAgdG9vbGtpdFN0YWNrTmFtZTogYXJndi50b29sa2l0U3RhY2tOYW1lLFxuICAgICAgdG9vbGtpdEJ1Y2tldDoge1xuICAgICAgICBidWNrZXROYW1lOiBhcmd2LmJvb3RzdHJhcEJ1Y2tldE5hbWUsXG4gICAgICAgIGttc0tleUlkOiBhcmd2LmJvb3RzdHJhcEttc0tleUlkLFxuICAgICAgfSxcbiAgICAgIHZlcnNpb25SZXBvcnRpbmc6IGFyZ3YudmVyc2lvblJlcG9ydGluZyxcbiAgICAgIHN0YWdpbmc6IGFyZ3Yuc3RhZ2luZyxcbiAgICAgIG91dHB1dDogYXJndi5vdXRwdXQsXG4gICAgICBvdXRwdXRzRmlsZTogYXJndi5vdXRwdXRzRmlsZSxcbiAgICAgIHByb2dyZXNzOiBhcmd2LnByb2dyZXNzLFxuICAgICAgYnVuZGxpbmdTdGFja3MsXG4gICAgICBsb29rdXBzOiBhcmd2Lmxvb2t1cHMsXG4gICAgICByb2xsYmFjazogYXJndi5yb2xsYmFjayxcbiAgICAgIG5vdGljZXM6IGFyZ3Yubm90aWNlcyxcbiAgICAgIGFzc2V0UGFyYWxsZWxpc206IGFyZ3ZbJ2Fzc2V0LXBhcmFsbGVsaXNtJ10sXG4gICAgICBhc3NldFByZWJ1aWxkOiBhcmd2Wydhc3NldC1wcmVidWlsZCddLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBtZXJnZUFsbCguLi5zZXR0aW5nczogU2V0dGluZ3NbXSk6IFNldHRpbmdzIHtcbiAgICBsZXQgcmV0ID0gbmV3IFNldHRpbmdzKCk7XG4gICAgZm9yIChjb25zdCBzZXR0aW5nIG9mIHNldHRpbmdzKSB7XG4gICAgICByZXQgPSByZXQubWVyZ2Uoc2V0dGluZyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ0NvbnRleHRMaXN0VG9PYmplY3QoYXJndjogQXJndW1lbnRzKTogYW55IHtcbiAgICBjb25zdCBjb250ZXh0OiBhbnkgPSB7fTtcblxuICAgIGZvciAoY29uc3QgYXNzaWdubWVudCBvZiAoKGFyZ3YgYXMgYW55KS5jb250ZXh0IHx8IFtdKSkge1xuICAgICAgY29uc3QgcGFydHMgPSBhc3NpZ25tZW50LnNwbGl0KC89KC4qKS8sIDIpO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICBkZWJ1ZygnQ0xJIGFyZ3VtZW50IGNvbnRleHQ6ICVzPSVzJywgcGFydHNbMF0sIHBhcnRzWzFdKTtcbiAgICAgICAgaWYgKHBhcnRzWzBdLm1hdGNoKC9eYXdzOi4rLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVzZXItcHJvdmlkZWQgY29udGV4dCBjYW5ub3QgdXNlIGtleXMgcHJlZml4ZWQgd2l0aCAnYXdzOicsIGJ1dCAke3BhcnRzWzBdfSB3YXMgcHJvdmlkZWQuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGV4dFtwYXJ0c1swXV0gPSBwYXJ0c1sxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdhcm5pbmcoJ0NvbnRleHQgYXJndW1lbnQgaXMgbm90IGFuIGFzc2lnbm1lbnQgKGtleT12YWx1ZSk6ICVzJywgYXNzaWdubWVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIHRhZ3Mgb3V0IG9mIGFyZ3VtZW50c1xuICAgKlxuICAgKiBSZXR1cm4gdW5kZWZpbmVkIGlmIG5vIHRhZ3Mgd2VyZSBwcm92aWRlZCwgcmV0dXJuIGFuIGVtcHR5IGFycmF5IGlmIG9ubHkgZW1wdHlcbiAgICogc3RyaW5ncyB3ZXJlIHByb3ZpZGVkXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ1RhZ3NMaXN0VG9PYmplY3QoYXJnVGFnczogc3RyaW5nW10gfCB1bmRlZmluZWQpOiBUYWdbXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGFyZ1RhZ3MgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gICAgaWYgKGFyZ1RhZ3MubGVuZ3RoID09PSAwKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgICBjb25zdCBub25FbXB0eVRhZ3MgPSBhcmdUYWdzLmZpbHRlcih0ID0+IHQgIT09ICcnKTtcbiAgICBpZiAobm9uRW1wdHlUYWdzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gW107IH1cblxuICAgIGNvbnN0IHRhZ3M6IFRhZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGFzc2lnbm1lbnQgb2Ygbm9uRW1wdHlUYWdzKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IGFzc2lnbm1lbnQuc3BsaXQoLz0oLiopLywgMik7XG4gICAgICBpZiAocGFydHMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIGRlYnVnKCdDTEkgYXJndW1lbnQgdGFnczogJXM9JXMnLCBwYXJ0c1swXSwgcGFydHNbMV0pO1xuICAgICAgICB0YWdzLnB1c2goe1xuICAgICAgICAgIEtleTogcGFydHNbMF0sXG4gICAgICAgICAgVmFsdWU6IHBhcnRzWzFdLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdhcm5pbmcoJ1RhZ3MgYXJndW1lbnQgaXMgbm90IGFuIGFzc2lnbm1lbnQgKGtleT12YWx1ZSk6ICVzJywgYXNzaWdubWVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0YWdzLmxlbmd0aCA+IDAgPyB0YWdzIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NNYXAgPSB7fSwgcHVibGljIHJlYWRvbmx5IHJlYWRPbmx5ID0gZmFsc2UpIHt9XG5cbiAgcHVibGljIGFzeW5jIGxvYWQoZmlsZU5hbWU6IHN0cmluZyk6IFByb21pc2U8dGhpcz4ge1xuICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGxvYWQgJHtmaWxlTmFtZX06IHNldHRpbmdzIG9iamVjdCBpcyByZWFkb25seWApO1xuICAgIH1cbiAgICB0aGlzLnNldHRpbmdzID0ge307XG5cbiAgICBjb25zdCBleHBhbmRlZCA9IGV4cGFuZEhvbWVEaXIoZmlsZU5hbWUpO1xuICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGV4cGFuZGVkKSkge1xuICAgICAgdGhpcy5zZXR0aW5ncyA9IGF3YWl0IGZzLnJlYWRKc29uKGV4cGFuZGVkKTtcbiAgICB9XG5cbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy81OVxuICAgIHRoaXMucHJvaGliaXRDb250ZXh0S2V5KCdkZWZhdWx0LWFjY291bnQnLCBmaWxlTmFtZSk7XG4gICAgdGhpcy5wcm9oaWJpdENvbnRleHRLZXkoJ2RlZmF1bHQtcmVnaW9uJywgZmlsZU5hbWUpO1xuICAgIHRoaXMud2FybkFib3V0Q29udGV4dEtleSgnYXdzOicsIGZpbGVOYW1lKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHNhdmUoZmlsZU5hbWU6IHN0cmluZyk6IFByb21pc2U8dGhpcz4ge1xuICAgIGNvbnN0IGV4cGFuZGVkID0gZXhwYW5kSG9tZURpcihmaWxlTmFtZSk7XG4gICAgYXdhaXQgZnMud3JpdGVKc29uKGV4cGFuZGVkLCBzdHJpcFRyYW5zaWVudFZhbHVlcyh0aGlzLnNldHRpbmdzKSwgeyBzcGFjZXM6IDIgfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFsbCgpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLmdldChbXSk7XG4gIH1cblxuICBwdWJsaWMgbWVyZ2Uob3RoZXI6IFNldHRpbmdzKTogU2V0dGluZ3Mge1xuICAgIHJldHVybiBuZXcgU2V0dGluZ3ModXRpbC5kZWVwTWVyZ2UodGhpcy5zZXR0aW5ncywgb3RoZXIuc2V0dGluZ3MpKTtcbiAgfVxuXG4gIHB1YmxpYyBzdWJTZXR0aW5ncyhrZXlQcmVmaXg6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIG5ldyBTZXR0aW5ncyh0aGlzLmdldChrZXlQcmVmaXgpIHx8IHt9LCBmYWxzZSk7XG4gIH1cblxuICBwdWJsaWMgbWFrZVJlYWRPbmx5KCk6IFNldHRpbmdzIHtcbiAgICByZXR1cm4gbmV3IFNldHRpbmdzKHRoaXMuc2V0dGluZ3MsIHRydWUpO1xuICB9XG5cbiAgcHVibGljIGNsZWFyKCkge1xuICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjbGVhcigpOiBzZXR0aW5ncyBhcmUgcmVhZG9ubHknKTtcbiAgICB9XG4gICAgdGhpcy5zZXR0aW5ncyA9IHt9O1xuICB9XG5cbiAgcHVibGljIGdldCBlbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5zZXR0aW5ncykubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcHVibGljIGdldChwYXRoOiBzdHJpbmdbXSk6IGFueSB7XG4gICAgcmV0dXJuIHV0aWwuZGVlcENsb25lKHV0aWwuZGVlcEdldCh0aGlzLnNldHRpbmdzLCBwYXRoKSk7XG4gIH1cblxuICBwdWJsaWMgc2V0KHBhdGg6IHN0cmluZ1tdLCB2YWx1ZTogYW55KTogU2V0dGluZ3Mge1xuICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHNldCAke3BhdGh9OiBzZXR0aW5ncyBvYmplY3QgaXMgcmVhZG9ubHlgKTtcbiAgICB9XG4gICAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBkZWVwU2V0IGNhbid0IGhhbmRsZSB0aGlzIGNhc2VcbiAgICAgIHRoaXMuc2V0dGluZ3MgPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXRpbC5kZWVwU2V0KHRoaXMuc2V0dGluZ3MsIHBhdGgsIHZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgdW5zZXQocGF0aDogc3RyaW5nW10pIHtcbiAgICB0aGlzLnNldChwYXRoLCB1bmRlZmluZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9oaWJpdENvbnRleHRLZXkoa2V5OiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMuc2V0dGluZ3MuY29udGV4dCkgeyByZXR1cm47IH1cbiAgICBpZiAoa2V5IGluIHRoaXMuc2V0dGluZ3MuY29udGV4dCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlICdjb250ZXh0LiR7a2V5fScga2V5IHdhcyBmb3VuZCBpbiAke2ZzX3BhdGgucmVzb2x2ZShmaWxlTmFtZSl9LCBidXQgaXQgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gUGxlYXNlIHJlbW92ZSBpdC5gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHdhcm5BYm91dENvbnRleHRLZXkocHJlZml4OiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMuc2V0dGluZ3MuY29udGV4dCkgeyByZXR1cm47IH1cbiAgICBmb3IgKGNvbnN0IGNvbnRleHRLZXkgb2YgT2JqZWN0LmtleXModGhpcy5zZXR0aW5ncy5jb250ZXh0KSkge1xuICAgICAgaWYgKGNvbnRleHRLZXkuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgIHdhcm5pbmcoYEEgcmVzZXJ2ZWQgY29udGV4dCBrZXkgKCdjb250ZXh0LiR7cHJlZml4fScpIGtleSB3YXMgZm91bmQgaW4gJHtmc19wYXRoLnJlc29sdmUoZmlsZU5hbWUpfSwgaXQgbWlnaHQgY2F1c2Ugc3VycHJpc2luZyBiZWhhdmlvciBhbmQgc2hvdWxkIGJlIHJlbW92ZWQuYCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGV4cGFuZEhvbWVEaXIoeDogc3RyaW5nKSB7XG4gIGlmICh4LnN0YXJ0c1dpdGgoJ34nKSkge1xuICAgIHJldHVybiBmc19wYXRoLmpvaW4ob3MuaG9tZWRpcigpLCB4LnNsaWNlKDEpKTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuLyoqXG4gKiBSZXR1cm4gYWxsIGNvbnRleHQgdmFsdWUgdGhhdCBhcmUgbm90IHRyYW5zaWVudCBjb250ZXh0IHZhbHVlc1xuICovXG5mdW5jdGlvbiBzdHJpcFRyYW5zaWVudFZhbHVlcyhvYmo6IHtba2V5OiBzdHJpbmddOiBhbnl9KSB7XG4gIGNvbnN0IHJldDogYW55ID0ge307XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICBpZiAoIWlzVHJhbnNpZW50VmFsdWUodmFsdWUpKSB7XG4gICAgICByZXRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIHRoZSBnaXZlbiB2YWx1ZSBpcyBhIHRyYW5zaWVudCBjb250ZXh0IHZhbHVlXG4gKlxuICogVmFsdWVzIHRoYXQgYXJlIG9iamVjdHMgd2l0aCBhIG1hZ2ljIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUgYXJlIGNvbnNpZGVyZWQgdHJhbnNpZW50LlxuICovXG5mdW5jdGlvbiBpc1RyYW5zaWVudFZhbHVlKHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgKHZhbHVlIGFzIGFueSlbVFJBTlNJRU5UX0NPTlRFWFRfS0VZXTtcbn1cblxuZnVuY3Rpb24gZXhwZWN0U3RyaW5nTGlzdCh4OiB1bmtub3duKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICBpZiAoeCA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgaWYgKCFBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhcnJheSwgZ290ICcke3h9J2ApO1xuICB9XG4gIGNvbnN0IG5vblN0cmluZ3MgPSB4LmZpbHRlcihlID0+IHR5cGVvZiBlICE9PSAnc3RyaW5nJyk7XG4gIGlmIChub25TdHJpbmdzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGxpc3Qgb2Ygc3RyaW5ncywgZm91bmQgJHtub25TdHJpbmdzfWApO1xuICB9XG4gIHJldHVybiB4O1xufVxuIl19