aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
206 lines • 28.8 kB
JavaScript
;
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");
const notices_1 = require("../notices");
const error_1 = require("../toolkit/error");
const error_2 = require("../util/error");
/**
* 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), this.environment);
return;
}
catch (e) {
if (e.name !== '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}: ${(0, error_2.formatErrorMessage)(e)}, falling back to version from ${bootstrapStack}`);
doValidate(bootstrapStack.version, this.environment);
return;
}
throw new error_1.ToolkitError(`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, this.environment);
function doValidate(version, environment) {
const notices = notices_1.Notices.get();
if (notices) {
// if `Notices` hasn't been initialized there is probably a good
// reason for it. handle gracefully.
notices.addBootstrappedEnvironment({ bootstrapStackVersion: version, environment });
}
if (defExpectedVersion > version) {
throw new error_1.ToolkitError(`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 });
const asNumber = parseInt(`${result.Parameter?.Value}`, 10);
if (isNaN(asNumber)) {
throw new error_1.ToolkitError(`SSM parameter ${parameterName} not a number: ${result.Parameter?.Value}`);
}
this.cache.ssmParameters.set(parameterName, asNumber);
return asNumber;
}
catch (e) {
if (e.name === 'ParameterNotFound') {
throw new error_1.ToolkitError(`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_1.ToolkitError('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],
});
const existingRepositoryUri = describeResponse.repositories[0]?.repositoryUri;
if (existingRepositoryUri) {
return { repositoryUri: existingRepositoryUri };
}
}
catch (e) {
if (e.name !== '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],
});
const repositoryUri = response.repository?.repositoryUri;
if (!repositoryUri) {
throw new error_1.ToolkitError(`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 },
});
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_1.ToolkitError('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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52aXJvbm1lbnQtcmVzb3VyY2VzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZW52aXJvbm1lbnQtcmVzb3VyY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLGlEQUFxRTtBQUNyRSx3Q0FBNEM7QUFDNUMsd0NBQXFDO0FBQ3JDLDRDQUFnRDtBQUNoRCx5Q0FBbUQ7QUFFbkQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLDRCQUE0QjtJQUd2QyxZQUE2QixnQkFBeUI7UUFBekIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFTO1FBRnJDLFVBQUssR0FBRyxJQUFJLEdBQUcsRUFBNEIsQ0FBQztJQUVKLENBQUM7SUFFbkQsR0FBRyxDQUFDLG1CQUFnQyxFQUFFLEdBQVE7UUFDbkQsTUFBTSxHQUFHLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLElBQUksbUJBQW1CLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0UsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsUUFBUSxHQUFHLFVBQVUsRUFBRSxDQUFDO1lBQ3hCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsT0FBTyxJQUFJLG9CQUFvQixDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDN0YsQ0FBQztDQUNGO0FBZEQsb0VBY0M7QUFFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQWEsb0JBQW9CO0lBQy9CLFlBQ2tCLFdBQXdCLEVBQ3ZCLEdBQVEsRUFDUixLQUF1QixFQUN2QixnQkFBeUI7UUFIMUIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDdkIsUUFBRyxHQUFILEdBQUcsQ0FBSztRQUNSLFVBQUssR0FB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RyxDQUFDO1FBRUQseUdBQXlHO1FBQ3pHLElBQUEsZUFBSyxFQUFDLEdBQUcsY0FBYyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sR0FBRyxDQUFDLDZCQUE2QixDQUFDO1lBQ3RDLGNBQWM7WUFDZCwwQkFBMEIsRUFBRSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUU7U0FDakQsQ0FBQyxDQUFDO1FBRUgsT0FBTyxFQUFFLGFBQWEsRUFBRSxDQUFDO0lBQzNCLENBQUM7Q0FDRjtBQTlKRCxvREE4SkM7QUFFRCxNQUFhLG9DQUFxQyxTQUFRLG9CQUFvQjtJQUM1RSxZQUFZLFdBQXdCLEVBQUUsR0FBUTtRQUM1QyxLQUFLLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxhQUFhO1FBQ3hCLE1BQU0sSUFBSSxvQkFBWSxDQUNwQiw4SEFBOEgsQ0FDL0gsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQWJELG9GQWFDO0FBWUQsU0FBUyxVQUFVO0lBQ2pCLE9BQU87UUFDTCxhQUFhLEVBQUUsSUFBSSxHQUFHLEVBQUU7UUFDeEIsV0FBVyxFQUFFLFNBQVM7S0FDdkIsQ0FBQztBQUNKLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sbURBQW1ELEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBFbnZpcm9ubWVudCB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgdHlwZSB7IFNESyB9IGZyb20gJy4vYXdzLWF1dGgnO1xuaW1wb3J0IHsgdHlwZSBFY3JSZXBvc2l0b3J5SW5mbywgVG9vbGtpdEluZm8gfSBmcm9tICcuL3Rvb2xraXQtaW5mbyc7XG5pbXBvcnQgeyBkZWJ1Zywgd2FybmluZyB9IGZyb20gJy4uL2xvZ2dpbmcnO1xuaW1wb3J0IHsgTm90aWNlcyB9IGZyb20gJy4uL25vdGljZXMnO1xuaW1wb3J0IHsgVG9vbGtpdEVycm9yIH0gZnJvbSAnLi4vdG9vbGtpdC9lcnJvcic7XG5pbXBvcnQgeyBmb3JtYXRFcnJvck1lc3NhZ2UgfSBmcm9tICcuLi91dGlsL2Vycm9yJztcblxuLyoqXG4gKiBSZWdpc3RyeSBjbGFzcyBmb3IgYEVudmlyb25tZW50UmVzb3VyY2VzYC5cbiAqXG4gKiBUaGUgc3RhdGUgbWFuYWdlbWVudCBvZiB0aGlzIGNsYXNzIGlzIGEgYml0IG5vbi1zdGFuZGFyZC4gV2Ugd2FudCB0byBjYWNoZVxuICogZGF0YSByZWxhdGVkIHRvIHRvb2xraXQgc3RhY2tzIGFuZCBTU00gcGFyYW1ldGVycywgYnV0IHdlIGFyZSBub3QgaW4gY2hhcmdlXG4gKiBvZiBlbnN1cmluZyBjYWNoaW5nIG9mIFNES3MuIFNpbmNlIGBFbnZpcm9ubWVudFJlc291cmNlc2AgbmVlZHMgYW4gU0RLIHRvXG4gKiBmdW5jdGlvbiwgd2UgdHJlYXQgaXQgYXMgYW4gZXBoZW1lcmFsIGNsYXNzLCBhbmQgc3RvcmUgdGhlIGFjdHVhbCBjYWNoZWQgZGF0YVxuICogaW4gYEVudmlyb25tZW50UmVzb3VyY2VzUmVnaXN0cnlgLlxuICovXG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnRSZXNvdXJjZXNSZWdpc3RyeSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgRW52aXJvbm1lbnRDYWNoZT4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHRvb2xraXRTdGFja05hbWU/OiBzdHJpbmcpIHt9XG5cbiAgcHVibGljIGZvcihyZXNvbHZlZEVudmlyb25tZW50OiBFbnZpcm9ubWVudCwgc2RrOiBTREspIHtcbiAgICBjb25zdCBrZXkgPSBgJHtyZXNvbHZlZEVudmlyb25tZW50LmFjY291bnR9OiR7cmVzb2x2ZWRFbnZpcm9ubWVudC5yZWdpb259YDtcbiAgICBsZXQgZW52Q2FjaGUgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIGlmICghZW52Q2FjaGUpIHtcbiAgICAgIGVudkNhY2hlID0gZW1wdHlDYWNoZSgpO1xuICAgICAgdGhpcy5jYWNoZS5zZXQoa2V5LCBlbnZDYWNoZSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRW52aXJvbm1lbnRSZXNvdXJjZXMocmVzb2x2ZWRFbnZpcm9ubWVudCwgc2RrLCBlbnZDYWNoZSwgdGhpcy50b29sa2l0U3RhY2tOYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEludGVyZmFjZSB3aXRoIHRoZSBhY2NvdW50IGFuZCByZWdpb24gd2UncmUgZGVwbG95aW5nIGludG9cbiAqXG4gKiBNYW5hZ2VzIGxvb2t1cHMgZm9yIGJvb3RzdHJhcHBlZCByZXNvdXJjZXMsIGZhbGxpbmcgYmFjayB0byB0aGUgbGVnYWN5IFwiQ0RLIFRvb2xraXRcIlxuICogb3JpZ2luYWwgYm9vdHN0cmFwIHN0YWNrIGlmIG5lY2Vzc2FyeS5cbiAqXG4gKiBUaGUgc3RhdGUgbWFuYWdlbWVudCBvZiB0aGlzIGNsYXNzIGlzIGEgYml0IG5vbi1zdGFuZGFyZC4gV2Ugd2FudCB0byBjYWNoZVxuICogZGF0YSByZWxhdGVkIHRvIHRvb2xraXQgc3RhY2tzIGFuZCBTU00gcGFyYW1ldGVycywgYnV0IHdlIGFyZSBub3QgaW4gY2hhcmdlXG4gKiBvZiBlbnN1cmluZyBjYWNoaW5nIG9mIFNES3MuIFNpbmNlIGBFbnZpcm9ubWVudFJlc291cmNlc2AgbmVlZHMgYW4gU0RLIHRvXG4gKiBmdW5jdGlvbiwgd2UgdHJlYXQgaXQgYXMgYW4gZXBoZW1lcmFsIGNsYXNzLCBhbmQgc3RvcmUgdGhlIGFjdHVhbCBjYWNoZWQgZGF0YVxuICogaW4gYEVudmlyb25tZW50UmVzb3VyY2VzUmVnaXN0cnlgLlxuICovXG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnRSZXNvdXJjZXMge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2RrOiBTREssXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogRW52aXJvbm1lbnRDYWNoZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRvb2xraXRTdGFja05hbWU/OiBzdHJpbmcsXG4gICkge31cblxuICAvKipcbiAgICogTG9vayB1cCB0aGUgdG9vbGtpdCBmb3IgYSBnaXZlbiBlbnZpcm9ubWVudCwgdXNpbmcgYSBnaXZlbiBTREtcbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb29rdXBUb29sa2l0KCkge1xuICAgIGlmICghdGhpcy5jYWNoZS50b29sa2l0SW5mbykge1xuICAgICAgdGhpcy5jYWNoZS50b29sa2l0SW5mbyA9IGF3YWl0IFRvb2xraXRJbmZvLmxvb2t1cCh0aGlzLmVudmlyb25tZW50LCB0aGlzLnNkaywgdGhpcy50b29sa2l0U3RhY2tOYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUudG9vbGtpdEluZm87XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGUgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gbWF0Y2hlcyBvciBleGNlZWRzIHRoZSBleHBlY3RlZCB2ZXJzaW9uXG4gICAqXG4gICAqIFVzZSB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHRvIHJlYWQgdGhlIHZlcnNpb24gbnVtYmVyIGlmIGdpdmVuLCBvdGhlcndpc2UgdXNlIHRoZSB2ZXJzaW9uXG4gICAqIGRpc2NvdmVyZWQgb24gdGhlIGJvb3RzdHJhcCBzdGFjay5cbiAgICpcbiAgICogUGFzcyBpbiB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHNvIHdlIGNhbiBjYWNoZSB0aGUgbG9va3VwcyBhbiBkb24ndCBuZWVkIHRvIGRvIHRoZSBzYW1lXG4gICAqIGxvb2t1cCBhZ2FpbiBhbmQgYWdhaW4gZm9yIGV2ZXJ5IGFydGlmYWN0LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHZhbGlkYXRlVmVyc2lvbihleHBlY3RlZFZlcnNpb246IG51bWJlciB8IHVuZGVmaW5lZCwgc3NtUGFyYW1ldGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKGV4cGVjdGVkVmVyc2lvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBObyByZXF1aXJlbWVudFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBkZWZFeHBlY3RlZFZlcnNpb24gPSBleHBlY3RlZFZlcnNpb247XG5cbiAgICBpZiAoc3NtUGFyYW1ldGVyTmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBkb1ZhbGlkYXRlKGF3YWl0IHRoaXMudmVyc2lvbkZyb21Tc21QYXJhbWV0ZXIoc3NtUGFyYW1ldGVyTmFtZSksIHRoaXMuZW52aXJvbm1lbnQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgaWYgKGUubmFtZSAhPT0gJ0FjY2Vzc0RlbmllZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhpcyBpcyBhIGZhbGxiYWNrISBUaGUgYm9vdHN0cmFwIHRlbXBsYXRlIHRoYXQgZ29lcyBhbG9uZyB3aXRoIHRoaXMgY2hhbmdlIGludHJvZHVjZXNcbiAgICAgICAgLy8gYSBuZXcgJ3NzbTpHZXRQYXJhbWV0ZXInIHBlcm1pc3Npb24sIGJ1dCB3aGVuIHJ1biB1c2luZyB0aGUgcHJldmlvdXMgYm9vdHN0cmFwIHRlbXBsYXRlIHdlXG4gICAgICAgIC8vIHdvbid0IGhhdmUgdGhlIHBlcm1pc3Npb25zIHlldCB0byByZWFkIHRoZSB2ZXJzaW9uLCBzbyB3ZSB3b24ndCBiZSBhYmxlIHRvIHNob3cgdGhlXG4gICAgICAgIC8vIG1lc3NhZ2UgdGVsbGluZyB0aGUgdXNlciB0aGV5IG5lZWQgdG8gdXBkYXRlISBXaGVuIHdlIHNlZSBhbiBBY2Nlc3NEZW5pZWRFeGNlcHRpb24sIGZhbGxcbiAgICAgICAgLy8gYmFjayB0byB0aGUgdmVyc2lvbiB3ZSByZWFkIGZyb20gU3RhY2sgT3V0cHV0czsgYnV0IE9OTFkgaWYgdGhlIHZlcnNpb24gd2UgZGlzY292ZXJlZCB2aWFcbiAgICAgICAgLy8gb3V0cHV0cyBpcyBsZWdpdGltYXRlbHkgYW4gb2xkIHZlcnNpb24uIElmIGl0J3MgbmV3ZXIgdGhhbiB0aGF0LCBzb21ldGhpbmcgZWxzZSBtdXN0IGJlIGJyb2tlbixcbiAgICAgICAgLy8gc28gbGV0IGl0IGZhaWwgYXMgaXQgd291bGQgaWYgd2UgZGlkbid0IGhhdmUgdGhpcyBmYWxsYmFjay5cbiAgICAgICAgY29uc3QgYm9vdHN0cmFwU3RhY2sgPSBhd2FpdCB0aGlzLmxvb2t1cFRvb2xraXQoKTtcbiAgICAgICAgaWYgKGJvb3RzdHJhcFN0YWNrLmZvdW5kICYmIGJvb3RzdHJhcFN0YWNrLnZlcnNpb24gPCBCT09UU1RSQVBfVEVNUExBVEVfVkVSU0lPTl9JTlRST0RVQ0lOR19HRVRQQVJBTUVURVIpIHtcbiAgICAgICAgICB3YXJuaW5nKFxuICAgICAgICAgICAgYENvdWxkIG5vdCByZWFkIFNTTSBwYXJhbWV0ZXIgJHtzc21QYXJhbWV0ZXJOYW1lfTogJHtmb3JtYXRFcnJvck1lc3NhZ2UoZSl9LCBmYWxsaW5nIGJhY2sgdG8gdmVyc2lvbiBmcm9tICR7Ym9vdHN0cmFwU3RhY2t9YCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGRvVmFsaWRhdGUoYm9vdHN0cmFwU3RhY2sudmVyc2lvbiwgdGhpcy5lbnZpcm9ubWVudCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgICBgVGhpcyBDREsgZGVwbG95bWVudCByZXF1aXJlcyBib290c3RyYXAgc3RhY2sgdmVyc2lvbiAnJHtleHBlY3RlZFZlcnNpb259JywgYnV0IGR1cmluZyB0aGUgY29uZmlybWF0aW9uIHZpYSBTU00gcGFyYW1ldGVyICR7c3NtUGFyYW1ldGVyTmFtZX0gdGhlIGZvbGxvd2luZyBlcnJvciBvY2N1cnJlZDogJHtlfWAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTm8gU1NNIHBhcmFtZXRlclxuICAgIGNvbnN0IGJvb3RzdHJhcFN0YWNrID0gYXdhaXQgdGhpcy5sb29rdXBUb29sa2l0KCk7XG4gICAgZG9WYWxpZGF0ZShib290c3RyYXBTdGFjay52ZXJzaW9uLCB0aGlzLmVudmlyb25tZW50KTtcblxuICAgIGZ1bmN0aW9uIGRvVmFsaWRhdGUodmVyc2lvbjogbnVtYmVyLCBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQpIHtcbiAgICAgIGNvbnN0IG5vdGljZXMgPSBOb3RpY2VzLmdldCgpO1xuICAgICAgaWYgKG5vdGljZXMpIHtcbiAgICAgICAgLy8gaWYgYE5vdGljZXNgIGhhc24ndCBiZWVuIGluaXRpYWxpemVkIHRoZXJlIGlzIHByb2JhYmx5IGEgZ29vZFxuICAgICAgICAvLyByZWFzb24gZm9yIGl0LiBoYW5kbGUgZ3JhY2VmdWxseS5cbiAgICAgICAgbm90aWNlcy5hZGRCb290c3RyYXBwZWRFbnZpcm9ubWVudCh7IGJvb3RzdHJhcFN0YWNrVmVyc2lvbjogdmVyc2lvbiwgZW52aXJvbm1lbnQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoZGVmRXhwZWN0ZWRWZXJzaW9uID4gdmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgICAgIGBUaGlzIENESyBkZXBsb3ltZW50IHJlcXVpcmVzIGJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uICcke2V4cGVjdGVkVmVyc2lvbn0nLCBmb3VuZCAnJHt2ZXJzaW9ufScuIFBsZWFzZSBydW4gJ2NkayBib290c3RyYXAnLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlYWQgYSB2ZXJzaW9uIGZyb20gYW4gU1NNIHBhcmFtZXRlciwgY2FjaGVkXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmVyc2lvbkZyb21Tc21QYXJhbWV0ZXIocGFyYW1ldGVyTmFtZTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMuY2FjaGUuc3NtUGFyYW1ldGVycy5nZXQocGFyYW1ldGVyTmFtZSk7XG4gICAgaWYgKGV4aXN0aW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBleGlzdGluZztcbiAgICB9XG5cbiAgICBjb25zdCBzc20gPSB0aGlzLnNkay5zc20oKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzc20uZ2V0UGFyYW1ldGVyKHsgTmFtZTogcGFyYW1ldGVyTmFtZSB9KTtcblxuICAgICAgY29uc3QgYXNOdW1iZXIgPSBwYXJzZUludChgJHtyZXN1bHQuUGFyYW1ldGVyPy5WYWx1ZX1gLCAxMCk7XG4gICAgICBpZiAoaXNOYU4oYXNOdW1iZXIpKSB7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoYFNTTSBwYXJhbWV0ZXIgJHtwYXJhbWV0ZXJOYW1lfSBub3QgYSBudW1iZXI6ICR7cmVzdWx0LlBhcmFtZXRlcj8uVmFsdWV9YCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2FjaGUuc3NtUGFyYW1ldGVycy5zZXQocGFyYW1ldGVyTmFtZSwgYXNOdW1iZXIpO1xuICAgICAgcmV0dXJuIGFzTnVtYmVyO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGUubmFtZSA9PT0gJ1BhcmFtZXRlck5vdEZvdW5kJykge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgICAgIGBTU00gcGFyYW1ldGVyICR7cGFyYW1ldGVyTmFtZX0gbm90IGZvdW5kLiBIYXMgdGhlIGVudmlyb25tZW50IGJlZW4gYm9vdHN0cmFwcGVkPyBQbGVhc2UgcnVuIFxcJ2NkayBib290c3RyYXBcXCcgKHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL2xhdGVzdC9ndWlkZS9ib290c3RyYXBwaW5nLmh0bWwpYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHByZXBhcmVFY3JSZXBvc2l0b3J5KHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpOiBQcm9taXNlPEVjclJlcG9zaXRvcnlJbmZvPiB7XG4gICAgaWYgKCF0aGlzLnNkaykge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignVG9vbGtpdEluZm8gbmVlZHMgdG8gaGF2ZSBiZWVuIGluaXRpYWxpemVkIHdpdGggYW4gc2RrIHRvIGNhbGwgcHJlcGFyZUVjclJlcG9zaXRvcnknKTtcbiAgICB9XG4gICAgY29uc3QgZWNyID0gdGhpcy5zZGsuZWNyKCk7XG5cbiAgICAvLyBjaGVjayBpZiByZXBvIGFscmVhZHkgZXhpc3RzXG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogY2hlY2tpbmcgaWYgRUNSIHJlcG9zaXRvcnkgYWxyZWFkeSBleGlzdHNgKTtcbiAgICAgIGNvbnN0IGRlc2NyaWJlUmVzcG9uc2UgPSBhd2FpdCBlY3IuZGVzY3JpYmVSZXBvc2l0b3JpZXMoe1xuICAgICAgICByZXBvc2l0b3J5TmFtZXM6IFtyZXBvc2l0b3J5TmFtZV0sXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nUmVwb3NpdG9yeVVyaSA9IGRlc2NyaWJlUmVzcG9uc2UucmVwb3NpdG9yaWVzIVswXT8ucmVwb3NpdG9yeVVyaTtcbiAgICAgIGlmIChleGlzdGluZ1JlcG9zaXRvcnlVcmkpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVwb3NpdG9yeVVyaTogZXhpc3RpbmdSZXBvc2l0b3J5VXJpIH07XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVwb3NpdG9yeU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0aGUgcmVwbyAodGFnIGl0IHNvIGl0IHdpbGwgYmUgZWFzaWVyIHRvIGdhcmJhZ2UgY29sbGVjdCBpbiB0aGUgZnV0dXJlKVxuICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogY3JlYXRpbmcgRUNSIHJlcG9zaXRvcnlgKTtcbiAgICBjb25zdCBhc3NldFRhZyA9IHsgS2V5OiAnYXdzY2RrOmFzc2V0JywgVmFsdWU6ICd0cnVlJyB9O1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZWNyLmNyZWF0ZVJlcG9zaXRvcnkoe1xuICAgICAgcmVwb3NpdG9yeU5hbWUsXG4gICAgICB0YWdzOiBbYXNzZXRUYWddLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlcG9zaXRvcnlVcmkgPSByZXNwb25zZS5yZXBvc2l0b3J5Py5yZXBvc2l0b3J5VXJpO1xuICAgIGlmICghcmVwb3NpdG9yeVVyaSkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgQ3JlYXRlUmVwb3NpdG9yeSBkaWQgbm90IHJldHVybiBhIHJlcG9zaXRvcnkgVVJJIGZvciAke3JlcG9zaXRvcnlVcml9YCk7XG4gICAgfVxuXG4gICAgLy8gY29uZmlndXJlIGltYWdlIHNjYW5uaW5nIG9uIHB1c2ggKGhlbHBzIGluIGlkZW50aWZ5aW5nIHNvZnR3YXJlIHZ1bG5lcmFiaWxpdGllcywgbm8gYWRkaXRpb25hbCBjaGFyZ2UpXG4gICAgZGVidWcoYCR7cmVwb3NpdG9yeU5hbWV9OiBlbmFibGUgaW1hZ2Ugc2Nhbm5pbmdgKTtcbiAgICBhd2FpdCBlY3IucHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb24oe1xuICAgICAgcmVwb3NpdG9yeU5hbWUsXG4gICAgICBpbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbjogeyBzY2FuT25QdXNoOiB0cnVlIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyByZXBvc2l0b3J5VXJpIH07XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5vQm9vdHN0cmFwU3RhY2tFbnZpcm9ubWVudFJlc291cmNlcyBleHRlbmRzIEVudmlyb25tZW50UmVzb3VyY2VzIHtcbiAgY29uc3RydWN0b3IoZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LCBzZGs6IFNESykge1xuICAgIHN1cGVyKGVudmlyb25tZW50LCBzZGssIGVtcHR5Q2FjaGUoKSk7XG4gIH1cblxuICAvKipcbiAgICogTG9vayB1cCB0aGUgdG9vbGtpdCBmb3IgYSBnaXZlbiBlbnZpcm9ubWVudCwgdXNpbmcgYSBnaXZlbiBTREtcbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb29rdXBUb29sa2l0KCk6IFByb21pc2U8VG9vbGtpdEluZm8+IHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgJ1RyeWluZyB0byBwZXJmb3JtIGFuIG9wZXJhdGlvbiB0aGF0IHJlcXVpcmVzIGEgYm9vdHN0cmFwIHN0YWNrOyB5b3Ugc2hvdWxkIG5vdCBzZWUgdGhpcyBlcnJvciwgdGhpcyBpcyBhIGJ1ZyBpbiB0aGUgQ0RLIENMSS4nLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBEYXRhIHRoYXQgaXMgY2FjaGVkIG9uIGEgcGVyLWVudmlyb25tZW50IGxldmVsXG4gKlxuICogVGhpcyBjYWNoZSBtYXkgYmUgc2hhcmVkIGJldHdlZW4gZGlmZmVyZW50IGluc3RhbmNlcyBvZiB0aGUgYEVudmlyb25tZW50UmVzb3VyY2VzYCBjbGFzcy5cbiAqL1xuaW50ZXJmYWNlIEVudmlyb25tZW50Q2FjaGUge1xuICByZWFkb25seSBzc21QYXJhbWV0ZXJzOiBNYXA8c3RyaW5nLCBudW1iZXI+O1xuICB0b29sa2l0SW5mbz86IFRvb2xraXRJbmZvO1xufVxuXG5mdW5jdGlvbiBlbXB0eUNhY2hlKCk6IEVudmlyb25tZW50Q2FjaGUge1xuICByZXR1cm4ge1xuICAgIHNzbVBhcmFtZXRlcnM6IG5ldyBNYXAoKSxcbiAgICB0b29sa2l0SW5mbzogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBib290c3RyYXAgdGVtcGxhdGUgdmVyc2lvbiB0aGF0IGludHJvZHVjZWQgc3NtOkdldFBhcmFtZXRlclxuICovXG5jb25zdCBCT09UU1RSQVBfVEVNUExBVEVfVkVSU0lPTl9JTlRST0RVQ0lOR19HRVRQQVJBTUVURVIgPSA1O1xuIl19