cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
250 lines • 49.3 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FargateServiceMonitoring = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const BaseServiceMetricFactory_1 = require("./BaseServiceMetricFactory");
const common_1 = require("../../common");
const dashboard_1 = require("../../dashboard");
const aws_loadbalancing_1 = require("../aws-loadbalancing");
class FargateServiceMonitoring extends common_1.Monitoring {
constructor(scope, props) {
super(scope, props);
this.hasLoadBalancer =
props.loadBalancer !== undefined && props.targetGroup !== undefined;
const namingStrategy = new dashboard_1.MonitoringNamingStrategy({
...props,
namedConstruct: props.fargateService,
});
this.title = namingStrategy.resolveHumanReadableName();
this.metricFactory = scope.createMetricFactory();
this.baseServiceMetricFactory = new BaseServiceMetricFactory_1.BaseServiceMetricFactory(this.metricFactory, { service: props.fargateService });
if (this.hasLoadBalancer) {
this.loadBalancerMetricFactory = (0, aws_loadbalancing_1.createLoadBalancerMetricFactory)(this.metricFactory, props.loadBalancer, props.targetGroup, props.invertLoadBalancerTaskCountMetricsStatistics);
this.healthyTaskCountMetric =
this.loadBalancerMetricFactory.metricHealthyTaskCount();
this.unhealthyTaskCountMetric =
this.loadBalancerMetricFactory.metricUnhealthyTaskCount();
this.healthyTaskPercentMetric =
this.loadBalancerMetricFactory.metricHealthyTaskInPercent();
this.activeTcpFlowCountMetric =
this.loadBalancerMetricFactory.metricActiveConnectionCount();
this.newTcpFlowCountMetric =
this.loadBalancerMetricFactory.metricNewConnectionCount();
this.unhealthyRoutingFlowCountMetric =
this.loadBalancerMetricFactory.metricUnhealthyRoutingCount();
this.processedBytesMetric =
this.loadBalancerMetricFactory.metricProcessedBytesMin();
}
this.cpuUtilisationMetric =
this.baseServiceMetricFactory.metricClusterCpuUtilisationInPercent();
this.cpuP100UtilisationMetric =
this.baseServiceMetricFactory.metricClusterCpuUtilisationInPercent(common_1.MetricStatistic.P100);
this.memoryUtilisationMetric =
this.baseServiceMetricFactory.metricClusterMemoryUtilisationInPercent();
this.memoryP100UtilisationMetric =
this.baseServiceMetricFactory.metricClusterMemoryUtilisationInPercent(common_1.MetricStatistic.P100);
this.runningTaskCountMetric =
this.baseServiceMetricFactory.metricRunningTaskCount();
this.ephemeralStorageUsageMetric =
this.baseServiceMetricFactory.metricEphemeralStorageUsageInPercent();
const alarmFactory = this.createAlarmFactory(namingStrategy.resolveAlarmFriendlyName());
this.taskHealthAlarmFactory = new common_1.TaskHealthAlarmFactory(alarmFactory);
this.throughputAlarmFactory = new common_1.ThroughputAlarmFactory(alarmFactory);
this.taskHealthAnnotations = [];
this.usageAlarmFactory = new common_1.UsageAlarmFactory(alarmFactory);
this.cpuUsageAnnotations = [];
this.memoryUsageAnnotations = [];
this.processedBytesAnnotations = [];
if (props.minAutoScalingTaskCount) {
// TODO: use annotation strategy to create neutral annotation
this.taskHealthAnnotations.push({
value: props.minAutoScalingTaskCount,
label: "AutoScaling: Min",
color: common_1.NeutralColor,
});
}
if (props.maxAutoScalingTaskCount) {
// TODO: use annotation strategy to create neutral annotation
this.taskHealthAnnotations.push({
value: props.maxAutoScalingTaskCount,
label: "AutoScaling: Max",
color: common_1.NeutralColor,
});
}
if (this.hasLoadBalancer) {
for (const disambiguator in props.addHealthyTaskCountAlarm) {
const alarmProps = props.addHealthyTaskCountAlarm[disambiguator];
const createdAlarm = this.taskHealthAlarmFactory.addHealthyTaskCountAlarm(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.healthyTaskCountMetric, alarmProps, disambiguator);
this.taskHealthAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addUnhealthyTaskCountAlarm) {
const alarmProps = props.addUnhealthyTaskCountAlarm[disambiguator];
const createdAlarm = this.taskHealthAlarmFactory.addUnhealthyTaskCountAlarm(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.unhealthyTaskCountMetric, alarmProps, disambiguator);
this.taskHealthAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addHealthyTaskPercentAlarm) {
const alarmProps = props.addHealthyTaskPercentAlarm[disambiguator];
const createdAlarm = this.taskHealthAlarmFactory.addHealthyTaskPercentAlarm(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.healthyTaskPercentMetric, alarmProps, disambiguator);
this.addAlarm(createdAlarm);
}
}
for (const disambiguator in props.addCpuUsageAlarm) {
const alarmProps = props.addCpuUsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxCpuUsagePercentAlarm(this.cpuUtilisationMetric, alarmProps, disambiguator);
this.cpuUsageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addCpuP100UsageAlarm) {
const alarmProps = props.addCpuP100UsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxCpuUsagePercentAlarm(this.cpuP100UtilisationMetric, alarmProps, disambiguator, common_1.UsageType.P100);
this.cpuUsageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addMemoryUsageAlarm) {
const alarmProps = props.addMemoryUsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxMemoryUsagePercentAlarm(this.memoryUtilisationMetric, alarmProps, disambiguator);
this.memoryUsageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addMemoryP100UsageAlarm) {
const alarmProps = props.addMemoryP100UsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMemoryUsagePercentAlarm(this.memoryP100UtilisationMetric, alarmProps, common_1.UsageType.P100, disambiguator);
this.memoryUsageAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addRunningTaskCountAlarm) {
const alarmProps = props.addRunningTaskCountAlarm[disambiguator];
const createdAlarm = this.taskHealthAlarmFactory.addRunningTaskCountAlarm(this.runningTaskCountMetric, alarmProps, disambiguator);
this.taskHealthAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addEphermalStorageUsageAlarm) {
const alarmProps = props.addEphermalStorageUsageAlarm[disambiguator];
const createdAlarm = this.usageAlarmFactory.addMaxDiskUsagePercentAlarm(this.ephemeralStorageUsageMetric, alarmProps, disambiguator);
this.addAlarm(createdAlarm);
}
if (this.hasLoadBalancer) {
for (const disambiguator in props.addMinProcessedBytesAlarm) {
const alarmProps = props.addMinProcessedBytesAlarm[disambiguator];
const createdAlarm = this.throughputAlarmFactory.addMinProcessedBytesAlarm(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.processedBytesMetric, alarmProps, disambiguator);
this.processedBytesAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
}
props.useCreatedAlarms?.consume(this.createdAlarms());
}
summaryWidgets() {
return [
this.createTitleWidget(),
this.createCpuWidget(common_1.ThirdWidth, common_1.DefaultSummaryWidgetHeight),
this.createMemoryWidget(common_1.ThirdWidth, common_1.DefaultSummaryWidgetHeight),
this.createTaskHealthWidget(common_1.ThirdWidth, common_1.DefaultSummaryWidgetHeight),
];
}
widgets() {
const baseWidget = [
this.createTitleWidget(),
this.createCpuWidget(this.hasLoadBalancer ? common_1.QuarterWidth : common_1.ThirdWidth, common_1.DefaultGraphWidgetHeight),
this.createMemoryWidget(this.hasLoadBalancer ? common_1.QuarterWidth : common_1.ThirdWidth, common_1.DefaultGraphWidgetHeight),
];
if (this.hasLoadBalancer) {
return baseWidget.concat([
this.createTcpFlowsWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
this.createTaskHealthWidget(common_1.QuarterWidth, common_1.DefaultGraphWidgetHeight),
]);
}
else {
return baseWidget.concat(this.createTaskHealthWidget(common_1.ThirdWidth, common_1.DefaultGraphWidgetHeight));
}
}
createTitleWidget() {
return new dashboard_1.MonitoringHeaderWidget({
family: "Fargate Service",
title: this.title,
});
}
createCpuWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "CPU Utilization",
left: [this.cpuUtilisationMetric, this.cpuP100UtilisationMetric],
leftYAxis: common_1.PercentageAxisFromZeroToHundred,
leftAnnotations: this.cpuUsageAnnotations,
});
}
createMemoryWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Memory Utilization",
left: [this.memoryUtilisationMetric, this.memoryP100UtilisationMetric],
leftYAxis: common_1.PercentageAxisFromZeroToHundred,
leftAnnotations: this.memoryUsageAnnotations,
});
}
createTaskHealthWidget(width, height) {
const left = [this.runningTaskCountMetric];
if (this.healthyTaskCountMetric) {
left.push(this.healthyTaskCountMetric);
}
if (this.unhealthyTaskCountMetric) {
left.push(this.unhealthyTaskCountMetric);
}
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: this.hasLoadBalancer ? "Task Health" : "Task Count",
left,
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.taskHealthAnnotations,
});
}
createTcpFlowsWidget(width, height) {
const left = [];
const right = [];
if (this.activeTcpFlowCountMetric) {
left.push(this.activeTcpFlowCountMetric);
}
if (this.newTcpFlowCountMetric) {
left.push(this.newTcpFlowCountMetric);
}
if (this.unhealthyRoutingFlowCountMetric) {
left.push(this.unhealthyRoutingFlowCountMetric);
}
if (this.processedBytesMetric) {
right.push(this.processedBytesMetric);
}
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "TCP Flows",
left,
leftYAxis: common_1.CountAxisFromZero,
right,
rightYAxis: common_1.SizeAxisBytesFromZero,
});
}
/**
* @deprecated use {@see createTcpFlowsWidget} instead.
*/
createTpcFlowsWidget(width, height) {
return this.createTcpFlowsWidget(width, height);
}
}
exports.FargateServiceMonitoring = FargateServiceMonitoring;
_a = JSII_RTTI_SYMBOL_1;
FargateServiceMonitoring[_a] = { fqn: "cdk-monitoring-constructs.FargateServiceMonitoring", version: "10.0.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0RBS29DO0FBYXBDLHlFQUFzRTtBQUN0RSx5Q0F5QnNCO0FBQ3RCLCtDQUd5QjtBQUN6Qiw0REFLOEI7QUE2RzlCLE1BQWEsd0JBQXlCLFNBQVEsbUJBQVU7SUErQnRELFlBQ0UsS0FBc0IsRUFDdEIsS0FBMEM7UUFFMUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVwQixJQUFJLENBQUMsZUFBZTtZQUNsQixLQUFLLENBQUMsWUFBWSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFNBQVMsQ0FBQztRQUV0RSxNQUFNLGNBQWMsR0FBRyxJQUFJLG9DQUF3QixDQUFDO1lBQ2xELEdBQUcsS0FBSztZQUNSLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYztTQUNyQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1FBRXZELElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDakQsSUFBSSxDQUFDLHdCQUF3QixHQUFHLElBQUksbURBQXdCLENBQzFELElBQUksQ0FBQyxhQUFhLEVBQ2xCLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FDbEMsQ0FBQztRQUNGLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFBLG1EQUErQixFQUM5RCxJQUFJLENBQUMsYUFBYSxFQUNsQixLQUFLLENBQUMsWUFBYSxFQUNuQixLQUFLLENBQUMsV0FBWSxFQUNsQixLQUFLLENBQUMsNENBQTRDLENBQ25ELENBQUM7WUFDRixJQUFJLENBQUMsc0JBQXNC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LHdCQUF3QixFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQywrQkFBK0IsRUFBRSxDQUFDO1lBQ3pDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLCtCQUErQixDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDOUIsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUN4QyxDQUFDO1FBRUQsT0FBTyxJQUFJLDRCQUFXLENBQUM7WUFDckIsS0FBSztZQUNMLE1BQU07WUFDTixLQUFLLEVBQUUsV0FBVztZQUNsQixJQUFJO1lBQ0osU0FBUyxFQUFFLDBCQUFpQjtZQUM1QixLQUFLO1lBQ0wsVUFBVSxFQUFFLDhCQUFxQjtTQUNsQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxvQkFBb0IsQ0FBQyxLQUFhLEVBQUUsTUFBYztRQUNoRCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbEQsQ0FBQzs7QUFyV0gsNERBc1dDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgR3JhcGhXaWRnZXQsXG4gIEhvcml6b250YWxBbm5vdGF0aW9uLFxuICBJTWV0cmljLFxuICBJV2lkZ2V0LFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIjtcbmltcG9ydCB7IEZhcmdhdGVTZXJ2aWNlLCBJQmFzZVNlcnZpY2UgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjc1wiO1xuaW1wb3J0IHtcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSxcbiAgTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjcy1wYXR0ZXJuc1wiO1xuaW1wb3J0IHtcbiAgSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICBJQXBwbGljYXRpb25UYXJnZXRHcm91cCxcbiAgSU5ldHdvcmtMb2FkQmFsYW5jZXIsXG4gIElOZXR3b3JrVGFyZ2V0R3JvdXAsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWxhc3RpY2xvYWRiYWxhbmNpbmd2MlwiO1xuXG5pbXBvcnQgeyBCYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkgfSBmcm9tIFwiLi9CYXNlU2VydmljZU1ldHJpY0ZhY3RvcnlcIjtcbmltcG9ydCB7XG4gIEJhc2VNb25pdG9yaW5nUHJvcHMsXG4gIENvdW50QXhpc0Zyb21aZXJvLFxuICBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQsXG4gIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0LFxuICBIZWFsdGh5VGFza0NvdW50VGhyZXNob2xkLFxuICBIZWFsdGh5VGFza1BlcmNlbnRUaHJlc2hvbGQsXG4gIE1ldHJpY0ZhY3RvcnksXG4gIE1ldHJpY1N0YXRpc3RpYyxcbiAgTWV0cmljV2l0aEFsYXJtU3VwcG9ydCxcbiAgTWluUHJvY2Vzc2VkQnl0ZXNUaHJlc2hvbGQsXG4gIE1vbml0b3JpbmcsXG4gIE1vbml0b3JpbmdTY29wZSxcbiAgTmV1dHJhbENvbG9yLFxuICBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICBRdWFydGVyV2lkdGgsXG4gIFJ1bm5pbmdUYXNrQ291bnRUaHJlc2hvbGQsXG4gIFNpemVBeGlzQnl0ZXNGcm9tWmVybyxcbiAgVGFza0hlYWx0aEFsYXJtRmFjdG9yeSxcbiAgVGhpcmRXaWR0aCxcbiAgVGhyb3VnaHB1dEFsYXJtRmFjdG9yeSxcbiAgVW5oZWFsdGh5VGFza0NvdW50VGhyZXNob2xkLFxuICBVc2FnZUFsYXJtRmFjdG9yeSxcbiAgVXNhZ2VUaHJlc2hvbGQsXG4gIFVzYWdlVHlwZSxcbn0gZnJvbSBcIi4uLy4uL2NvbW1vblwiO1xuaW1wb3J0IHtcbiAgTW9uaXRvcmluZ0hlYWRlcldpZGdldCxcbiAgTW9uaXRvcmluZ05hbWluZ1N0cmF0ZWd5LFxufSBmcm9tIFwiLi4vLi4vZGFzaGJvYXJkXCI7XG5pbXBvcnQge1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnlQcm9wcyxcbiAgSUxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnksXG4gIE5ldHdvcmtMb2FkQmFsYW5jZXJNZXRyaWNGYWN0b3J5UHJvcHMsXG4gIGNyZWF0ZUxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnksXG59IGZyb20gXCIuLi9hd3MtbG9hZGJhbGFuY2luZ1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJhc2VGYXJnYXRlU2VydmljZUFsYXJtcyB7XG4gIC8qKlxuICAgKiBNaW5pbXVtIG51bWJlciBvZiB0YXNrcywgYXMgc3BlY2lmaWVkIGluIHlvdXIgYXV0byBzY2FsaW5nIGNvbmZpZy5cbiAgICovXG4gIHJlYWRvbmx5IG1pbkF1dG9TY2FsaW5nVGFza0NvdW50PzogbnVtYmVyO1xuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgdGFza3MsIGFzIHNwZWNpZmllZCBpbiB5b3VyIGF1dG8gc2NhbGluZyBjb25maWcuXG4gICAqL1xuICByZWFkb25seSBtYXhBdXRvU2NhbGluZ1Rhc2tDb3VudD86IG51bWJlcjtcbiAgcmVhZG9ubHkgYWRkQ3B1VXNhZ2VBbGFybT86IFJlY29yZDxzdHJpbmcsIFVzYWdlVGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkTWVtb3J5VXNhZ2VBbGFybT86IFJlY29yZDxzdHJpbmcsIFVzYWdlVGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkQ3B1UDEwMFVzYWdlQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBVc2FnZVRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZE1lbW9yeVAxMDBVc2FnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgVXNhZ2VUaHJlc2hvbGQ+O1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgSW5zaWdodHMgbmVlZHMgdG8gYmUgZW5hYmxlZCBmb3IgdGhlIGNsdXN0ZXIgZm9yIHRoaXMgYWxhcm0uXG4gICAqL1xuICByZWFkb25seSBhZGRSdW5uaW5nVGFza0NvdW50QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBSdW5uaW5nVGFza0NvdW50VGhyZXNob2xkPjtcbiAgLyoqXG4gICAqIENvbnRhaW5lciBJbnNpZ2h0cyBuZWVkcyB0byBiZSBlbmFibGVkIGZvciB0aGUgY2x1c3RlciBmb3IgdGhpcyBhbGFybS5cbiAgICovXG4gIHJlYWRvbmx5IGFkZEVwaGVybWFsU3RvcmFnZVVzYWdlQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBVc2FnZVRocmVzaG9sZD47XG59XG5cbi8qKlxuICogTW9uaXRvcmluZyBwcm9wcyBmb3IgYW55IHR5cGUgb2YgRmFyZ2F0ZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhc2VGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIEJhc2VNb25pdG9yaW5nUHJvcHMsXG4gICAgQmFzZUZhcmdhdGVTZXJ2aWNlQWxhcm1zIHt9XG5cbi8qKlxuICogTW9uaXRvcmluZyBwcm9wcyBmb3IgU2ltcGxlIEZhcmdhdGUgc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaW1wbGVGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIEJhc2VGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wcyB7XG4gIHJlYWRvbmx5IGZhcmdhdGVTZXJ2aWNlOiBGYXJnYXRlU2VydmljZTtcbn1cblxuLyoqXG4gKiBCYXNlIG9mIE1vbml0b3JpbmcgcHJvcHMgZm9yIGxvYWQtYmFsYW5jZWQgRmFyZ2F0ZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhc2VMb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIEJhc2VGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wcyB7XG4gIHJlYWRvbmx5IGFkZEhlYWx0aHlUYXNrQ291bnRBbGFybT86IFJlY29yZDxzdHJpbmcsIEhlYWx0aHlUYXNrQ291bnRUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRVbmhlYWx0aHlUYXNrQ291bnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgVW5oZWFsdGh5VGFza0NvdW50VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEhlYWx0aHlUYXNrUGVyY2VudEFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBIZWFsdGh5VGFza1BlcmNlbnRUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkTWluUHJvY2Vzc2VkQnl0ZXNBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTWluUHJvY2Vzc2VkQnl0ZXNUaHJlc2hvbGRcbiAgPjtcblxuICAvKipcbiAgICogSW52ZXJ0IHRoZSBzdGF0aXN0aWNzIG9mIGBIZWFsdGh5SG9zdENvdW50YCBhbmQgYFVuSGVhbHRoeUhvc3RDb3VudGAuXG4gICAqXG4gICAqIFdoZW4gYGludmVydExvYWRCYWxhbmNlclRhc2tDb3VudE1ldHJpY3NTdGF0aXN0aWNzYCBpcyBzZXQgdG8gZmFsc2UsIHRoZSBtaW5pbXVtIG9mIGBIZWFsdGh5SG9zdENvdW50YCBhbmQgdGhlIG1heGltdW0gb2YgYFVuSGVhbHRoeUhvc3RDb3VudGAgYXJlIG1vbml0b3JlZC5cbiAgICogV2hlbiBgaW52ZXJ0TG9hZEJhbGFuY2VyVGFza0NvdW50TWV0cmljc1N0YXRpc3RpY3NgIGlzIHNldCB0byB0cnVlLCB0aGUgbWF4aW11bSBvZiBgSGVhbHRoeUhvc3RDb3VudGAgYW5kIHRoZSBtaW5pbXVtIG9mIGBVbkhlYWx0aHlIb3N0Q291bnRgIGFyZSBtb25pdG9yZWQuXG4gICAqXG4gICAqIGBpbnZlcnRMb2FkQmFsYW5jZXJUYXNrQ291bnRNZXRyaWNzU3RhdGlzdGljc2AgaXMgcmVjb21tZW5kZWQgdG8gc2V0IHRvIHRydWUgYXMgcGVyIHRoZSBndWlkZWxpbmVzIGF0XG5odHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWxhc3RpY2xvYWRiYWxhbmNpbmcvbGF0ZXN0L25ldHdvcmsvbG9hZC1iYWxhbmNlci1jbG91ZHdhdGNoLW1ldHJpY3MuaHRtbCNtZXRyaWMtc3RhdGlzdGljc1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaW52ZXJ0TG9hZEJhbGFuY2VyVGFza0NvdW50TWV0cmljc1N0YXRpc3RpY3M/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIE1vbml0b3JpbmcgcHJvcHMgZm9yIGxvYWQtYmFsYW5jZWQgRmFyZ2F0ZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgQmFzZUxvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgZmFyZ2F0ZVNlcnZpY2U6XG4gICAgfCBOZXR3b3JrTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2VcbiAgICB8IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2U7XG59XG5cbi8qKlxuICogTW9uaXRvcmluZyBwcm9wcyBmb3IgRmFyZ2F0ZSBzZXJ2aWNlIHdpdGggbmV0d29yayBsb2FkIGJhbGFuY2VyIGFuZCBwbGFpbiBzZXJ2aWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZhcmdhdGVOZXR3b3JrTG9hZEJhbGFuY2VyTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgTmV0d29ya0xvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnlQcm9wcyxcbiAgICBCYXNlTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBmYXJnYXRlU2VydmljZTogRmFyZ2F0ZVNlcnZpY2U7XG59XG5cbi8qKlxuICogTW9uaXRvcmluZyBwcm9wcyBmb3IgRmFyZ2F0ZSBzZXJ2aWNlIHdpdGggYXBwbGljYXRpb24gbG9hZCBiYWxhbmNlciBhbmQgcGxhaW4gc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGYXJnYXRlQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNb25pdG9yaW5nUHJvcHNcbiAgZXh0ZW5kcyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnlQcm9wcyxcbiAgICBCYXNlTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBmYXJnYXRlU2VydmljZTogRmFyZ2F0ZVNlcnZpY2U7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHNcbiAgZXh0ZW5kcyBCYXNlTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBmYXJnYXRlU2VydmljZTogSUJhc2VTZXJ2aWNlO1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/OiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIgfCBJTmV0d29ya0xvYWRCYWxhbmNlcjtcbiAgcmVhZG9ubHkgdGFyZ2V0R3JvdXA/OiBJQXBwbGljYXRpb25UYXJnZXRHcm91cCB8IElOZXR3b3JrVGFyZ2V0R3JvdXA7XG59XG5cbmV4cG9ydCBjbGFzcyBGYXJnYXRlU2VydmljZU1vbml0b3JpbmcgZXh0ZW5kcyBNb25pdG9yaW5nIHtcbiAgcmVhZG9ubHkgdGl0bGU6IHN0cmluZztcblxuICByZWFkb25seSBtZXRyaWNGYWN0b3J5OiBNZXRyaWNGYWN0b3J5O1xuICByZWFkb25seSBiYXNlU2VydmljZU1ldHJpY0ZhY3Rvcnk6IEJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeTtcbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeT86IElMb2FkQmFsYW5jZXJNZXRyaWNGYWN0b3J5O1xuXG4gIHJlYWRvbmx5IHRhc2tIZWFsdGhBbGFybUZhY3Rvcnk6IFRhc2tIZWFsdGhBbGFybUZhY3Rvcnk7XG4gIHJlYWRvbmx5IHRocm91Z2hwdXRBbGFybUZhY3Rvcnk6IFRocm91Z2hwdXRBbGFybUZhY3Rvcnk7XG4gIHJlYWRvbmx5IHRhc2tIZWFsdGhBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgdXNhZ2VBbGFybUZhY3Rvcnk6IFVzYWdlQWxhcm1GYWN0b3J5O1xuICByZWFkb25seSBjcHVVc2FnZUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSBtZW1vcnlVc2FnZUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSBwcm9jZXNzZWRCeXRlc0Fubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuXG4gIHJlYWRvbmx5IGhlYWx0aHlUYXNrQ291bnRNZXRyaWM/OiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSB1bmhlYWx0aHlUYXNrQ291bnRNZXRyaWM/OiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBoZWFsdGh5VGFza1BlcmNlbnRNZXRyaWM/OiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBjcHVVdGlsaXNhdGlvbk1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgY3B1UDEwMFV0aWxpc2F0aW9uTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBtZW1vcnlVdGlsaXNhdGlvbk1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgbWVtb3J5UDEwMFV0aWxpc2F0aW9uTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBydW5uaW5nVGFza0NvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBlcGhlbWVyYWxTdG9yYWdlVXNhZ2VNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IGFjdGl2ZVRjcEZsb3dDb3VudE1ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IG5ld1RjcEZsb3dDb3VudE1ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IHVuaGVhbHRoeVJvdXRpbmdGbG93Q291bnRNZXRyaWM/OiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBwcm9jZXNzZWRCeXRlc01ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG5cbiAgcHJpdmF0ZSBoYXNMb2FkQmFsYW5jZXI6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IE1vbml0b3JpbmdTY29wZSxcbiAgICBwcm9wczogQ3VzdG9tRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBwcm9wcyk7XG5cbiAgICB0aGlzLmhhc0xvYWRCYWxhbmNlciA9XG4gICAgICBwcm9wcy5sb2FkQmFsYW5jZXIgIT09IHVuZGVmaW5lZCAmJiBwcm9wcy50YXJnZXRHcm91cCAhPT0gdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgbmFtaW5nU3RyYXRlZ3kgPSBuZXcgTW9uaXRvcmluZ05hbWluZ1N0cmF0ZWd5KHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgbmFtZWRDb25zdHJ1Y3Q6IHByb3BzLmZhcmdhdGVTZXJ2aWNlLFxuICAgIH0pO1xuICAgIHRoaXMudGl0bGUgPSBuYW1pbmdTdHJhdGVneS5yZXNvbHZlSHVtYW5SZWFkYWJsZU5hbWUoKTtcblxuICAgIHRoaXMubWV0cmljRmFjdG9yeSA9IHNjb3BlLmNyZWF0ZU1ldHJpY0ZhY3RvcnkoKTtcbiAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeSA9IG5ldyBCYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkoXG4gICAgICB0aGlzLm1ldHJpY0ZhY3RvcnksXG4gICAgICB7IHNlcnZpY2U6IHByb3BzLmZhcmdhdGVTZXJ2aWNlIH0sXG4gICAgKTtcbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeSA9IGNyZWF0ZUxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkoXG4gICAgICAgIHRoaXMubWV0cmljRmFjdG9yeSxcbiAgICAgICAgcHJvcHMubG9hZEJhbGFuY2VyISxcbiAgICAgICAgcHJvcHMudGFyZ2V0R3JvdXAhLFxuICAgICAgICBwcm9wcy5pbnZlcnRMb2FkQmFsYW5jZXJUYXNrQ291bnRNZXRyaWNzU3RhdGlzdGljcyxcbiAgICAgICk7XG4gICAgICB0aGlzLmhlYWx0aHlUYXNrQ291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljSGVhbHRoeVRhc2tDb3VudCgpO1xuICAgICAgdGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljVW5oZWFsdGh5VGFza0NvdW50KCk7XG4gICAgICB0aGlzLmhlYWx0aHlUYXNrUGVyY2VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNIZWFsdGh5VGFza0luUGVyY2VudCgpO1xuICAgICAgdGhpcy5hY3RpdmVUY3BGbG93Q291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljQWN0aXZlQ29ubmVjdGlvbkNvdW50KCk7XG4gICAgICB0aGlzLm5ld1RjcEZsb3dDb3VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNOZXdDb25uZWN0aW9uQ291bnQoKTtcbiAgICAgIHRoaXMudW5oZWFsdGh5Um91dGluZ0Zsb3dDb3VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNVbmhlYWx0aHlSb3V0aW5nQ291bnQoKTtcbiAgICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljUHJvY2Vzc2VkQnl0ZXNNaW4oKTtcbiAgICB9XG4gICAgdGhpcy5jcHVVdGlsaXNhdGlvbk1ldHJpYyA9XG4gICAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeS5tZXRyaWNDbHVzdGVyQ3B1VXRpbGlzYXRpb25JblBlcmNlbnQoKTtcbiAgICB0aGlzLmNwdVAxMDBVdGlsaXNhdGlvbk1ldHJpYyA9XG4gICAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeS5tZXRyaWNDbHVzdGVyQ3B1VXRpbGlzYXRpb25JblBlcmNlbnQoXG4gICAgICAgIE1ldHJpY1N0YXRpc3RpYy5QMTAwLFxuICAgICAgKTtcbiAgICB0aGlzLm1lbW9yeVV0aWxpc2F0aW9uTWV0cmljID1cbiAgICAgIHRoaXMuYmFzZVNlcnZpY2VNZXRyaWNGYWN0b3J5Lm1ldHJpY0NsdXN0ZXJNZW1vcnlVdGlsaXNhdGlvbkluUGVyY2VudCgpO1xuICAgIHRoaXMubWVtb3J5UDEwMFV0aWxpc2F0aW9uTWV0cmljID1cbiAgICAgIHRoaXMuYmFzZVNlcnZpY2VNZXRyaWNGYWN0b3J5Lm1ldHJpY0NsdXN0ZXJNZW1vcnlVdGlsaXNhdGlvbkluUGVyY2VudChcbiAgICAgICAgTWV0cmljU3RhdGlzdGljLlAxMDAsXG4gICAgICApO1xuICAgIHRoaXMucnVubmluZ1Rhc2tDb3VudE1ldHJpYyA9XG4gICAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeS5tZXRyaWNSdW5uaW5nVGFza0NvdW50KCk7XG4gICAgdGhpcy5lcGhlbWVyYWxTdG9yYWdlVXNhZ2VNZXRyaWMgPVxuICAgICAgdGhpcy5iYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkubWV0cmljRXBoZW1lcmFsU3RvcmFnZVVzYWdlSW5QZXJjZW50KCk7XG5cbiAgICBjb25zdCBhbGFybUZhY3RvcnkgPSB0aGlzLmNyZWF0ZUFsYXJtRmFjdG9yeShcbiAgICAgIG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVBbGFybUZyaWVuZGx5TmFtZSgpLFxuICAgICk7XG4gICAgdGhpcy50YXNrSGVhbHRoQWxhcm1GYWN0b3J5ID0gbmV3IFRhc2tIZWFsdGhBbGFybUZhY3RvcnkoYWxhcm1GYWN0b3J5KTtcbiAgICB0aGlzLnRocm91Z2hwdXRBbGFybUZhY3RvcnkgPSBuZXcgVGhyb3VnaHB1dEFsYXJtRmFjdG9yeShhbGFybUZhY3RvcnkpO1xuICAgIHRoaXMudGFza0hlYWx0aEFubm90YXRpb25zID0gW107XG4gICAgdGhpcy51c2FnZUFsYXJtRmFjdG9yeSA9IG5ldyBVc2FnZUFsYXJtRmFjdG9yeShhbGFybUZhY3RvcnkpO1xuICAgIHRoaXMuY3B1VXNhZ2VBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMubWVtb3J5VXNhZ2VBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNBbm5vdGF0aW9ucyA9IFtdO1xuXG4gICAgaWYgKHByb3BzLm1pbkF1dG9TY2FsaW5nVGFza0NvdW50KSB7XG4gICAgICAvLyBUT0RPOiB1c2UgYW5ub3RhdGlvbiBzdHJhdGVneSB0byBjcmVhdGUgbmV1dHJhbCBhbm5vdGF0aW9uXG4gICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKHtcbiAgICAgICAgdmFsdWU6IHByb3BzLm1pbkF1dG9TY2FsaW5nVGFza0NvdW50LFxuICAgICAgICBsYWJlbDogXCJBdXRvU2NhbGluZzogTWluXCIsXG4gICAgICAgIGNvbG9yOiBOZXV0cmFsQ29sb3IsXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHByb3BzLm1heEF1dG9TY2FsaW5nVGFza0NvdW50KSB7XG4gICAgICAvLyBUT0RPOiB1c2UgYW5ub3RhdGlvbiBzdHJhdGVneSB0byBjcmVhdGUgbmV1dHJhbCBhbm5vdGF0aW9uXG4gICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKHtcbiAgICAgICAgdmFsdWU6IHByb3BzLm1heEF1dG9TY2FsaW5nVGFza0NvdW50LFxuICAgICAgICBsYWJlbDogXCJBdXRvU2NhbGluZzogTWF4XCIsXG4gICAgICAgIGNvbG9yOiBOZXV0cmFsQ29sb3IsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRIZWFsdGh5VGFza0NvdW50QWxhcm0pIHtcbiAgICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZEhlYWx0aHlUYXNrQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbGFybUZhY3RvcnkuYWRkSGVhbHRoeVRhc2tDb3VudEFsYXJtKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYyEsXG4gICAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgICApO1xuICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZFVuaGVhbHRoeVRhc2tDb3VudEFsYXJtKSB7XG4gICAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRVbmhlYWx0aHlUYXNrQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbGFybUZhY3RvcnkuYWRkVW5oZWFsdGh5VGFza0NvdW50QWxhcm0oXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICAgICAgdGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMhLFxuICAgICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgdGhpcy50YXNrSGVhbHRoQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRIZWFsdGh5VGFza1BlcmNlbnRBbGFybSkge1xuICAgICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkSGVhbHRoeVRhc2tQZXJjZW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgICAgdGhpcy50YXNrSGVhbHRoQWxhcm1GYWN0b3J5LmFkZEhlYWx0aHlUYXNrUGVyY2VudEFsYXJtKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHRoaXMuaGVhbHRoeVRhc2tQZXJjZW50TWV0cmljISxcbiAgICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkQ3B1VXNhZ2VBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZENwdVVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heENwdVVzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLmNwdVV0aWxpc2F0aW9uTWV0cmljLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgKTtcbiAgICAgIHRoaXMuY3B1VXNhZ2VBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZENwdVAxMDBVc2FnZUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkQ3B1UDEwMFVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heENwdVVzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLmNwdVAxMDBVdGlsaXNhdGlvbk1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgVXNhZ2VUeXBlLlAxMDAsXG4gICAgICApO1xuICAgICAgdGhpcy5jcHVVc2FnZUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkTWVtb3J5VXNhZ2VBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZE1lbW9yeVVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heE1lbW9yeVVzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLm1lbW9yeVV0aWxpc2F0aW9uTWV0cmljLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgKTtcbiAgICAgIHRoaXMubWVtb3J5VXNhZ2VBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZE1lbW9yeVAxMDBVc2FnZUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkTWVtb3J5UDEwMFVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1lbW9yeVVzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLm1lbW9yeVAxMDBVdGlsaXNhdGlvbk1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgVXNhZ2VUeXBlLlAxMDAsXG4gICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICApO1xuICAgICAgdGhpcy5tZW1vcnlVc2FnZUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRSdW5uaW5nVGFza0NvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRSdW5uaW5nVGFza0NvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnRhc2tIZWFsdGhBbGFybUZhY3RvcnkuYWRkUnVubmluZ1Rhc2tDb3VudEFsYXJtKFxuICAgICAgICB0aGlzLnJ1bm5pbmdUYXNrQ291bnRNZXRyaWMsXG4gICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICApO1xuICAgICAgdGhpcy50YXNrSGVhbHRoQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRFcGhlcm1hbFN0b3JhZ2VVc2FnZUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkRXBoZXJtYWxTdG9yYWdlVXNhZ2VBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMudXNhZ2VBbGFybUZhY3RvcnkuYWRkTWF4RGlza1VzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLmVwaGVtZXJhbFN0b3JhZ2VVc2FnZU1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGFzTG9hZEJhbGFuY2VyKSB7XG4gICAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkTWluUHJvY2Vzc2VkQnl0ZXNBbGFybSkge1xuICAgICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkTWluUHJvY2Vzc2VkQnl0ZXNBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgICB0aGlzLnRocm91Z2hwdXRBbGFybUZhY3RvcnkuYWRkTWluUHJvY2Vzc2VkQnl0ZXNBbGFybShcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NlZEJ5dGVzTWV0cmljISxcbiAgICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByb3BzLnVzZUNyZWF0ZWRBbGFybXM/LmNvbnN1bWUodGhpcy5jcmVhdGVkQWxhcm1zKCkpO1xuICB9XG5cbiAgc3VtbWFyeVdpZGdldHMoKTogSVdpZGdldFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgdGhpcy5jcmVhdGVUaXRsZVdpZGdldCgpLFxuICAgICAgdGhpcy5jcmVhdGVDcHVXaWRnZXQoVGhpcmRXaWR0aCwgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQpLFxuICAgICAgdGhpcy5jcmVhdGVNZW1vcnlXaWRnZXQoVGhpcmRXaWR0aCwgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQpLFxuICAgICAgdGhpcy5jcmVhdGVUYXNrSGVhbHRoV2lkZ2V0KFRoaXJkV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICBdO1xuICB9XG5cbiAgd2lkZ2V0cygpOiBJV2lkZ2V0W10ge1xuICAgIGNvbnN0IGJhc2VXaWRnZXQgPSBbXG4gICAgICB0aGlzLmNyZWF0ZVRpdGxlV2lkZ2V0KCksXG4gICAgICB0aGlzLmNyZWF0ZUNwdVdpZGdldChcbiAgICAgICAgdGhpcy5oYXNMb2FkQmFsYW5jZXIgPyBRdWFydGVyV2lkdGggOiBUaGlyZFdpZHRoLFxuICAgICAgICBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQsXG4gICAgICApLFxuICAgICAgdGhpcy5jcmVhdGVNZW1vcnlXaWRnZXQoXG4gICAgICAgIHRoaXMuaGFzTG9hZEJhbGFuY2VyID8gUXVhcnRlcldpZHRoIDogVGhpcmRXaWR0aCxcbiAgICAgICAgRGVmYXVsdEdyYXBoV2lkZ2V0SGVpZ2h0LFxuICAgICAgKSxcbiAgICBdO1xuXG4gICAgaWYgKHRoaXMuaGFzTG9hZEJhbGFuY2VyKSB7XG4gICAgICByZXR1cm4gYmFzZVdpZGdldC5jb25jYXQoW1xuICAgICAgICB0aGlzLmNyZWF0ZVRjcEZsb3dzV2lkZ2V0KFF1YXJ0ZXJXaWR0aCwgRGVmYXVsdEdyYXBoV2lkZ2V0SGVpZ2h0KSxcbiAgICAgICAgdGhpcy5jcmVhdGVUYXNrSGVhbHRoV2lkZ2V0KFF1YXJ0ZXJXaWR0aCwgRGVmYXVsdEdyYXBoV2lkZ2V0SGVpZ2h0KSxcbiAgICAgIF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYmFzZVdpZGdldC5jb25jYXQoXG4gICAgICAgIHRoaXMuY3JlYXRlVGFza0hlYWx0aFdpZGdldChUaGlyZFdpZHRoLCBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVUaXRsZVdpZGdldCgpIHtcbiAgICByZXR1cm4gbmV3IE1vbml0b3JpbmdIZWFkZXJXaWRnZXQoe1xuICAgICAgZmFtaWx5OiBcIkZhcmdhdGUgU2VydmljZVwiLFxuICAgICAgdGl0bGU6IHRoaXMudGl0bGUsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVDcHVXaWRnZXQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiQ1BVIFV0aWxpemF0aW9uXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5jcHVVdGlsaXNhdGlvbk1ldHJpYywgdGhpcy5jcHVQMTAwVXRpbGlzYXRpb25NZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmNwdVVzYWdlQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVNZW1vcnlXaWRnZXQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiTWVtb3J5IFV0aWxpemF0aW9uXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5tZW1vcnlVdGlsaXNhdGlvbk1ldHJpYywgdGhpcy5tZW1vcnlQMTAwVXRpbGlzYXRpb25NZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLm1lbW9yeVVzYWdlQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVUYXNrSGVhbHRoV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgY29uc3QgbGVmdCA9IFt0aGlzLnJ1bm5pbmdUYXNrQ291bnRNZXRyaWNdO1xuXG4gICAgaWYgKHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYykge1xuICAgICAgbGVmdC5wdXNoKHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudW5oZWFsdGh5VGFza0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogdGhpcy5oYXNMb2FkQmFsYW5jZXIgPyBcIlRhc2sgSGVhbHRoXCIgOiBcIlRhc2sgQ291bnRcIixcbiAgICAgIGxlZnQsXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZVRjcEZsb3dzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgY29uc3QgbGVmdDogSU1ldHJpY1tdID0gW107XG4gICAgY29uc3QgcmlnaHQ6IElNZXRyaWNbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMuYWN0aXZlVGNwRmxvd0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy5hY3RpdmVUY3BGbG93Q291bnRNZXRyaWMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm5ld1RjcEZsb3dDb3VudE1ldHJpYykge1xuICAgICAgbGVmdC5wdXNoKHRoaXMubmV3VGNwRmxvd0NvdW50TWV0cmljKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy51bmhlYWx0aHlSb3V0aW5nRmxvd0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy51bmhlYWx0aHlSb3V0aW5nRmxvd0NvdW50TWV0cmljKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9jZXNzZWRCeXRlc01ldHJpYykge1xuICAgICAgcmlnaHQucHVzaCh0aGlzLnByb2Nlc3NlZEJ5dGVzTWV0cmljKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiVENQIEZsb3dzXCIsXG4gICAgICBsZWZ0LFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIHJpZ2h0LFxuICAgICAgcmlnaHRZQXhpczogU2l6ZUF4aXNCeXRlc0Zyb21aZXJvLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSB7QHNlZSBjcmVhdGVUY3BGbG93c1dpZGdldH0gaW5zdGVhZC5cbiAgICovXG4gIGNyZWF0ZVRwY0Zsb3dzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGNwRmxvd3NXaWRnZXQod2lkdGgsIGhlaWdodCk7XG4gIH1cbn1cbiJdfQ==