aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
540 lines • 82 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CurrentActivityPrinter = exports.HistoryActivityPrinter = exports.StackActivityMonitor = exports.StackActivityProgress = void 0;
const util = require("util");
const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema");
const chalk = require("chalk");
const stack_event_poller_1 = require("./stack-event-poller");
const logging_1 = require("../../../logging");
const cli_io_host_1 = require("../../../toolkit/cli-io-host");
const display_1 = require("../display");
/**
* Supported display modes for stack deployment activity
*/
var StackActivityProgress;
(function (StackActivityProgress) {
/**
* Displays a progress bar with only the events for the resource currently being deployed
*/
StackActivityProgress["BAR"] = "bar";
/**
* Displays complete history with all CloudFormation stack events
*/
StackActivityProgress["EVENTS"] = "events";
})(StackActivityProgress || (exports.StackActivityProgress = StackActivityProgress = {}));
class StackActivityMonitor {
/**
* Create a Stack Activity Monitor using a default printer, based on context clues
*/
static withDefaultPrinter(cfn, stackName, stackArtifact, options = {}) {
const stream = options.ci ? process.stdout : process.stderr;
const props = {
resourceTypeColumnWidth: calcMaxResourceTypeLength(stackArtifact.template),
resourcesTotal: options.resourcesTotal,
stream,
};
const isWindows = process.platform === 'win32';
const verbose = options.logLevel ?? 'info';
// On some CI systems (such as CircleCI) output still reports as a TTY so we also
// need an individual check for whether we're running on CI.
// see: https://discuss.circleci.com/t/circleci-terminal-is-a-tty-but-term-is-not-set/9965
const fancyOutputAvailable = !isWindows && stream.isTTY && !options.ci;
const progress = options.progress ?? StackActivityProgress.BAR;
const printer = fancyOutputAvailable && !verbose && progress === StackActivityProgress.BAR
? new CurrentActivityPrinter(props)
: new HistoryActivityPrinter(props);
return new StackActivityMonitor(cfn, stackName, printer, stackArtifact, options.changeSetCreationTime);
}
constructor(cfn, stackName, printer, stack, changeSetCreationTime) {
this.stackName = stackName;
this.printer = printer;
this.stack = stack;
this.errors = [];
this.active = false;
this.poller = new stack_event_poller_1.StackEventPoller(cfn, {
stackName,
startTime: changeSetCreationTime?.getTime() ?? Date.now(),
});
}
start() {
this.active = true;
this.printer.start();
this.scheduleNextTick();
return this;
}
async stop() {
this.active = false;
if (this.tickTimer) {
clearTimeout(this.tickTimer);
}
// Do a final poll for all events. This is to handle the situation where DescribeStackStatus
// already returned an error, but the monitor hasn't seen all the events yet and we'd end
// up not printing the failure reason to users.
await this.finalPollToEnd();
this.printer.stop();
}
scheduleNextTick() {
if (!this.active) {
return;
}
this.tickTimer = setTimeout(() => void this.tick(), this.printer.updateSleep);
}
async tick() {
if (!this.active) {
return;
}
try {
this.readPromise = this.readNewEvents();
await this.readPromise;
this.readPromise = undefined;
// We might have been stop()ped while the network call was in progress.
if (!this.active) {
return;
}
this.printer.print();
}
catch (e) {
(0, logging_1.error)('Error occurred while monitoring stack: %s', e);
}
this.scheduleNextTick();
}
findMetadataFor(logicalId) {
const metadata = this.stack?.manifest?.metadata;
if (!logicalId || !metadata) {
return undefined;
}
for (const path of Object.keys(metadata)) {
const entry = metadata[path]
.filter((e) => e.type === cloud_assembly_schema_1.ArtifactMetadataEntryType.LOGICAL_ID)
.find((e) => e.data === logicalId);
if (entry) {
return {
entry,
constructPath: this.simplifyConstructPath(path),
};
}
}
return undefined;
}
/**
* Reads all new events from the stack history
*
* The events are returned in reverse chronological order; we continue to the next page if we
* see a next page and the last event in the page is new to us (and within the time window).
* haven't seen the final event
*/
async readNewEvents() {
const pollEvents = await this.poller.poll();
const activities = pollEvents.map((event) => ({
...event,
metadata: this.findMetadataFor(event.event.LogicalResourceId),
}));
for (const activity of activities) {
this.checkForErrors(activity);
this.printer.addActivity(activity);
}
}
/**
* Perform a final poll to the end and flush out all events to the printer
*
* Finish any poll currently in progress, then do a final one until we've
* reached the last page.
*/
async finalPollToEnd() {
// If we were doing a poll, finish that first. It was started before
// the moment we were sure we weren't going to get any new events anymore
// so we need to do a new one anyway. Need to wait for this one though
// because our state is single-threaded.
if (this.readPromise) {
await this.readPromise;
}
await this.readNewEvents();
}
checkForErrors(activity) {
if (hasErrorMessage(activity.event.ResourceStatus ?? '')) {
const isCancelled = (activity.event.ResourceStatusReason ?? '').indexOf('cancelled') > -1;
// Cancelled is not an interesting failure reason, nor is the stack message (stack
// message will just say something like "stack failed to update")
if (!isCancelled && activity.event.StackName !== activity.event.LogicalResourceId) {
this.errors.push(activity.event.ResourceStatusReason ?? '');
}
}
}
simplifyConstructPath(path) {
path = path.replace(/\/Resource$/, '');
path = path.replace(/^\//, ''); // remove "/" prefix
// remove "<stack-name>/" prefix
if (path.startsWith(this.stackName + '/')) {
path = path.slice(this.stackName.length + 1);
}
return path;
}
}
exports.StackActivityMonitor = StackActivityMonitor;
function padRight(n, x) {
return x + ' '.repeat(Math.max(0, n - x.length));
}
/**
* Infamous padLeft()
*/
function padLeft(n, x) {
return ' '.repeat(Math.max(0, n - x.length)) + x;
}
function calcMaxResourceTypeLength(template) {
const resources = (template && template.Resources) || {};
let maxWidth = 0;
for (const id of Object.keys(resources)) {
const type = resources[id].Type || '';
if (type.length > maxWidth) {
maxWidth = type.length;
}
}
return maxWidth;
}
class ActivityPrinterBase {
constructor(props) {
this.props = props;
/**
* Fetch new activity every 5 seconds
*/
this.updateSleep = 5000;
/**
* A list of resource IDs which are currently being processed
*/
this.resourcesInProgress = {};
/**
* Previous completion state observed by logical ID
*
* We use this to detect that if we see a DELETE_COMPLETE after a
* CREATE_COMPLETE, it's actually a rollback and we should DECREASE
* resourcesDone instead of increase it
*/
this.resourcesPrevCompleteState = {};
/**
* Count of resources that have reported a _COMPLETE status
*/
this.resourcesDone = 0;
/**
* How many digits we need to represent the total count (for lining up the status reporting)
*/
this.resourceDigits = 0;
this.rollingBack = false;
this.failures = new Array();
this.hookFailureMap = new Map();
// +1 because the stack also emits a "COMPLETE" event at the end, and that wasn't
// counted yet. This makes it line up with the amount of events we expect.
this.resourcesTotal = props.resourcesTotal ? props.resourcesTotal + 1 : undefined;
// How many digits does this number take to represent?
this.resourceDigits = this.resourcesTotal ? Math.ceil(Math.log10(this.resourcesTotal)) : 0;
}
failureReason(activity) {
const resourceStatusReason = activity.event.ResourceStatusReason ?? '';
const logicalResourceId = activity.event.LogicalResourceId ?? '';
const hookFailureReasonMap = this.hookFailureMap.get(logicalResourceId);
if (hookFailureReasonMap !== undefined) {
for (const hookType of hookFailureReasonMap.keys()) {
if (resourceStatusReason.includes(hookType)) {
return resourceStatusReason + ' : ' + hookFailureReasonMap.get(hookType);
}
}
}
return resourceStatusReason;
}
addActivity(activity) {
const status = activity.event.ResourceStatus;
const hookStatus = activity.event.HookStatus;
const hookType = activity.event.HookType;
if (!status || !activity.event.LogicalResourceId) {
return;
}
if (status === 'ROLLBACK_IN_PROGRESS' || status === 'UPDATE_ROLLBACK_IN_PROGRESS') {
// Only triggered on the stack once we've started doing a rollback
this.rollingBack = true;
}
if (status.endsWith('_IN_PROGRESS')) {
this.resourcesInProgress[activity.event.LogicalResourceId] = activity;
}
if (hasErrorMessage(status)) {
const isCancelled = (activity.event.ResourceStatusReason ?? '').indexOf('cancelled') > -1;
// Cancelled is not an interesting failure reason
if (!isCancelled) {
this.failures.push(activity);
}
}
if (status.endsWith('_COMPLETE') || status.endsWith('_FAILED')) {
delete this.resourcesInProgress[activity.event.LogicalResourceId];
}
if (status.endsWith('_COMPLETE_CLEANUP_IN_PROGRESS')) {
this.resourcesDone++;
}
if (status.endsWith('_COMPLETE')) {
const prevState = this.resourcesPrevCompleteState[activity.event.LogicalResourceId];
if (!prevState) {
this.resourcesDone++;
}
else {
// If we completed this before and we're completing it AGAIN, means we're rolling back.
// Protect against silly underflow.
this.resourcesDone--;
if (this.resourcesDone < 0) {
this.resourcesDone = 0;
}
}
this.resourcesPrevCompleteState[activity.event.LogicalResourceId] = status;
}
if (hookStatus !== undefined &&
hookStatus.endsWith('_COMPLETE_FAILED') &&
activity.event.LogicalResourceId !== undefined &&
hookType !== undefined) {
if (this.hookFailureMap.has(activity.event.LogicalResourceId)) {
this.hookFailureMap.get(activity.event.LogicalResourceId)?.set(hookType, activity.event.HookStatusReason ?? '');
}
else {
this.hookFailureMap.set(activity.event.LogicalResourceId, new Map());
this.hookFailureMap.get(activity.event.LogicalResourceId)?.set(hookType, activity.event.HookStatusReason ?? '');
}
}
}
start() {
// Empty on purpose
}
stop() {
// Empty on purpose
}
}
/**
* Activity Printer which shows a full log of all CloudFormation events
*
* When there hasn't been activity for a while, it will print the resources
* that are currently in progress, to show what's holding up the deployment.
*/
class HistoryActivityPrinter extends ActivityPrinterBase {
constructor(props) {
super(props);
/**
* Last time we printed something to the console.
*
* Used to measure timeout for progress reporting.
*/
this.lastPrintTime = Date.now();
/**
* Number of ms of change absence before we tell the user about the resources that are currently in progress.
*/
this.inProgressDelay = 30000;
this.printable = new Array();
}
addActivity(activity) {
super.addActivity(activity);
this.printable.push(activity);
this.print();
}
print() {
for (const activity of this.printable) {
this.printOne(activity);
}
this.printable.splice(0, this.printable.length);
this.printInProgress();
}
stop() {
// Print failures at the end
if (this.failures.length > 0) {
(0, logging_1.info)('\nFailed resources:');
for (const failure of this.failures) {
// Root stack failures are not interesting
if (failure.isStackEvent) {
continue;
}
this.printOne(failure, false);
}
}
}
printOne(activity, progress) {
const event = activity.event;
const color = colorFromStatusResult(event.ResourceStatus);
let reasonColor = chalk.cyan;
let stackTrace = '';
const metadata = activity.metadata;
if (event.ResourceStatus && event.ResourceStatus.indexOf('FAILED') !== -1) {
if (progress == undefined || progress) {
event.ResourceStatusReason = event.ResourceStatusReason ? this.failureReason(activity) : '';
}
if (metadata) {
stackTrace = metadata.entry.trace ? `\n\t${metadata.entry.trace.join('\n\t\\_ ')}` : '';
}
reasonColor = chalk.red;
}
const resourceName = metadata ? metadata.constructPath : event.LogicalResourceId || '';
const logicalId = resourceName !== event.LogicalResourceId ? `(${event.LogicalResourceId}) ` : '';
(0, logging_1.info)(util.format('%s | %s%s | %s | %s | %s %s%s%s', event.StackName, progress !== false ? `${this.progress()} | ` : '', new Date(event.Timestamp).toLocaleTimeString(), color(padRight(STATUS_WIDTH, (event.ResourceStatus || '').slice(0, STATUS_WIDTH))), // pad left and trim
padRight(this.props.resourceTypeColumnWidth, event.ResourceType || ''), color(chalk.bold(resourceName)), logicalId, reasonColor(chalk.bold(event.ResourceStatusReason ? event.ResourceStatusReason : '')), reasonColor(stackTrace)));
this.lastPrintTime = Date.now();
}
/**
* Report the current progress as a [34/42] string, or just [34] if the total is unknown
*/
progress() {
if (this.resourcesTotal == null) {
// Don't have total, show simple count and hope the human knows
return padLeft(3, util.format('%s', this.resourcesDone)); // max 500 resources
}
return util.format('%s/%s', padLeft(this.resourceDigits, this.resourcesDone.toString()), padLeft(this.resourceDigits, this.resourcesTotal != null ? this.resourcesTotal.toString() : '?'));
}
/**
* If some resources are taking a while to create, notify the user about what's currently in progress
*/
printInProgress() {
if (Date.now() < this.lastPrintTime + this.inProgressDelay) {
return;
}
if (Object.keys(this.resourcesInProgress).length > 0) {
(0, logging_1.info)(util.format('%s Currently in progress: %s', this.progress(), chalk.bold(Object.keys(this.resourcesInProgress).join(', '))));
}
// We cheat a bit here. To prevent printInProgress() from repeatedly triggering,
// we set the timestamp into the future. It will be reset whenever a regular print
// occurs, after which we can be triggered again.
this.lastPrintTime = +Infinity;
}
}
exports.HistoryActivityPrinter = HistoryActivityPrinter;
/**
* Activity Printer which shows the resources currently being updated
*
* It will continuously reupdate the terminal and show only the resources
* that are currently being updated, in addition to a progress bar which
* shows how far along the deployment is.
*
* Resources that have failed will always be shown, and will be recapitulated
* along with their stack trace when the monitoring ends.
*
* Resources that failed deployment because they have been cancelled are
* not included.
*/
class CurrentActivityPrinter extends ActivityPrinterBase {
constructor(props) {
super(props);
/**
* This looks very disorienting sleeping for 5 seconds. Update quicker.
*/
this.updateSleep = 2000;
this.oldLogThreshold = cli_io_host_1.CliIoHost.instance().logLevel;
this.stream = props.stream;
this.block = new display_1.RewritableBlock(this.stream);
}
print() {
const lines = [];
// Add a progress bar at the top
const progressWidth = Math.max(Math.min((this.block.width ?? 80) - PROGRESSBAR_EXTRA_SPACE - 1, MAX_PROGRESSBAR_WIDTH), MIN_PROGRESSBAR_WIDTH);
const prog = this.progressBar(progressWidth);
if (prog) {
lines.push(' ' + prog, '');
}
// Normally we'd only print "resources in progress", but it's also useful
// to keep an eye on the failures and know about the specific errors asquickly
// as possible (while the stack is still rolling back), so add those in.
const toPrint = [...this.failures, ...Object.values(this.resourcesInProgress)];
toPrint.sort((a, b) => a.event.Timestamp.getTime() - b.event.Timestamp.getTime());
lines.push(...toPrint.map((res) => {
const color = colorFromStatusActivity(res.event.ResourceStatus);
const resourceName = res.metadata?.constructPath ?? res.event.LogicalResourceId ?? '';
return util.format('%s | %s | %s | %s%s', padLeft(TIMESTAMP_WIDTH, new Date(res.event.Timestamp).toLocaleTimeString()), color(padRight(STATUS_WIDTH, (res.event.ResourceStatus || '').slice(0, STATUS_WIDTH))), padRight(this.props.resourceTypeColumnWidth, res.event.ResourceType || ''), color(chalk.bold(shorten(40, resourceName))), this.failureReasonOnNextLine(res));
}));
this.block.displayLines(lines);
}
start() {
// Need to prevent the waiter from printing 'stack not stable' every 5 seconds, it messes
// with the output calculations.
this.oldLogThreshold = cli_io_host_1.CliIoHost.instance().logLevel;
cli_io_host_1.CliIoHost.instance().logLevel = 'info';
}
stop() {
cli_io_host_1.CliIoHost.instance().logLevel = this.oldLogThreshold;
// Print failures at the end
const lines = new Array();
for (const failure of this.failures) {
// Root stack failures are not interesting
if (failure.isStackEvent) {
continue;
}
lines.push(util.format(chalk.red('%s | %s | %s | %s%s') + '\n', padLeft(TIMESTAMP_WIDTH, new Date(failure.event.Timestamp).toLocaleTimeString()), padRight(STATUS_WIDTH, (failure.event.ResourceStatus || '').slice(0, STATUS_WIDTH)), padRight(this.props.resourceTypeColumnWidth, failure.event.ResourceType || ''), shorten(40, failure.event.LogicalResourceId ?? ''), this.failureReasonOnNextLine(failure)));
const trace = failure.metadata?.entry?.trace;
if (trace) {
lines.push(chalk.red(`\t${trace.join('\n\t\\_ ')}\n`));
}
}
// Display in the same block space, otherwise we're going to have silly empty lines.
this.block.displayLines(lines);
this.block.removeEmptyLines();
}
progressBar(width) {
if (!this.resourcesTotal) {
return '';
}
const fraction = Math.min(this.resourcesDone / this.resourcesTotal, 1);
const innerWidth = Math.max(1, width - 2);
const chars = innerWidth * fraction;
const remainder = chars - Math.floor(chars);
const fullChars = FULL_BLOCK.repeat(Math.floor(chars));
const partialChar = PARTIAL_BLOCK[Math.floor(remainder * PARTIAL_BLOCK.length)];
const filler = '·'.repeat(innerWidth - Math.floor(chars) - (partialChar ? 1 : 0));
const color = this.rollingBack ? chalk.yellow : chalk.green;
return '[' + color(fullChars + partialChar) + filler + `] (${this.resourcesDone}/${this.resourcesTotal})`;
}
failureReasonOnNextLine(activity) {
return hasErrorMessage(activity.event.ResourceStatus ?? '')
? `\n${' '.repeat(TIMESTAMP_WIDTH + STATUS_WIDTH + 6)}${chalk.red(this.failureReason(activity) ?? '')}`
: '';
}
}
exports.CurrentActivityPrinter = CurrentActivityPrinter;
const FULL_BLOCK = '█';
const PARTIAL_BLOCK = ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉'];
const MAX_PROGRESSBAR_WIDTH = 60;
const MIN_PROGRESSBAR_WIDTH = 10;
const PROGRESSBAR_EXTRA_SPACE = 2 /* leading spaces */ + 2 /* brackets */ + 4 /* progress number decoration */ + 6; /* 2 progress numbers up to 999 */
function hasErrorMessage(status) {
return status.endsWith('_FAILED') || status === 'ROLLBACK_IN_PROGRESS' || status === 'UPDATE_ROLLBACK_IN_PROGRESS';
}
function colorFromStatusResult(status) {
if (!status) {
return chalk.reset;
}
if (status.indexOf('FAILED') !== -1) {
return chalk.red;
}
if (status.indexOf('ROLLBACK') !== -1) {
return chalk.yellow;
}
if (status.indexOf('COMPLETE') !== -1) {
return chalk.green;
}
return chalk.reset;
}
function colorFromStatusActivity(status) {
if (!status) {
return chalk.reset;
}
if (status.endsWith('_FAILED')) {
return chalk.red;
}
if (status.startsWith('CREATE_') || status.startsWith('UPDATE_') || status.startsWith('IMPORT_')) {
return chalk.green;
}
// For stacks, it may also be 'UPDDATE_ROLLBACK_IN_PROGRESS'
if (status.indexOf('ROLLBACK_') !== -1) {
return chalk.yellow;
}
if (status.startsWith('DELETE_')) {
return chalk.yellow;
}
return chalk.reset;
}
function shorten(maxWidth, p) {
if (p.length <= maxWidth) {
return p;
}
const half = Math.floor((maxWidth - 3) / 2);
return p.slice(0, half) + '...' + p.slice(-half);
}
const TIMESTAMP_WIDTH = 12;
const STATUS_WIDTH = 20;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stYWN0aXZpdHktbW9uaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInN0YWNrLWFjdGl2aXR5LW1vbml0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTZCO0FBQzdCLDBFQUErRjtBQUUvRiwrQkFBK0I7QUFDL0IsNkRBQXVFO0FBQ3ZFLDhDQUErQztBQUMvQyw4REFBeUU7QUFFekUsd0NBQTZDO0FBVzdDOztHQUVHO0FBQ0gsSUFBWSxxQkFVWDtBQVZELFdBQVkscUJBQXFCO0lBQy9COztPQUVHO0lBQ0gsb0NBQVcsQ0FBQTtJQUVYOztPQUVHO0lBQ0gsMENBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQVZXLHFCQUFxQixxQ0FBckIscUJBQXFCLFFBVWhDO0FBc0RELE1BQWEsb0JBQW9CO0lBQy9COztPQUVHO0lBQ0ksTUFBTSxDQUFDLGtCQUFrQixDQUM5QixHQUEwQixFQUMxQixTQUFpQixFQUNqQixhQUEwQyxFQUMxQyxVQUFtQyxFQUFFO1FBRXJDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFFNUQsTUFBTSxLQUFLLEdBQWlCO1lBQzFCLHVCQUF1QixFQUFFLHlCQUF5QixDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7WUFDMUUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO1lBQ3RDLE1BQU07U0FDUCxDQUFDO1FBRUYsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLENBQUM7UUFDL0MsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFFBQVEsSUFBSSxNQUFNLENBQUM7UUFDM0MsaUZBQWlGO1FBQ2pGLDREQUE0RDtRQUM1RCwwRkFBMEY7UUFDMUYsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsT0FB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QUN0QixDQUFDO0lBQ0QsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDakMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUM7QUFDckIsQ0FBQztBQUVELFNBQVMsT0FBTyxDQUFDLFFBQWdCLEVBQUUsQ0FBUztJQUMxQyxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksUUFBUSxFQUFFLENBQUM7UUFDekIsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBQ0QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM1QyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQUVELE1BQU0sZUFBZSxHQUFHLEVBQUUsQ0FBQztBQUMzQixNQUFNLFlBQVksR0FBRyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB1dGlsIGZyb20gJ3V0aWwnO1xuaW1wb3J0IHsgQXJ0aWZhY3RNZXRhZGF0YUVudHJ5VHlwZSwgdHlwZSBNZXRhZGF0YUVudHJ5IH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCB0eXBlIHsgQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0IH0gZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCB7IFJlc291cmNlRXZlbnQsIFN0YWNrRXZlbnRQb2xsZXIgfSBmcm9tICcuL3N0YWNrLWV2ZW50LXBvbGxlcic7XG5pbXBvcnQgeyBlcnJvciwgaW5mbyB9IGZyb20gJy4uLy4uLy4uL2xvZ2dpbmcnO1xuaW1wb3J0IHsgQ2xpSW9Ib3N0LCBJb01lc3NhZ2VMZXZlbCB9IGZyb20gJy4uLy4uLy4uL3Rvb2xraXQvY2xpLWlvLWhvc3QnO1xuaW1wb3J0IHR5cGUgeyBJQ2xvdWRGb3JtYXRpb25DbGllbnQgfSBmcm9tICcuLi8uLi9hd3MtYXV0aCc7XG5pbXBvcnQgeyBSZXdyaXRhYmxlQmxvY2sgfSBmcm9tICcuLi9kaXNwbGF5JztcblxuZXhwb3J0IGludGVyZmFjZSBTdGFja0FjdGl2aXR5IGV4dGVuZHMgUmVzb3VyY2VFdmVudCB7XG4gIHJlYWRvbmx5IG1ldGFkYXRhPzogUmVzb3VyY2VNZXRhZGF0YTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvdXJjZU1ldGFkYXRhIHtcbiAgZW50cnk6IE1ldGFkYXRhRW50cnk7XG4gIGNvbnN0cnVjdFBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdXBwb3J0ZWQgZGlzcGxheSBtb2RlcyBmb3Igc3RhY2sgZGVwbG95bWVudCBhY3Rpdml0eVxuICovXG5leHBvcnQgZW51bSBTdGFja0FjdGl2aXR5UHJvZ3Jlc3Mge1xuICAvKipcbiAgICogRGlzcGxheXMgYSBwcm9ncmVzcyBiYXIgd2l0aCBvbmx5IHRoZSBldmVudHMgZm9yIHRoZSByZXNvdXJjZSBjdXJyZW50bHkgYmVpbmcgZGVwbG95ZWRcbiAgICovXG4gIEJBUiA9ICdiYXInLFxuXG4gIC8qKlxuICAgKiBEaXNwbGF5cyBjb21wbGV0ZSBoaXN0b3J5IHdpdGggYWxsIENsb3VkRm9ybWF0aW9uIHN0YWNrIGV2ZW50c1xuICAgKi9cbiAgRVZFTlRTID0gJ2V2ZW50cycsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2l0aERlZmF1bHRQcmludGVyUHJvcHMge1xuICAvKipcbiAgICogVG90YWwgbnVtYmVyIG9mIHJlc291cmNlcyB0byB1cGRhdGVcbiAgICpcbiAgICogVXNlZCB0byBjYWxjdWxhdGUgYSBwcm9ncmVzcyBiYXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcHJvZ3Jlc3MgcmVwb3J0aW5nLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VzVG90YWw/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBsb2cgbGV2ZWwgdGhhdCB3YXMgcmVxdWVzdGVkIGluIHRoZSBDTElcbiAgICpcbiAgICogSWYgdmVyYm9zZSBvciB0cmFjZSBpcyByZXF1ZXN0ZWQsIHdlJ2xsIGFsd2F5cyB1c2UgdGhlIGZ1bGwgaGlzdG9yeSBwcmludGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFVzZSB2YWx1ZSBmcm9tIGxvZ2dpbmcubG9nTGV2ZWxcbiAgICovXG4gIHJlYWRvbmx5IGxvZ0