UNPKG

aws-cdk

Version:

AWS CDK CLI, the command line tool for CDK apps

467 lines 75.3 kB
"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, cliContextValues = {}) { this.flags = flags; this.toolkit = toolkit; this.ioHelper = ioHelper; this.cliContextValues = cliContextValues; 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.cliContextValues }; this.baselineTempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-baseline-')); const mergedContext = new toolkit_lib_1.MemoryContext(this.baseContextValues); const baseSource = await this.toolkit.fromCdkApp(this.app, { contextStore: mergedContext, 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(), ...this.cliContextValues }; 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: memoryContext, 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 && !params.all) { 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZXJhdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBcWdCQSxnRkFFQztBQXZnQkQseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUU3QixzRUFBMkQ7QUFFM0Qsc0RBQXFGO0FBQ3JGLCtCQUErQjtBQUMvQiwrQkFBK0I7QUFDL0IscUNBQTZCO0FBQzdCLHFEQUFrRDtBQUVsRCxtQ0FBbUQ7QUFHbkQsTUFBYSxjQUFjO0lBQ3pCOzs7Ozs7Ozs7Ozs7Ozs7OztPQWlCRztJQUNJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxLQUFvQjtRQUNyRCxPQUFPLEtBQUs7YUFDVCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLCtCQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUNuRCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQzthQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDbEUsQ0FBQztJQVFELFlBQ21CLEtBQW9CLEVBQ3BCLE9BQWdCLEVBQ2hCLFFBQWtCLEVBQ2xCLG1CQUF3QyxFQUFFO1FBSDFDLFVBQUssR0FBTCxLQUFLLENBQWU7UUFDcEIsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUNoQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBMEI7UUFFM0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDZCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxpQkFBTSxDQUFD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Q0Y7QUFwZkQsd0NBb2ZDO0FBRUQsZ0ZBQWdGO0FBQ2hGLFNBQWdCLGtDQUFrQyxDQUFDLElBQWlCO0lBQ2xFLE9BQU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGNBQWMsQ0FBQyxJQUFpQjtJQUN2QyxPQUFPLElBQUksQ0FBQyxTQUFTLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLElBQWlCO0lBQ3JDLE9BQU8sSUFBSSxDQUFDLHVCQUF1QixFQUFFLEVBQUUsSUFBSSxLQUFLLENBQUM7QUFDbkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgdHlwZSB7IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LWFwaSc7XG5pbXBvcnQgeyBmb3JtYXRUYWJsZSB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkZm9ybWF0aW9uLWRpZmYnO1xuaW1wb3J0IHR5cGUgeyBGZWF0dXJlRmxhZywgVG9vbGtpdCB9IGZyb20gJ0Bhd3MtY2RrL3Rvb2xraXQtbGliJztcbmltcG9ydCB7IENka0FwcE11bHRpQ29udGV4dCwgTWVtb3J5Q29udGV4dCwgRGlmZk1ldGhvZCB9IGZyb20gJ0Bhd3MtY2RrL3Rvb2xraXQtbGliJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBQUXVldWUgZnJvbSAncC1xdWV1ZSc7XG5pbXBvcnQgeyBPQlNPTEVURV9GTEFHUyB9IGZyb20gJy4vb2Jzb2xldGUtZmxhZ3MnO1xuaW1wb3J0IHR5cGUgeyBGbGFnT3BlcmF0aW9uc1BhcmFtcyB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgU3RhY2tTZWxlY3Rpb25TdHJhdGVneSB9IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgdHlwZSB7IElvSGVscGVyIH0gZnJvbSAnLi4vLi4vYXBpLXByaXZhdGUnO1xuXG5leHBvcnQgY2xhc3MgRmxhZ09wZXJhdGlvbnMge1xuICAvKipcbiAgICogUmV0dXJucyBvbmx5IHRob3NlIGZlYXR1cmUgZmxhZ3MgdGhhdCBuZWVkIGNvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogVGhhdCBpcyB0aG9zZSBmbGFnczpcbiAgICogLSBUaGF0IGFyZSB1bmNvbmZpZ3VyZWRcbiAgICogLSBUaGF0IGFyZSBub3Qgb2Jzb2xldGVcbiAgICogLSBXaG9zZSBkZWZhdWx0IHZhbHVlIGlzIGRpZmZlcmVudCBmcm9tIHRoZSByZWNvbW1lbmRlZCB2YWx1ZVxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBiZWluZyBlcXVhbCB0byB0aGUgcmVjb21tZW5kZWQgdmFsdWUgc291bmRzIG9kZCwgYnV0XG4gICAqIGNyb3BzIHVwIGluIGEgbnVtYmVyIG9mIHNpdHV0YXRpb25zOlxuICAgKlxuICAgKiAtIFNlY3VyaXR5LXJlbGF0ZWQgZml4ZXMgdGhhdCB3ZSB3YW50IHRvIGZvcmNlIG9uIHBlb3BsZSwgYnV0IHdhbnQgdG9cbiAgICogICBnaXZlIHRoZW0gYSBmbGFnIHRvIGJhY2sgb3V0IG9mIHRoZSBjaGFuZ2VzIGlmIHRoZXkgcmVhbGx5IG5lZWQgdG8uXG4gICAqIC0gRmxhZ3MgdGhhdCBjaGFuZ2VkIHRoZWlyIGRlZmF1bHQgdmFsdWUgaW4gdGhlIG1vc3QgcmVjZW50IG1ham9yXG4gICAqICAgdmVyc2lvbi5cbiAgICogLSBGbGFncyB0aGF0IHdlJ3ZlIGludHJvZHVjZWQgYXQgc29tZSBwb2ludCBpbiB0aGUgcGFzdCwgYnV0IGhhdmUgZ29uZVxuICAgKiAgIGJhY2sgb24uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZpbHRlck5lZWRzQXR0ZW50aW9uKGZsYWdzOiBGZWF0dXJlRmxhZ1tdKTogRmVhdHVyZUZsYWdbXSB7XG4gICAgcmV0dXJuIGZsYWdzXG4gICAgICAuZmlsdGVyKGZsYWcgPT4gIU9CU09MRVRFX0ZMQUdTLmluY2x1ZGVzKGZsYWcubmFtZSkpXG4gICAgICAuZmlsdGVyKGZsYWcgPT4gZmxhZy51c2VyVmFsdWUgPT09IHVuZGVmaW5lZClcbiAgICAgIC5maWx0ZXIoZmxhZyA9PiBkZWZhdWx0VmFsdWUoZmxhZykgIT09IGZsYWcucmVjb21tZW5kZWRWYWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIGFwcDogc3RyaW5nO1xuICBwcml2YXRlIGJhc2VDb250ZXh0VmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBwcml2YXRlIGFsbFN0YWNrczogQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0W107XG4gIHByaXZhdGUgcXVldWU6IFBRdWV1ZTtcbiAgcHJpdmF0ZSBiYXNlbGluZVRlbXBEaXI/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBmbGFnczogRmVhdHVyZUZsYWdbXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRvb2xraXQ6IFRvb2xraXQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBpb0hlbHBlcjogSW9IZWxwZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjbGlDb250ZXh0VmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge30sXG4gICkge1xuICAgIHRoaXMuYXBwID0gJyc7XG4gICAgdGhpcy5iYXNlQ29udGV4dFZhbHVlcyA9IHt9O1xuICAgIHRoaXMuYWxsU3RhY2tzID0gW107XG4gICAgdGhpcy5xdWV1ZSA9IG5ldyBQUXVldWUoeyBjb25jdXJyZW5jeTogNCB9KTtcbiAgfVxuXG4gIC8qKiBNYWluIGVudHJ5IHBvaW50IHRoYXQgcm91dGVzIHRvIGVpdGhlciBmbGFnIHNldHRpbmcgb3IgZGlzcGxheSBvcGVyYXRpb25zICovXG4gIGFzeW5jIGV4ZWN1dGUocGFyYW1zOiBGbGFnT3BlcmF0aW9uc1BhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChwYXJhbXMuc2V0KSB7XG4gICAgICBpZiAocGFyYW1zLkZMQUdOQU1FICYmIHBhcmFtcy52YWx1ZSkge1xuICAgICAgICBhd2FpdCB0aGlzLnNldEZsYWcocGFyYW1zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0TXVsdGlwbGVGbGFncyhwYXJhbXMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmRpc3BsYXlGbGFncyhwYXJhbXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTZXRzI