UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

189 lines 26.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NoBootstrapStackEnvironmentResources = exports.EnvironmentResources = exports.EnvironmentResourcesRegistry = void 0; const toolkit_info_1 = require("./toolkit-info"); const logging_1 = require("../logging"); /** * Registry class for `EnvironmentResources`. * * The state management of this class is a bit non-standard. We want to cache * data related to toolkit stacks and SSM parameters, but we are not in charge * of ensuring caching of SDKs. Since `EnvironmentResources` needs an SDK to * function, we treat it as an ephemeral class, and store the actual cached data * in `EnvironmentResourcesRegistry`. */ class EnvironmentResourcesRegistry { constructor(toolkitStackName) { this.toolkitStackName = toolkitStackName; this.cache = new Map(); } for(resolvedEnvironment, sdk) { const key = `${resolvedEnvironment.account}:${resolvedEnvironment.region}`; let envCache = this.cache.get(key); if (!envCache) { envCache = emptyCache(); this.cache.set(key, envCache); } return new EnvironmentResources(resolvedEnvironment, sdk, envCache, this.toolkitStackName); } } exports.EnvironmentResourcesRegistry = EnvironmentResourcesRegistry; /** * Interface with the account and region we're deploying into * * Manages lookups for bootstrapped resources, falling back to the legacy "CDK Toolkit" * original bootstrap stack if necessary. * * The state management of this class is a bit non-standard. We want to cache * data related to toolkit stacks and SSM parameters, but we are not in charge * of ensuring caching of SDKs. Since `EnvironmentResources` needs an SDK to * function, we treat it as an ephemeral class, and store the actual cached data * in `EnvironmentResourcesRegistry`. */ class EnvironmentResources { constructor(environment, sdk, cache, toolkitStackName) { this.environment = environment; this.sdk = sdk; this.cache = cache; this.toolkitStackName = toolkitStackName; } /** * Look up the toolkit for a given environment, using a given SDK */ async lookupToolkit() { if (!this.cache.toolkitInfo) { this.cache.toolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(this.environment, this.sdk, this.toolkitStackName); } return this.cache.toolkitInfo; } /** * Validate that the bootstrap stack version matches or exceeds the expected version * * Use the SSM parameter name to read the version number if given, otherwise use the version * discovered on the bootstrap stack. * * Pass in the SSM parameter name so we can cache the lookups an don't need to do the same * lookup again and again for every artifact. */ async validateVersion(expectedVersion, ssmParameterName) { if (expectedVersion === undefined) { // No requirement return; } const defExpectedVersion = expectedVersion; if (ssmParameterName !== undefined) { try { doValidate(await this.versionFromSsmParameter(ssmParameterName)); return; } catch (e) { if (e.code !== 'AccessDeniedException') { throw e; } // This is a fallback! The bootstrap template that goes along with this change introduces // a new 'ssm:GetParameter' permission, but when run using the previous bootstrap template we // won't have the permissions yet to read the version, so we won't be able to show the // message telling the user they need to update! When we see an AccessDeniedException, fall // back to the version we read from Stack Outputs; but ONLY if the version we discovered via // outputs is legitimately an old version. If it's newer than that, something else must be broken, // so let it fail as it would if we didn't have this fallback. const bootstrapStack = await this.lookupToolkit(); if (bootstrapStack.found && bootstrapStack.version < BOOTSTRAP_TEMPLATE_VERSION_INTRODUCING_GETPARAMETER) { (0, logging_1.warning)(`Could not read SSM parameter ${ssmParameterName}: ${e.message}, falling back to version from ${bootstrapStack}`); doValidate(bootstrapStack.version); return; } throw new Error(`This CDK deployment requires bootstrap stack version '${expectedVersion}', but during the confirmation via SSM parameter ${ssmParameterName} the following error occurred: ${e}`); } } // No SSM parameter const bootstrapStack = await this.lookupToolkit(); doValidate(bootstrapStack.version); function doValidate(version) { if (defExpectedVersion > version) { throw new Error(`This CDK deployment requires bootstrap stack version '${expectedVersion}', found '${version}'. Please run 'cdk bootstrap'.`); } } } /** * Read a version from an SSM parameter, cached */ async versionFromSsmParameter(parameterName) { const existing = this.cache.ssmParameters.get(parameterName); if (existing !== undefined) { return existing; } const ssm = this.sdk.ssm(); try { const result = await ssm.getParameter({ Name: parameterName }).promise(); const asNumber = parseInt(`${result.Parameter?.Value}`, 10); if (isNaN(asNumber)) { throw new Error(`SSM parameter ${parameterName} not a number: ${result.Parameter?.Value}`); } this.cache.ssmParameters.set(parameterName, asNumber); return asNumber; } catch (e) { if (e.code === 'ParameterNotFound') { throw new Error(`SSM parameter ${parameterName} not found. Has the environment been bootstrapped? Please run \'cdk bootstrap\' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)`); } throw e; } } async prepareEcrRepository(repositoryName) { if (!this.sdk) { throw new Error('ToolkitInfo needs to have been initialized with an sdk to call prepareEcrRepository'); } const ecr = this.sdk.ecr(); // check if repo already exists try { (0, logging_1.debug)(`${repositoryName}: checking if ECR repository already exists`); const describeResponse = await ecr.describeRepositories({ repositoryNames: [repositoryName] }).promise(); const existingRepositoryUri = describeResponse.repositories[0]?.repositoryUri; if (existingRepositoryUri) { return { repositoryUri: existingRepositoryUri }; } } catch (e) { if (e.code !== 'RepositoryNotFoundException') { throw e; } } // create the repo (tag it so it will be easier to garbage collect in the future) (0, logging_1.debug)(`${repositoryName}: creating ECR repository`); const assetTag = { Key: 'awscdk:asset', Value: 'true' }; const response = await ecr.createRepository({ repositoryName, tags: [assetTag] }).promise(); const repositoryUri = response.repository?.repositoryUri; if (!repositoryUri) { throw new Error(`CreateRepository did not return a repository URI for ${repositoryUri}`); } // configure image scanning on push (helps in identifying software vulnerabilities, no additional charge) (0, logging_1.debug)(`${repositoryName}: enable image scanning`); await ecr.putImageScanningConfiguration({ repositoryName, imageScanningConfiguration: { scanOnPush: true } }).promise(); return { repositoryUri }; } } exports.EnvironmentResources = EnvironmentResources; class NoBootstrapStackEnvironmentResources extends EnvironmentResources { constructor(environment, sdk) { super(environment, sdk, emptyCache()); } /** * Look up the toolkit for a given environment, using a given SDK */ async lookupToolkit() { throw new Error('Trying to perform an operation that requires a bootstrap stack; you should not see this error, this is a bug in the CDK CLI.'); } } exports.NoBootstrapStackEnvironmentResources = NoBootstrapStackEnvironmentResources; function emptyCache() { return { ssmParameters: new Map(), toolkitInfo: undefined, }; } /** * The bootstrap template version that introduced ssm:GetParameter */ const BOOTSTRAP_TEMPLATE_VERSION_INTRODUCING_GETPARAMETER = 5; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52aXJvbm1lbnQtcmVzb3VyY2VzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZW52aXJvbm1lbnQtcmVzb3VyY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLGlEQUFnRTtBQUNoRSx3Q0FBNEM7QUFFNUM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLDRCQUE0QjtJQUd2QyxZQUE2QixnQkFBeUI7UUFBekIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFTO1FBRnJDLFVBQUssR0FBRyxJQUFJLEdBQUcsRUFBNEIsQ0FBQztJQUc3RCxDQUFDO0lBRU0sR0FBRyxDQUFDLG1CQUFzQyxFQUFFLEdBQVM7UUFDMUQsTUFBTSxHQUFHLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLElBQUksbUJBQW1CLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0UsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNiLFFBQVEsR0FBRyxVQUFVLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7U0FDL0I7UUFDRCxPQUFPLElBQUksb0JBQW9CLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM3RixDQUFDO0NBQ0Y7QUFmRCxvRUFlQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBYSxvQkFBb0I7SUFDL0IsWUFDa0IsV0FBOEIsRUFDN0IsR0FBUyxFQUNULEtBQXVCLEVBQ3ZCLGdCQUF5QjtRQUgxQixnQkFBVyxHQUFYLFdBQVcsQ0FBbUI7UUFDN0IsUUFBRyxHQUFILEdBQUcsQ0FBTTtRQUNULFVBQUssR0FBTCxLQUFLLENBQWtCO1FBQ3ZCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBUztJQUN6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QVU7SUFDakIsT0FBTztRQUNMLGFBQWEsRUFBRSxJQUFJLEdBQUcsRUFBRTtRQUN4QixXQUFXLEVBQUUsU0FBUztLQUN2QixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxtREFBbUQsR0FBRyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgSVNESyB9IGZyb20gJy4vYXdzLWF1dGgnO1xuaW1wb3J0IHsgRWNyUmVwb3NpdG9yeUluZm8sIFRvb2xraXRJbmZvIH0gZnJvbSAnLi90b29sa2l0LWluZm8nO1xuaW1wb3J0IHsgZGVidWcsIHdhcm5pbmcgfSBmcm9tICcuLi9sb2dnaW5nJztcblxuLyoqXG4gKiBSZWdpc3RyeSBjbGFzcyBmb3IgYEVudmlyb25tZW50UmVzb3VyY2VzYC5cbiAqXG4gKiBUaGUgc3RhdGUgbWFuYWdlbWVudCBvZiB0aGlzIGNsYXNzIGlzIGEgYml0IG5vbi1zdGFuZGFyZC4gV2Ugd2FudCB0byBjYWNoZVxuICogZGF0YSByZWxhdGVkIHRvIHRvb2xraXQgc3RhY2tzIGFuZCBTU00gcGFyYW1ldGVycywgYnV0IHdlIGFyZSBub3QgaW4gY2hhcmdlXG4gKiBvZiBlbnN1cmluZyBjYWNoaW5nIG9mIFNES3MuIFNpbmNlIGBFbnZpcm9ubWVudFJlc291cmNlc2AgbmVlZHMgYW4gU0RLIHRvXG4gKiBmdW5jdGlvbiwgd2UgdHJlYXQgaXQgYXMgYW4gZXBoZW1lcmFsIGNsYXNzLCBhbmQgc3RvcmUgdGhlIGFjdHVhbCBjYWNoZWQgZGF0YVxuICogaW4gYEVudmlyb25tZW50UmVzb3VyY2VzUmVnaXN0cnlgLlxuICovXG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnRSZXNvdXJjZXNSZWdpc3RyeSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgRW52aXJvbm1lbnRDYWNoZT4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHRvb2xraXRTdGFja05hbWU/OiBzdHJpbmcpIHtcbiAgfVxuXG4gIHB1YmxpYyBmb3IocmVzb2x2ZWRFbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsIHNkazogSVNESykge1xuICAgIGNvbnN0IGtleSA9IGAke3Jlc29sdmVkRW52aXJvbm1lbnQuYWNjb3VudH06JHtyZXNvbHZlZEVudmlyb25tZW50LnJlZ2lvbn1gO1xuICAgIGxldCBlbnZDYWNoZSA9IHRoaXMuY2FjaGUuZ2V0KGtleSk7XG4gICAgaWYgKCFlbnZDYWNoZSkge1xuICAgICAgZW52Q2FjaGUgPSBlbXB0eUNhY2hlKCk7XG4gICAgICB0aGlzLmNhY2hlLnNldChrZXksIGVudkNhY2hlKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBFbnZpcm9ubWVudFJlc291cmNlcyhyZXNvbHZlZEVudmlyb25tZW50LCBzZGssIGVudkNhY2hlLCB0aGlzLnRvb2xraXRTdGFja05hbWUpO1xuICB9XG59XG5cbi8qKlxuICogSW50ZXJmYWNlIHdpdGggdGhlIGFjY291bnQgYW5kIHJlZ2lvbiB3ZSdyZSBkZXBsb3lpbmcgaW50b1xuICpcbiAqIE1hbmFnZXMgbG9va3VwcyBmb3IgYm9vdHN0cmFwcGVkIHJlc291cmNlcywgZmFsbGluZyBiYWNrIHRvIHRoZSBsZWdhY3kgXCJDREsgVG9vbGtpdFwiXG4gKiBvcmlnaW5hbCBib290c3RyYXAgc3RhY2sgaWYgbmVjZXNzYXJ5LlxuICpcbiAqIFRoZSBzdGF0ZSBtYW5hZ2VtZW50IG9mIHRoaXMgY2xhc3MgaXMgYSBiaXQgbm9uLXN0YW5kYXJkLiBXZSB3YW50IHRvIGNhY2hlXG4gKiBkYXRhIHJlbGF0ZWQgdG8gdG9vbGtpdCBzdGFja3MgYW5kIFNTTSBwYXJhbWV0ZXJzLCBidXQgd2UgYXJlIG5vdCBpbiBjaGFyZ2VcbiAqIG9mIGVuc3VyaW5nIGNhY2hpbmcgb2YgU0RLcy4gU2luY2UgYEVudmlyb25tZW50UmVzb3VyY2VzYCBuZWVkcyBhbiBTREsgdG9cbiAqIGZ1bmN0aW9uLCB3ZSB0cmVhdCBpdCBhcyBhbiBlcGhlbWVyYWwgY2xhc3MsIGFuZCBzdG9yZSB0aGUgYWN0dWFsIGNhY2hlZCBkYXRhXG4gKiBpbiBgRW52aXJvbm1lbnRSZXNvdXJjZXNSZWdpc3RyeWAuXG4gKi9cbmV4cG9ydCBjbGFzcyBFbnZpcm9ubWVudFJlc291cmNlcyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGs6IElTREssXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogRW52aXJvbm1lbnRDYWNoZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRvb2xraXRTdGFja05hbWU/OiBzdHJpbmcsXG4gICkge31cblxuICAvKipcbiAgICogTG9vayB1cCB0aGUgdG9vbGtpdCBmb3IgYSBnaXZlbiBlbnZpcm9ubWVudCwgdXNpbmcgYSBnaXZlbiBTREtcbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb29rdXBUb29sa2l0KCkge1xuICAgIGlmICghdGhpcy5jYWNoZS50b29sa2l0SW5mbykge1xuICAgICAgdGhpcy5jYWNoZS50b29sa2l0SW5mbyA9IGF3YWl0IFRvb2xraXRJbmZvLmxvb2t1cCh0aGlzLmVudmlyb25tZW50LCB0aGlzLnNkaywgdGhpcy50b29sa2l0U3RhY2tOYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUudG9vbGtpdEluZm87XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGUgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gbWF0Y2hlcyBvciBleGNlZWRzIHRoZSBleHBlY3RlZCB2ZXJzaW9uXG4gICAqXG4gICAqIFVzZSB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHRvIHJlYWQgdGhlIHZlcnNpb24gbnVtYmVyIGlmIGdpdmVuLCBvdGhlcndpc2UgdXNlIHRoZSB2ZXJzaW9uXG4gICAqIGRpc2NvdmVyZWQgb24gdGhlIGJvb3RzdHJhcCBzdGFjay5cbiAgICpcbiAgICogUGFzcyBpbiB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHNvIHdlIGNhbiBjYWNoZSB0aGUgbG9va3VwcyBhbiBkb24ndCBuZWVkIHRvIGRvIHRoZSBzYW1lXG4gICAqIGxvb2t1cCBhZ2FpbiBhbmQgYWdhaW4gZm9yIGV2ZXJ5IGFydGlmYWN0LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHZhbGlkYXRlVmVyc2lvbihleHBlY3RlZFZlcnNpb246IG51bWJlciB8IHVuZGVmaW5lZCwgc3NtUGFyYW1ldGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKGV4cGVjdGVkVmVyc2lvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBObyByZXF1aXJlbWVudFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBkZWZFeHBlY3RlZFZlcnNpb24gPSBleHBlY3RlZFZlcnNpb247XG5cbiAgICBpZiAoc3NtUGFyYW1ldGVyTmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBkb1ZhbGlkYXRlKGF3YWl0IHRoaXMudmVyc2lvbkZyb21Tc21QYXJhbWV0ZXIoc3NtUGFyYW1ldGVyTmFtZSkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgaWYgKGUuY29kZSAhPT0gJ0FjY2Vzc0RlbmllZEV4Y2VwdGlvbicpIHsgdGhyb3cgZTsgfVxuXG4gICAgICAgIC8vIFRoaXMgaXMgYSBmYWxsYmFjayEgVGhlIGJvb3RzdHJhcCB0ZW1wbGF0ZSB0aGF0IGdvZXMgYWxvbmcgd2l0aCB0aGlzIGNoYW5nZSBpbnRyb2R1Y2VzXG4gICAgICAgIC8vIGEgbmV3ICdzc206R2V0UGFyYW1ldGVyJyBwZXJtaXNzaW9uLCBidXQgd2hlbiBydW4gdXNpbmcgdGhlIHByZXZpb3VzIGJvb3RzdHJhcCB0ZW1wbGF0ZSB3ZVxuICAgICAgICAvLyB3b24ndCBoYXZlIHRoZSBwZXJtaXNzaW9ucyB5ZXQgdG8gcmVhZCB0aGUgdmVyc2lvbiwgc28gd2Ugd29uJ3QgYmUgYWJsZSB0byBzaG93IHRoZVxuICAgICAgICAvLyBtZXNzYWdlIHRlbGxpbmcgdGhlIHVzZXIgdGhleSBuZWVkIHRvIHVwZGF0ZSEgV2hlbiB3ZSBzZWUgYW4gQWNjZXNzRGVuaWVkRXhjZXB0aW9uLCBmYWxsXG4gICAgICAgIC8vIGJhY2sgdG8gdGhlIHZlcnNpb24gd2UgcmVhZCBmcm9tIFN0YWNrIE91dHB1dHM7IGJ1dCBPTkxZIGlmIHRoZSB2ZXJzaW9uIHdlIGRpc2NvdmVyZWQgdmlhXG4gICAgICAgIC8vIG91dHB1dHMgaXMgbGVnaXRpbWF0ZWx5IGFuIG9sZCB2ZXJzaW9uLiBJZiBpdCdzIG5ld2VyIHRoYW4gdGhhdCwgc29tZXRoaW5nIGVsc2UgbXVzdCBiZSBicm9rZW4sXG4gICAgICAgIC8vIHNvIGxldCBpdCBmYWlsIGFzIGl0IHdvdWxkIGlmIHdlIGRpZG4ndCBoYXZlIHRoaXMgZmFsbGJhY2suXG4gICAgICAgIGNvbnN0IGJvb3RzdHJhcFN0YWNrID0gYXdhaXQgdGhpcy5sb29rdXBUb29sa2l0KCk7XG4gICAgICAgIGlmIChib290c3RyYXBTdGFjay5mb3VuZCAmJiBib290c3RyYXBTdGFjay52ZXJzaW9uIDwgQk9PVFNUUkFQX1RFTVBMQVRFX1ZFUlNJT05fSU5UUk9EVUNJTkdfR0VUUEFSQU1FVEVSKSB7XG4gICAgICAgICAgd2FybmluZyhgQ291bGQgbm90IHJlYWQgU1NNIHBhcmFtZXRlciAke3NzbVBhcmFtZXRlck5hbWV9OiAke2UubWVzc2FnZX0sIGZhbGxpbmcgYmFjayB0byB2ZXJzaW9uIGZyb20gJHtib290c3RyYXBTdGFja31gKTtcbiAgICAgICAgICBkb1ZhbGlkYXRlKGJvb3RzdHJhcFN0YWNrLnZlcnNpb24pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhpcyBDREsgZGVwbG95bWVudCByZXF1aXJlcyBib290c3RyYXAgc3RhY2sgdmVyc2lvbiAnJHtleHBlY3RlZFZlcnNpb259JywgYnV0IGR1cmluZyB0aGUgY29uZmlybWF0aW9uIHZpYSBTU00gcGFyYW1ldGVyICR7c3NtUGFyYW1ldGVyTmFtZX0gdGhlIGZvbGxvd2luZyBlcnJvciBvY2N1cnJlZDogJHtlfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vIFNTTSBwYXJhbWV0ZXJcbiAgICBjb25zdCBib290c3RyYXBTdGFjayA9IGF3YWl0IHRoaXMubG9va3VwVG9vbGtpdCgpO1xuICAgIGRvVmFsaWRhdGUoYm9vdHN0cmFwU3RhY2sudmVyc2lvbik7XG5cbiAgICBmdW5jdGlvbiBkb1ZhbGlkYXRlKHZlcnNpb246IG51bWJlcikge1xuICAgICAgaWYgKGRlZkV4cGVjdGVkVmVyc2lvbiA+IHZlcnNpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGlzIENESyBkZXBsb3ltZW50IHJlcXVpcmVzIGJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uICcke2V4cGVjdGVkVmVyc2lvbn0nLCBmb3VuZCAnJHt2ZXJzaW9ufScuIFBsZWFzZSBydW4gJ2NkayBib290c3RyYXAnLmApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkIGEgdmVyc2lvbiBmcm9tIGFuIFNTTSBwYXJhbWV0ZXIsIGNhY2hlZFxuICAgKi9cbiAgcHVibGljIGFzeW5jIHZlcnNpb25Gcm9tU3NtUGFyYW1ldGVyKHBhcmFtZXRlck5hbWU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmNhY2hlLnNzbVBhcmFtZXRlcnMuZ2V0KHBhcmFtZXRlck5hbWUpO1xuICAgIGlmIChleGlzdGluZyAhPT0gdW5kZWZpbmVkKSB7IHJldHVybiBleGlzdGluZzsgfVxuXG4gICAgY29uc3Qgc3NtID0gdGhpcy5zZGsuc3NtKCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3NtLmdldFBhcmFtZXRlcih7IE5hbWU6IHBhcmFtZXRlck5hbWUgfSkucHJvbWlzZSgpO1xuXG4gICAgICBjb25zdCBhc051bWJlciA9IHBhcnNlSW50KGAke3Jlc3VsdC5QYXJhbWV0ZXI/LlZhbHVlfWAsIDEwKTtcbiAgICAgIGlmIChpc05hTihhc051bWJlcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTU00gcGFyYW1ldGVyICR7cGFyYW1ldGVyTmFtZX0gbm90IGEgbnVtYmVyOiAke3Jlc3VsdC5QYXJhbWV0ZXI/LlZhbHVlfWApO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmNhY2hlLnNzbVBhcmFtZXRlcnMuc2V0KHBhcmFtZXRlck5hbWUsIGFzTnVtYmVyKTtcbiAgICAgIHJldHVybiBhc051bWJlcjtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdQYXJhbWV0ZXJOb3RGb3VuZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTU00gcGFyYW1ldGVyICR7cGFyYW1ldGVyTmFtZX0gbm90IGZvdW5kLiBIYXMgdGhlIGVudmlyb25tZW50IGJlZW4gYm9vdHN0cmFwcGVkPyBQbGVhc2UgcnVuIFxcJ2NkayBib290c3RyYXBcXCcgKHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL2xhdGVzdC9ndWlkZS9ib290c3RyYXBwaW5nLmh0bWwpYCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBwcmVwYXJlRWNyUmVwb3NpdG9yeShyZXBvc2l0b3J5TmFtZTogc3RyaW5nKTogUHJvbWlzZTxFY3JSZXBvc2l0b3J5SW5mbz4ge1xuICAgIGlmICghdGhpcy5zZGspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVG9vbGtpdEluZm8gbmVlZHMgdG8gaGF2ZSBiZWVuIGluaXRpYWxpemVkIHdpdGggYW4gc2RrIHRvIGNhbGwgcHJlcGFyZUVjclJlcG9zaXRvcnknKTtcbiAgICB9XG4gICAgY29uc3QgZWNyID0gdGhpcy5zZGsuZWNyKCk7XG5cbiAgICAvLyBjaGVjayBpZiByZXBvIGFscmVhZHkgZXhpc3RzXG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogY2hlY2tpbmcgaWYgRUNSIHJlcG9zaXRvcnkgYWxyZWFkeSBleGlzdHNgKTtcbiAgICAgIGNvbnN0IGRlc2NyaWJlUmVzcG9uc2UgPSBhd2FpdCBlY3IuZGVzY3JpYmVSZXBvc2l0b3JpZXMoeyByZXBvc2l0b3J5TmFtZXM6IFtyZXBvc2l0b3J5TmFtZV0gfSkucHJvbWlzZSgpO1xuICAgICAgY29uc3QgZXhpc3RpbmdSZXBvc2l0b3J5VXJpID0gZGVzY3JpYmVSZXNwb25zZS5yZXBvc2l0b3JpZXMhWzBdPy5yZXBvc2l0b3J5VXJpO1xuICAgICAgaWYgKGV4aXN0aW5nUmVwb3NpdG9yeVVyaSkge1xuICAgICAgICByZXR1cm4geyByZXBvc2l0b3J5VXJpOiBleGlzdGluZ1JlcG9zaXRvcnlVcmkgfTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXBvc2l0b3J5Tm90Rm91bmRFeGNlcHRpb24nKSB7IHRocm93IGU7IH1cbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIHJlcG8gKHRhZyBpdCBzbyBpdCB3aWxsIGJlIGVhc2llciB0byBnYXJiYWdlIGNvbGxlY3QgaW4gdGhlIGZ1dHVyZSlcbiAgICBkZWJ1ZyhgJHtyZXBvc2l0b3J5TmFtZX06IGNyZWF0aW5nIEVDUiByZXBvc2l0b3J5YCk7XG4gICAgY29uc3QgYXNzZXRUYWcgPSB7IEtleTogJ2F3c2Nkazphc3NldCcsIFZhbHVlOiAndHJ1ZScgfTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGVjci5jcmVhdGVSZXBvc2l0b3J5KHsgcmVwb3NpdG9yeU5hbWUsIHRhZ3M6IFthc3NldFRhZ10gfSkucHJvbWlzZSgpO1xuICAgIGNvbnN0IHJlcG9zaXRvcnlVcmkgPSByZXNwb25zZS5yZXBvc2l0b3J5Py5yZXBvc2l0b3J5VXJpO1xuICAgIGlmICghcmVwb3NpdG9yeVVyaSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDcmVhdGVSZXBvc2l0b3J5IGRpZCBub3QgcmV0dXJuIGEgcmVwb3NpdG9yeSBVUkkgZm9yICR7cmVwb3NpdG9yeVVyaX1gKTtcbiAgICB9XG5cbiAgICAvLyBjb25maWd1cmUgaW1hZ2Ugc2Nhbm5pbmcgb24gcHVzaCAoaGVscHMgaW4gaWRlbnRpZnlpbmcgc29mdHdhcmUgdnVsbmVyYWJpbGl0aWVzLCBubyBhZGRpdGlvbmFsIGNoYXJnZSlcbiAgICBkZWJ1ZyhgJHtyZXBvc2l0b3J5TmFtZX06IGVuYWJsZSBpbWFnZSBzY2FubmluZ2ApO1xuICAgIGF3YWl0IGVjci5wdXRJbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbih7IHJlcG9zaXRvcnlOYW1lLCBpbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbjogeyBzY2FuT25QdXNoOiB0cnVlIH0gfSkucHJvbWlzZSgpO1xuXG4gICAgcmV0dXJuIHsgcmVwb3NpdG9yeVVyaSB9O1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOb0Jvb3RzdHJhcFN0YWNrRW52aXJvbm1lbnRSZXNvdXJjZXMgZXh0ZW5kcyBFbnZpcm9ubWVudFJlc291cmNlcyB7XG4gIGNvbnN0cnVjdG9yKGVudmlyb25tZW50OiBjeGFwaS5FbnZpcm9ubWVudCwgc2RrOiBJU0RLKSB7XG4gICAgc3VwZXIoZW52aXJvbm1lbnQsIHNkaywgZW1wdHlDYWNoZSgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb29rIHVwIHRoZSB0b29sa2l0IGZvciBhIGdpdmVuIGVudmlyb25tZW50LCB1c2luZyBhIGdpdmVuIFNES1xuICAgKi9cbiAgcHVibGljIGFzeW5jIGxvb2t1cFRvb2xraXQoKTogUHJvbWlzZTxUb29sa2l0SW5mbz4ge1xuICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHBlcmZvcm0gYW4gb3BlcmF0aW9uIHRoYXQgcmVxdWlyZXMgYSBib290c3RyYXAgc3RhY2s7IHlvdSBzaG91bGQgbm90IHNlZSB0aGlzIGVycm9yLCB0aGlzIGlzIGEgYnVnIGluIHRoZSBDREsgQ0xJLicpO1xuICB9XG59XG5cbi8qKlxuICogRGF0YSB0aGF0IGlzIGNhY2hlZCBvbiBhIHBlci1lbnZpcm9ubWVudCBsZXZlbFxuICpcbiAqIFRoaXMgY2FjaGUgbWF5IGJlIHNoYXJlZCBiZXR3ZWVuIGRpZmZlcmVudCBpbnN0YW5jZXMgb2YgdGhlIGBFbnZpcm9ubWVudFJlc291cmNlc2AgY2xhc3MuXG4gKi9cbmludGVyZmFjZSBFbnZpcm9ubWVudENhY2hlIHtcbiAgcmVhZG9ubHkgc3NtUGFyYW1ldGVyczogTWFwPHN0cmluZywgbnVtYmVyPjtcbiAgdG9vbGtpdEluZm8/OiBUb29sa2l0SW5mbztcbn1cblxuZnVuY3Rpb24gZW1wdHlDYWNoZSgpOiBFbnZpcm9ubWVudENhY2hlIHtcbiAgcmV0dXJuIHtcbiAgICBzc21QYXJhbWV0ZXJzOiBuZXcgTWFwKCksXG4gICAgdG9vbGtpdEluZm86IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBUaGUgYm9vdHN0cmFwIHRlbXBsYXRlIHZlcnNpb24gdGhhdCBpbnRyb2R1Y2VkIHNzbTpHZXRQYXJhbWV0ZXJcbiAqL1xuY29uc3QgQk9PVFNUUkFQX1RFTVBMQVRFX1ZFUlNJT05fSU5UUk9EVUNJTkdfR0VUUEFSQU1FVEVSID0gNTtcbiJdfQ==