UNPKG

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