cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
234 lines • 44.4 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 = 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.memoryUtilisationMetric =
this.baseServiceMetricFactory.metricClusterMemoryUtilisationInPercent();
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.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.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],
leftYAxis: common_1.PercentageAxisFromZeroToHundred,
leftAnnotations: this.cpuUsageAnnotations,
});
}
createMemoryWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Memory Utilization",
left: [this.memoryUtilisationMetric],
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: "9.15.2" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0RBS29DO0FBYXBDLHlFQUFzRTtBQUN0RSx5Q0F1QnNCO0FBQ3RCLCtDQUd5QjtBQUN6Qiw0REFLOEI7QUEyRzlCLE1BQWEsd0JBQXlCLFNBQVEsbUJBQVU7SUE2QnRELFlBQ0UsS0FBc0IsRUFDdEIsS0FBMEM7UUFFMUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVwQixJQUFJLENBQUMsZUFBZTtZQUNsQixLQUFLLENBQUMsWUFBWSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFNBQVMsQ0FBQztRQUV0RSxNQUFNLGNBQWMsR0FBRyxJQUFJLG9DQUF3QixDQUFDO1lBQ2xELEdBQUcsS0FBSztZQUNSLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYztTQUNyQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1FBRXZELElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDakQsSUFBSSxDQUFDLHdCQUF3QixHQUFHLElBQUksbURBQXdCLENBQzFELElBQUksQ0FBQyxhQUFhLEVBQ2xCLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FDbEMsQ0FBQztRQUNGLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUN4QixJQUFJLENBQUMseUJBQXlCLEdBQUcsbURBQStCLENBQzlELElBQUksQ0FBQyxhQUFhLEVBQ2xCLEtBQUssQ0FBQyxZQUFhLEVBQ25CLEtBQUssQ0FBQyxXQUFZLEVBQ2xCLEtBQUssQ0FBQyw0Q0FBNEMsQ0FDbkQsQ0FBQztZQUNGLElBQUksQ0FBQyxzQkFBc0I7Z0JBQ3pCLElB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Q3hDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLCtCQUErQixDQUFDLENBQUM7U0FDakQ7UUFFRCxJQUFJLElBQUksQ0FBQyxvQkFBb0IsRUFBRTtZQUM3QixLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1NBQ3ZDO1FBRUQsT0FBTyxJQUFJLDRCQUFXLENBQUM7WUFDckIsS0FBSztZQUNMLE1BQU07WUFDTixLQUFLLEVBQUUsV0FBVztZQUNsQixJQUFJO1lBQ0osU0FBUyxFQUFFLDBCQUFpQjtZQUM1QixLQUFLO1lBQ0wsVUFBVSxFQUFFLDhCQUFxQjtTQUNsQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxvQkFBb0IsQ0FBQyxLQUFhLEVBQUUsTUFBYztRQUNoRCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbEQsQ0FBQzs7QUFyVUgsNERBc1VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgR3JhcGhXaWRnZXQsXG4gIEhvcml6b250YWxBbm5vdGF0aW9uLFxuICBJTWV0cmljLFxuICBJV2lkZ2V0LFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIjtcbmltcG9ydCB7IEZhcmdhdGVTZXJ2aWNlLCBJQmFzZVNlcnZpY2UgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjc1wiO1xuaW1wb3J0IHtcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSxcbiAgTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjcy1wYXR0ZXJuc1wiO1xuaW1wb3J0IHtcbiAgSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICBJQXBwbGljYXRpb25UYXJnZXRHcm91cCxcbiAgSU5ldHdvcmtMb2FkQmFsYW5jZXIsXG4gIElOZXR3b3JrVGFyZ2V0R3JvdXAsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWxhc3RpY2xvYWRiYWxhbmNpbmd2MlwiO1xuXG5pbXBvcnQgeyBCYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkgfSBmcm9tIFwiLi9CYXNlU2VydmljZU1ldHJpY0ZhY3RvcnlcIjtcbmltcG9ydCB7XG4gIEJhc2VNb25pdG9yaW5nUHJvcHMsXG4gIENvdW50QXhpc0Zyb21aZXJvLFxuICBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQsXG4gIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0LFxuICBIZWFsdGh5VGFza0NvdW50VGhyZXNob2xkLFxuICBIZWFsdGh5VGFza1BlcmNlbnRUaHJlc2hvbGQsXG4gIE1ldHJpY0ZhY3RvcnksXG4gIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gIE1pblByb2Nlc3NlZEJ5dGVzVGhyZXNob2xkLFxuICBNb25pdG9yaW5nLFxuICBNb25pdG9yaW5nU2NvcGUsXG4gIE5ldXRyYWxDb2xvcixcbiAgUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgUXVhcnRlcldpZHRoLFxuICBSdW5uaW5nVGFza0NvdW50VGhyZXNob2xkLFxuICBTaXplQXhpc0J5dGVzRnJvbVplcm8sXG4gIFRhc2tIZWFsdGhBbGFybUZhY3RvcnksXG4gIFRoaXJkV2lkdGgsXG4gIFRocm91Z2hwdXRBbGFybUZhY3RvcnksXG4gIFVuaGVhbHRoeVRhc2tDb3VudFRocmVzaG9sZCxcbiAgVXNhZ2VBbGFybUZhY3RvcnksXG4gIFVzYWdlVGhyZXNob2xkLFxufSBmcm9tIFwiLi4vLi4vY29tbW9uXCI7XG5pbXBvcnQge1xuICBNb25pdG9yaW5nSGVhZGVyV2lkZ2V0LFxuICBNb25pdG9yaW5nTmFtaW5nU3RyYXRlZ3ksXG59IGZyb20gXCIuLi8uLi9kYXNoYm9hcmRcIjtcbmltcG9ydCB7XG4gIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeVByb3BzLFxuICBJTG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeSxcbiAgTmV0d29ya0xvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnlQcm9wcyxcbiAgY3JlYXRlTG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeSxcbn0gZnJvbSBcIi4uL2F3cy1sb2FkYmFsYW5jaW5nXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmFzZUZhcmdhdGVTZXJ2aWNlQWxhcm1zIHtcbiAgLyoqXG4gICAqIE1pbmltdW0gbnVtYmVyIG9mIHRhc2tzLCBhcyBzcGVjaWZpZWQgaW4geW91ciBhdXRvIHNjYWxpbmcgY29uZmlnLlxuICAgKi9cbiAgcmVhZG9ubHkgbWluQXV0b1NjYWxpbmdUYXNrQ291bnQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBNYXhpbXVtIG51bWJlciBvZiB0YXNrcywgYXMgc3BlY2lmaWVkIGluIHlvdXIgYXV0byBzY2FsaW5nIGNvbmZpZy5cbiAgICovXG4gIHJlYWRvbmx5IG1heEF1dG9TY2FsaW5nVGFza0NvdW50PzogbnVtYmVyO1xuICByZWFkb25seSBhZGRDcHVVc2FnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgVXNhZ2VUaHJlc2hvbGQ+O1xuICByZWFkb25seSBhZGRNZW1vcnlVc2FnZUFsYXJtPzogUmVjb3JkPHN0cmluZywgVXNhZ2VUaHJlc2hvbGQ+O1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgSW5zaWdodHMgbmVlZHMgdG8gYmUgZW5hYmxlZCBmb3IgdGhlIGNsdXN0ZXIgZm9yIHRoaXMgYWxhcm0uXG4gICAqL1xuICByZWFkb25seSBhZGRSdW5uaW5nVGFza0NvdW50QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBSdW5uaW5nVGFza0NvdW50VGhyZXNob2xkPjtcbiAgLyoqXG4gICAqIENvbnRhaW5lciBJbnNpZ2h0cyBuZWVkcyB0byBiZSBlbmFibGVkIGZvciB0aGUgY2x1c3RlciBmb3IgdGhpcyBhbGFybS5cbiAgICovXG4gIHJlYWRvbmx5IGFkZEVwaGVybWFsU3RvcmFnZVVzYWdlQWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBVc2FnZVRocmVzaG9sZD47XG59XG5cbi8qKlxuICogTW9uaXRvcmluZyBwcm9wcyBmb3IgYW55IHR5cGUgb2YgRmFyZ2F0ZSBzZXJ2aWNlLlxuICovXG5pbnRlcmZhY2UgQmFzZUZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgQmFzZU1vbml0b3JpbmdQcm9wcyxcbiAgICBCYXNlRmFyZ2F0ZVNlcnZpY2VBbGFybXMge31cblxuLyoqXG4gKiBNb25pdG9yaW5nIHByb3BzIGZvciBTaW1wbGUgRmFyZ2F0ZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpbXBsZUZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgQmFzZUZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgZmFyZ2F0ZVNlcnZpY2U6IEZhcmdhdGVTZXJ2aWNlO1xufVxuXG4vKipcbiAqIEJhc2Ugb2YgTW9uaXRvcmluZyBwcm9wcyBmb3IgbG9hZC1iYWxhbmNlZCBGYXJnYXRlIHNlcnZpY2UuXG4gKi9cbmludGVyZmFjZSBCYXNlTG9hZEJhbGFuY2VkRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHNcbiAgZXh0ZW5kcyBCYXNlRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBhZGRIZWFsdGh5VGFza0NvdW50QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBIZWFsdGh5VGFza0NvdW50VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkVW5oZWFsdGh5VGFza0NvdW50QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFVuaGVhbHRoeVRhc2tDb3VudFRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRIZWFsdGh5VGFza1BlcmNlbnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgSGVhbHRoeVRhc2tQZXJjZW50VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZE1pblByb2Nlc3NlZEJ5dGVzQWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIE1pblByb2Nlc3NlZEJ5dGVzVGhyZXNob2xkXG4gID47XG5cbiAgLyoqXG4gICAqIEludmVydCB0aGUgc3RhdGlzdGljcyBvZiBgSGVhbHRoeUhvc3RDb3VudGAgYW5kIGBVbkhlYWx0aHlIb3N0Q291bnRgLlxuICAgKlxuICAgKiBXaGVuIGBpbnZlcnRMb2FkQmFsYW5jZXJUYXNrQ291bnRNZXRyaWNzU3RhdGlzdGljc2AgaXMgc2V0IHRvIGZhbHNlLCB0aGUgbWluaW11bSBvZiBgSGVhbHRoeUhvc3RDb3VudGAgYW5kIHRoZSBtYXhpbXVtIG9mIGBVbkhlYWx0aHlIb3N0Q291bnRgIGFyZSBtb25pdG9yZWQuXG4gICAqIFdoZW4gYGludmVydExvYWRCYWxhbmNlclRhc2tDb3VudE1ldHJpY3NTdGF0aXN0aWNzYCBpcyBzZXQgdG8gdHJ1ZSwgdGhlIG1heGltdW0gb2YgYEhlYWx0aHlIb3N0Q291bnRgIGFuZCB0aGUgbWluaW11bSBvZiBgVW5IZWFsdGh5SG9zdENvdW50YCBhcmUgbW9uaXRvcmVkLlxuICAgKlxuICAgKiBgaW52ZXJ0TG9hZEJhbGFuY2VyVGFza0NvdW50TWV0cmljc1N0YXRpc3RpY3NgIGlzIHJlY29tbWVuZGVkIHRvIHNldCB0byB0cnVlIGFzIHBlciB0aGUgZ3VpZGVsaW5lcyBhdFxuaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2VsYXN0aWNsb2FkYmFsYW5jaW5nL2xhdGVzdC9uZXR3b3JrL2xvYWQtYmFsYW5jZXItY2xvdWR3YXRjaC1tZXRyaWNzLmh0bWwjbWV0cmljLXN0YXRpc3RpY3NcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGludmVydExvYWRCYWxhbmNlclRhc2tDb3VudE1ldHJpY3NTdGF0aXN0aWNzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBNb25pdG9yaW5nIHByb3BzIGZvciBsb2FkLWJhbGFuY2VkIEZhcmdhdGUgc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIEJhc2VMb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZU1vbml0b3JpbmdQcm9wcyB7XG4gIHJlYWRvbmx5IGZhcmdhdGVTZXJ2aWNlOlxuICAgIHwgTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlXG4gICAgfCBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlO1xufVxuXG4vKipcbiAqIE1vbml0b3JpbmcgcHJvcHMgZm9yIEZhcmdhdGUgc2VydmljZSB3aXRoIG5ldHdvcmsgbG9hZCBiYWxhbmNlciBhbmQgcGxhaW4gc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGYXJnYXRlTmV0d29ya0xvYWRCYWxhbmNlck1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIE5ldHdvcmtMb2FkQmFsYW5jZXJNZXRyaWNGYWN0b3J5UHJvcHMsXG4gICAgQmFzZUxvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgZmFyZ2F0ZVNlcnZpY2U6IEZhcmdhdGVTZXJ2aWNlO1xufVxuXG4vKipcbiAqIE1vbml0b3JpbmcgcHJvcHMgZm9yIEZhcmdhdGUgc2VydmljZSB3aXRoIGFwcGxpY2F0aW9uIGxvYWQgYmFsYW5jZXIgYW5kIHBsYWluIHNlcnZpY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmFyZ2F0ZUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNGYWN0b3J5UHJvcHMsXG4gICAgQmFzZUxvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgZmFyZ2F0ZVNlcnZpY2U6IEZhcmdhdGVTZXJ2aWNlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEN1c3RvbUZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgQmFzZUxvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgZmFyZ2F0ZVNlcnZpY2U6IElCYXNlU2VydmljZTtcbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyPzogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIHwgSU5ldHdvcmtMb2FkQmFsYW5jZXI7XG4gIHJlYWRvbmx5IHRhcmdldEdyb3VwPzogSUFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAgfCBJTmV0d29ya1RhcmdldEdyb3VwO1xufVxuXG5leHBvcnQgY2xhc3MgRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nIGV4dGVuZHMgTW9uaXRvcmluZyB7XG4gIHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG5cbiAgcmVhZG9ubHkgbWV0cmljRmFjdG9yeTogTWV0cmljRmFjdG9yeTtcbiAgcmVhZG9ubHkgYmFzZVNlcnZpY2VNZXRyaWNGYWN0b3J5OiBCYXNlU2VydmljZU1ldHJpY0ZhY3Rvcnk7XG4gIHJlYWRvbmx5IGxvYWRCYWxhbmNlck1ldHJpY0ZhY3Rvcnk/OiBJTG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeTtcblxuICByZWFkb25seSB0YXNrSGVhbHRoQWxhcm1GYWN0b3J5OiBUYXNrSGVhbHRoQWxhcm1GYWN0b3J5O1xuICByZWFkb25seSB0aHJvdWdocHV0QWxhcm1GYWN0b3J5OiBUaHJvdWdocHV0QWxhcm1GYWN0b3J5O1xuICByZWFkb25seSB0YXNrSGVhbHRoQW5ub3RhdGlvbnM6IEhvcml6b250YWxBbm5vdGF0aW9uW107XG4gIHJlYWRvbmx5IHVzYWdlQWxhcm1GYWN0b3J5OiBVc2FnZUFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgY3B1VXNhZ2VBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgbWVtb3J5VXNhZ2VBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgcHJvY2Vzc2VkQnl0ZXNBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcblxuICByZWFkb25seSBoZWFsdGh5VGFza0NvdW50TWV0cmljPzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgdW5oZWFsdGh5VGFza0NvdW50TWV0cmljPzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgaGVhbHRoeVRhc2tQZXJjZW50TWV0cmljPzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgY3B1VXRpbGlzYXRpb25NZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IG1lbW9yeVV0aWxpc2F0aW9uTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBydW5uaW5nVGFza0NvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBlcGhlbWVyYWxTdG9yYWdlVXNhZ2VNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IGFjdGl2ZVRjcEZsb3dDb3VudE1ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IG5ld1RjcEZsb3dDb3VudE1ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IHVuaGVhbHRoeVJvdXRpbmdGbG93Q291bnRNZXRyaWM/OiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBwcm9jZXNzZWRCeXRlc01ldHJpYz86IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG5cbiAgcHJpdmF0ZSBoYXNMb2FkQmFsYW5jZXI6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IE1vbml0b3JpbmdTY29wZSxcbiAgICBwcm9wczogQ3VzdG9tRmFyZ2F0ZVNlcnZpY2VNb25pdG9yaW5nUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBwcm9wcyk7XG5cbiAgICB0aGlzLmhhc0xvYWRCYWxhbmNlciA9XG4gICAgICBwcm9wcy5sb2FkQmFsYW5jZXIgIT09IHVuZGVmaW5lZCAmJiBwcm9wcy50YXJnZXRHcm91cCAhPT0gdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgbmFtaW5nU3RyYXRlZ3kgPSBuZXcgTW9uaXRvcmluZ05hbWluZ1N0cmF0ZWd5KHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgbmFtZWRDb25zdHJ1Y3Q6IHByb3BzLmZhcmdhdGVTZXJ2aWNlLFxuICAgIH0pO1xuICAgIHRoaXMudGl0bGUgPSBuYW1pbmdTdHJhdGVneS5yZXNvbHZlSHVtYW5SZWFkYWJsZU5hbWUoKTtcblxuICAgIHRoaXMubWV0cmljRmFjdG9yeSA9IHNjb3BlLmNyZWF0ZU1ldHJpY0ZhY3RvcnkoKTtcbiAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeSA9IG5ldyBCYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkoXG4gICAgICB0aGlzLm1ldHJpY0ZhY3RvcnksXG4gICAgICB7IHNlcnZpY2U6IHByb3BzLmZhcmdhdGVTZXJ2aWNlIH0sXG4gICAgKTtcbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeSA9IGNyZWF0ZUxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkoXG4gICAgICAgIHRoaXMubWV0cmljRmFjdG9yeSxcbiAgICAgICAgcHJvcHMubG9hZEJhbGFuY2VyISxcbiAgICAgICAgcHJvcHMudGFyZ2V0R3JvdXAhLFxuICAgICAgICBwcm9wcy5pbnZlcnRMb2FkQmFsYW5jZXJUYXNrQ291bnRNZXRyaWNzU3RhdGlzdGljcyxcbiAgICAgICk7XG4gICAgICB0aGlzLmhlYWx0aHlUYXNrQ291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljSGVhbHRoeVRhc2tDb3VudCgpO1xuICAgICAgdGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljVW5oZWFsdGh5VGFza0NvdW50KCk7XG4gICAgICB0aGlzLmhlYWx0aHlUYXNrUGVyY2VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNIZWFsdGh5VGFza0luUGVyY2VudCgpO1xuICAgICAgdGhpcy5hY3RpdmVUY3BGbG93Q291bnRNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljQWN0aXZlQ29ubmVjdGlvbkNvdW50KCk7XG4gICAgICB0aGlzLm5ld1RjcEZsb3dDb3VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNOZXdDb25uZWN0aW9uQ291bnQoKTtcbiAgICAgIHRoaXMudW5oZWFsdGh5Um91dGluZ0Zsb3dDb3VudE1ldHJpYyA9XG4gICAgICAgIHRoaXMubG9hZEJhbGFuY2VyTWV0cmljRmFjdG9yeS5tZXRyaWNVbmhlYWx0aHlSb3V0aW5nQ291bnQoKTtcbiAgICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNNZXRyaWMgPVxuICAgICAgICB0aGlzLmxvYWRCYWxhbmNlck1ldHJpY0ZhY3RvcnkubWV0cmljUHJvY2Vzc2VkQnl0ZXNNaW4oKTtcbiAgICB9XG4gICAgdGhpcy5jcHVVdGlsaXNhdGlvbk1ldHJpYyA9XG4gICAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeS5tZXRyaWNDbHVzdGVyQ3B1VXRpbGlzYXRpb25JblBlcmNlbnQoKTtcbiAgICB0aGlzLm1lbW9yeVV0aWxpc2F0aW9uTWV0cmljID1cbiAgICAgIHRoaXMuYmFzZVNlcnZpY2VNZXRyaWNGYWN0b3J5Lm1ldHJpY0NsdXN0ZXJNZW1vcnlVdGlsaXNhdGlvbkluUGVyY2VudCgpO1xuICAgIHRoaXMucnVubmluZ1Rhc2tDb3VudE1ldHJpYyA9XG4gICAgICB0aGlzLmJhc2VTZXJ2aWNlTWV0cmljRmFjdG9yeS5tZXRyaWNSdW5uaW5nVGFza0NvdW50KCk7XG4gICAgdGhpcy5lcGhlbWVyYWxTdG9yYWdlVXNhZ2VNZXRyaWMgPVxuICAgICAgdGhpcy5iYXNlU2VydmljZU1ldHJpY0ZhY3RvcnkubWV0cmljRXBoZW1lcmFsU3RvcmFnZVVzYWdlSW5QZXJjZW50KCk7XG5cbiAgICBjb25zdCBhbGFybUZhY3RvcnkgPSB0aGlzLmNyZWF0ZUFsYXJtRmFjdG9yeShcbiAgICAgIG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVBbGFybUZyaWVuZGx5TmFtZSgpLFxuICAgICk7XG4gICAgdGhpcy50YXNrSGVhbHRoQWxhcm1GYWN0b3J5ID0gbmV3IFRhc2tIZWFsdGhBbGFybUZhY3RvcnkoYWxhcm1GYWN0b3J5KTtcbiAgICB0aGlzLnRocm91Z2hwdXRBbGFybUZhY3RvcnkgPSBuZXcgVGhyb3VnaHB1dEFsYXJtRmFjdG9yeShhbGFybUZhY3RvcnkpO1xuICAgIHRoaXMudGFza0hlYWx0aEFubm90YXRpb25zID0gW107XG4gICAgdGhpcy51c2FnZUFsYXJtRmFjdG9yeSA9IG5ldyBVc2FnZUFsYXJtRmFjdG9yeShhbGFybUZhY3RvcnkpO1xuICAgIHRoaXMuY3B1VXNhZ2VBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMubWVtb3J5VXNhZ2VBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNBbm5vdGF0aW9ucyA9IFtdO1xuXG4gICAgaWYgKHByb3BzLm1pbkF1dG9TY2FsaW5nVGFza0NvdW50KSB7XG4gICAgICAvLyBUT0RPOiB1c2UgYW5ub3RhdGlvbiBzdHJhdGVneSB0byBjcmVhdGUgbmV1dHJhbCBhbm5vdGF0aW9uXG4gICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKHtcbiAgICAgICAgdmFsdWU6IHByb3BzLm1pbkF1dG9TY2FsaW5nVGFza0NvdW50LFxuICAgICAgICBsYWJlbDogXCJBdXRvU2NhbGluZzogTWluXCIsXG4gICAgICAgIGNvbG9yOiBOZXV0cmFsQ29sb3IsXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHByb3BzLm1heEF1dG9TY2FsaW5nVGFza0NvdW50KSB7XG4gICAgICAvLyBUT0RPOiB1c2UgYW5ub3RhdGlvbiBzdHJhdGVneSB0byBjcmVhdGUgbmV1dHJhbCBhbm5vdGF0aW9uXG4gICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKHtcbiAgICAgICAgdmFsdWU6IHByb3BzLm1heEF1dG9TY2FsaW5nVGFza0NvdW50LFxuICAgICAgICBsYWJlbDogXCJBdXRvU2NhbGluZzogTWF4XCIsXG4gICAgICAgIGNvbG9yOiBOZXV0cmFsQ29sb3IsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRIZWFsdGh5VGFza0NvdW50QWxhcm0pIHtcbiAgICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZEhlYWx0aHlUYXNrQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbGFybUZhY3RvcnkuYWRkSGVhbHRoeVRhc2tDb3VudEFsYXJtKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYyEsXG4gICAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgICApO1xuICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZFVuaGVhbHRoeVRhc2tDb3VudEFsYXJtKSB7XG4gICAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRVbmhlYWx0aHlUYXNrQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgICB0aGlzLnRhc2tIZWFsdGhBbGFybUZhY3RvcnkuYWRkVW5oZWFsdGh5VGFza0NvdW50QWxhcm0oXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICAgICAgdGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMhLFxuICAgICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgdGhpcy50YXNrSGVhbHRoQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRIZWFsdGh5VGFza1BlcmNlbnRBbGFybSkge1xuICAgICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkSGVhbHRoeVRhc2tQZXJjZW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgICAgdGhpcy50YXNrSGVhbHRoQWxhcm1GYWN0b3J5LmFkZEhlYWx0aHlUYXNrUGVyY2VudEFsYXJtKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHRoaXMuaGVhbHRoeVRhc2tQZXJjZW50TWV0cmljISxcbiAgICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkQ3B1VXNhZ2VBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZENwdVVzYWdlQWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLnVzYWdlQWxhcm1GYWN0b3J5LmFkZE1heENwdVVzYWdlUGVyY2VudEFsYXJtKFxuICAgICAgICB0aGlzLmNwdVV0aWxpc2F0aW9uTWV0cmljLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgKTtcbiAgICAgIHRoaXMuY3B1VXNhZ2VBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZE1lbW9yeVVzYWdlQWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRNZW1vcnlVc2FnZUFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy51c2FnZUFsYXJtRmFjdG9yeS5hZGRNYXhNZW1vcnlVc2FnZVBlcmNlbnRBbGFybShcbiAgICAgICAgdGhpcy5tZW1vcnlVdGlsaXNhdGlvbk1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLm1lbW9yeVVzYWdlQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZFJ1bm5pbmdUYXNrQ291bnRBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZFJ1bm5pbmdUYXNrQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMudGFza0hlYWx0aEFsYXJtRmFjdG9yeS5hZGRSdW5uaW5nVGFza0NvdW50QWxhcm0oXG4gICAgICAgIHRoaXMucnVubmluZ1Rhc2tDb3VudE1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZEVwaGVybWFsU3RvcmFnZVVzYWdlQWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRFcGhlcm1hbFN0b3JhZ2VVc2FnZUFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy51c2FnZUFsYXJtRmFjdG9yeS5hZGRNYXhEaXNrVXNhZ2VQZXJjZW50QWxhcm0oXG4gICAgICAgIHRoaXMuZXBoZW1lcmFsU3RvcmFnZVVzYWdlTWV0cmljLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRNaW5Qcm9jZXNzZWRCeXRlc0FsYXJtKSB7XG4gICAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRNaW5Qcm9jZXNzZWRCeXRlc0FsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICAgIHRoaXMudGhyb3VnaHB1dEFsYXJtRmFjdG9yeS5hZGRNaW5Qcm9jZXNzZWRCeXRlc0FsYXJtKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2VkQnl0ZXNNZXRyaWMhLFxuICAgICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgdGhpcy5wcm9jZXNzZWRCeXRlc0Fubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJvcHMudXNlQ3JlYXRlZEFsYXJtcz8uY29uc3VtZSh0aGlzLmNyZWF0ZWRBbGFybXMoKSk7XG4gIH1cblxuICBzdW1tYXJ5V2lkZ2V0cygpOiBJV2lkZ2V0W10ge1xuICAgIHJldHVybiBbXG4gICAgICB0aGlzLmNyZWF0ZVRpdGxlV2lkZ2V0KCksXG4gICAgICB0aGlzLmNyZWF0ZUNwdVdpZGdldChUaGlyZFdpZHRoLCBEZWZhdWx0U3VtbWFyeVdpZGdldEhlaWdodCksXG4gICAgICB0aGlzLmNyZWF0ZU1lbW9yeVdpZGdldChUaGlyZFdpZHRoLCBEZWZhdWx0U3VtbWFyeVdpZGdldEhlaWdodCksXG4gICAgICB0aGlzLmNyZWF0ZVRhc2tIZWFsdGhXaWRnZXQoVGhpcmRXaWR0aCwgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQpLFxuICAgIF07XG4gIH1cblxuICB3aWRnZXRzKCk6IElXaWRnZXRbXSB7XG4gICAgY29uc3QgYmFzZVdpZGdldCA9IFtcbiAgICAgIHRoaXMuY3JlYXRlVGl0bGVXaWRnZXQoKSxcbiAgICAgIHRoaXMuY3JlYXRlQ3B1V2lkZ2V0KFxuICAgICAgICB0aGlzLmhhc0xvYWRCYWxhbmNlciA/IFF1YXJ0ZXJXaWR0aCA6IFRoaXJkV2lkdGgsXG4gICAgICAgIERlZmF1bHRHcmFwaFdpZGdldEhlaWdodCxcbiAgICAgICksXG4gICAgICB0aGlzLmNyZWF0ZU1lbW9yeVdpZGdldChcbiAgICAgICAgdGhpcy5oYXNMb2FkQmFsYW5jZXIgPyBRdWFydGVyV2lkdGggOiBUaGlyZFdpZHRoLFxuICAgICAgICBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQsXG4gICAgICApLFxuICAgIF07XG5cbiAgICBpZiAodGhpcy5oYXNMb2FkQmFsYW5jZXIpIHtcbiAgICAgIHJldHVybiBiYXNlV2lkZ2V0LmNvbmNhdChbXG4gICAgICAgIHRoaXMuY3JlYXRlVGNwRmxvd3NXaWRnZXQoUXVhcnRlcldpZHRoLCBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgICAgICB0aGlzLmNyZWF0ZVRhc2tIZWFsdGhXaWRnZXQoUXVhcnRlcldpZHRoLCBEZWZhdWx0R3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgICAgXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBiYXNlV2lkZ2V0LmNvbmNhdChcbiAgICAgICAgdGhpcy5jcmVhdGVUYXNrSGVhbHRoV2lkZ2V0KFRoaXJkV2lkdGgsIERlZmF1bHRHcmFwaFdpZGdldEhlaWdodCksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGNyZWF0ZVRpdGxlV2lkZ2V0KCkge1xuICAgIHJldHVybiBuZXcgTW9uaXRvcmluZ0hlYWRlcldpZGdldCh7XG4gICAgICBmYW1pbHk6IFwiRmFyZ2F0ZSBTZXJ2aWNlXCIsXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZUNwdVdpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJDUFUgVXRpbGl6YXRpb25cIixcbiAgICAgIGxlZnQ6IFt0aGlzLmNwdVV0aWxpc2F0aW9uTWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5jcHVVc2FnZUFubm90YXRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlTWVtb3J5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIk1lbW9yeSBVdGlsaXphdGlvblwiLFxuICAgICAgbGVmdDogW3RoaXMubWVtb3J5VXRpbGlzYXRpb25NZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLm1lbW9yeVVzYWdlQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVUYXNrSGVhbHRoV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgY29uc3QgbGVmdCA9IFt0aGlzLnJ1bm5pbmdUYXNrQ291bnRNZXRyaWNdO1xuXG4gICAgaWYgKHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYykge1xuICAgICAgbGVmdC5wdXNoKHRoaXMuaGVhbHRoeVRhc2tDb3VudE1ldHJpYyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudW5oZWFsdGh5VGFza0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy51bmhlYWx0aHlUYXNrQ291bnRNZXRyaWMpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogdGhpcy5oYXNMb2FkQmFsYW5jZXIgPyBcIlRhc2sgSGVhbHRoXCIgOiBcIlRhc2sgQ291bnRcIixcbiAgICAgIGxlZnQsXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLnRhc2tIZWFsdGhBbm5vdGF0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZVRjcEZsb3dzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgY29uc3QgbGVmdDogSU1ldHJpY1tdID0gW107XG4gICAgY29uc3QgcmlnaHQ6IElNZXRyaWNbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMuYWN0aXZlVGNwRmxvd0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy5hY3RpdmVUY3BGbG93Q291bnRNZXRyaWMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm5ld1RjcEZsb3dDb3VudE1ldHJpYykge1xuICAgICAgbGVmdC5wdXNoKHRoaXMubmV3VGNwRmxvd0NvdW50TWV0cmljKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy51bmhlYWx0aHlSb3V0aW5nRmxvd0NvdW50TWV0cmljKSB7XG4gICAgICBsZWZ0LnB1c2godGhpcy51bmhlYWx0aHlSb3V0aW5nRmxvd0NvdW50TWV0cmljKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9jZXNzZWRCeXRlc01ldHJpYykge1xuICAgICAgcmlnaHQucHVzaCh0aGlzLnByb2Nlc3NlZEJ5dGVzTWV0cmljKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiVENQIEZsb3dzXCIsXG4gICAgICBsZWZ0LFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIHJpZ2h0LFxuICAgICAgcmlnaHRZQXhpczogU2l6ZUF4aXNCeXRlc0Zyb21aZXJvLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSB7QHNlZSBjcmVhdGVUY3BGbG93c1dpZGdldH0gaW5zdGVhZC5cbiAgICovXG4gIGNyZWF0ZVRwY0Zsb3dzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGNwRmxvd3NXaWRnZXQod2lkdGgsIGhlaWdodCk7XG4gIH1cbn1cbiJdfQ==