UNPKG

49.5 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.Alarm = exports.TreatMissingData = exports.ComparisonOperator = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const core_1 = require("@aws-cdk/core");
8const alarm_base_1 = require("./alarm-base");
9const cloudwatch_generated_1 = require("./cloudwatch.generated");
10const metric_util_1 = require("./private/metric-util");
11const object_1 = require("./private/object");
12const rendering_1 = require("./private/rendering");
13const statistic_1 = require("./private/statistic");
14/**
15 * Comparison operator for evaluating alarms
16 */
17var ComparisonOperator;
18(function (ComparisonOperator) {
19 /**
20 * Specified statistic is greater than or equal to the threshold
21 */
22 ComparisonOperator["GREATER_THAN_OR_EQUAL_TO_THRESHOLD"] = "GreaterThanOrEqualToThreshold";
23 /**
24 * Specified statistic is strictly greater than the threshold
25 */
26 ComparisonOperator["GREATER_THAN_THRESHOLD"] = "GreaterThanThreshold";
27 /**
28 * Specified statistic is strictly less than the threshold
29 */
30 ComparisonOperator["LESS_THAN_THRESHOLD"] = "LessThanThreshold";
31 /**
32 * Specified statistic is less than or equal to the threshold.
33 */
34 ComparisonOperator["LESS_THAN_OR_EQUAL_TO_THRESHOLD"] = "LessThanOrEqualToThreshold";
35 /**
36 * Specified statistic is lower than or greater than the anomaly model band.
37 * Used only for alarms based on anomaly detection models
38 */
39 ComparisonOperator["LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD"] = "LessThanLowerOrGreaterThanUpperThreshold";
40 /**
41 * Specified statistic is greater than the anomaly model band.
42 * Used only for alarms based on anomaly detection models
43 */
44 ComparisonOperator["GREATER_THAN_UPPER_THRESHOLD"] = "GreaterThanUpperThreshold";
45 /**
46 * Specified statistic is lower than the anomaly model band.
47 * Used only for alarms based on anomaly detection models
48 */
49 ComparisonOperator["LESS_THAN_LOWER_THRESHOLD"] = "LessThanLowerThreshold";
50})(ComparisonOperator = exports.ComparisonOperator || (exports.ComparisonOperator = {}));
51const OPERATOR_SYMBOLS = {
52 GreaterThanOrEqualToThreshold: '>=',
53 GreaterThanThreshold: '>',
54 LessThanThreshold: '<',
55 LessThanOrEqualToThreshold: '<=',
56};
57/**
58 * Specify how missing data points are treated during alarm evaluation
59 */
60var TreatMissingData;
61(function (TreatMissingData) {
62 /**
63 * Missing data points are treated as breaching the threshold
64 */
65 TreatMissingData["BREACHING"] = "breaching";
66 /**
67 * Missing data points are treated as being within the threshold
68 */
69 TreatMissingData["NOT_BREACHING"] = "notBreaching";
70 /**
71 * The current alarm state is maintained
72 */
73 TreatMissingData["IGNORE"] = "ignore";
74 /**
75 * The alarm does not consider missing data points when evaluating whether to change state
76 */
77 TreatMissingData["MISSING"] = "missing";
78})(TreatMissingData = exports.TreatMissingData || (exports.TreatMissingData = {}));
79/**
80 * An alarm on a CloudWatch metric
81 */
82class Alarm extends alarm_base_1.AlarmBase {
83 constructor(scope, id, props) {
84 var _b;
85 super(scope, id, {
86 physicalName: props.alarmName,
87 });
88 try {
89 jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_AlarmProps(props);
90 }
91 catch (error) {
92 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
93 Error.captureStackTrace(error, this.constructor);
94 }
95 throw error;
96 }
97 const comparisonOperator = props.comparisonOperator || ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD;
98 // Render metric, process potential overrides from the alarm
99 // (It would be preferable if the statistic etc. was worked into the metric,
100 // but hey we're allowing overrides...)
101 const metricProps = this.renderMetric(props.metric);
102 if (props.period) {
103 metricProps.period = props.period.toSeconds();
104 }
105 if (props.statistic) {
106 // Will overwrite both fields if present
107 Object.assign(metricProps, {
108 statistic: renderIfSimpleStatistic(props.statistic),
109 extendedStatistic: renderIfExtendedStatistic(props.statistic),
110 });
111 }
112 const alarm = new cloudwatch_generated_1.CfnAlarm(this, 'Resource', {
113 // Meta
114 alarmDescription: props.alarmDescription,
115 alarmName: this.physicalName,
116 // Evaluation
117 comparisonOperator,
118 threshold: props.threshold,
119 datapointsToAlarm: props.datapointsToAlarm,
120 evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile,
121 evaluationPeriods: props.evaluationPeriods,
122 treatMissingData: props.treatMissingData,
123 // Actions
124 actionsEnabled: props.actionsEnabled,
125 alarmActions: core_1.Lazy.list({ produce: () => this.alarmActionArns }),
126 insufficientDataActions: core_1.Lazy.list({ produce: (() => this.insufficientDataActionArns) }),
127 okActions: core_1.Lazy.list({ produce: () => this.okActionArns }),
128 // Metric
129 ...metricProps,
130 });
131 this.alarmArn = this.getResourceArnAttribute(alarm.attrArn, {
132 service: 'cloudwatch',
133 resource: 'alarm',
134 resourceName: this.physicalName,
135 arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME,
136 });
137 this.alarmName = this.getResourceNameAttribute(alarm.ref);
138 this.metric = props.metric;
139 const datapoints = props.datapointsToAlarm || props.evaluationPeriods;
140 this.annotation = {
141 // eslint-disable-next-line max-len
142 label: `${this.metric} ${OPERATOR_SYMBOLS[comparisonOperator]} ${props.threshold} for ${datapoints} datapoints within ${describePeriod(props.evaluationPeriods * metric_util_1.metricPeriod(props.metric).toSeconds())}`,
143 value: props.threshold,
144 };
145 for (const w of (_b = this.metric.warnings) !== null && _b !== void 0 ? _b : []) {
146 core_1.Annotations.of(this).addWarning(w);
147 }
148 }
149 /**
150 * Import an existing CloudWatch alarm provided an ARN
151 *
152 * @param scope The parent creating construct (usually `this`).
153 * @param id The construct's name
154 * @param alarmArn Alarm ARN (i.e. arn:aws:cloudwatch:<region>:<account-id>:alarm:Foo)
155 */
156 static fromAlarmArn(scope, id, alarmArn) {
157 class Import extends alarm_base_1.AlarmBase {
158 constructor() {
159 super(...arguments);
160 this.alarmArn = alarmArn;
161 this.alarmName = core_1.Stack.of(scope).splitArn(alarmArn, core_1.ArnFormat.COLON_RESOURCE_NAME).resourceName;
162 }
163 }
164 return new Import(scope, id);
165 }
166 /**
167 * Turn this alarm into a horizontal annotation
168 *
169 * This is useful if you want to represent an Alarm in a non-AlarmWidget.
170 * An `AlarmWidget` can directly show an alarm, but it can only show a
171 * single alarm and no other metrics. Instead, you can convert the alarm to
172 * a HorizontalAnnotation and add it as an annotation to another graph.
173 *
174 * This might be useful if:
175 *
176 * - You want to show multiple alarms inside a single graph, for example if
177 * you have both a "small margin/long period" alarm as well as a
178 * "large margin/short period" alarm.
179 *
180 * - You want to show an Alarm line in a graph with multiple metrics in it.
181 */
182 toAnnotation() {
183 return this.annotation;
184 }
185 /**
186 * Trigger this action if the alarm fires
187 *
188 * Typically the ARN of an SNS topic or ARN of an AutoScaling policy.
189 */
190 addAlarmAction(...actions) {
191 try {
192 jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_IAlarmAction(actions);
193 }
194 catch (error) {
195 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
196 Error.captureStackTrace(error, this.addAlarmAction);
197 }
198 throw error;
199 }
200 if (this.alarmActionArns === undefined) {
201 this.alarmActionArns = [];
202 }
203 this.alarmActionArns.push(...actions.map(a => this.validateActionArn(a.bind(this, this).alarmActionArn)));
204 }
205 validateActionArn(actionArn) {
206 var _b, _c, _d;
207 const ec2ActionsRegexp = /arn:aws[a-z0-9-]*:automate:[a-z|\d|-]+:ec2:[a-z]+/;
208 if (ec2ActionsRegexp.test(actionArn)) {
209 // Check per-instance metric
210 const metricConfig = this.metric.toMetricConfig();
211 if (((_c = (_b = metricConfig.metricStat) === null || _b === void 0 ? void 0 : _b.dimensions) === null || _c === void 0 ? void 0 : _c.length) != 1 || ((_d = metricConfig.metricStat) === null || _d === void 0 ? void 0 : _d.dimensions[0].name) != 'InstanceId') {
212 throw new Error(`EC2 alarm actions requires an EC2 Per-Instance Metric. (${JSON.stringify(metricConfig)} does not have an 'InstanceId' dimension)`);
213 }
214 }
215 return actionArn;
216 }
217 renderMetric(metric) {
218 const self = this;
219 return metric_util_1.dispatchMetric(metric, {
220 withStat(stat, conf) {
221 var _b, _c, _d;
222 self.validateMetricStat(stat, metric);
223 const canRenderAsLegacyMetric = ((_b = conf.renderingProperties) === null || _b === void 0 ? void 0 : _b.label) == undefined && !self.requiresAccountId(stat);
224 // Do this to disturb existing templates as little as possible
225 if (canRenderAsLegacyMetric) {
226 return object_1.dropUndefined({
227 dimensions: stat.dimensions,
228 namespace: stat.namespace,
229 metricName: stat.metricName,
230 period: (_c = stat.period) === null || _c === void 0 ? void 0 : _c.toSeconds(),
231 statistic: renderIfSimpleStatistic(stat.statistic),
232 extendedStatistic: renderIfExtendedStatistic(stat.statistic),
233 unit: stat.unitFilter,
234 });
235 }
236 return {
237 metrics: [
238 {
239 metricStat: {
240 metric: {
241 metricName: stat.metricName,
242 namespace: stat.namespace,
243 dimensions: stat.dimensions,
244 },
245 period: stat.period.toSeconds(),
246 stat: stat.statistic,
247 unit: stat.unitFilter,
248 },
249 id: 'm1',
250 accountId: self.requiresAccountId(stat) ? stat.account : undefined,
251 label: (_d = conf.renderingProperties) === null || _d === void 0 ? void 0 : _d.label,
252 returnData: true,
253 },
254 ],
255 };
256 },
257 withExpression() {
258 // Expand the math expression metric into a set
259 const mset = new rendering_1.MetricSet();
260 mset.addTopLevel(true, metric);
261 let eid = 0;
262 function uniqueMetricId() {
263 return `expr_${++eid}`;
264 }
265 return {
266 metrics: mset.entries.map(entry => metric_util_1.dispatchMetric(entry.metric, {
267 withStat(stat, conf) {
268 var _b;
269 self.validateMetricStat(stat, entry.metric);
270 return {
271 metricStat: {
272 metric: {
273 metricName: stat.metricName,
274 namespace: stat.namespace,
275 dimensions: stat.dimensions,
276 },
277 period: stat.period.toSeconds(),
278 stat: stat.statistic,
279 unit: stat.unitFilter,
280 },
281 id: entry.id || uniqueMetricId(),
282 accountId: self.requiresAccountId(stat) ? stat.account : undefined,
283 label: (_b = conf.renderingProperties) === null || _b === void 0 ? void 0 : _b.label,
284 returnData: entry.tag ? undefined : false,
285 };
286 },
287 withExpression(expr, conf) {
288 var _b;
289 const hasSubmetrics = mathExprHasSubmetrics(expr);
290 if (hasSubmetrics) {
291 assertSubmetricsCount(expr);
292 }
293 self.validateMetricExpression(expr);
294 return {
295 expression: expr.expression,
296 id: entry.id || uniqueMetricId(),
297 label: (_b = conf.renderingProperties) === null || _b === void 0 ? void 0 : _b.label,
298 period: hasSubmetrics ? undefined : expr.period,
299 returnData: entry.tag ? undefined : false,
300 };
301 },
302 })),
303 };
304 },
305 });
306 }
307 /**
308 * Validate that if a region is in the given stat config, they match the Alarm
309 */
310 validateMetricStat(stat, metric) {
311 const stack = core_1.Stack.of(this);
312 if (definitelyDifferent(stat.region, stack.region)) {
313 throw new Error(`Cannot create an Alarm in region '${stack.region}' based on metric '${metric}' in '${stat.region}'`);
314 }
315 }
316 /**
317 * Validates that the expression config does not specify searchAccount or searchRegion props
318 * as search expressions are not supported by Alarms.
319 */
320 validateMetricExpression(expr) {
321 if (expr.searchAccount !== undefined || expr.searchRegion !== undefined) {
322 throw new Error('Cannot create an Alarm based on a MathExpression which specifies a searchAccount or searchRegion');
323 }
324 }
325 /**
326 * Determine if the accountId property should be included in the metric.
327 */
328 requiresAccountId(stat) {
329 const stackAccount = core_1.Stack.of(this).account;
330 // if stat.account is undefined, it's by definition in the same account
331 if (stat.account === undefined) {
332 return false;
333 }
334 // Return true if they're different. The ACCOUNT_ID token is interned
335 // so will always have the same string value (and even if we guess wrong
336 // it will still work).
337 return stackAccount !== stat.account;
338 }
339}
340exports.Alarm = Alarm;
341_a = JSII_RTTI_SYMBOL_1;
342Alarm[_a] = { fqn: "@aws-cdk/aws-cloudwatch.Alarm", version: "1.157.0" };
343function definitelyDifferent(x, y) {
344 return x && !core_1.Token.isUnresolved(y) && x !== y;
345}
346/**
347 * Return a human readable string for this period
348 *
349 * We know the seconds are always one of a handful of allowed values.
350 */
351function describePeriod(seconds) {
352 if (seconds === 60) {
353 return '1 minute';
354 }
355 if (seconds === 1) {
356 return '1 second';
357 }
358 if (seconds > 60) {
359 return (seconds / 60) + ' minutes';
360 }
361 return seconds + ' seconds';
362}
363function renderIfSimpleStatistic(statistic) {
364 if (statistic === undefined) {
365 return undefined;
366 }
367 const parsed = statistic_1.parseStatistic(statistic);
368 if (parsed.type === 'simple') {
369 return parsed.statistic;
370 }
371 return undefined;
372}
373function renderIfExtendedStatistic(statistic) {
374 if (statistic === undefined) {
375 return undefined;
376 }
377 const parsed = statistic_1.parseStatistic(statistic);
378 if (parsed.type === 'percentile') {
379 // Already percentile. Avoid parsing because we might get into
380 // floating point rounding issues, return as-is but lowercase the p.
381 return statistic.toLowerCase();
382 }
383 else if (parsed.type === 'generic') {
384 return statistic;
385 }
386 return undefined;
387}
388function mathExprHasSubmetrics(expr) {
389 return Object.keys(expr.usingMetrics).length > 0;
390}
391function assertSubmetricsCount(expr) {
392 if (Object.keys(expr.usingMetrics).length > 10) {
393 // https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-on-metric-math-expressions
394 throw new Error('Alarms on math expressions cannot contain more than 10 individual metrics');
395 }
396 ;
397}
398//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxhcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJhbGFybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3Q0FBMkU7QUFHM0UsNkNBQWlEO0FBQ2pELGlFQUFpRTtBQUlqRSx1REFBcUU7QUFDckUsNkNBQWlEO0FBQ2pELG1EQUFnRDtBQUNoRCxtREFBcUQ7QUFlckQ7O0dBRUc7QUFDSCxJQUFZLGtCQXNDWDtBQXRDRCxXQUFZLGtCQUFrQjtJQUM1Qjs7T0FFRztJQUNILDBGQUFvRSxDQUFBO0lBRXBFOztPQUVHO0lBQ0gscUVBQStDLENBQUE7SUFFL0M7O09BRUc7SUFDSCwrREFBeUMsQ0FBQTtJQUV6Qzs7T0FFRztJQUNILG9GQUE4RCxDQUFBO0lBRTlEOzs7T0FHRztJQUNILGtIQUE0RixDQUFBO0lBRTVGOzs7T0FHRztJQUNILGdGQUEwRCxDQUFBO0lBRTFEOzs7T0FHRztJQUNILDBFQUFvRCxDQUFBO0FBQ3RELENBQUMsRUF0Q1csa0JBQWtCLEdBQWxCLDBCQUFrQixLQUFsQiwwQkFBa0IsUUFzQzdCO0FBRUQsTUFBTSxnQkFBZ0IsR0FBNEI7SUFDaEQsNkJBQTZCLEVBQUUsSUFBSTtJQUNuQyxvQkFBb0IsRUFBRSxHQUFHO0lBQ3pCLGlCQUFpQixFQUFFLEdBQUc7SUFDdEIsMEJBQTBCLEVBQUUsSUFBSTtDQUNqQyxDQUFDO0FBRUY7O0dBRUc7QUFDSCxJQUFZLGdCQW9CWDtBQXBCRCxXQUFZLGdCQUFnQjtJQUMxQjs7T0FFRztJQUNILDJDQUF1QixDQUFBO0lBRXZCOztPQUVHO0lBQ0gsa0RBQThCLENBQUE7SUFFOUI7O09BRUc7SUFDSCxxQ0FBaUIsQ0FBQTtJQUVqQjs7T0FFRztJQUNILHVDQUFtQixDQUFBO0FBQ3JCLENBQUMsRUFwQlcsZ0JBQWdCLEdBQWhCLHdCQUFnQixLQUFoQix3QkFBZ0IsUUFvQjNCO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLEtBQU0sU0FBUSxzQkFBUztJQXlDbEMsWUFBWSxLQUFnQixF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QUFDO0FBQ25CLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLFNBQWtCO0lBQ25ELElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTtRQUFFLE9BQU8sU0FBUyxDQUFDO0tBQUU7SUFFbEQsTUFBTSxNQUFNLEdBQUcsMEJBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN6QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFO1FBQ2hDLDhEQUE4RDtRQUM5RCxvRUFBb0U7UUFDcEUsT0FBTyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7S0FDaEM7U0FBTSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFO1FBQ3BDLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBRUQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVELFNBQVMscUJBQXFCLENBQUMsSUFBNEI7SUFDekQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxTQUFTLHFCQUFxQixDQUFDLElBQTRCO0lBQ3pELElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRTtRQUM5Qyw0SEFBNEg7UUFDNUgsTUFBTSxJQUFJLEtBQUssQ0FBQywyRUFBMkUsQ0FBQyxDQUFDO0tBQzlGO0lBQUEsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBcm5Gb3JtYXQsIExhenksIFN0YWNrLCBUb2tlbiwgQW5ub3RhdGlvbnMgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgSUFsYXJtQWN0aW9uIH0gZnJvbSAnLi9hbGFybS1hY3Rpb24nO1xuaW1wb3J0IHsgQWxhcm1CYXNlLCBJQWxhcm0gfSBmcm9tICcuL2FsYXJtLWJhc2UnO1xuaW1wb3J0IHsgQ2ZuQWxhcm0sIENmbkFsYXJtUHJvcHMgfSBmcm9tICcuL2Nsb3Vkd2F0Y2guZ2VuZXJhdGVkJztcbmltcG9ydCB7IEhvcml6b250YWxBbm5vdGF0aW9uIH0gZnJvbSAnLi9ncmFwaCc7XG5pbXBvcnQgeyBDcmVhdGVBbGFybU9wdGlvbnMgfSBmcm9tICcuL21ldHJpYyc7XG5pbXBvcnQgeyBJTWV0cmljLCBNZXRyaWNFeHByZXNzaW9uQ29uZmlnLCBNZXRyaWNTdGF0Q29uZmlnIH0gZnJvbSAnLi9tZXRyaWMtdHlwZXMnO1xuaW1wb3J0IHsgZGlzcGF0Y2hNZXRyaWMsIG1ldHJpY1BlcmlvZCB9IGZyb20gJy4vcHJpdmF0ZS9tZXRyaWMtdXRpbCc7XG5pbXBvcnQgeyBkcm9wVW5kZWZpbmVkIH0gZnJvbSAnLi9wcml2YXRlL29iamVjdCc7XG5pbXBvcnQgeyBNZXRyaWNTZXQgfSBmcm9tICcuL3ByaXZhdGUvcmVuZGVyaW5nJztcbmltcG9ydCB7IHBhcnNlU3RhdGlzdGljIH0gZnJvbSAnLi9wcml2YXRlL3N0YXRpc3RpYyc7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgQWxhcm1zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWxhcm1Qcm9wcyBleHRlbmRzIENyZWF0ZUFsYXJtT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbWV0cmljIHRvIGFkZCB0aGUgYWxhcm0gb25cbiAgICpcbiAgICogTWV0cmljIG9iamVjdHMgY2FuIGJlIG9idGFpbmVkIGZyb20gbW9zdCByZXNvdXJjZXMsIG9yIHlvdSBjYW4gY29uc3RydWN0XG4gICAqIGN1c3RvbSBNZXRyaWMgb2JqZWN0cyBieSBpbnN0YW50aWF0aW5nIG9uZS5cbiAgICovXG4gIHJlYWRvbmx5IG1ldHJpYzogSU1ldHJpYztcbn1cblxuLyoqXG4gKiBDb21wYXJpc29uIG9wZXJhdG9yIGZvciBldmFsdWF0aW5nIGFsYXJtc1xuICovXG5leHBvcnQgZW51bSBDb21wYXJpc29uT3BlcmF0b3Ige1xuICAvKipcbiAgICogU3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHRocmVzaG9sZFxuICAgKi9cbiAgR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCA9ICdHcmVhdGVyVGhhbk9yRXF1YWxUb1RocmVzaG9sZCcsXG5cbiAgLyoqXG4gICAqIFNwZWNpZmllZCBzdGF0aXN0aWMgaXMgc3RyaWN0bHkgZ3JlYXRlciB0aGFuIHRoZSB0aHJlc2hvbGRcbiAgICovXG4gIEdSRUFURVJfVEhBTl9USFJFU0hPTEQgPSAnR3JlYXRlclRoYW5UaHJlc2hvbGQnLFxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZWQgc3RhdGlzdGljIGlzIHN0cmljdGx5IGxlc3MgdGhhbiB0aGUgdGhyZXNob2xkXG4gICAqL1xuICBMRVNTX1RIQU5fVEhSRVNIT0xEID0gJ0xlc3NUaGFuVGhyZXNob2xkJyxcblxuICAvKipcbiAgICogU3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHRocmVzaG9sZC5cbiAgICovXG4gIExFU1NfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQgPSAnTGVzc1RoYW5PckVxdWFsVG9UaHJlc2hvbGQnLFxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZWQgc3RhdGlzdGljIGlzIGxvd2VyIHRoYW4gb3IgZ3JlYXRlciB0aGFuIHRoZSBhbm9tYWx5IG1vZGVsIGJhbmQuXG4gICAqIFVzZWQgb25seSBmb3IgYWxhcm1zIGJhc2VkIG9uIGFub21hbHkgZGV0ZWN0aW9uIG1vZGVsc1xuICAgKi9cbiAgTEVTU19USEFOX0xPV0VSX09SX0dSRUFURVJfVEhBTl9VUFBFUl9USFJFU0hPTEQgPSAnTGVzc1RoYW5Mb3dlck9yR3JlYXRlclRoYW5VcHBlclRocmVzaG9sZCcsXG5cbiAgLyoqXG4gICAqIFNwZWNpZmllZCBzdGF0aXN0aWMgaXMgZ3JlYXRlciB0aGFuIHRoZSBhbm9tYWx5IG1vZGVsIGJhbmQuXG4gICAqIFVzZWQgb25seSBmb3IgYWxhcm1zIGJhc2VkIG9uIGFub21hbHkgZGV0ZWN0aW9uIG1vZGVsc1xuICAgKi9cbiAgR1JFQVRFUl9USEFOX1VQUEVSX1RIUkVTSE9MRCA9ICdHcmVhdGVyVGhhblVwcGVyVGhyZXNob2xkJyxcblxuICAvKipcbiAgICogU3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBsb3dlciB0aGFuIHRoZSBhbm9tYWx5IG1vZGVsIGJhbmQuXG4gICAqIFVzZWQgb25seSBmb3IgYWxhcm1zIGJhc2VkIG9uIGFub21hbHkgZGV0ZWN0aW9uIG1vZGVsc1xuICAgKi9cbiAgTEVTU19USEFOX0xPV0VSX1RIUkVTSE9MRCA9ICdMZXNzVGhhbkxvd2VyVGhyZXNob2xkJyxcbn1cblxuY29uc3QgT1BFUkFUT1JfU1lNQk9MUzoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7XG4gIEdyZWF0ZXJUaGFuT3JFcXVhbFRvVGhyZXNob2xkOiAnPj0nLFxuICBHcmVhdGVyVGhhblRocmVzaG9sZDogJz4nLFxuICBMZXNzVGhhblRocmVzaG9sZDogJzwnLFxuICBMZXNzVGhhbk9yRXF1YWxUb1RocmVzaG9sZDogJzw9Jyxcbn07XG5cbi8qKlxuICogU3BlY2lmeSBob3cgbWlzc2luZyBkYXRhIHBvaW50cyBhcmUgdHJlYXRlZCBkdXJpbmcgYWxhcm0gZXZhbHVhdGlvblxuICovXG5leHBvcnQgZW51bSBUcmVhdE1pc3NpbmdEYXRhIHtcbiAgLyoqXG4gICAqIE1pc3NpbmcgZGF0YSBwb2ludHMgYXJlIHRyZWF0ZWQgYXMgYnJlYWNoaW5nIHRoZSB0aHJlc2hvbGRcbiAgICovXG4gIEJSRUFDSElORyA9ICdicmVhY2hpbmcnLFxuXG4gIC8qKlxuICAgKiBNaXNzaW5nIGRhdGEgcG9pbnRzIGFyZSB0cmVhdGVkIGFzIGJlaW5nIHdpdGhpbiB0aGUgdGhyZXNob2xkXG4gICAqL1xuICBOT1RfQlJFQUNISU5HID0gJ25vdEJyZWFjaGluZycsXG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IGFsYXJtIHN0YXRlIGlzIG1haW50YWluZWRcbiAgICovXG4gIElHTk9SRSA9ICdpZ25vcmUnLFxuXG4gIC8qKlxuICAgKiBUaGUgYWxhcm0gZG9lcyBub3QgY29uc2lkZXIgbWlzc2luZyBkYXRhIHBvaW50cyB3aGVuIGV2YWx1YXRpbmcgd2hldGhlciB0byBjaGFuZ2Ugc3RhdGVcbiAgICovXG4gIE1JU1NJTkcgPSAnbWlzc2luZydcbn1cblxuLyoqXG4gKiBBbiBhbGFybSBvbiBhIENsb3VkV2F0Y2ggbWV0cmljXG4gKi9cbmV4cG9ydCBjbGFzcyBBbGFybSBleHRlbmRzIEFsYXJtQmFzZSB7XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhbiBleGlzdGluZyBDbG91ZFdhdGNoIGFsYXJtIHByb3ZpZGVkIGFuIEFSTlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBjcmVhdGluZyBjb25zdHJ1Y3QgKHVzdWFsbHkgYHRoaXNgKS5cbiAgICogQHBhcmFtIGlkIFRoZSBjb25zdHJ1Y3QncyBuYW1lXG4gICAqIEBwYXJhbSBhbGFybUFybiBBbGFybSBBUk4gKGkuZS4gYXJuOmF3czpjbG91ZHdhdGNoOjxyZWdpb24+OjxhY2NvdW50LWlkPjphbGFybTpGb28pXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21BbGFybUFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhbGFybUFybjogc3RyaW5nKTogSUFsYXJtIHtcbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBBbGFybUJhc2UgaW1wbGVtZW50cyBJQWxhcm0ge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGFsYXJtQXJuID0gYWxhcm1Bcm47XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgYWxhcm1OYW1lID0gU3RhY2sub2Yoc2NvcGUpLnNwbGl0QXJuKGFsYXJtQXJuLCBBcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lITtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhpcyBhbGFybVxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYWxhcm1Bcm46IHN0cmluZztcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGlzIGFsYXJtLlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYWxhcm1OYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBtZXRyaWMgb2JqZWN0IHRoaXMgYWxhcm0gd2FzIGJhc2VkIG9uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbWV0cmljOiBJTWV0cmljO1xuXG4gIC8qKlxuICAgKiBUaGlzIG1ldHJpYyBhcyBhbiBhbm5vdGF0aW9uXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGFubm90YXRpb246IEhvcml6b250YWxBbm5vdGF0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBBbGFybVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBwaHlzaWNhbE5hbWU6IHByb3BzLmFsYXJtTmFtZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbXBhcmlzb25PcGVyYXRvciA9IHByb3BzLmNvbXBhcmlzb25PcGVyYXRvciB8fCBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRDtcblxuICAgIC8vIFJlbmRlciBtZXRyaWMsIHByb2Nlc3MgcG90ZW50aWFsIG92ZXJyaWRlcyBmcm9tIHRoZSBhbGFybVxuICAgIC8vIChJdCB3b3VsZCBiZSBwcmVmZXJhYmxlIGlmIHRoZSBzdGF0aXN0aWMgZXRjLiB3YXMgd29ya2VkIGludG8gdGhlIG1ldHJpYyxcbiAgICAvLyBidXQgaGV5IHdlJ3JlIGFsbG93aW5nIG92ZXJyaWRlcy4uLilcbiAgICBjb25zdCBtZXRyaWNQcm9wczogV3JpdGVhYmxlPFBhcnRpYWw8Q2ZuQWxhcm1Qcm9wcz4+ID0gdGhpcy5yZW5kZXJNZXRyaWMocHJvcHMubWV0cmljKTtcbiAgICBpZiAocHJvcHMucGVyaW9kKSB7XG4gICAgICBtZXRyaWNQcm9wcy5wZXJpb2QgPSBwcm9wcy5wZXJpb2QudG9TZWNvbmRzKCk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5zdGF0aXN0aWMpIHtcbiAgICAgIC8vIFdpbGwgb3ZlcndyaXRlIGJvdGggZmllbGRzIGlmIHByZXNlbnRcbiAgICAgIE9iamVjdC5hc3NpZ24obWV0cmljUHJvcHMsIHtcbiAgICAgICAgc3RhdGlzdGljOiByZW5kZXJJZlNpbXBsZVN0YXRpc3RpYyhwcm9wcy5zdGF0aXN0aWMpLFxuICAgICAgICBleHRlbmRlZFN0YXRpc3RpYzogcmVuZGVySWZFeHRlbmRlZFN0YXRpc3RpYyhwcm9wcy5zdGF0aXN0aWMpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYWxhcm0gPSBuZXcgQ2ZuQWxhcm0odGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgLy8gTWV0YVxuICAgICAgYWxhcm1EZXNjcmlwdGlvbjogcHJvcHMuYWxhcm1EZXNjcmlwdGlvbixcbiAgICAgIGFsYXJtTmFtZTogdGhpcy5waHlzaWNhbE5hbWUsXG5cbiAgICAgIC8vIEV2YWx1YXRpb25cbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcixcbiAgICAgIHRocmVzaG9sZDogcHJvcHMudGhyZXNob2xkLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm06IHByb3BzLmRhdGFwb2ludHNUb0FsYXJtLFxuICAgICAgZXZhbHVhdGVMb3dTYW1wbGVDb3VudFBlcmNlbnRpbGU6IHByb3BzLmV2YWx1YXRlTG93U2FtcGxlQ291bnRQZXJjZW50aWxlLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogcHJvcHMudHJlYXRNaXNzaW5nRGF0YSxcblxuICAgICAgLy8gQWN0aW9uc1xuICAgICAgYWN0aW9uc0VuYWJsZWQ6IHByb3BzLmFjdGlvbnNFbmFibGVkLFxuICAgICAgYWxhcm1BY3Rpb25zOiBMYXp5Lmxpc3QoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmFsYXJtQWN0aW9uQXJucyB9KSxcbiAgICAgIGluc3VmZmljaWVudERhdGFBY3Rpb25zOiBMYXp5Lmxpc3QoeyBwcm9kdWNlOiAoKCkgPT4gdGhpcy5pbnN1ZmZpY2llbnREYXRhQWN0aW9uQXJucykgfSksXG4gICAgICBva0FjdGlvbnM6IExhenkubGlzdCh7IHByb2R1Y2U6ICgpID0+IHRoaXMub2tBY3Rpb25Bcm5zIH0pLFxuXG4gICAgICAvLyBNZXRyaWNcbiAgICAgIC4uLm1ldHJpY1Byb3BzLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hbGFybUFybiA9IHRoaXMuZ2V0UmVzb3VyY2VBcm5BdHRyaWJ1dGUoYWxhcm0uYXR0ckFybiwge1xuICAgICAgc2VydmljZTogJ2Nsb3Vkd2F0Y2gnLFxuICAgICAgcmVzb3VyY2U6ICdhbGFybScsXG4gICAgICByZXNvdXJjZU5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAgYXJuRm9ybWF0OiBBcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSxcbiAgICB9KTtcbiAgICB0aGlzLmFsYXJtTmFtZSA9IHRoaXMuZ2V0UmVzb3VyY2VOYW1lQXR0cmlidXRlKGFsYXJtLnJlZik7XG5cbiAgICB0aGlzLm1ldHJpYyA9IHByb3BzLm1ldHJpYztcbiAgICBjb25zdCBkYXRhcG9pbnRzID0gcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0gfHwgcHJvcHMuZXZhbHVhdGlvblBlcmlvZHM7XG4gICAgdGhpcy5hbm5vdGF0aW9uID0ge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgIGxhYmVsOiBgJHt0aGlzLm1ldHJpY30gJHtPUEVSQVRPUl9TWU1CT0xTW2NvbXBhcmlzb25PcGVyYXRvcl19ICR7cHJvcHMudGhyZXNob2xkfSBmb3IgJHtkYXRhcG9pbnRzfSBkYXRhcG9pbnRzIHdpdGhpbiAke2Rlc2NyaWJlUGVyaW9kKHByb3BzLmV2YWx1YXRpb25QZXJpb2RzICogbWV0cmljUGVyaW9kKHByb3BzLm1ldHJpYykudG9TZWNvbmRzKCkpfWAsXG4gICAgICB2YWx1ZTogcHJvcHMudGhyZXNob2xkLFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IHcgb2YgdGhpcy5tZXRyaWMud2FybmluZ3MgPz8gW10pIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmcodyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFR1cm4gdGhpcyBhbGFybSBpbnRvIGEgaG9yaXpvbnRhbCBhbm5vdGF0aW9uXG4gICAqXG4gICAqIFRoaXMgaXMgdXNlZnVsIGlmIHlvdSB3YW50IHRvIHJlcHJlc2VudCBhbiBBbGFybSBpbiBhIG5vbi1BbGFybVdpZGdldC5cbiAgICogQW4gYEFsYXJtV2lkZ2V0YCBjYW4gZGlyZWN0bHkgc2hvdyBhbiBhbGFybSwgYnV0IGl0IGNhbiBvbmx5IHNob3cgYVxuICAgKiBzaW5nbGUgYWxhcm0gYW5kIG5vIG90aGVyIG1ldHJpY3MuIEluc3RlYWQsIHlvdSBjYW4gY29udmVydCB0aGUgYWxhcm0gdG9cbiAgICogYSBIb3Jpem9udGFsQW5ub3RhdGlvbiBhbmQgYWRkIGl0IGFzIGFuIGFubm90YXRpb24gdG8gYW5vdGhlciBncmFwaC5cbiAgICpcbiAgICogVGhpcyBtaWdodCBiZSB1c2VmdWwgaWY6XG4gICAqXG4gICAqIC0gWW91IHdhbnQgdG8gc2hvdyBtdWx0aXBsZSBhbGFybXMgaW5zaWRlIGEgc2luZ2xlIGdyYXBoLCBmb3IgZXhhbXBsZSBpZlxuICAgKiAgIHlvdSBoYXZlIGJvdGggYSBcInNtYWxsIG1hcmdpbi9sb25nIHBlcmlvZFwiIGFsYXJtIGFzIHdlbGwgYXMgYVxuICAgKiAgIFwibGFyZ2UgbWFyZ2luL3Nob3J0IHBlcmlvZFwiIGFsYXJtLlxuICAgKlxuICAgKiAtIFlvdSB3YW50IHRvIHNob3cgYW4gQWxhcm0gbGluZSBpbiBhIGdyYXBoIHdpdGggbXVsdGlwbGUgbWV0cmljcyBpbiBpdC5cbiAgICovXG4gIHB1YmxpYyB0b0Fubm90YXRpb24oKTogSG9yaXpvbnRhbEFubm90YXRpb24ge1xuICAgIHJldHVybiB0aGlzLmFubm90YXRpb247XG4gIH1cblxuICAvKipcbiAgICogVHJpZ2dlciB0aGlzIGFjdGlvbiBpZiB0aGUgYWxhcm0gZmlyZXNcbiAgICpcbiAgICogVHlwaWNhbGx5IHRoZSBBUk4gb2YgYW4gU05TIHRvcGljIG9yIEFSTiBvZiBhbiBBdXRvU2NhbGluZyBwb2xpY3kuXG4gICAqL1xuICBwdWJsaWMgYWRkQWxhcm1BY3Rpb24oLi4uYWN0aW9uczogSUFsYXJtQWN0aW9uW10pIHtcbiAgICBpZiAodGhpcy5hbGFybUFjdGlvbkFybnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5hbGFybUFjdGlvbkFybnMgPSBbXTtcbiAgICB9XG5cbiAgICB0aGlzLmFsYXJtQWN0aW9uQXJucy5wdXNoKC4uLmFjdGlvbnMubWFwKGEgPT5cbiAgICAgIHRoaXMudmFsaWRhdGVBY3Rpb25Bcm4oYS5iaW5kKHRoaXMsIHRoaXMpLmFsYXJtQWN0aW9uQXJuKSxcbiAgICApKTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVBY3Rpb25Bcm4oYWN0aW9uQXJuOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGVjMkFjdGlvbnNSZWdleHA6IFJlZ0V4cCA9IC9hcm46YXdzW2EtejAtOS1dKjphdXRvbWF0ZTpbYS16fFxcZHwtXSs6ZWMyOlthLXpdKy87XG4gICAgaWYgKGVjMkFjdGlvbnNSZWdleHAudGVzdChhY3Rpb25Bcm4pKSB7XG4gICAgICAvLyBDaGVjayBwZXItaW5zdGFuY2UgbWV0cmljXG4gICAgICBjb25zdCBtZXRyaWNDb25maWcgPSB0aGlzLm1ldHJpYy50b01ldHJpY0NvbmZpZygpO1xuICAgICAgaWYgKG1ldHJpY0NvbmZpZy5tZXRyaWNTdGF0Py5kaW1lbnNpb25zPy5sZW5ndGggIT0gMSB8fCBtZXRyaWNDb25maWcubWV0cmljU3RhdD8uZGltZW5zaW9ucyFbMF0ubmFtZSAhPSAnSW5zdGFuY2VJZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFQzIgYWxhcm0gYWN0aW9ucyByZXF1aXJlcyBhbiBFQzIgUGVyLUluc3RhbmNlIE1ldHJpYy4gKCR7SlNPTi5zdHJpbmdpZnkobWV0cmljQ29uZmlnKX0gZG9lcyBub3QgaGF2ZSBhbiAnSW5zdGFuY2VJZCcgZGltZW5zaW9uKWApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWN0aW9uQXJuO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJNZXRyaWMobWV0cmljOiBJTWV0cmljKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgcmV0dXJuIGRpc3BhdGNoTWV0cmljKG1ldHJpYywge1xuICAgICAgd2l0aFN0YXQoc3RhdCwgY29uZikge1xuICAgICAgICBzZWxmLnZhbGlkYXRlTWV0cmljU3RhdChzdGF0LCBtZXRyaWMpO1xuICAgICAgICBjb25zdCBjYW5SZW5kZXJBc0xlZ2FjeU1ldHJpYyA9IGNvbmYucmVuZGVyaW5nUHJvcGVydGllcz8ubGFiZWwgPT0gdW5kZWZpbmVkICYmICFzZWxmLnJlcXVpcmVzQWNjb3VudElkKHN0YXQpO1xuICAgICAgICAvLyBEbyB0aGlzIHRvIGRpc3R1cmIgZXhpc3RpbmcgdGVtcGxhdGVzIGFzIGxpdHRsZSBhcyBwb3NzaWJsZVxuICAgICAgICBpZiAoY2FuUmVuZGVyQXNMZWdhY3lNZXRyaWMpIHtcbiAgICAgICAgICByZXR1cm4gZHJvcFVuZGVmaW5lZCh7XG4gICAgICAgICAgICBkaW1lbnNpb25zOiBzdGF0LmRpbWVuc2lvbnMsXG4gICAgICAgICAgICBuYW1lc3BhY2U6IHN0YXQubmFtZXNwYWNlLFxuICAgICAgICAgICAgbWV0cmljTmFtZTogc3RhdC5tZXRyaWNOYW1lLFxuICAgICAgICAgICAgcGVyaW9kOiBzdGF0LnBlcmlvZD8udG9TZWNvbmRzKCksXG4gICAgICAgICAgICBzdGF0aXN0aWM6IHJlbmRlcklmU2ltcGxlU3RhdGlzdGljKHN0YXQuc3RhdGlzdGljKSxcbiAgICAgICAgICAgIGV4dGVuZGVkU3RhdGlzdGljOiByZW5kZXJJZkV4dGVuZGVkU3RhdGlzdGljKHN0YXQuc3RhdGlzdGljKSxcbiAgICAgICAgICAgIHVuaXQ6IHN0YXQudW5pdEZpbHRlcixcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbWV0cmljczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRyaWNTdGF0OiB7XG4gICAgICAgICAgICAgICAgbWV0cmljOiB7XG4gICAgICAgICAgICAgICAgICBtZXRyaWNOYW1lOiBzdGF0Lm1ldHJpY05hbWUsXG4gICAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHN0YXQubmFtZXNwYWNlLFxuICAgICAgICAgICAgICAgICAgZGltZW5zaW9uczogc3RhdC5kaW1lbnNpb25zLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcGVyaW9kOiBzdGF0LnBlcmlvZC50b1NlY29uZHMoKSxcbiAgICAgICAgICAgICAgICBzdGF0OiBzdGF0LnN0YXRpc3RpYyxcbiAgICAgICAgICAgICAgICB1bml0OiBzdGF0LnVuaXRGaWx0ZXIsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGlkOiAnbTEnLFxuICAgICAgICAgICAgICBhY2NvdW50SWQ6IHNlbGYucmVxdWlyZXNBY2NvdW50SWQoc3RhdCkgPyBzdGF0LmFjY291bnQgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBjb25mLnJlbmRlcmluZ1Byb3BlcnRpZXM/LmxhYmVsLFxuICAgICAgICAgICAgICByZXR1cm5EYXRhOiB0cnVlLFxuICAgICAgICAgICAgfSBhcyBDZm5BbGFybS5NZXRyaWNEYXRhUXVlcnlQcm9wZXJ0eSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfSxcblxuICAgICAgd2l0aEV4cHJlc3Npb24oKSB7XG4gICAgICAgIC8vIEV4cGFuZCB0aGUgbWF0aCBleHByZXNzaW9uIG1ldHJpYyBpbnRvIGEgc2V0XG4gICAgICAgIGNvbnN0IG1zZXQgPSBuZXcgTWV0cmljU2V0PGJvb2xlYW4+KCk7XG4gICAgICAgIG1zZXQuYWRkVG9wTGV2ZWwodHJ1ZSwgbWV0cmljKTtcblxuICAgICAgICBsZXQgZWlkID0gMDtcbiAgICAgICAgZnVuY3Rpb24gdW5pcXVlTWV0cmljSWQoKSB7XG4gICAgICAgICAgcmV0dXJuIGBleHByXyR7KytlaWR9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbWV0cmljczogbXNldC5lbnRyaWVzLm1hcChlbnRyeSA9PiBkaXNwYXRjaE1ldHJpYyhlbnRyeS5tZXRyaWMsIHtcbiAgICAgICAgICAgIHdpdGhTdGF0KHN0YXQsIGNvbmYpIHtcbiAgICAgICAgICAgICAgc2VsZi52YWxpZGF0ZU1ldHJpY1N0YXQoc3RhdCwgZW50cnkubWV0cmljKTtcblxuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1ldHJpY1N0YXQ6IHtcbiAgICAgICAgICAgICAgICAgIG1ldHJpYzoge1xuICAgICAgICAgICAgICAgICAgICBtZXRyaWNOYW1lOiBzdGF0Lm1ldHJpY05hbWUsXG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZTogc3RhdC5uYW1lc3BhY2UsXG4gICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbnM6IHN0YXQuZGltZW5zaW9ucyxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBwZXJpb2Q6IHN0YXQucGVyaW9kLnRvU2Vjb25kcygpLFxuICAgICAgICAgICAgICAgICAgc3RhdDogc3RhdC5zdGF0aXN0aWMsXG4gICAgICAgICAgICAgICAgICB1bml0OiBzdGF0LnVuaXRGaWx0ZXIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpZDogZW50cnkuaWQgfHwgdW5pcXVlTWV0cmljSWQoKSxcbiAgICAgICAgICAgICAgICBhY2NvdW50SWQ6IHNlbGYucmVxdWlyZXNBY2NvdW50SWQoc3RhdCkgPyBzdGF0LmFjY291bnQgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgbGFiZWw6IGNvbmYucmVuZGVyaW5nUHJvcGVydGllcz8ubGFiZWwsXG4gICAgICAgICAgICAgICAgcmV0dXJuRGF0YTogZW50cnkudGFnID8gdW5kZWZpbmVkIDogZmFsc2UsIC8vIGVudHJ5LnRhZyBldmFsdWF0ZXMgdG8gdHJ1ZSBpZiB0aGUgbWV0cmljIGlzIHRoZSBtYXRoIGV4cHJlc3Npb24gdGhlIGFsYXJtIGlzIGJhc2VkIG9uLlxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdpdGhFeHByZXNzaW9uKGV4cHIsIGNvbmYpIHtcblxuICAgICAgICAgICAgICBjb25zdCBoYXNTdWJtZXRyaWNzID0gbWF0aEV4cHJIYXNTdWJtZXRyaWNzKGV4cHIpO1xuXG4gICAgICAgICAgICAgIGlmIChoYXNTdWJtZXRyaWNzKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0U3VibWV0cmljc0NvdW50KGV4cHIpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc2VsZi52YWxpZGF0ZU1ldHJpY0V4cHJlc3Npb24oZXhwcik7XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBleHByZXNzaW9uOiBleHByLmV4cHJlc3Npb24sXG4gICAgICAgICAgICAgICAgaWQ6IGVudHJ5LmlkIHx8IHVuaXF1ZU1ldHJpY0lkKCksXG4gICAgICAgICAgICAgICAgbGFiZWw6IGNvbmYucmVuZGVyaW5nUHJvcGVydGllcz8ubGFiZWwsXG4gICAgICAgICAgICAgICAgcGVyaW9kOiBoYXNTdWJtZXRyaWNzID8gdW5kZWZpbmVkIDogZXhwci5wZXJpb2QsXG4gICAgICAgICAgICAgICAgcmV0dXJuRGF0YTogZW50cnkudGFnID8gdW5kZWZpbmVkIDogZmFsc2UsIC8vIGVudHJ5LnRhZyBldmFsdWF0ZXMgdG8gdHJ1ZSBpZiB0aGUgbWV0cmljIGlzIHRoZSBtYXRoIGV4cHJlc3Npb24gdGhlIGFsYXJtIGlzIGJhc2VkIG9uLlxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSBhcyBDZm5BbGFybS5NZXRyaWNEYXRhUXVlcnlQcm9wZXJ0eSksXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgaWYgYSByZWdpb24gaXMgaW4gdGhlIGdpdmVuIHN0YXQgY29uZmlnLCB0aGV5IG1hdGNoIHRoZSBBbGFybVxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZU1ldHJpY1N0YXQoc3RhdDogTWV0cmljU3RhdENvbmZpZywgbWV0cmljOiBJTWV0cmljKSB7XG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZih0aGlzKTtcblxuICAgIGlmIChkZWZpbml0ZWx5RGlmZmVyZW50KHN0YXQucmVnaW9uLCBzdGFjay5yZWdpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBjcmVhdGUgYW4gQWxhcm0gaW4gcmVnaW9uICcke3N0YWNrLnJlZ2lvbn0nIGJhc2VkIG9uIG1ldHJpYyAnJHttZXRyaWN9JyBpbiAnJHtzdGF0LnJlZ2lvbn0nYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGF0IHRoZSBleHByZXNzaW9uIGNvbmZpZyBkb2VzIG5vdCBzcGVjaWZ5IHNlYXJjaEFjY291bnQgb3Igc2VhcmNoUmVnaW9uIHByb3BzXG4gICAqIGFzIHNlYXJjaCBleHByZXNzaW9ucyBhcmUgbm90IHN1cHBvcnRlZCBieSBBbGFybXMuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlTWV0cmljRXhwcmVzc2lvbihleHByOiBNZXRyaWNFeHByZXNzaW9uQ29uZmlnKSB7XG4gICAgaWYgKGV4cHIuc2VhcmNoQWNjb3VudCAhPT0gdW5kZWZpbmVkIHx8IGV4cHIuc2VhcmNoUmVnaW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNyZWF0ZSBhbiBBbGFybSBiYXNlZCBvbiBhIE1hdGhFeHByZXNzaW9uIHdoaWNoIHNwZWNpZmllcyBhIHNlYXJjaEFjY291bnQgb3Igc2VhcmNoUmVnaW9uJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSBpZiB0aGUgYWNjb3VudElkIHByb3BlcnR5IHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgbWV0cmljLlxuICAgKi9cbiAgcHJpdmF0ZSByZXF1aXJlc0FjY291bnRJZChzdGF0OiBNZXRyaWNTdGF0Q29uZmlnKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc3RhY2tBY2NvdW50ID0gU3RhY2sub2YodGhpcykuYWNjb3VudDtcblxuICAgIC8vIGlmIHN0YXQuYWNjb3VudCBpcyB1bmRlZmluZWQsIGl0J3MgYnkgZGVmaW5pdGlvbiBpbiB0aGUgc2FtZSBhY2NvdW50XG4gICAgaWYgKHN0YXQuYWNjb3VudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIHRydWUgaWYgdGhleSdyZSBkaWZmZXJlbnQuIFRoZSBBQ0NPVU5UX0lEIHRva2VuIGlzIGludGVybmVkXG4gICAgLy8gc28gd2lsbCBhbHdheXMgaGF2ZSB0aGUgc2FtZSBzdHJpbmcgdmFsdWUgKGFuZCBldmVuIGlmIHdlIGd1ZXNzIHdyb25nXG4gICAgLy8gaXQgd2lsbCBzdGlsbCB3b3JrKS5cbiAgICByZXR1cm4gc3RhY2tBY2NvdW50ICE9PSBzdGF0LmFjY291bnQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGVmaW5pdGVseURpZmZlcmVudCh4OiBzdHJpbmcgfCB1bmRlZmluZWQsIHk6IHN0cmluZykge1xuICByZXR1cm4geCAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKHkpICYmIHggIT09IHk7XG59XG5cbi8qKlxuICogUmV0dXJuIGEgaHVtYW4gcmVhZGFibGUgc3RyaW5nIGZvciB0aGlzIHBlcmlvZFxuICpcbiAqIFdlIGtub3cgdGhlIHNlY29uZHMgYXJlIGFsd2F5cyBvbmUgb2YgYSBoYW5kZnVsIG9mIGFsbG93ZWQgdmFsdWVzLlxuICovXG5mdW5jdGlvbiBkZXNjcmliZVBlcmlvZChzZWNvbmRzOiBudW1iZXIpIHtcbiAgaWYgKHNlY29uZHMgPT09IDYwKSB7IHJldHVybiAnMSBtaW51dGUnOyB9XG4gIGlmIChzZWNvbmRzID09PSAxKSB7IHJldHVybiAnMSBzZWNvbmQnOyB9XG4gIGlmIChzZWNvbmRzID4gNjApIHsgcmV0dXJuIChzZWNvbmRzIC8gNjApICsgJyBtaW51dGVzJzsgfVxuICByZXR1cm4gc2Vjb25kcyArICcgc2Vjb25kcyc7XG59XG5cbmZ1bmN0aW9uIHJlbmRlcklmU2ltcGxlU3RhdGlzdGljKHN0YXRpc3RpYz86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChzdGF0aXN0aWMgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG5cbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTdGF0aXN0aWMoc3RhdGlzdGljKTtcbiAgaWYgKHBhcnNlZC50eXBlID09PSAnc2ltcGxlJykge1xuICAgIHJldHVybiBwYXJzZWQuc3RhdGlzdGljO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlbmRlcklmRXh0ZW5kZWRTdGF0aXN0aWMoc3RhdGlzdGljPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHN0YXRpc3RpYyA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cblxuICBjb25zdCBwYXJzZWQgPSBwYXJzZVN0YXRpc3RpYyhzdGF0aXN0aWMpO1xuICBpZiAocGFyc2VkLnR5cGUgPT09ICdwZXJjZW50aWxlJykge1xuICAgIC8vIEFscmVhZHkgcGVyY2VudGlsZS4gQXZvaWQgcGFyc2luZyBiZWNhdXNlIHdlIG1pZ2h0IGdldCBpbnRvXG4gICAgLy8gZmxvYXRpbmcgcG9pbnQgcm91bmRpbmcgaXNzdWVzLCByZXR1cm4gYXMtaXMgYnV0IGxvd2VyY2FzZSB0aGUgcC5cbiAgICByZXR1cm4gc3RhdGlzdGljLnRvTG93ZXJDYXNlKCk7XG4gIH0gZWxzZSBpZiAocGFyc2VkLnR5cGUgPT09ICdnZW5lcmljJykge1xuICAgIHJldHVybiBzdGF0aXN0aWM7XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBtYXRoRXhwckhhc1N1Ym1ldHJpY3MoZXhwcjogTWV0cmljRXhwcmVzc2lvbkNvbmZpZykge1xuICByZXR1cm4gT2JqZWN0LmtleXMoZXhwci51c2luZ01ldHJpY3MpLmxlbmd0aCA+IDA7XG59XG5cbmZ1bmN0aW9uIGFzc2VydFN1Ym1ldHJpY3NDb3VudChleHByOiBNZXRyaWNFeHByZXNzaW9uQ29uZmlnKSB7XG4gIGlmIChPYmplY3Qua2V5cyhleHByLnVzaW5nTWV0cmljcykubGVuZ3RoID4gMTApIHtcbiAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvbW9uaXRvcmluZy9BbGFybVRoYXRTZW5kc0VtYWlsLmh0bWwjYWxhcm1zLW9uLW1ldHJpYy1tYXRoLWV4cHJlc3Npb25zXG4gICAgdGhyb3cgbmV3IEVycm9yKCdBbGFybXMgb24gbWF0aCBleHByZXNzaW9ucyBjYW5ub3QgY29udGFpbiBtb3JlIHRoYW4gMTAgaW5kaXZpZHVhbCBtZXRyaWNzJyk7XG4gIH07XG59XG5cbnR5cGUgV3JpdGVhYmxlPFQ+ID0geyAtcmVhZG9ubHkgW1AgaW4ga2V5b2YgVF06IFRbUF0gfTtcbiJdfQ==
\No newline at end of file