aws-cdk
Version:
AWS CDK CLI, the command line tool for CDK apps
465 lines • 74.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlagOperations = void 0;
exports.isEffectiveValueEqualToRecommended = isEffectiveValueEqualToRecommended;
const os = require("os");
const path = require("path");
const cloudformation_diff_1 = require("@aws-cdk/cloudformation-diff");
const toolkit_lib_1 = require("@aws-cdk/toolkit-lib");
const chalk = require("chalk");
const fs = require("fs-extra");
const p_queue_1 = require("p-queue");
const obsolete_flags_1 = require("./obsolete-flags");
const api_1 = require("../../api");
class FlagOperations {
/**
* Returns only those feature flags that need configuration
*
* That is those flags:
* - That are unconfigured
* - That are not obsolete
* - Whose default value is different from the recommended value
*
* The default value being equal to the recommended value sounds odd, but
* crops up in a number of situtations:
*
* - Security-related fixes that we want to force on people, but want to
* give them a flag to back out of the changes if they really need to.
* - Flags that changed their default value in the most recent major
* version.
* - Flags that we've introduced at some point in the past, but have gone
* back on.
*/
static filterNeedsAttention(flags) {
return flags
.filter(flag => !obsolete_flags_1.OBSOLETE_FLAGS.includes(flag.name))
.filter(flag => flag.userValue === undefined)
.filter(flag => defaultValue(flag) !== flag.recommendedValue);
}
constructor(flags, toolkit, ioHelper) {
this.flags = flags;
this.toolkit = toolkit;
this.ioHelper = ioHelper;
this.app = '';
this.baseContextValues = {};
this.allStacks = [];
this.queue = new p_queue_1.default({ concurrency: 4 });
}
/** Main entry point that routes to either flag setting or display operations */
async execute(params) {
if (params.set) {
if (params.FLAGNAME && params.value) {
await this.setFlag(params);
}
else {
await this.setMultipleFlags(params);
}
}
else {
await this.displayFlags(params);
}
}
/** Sets a single specific flag with validation and user confirmation */
async setFlag(params) {
const flagName = params.FLAGNAME[0];
const flag = this.flags.find(f => f.name === flagName);
if (!flag) {
await this.ioHelper.defaults.error('Flag not found.');
return;
}
if (!this.isBooleanFlag(flag)) {
await this.ioHelper.defaults.error(`Flag '${flagName}' is not a boolean flag. Only boolean flags are currently supported.`);
return;
}
const prototypeSuccess = await this.prototypeChanges([flagName], params);
if (prototypeSuccess) {
await this.handleUserResponse([flagName], params);
}
}
/** Sets multiple flags (all or unconfigured) with validation and user confirmation */
async setMultipleFlags(params) {
if (params.default && !this.flags.some(f => f.unconfiguredBehavesLike)) {
await this.ioHelper.defaults.error('The --default options are not compatible with the AWS CDK library used by your application. Please upgrade to 2.212.0 or above.');
return;
}
const flagsToSet = this.getFlagsToSet(params);
const prototypeSuccess = await this.prototypeChanges(flagsToSet, params);
if (prototypeSuccess) {
await this.handleUserResponse(flagsToSet, params);
}
}
/** Determines which flags should be set based on the provided parameters */
getFlagsToSet(params) {
if (params.all && params.default) {
return this.flags
.filter(flag => this.isBooleanFlag(flag))
.map(flag => flag.name);
}
else if (params.all) {
return this.flags
.filter(flag => flag.userValue === undefined || !isEffectiveValueEqualToRecommended(flag))
.filter(flag => this.isBooleanFlag(flag))
.map(flag => flag.name);
}
else {
return this.flags
.filter(flag => flag.userValue === undefined)
.filter(flag => this.isBooleanFlag(flag))
.map(flag => flag.name);
}
}
/** Sets flags that don't cause template changes */
async setSafeFlags(params) {
const cdkJson = await JSON.parse(await fs.readFile(path.join(process.cwd(), 'cdk.json'), 'utf-8'));
this.app = params.app || cdkJson.app;
const isUsingTsNode = this.app.includes('ts-node');
if (isUsingTsNode && !this.app.includes('-T') && !this.app.includes('--transpileOnly')) {
await this.ioHelper.defaults.info('Repeated synths with ts-node will type-check the application on every synth. Add --transpileOnly to cdk.json\'s "app" command to make this operation faster.');
}
const unconfiguredFlags = this.flags.filter(flag => flag.userValue === undefined && this.isBooleanFlag(flag));
if (unconfiguredFlags.length === 0) {
await this.ioHelper.defaults.info('All feature flags are configured.');
return;
}
await this.initializeSafetyCheck();
const safeFlags = await this.batchTestFlags(unconfiguredFlags);
await this.cleanupSafetyCheck();
if (safeFlags.length > 0) {
await this.ioHelper.defaults.info('Flags that can be set without template changes:');
for (const flag of safeFlags) {
await this.ioHelper.defaults.info(`- ${flag.name} -> ${flag.recommendedValue}`);
}
await this.handleUserResponse(safeFlags.map(flag => flag.name), { ...params, recommended: true });
}
else {
await this.ioHelper.defaults.info('No more flags can be set without causing template changes.');
}
}
/** Initializes the safety check by reading context and synthesizing baseline templates */
async initializeSafetyCheck() {
const baseContext = new toolkit_lib_1.CdkAppMultiContext(process.cwd());
this.baseContextValues = await baseContext.read();
this.baselineTempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-baseline-'));
const baseSource = await this.toolkit.fromCdkApp(this.app, {
contextStore: baseContext,
outdir: this.baselineTempDir,
});
const baseCx = await this.toolkit.synth(baseSource);
const baseAssembly = baseCx.cloudAssembly;
this.allStacks = baseAssembly.stacksRecursively;
this.queue = new p_queue_1.default({ concurrency: 4 });
}
/** Cleans up temporary directories created during safety checks */
async cleanupSafetyCheck() {
if (this.baselineTempDir) {
await fs.remove(this.baselineTempDir);
this.baselineTempDir = undefined;
}
}
/** Tests multiple flags together and isolates unsafe ones using binary search */
async batchTestFlags(flags) {
if (flags.length === 0)
return [];
const allFlagsContext = { ...this.baseContextValues };
flags.forEach(flag => {
allFlagsContext[flag.name] = flag.recommendedValue;
});
const allSafe = await this.testBatch(allFlagsContext);
if (allSafe)
return flags;
return this.isolateUnsafeFlags(flags);
}
/** Tests if a set of context values causes template changes by synthesizing and diffing */
async testBatch(contextValues) {
const testContext = new toolkit_lib_1.MemoryContext(contextValues);
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-test-'));
const testSource = await this.toolkit.fromCdkApp(this.app, {
contextStore: testContext,
outdir: tempDir,
});
const testCx = await this.toolkit.synth(testSource);
try {
for (const stack of this.allStacks) {
const templatePath = stack.templateFullPath;
const diff = await this.toolkit.diff(testCx, {
method: toolkit_lib_1.DiffMethod.LocalFile(templatePath),
stacks: {
strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE,
patterns: [stack.hierarchicalId],
},
});
for (const stackDiff of Object.values(diff)) {
if (stackDiff.differenceCount > 0) {
return false;
}
}
}
return true;
}
finally {
await fs.remove(tempDir);
}
}
/** Uses binary search to isolate which flags are safe to set without template changes */
async isolateUnsafeFlags(flags) {
const safeFlags = [];
const processBatch = async (batch, contextValues) => {
if (batch.length === 1) {
const isSafe = await this.testBatch({ ...contextValues, [batch[0].name]: batch[0].recommendedValue });
if (isSafe)
safeFlags.push(batch[0]);
return;
}
const batchContext = { ...contextValues };
batch.forEach(flag => {
batchContext[flag.name] = flag.recommendedValue;
});
const isSafeBatch = await this.testBatch(batchContext);
if (isSafeBatch) {
safeFlags.push(...batch);
return;
}
const mid = Math.floor(batch.length / 2);
const left = batch.slice(0, mid);
const right = batch.slice(mid);
void this.queue.add(() => processBatch(left, contextValues));
void this.queue.add(() => processBatch(right, contextValues));
};
void this.queue.add(() => processBatch(flags, this.baseContextValues));
await this.queue.onIdle();
return safeFlags;
}
/** Prototypes flag changes by synthesizing templates and showing diffs to the user */
async prototypeChanges(flagNames, params) {
const baseContext = new toolkit_lib_1.CdkAppMultiContext(process.cwd());
const baseContextValues = await baseContext.read();
const memoryContext = new toolkit_lib_1.MemoryContext(baseContextValues);
const cdkJson = await JSON.parse(await fs.readFile(path.join(process.cwd(), 'cdk.json'), 'utf-8'));
const app = cdkJson.app;
const source = await this.toolkit.fromCdkApp(app, {
contextStore: baseContext,
outdir: fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-original-')),
});
const updateObj = await this.buildUpdateObject(flagNames, params, baseContextValues);
if (!updateObj)
return false;
await memoryContext.update(updateObj);
const cx = await this.toolkit.synth(source);
const assembly = cx.cloudAssembly;
const modifiedSource = await this.toolkit.fromCdkApp(app, {
contextStore: memoryContext,
outdir: fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-temp-')),
});
const modifiedCx = await this.toolkit.synth(modifiedSource);
const allStacks = assembly.stacksRecursively;
for (const stack of allStacks) {
const templatePath = stack.templateFullPath;
await this.toolkit.diff(modifiedCx, {
method: toolkit_lib_1.DiffMethod.LocalFile(templatePath),
stacks: {
strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE,
patterns: [stack.hierarchicalId],
},
});
}
await this.displayFlagChanges(updateObj, baseContextValues);
return true;
}
/** Displays a summary of flag changes showing old and new values */
async displayFlagChanges(updateObj, baseContextValues) {
await this.ioHelper.defaults.info('\nFlag changes:');
for (const [flagName, newValue] of Object.entries(updateObj)) {
const currentValue = baseContextValues[flagName];
const currentDisplay = currentValue === undefined ? '<unset>' : String(currentValue);
await this.ioHelper.defaults.info(` ${flagName}: ${currentDisplay} → ${newValue}`);
}
}
/** Builds the update object with new flag values based on parameters and current context */
async buildUpdateObject(flagNames, params, baseContextValues) {
const updateObj = {};
if (flagNames.length === 1 && params.value !== undefined) {
const flagName = flagNames[0];
const boolValue = params.value === 'true';
if (baseContextValues[flagName] === boolValue) {
await this.ioHelper.defaults.info('Flag is already set to the specified value. No changes needed.');
return null;
}
updateObj[flagName] = boolValue;
}
else {
for (const flagName of flagNames) {
const flag = this.flags.find(f => f.name === flagName);
if (!flag) {
await this.ioHelper.defaults.error(`Flag ${flagName} not found.`);
return null;
}
const newValue = params.recommended
? flag.recommendedValue
: String(defaultValue(flag)) === 'true';
updateObj[flagName] = newValue;
}
}
return updateObj;
}
/** Prompts user for confirmation and applies changes if accepted */
async handleUserResponse(flagNames, params) {
const userAccepted = await this.ioHelper.requestResponse({
time: new Date(),
level: 'info',
code: 'CDK_TOOLKIT_I9300',
message: 'Do you want to accept these changes?',
data: {
flagNames,
responseDescription: 'Enter "y" to apply changes or "n" to cancel',
},
defaultResponse: false,
});
if (userAccepted) {
await this.modifyValues(flagNames, params);
await this.ioHelper.defaults.info('Flag value(s) updated successfully.');
}
else {
await this.ioHelper.defaults.info('Operation cancelled');
}
await this.cleanupTempDirectories();
}
/** Removes temporary directories created during flag operations */
async cleanupTempDirectories() {
const originalDir = path.join(process.cwd(), 'original');
const tempDir = path.join(process.cwd(), 'temp');
await fs.remove(originalDir);
await fs.remove(tempDir);
}
/** Actually modifies the cdk.json file with the new flag values */
async modifyValues(flagNames, params) {
const cdkJsonPath = path.join(process.cwd(), 'cdk.json');
const cdkJsonContent = await fs.readFile(cdkJsonPath, 'utf-8');
const cdkJson = JSON.parse(cdkJsonContent);
if (flagNames.length === 1 && !params.safe) {
const boolValue = params.value === 'true';
cdkJson.context[String(flagNames[0])] = boolValue;
await this.ioHelper.defaults.info(`Setting flag '${flagNames}' to: ${boolValue}`);
}
else {
for (const flagName of flagNames) {
const flag = this.flags.find(f => f.name === flagName);
const newValue = params.recommended || params.safe
? flag.recommendedValue
: String(defaultValue(flag)) === 'true';
cdkJson.context[flagName] = newValue;
}
}
await fs.writeFile(cdkJsonPath, JSON.stringify(cdkJson, null, 2), 'utf-8');
}
/** Displays flags in a table format, either specific flags or filtered by criteria */
async displayFlags(params) {
const { FLAGNAME, all } = params;
if (FLAGNAME && FLAGNAME.length > 0) {
await this.displaySpecificFlags(FLAGNAME);
return;
}
const [flagsToDisplay, header] = all
? [this.flags, 'All feature flags']
: [FlagOperations.filterNeedsAttention(this.flags), 'Unconfigured feature flags'];
await this.ioHelper.defaults.info(header);
await this.displayFlagTable(flagsToDisplay);
// Add helpful message after empty table when not using --all
if (!all && flagsToDisplay.length === 0) {
await this.ioHelper.defaults.info('');
await this.ioHelper.defaults.info('✅ All feature flags are already set to their recommended values.');
await this.ioHelper.defaults.info('Use \'cdk flags --all --unstable=flags\' to see all flags and their current values.');
}
}
/** Displays detailed information for specific flags matching the given names */
async displaySpecificFlags(flagNames) {
const matchingFlags = this.flags.filter(f => flagNames.some(searchTerm => f.name.toLowerCase().includes(searchTerm.toLowerCase())));
if (matchingFlags.length === 0) {
await this.ioHelper.defaults.error(`Flag matching "${flagNames.join(', ')}" not found.`);
return;
}
if (matchingFlags.length === 1) {
const flag = matchingFlags[0];
await this.ioHelper.defaults.info(`Flag name: ${flag.name}`);
await this.ioHelper.defaults.info(`Description: ${flag.explanation}`);
await this.ioHelper.defaults.info(`Recommended value: ${flag.recommendedValue}`);
await this.ioHelper.defaults.info(`Default value: ${defaultValue(flag)}`);
await this.ioHelper.defaults.info(`User value: ${flag.userValue}`);
await this.ioHelper.defaults.info(`Effective value: ${effectiveValue(flag)}`);
return;
}
await this.ioHelper.defaults.info(`Found ${matchingFlags.length} flags matching "${flagNames.join(', ')}"`);
await this.displayFlagTable(matchingFlags);
}
/** Returns sort order for flags */
getFlagSortOrder(flag) {
if (flag.userValue === undefined)
return 3;
if (isEffectiveValueEqualToRecommended(flag))
return 1;
return 2;
}
/** Displays flags in a formatted table grouped by module and sorted */
async displayFlagTable(flags) {
const sortedFlags = [...flags].sort((a, b) => {
const orderA = this.getFlagSortOrder(a);
const orderB = this.getFlagSortOrder(b);
if (orderA !== orderB)
return orderA - orderB;
if (a.module !== b.module)
return a.module.localeCompare(b.module);
return a.name.localeCompare(b.name);
});
const rows = [['Feature Flag', 'Recommended', 'User', 'Effective']];
let currentModule = '';
sortedFlags.forEach((flag) => {
if (flag.module !== currentModule) {
rows.push([chalk.bold(`Module: ${flag.module}`), '', '', '']);
currentModule = flag.module;
}
rows.push([
` ${flag.name}`,
String(flag.recommendedValue),
flag.userValue === undefined ? '<unset>' : String(flag.userValue),
String(effectiveValue(flag)),
]);
});
const formattedTable = (0, cloudformation_diff_1.formatTable)(rows, undefined, true);
await this.ioHelper.defaults.info(formattedTable);
}
/** Checks if a flag has a boolean recommended value */
isBooleanFlag(flag) {
const recommended = flag.recommendedValue;
return typeof recommended === 'boolean' ||
recommended === 'true' ||
recommended === 'false';
}
/** Shows helpful usage examples and available command options */
async displayHelpMessage() {
await this.ioHelper.defaults.info('\n' + chalk.bold('Available options:'));
await this.ioHelper.defaults.info(' cdk flags --interactive # Interactive menu to manage flags');
await this.ioHelper.defaults.info(' cdk flags --all # Show all flags (including configured ones)');
await this.ioHelper.defaults.info(' cdk flags --set --all --recommended # Set all flags to recommended values');
await this.ioHelper.defaults.info(' cdk flags --set --all --default # Set all flags to default values');
await this.ioHelper.defaults.info(' cdk flags --set --unconfigured --recommended # Set unconfigured flags to recommended');
await this.ioHelper.defaults.info(' cdk flags --set <flag-name> --value <true|false> # Set specific flag');
await this.ioHelper.defaults.info(' cdk flags --safe # Safely set flags that don\'t change templates');
}
}
exports.FlagOperations = FlagOperations;
/** Checks if the flags current effective value matches the recommended value */
function isEffectiveValueEqualToRecommended(flag) {
return String(effectiveValue(flag)) === String(flag.recommendedValue);
}
/**
* Return the effective value of a flag (user value or default)
*/
function effectiveValue(flag) {
return flag.userValue ?? defaultValue(flag);
}
/**
* Return the default value for a flag, assume it's `false` if not given
*/
function defaultValue(flag) {
return flag.unconfiguredBehavesLike?.v2 ?? false;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZXJhdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBbWdCQSxnRkFFQztBQXJnQkQseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QixzRUFBMkQ7QUFHM0Qsc0RBQXFGO0FBQ3JGLCtCQUErQjtBQUMvQiwrQkFBK0I7QUFDL0IscUNBQTZCO0FBQzdCLHFEQUFrRDtBQUVsRCxtQ0FBbUQ7QUFHbkQsTUFBYSxjQUFjO0lBQ3pCOzs7Ozs7Ozs7Ozs7Ozs7OztPQWlCRztJQUNJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxLQUFvQjtRQUNyRCxPQUFPLEtBQUs7YUFDVCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLCtCQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUNuRCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQzthQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDbEUsQ0FBQztJQVFELFlBQ21CLEtBQW9CLEVBQ3BCLE9BQWdCLEVBQ2hCLFFBQWtCO1FBRmxCLFVBQUssR0FBTCxLQUFLLENBQWU7UUFDcEIsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUNoQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBRW5DLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksaUJBQU0sQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFF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SSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDOUMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxZQUFZLENBQUMsSUFBaUI7SUFDckMsT0FBTyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxJQUFJLEtBQUssQ0FBQztBQUNuRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGZvcm1hdFRhYmxlIH0gZnJvbSAnQGF3cy1jZGsvY2xvdWRmb3JtYXRpb24tZGlmZic7XG5pbXBvcnQgdHlwZSB7IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgdHlwZSB7IEZlYXR1cmVGbGFnLCBUb29sa2l0IH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuaW1wb3J0IHsgQ2RrQXBwTXVsdGlDb250ZXh0LCBNZW1vcnlDb250ZXh0LCBEaWZmTWV0aG9kIH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuaW1wb3J0ICogYXMgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IFBRdWV1ZSBmcm9tICdwLXF1ZXVlJztcbmltcG9ydCB7IE9CU09MRVRFX0ZMQUdTIH0gZnJvbSAnLi9vYnNvbGV0ZS1mbGFncyc7XG5pbXBvcnQgdHlwZSB7IEZsYWdPcGVyYXRpb25zUGFyYW1zIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBTdGFja1NlbGVjdGlvblN0cmF0ZWd5IH0gZnJvbSAnLi4vLi4vYXBpJztcbmltcG9ydCB0eXBlIHsgSW9IZWxwZXIgfSBmcm9tICcuLi8uLi9hcGktcHJpdmF0ZSc7XG5cbmV4cG9ydCBjbGFzcyBGbGFnT3BlcmF0aW9ucyB7XG4gIC8qKlxuICAgKiBSZXR1cm5zIG9ubHkgdGhvc2UgZmVhdHVyZSBmbGFncyB0aGF0IG5lZWQgY29uZmlndXJhdGlvblxuICAgKlxuICAgKiBUaGF0IGlzIHRob3NlIGZsYWdzOlxuICAgKiAtIFRoYXQgYXJlIHVuY29uZmlndXJlZFxuICAgKiAtIFRoYXQgYXJlIG5vdCBvYnNvbGV0ZVxuICAgKiAtIFdob3NlIGRlZmF1bHQgdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gdGhlIHJlY29tbWVuZGVkIHZhbHVlXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IHZhbHVlIGJlaW5nIGVxdWFsIHRvIHRoZSByZWNvbW1lbmRlZCB2YWx1ZSBzb3VuZHMgb2RkLCBidXRcbiAgICogY3JvcHMgdXAgaW4gYSBudW1iZXIgb2Ygc2l0dXRhdGlvbnM6XG4gICAqXG4gICAqIC0gU2VjdXJpdHktcmVsYXRlZCBmaXhlcyB0aGF0IHdlIHdhbnQgdG8gZm9yY2Ugb24gcGVvcGxlLCBidXQgd2FudCB0b1xuICAgKiAgIGdpdmUgdGhlbSBhIGZsYWcgdG8gYmFjayBvdXQgb2YgdGhlIGNoYW5nZXMgaWYgdGhleSByZWFsbHkgbmVlZCB0by5cbiAgICogLSBGbGFncyB0aGF0IGNoYW5nZWQgdGhlaXIgZGVmYXVsdCB2YWx1ZSBpbiB0aGUgbW9zdCByZWNlbnQgbWFqb3JcbiAgICogICB2ZXJzaW9uLlxuICAgKiAtIEZsYWdzIHRoYXQgd2UndmUgaW50cm9kdWNlZCBhdCBzb21lIHBvaW50IGluIHRoZSBwYXN0LCBidXQgaGF2ZSBnb25lXG4gICAqICAgYmFjayBvbi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZmlsdGVyTmVlZHNBdHRlbnRpb24oZmxhZ3M6IEZlYXR1cmVGbGFnW10pOiBGZWF0dXJlRmxhZ1tdIHtcbiAgICByZXR1cm4gZmxhZ3NcbiAgICAgIC5maWx0ZXIoZmxhZyA9PiAhT0JTT0xFVEVfRkxBR1MuaW5jbHVkZXMoZmxhZy5uYW1lKSlcbiAgICAgIC5maWx0ZXIoZmxhZyA9PiBmbGFnLnVzZXJWYWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgLmZpbHRlcihmbGFnID0+IGRlZmF1bHRWYWx1ZShmbGFnKSAhPT0gZmxhZy5yZWNvbW1lbmRlZFZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwOiBzdHJpbmc7XG4gIHByaXZhdGUgYmFzZUNvbnRleHRWYWx1ZXM6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIHByaXZhdGUgYWxsU3RhY2tzOiBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXTtcbiAgcHJpdmF0ZSBxdWV1ZTogUFF1ZXVlO1xuICBwcml2YXRlIGJhc2VsaW5lVGVtcERpcj86IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGZsYWdzOiBGZWF0dXJlRmxhZ1tdLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdG9vbGtpdDogVG9vbGtpdCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcixcbiAgKSB7XG4gICAgdGhpcy5hcHAgPSAnJztcbiAgICB0aGlzLmJhc2VDb250ZXh0VmFsdWVzID0ge307XG4gICAgdGhpcy5hbGxTdGFja3MgPSBbXTtcbiAgICB0aGlzLnF1ZXVlID0gbmV3IFBRdWV1ZSh7IGNvbmN1cnJlbmN5OiA0IH0pO1xuICB9XG5cbiAgLyoqIE1haW4gZW50cnkgcG9pbnQgdGhhdCByb3V0ZXMgdG8gZWl0aGVyIGZsYWcgc2V0dGluZyBvciBkaXNwbGF5IG9wZXJhdGlvbnMgKi9cbiAgYXN5bmMgZXhlY3V0ZShwYXJhbXM6IEZsYWdPcGVyYXRpb25zUGFyYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHBhcmFtcy5zZXQpIHtcbiAgICAgIGlmIChwYXJhbXMuRkxBR05BTUUgJiYgcGFyYW1zLnZhbHVlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0RmxhZyhwYXJhbXMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXRNdWx0aXBsZUZsYWdzKHBhcmFtcyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuZGlzcGxheUZsYWdzKHBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFNldHMgYSBzaW5nbGUgc3BlY2lmaWMgZmxhZyB3aXRoIHZhbGlkYXRpb24gYW5kIHVzZXIgY29uZmlybWF0aW9uICovXG4gIGFzeW5jIHNldEZsYWcocGFyYW1zOiBGbGFnT3BlcmF0aW9uc1BhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZsYWdOYW1lID0gcGFyYW1zLkZMQUdOQU1FIVswXTtcbiAgICBjb25zdCBmbGFnID0gdGhpcy5mbGFncy5maW5kKGYgPT4gZi5uYW1lID09PSBmbGFnTmFtZSk7XG5cbiAgICBpZiAoIWZsYWcpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIuZGVmYXVsdHMuZXJyb3IoJ0ZsYWcgbm90IGZvdW5kLicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0Jvb2xlYW5GbGFnKGZsYWcpKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLmRlZmF1bHRzLmVycm9yKGBGbGFnICcke2ZsYWdOYW1lfScgaXMgbm90IGEgYm9vbGVhbiBmbGFnLiBPbmx5IGJvb2xlYW4gZmxhZ3MgYXJlIG