UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

140 lines 21.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BootstrapStack = void 0; exports.bootstrapVersionFromTemplate = bootstrapVersionFromTemplate; exports.bootstrapVariantFromTemplate = bootstrapVariantFromTemplate; const os = require("os"); const path = require("path"); const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema"); const cx_api_1 = require("@aws-cdk/cx-api"); const fs = require("fs-extra"); const bootstrap_props_1 = require("./bootstrap-props"); const logging = require("../../logging"); const deployments_1 = require("../deployments"); const deploy_stack_1 = require("../deployments/deploy-stack"); const environment_resources_1 = require("../environment-resources"); const mode_1 = require("../plugin/mode"); const toolkit_info_1 = require("../toolkit-info"); /** * A class to hold state around stack bootstrapping * * This class exists so we can break bootstrapping into 2 phases: * * ```ts * const current = BootstrapStack.lookup(...); * // ... * current.update(newTemplate, ...); * ``` * * And do something in between the two phases (such as look at the * current bootstrap stack and doing something intelligent). */ class BootstrapStack { static async lookup(sdkProvider, environment, toolkitStackName) { toolkitStackName = toolkitStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME; const resolvedEnvironment = await sdkProvider.resolveEnvironment(environment); const sdk = (await sdkProvider.forEnvironment(resolvedEnvironment, mode_1.Mode.ForWriting)).sdk; const currentToolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(resolvedEnvironment, sdk, toolkitStackName); return new BootstrapStack(sdkProvider, sdk, resolvedEnvironment, toolkitStackName, currentToolkitInfo); } constructor(sdkProvider, sdk, resolvedEnvironment, toolkitStackName, currentToolkitInfo) { this.sdkProvider = sdkProvider; this.sdk = sdk; this.resolvedEnvironment = resolvedEnvironment; this.toolkitStackName = toolkitStackName; this.currentToolkitInfo = currentToolkitInfo; } get parameters() { return this.currentToolkitInfo.found ? this.currentToolkitInfo.bootstrapStack.parameters : {}; } get terminationProtection() { return this.currentToolkitInfo.found ? this.currentToolkitInfo.bootstrapStack.terminationProtection : undefined; } async partition() { return (await this.sdk.currentAccount()).partition; } /** * Perform the actual deployment of a bootstrap stack, given a template and some parameters */ async update(template, parameters, options) { if (this.currentToolkitInfo.found && !options.force) { // Safety checks const abortResponse = { type: 'did-deploy-stack', noOp: true, outputs: {}, stackArn: this.currentToolkitInfo.bootstrapStack.stackId, }; // Validate that the bootstrap stack we're trying to replace is from the same variant as the one we're trying to deploy const currentVariant = this.currentToolkitInfo.variant; const newVariant = bootstrapVariantFromTemplate(template); if (currentVariant !== newVariant) { logging.warning(`Bootstrap stack already exists, containing '${currentVariant}'. Not overwriting it with a template containing '${newVariant}' (use --force if you intend to overwrite)`); return abortResponse; } // Validate that we're not downgrading the bootstrap stack const newVersion = bootstrapVersionFromTemplate(template); const currentVersion = this.currentToolkitInfo.version; if (newVersion < currentVersion) { logging.warning(`Bootstrap stack already at version ${currentVersion}. Not downgrading it to version ${newVersion} (use --force if you intend to downgrade)`); if (newVersion === 0) { // A downgrade with 0 as target version means we probably have a new-style bootstrap in the account, // and an old-style bootstrap as current target, which means the user probably forgot to put this flag in. logging.warning("(Did you set the '@aws-cdk/core:newStyleStackSynthesis' feature flag in cdk.json?)"); } return abortResponse; } } const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap')); const builder = new cx_api_1.CloudAssemblyBuilder(outdir); const templateFile = `${this.toolkitStackName}.template.json`; await fs.writeJson(path.join(builder.outdir, templateFile), template, { spaces: 2, }); builder.addArtifact(this.toolkitStackName, { type: cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK, environment: cx_api_1.EnvironmentUtils.format(this.resolvedEnvironment.account, this.resolvedEnvironment.region), properties: { templateFile, terminationProtection: options.terminationProtection ?? false, }, }); const assembly = builder.buildAssembly(); const ret = await (0, deploy_stack_1.deployStack)({ stack: assembly.getStackByName(this.toolkitStackName), resolvedEnvironment: this.resolvedEnvironment, sdk: this.sdk, sdkProvider: this.sdkProvider, force: options.force, roleArn: options.roleArn, tags: options.tags, deploymentMethod: { method: 'change-set', execute: options.execute }, parameters, usePreviousParameters: options.usePreviousParameters ?? true, // Obviously we can't need a bootstrap stack to deploy a bootstrap stack envResources: new environment_resources_1.NoBootstrapStackEnvironmentResources(this.resolvedEnvironment, this.sdk), }); (0, deployments_1.assertIsSuccessfulDeployStackResult)(ret); return ret; } } exports.BootstrapStack = BootstrapStack; function bootstrapVersionFromTemplate(template) { const versionSources = [ template.Outputs?.[bootstrap_props_1.BOOTSTRAP_VERSION_OUTPUT]?.Value, template.Resources?.[bootstrap_props_1.BOOTSTRAP_VERSION_RESOURCE]?.Properties?.Value, ]; for (const vs of versionSources) { if (typeof vs === 'number') { return vs; } if (typeof vs === 'string' && !isNaN(parseInt(vs, 10))) { return parseInt(vs, 10); } } return 0; } function bootstrapVariantFromTemplate(template) { return template.Parameters?.[bootstrap_props_1.BOOTSTRAP_VARIANT_PARAMETER]?.Default ?? bootstrap_props_1.DEFAULT_BOOTSTRAP_VARIANT; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LWJvb3RzdHJhcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRlcGxveS1ib290c3RyYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBb0pBLG9FQWVDO0FBRUQsb0VBRUM7QUF2S0QseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwwRUFBOEQ7QUFDOUQsNENBQXNGO0FBQ3RGLCtCQUErQjtBQUMvQix1REFNMkI7QUFDM0IseUNBQXlDO0FBRXpDLGdEQUFrRztBQUNsRyw4REFBMEQ7QUFDMUQsb0VBQWdGO0FBQ2hGLHlDQUFzQztBQUN0QyxrREFBMEU7QUFFMUU7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQWEsY0FBYztJQUNsQixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUF3QixFQUFFLFdBQXdCLEVBQUUsZ0JBQXlCO1FBQ3RHLGdCQUFnQixHQUFHLGdCQUFnQixJQUFJLHlDQUEwQixDQUFDO1FBRWxFLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxXQUFXLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDOUUsTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLFdBQVcsQ0FBQyxjQUFjLENBQUMsbUJBQW1CLEVBQUUsV0FBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBRXpGLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSwwQkFBVyxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUVoRyxPQUFPLElBQUksY0FBYyxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN6RyxDQUFDO0lBRUQsWUFDbUIsV0FBd0IsRUFDeEIsR0FBUSxFQUNSLG1CQUFnQyxFQUNoQyxnQkFBd0IsRUFDeEIsa0JBQStCO1FBSi9CLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLFFBQUcs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Q0FDRjtBQWhIRCx3Q0FnSEM7QUFFRCxTQUFnQiw0QkFBNEIsQ0FBQyxRQUFhO0lBQ3hELE1BQU0sY0FBYyxHQUFHO1FBQ3JCLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQywwQ0FBd0IsQ0FBQyxFQUFFLEtBQUs7UUFDbkQsUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLDRDQUEwQixDQUFDLEVBQUUsVUFBVSxFQUFFLEtBQUs7S0FDcEUsQ0FBQztJQUVGLEtBQUssTUFBTSxFQUFFLElBQUksY0FBYyxFQUFFLENBQUM7UUFDaEMsSUFBSSxPQUFPLEVBQUUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMzQixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7UUFDRCxJQUFJLE9BQU8sRUFBRSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN2RCxPQUFPLFFBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxTQUFnQiw0QkFBNEIsQ0FBQyxRQUFhO0lBQ3hELE9BQU8sUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDLDZDQUEyQixDQUFDLEVBQUUsT0FBTyxJQUFJLDJDQUF5QixDQUFDO0FBQ2xHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQXJ0aWZhY3RUeXBlIH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCB7IENsb3VkQXNzZW1ibHlCdWlsZGVyLCBFbnZpcm9ubWVudCwgRW52aXJvbm1lbnRVdGlscyB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQge1xuICBCT09UU1RSQVBfVkFSSUFOVF9QQVJBTUVURVIsXG4gIEJPT1RTVFJBUF9WRVJTSU9OX09VVFBVVCxcbiAgQk9PVFNUUkFQX1ZFUlNJT05fUkVTT1VSQ0UsXG4gIEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyxcbiAgREVGQVVMVF9CT09UU1RSQVBfVkFSSUFOVCxcbn0gZnJvbSAnLi9ib290c3RyYXAtcHJvcHMnO1xuaW1wb3J0ICogYXMgbG9nZ2luZyBmcm9tICcuLi8uLi9sb2dnaW5nJztcbmltcG9ydCB0eXBlIHsgU0RLLCBTZGtQcm92aWRlciB9IGZyb20gJy4uL2F3cy1hdXRoJztcbmltcG9ydCB7IGFzc2VydElzU3VjY2Vzc2Z1bERlcGxveVN0YWNrUmVzdWx0LCBTdWNjZXNzZnVsRGVwbG95U3RhY2tSZXN1bHQgfSBmcm9tICcuLi9kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBkZXBsb3lTdGFjayB9IGZyb20gJy4uL2RlcGxveW1lbnRzL2RlcGxveS1zdGFjayc7XG5pbXBvcnQgeyBOb0Jvb3RzdHJhcFN0YWNrRW52aXJvbm1lbnRSZXNvdXJjZXMgfSBmcm9tICcuLi9lbnZpcm9ubWVudC1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgTW9kZSB9IGZyb20gJy4uL3BsdWdpbi9tb2RlJztcbmltcG9ydCB7IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FLCBUb29sa2l0SW5mbyB9IGZyb20gJy4uL3Rvb2xraXQtaW5mbyc7XG5cbi8qKlxuICogQSBjbGFzcyB0byBob2xkIHN0YXRlIGFyb3VuZCBzdGFjayBib290c3RyYXBwaW5nXG4gKlxuICogVGhpcyBjbGFzcyBleGlzdHMgc28gd2UgY2FuIGJyZWFrIGJvb3RzdHJhcHBpbmcgaW50byAyIHBoYXNlczpcbiAqXG4gKiBgYGB0c1xuICogY29uc3QgY3VycmVudCA9IEJvb3RzdHJhcFN0YWNrLmxvb2t1cCguLi4pO1xuICogLy8gLi4uXG4gKiBjdXJyZW50LnVwZGF0ZShuZXdUZW1wbGF0ZSwgLi4uKTtcbiAqIGBgYFxuICpcbiAqIEFuZCBkbyBzb21ldGhpbmcgaW4gYmV0d2VlbiB0aGUgdHdvIHBoYXNlcyAoc3VjaCBhcyBsb29rIGF0IHRoZVxuICogY3VycmVudCBib290c3RyYXAgc3RhY2sgYW5kIGRvaW5nIHNvbWV0aGluZyBpbnRlbGxpZ2VudCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBCb290c3RyYXBTdGFjayB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbG9va3VwKHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlciwgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LCB0b29sa2l0U3RhY2tOYW1lPzogc3RyaW5nKSB7XG4gICAgdG9vbGtpdFN0YWNrTmFtZSA9IHRvb2xraXRTdGFja05hbWUgPz8gREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUU7XG5cbiAgICBjb25zdCByZXNvbHZlZEVudmlyb25tZW50ID0gYXdhaXQgc2RrUHJvdmlkZXIucmVzb2x2ZUVudmlyb25tZW50KGVudmlyb25tZW50KTtcbiAgICBjb25zdCBzZGsgPSAoYXdhaXQgc2RrUHJvdmlkZXIuZm9yRW52aXJvbm1lbnQocmVzb2x2ZWRFbnZpcm9ubWVudCwgTW9kZS5Gb3JXcml0aW5nKSkuc2RrO1xuXG4gICAgY29uc3QgY3VycmVudFRvb2xraXRJbmZvID0gYXdhaXQgVG9vbGtpdEluZm8ubG9va3VwKHJlc29sdmVkRW52aXJvbm1lbnQsIHNkaywgdG9vbGtpdFN0YWNrTmFtZSk7XG5cbiAgICByZXR1cm4gbmV3IEJvb3RzdHJhcFN0YWNrKHNka1Byb3ZpZGVyLCBzZGssIHJlc29sdmVkRW52aXJvbm1lbnQsIHRvb2xraXRTdGFja05hbWUsIGN1cnJlbnRUb29sa2l0SW5mbyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGtQcm92aWRlcjogU2RrUHJvdmlkZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGs6IFNESyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmVkRW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY3VycmVudFRvb2xraXRJbmZvOiBUb29sa2l0SW5mbyxcbiAgKSB7fVxuXG4gIHB1YmxpYyBnZXQgcGFyYW1ldGVycygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50VG9vbGtpdEluZm8uZm91bmQgPyB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby5ib290c3RyYXBTdGFjay5wYXJhbWV0ZXJzIDoge307XG4gIH1cblxuICBwdWJsaWMgZ2V0IHRlcm1pbmF0aW9uUHJvdGVjdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50VG9vbGtpdEluZm8uZm91bmQgPyB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby5ib290c3RyYXBTdGFjay50ZXJtaW5hdGlvblByb3RlY3Rpb24gOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcGFydGl0aW9uKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnNkay5jdXJyZW50QWNjb3VudCgpKS5wYXJ0aXRpb247XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSB0aGUgYWN0dWFsIGRlcGxveW1lbnQgb2YgYSBib290c3RyYXAgc3RhY2ssIGdpdmVuIGEgdGVtcGxhdGUgYW5kIHNvbWUgcGFyYW1ldGVyc1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHVwZGF0ZShcbiAgICB0ZW1wbGF0ZTogYW55LFxuICAgIHBhcmFtZXRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4sXG4gICAgb3B0aW9uczogT21pdDxCb290c3RyYXBFbnZpcm9ubWVudE9wdGlvbnMsICdwYXJhbWV0ZXJzJz4sXG4gICk6IFByb21pc2U8U3VjY2Vzc2Z1bERlcGxveVN0YWNrUmVzdWx0PiB7XG4gICAgaWYgKHRoaXMuY3VycmVudFRvb2xraXRJbmZvLmZvdW5kICYmICFvcHRpb25zLmZvcmNlKSB7XG4gICAgICAvLyBTYWZldHkgY2hlY2tzXG4gICAgICBjb25zdCBhYm9ydFJlc3BvbnNlID0ge1xuICAgICAgICB0eXBlOiAnZGlkLWRlcGxveS1zdGFjaycsXG4gICAgICAgIG5vT3A6IHRydWUsXG4gICAgICAgIG91dHB1dHM6IHt9LFxuICAgICAgICBzdGFja0FybjogdGhpcy5jdXJyZW50VG9vbGtpdEluZm8uYm9vdHN0cmFwU3RhY2suc3RhY2tJZCxcbiAgICAgIH0gc2F0aXNmaWVzIFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdDtcblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCB0aGUgYm9vdHN0cmFwIHN0YWNrIHdlJ3JlIHRyeWluZyB0byByZXBsYWNlIGlzIGZyb20gdGhlIHNhbWUgdmFyaWFudCBhcyB0aGUgb25lIHdlJ3JlIHRyeWluZyB0byBkZXBsb3lcbiAgICAgIGNvbnN0IGN1cnJlbnRWYXJpYW50ID0gdGhpcy5jdXJyZW50VG9vbGtpdEluZm8udmFyaWFudDtcbiAgICAgIGNvbnN0IG5ld1ZhcmlhbnQgPSBib290c3RyYXBWYXJpYW50RnJvbVRlbXBsYXRlKHRlbXBsYXRlKTtcbiAgICAgIGlmIChjdXJyZW50VmFyaWFudCAhPT0gbmV3VmFyaWFudCkge1xuICAgICAgICBsb2dnaW5nLndhcm5pbmcoXG4gICAgICAgICAgYEJvb3RzdHJhcCBzdGFjayBhbHJlYWR5IGV4aXN0cywgY29udGFpbmluZyAnJHtjdXJyZW50VmFyaWFudH0nLiBOb3Qgb3ZlcndyaXRpbmcgaXQgd2l0aCBhIHRlbXBsYXRlIGNvbnRhaW5pbmcgJyR7bmV3VmFyaWFudH0nICh1c2UgLS1mb3JjZSBpZiB5b3UgaW50ZW5kIHRvIG92ZXJ3cml0ZSlgLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gYWJvcnRSZXNwb25zZTtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCB3ZSdyZSBub3QgZG93bmdyYWRpbmcgdGhlIGJvb3RzdHJhcCBzdGFja1xuICAgICAgY29uc3QgbmV3VmVyc2lvbiA9IGJvb3RzdHJhcFZlcnNpb25Gcm9tVGVtcGxhdGUodGVtcGxhdGUpO1xuICAgICAgY29uc3QgY3VycmVudFZlcnNpb24gPSB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby52ZXJzaW9uO1xuICAgICAgaWYgKG5ld1ZlcnNpb24gPCBjdXJyZW50VmVyc2lvbikge1xuICAgICAgICBsb2dnaW5nLndhcm5pbmcoXG4gICAgICAgICAgYEJvb3RzdHJhcCBzdGFjayBhbHJlYWR5IGF0IHZlcnNpb24gJHtjdXJyZW50VmVyc2lvbn0uIE5vdCBkb3duZ3JhZGluZyBpdCB0byB2ZXJzaW9uICR7bmV3VmVyc2lvbn0gKHVzZSAtLWZvcmNlIGlmIHlvdSBpbnRlbmQgdG8gZG93bmdyYWRlKWAsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChuZXdWZXJzaW9uID09PSAwKSB7XG4gICAgICAgICAgLy8gQSBkb3duZ3JhZGUgd2l0aCAwIGFzIHRhcmdldCB2ZXJzaW9uIG1lYW5zIHdlIHByb2JhYmx5IGhhdmUgYSBuZXctc3R5bGUgYm9vdHN0cmFwIGluIHRoZSBhY2NvdW50LFxuICAgICAgICAgIC8vIGFuZCBhbiBvbGQtc3R5bGUgYm9vdHN0cmFwIGFzIGN1cnJlbnQgdGFyZ2V0LCB3aGljaCBtZWFucyB0aGUgdXNlciBwcm9iYWJseSBmb3Jnb3QgdG8gcHV0IHRoaXMgZmxhZyBpbi5cbiAgICAgICAgICBsb2dnaW5nLndhcm5pbmcoXCIoRGlkIHlvdSBzZXQgdGhlICdAYXdzLWNkay9jb3JlOm5ld1N0eWxlU3RhY2tTeW50aGVzaXMnIGZlYXR1cmUgZmxhZyBpbiBjZGsuanNvbj8pXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhYm9ydFJlc3BvbnNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG91dGRpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCAnY2RrLWJvb3RzdHJhcCcpKTtcbiAgICBjb25zdCBidWlsZGVyID0gbmV3IENsb3VkQXNzZW1ibHlCdWlsZGVyKG91dGRpcik7XG4gICAgY29uc3QgdGVtcGxhdGVGaWxlID0gYCR7dGhpcy50b29sa2l0U3RhY2tOYW1lfS50ZW1wbGF0ZS5qc29uYDtcbiAgICBhd2FpdCBmcy53cml0ZUpzb24ocGF0aC5qb2luKGJ1aWxkZXIub3V0ZGlyLCB0ZW1wbGF0ZUZpbGUpLCB0ZW1wbGF0ZSwge1xuICAgICAgc3BhY2VzOiAyLFxuICAgIH0pO1xuXG4gICAgYnVpbGRlci5hZGRBcnRpZmFjdCh0aGlzLnRvb2xraXRTdGFja05hbWUsIHtcbiAgICAgIHR5cGU6IEFydGlmYWN0VHlwZS5BV1NfQ0xPVURGT1JNQVRJT05fU1RBQ0ssXG4gICAgICBlbnZpcm9ubWVudDogRW52aXJvbm1lbnRVdGlscy5mb3JtYXQodGhpcy5yZXNvbHZlZEVudmlyb25tZW50LmFjY291bnQsIHRoaXMucmVzb2x2ZWRFbnZpcm9ubWVudC5yZWdpb24pLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICB0ZW1wbGF0ZUZpbGUsXG4gICAgICAgIHRlcm1pbmF0aW9uUHJvdGVjdGlvbjogb3B0aW9ucy50ZXJtaW5hdGlvblByb3RlY3Rpb24gPz8gZmFsc2UsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgYXNzZW1ibHkgPSBidWlsZGVyLmJ1aWxkQXNzZW1ibHkoKTtcblxuICAgIGNvbnN0IHJldCA9IGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAgIHN0YWNrOiBhc3NlbWJseS5nZXRTdGFja0J5TmFtZSh0aGlzLnRvb2xraXRTdGFja05hbWUpLFxuICAgICAgcmVzb2x2ZWRFbnZpcm9ubWVudDogdGhpcy5yZXNvbHZlZEVudmlyb25tZW50LFxuICAgICAgc2RrOiB0aGlzLnNkayxcbiAgICAgIHNka1Byb3ZpZGVyOiB0aGlzLnNka1Byb3ZpZGVyLFxuICAgICAgZm9yY2U6IG9wdGlvbnMuZm9yY2UsXG4gICAgICByb2xlQXJuOiBvcHRpb25zLnJvbGVBcm4sXG4gICAgICB0YWdzOiBvcHRpb25zLnRhZ3MsXG4gICAgICBkZXBsb3ltZW50TWV0aG9kOiB7IG1ldGhvZDogJ2NoYW5nZS1zZXQnLCBleGVjdXRlOiBvcHRpb25zLmV4ZWN1dGUgfSxcbiAgICAgIHBhcmFtZXRlcnMsXG4gICAgICB1c2VQcmV2aW91c1BhcmFtZXRlcnM6IG9wdGlvbnMudXNlUHJldmlvdXNQYXJhbWV0ZXJzID8/IHRydWUsXG4gICAgICAvLyBPYnZpb3VzbHkgd2UgY2FuJ3QgbmVlZCBhIGJvb3RzdHJhcCBzdGFjayB0byBkZXBsb3kgYSBib290c3RyYXAgc3RhY2tcbiAgICAgIGVudlJlc291cmNlczogbmV3IE5vQm9vdHN0cmFwU3RhY2tFbnZpcm9ubWVudFJlc291cmNlcyh0aGlzLnJlc29sdmVkRW52aXJvbm1lbnQsIHRoaXMuc2RrKSxcbiAgICB9KTtcblxuICAgIGFzc2VydElzU3VjY2Vzc2Z1bERlcGxveVN0YWNrUmVzdWx0KHJldCk7XG5cbiAgICByZXR1cm4gcmV0O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBib290c3RyYXBWZXJzaW9uRnJvbVRlbXBsYXRlKHRlbXBsYXRlOiBhbnkpOiBudW1iZXIge1xuICBjb25zdCB2ZXJzaW9uU291cmNlcyA9IFtcbiAgICB0ZW1wbGF0ZS5PdXRwdXRzPy5bQk9PVFNUUkFQX1ZFUlNJT05fT1VUUFVUXT8uVmFsdWUsXG4gICAgdGVtcGxhdGUuUmVzb3VyY2VzPy5bQk9PVFNUUkFQX1ZFUlNJT05fUkVTT1VSQ0VdPy5Qcm9wZXJ0aWVzPy5WYWx1ZSxcbiAgXTtcblxuICBmb3IgKGNvbnN0IHZzIG9mIHZlcnNpb25Tb3VyY2VzKSB7XG4gICAgaWYgKHR5cGVvZiB2cyA9PT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiB2cztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2cyA9PT0gJ3N0cmluZycgJiYgIWlzTmFOKHBhcnNlSW50KHZzLCAxMCkpKSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnQodnMsIDEwKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBib290c3RyYXBWYXJpYW50RnJvbVRlbXBsYXRlKHRlbXBsYXRlOiBhbnkpOiBzdHJpbmcge1xuICByZXR1cm4gdGVtcGxhdGUuUGFyYW1ldGVycz8uW0JPT1RTVFJBUF9WQVJJQU5UX1BBUkFNRVRFUl0/LkRlZmF1bHQgPz8gREVGQVVMVF9CT09UU1RSQVBfVkFSSUFOVDtcbn1cbiJdfQ==