@cdklabs/multi-az-observability 0.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +10177 -0
- package/API.md +5119 -0
- package/LICENSE +202 -0
- package/README.md +175 -0
- package/cdk.json +68 -0
- package/lib/alarmsandrules/AvailabilityAndLatencyAlarmsAndRules.d.ts +214 -0
- package/lib/alarmsandrules/AvailabilityAndLatencyAlarmsAndRules.js +763 -0
- package/lib/alarmsandrules/BaseOperationRegionalAlarmsAndRules.d.ts +22 -0
- package/lib/alarmsandrules/BaseOperationRegionalAlarmsAndRules.js +21 -0
- package/lib/alarmsandrules/BaseOperationZonalAlarmsAndRules.d.ts +34 -0
- package/lib/alarmsandrules/BaseOperationZonalAlarmsAndRules.js +39 -0
- package/lib/alarmsandrules/CanaryOperationRegionalAlarmsAndRules.d.ts +7 -0
- package/lib/alarmsandrules/CanaryOperationRegionalAlarmsAndRules.js +11 -0
- package/lib/alarmsandrules/CanaryOperationZonalAlarmsAndRules.d.ts +16 -0
- package/lib/alarmsandrules/CanaryOperationZonalAlarmsAndRules.js +17 -0
- package/lib/alarmsandrules/IBaseOperationRegionalAlarmsAndRules.d.ts +18 -0
- package/lib/alarmsandrules/IBaseOperationRegionalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/IBaseOperationZonalAlarmsAndRules.d.ts +30 -0
- package/lib/alarmsandrules/IBaseOperationZonalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/ICanaryOperationRegionalAlarmsAndRules.d.ts +6 -0
- package/lib/alarmsandrules/ICanaryOperationRegionalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/ICanaryOperationZonalAlarmsAndRules.d.ts +12 -0
- package/lib/alarmsandrules/ICanaryOperationZonalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/IOperationAlarmsAndRules.d.ts +55 -0
- package/lib/alarmsandrules/IOperationAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/IServerSideOperationRegionalAlarmsAndRules.d.ts +15 -0
- package/lib/alarmsandrules/IServerSideOperationRegionalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/IServerSideOperationZonalAlarmsAndRules.d.ts +36 -0
- package/lib/alarmsandrules/IServerSideOperationZonalAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/IServiceAlarmsAndRules.d.ts +44 -0
- package/lib/alarmsandrules/IServiceAlarmsAndRules.js +3 -0
- package/lib/alarmsandrules/InsightRuleBody.d.ts +67 -0
- package/lib/alarmsandrules/InsightRuleBody.js +46 -0
- package/lib/alarmsandrules/OperationAlarmsAndRules.d.ts +59 -0
- package/lib/alarmsandrules/OperationAlarmsAndRules.js +135 -0
- package/lib/alarmsandrules/ServerSideOperationRegionalAlarmsAndRules.d.ts +19 -0
- package/lib/alarmsandrules/ServerSideOperationRegionalAlarmsAndRules.js +22 -0
- package/lib/alarmsandrules/ServerSideOperationZonalAlarmsAndRules.d.ts +40 -0
- package/lib/alarmsandrules/ServerSideOperationZonalAlarmsAndRules.js +46 -0
- package/lib/alarmsandrules/ServiceAlarmsAndRules.d.ts +48 -0
- package/lib/alarmsandrules/ServiceAlarmsAndRules.js +166 -0
- package/lib/alarmsandrules/props/BaseOperationRegionalAlarmsAndRulesProps.d.ts +24 -0
- package/lib/alarmsandrules/props/BaseOperationRegionalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/BaseOperationZonalAlarmsAndRulesProps.d.ts +62 -0
- package/lib/alarmsandrules/props/BaseOperationZonalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/CanaryOperationRegionalAlarmsAndRulesProps.d.ts +6 -0
- package/lib/alarmsandrules/props/CanaryOperationRegionalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/CanaryOperationZonalAlarmsAndRulesProps.d.ts +6 -0
- package/lib/alarmsandrules/props/CanaryOperationZonalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/OperationAlarmsAndRulesProps.d.ts +45 -0
- package/lib/alarmsandrules/props/OperationAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/ServerSideOperationRegionalAlarmsAndRulesProps.d.ts +6 -0
- package/lib/alarmsandrules/props/ServerSideOperationRegionalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/ServerSideOperationZonalAlarmsAndRulesProps.d.ts +6 -0
- package/lib/alarmsandrules/props/ServerSideOperationZonalAlarmsAndRulesProps.js +3 -0
- package/lib/alarmsandrules/props/ServiceAlarmsAndRulesProps.d.ts +13 -0
- package/lib/alarmsandrules/props/ServiceAlarmsAndRulesProps.js +3 -0
- package/lib/azmapper/AvailabilityZoneMapper.d.ts +86 -0
- package/lib/azmapper/AvailabilityZoneMapper.js +200 -0
- package/lib/azmapper/IAvailabilityZoneMapper.d.ts +86 -0
- package/lib/azmapper/IAvailabilityZoneMapper.js +3 -0
- package/lib/azmapper/props/AvailabilityZoneMapperProps.d.ts +13 -0
- package/lib/azmapper/props/AvailabilityZoneMapperProps.js +3 -0
- package/lib/azmapper/src/index.py +107 -0
- package/lib/canaries/CanaryFunction.d.ts +16 -0
- package/lib/canaries/CanaryFunction.js +152 -0
- package/lib/canaries/CanaryTest.d.ts +10 -0
- package/lib/canaries/CanaryTest.js +84 -0
- package/lib/canaries/ICanaryFunction.d.ts +6 -0
- package/lib/canaries/ICanaryFunction.js +3 -0
- package/lib/canaries/props/AddCanaryTestProps.d.ts +66 -0
- package/lib/canaries/props/AddCanaryTestProps.js +3 -0
- package/lib/canaries/props/CanaryFunctionProps.d.ts +29 -0
- package/lib/canaries/props/CanaryFunctionProps.js +3 -0
- package/lib/canaries/props/CanaryTestProps.d.ts +21 -0
- package/lib/canaries/props/CanaryTestProps.js +3 -0
- package/lib/canaries/props/NetworkConfigurationProps.d.ts +16 -0
- package/lib/canaries/props/NetworkConfigurationProps.js +3 -0
- package/lib/canaries/src/canary.zip +0 -0
- package/lib/dashboards/BasicServiceDashboard.d.ts +10 -0
- package/lib/dashboards/BasicServiceDashboard.js +130 -0
- package/lib/dashboards/ContributorInsightsWidget.d.ts +22 -0
- package/lib/dashboards/ContributorInsightsWidget.js +55 -0
- package/lib/dashboards/IOperationAvailabilityAndLatencyDashboard.d.ts +10 -0
- package/lib/dashboards/IOperationAvailabilityAndLatencyDashboard.js +3 -0
- package/lib/dashboards/IServiceAvailabilityAndLatencyDashboard.d.ts +10 -0
- package/lib/dashboards/IServiceAvailabilityAndLatencyDashboard.js +3 -0
- package/lib/dashboards/OperationAvailabilityAndLatencyDashboard.d.ts +20 -0
- package/lib/dashboards/OperationAvailabilityAndLatencyDashboard.js +588 -0
- package/lib/dashboards/ServiceAvailabilityAndLatencyDashboard.d.ts +24 -0
- package/lib/dashboards/ServiceAvailabilityAndLatencyDashboard.js +475 -0
- package/lib/dashboards/props/BasicServiceDashboardProps.d.ts +23 -0
- package/lib/dashboards/props/BasicServiceDashboardProps.js +3 -0
- package/lib/dashboards/props/ContributorInsightWidgetProps.d.ts +31 -0
- package/lib/dashboards/props/ContributorInsightWidgetProps.js +3 -0
- package/lib/dashboards/props/OperationAvailabilityAndLatencyDashboardProps.d.ts +84 -0
- package/lib/dashboards/props/OperationAvailabilityAndLatencyDashboardProps.js +3 -0
- package/lib/dashboards/props/OperationAvailabilityWidgetProps.d.ts +37 -0
- package/lib/dashboards/props/OperationAvailabilityWidgetProps.js +3 -0
- package/lib/dashboards/props/OperationLatencyWidgetProps.d.ts +37 -0
- package/lib/dashboards/props/OperationLatencyWidgetProps.js +3 -0
- package/lib/dashboards/props/ServiceAvailabilityAndLatencyDashboardProps.d.ts +30 -0
- package/lib/dashboards/props/ServiceAvailabilityAndLatencyDashboardProps.js +3 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.js +30 -0
- package/lib/metrics/ApplicationLoadBalancerMetrics.d.ts +36 -0
- package/lib/metrics/ApplicationLoadBalancerMetrics.js +150 -0
- package/lib/metrics/AvailabilityAndLatencyMetrics.d.ts +61 -0
- package/lib/metrics/AvailabilityAndLatencyMetrics.js +212 -0
- package/lib/metrics/NetworkLoadBalancerMetrics.d.ts +19 -0
- package/lib/metrics/NetworkLoadBalancerMetrics.js +48 -0
- package/lib/metrics/RegionalAvailabilityMetrics.d.ts +19 -0
- package/lib/metrics/RegionalAvailabilityMetrics.js +71 -0
- package/lib/metrics/RegionalLatencyMetrics.d.ts +33 -0
- package/lib/metrics/RegionalLatencyMetrics.js +69 -0
- package/lib/metrics/ZonalAvailabilityMetrics.d.ts +19 -0
- package/lib/metrics/ZonalAvailabilityMetrics.js +71 -0
- package/lib/metrics/ZonalLatencyMetrics.d.ts +29 -0
- package/lib/metrics/ZonalLatencyMetrics.js +65 -0
- package/lib/metrics/props/AvailabilityAndLatencyMetricProps.d.ts +23 -0
- package/lib/metrics/props/AvailabilityAndLatencyMetricProps.js +3 -0
- package/lib/metrics/props/AvailabilityMetricProps.d.ts +11 -0
- package/lib/metrics/props/AvailabilityMetricProps.js +3 -0
- package/lib/metrics/props/LatencyMetricProps.d.ts +15 -0
- package/lib/metrics/props/LatencyMetricProps.js +3 -0
- package/lib/metrics/props/RegionalAvailabilityMetricProps.d.ts +6 -0
- package/lib/metrics/props/RegionalAvailabilityMetricProps.js +3 -0
- package/lib/metrics/props/RegionalLatencyMetricProps.d.ts +6 -0
- package/lib/metrics/props/RegionalLatencyMetricProps.js +3 -0
- package/lib/metrics/props/ServiceAvailabilityMetricProps.d.ts +23 -0
- package/lib/metrics/props/ServiceAvailabilityMetricProps.js +3 -0
- package/lib/metrics/props/ServiceLatencyMericProps.d.ts +23 -0
- package/lib/metrics/props/ServiceLatencyMericProps.js +3 -0
- package/lib/metrics/props/ZonalAvailabilityMetricProps.d.ts +10 -0
- package/lib/metrics/props/ZonalAvailabilityMetricProps.js +3 -0
- package/lib/metrics/props/ZonalLatencyMetricProps.d.ts +10 -0
- package/lib/metrics/props/ZonalLatencyMetricProps.js +3 -0
- package/lib/monitoring/src/monitoring-layer.zip +0 -0
- package/lib/outlier-detection/IOutlierDetectionFunction.d.ts +12 -0
- package/lib/outlier-detection/IOutlierDetectionFunction.js +3 -0
- package/lib/outlier-detection/OutlierDetectionFunction.d.ts +16 -0
- package/lib/outlier-detection/OutlierDetectionFunction.js +126 -0
- package/lib/outlier-detection/props/OutlierDetectionFunctionProps.d.ts +12 -0
- package/lib/outlier-detection/props/OutlierDetectionFunctionProps.js +3 -0
- package/lib/outlier-detection/src/outlier-detection.zip +0 -0
- package/lib/outlier-detection/src/scipy-layer.zip +0 -0
- package/lib/services/BasicServiceMultiAZObservability.d.ts +64 -0
- package/lib/services/BasicServiceMultiAZObservability.js +504 -0
- package/lib/services/CanaryMetrics.d.ts +17 -0
- package/lib/services/CanaryMetrics.js +19 -0
- package/lib/services/CanaryTestMetricsOverride.d.ts +39 -0
- package/lib/services/CanaryTestMetricsOverride.js +23 -0
- package/lib/services/ContributorInsightRuleDetails.d.ts +42 -0
- package/lib/services/ContributorInsightRuleDetails.js +23 -0
- package/lib/services/IBasicServiceMultiAZObservability.d.ts +45 -0
- package/lib/services/IBasicServiceMultiAZObservability.js +3 -0
- package/lib/services/ICanaryMetrics.d.ts +14 -0
- package/lib/services/ICanaryMetrics.js +3 -0
- package/lib/services/ICanaryTestMetricsOverride.d.ts +36 -0
- package/lib/services/ICanaryTestMetricsOverride.js +3 -0
- package/lib/services/IContributorInsightRuleDetails.d.ts +38 -0
- package/lib/services/IContributorInsightRuleDetails.js +3 -0
- package/lib/services/IInstrumentedServiceMultiAZObservability.d.ts +39 -0
- package/lib/services/IInstrumentedServiceMultiAZObservability.js +3 -0
- package/lib/services/IOperation.d.ts +75 -0
- package/lib/services/IOperation.js +3 -0
- package/lib/services/IOperationMetricDetails.d.ts +78 -0
- package/lib/services/IOperationMetricDetails.js +3 -0
- package/lib/services/IService.d.ts +76 -0
- package/lib/services/IService.js +3 -0
- package/lib/services/IServiceMetricDetails.d.ts +68 -0
- package/lib/services/IServiceMetricDetails.js +3 -0
- package/lib/services/InstrumentedServiceMultiAZObservability.d.ts +55 -0
- package/lib/services/InstrumentedServiceMultiAZObservability.js +310 -0
- package/lib/services/Operation.d.ts +78 -0
- package/lib/services/Operation.js +34 -0
- package/lib/services/OperationMetricDetails.d.ts +82 -0
- package/lib/services/OperationMetricDetails.js +50 -0
- package/lib/services/Service.d.ts +80 -0
- package/lib/services/Service.js +36 -0
- package/lib/services/ServiceMetricDetails.d.ts +71 -0
- package/lib/services/ServiceMetricDetails.js +28 -0
- package/lib/services/props/BasicServiceMultiAZObservabilityProps.d.ts +126 -0
- package/lib/services/props/BasicServiceMultiAZObservabilityProps.js +3 -0
- package/lib/services/props/CanaryMetricProps.d.ts +14 -0
- package/lib/services/props/CanaryMetricProps.js +3 -0
- package/lib/services/props/CanaryTestMetricsOverrideProps.d.ts +47 -0
- package/lib/services/props/CanaryTestMetricsOverrideProps.js +3 -0
- package/lib/services/props/ContributorInsightRuleDetailsProps.d.ts +38 -0
- package/lib/services/props/ContributorInsightRuleDetailsProps.js +3 -0
- package/lib/services/props/InstrumentedServiceMultiAZObservabilityProps.d.ts +88 -0
- package/lib/services/props/InstrumentedServiceMultiAZObservabilityProps.js +3 -0
- package/lib/services/props/MetricDimensions.d.ts +61 -0
- package/lib/services/props/MetricDimensions.js +63 -0
- package/lib/services/props/OperationMetricDetailsProps.d.ts +97 -0
- package/lib/services/props/OperationMetricDetailsProps.js +3 -0
- package/lib/services/props/OperationProps.d.ts +93 -0
- package/lib/services/props/OperationProps.js +3 -0
- package/lib/services/props/ServiceMetricDetailsProps.d.ts +68 -0
- package/lib/services/props/ServiceMetricDetailsProps.js +3 -0
- package/lib/services/props/ServiceProps.d.ts +69 -0
- package/lib/services/props/ServiceProps.js +3 -0
- package/lib/utilities/AvailabilityMetricType.d.ts +26 -0
- package/lib/utilities/AvailabilityMetricType.js +33 -0
- package/lib/utilities/LatencyMetricType.d.ts +13 -0
- package/lib/utilities/LatencyMetricType.js +20 -0
- package/lib/utilities/OutlierDetectionAlgorithm.d.ts +42 -0
- package/lib/utilities/OutlierDetectionAlgorithm.js +49 -0
- package/lib/utilities/StackWithDynamicSource.d.ts +14 -0
- package/lib/utilities/StackWithDynamicSource.js +82 -0
- package/package.json +176 -0
- package/rosetta/default.ts-fixture +13 -0
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperationAvailabilityAndLatencyDashboard = void 0;
|
|
4
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
7
|
+
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
|
|
8
|
+
const constructs_1 = require("constructs");
|
|
9
|
+
const ContributorInsightsWidget_1 = require("./ContributorInsightsWidget");
|
|
10
|
+
const ApplicationLoadBalancerMetrics_1 = require("../metrics/ApplicationLoadBalancerMetrics");
|
|
11
|
+
const AvailabilityAndLatencyMetrics_1 = require("../metrics/AvailabilityAndLatencyMetrics");
|
|
12
|
+
const NetworkLoadBalancerMetrics_1 = require("../metrics/NetworkLoadBalancerMetrics");
|
|
13
|
+
const RegionalAvailabilityMetrics_1 = require("../metrics/RegionalAvailabilityMetrics");
|
|
14
|
+
const RegionalLatencyMetrics_1 = require("../metrics/RegionalLatencyMetrics");
|
|
15
|
+
const ZonalAvailabilityMetrics_1 = require("../metrics/ZonalAvailabilityMetrics");
|
|
16
|
+
const ZonalLatencyMetrics_1 = require("../metrics/ZonalLatencyMetrics");
|
|
17
|
+
const AvailabilityMetricType_1 = require("../utilities/AvailabilityMetricType");
|
|
18
|
+
const LatencyMetricType_1 = require("../utilities/LatencyMetricType");
|
|
19
|
+
/**
|
|
20
|
+
* Creates an operation level availability and latency dashboard
|
|
21
|
+
*/
|
|
22
|
+
class OperationAvailabilityAndLatencyDashboard extends constructs_1.Construct {
|
|
23
|
+
static createTopLevelAggregateAlarmWidgets(props, title, availabilityZoneIds) {
|
|
24
|
+
let topLevelAggregateAlarms = [
|
|
25
|
+
new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: title }),
|
|
26
|
+
new aws_cloudwatch_1.AlarmStatusWidget({
|
|
27
|
+
height: 2,
|
|
28
|
+
width: 24,
|
|
29
|
+
alarms: [props.regionalImpactAlarm],
|
|
30
|
+
title: props.operation.operationName + ' Regional Impact',
|
|
31
|
+
}),
|
|
32
|
+
];
|
|
33
|
+
for (let i = 0; i < availabilityZoneIds.length; i++) {
|
|
34
|
+
let availabilityZoneId = availabilityZoneIds[i];
|
|
35
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.AlarmStatusWidget({
|
|
36
|
+
height: 2,
|
|
37
|
+
width: 8,
|
|
38
|
+
alarms: [props.isolatedAZImpactAlarms[i]],
|
|
39
|
+
title: availabilityZoneId + ' Isolated Impact',
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: '**AZ Contributors**' }));
|
|
43
|
+
let zonalServerSideHighLatencyMetrics = [];
|
|
44
|
+
let zonalServerSideFaultCountMetrics = [];
|
|
45
|
+
let zonalCanaryHighLatencyMetrics = [];
|
|
46
|
+
let zonalCanaryFaultCountMetrics = [];
|
|
47
|
+
let keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar('');
|
|
48
|
+
for (let i = 0; i < availabilityZoneIds.length; i++) {
|
|
49
|
+
let availabilityZoneId = availabilityZoneIds[i];
|
|
50
|
+
zonalServerSideHighLatencyMetrics.push(ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalCountLatencyMetric({
|
|
51
|
+
availabilityZoneId: availabilityZoneId,
|
|
52
|
+
metricDetails: props.operation.serverSideLatencyMetricDetails,
|
|
53
|
+
label: availabilityZoneId + ' high latency responses',
|
|
54
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
55
|
+
statistic: `TC(${props.operation.serverSideLatencyMetricDetails.successAlarmThreshold}:)`,
|
|
56
|
+
keyPrefix: keyPrefix,
|
|
57
|
+
}));
|
|
58
|
+
zonalServerSideFaultCountMetrics.push(ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
59
|
+
availabilityZoneId: availabilityZoneId,
|
|
60
|
+
metricDetails: props.operation.serverSideAvailabilityMetricDetails,
|
|
61
|
+
label: availabilityZoneId + ' fault count',
|
|
62
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
63
|
+
keyPrefix: keyPrefix,
|
|
64
|
+
}));
|
|
65
|
+
if (props.operation.canaryMetricDetails !== undefined &&
|
|
66
|
+
props.operation.canaryMetricDetails != null) {
|
|
67
|
+
zonalCanaryHighLatencyMetrics.push(ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalCountLatencyMetric({
|
|
68
|
+
availabilityZoneId: availabilityZoneId,
|
|
69
|
+
metricDetails: props.operation.canaryMetricDetails.canaryLatencyMetricDetails,
|
|
70
|
+
label: availabilityZoneId + ' high latency responses',
|
|
71
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
72
|
+
statistic: `TC(${props.operation.canaryMetricDetails.canaryLatencyMetricDetails.successAlarmThreshold}:)`,
|
|
73
|
+
keyPrefix: keyPrefix,
|
|
74
|
+
}));
|
|
75
|
+
zonalCanaryFaultCountMetrics.push(ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
76
|
+
availabilityZoneId: availabilityZoneId,
|
|
77
|
+
metricDetails: props.operation.canaryMetricDetails
|
|
78
|
+
.canaryAvailabilityMetricDetails,
|
|
79
|
+
label: availabilityZoneId + ' fault count',
|
|
80
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
81
|
+
keyPrefix: keyPrefix,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix);
|
|
85
|
+
}
|
|
86
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
87
|
+
height: 6,
|
|
88
|
+
width: 24,
|
|
89
|
+
title: 'Server-side AZ Fault Contributors',
|
|
90
|
+
left: zonalServerSideFaultCountMetrics,
|
|
91
|
+
}));
|
|
92
|
+
if (zonalCanaryFaultCountMetrics.length > 0) {
|
|
93
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
94
|
+
height: 6,
|
|
95
|
+
width: 24,
|
|
96
|
+
title: 'Canary AZ Fault Contributors',
|
|
97
|
+
left: zonalCanaryFaultCountMetrics,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
101
|
+
height: 6,
|
|
102
|
+
width: 24,
|
|
103
|
+
title: 'Server-side High Latency Contributors',
|
|
104
|
+
left: zonalServerSideHighLatencyMetrics,
|
|
105
|
+
}));
|
|
106
|
+
if (zonalCanaryHighLatencyMetrics.length > 0) {
|
|
107
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
108
|
+
height: 6,
|
|
109
|
+
width: 24,
|
|
110
|
+
title: 'Canary High Latency Contributors',
|
|
111
|
+
left: zonalCanaryHighLatencyMetrics,
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: '**TPS Metrics**' }));
|
|
115
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
116
|
+
height: 6,
|
|
117
|
+
width: 24,
|
|
118
|
+
title: aws_cdk_lib_1.Fn.sub('${AWS::Region} TPS'),
|
|
119
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
120
|
+
left: [
|
|
121
|
+
RegionalAvailabilityMetrics_1.RegionalAvailabilityMetrics.createRegionalAvailabilityMetric({
|
|
122
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') + ' tps',
|
|
123
|
+
metricDetails: props.operation.serverSideAvailabilityMetricDetails,
|
|
124
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.REQUEST_COUNT,
|
|
125
|
+
}),
|
|
126
|
+
],
|
|
127
|
+
statistic: 'Sum',
|
|
128
|
+
leftYAxis: {
|
|
129
|
+
label: 'TPS',
|
|
130
|
+
showUnits: false,
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
for (let i = 0; i < availabilityZoneIds.length; i++) {
|
|
134
|
+
let availabilityZoneId = availabilityZoneIds[i];
|
|
135
|
+
topLevelAggregateAlarms.push(new aws_cloudwatch_1.GraphWidget({
|
|
136
|
+
height: 6,
|
|
137
|
+
width: 8,
|
|
138
|
+
title: availabilityZoneId + ' TPS',
|
|
139
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
140
|
+
left: [
|
|
141
|
+
ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
142
|
+
availabilityZoneId: availabilityZoneId,
|
|
143
|
+
label: availabilityZoneId + ' tps',
|
|
144
|
+
metricDetails: props.operation.serverSideAvailabilityMetricDetails,
|
|
145
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.REQUEST_COUNT,
|
|
146
|
+
}),
|
|
147
|
+
],
|
|
148
|
+
statistic: 'Sum',
|
|
149
|
+
leftYAxis: {
|
|
150
|
+
label: 'TPS',
|
|
151
|
+
showUnits: false,
|
|
152
|
+
},
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
return topLevelAggregateAlarms;
|
|
156
|
+
}
|
|
157
|
+
static createAvailabilityWidgets(props, title) {
|
|
158
|
+
let availabilityWidgets = [];
|
|
159
|
+
availabilityWidgets.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: title }));
|
|
160
|
+
let rowTracker = 0;
|
|
161
|
+
let keyPrefix1 = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar('');
|
|
162
|
+
let keyPrefix2 = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix1);
|
|
163
|
+
// Create regional availability and fault metrics and availability alarm widgets
|
|
164
|
+
availabilityWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
165
|
+
height: 8,
|
|
166
|
+
width: 24,
|
|
167
|
+
title: aws_cdk_lib_1.Fn.sub('${AWS::Region} Availability'),
|
|
168
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
169
|
+
left: [
|
|
170
|
+
RegionalAvailabilityMetrics_1.RegionalAvailabilityMetrics.createRegionalAvailabilityMetric({
|
|
171
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') + ' availability',
|
|
172
|
+
metricDetails: props.availabilityMetricDetails,
|
|
173
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.SUCCESS_RATE,
|
|
174
|
+
keyPrefix: keyPrefix1,
|
|
175
|
+
}),
|
|
176
|
+
],
|
|
177
|
+
statistic: 'Sum',
|
|
178
|
+
leftYAxis: {
|
|
179
|
+
max: 100,
|
|
180
|
+
min: 95,
|
|
181
|
+
label: 'Availability',
|
|
182
|
+
showUnits: false,
|
|
183
|
+
},
|
|
184
|
+
leftAnnotations: [
|
|
185
|
+
{
|
|
186
|
+
value: props.availabilityMetricDetails.successAlarmThreshold,
|
|
187
|
+
visible: true,
|
|
188
|
+
color: aws_cloudwatch_1.Color.RED,
|
|
189
|
+
label: 'High Severity',
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
right: [
|
|
193
|
+
RegionalAvailabilityMetrics_1.RegionalAvailabilityMetrics.createRegionalAvailabilityMetric({
|
|
194
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') + ' fault count',
|
|
195
|
+
metricDetails: props.availabilityMetricDetails,
|
|
196
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
197
|
+
keyPrefix: keyPrefix2,
|
|
198
|
+
}),
|
|
199
|
+
],
|
|
200
|
+
rightYAxis: {
|
|
201
|
+
label: 'Fault Count',
|
|
202
|
+
showUnits: false,
|
|
203
|
+
},
|
|
204
|
+
}));
|
|
205
|
+
availabilityWidgets.push(new aws_cloudwatch_1.AlarmWidget({
|
|
206
|
+
height: 2,
|
|
207
|
+
width: 24,
|
|
208
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
209
|
+
alarm: props.regionalEndpointAvailabilityAlarm,
|
|
210
|
+
title: 'Success Rate',
|
|
211
|
+
}));
|
|
212
|
+
for (let i = 0; i < props.availabilityZoneIds.length; i++) {
|
|
213
|
+
let availabilityZoneId = props.availabilityZoneIds[i];
|
|
214
|
+
let keyPrefix3 = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar('');
|
|
215
|
+
let keyPrefix4 = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix3);
|
|
216
|
+
availabilityWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
217
|
+
height: 6,
|
|
218
|
+
width: 8,
|
|
219
|
+
title: availabilityZoneId + ' Availability',
|
|
220
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
221
|
+
left: [
|
|
222
|
+
ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
223
|
+
availabilityZoneId: availabilityZoneId,
|
|
224
|
+
label: availabilityZoneId + ' availability',
|
|
225
|
+
metricDetails: props.availabilityMetricDetails,
|
|
226
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.SUCCESS_RATE,
|
|
227
|
+
keyPrefix: keyPrefix3,
|
|
228
|
+
}),
|
|
229
|
+
],
|
|
230
|
+
statistic: 'Sum',
|
|
231
|
+
leftYAxis: {
|
|
232
|
+
max: 100,
|
|
233
|
+
min: 95,
|
|
234
|
+
label: 'Availability',
|
|
235
|
+
showUnits: false,
|
|
236
|
+
},
|
|
237
|
+
leftAnnotations: [
|
|
238
|
+
{
|
|
239
|
+
value: props.availabilityMetricDetails.successAlarmThreshold,
|
|
240
|
+
visible: true,
|
|
241
|
+
color: aws_cloudwatch_1.Color.RED,
|
|
242
|
+
label: 'High Severity',
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
right: [
|
|
246
|
+
ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
247
|
+
availabilityZoneId: availabilityZoneId,
|
|
248
|
+
label: availabilityZoneId + ' fault count',
|
|
249
|
+
metricDetails: props.availabilityMetricDetails,
|
|
250
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
251
|
+
keyPrefix: keyPrefix4,
|
|
252
|
+
}),
|
|
253
|
+
],
|
|
254
|
+
rightYAxis: {
|
|
255
|
+
label: 'Fault Count',
|
|
256
|
+
showUnits: false,
|
|
257
|
+
},
|
|
258
|
+
}));
|
|
259
|
+
//We're on the third one for this set, add 3 alarms
|
|
260
|
+
//or if we're at the end, at the necessary amount
|
|
261
|
+
//of alarms, 1, 2, or 3
|
|
262
|
+
if (i % 3 == 2 || i - 1 == props.availabilityZoneIds.length) {
|
|
263
|
+
for (let k = rowTracker; k <= i; k++) {
|
|
264
|
+
availabilityWidgets.push(new aws_cloudwatch_1.AlarmWidget({
|
|
265
|
+
height: 2,
|
|
266
|
+
width: 8,
|
|
267
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
268
|
+
alarm: props.zonalEndpointAvailabilityAlarms[k],
|
|
269
|
+
title: 'Success Rate',
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
rowTracker += i + 1;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (!props.isCanary &&
|
|
276
|
+
props.instanceContributorsToFaults !== undefined &&
|
|
277
|
+
props.instanceContributorsToFaults != null) {
|
|
278
|
+
availabilityWidgets.push(new ContributorInsightsWidget_1.ContributorInsightsWidget({
|
|
279
|
+
height: 6,
|
|
280
|
+
width: 24,
|
|
281
|
+
title: 'Individual Instance Contributors to Fault Count',
|
|
282
|
+
insightRule: props.instanceContributorsToFaults,
|
|
283
|
+
period: props.availabilityMetricDetails.period,
|
|
284
|
+
legendPosition: aws_cloudwatch_1.LegendPosition.BOTTOM,
|
|
285
|
+
orderStatistic: 'Sum',
|
|
286
|
+
accountId: aws_cdk_lib_1.Fn.ref('AWS::AccountId'),
|
|
287
|
+
topContributors: 10,
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
return availabilityWidgets;
|
|
291
|
+
}
|
|
292
|
+
static createLatencyWidgets(props, title) {
|
|
293
|
+
let latencyWidgets = [];
|
|
294
|
+
latencyWidgets.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: title }));
|
|
295
|
+
let rowTracker = 0;
|
|
296
|
+
let keyPrefix = '';
|
|
297
|
+
let latencyMetrics = [];
|
|
298
|
+
let stats = props.latencyMetricDetails.graphedSuccessStatistics !== undefined
|
|
299
|
+
? props.latencyMetricDetails.graphedSuccessStatistics
|
|
300
|
+
: ['p99'];
|
|
301
|
+
let latencySuccessMetrics = stats.map((x) => {
|
|
302
|
+
keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix);
|
|
303
|
+
return RegionalLatencyMetrics_1.RegionalLatencyMetrics.createRegionalAverageLatencyMetric({
|
|
304
|
+
label: x + ' Success Latency',
|
|
305
|
+
metricDetails: props.latencyMetricDetails,
|
|
306
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
307
|
+
statistic: x,
|
|
308
|
+
keyPrefix: keyPrefix,
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
stats =
|
|
312
|
+
props.latencyMetricDetails.graphedFaultStatistics !== undefined
|
|
313
|
+
? props.latencyMetricDetails.graphedFaultStatistics
|
|
314
|
+
: ['p99'];
|
|
315
|
+
let latencyFaultMetrics = stats.map((x) => {
|
|
316
|
+
keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix);
|
|
317
|
+
return RegionalLatencyMetrics_1.RegionalLatencyMetrics.createRegionalAverageLatencyMetric({
|
|
318
|
+
label: x + ' Fault Latency',
|
|
319
|
+
metricDetails: props.latencyMetricDetails,
|
|
320
|
+
metricType: LatencyMetricType_1.LatencyMetricType.FAULT_LATENCY,
|
|
321
|
+
statistic: x,
|
|
322
|
+
keyPrefix: keyPrefix,
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
latencyMetrics = latencySuccessMetrics.concat(latencyFaultMetrics);
|
|
326
|
+
if (latencyMetrics.length > 0) {
|
|
327
|
+
latencyWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
328
|
+
height: 8,
|
|
329
|
+
width: 24,
|
|
330
|
+
title: aws_cdk_lib_1.Fn.sub('${AWS::Region} Latency'),
|
|
331
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
332
|
+
left: latencyMetrics,
|
|
333
|
+
leftYAxis: {
|
|
334
|
+
max: props.latencyMetricDetails.successAlarmThreshold * 1.5,
|
|
335
|
+
min: 0,
|
|
336
|
+
label: 'Latency',
|
|
337
|
+
showUnits: false,
|
|
338
|
+
},
|
|
339
|
+
leftAnnotations: [
|
|
340
|
+
{
|
|
341
|
+
value: props.latencyMetricDetails.successAlarmThreshold,
|
|
342
|
+
visible: true,
|
|
343
|
+
color: aws_cloudwatch_1.Color.RED,
|
|
344
|
+
label: 'High Severity',
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
latencyWidgets.push(new aws_cloudwatch_1.AlarmWidget({
|
|
350
|
+
height: 2,
|
|
351
|
+
width: 24,
|
|
352
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
353
|
+
alarm: props.regionalEndpointLatencyAlarm,
|
|
354
|
+
}));
|
|
355
|
+
keyPrefix = '';
|
|
356
|
+
for (let i = 0; i < props.availabilityZoneIds.length; i++) {
|
|
357
|
+
let availabilityZoneId = props.availabilityZoneIds[i];
|
|
358
|
+
let latencyMetrics2 = [];
|
|
359
|
+
let stats2 = props.latencyMetricDetails.graphedSuccessStatistics
|
|
360
|
+
? props.latencyMetricDetails.graphedSuccessStatistics
|
|
361
|
+
: ['p99'];
|
|
362
|
+
let zonalSuccessLatencyMetrics = stats2.map((x) => {
|
|
363
|
+
keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix);
|
|
364
|
+
return ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalAverageLatencyMetric({
|
|
365
|
+
label: x + ' Success Latency',
|
|
366
|
+
metricDetails: props.latencyMetricDetails,
|
|
367
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
368
|
+
statistic: x,
|
|
369
|
+
availabilityZoneId: availabilityZoneId,
|
|
370
|
+
keyPrefix: keyPrefix,
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
stats2 = props.latencyMetricDetails.graphedFaultStatistics
|
|
374
|
+
? props.latencyMetricDetails.graphedFaultStatistics
|
|
375
|
+
: ['p99'];
|
|
376
|
+
let zonalFaultLatencyMetrics = stats2.map((x) => {
|
|
377
|
+
keyPrefix = AvailabilityAndLatencyMetrics_1.AvailabilityAndLatencyMetrics.nextChar(keyPrefix);
|
|
378
|
+
return ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalAverageLatencyMetric({
|
|
379
|
+
label: x + ' Fault Latency',
|
|
380
|
+
metricDetails: props.latencyMetricDetails,
|
|
381
|
+
metricType: LatencyMetricType_1.LatencyMetricType.FAULT_LATENCY,
|
|
382
|
+
statistic: x,
|
|
383
|
+
availabilityZoneId: availabilityZoneId,
|
|
384
|
+
keyPrefix: keyPrefix,
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
latencyMetrics2 = zonalSuccessLatencyMetrics.concat(zonalFaultLatencyMetrics);
|
|
388
|
+
if (latencyMetrics2.length > 0) {
|
|
389
|
+
latencyWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
390
|
+
height: 6,
|
|
391
|
+
width: 8,
|
|
392
|
+
title: availabilityZoneId + ' Latency',
|
|
393
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
394
|
+
left: latencyMetrics2,
|
|
395
|
+
leftAnnotations: [
|
|
396
|
+
{
|
|
397
|
+
value: props.latencyMetricDetails.successAlarmThreshold,
|
|
398
|
+
visible: true,
|
|
399
|
+
color: aws_cloudwatch_1.Color.RED,
|
|
400
|
+
label: 'High Severity',
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
leftYAxis: {
|
|
404
|
+
max: props.latencyMetricDetails.successAlarmThreshold * 1.5,
|
|
405
|
+
min: 0,
|
|
406
|
+
label: 'Latency',
|
|
407
|
+
showUnits: false,
|
|
408
|
+
},
|
|
409
|
+
}));
|
|
410
|
+
}
|
|
411
|
+
//We're on the third one for this set, add 3 alarms
|
|
412
|
+
//or if we're at the end, at the necessary amount
|
|
413
|
+
//of alarms, 1, 2, or 3
|
|
414
|
+
if (i % 3 == 2 || i - 1 == props.availabilityZoneIds.length) {
|
|
415
|
+
for (let k = rowTracker; k <= i; k++) {
|
|
416
|
+
latencyWidgets.push(new aws_cloudwatch_1.AlarmWidget({
|
|
417
|
+
height: 2,
|
|
418
|
+
width: 8,
|
|
419
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
420
|
+
alarm: props.zonalEndpointLatencyAlarms[k],
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
rowTracker += i + 1;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (!props.isCanary &&
|
|
427
|
+
props.instanceContributorsToHighLatency !== undefined &&
|
|
428
|
+
props.instanceContributorsToHighLatency != null) {
|
|
429
|
+
latencyWidgets.push(new ContributorInsightsWidget_1.ContributorInsightsWidget({
|
|
430
|
+
height: 6,
|
|
431
|
+
width: 24,
|
|
432
|
+
title: 'Individual Instance Contributors to High Latency',
|
|
433
|
+
insightRule: props.instanceContributorsToHighLatency,
|
|
434
|
+
period: props.latencyMetricDetails.period,
|
|
435
|
+
legendPosition: aws_cloudwatch_1.LegendPosition.BOTTOM,
|
|
436
|
+
orderStatistic: 'Sum',
|
|
437
|
+
accountId: aws_cdk_lib_1.Fn.ref('AWS::AccountId'),
|
|
438
|
+
topContributors: 10,
|
|
439
|
+
}));
|
|
440
|
+
}
|
|
441
|
+
return latencyWidgets;
|
|
442
|
+
}
|
|
443
|
+
static createApplicationLoadBalancerWidgets(props, title, availabilityZoneNames) {
|
|
444
|
+
let albWidgets = [];
|
|
445
|
+
let loadBalancerFullName = props.loadBalancer
|
|
446
|
+
.loadBalancerFullName;
|
|
447
|
+
albWidgets.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: title }));
|
|
448
|
+
albWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
449
|
+
height: 8,
|
|
450
|
+
width: 24,
|
|
451
|
+
title: aws_cdk_lib_1.Fn.sub('${AWS::Region} Processed Bytes'),
|
|
452
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
453
|
+
left: [
|
|
454
|
+
ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createRegionalApplicationLoadBalancerProcessedBytesMetric(loadBalancerFullName, props.operation.serverSideAvailabilityMetricDetails.period),
|
|
455
|
+
],
|
|
456
|
+
leftYAxis: {
|
|
457
|
+
label: 'Processed Bytes',
|
|
458
|
+
showUnits: true,
|
|
459
|
+
},
|
|
460
|
+
}));
|
|
461
|
+
availabilityZoneNames.forEach((availabilityZoneName) => {
|
|
462
|
+
let availabilityZoneId = props.azMapper.availabilityZoneIdFromAvailabilityZoneLetter(availabilityZoneName.substring(availabilityZoneName.length - 1));
|
|
463
|
+
albWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
464
|
+
height: 6,
|
|
465
|
+
width: 8,
|
|
466
|
+
title: availabilityZoneId + ' Processed Bytes',
|
|
467
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
468
|
+
left: [
|
|
469
|
+
ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createZonalApplicationLoadBalancerProcessedBytesMetric(loadBalancerFullName, availabilityZoneName, props.operation.serverSideAvailabilityMetricDetails.period),
|
|
470
|
+
],
|
|
471
|
+
leftYAxis: {
|
|
472
|
+
label: 'Processed Bytes',
|
|
473
|
+
showUnits: true,
|
|
474
|
+
},
|
|
475
|
+
}));
|
|
476
|
+
});
|
|
477
|
+
return albWidgets;
|
|
478
|
+
}
|
|
479
|
+
static createNetworkLoadBalancerWidgets(props, title, availabilityZoneNames) {
|
|
480
|
+
let nlbWidgets = [];
|
|
481
|
+
let loadBalancerFullName = props.loadBalancer
|
|
482
|
+
.loadBalancerFullName;
|
|
483
|
+
nlbWidgets.push(new aws_cloudwatch_1.TextWidget({ height: 2, width: 24, markdown: title }));
|
|
484
|
+
nlbWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
485
|
+
height: 8,
|
|
486
|
+
width: 24,
|
|
487
|
+
title: aws_cdk_lib_1.Fn.sub('${AWS::Region} Processed Bytes'),
|
|
488
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
489
|
+
left: [
|
|
490
|
+
NetworkLoadBalancerMetrics_1.NetworkLoadBalancerMetrics.createRegionalNetworkLoadBalancerProcessedBytesMetric(loadBalancerFullName, props.operation.serverSideAvailabilityMetricDetails.period),
|
|
491
|
+
],
|
|
492
|
+
leftYAxis: {
|
|
493
|
+
label: 'Processed Bytes',
|
|
494
|
+
showUnits: true,
|
|
495
|
+
},
|
|
496
|
+
}));
|
|
497
|
+
availabilityZoneNames.forEach((availabilityZoneName) => {
|
|
498
|
+
let availabilityZoneId = props.azMapper.availabilityZoneIdFromAvailabilityZoneLetter(availabilityZoneName.substring(availabilityZoneName.length - 1));
|
|
499
|
+
nlbWidgets.push(new aws_cloudwatch_1.GraphWidget({
|
|
500
|
+
height: 6,
|
|
501
|
+
width: 8,
|
|
502
|
+
title: availabilityZoneId + ' Processed Bytes',
|
|
503
|
+
region: aws_cdk_lib_1.Fn.sub('${AWS::Region}'),
|
|
504
|
+
left: [
|
|
505
|
+
NetworkLoadBalancerMetrics_1.NetworkLoadBalancerMetrics.createZonalNetworkLoadBalancerProcessedBytesMetric(loadBalancerFullName, availabilityZoneName, props.operation.serverSideAvailabilityMetricDetails.period),
|
|
506
|
+
],
|
|
507
|
+
leftYAxis: {
|
|
508
|
+
label: 'Processed Bytes',
|
|
509
|
+
showUnits: true,
|
|
510
|
+
},
|
|
511
|
+
}));
|
|
512
|
+
});
|
|
513
|
+
return nlbWidgets;
|
|
514
|
+
}
|
|
515
|
+
constructor(scope, id, props) {
|
|
516
|
+
super(scope, id);
|
|
517
|
+
let widgets = [];
|
|
518
|
+
this.azMapper = props.azMapper;
|
|
519
|
+
let availabilityZoneIds = props.operation.service.availabilityZoneNames.map((x) => {
|
|
520
|
+
return this.azMapper.availabilityZoneIdFromAvailabilityZoneLetter(x.substring(x.length - 1));
|
|
521
|
+
});
|
|
522
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createTopLevelAggregateAlarmWidgets(props, '**Top Level Aggregate Alarms**', availabilityZoneIds));
|
|
523
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createAvailabilityWidgets({
|
|
524
|
+
operation: props.operation,
|
|
525
|
+
availabilityMetricDetails: props.operation.serverSideAvailabilityMetricDetails,
|
|
526
|
+
availabilityZoneIds: availabilityZoneIds,
|
|
527
|
+
isCanary: false,
|
|
528
|
+
zonalEndpointAvailabilityAlarms: props.zonalEndpointServerAvailabilityAlarms,
|
|
529
|
+
regionalEndpointAvailabilityAlarm: props.regionalEndpointServerAvailabilityAlarm,
|
|
530
|
+
instanceContributorsToFaults: props.instanceContributorsToFaults,
|
|
531
|
+
}, '**Server-side Availability**'));
|
|
532
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createLatencyWidgets({
|
|
533
|
+
operation: props.operation,
|
|
534
|
+
latencyMetricDetails: props.operation.serverSideLatencyMetricDetails,
|
|
535
|
+
availabilityZoneIds: availabilityZoneIds,
|
|
536
|
+
isCanary: false,
|
|
537
|
+
zonalEndpointLatencyAlarms: props.zonalEndpointServerLatencyAlarms,
|
|
538
|
+
regionalEndpointLatencyAlarm: props.regionalEndpointServerLatencyAlarm,
|
|
539
|
+
instanceContributorsToHighLatency: props.instanceContributorsToHighLatency,
|
|
540
|
+
}, '**Server-side Latency**'));
|
|
541
|
+
let lb = props.loadBalancer?.node
|
|
542
|
+
.defaultChild;
|
|
543
|
+
if (lb !== undefined && lb != null) {
|
|
544
|
+
if (lb.type == 'application') {
|
|
545
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createApplicationLoadBalancerWidgets(props, '**Application Load Balancer Metrics**', props.operation.service.availabilityZoneNames));
|
|
546
|
+
}
|
|
547
|
+
else if (lb.type == 'network') {
|
|
548
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createNetworkLoadBalancerWidgets(props, '**Network Load Balancer Metrics**', props.operation.service.availabilityZoneNames));
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (props.operation.canaryMetricDetails !== undefined &&
|
|
552
|
+
props.operation.canaryMetricDetails != null) {
|
|
553
|
+
if (props.zonalEndpointCanaryAvailabilityAlarms &&
|
|
554
|
+
props.zonalEndpointCanaryLatencyAlarms &&
|
|
555
|
+
props.regionalEndpointCanaryAvailabilityAlarm &&
|
|
556
|
+
props.regionalEndpointCanaryLatencyAlarm) {
|
|
557
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createAvailabilityWidgets({
|
|
558
|
+
operation: props.operation,
|
|
559
|
+
availabilityMetricDetails: props.operation.canaryMetricDetails
|
|
560
|
+
.canaryAvailabilityMetricDetails,
|
|
561
|
+
availabilityZoneIds: availabilityZoneIds,
|
|
562
|
+
isCanary: true,
|
|
563
|
+
zonalEndpointAvailabilityAlarms: props.zonalEndpointCanaryAvailabilityAlarms,
|
|
564
|
+
regionalEndpointAvailabilityAlarm: props.regionalEndpointCanaryAvailabilityAlarm,
|
|
565
|
+
}, '**Canary Measured Availability**'));
|
|
566
|
+
widgets.push(OperationAvailabilityAndLatencyDashboard.createLatencyWidgets({
|
|
567
|
+
operation: props.operation,
|
|
568
|
+
latencyMetricDetails: props.operation.canaryMetricDetails.canaryLatencyMetricDetails,
|
|
569
|
+
availabilityZoneIds: availabilityZoneIds,
|
|
570
|
+
isCanary: true,
|
|
571
|
+
zonalEndpointLatencyAlarms: props.zonalEndpointCanaryLatencyAlarms,
|
|
572
|
+
regionalEndpointLatencyAlarm: props.regionalEndpointCanaryLatencyAlarm,
|
|
573
|
+
}, '**Canary Measured Latency**'));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
this.dashboard = new aws_cloudwatch_1.Dashboard(this, 'Dashboard', {
|
|
577
|
+
dashboardName: props.operation.service.serviceName.toLowerCase() +
|
|
578
|
+
'-' +
|
|
579
|
+
props.operation.operationName.toLowerCase() +
|
|
580
|
+
aws_cdk_lib_1.Fn.sub('-operation-availability-and-latency-${AWS::Region}'),
|
|
581
|
+
defaultInterval: props.interval,
|
|
582
|
+
periodOverride: aws_cloudwatch_1.PeriodOverride.INHERIT,
|
|
583
|
+
widgets: widgets,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
exports.OperationAvailabilityAndLatencyDashboard = OperationAvailabilityAndLatencyDashboard;
|
|
588
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXNoYm9hcmRzL09wZXJhdGlvbkF2YWlsYWJpbGl0eUFuZExhdGVuY3lEYXNoYm9hcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUN0Qyw2Q0FBaUM7QUFDakMsK0RBV29DO0FBS3BDLDJDQUF1QztBQUN2QywyRUFBd0U7QUFNeEUsOEZBQTJGO0FBQzNGLDRGQUF5RjtBQUN6RixzRkFBbUY7QUFDbkYsd0ZBQXFGO0FBQ3JGLDhFQUEyRTtBQUMzRSxrRkFBK0U7QUFDL0Usd0VBQXFFO0FBQ3JFLGdGQUE2RTtBQUM3RSxzRUFBbUU7QUFFbkU7O0dBRUc7QUFDSCxNQUFhLHdDQUNYLFNBQVEsc0JBQVM7SUFFVCxNQUFNLENBQUMsbUNBQW1DLENBQ2hELEtBQW9ELEVBQ3BELEtBQWEsRUFDYixtQkFBNkI7UUFFN0IsSUFBSSx1QkFBdUIsR0FBYztZQUN2QyxJQUFJLDJCQUFVLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ3pELElBQUksa0NBQWlCLENBQUM7Z0JBQ3BCLE1BQU0sRUFBRSxDQUFDO2dCQUNULEtBQUssRUFBRSxFQUFFO2dCQUNULE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQztnQkFDbkMsS0FBSyxFQUFFLEtBQUssQ0FBQyxTQUFTLENBQUMsYUFBYSxHQUFHLGtCQUFrQjthQUMxRCxDQUFDO1NBQ0gsQ0FBQztRQUVGLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNwRCxJQUFJLGtCQUFrQixHQUFHLG1CQUFtQixDQUFDLENB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QWlDLEVBQy9CLEtBQUssQ0FBQyx1Q0FBdUM7aUJBQ2hELEVBQ0Qsa0NBQWtDLENBQ25DLENBQ0YsQ0FBQztnQkFFRixPQUFPLENBQUMsSUFBSSxDQUNWLHdDQUF3QyxDQUFDLG9CQUFvQixDQUMzRDtvQkFDRSxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7b0JBQzFCLG9CQUFvQixFQUNsQixLQUFLLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDLDBCQUEwQjtvQkFDaEUsbUJBQW1CLEVBQUUsbUJBQW1CO29CQUN4QyxRQUFRLEVBQUUsSUFBSTtvQkFDZCwwQkFBMEIsRUFDeEIsS0FBSyxDQUFDLGdDQUFnQztvQkFDeEMsNEJBQTRCLEVBQzFCLEtBQUssQ0FBQyxrQ0FBa0M7aUJBQzNDLEVBQ0QsNkJBQTZCLENBQzlCLENBQ0YsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLDBCQUFTLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUNoRCxhQUFhLEVBQ1gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDakQsR0FBRztnQkFDSCxLQUFLLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUU7Z0JBQzNDLGdCQUFFLENBQUMsR0FBRyxDQUFDLG9EQUFvRCxDQUFDO1lBQzlELGVBQWUsRUFBRSxLQUFLLENBQUMsUUFBUTtZQUMvQixjQUFjLEVBQUUsK0JBQWMsQ0FBQyxPQUFPO1lBQ3RDLE9BQU8sRUFBRSxPQUFPO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXB6QkQsNEZBb3pCQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbmltcG9ydCB7IEZuIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgRGFzaGJvYXJkLFxuICBJTWV0cmljLFxuICBQZXJpb2RPdmVycmlkZSxcbiAgSVdpZGdldCxcbiAgVGV4dFdpZGdldCxcbiAgQWxhcm1TdGF0dXNXaWRnZXQsXG4gIEdyYXBoV2lkZ2V0LFxuICBDb2xvcixcbiAgQWxhcm1XaWRnZXQsXG4gIExlZ2VuZFBvc2l0aW9uLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQge1xuICBCYXNlTG9hZEJhbGFuY2VyLFxuICBDZm5Mb2FkQmFsYW5jZXIsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ29udHJpYnV0b3JJbnNpZ2h0c1dpZGdldCB9IGZyb20gJy4vQ29udHJpYnV0b3JJbnNpZ2h0c1dpZGdldCc7XG5pbXBvcnQgeyBJT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZCB9IGZyb20gJy4vSU9wZXJhdGlvbkF2YWlsYWJpbGl0eUFuZExhdGVuY3lEYXNoYm9hcmQnO1xuaW1wb3J0IHsgT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZFByb3BzIH0gZnJvbSAnLi9wcm9wcy9PcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkUHJvcHMnO1xuaW1wb3J0IHsgT3BlcmF0aW9uQXZhaWxhYmlsaXR5V2lkZ2V0UHJvcHMgfSBmcm9tICcuL3Byb3BzL09wZXJhdGlvbkF2YWlsYWJpbGl0eVdpZGdldFByb3BzJztcbmltcG9ydCB7IE9wZXJhdGlvbkxhdGVuY3lXaWRnZXRQcm9wcyB9IGZyb20gJy4vcHJvcHMvT3BlcmF0aW9uTGF0ZW5jeVdpZGdldFByb3BzJztcbmltcG9ydCB7IElBdmFpbGFiaWxpdHlab25lTWFwcGVyIH0gZnJvbSAnLi4vYXptYXBwZXIvSUF2YWlsYWJpbGl0eVpvbmVNYXBwZXInO1xuaW1wb3J0IHsgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzIH0gZnJvbSAnLi4vbWV0cmljcy9BcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY3MnO1xuaW1wb3J0IHsgQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeU1ldHJpY3MgfSBmcm9tICcuLi9tZXRyaWNzL0F2YWlsYWJpbGl0eUFuZExhdGVuY3lNZXRyaWNzJztcbmltcG9ydCB7IE5ldHdvcmtMb2FkQmFsYW5jZXJNZXRyaWNzIH0gZnJvbSAnLi4vbWV0cmljcy9OZXR3b3JrTG9hZEJhbGFuY2VyTWV0cmljcyc7XG5pbXBvcnQgeyBSZWdpb25hbEF2YWlsYWJpbGl0eU1ldHJpY3MgfSBmcm9tICcuLi9tZXRyaWNzL1JlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljcyc7XG5pbXBvcnQgeyBSZWdpb25hbExhdGVuY3lNZXRyaWNzIH0gZnJvbSAnLi4vbWV0cmljcy9SZWdpb25hbExhdGVuY3lNZXRyaWNzJztcbmltcG9ydCB7IFpvbmFsQXZhaWxhYmlsaXR5TWV0cmljcyB9IGZyb20gJy4uL21ldHJpY3MvWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzJztcbmltcG9ydCB7IFpvbmFsTGF0ZW5jeU1ldHJpY3MgfSBmcm9tICcuLi9tZXRyaWNzL1pvbmFsTGF0ZW5jeU1ldHJpY3MnO1xuaW1wb3J0IHsgQXZhaWxhYmlsaXR5TWV0cmljVHlwZSB9IGZyb20gJy4uL3V0aWxpdGllcy9BdmFpbGFiaWxpdHlNZXRyaWNUeXBlJztcbmltcG9ydCB7IExhdGVuY3lNZXRyaWNUeXBlIH0gZnJvbSAnLi4vdXRpbGl0aWVzL0xhdGVuY3lNZXRyaWNUeXBlJztcblxuLyoqXG4gKiBDcmVhdGVzIGFuIG9wZXJhdGlvbiBsZXZlbCBhdmFpbGFiaWxpdHkgYW5kIGxhdGVuY3kgZGFzaGJvYXJkXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkXG4gIGV4dGVuZHMgQ29uc3RydWN0XG4gIGltcGxlbWVudHMgSU9wZXJhdGlvbkF2YWlsYWJpbGl0eUFuZExhdGVuY3lEYXNoYm9hcmQge1xuICBwcml2YXRlIHN0YXRpYyBjcmVhdGVUb3BMZXZlbEFnZ3JlZ2F0ZUFsYXJtV2lkZ2V0cyhcbiAgICBwcm9wczogT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZFByb3BzLFxuICAgIHRpdGxlOiBzdHJpbmcsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkczogc3RyaW5nW10sXG4gICk6IElXaWRnZXRbXSB7XG4gICAgbGV0IHRvcExldmVsQWdncmVnYXRlQWxhcm1zOiBJV2lkZ2V0W10gPSBbXG4gICAgICBuZXcgVGV4dFdpZGdldCh7IGhlaWdodDogMiwgd2lkdGg6IDI0LCBtYXJrZG93bjogdGl0bGUgfSksXG4gICAgICBuZXcgQWxhcm1TdGF0dXNXaWRnZXQoe1xuICAgICAgICBoZWlnaHQ6IDIsXG4gICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgYWxhcm1zOiBbcHJvcHMucmVnaW9uYWxJbXBhY3RBbGFybV0sXG4gICAgICAgIHRpdGxlOiBwcm9wcy5vcGVyYXRpb24ub3BlcmF0aW9uTmFtZSArICcgUmVnaW9uYWwgSW1wYWN0JyxcbiAgICAgIH0pLFxuICAgIF07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF2YWlsYWJpbGl0eVpvbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQgPSBhdmFpbGFiaWxpdHlab25lSWRzW2ldO1xuXG4gICAgICB0b3BMZXZlbEFnZ3JlZ2F0ZUFsYXJtcy5wdXNoKFxuICAgICAgICBuZXcgQWxhcm1TdGF0dXNXaWRnZXQoe1xuICAgICAgICAgIGhlaWdodDogMixcbiAgICAgICAgICB3aWR0aDogOCxcbiAgICAgICAgICBhbGFybXM6IFtwcm9wcy5pc29sYXRlZEFaSW1wYWN0QWxhcm1zW2ldXSxcbiAgICAgICAgICB0aXRsZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBJc29sYXRlZCBJbXBhY3QnLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdG9wTGV2ZWxBZ2dyZWdhdGVBbGFybXMucHVzaChcbiAgICAgIG5ldyBUZXh0V2lkZ2V0KHsgaGVpZ2h0OiAyLCB3aWR0aDogMjQsIG1hcmtkb3duOiAnKipBWiBDb250cmlidXRvcnMqKicgfSksXG4gICAgKTtcblxuICAgIGxldCB6b25hbFNlcnZlclNpZGVIaWdoTGF0ZW5jeU1ldHJpY3M6IElNZXRyaWNbXSA9IFtdO1xuICAgIGxldCB6b25hbFNlcnZlclNpZGVGYXVsdENvdW50TWV0cmljczogSU1ldHJpY1tdID0gW107XG5cbiAgICBsZXQgem9uYWxDYW5hcnlIaWdoTGF0ZW5jeU1ldHJpY3M6IElNZXRyaWNbXSA9IFtdO1xuICAgIGxldCB6b25hbENhbmFyeUZhdWx0Q291bnRNZXRyaWNzOiBJTWV0cmljW10gPSBbXTtcblxuICAgIGxldCBrZXlQcmVmaXg6IHN0cmluZyA9IEF2YWlsYWJpbGl0eUFuZExhdGVuY3lNZXRyaWNzLm5leHRDaGFyKCcnKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXZhaWxhYmlsaXR5Wm9uZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID0gYXZhaWxhYmlsaXR5Wm9uZUlkc1tpXTtcblxuICAgICAgem9uYWxTZXJ2ZXJTaWRlSGlnaExhdGVuY3lNZXRyaWNzLnB1c2goXG4gICAgICAgIFpvbmFsTGF0ZW5jeU1ldHJpY3MuY3JlYXRlWm9uYWxDb3VudExhdGVuY3lNZXRyaWMoe1xuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICAgIG1ldHJpY0RldGFpbHM6IHByb3BzLm9wZXJhdGlvbi5zZXJ2ZXJTaWRlTGF0ZW5jeU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgaGlnaCBsYXRlbmN5IHJlc3BvbnNlcycsXG4gICAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuU1VDQ0VTU19MQVRFTkNZLFxuICAgICAgICAgIHN0YXRpc3RpYzogYFRDKCR7cHJvcHMub3BlcmF0aW9uLnNlcnZlclNpZGVMYXRlbmN5TWV0cmljRGV0YWlscy5zdWNjZXNzQWxhcm1UaHJlc2hvbGR9OilgLFxuICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4LFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIHpvbmFsU2VydmVyU2lkZUZhdWx0Q291bnRNZXRyaWNzLnB1c2goXG4gICAgICAgIFpvbmFsQXZhaWxhYmlsaXR5TWV0cmljcy5jcmVhdGVab25hbEF2YWlsYWJpbGl0eU1ldHJpYyh7XG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgbWV0cmljRGV0YWlsczogcHJvcHMub3BlcmF0aW9uLnNlcnZlclNpZGVBdmFpbGFiaWxpdHlNZXRyaWNEZXRhaWxzLFxuICAgICAgICAgIGxhYmVsOiBhdmFpbGFiaWxpdHlab25lSWQgKyAnIGZhdWx0IGNvdW50JyxcbiAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLkZBVUxUX0NPVU5ULFxuICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4LFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGlmIChcbiAgICAgICAgcHJvcHMub3BlcmF0aW9uLmNhbmFyeU1ldHJpY0RldGFpbHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBwcm9wcy5vcGVyYXRpb24uY2FuYXJ5TWV0cmljRGV0YWlscyAhPSBudWxsXG4gICAgICApIHtcbiAgICAgICAgem9uYWxDYW5hcnlIaWdoTGF0ZW5jeU1ldHJpY3MucHVzaChcbiAgICAgICAgICBab25hbExhdGVuY3lNZXRyaWNzLmNyZWF0ZVpvbmFsQ291bnRMYXRlbmN5TWV0cmljKHtcbiAgICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICAgICAgbWV0cmljRGV0YWlsczpcbiAgICAgICAgICAgICAgcHJvcHMub3BlcmF0aW9uLmNhbmFyeU1ldHJpY0RldGFpbHMuY2FuYXJ5TGF0ZW5jeU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBoaWdoIGxhdGVuY3kgcmVzcG9uc2VzJyxcbiAgICAgICAgICAgIG1ldHJpY1R5cGU6IExhdGVuY3lNZXRyaWNUeXBlLlNVQ0NFU1NfTEFURU5DWSxcbiAgICAgICAgICAgIHN0YXRpc3RpYzogYFRDKCR7cHJvcHMub3BlcmF0aW9uLmNhbmFyeU1ldHJpY0RldGFpbHMuY2FuYXJ5TGF0ZW5jeU1ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkfTopYCxcbiAgICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4LFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIHpvbmFsQ2FuYXJ5RmF1bHRDb3VudE1ldHJpY3MucHVzaChcbiAgICAgICAgICBab25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgICBtZXRyaWNEZXRhaWxzOlxuICAgICAgICAgICAgICBwcm9wcy5vcGVyYXRpb24uY2FuYXJ5TWV0cmljRGV0YWlsc1xuICAgICAgICAgICAgICAgIC5jYW5hcnlBdmFpbGFiaWxpdHlNZXRyaWNEZXRhaWxzLFxuICAgICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgZmF1bHQgY291bnQnLFxuICAgICAgICAgICAgbWV0cmljVHlwZTogQXZhaWxhYmlsaXR5TWV0cmljVHlwZS5GQVVMVF9DT1VOVCxcbiAgICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4LFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBrZXlQcmVmaXggPSBBdmFpbGFiaWxpdHlBbmRMYXRlbmN5TWV0cmljcy5uZXh0Q2hhcihrZXlQcmVmaXgpO1xuICAgIH1cblxuICAgIHRvcExldmVsQWdncmVnYXRlQWxhcm1zLnB1c2goXG4gICAgICBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICBoZWlnaHQ6IDYsXG4gICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgdGl0bGU6ICdTZXJ2ZXItc2lkZSBBWiBGYXVsdCBDb250cmlidXRvcnMnLFxuICAgICAgICBsZWZ0OiB6b25hbFNlcnZlclNpZGVGYXVsdENvdW50TWV0cmljcyxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBpZiAoem9uYWxDYW5hcnlGYXVsdENvdW50TWV0cmljcy5sZW5ndGggPiAwKSB7XG4gICAgICB0b3BMZXZlbEFnZ3JlZ2F0ZUFsYXJtcy5wdXNoKFxuICAgICAgICBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICAgIGhlaWdodDogNixcbiAgICAgICAgICB3aWR0aDogMjQsXG4gICAgICAgICAgdGl0bGU6ICdDYW5hcnkgQVogRmF1bHQgQ29udHJpYnV0b3JzJyxcbiAgICAgICAgICBsZWZ0OiB6b25hbENhbmFyeUZhdWx0Q291bnRNZXRyaWNzLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdG9wTGV2ZWxBZ2dyZWdhdGVBbGFybXMucHVzaChcbiAgICAgIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgIGhlaWdodDogNixcbiAgICAgICAgd2lkdGg6IDI0LFxuICAgICAgICB0aXRsZTogJ1NlcnZlci1zaWRlIEhpZ2ggTGF0ZW5jeSBDb250cmlidXRvcnMnLFxuICAgICAgICBsZWZ0OiB6b25hbFNlcnZlclNpZGVIaWdoTGF0ZW5jeU1ldHJpY3MsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKHpvbmFsQ2FuYXJ5SGlnaExhdGVuY3lNZXRyaWNzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRvcExldmVsQWdncmVnYXRlQWxhcm1zLnB1c2goXG4gICAgICAgIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgICAgaGVpZ2h0OiA2LFxuICAgICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgICB0aXRsZTogJ0NhbmFyeSBIaWdoIExhdGVuY3kgQ29udHJpYnV0b3JzJyxcbiAgICAgICAgICBsZWZ0OiB6b25hbENhbmFyeUhpZ2hMYXRlbmN5TWV0cmljcyxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHRvcExldmVsQWdncmVnYXRlQWxhcm1zLnB1c2goXG4gICAgICBuZXcgVGV4dFdpZGdldCh7IGhlaWdodDogMiwgd2lkdGg6IDI0LCBtYXJrZG93bjogJyoqVFBTIE1ldHJpY3MqKicgfSksXG4gICAgKTtcblxuICAgIHRvcExldmVsQWdncmVnYXRlQWxhcm1zLnB1c2goXG4gICAgICBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICBoZWlnaHQ6IDYsXG4gICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgdGl0bGU6IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0gVFBTJyksXG4gICAgICAgIHJlZ2lvbjogRm4uc3ViKCcke0FXUzo6UmVnaW9ufScpLFxuICAgICAgICBsZWZ0OiBbXG4gICAgICAgICAgUmVnaW9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzLmNyZWF0ZVJlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljKHtcbiAgICAgICAgICAgIGxhYmVsOiBGbi5yZWYoJ0FXUzo6UmVnaW9uJykgKyAnIHRwcycsXG4gICAgICAgICAgICBtZXRyaWNEZXRhaWxzOiBwcm9wcy5vcGVyYXRpb24uc2VydmVyU2lkZUF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLlJFUVVFU1RfQ09VTlQsXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICAgIHN0YXRpc3RpYzogJ1N1bScsXG4gICAgICAgIGxlZnRZQXhpczoge1xuICAgICAgICAgIGxhYmVsOiAnVFBTJyxcbiAgICAgICAgICBzaG93VW5pdHM6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXZhaWxhYmlsaXR5Wm9uZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID0gYXZhaWxhYmlsaXR5Wm9uZUlkc1tpXTtcblxuICAgICAgdG9wTGV2ZWxBZ2dyZWdhdGVBbGFybXMucHVzaChcbiAgICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgICBoZWlnaHQ6IDYsXG4gICAgICAgICAgd2lkdGg6IDgsXG4gICAgICAgICAgdGl0bGU6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgVFBTJyxcbiAgICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgICBsZWZ0OiBbXG4gICAgICAgICAgICBab25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQ6IGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgdHBzJyxcbiAgICAgICAgICAgICAgbWV0cmljRGV0YWlsczpcbiAgICAgICAgICAgICAgICBwcm9wcy5vcGVyYXRpb24uc2VydmVyU2lkZUF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgICAgIG1ldHJpY1R5cGU6IEF2YWlsYWJpbGl0eU1ldHJpY1R5cGUuUkVRVUVTVF9DT1VOVCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgc3RhdGlzdGljOiAnU3VtJyxcbiAgICAgICAgICBsZWZ0WUF4aXM6IHtcbiAgICAgICAgICAgIGxhYmVsOiAnVFBTJyxcbiAgICAgICAgICAgIHNob3dVbml0czogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB0b3BMZXZlbEFnZ3JlZ2F0ZUFsYXJtcztcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWF0ZUF2YWlsYWJpbGl0eVdpZGdldHMoXG4gICAgcHJvcHM6IE9wZXJhdGlvbkF2YWlsYWJpbGl0eVdpZGdldFByb3BzLFxuICAgIHRpdGxlOiBzdHJpbmcsXG4gICk6IElXaWRnZXRbXSB7XG4gICAgbGV0IGF2YWlsYWJpbGl0eVdpZGdldHM6IElXaWRnZXRbXSA9IFtdO1xuICAgIGF2YWlsYWJpbGl0eVdpZGdldHMucHVzaChcbiAgICAgIG5ldyBUZXh0V2lkZ2V0KHsgaGVpZ2h0OiAyLCB3aWR0aDogMjQsIG1hcmtkb3duOiB0aXRsZSB9KSxcbiAgICApO1xuXG4gICAgbGV0IHJvd1RyYWNrZXI6IG51bWJlciA9IDA7XG4gICAgbGV0IGtleVByZWZpeDE6IHN0cmluZyA9IEF2YWlsYWJpbGl0eUFuZExhdGVuY3lNZXRyaWNzLm5leHRDaGFyKCcnKTtcbiAgICBsZXQga2V5UHJlZml4Mjogc3RyaW5nID0gQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeU1ldHJpY3MubmV4dENoYXIoa2V5UHJlZml4MSk7XG5cbiAgICAvLyBDcmVhdGUgcmVnaW9uYWwgYXZhaWxhYmlsaXR5IGFuZCBmYXVsdCBtZXRyaWNzIGFuZCBhdmFpbGFiaWxpdHkgYWxhcm0gd2lkZ2V0c1xuICAgIGF2YWlsYWJpbGl0eVdpZGdldHMucHVzaChcbiAgICAgIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgIGhlaWdodDogOCxcbiAgICAgICAgd2lkdGg6IDI0LFxuICAgICAgICB0aXRsZTogRm4uc3ViKCcke0FXUzo6UmVnaW9ufSBBdmFpbGFiaWxpdHknKSxcbiAgICAgICAgcmVnaW9uOiBGbi5zdWIoJyR7QVdTOjpSZWdpb259JyksXG4gICAgICAgIGxlZnQ6IFtcbiAgICAgICAgICBSZWdpb25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlUmVnaW9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgICAgbGFiZWw6IEZuLnJlZignQVdTOjpSZWdpb24nKSArICcgYXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICAgIG1ldHJpY0RldGFpbHM6IHByb3BzLmF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLlNVQ0NFU1NfUkFURSxcbiAgICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4MSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSxcbiAgICAgICAgc3RhdGlzdGljOiAnU3VtJyxcbiAgICAgICAgbGVmdFlBeGlzOiB7XG4gICAgICAgICAgbWF4OiAxMDAsXG4gICAgICAgICAgbWluOiA5NSxcbiAgICAgICAgICBsYWJlbDogJ0F2YWlsYWJpbGl0eScsXG4gICAgICAgICAgc2hvd1VuaXRzOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICAgbGVmdEFubm90YXRpb25zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdmFsdWU6IHByb3BzLmF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkLFxuICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbG9yOiBDb2xvci5SRUQsXG4gICAgICAgICAgICBsYWJlbDogJ0hpZ2ggU2V2ZXJpdHknLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHJpZ2h0OiBbXG4gICAgICAgICAgUmVnaW9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzLmNyZWF0ZVJlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljKHtcbiAgICAgICAgICAgIGxhYmVsOiBGbi5yZWYoJ0FXUzo6UmVnaW9uJykgKyAnIGZhdWx0IGNvdW50JyxcbiAgICAgICAgICAgIG1ldHJpY0RldGFpbHM6IHByb3BzLmF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLkZBVUxUX0NPVU5ULFxuICAgICAgICAgICAga2V5UHJlZml4OiBrZXlQcmVmaXgyLFxuICAgICAgICAgIH0pLFxuICAgICAgICBdLFxuICAgICAgICByaWdodFlBeGlzOiB7XG4gICAgICAgICAgbGFiZWw6ICdGYXVsdCBDb3VudCcsXG4gICAgICAgICAgc2hvd1VuaXRzOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBhdmFpbGFiaWxpdHlXaWRnZXRzLnB1c2goXG4gICAgICBuZXcgQWxhcm1XaWRnZXQoe1xuICAgICAgICBoZWlnaHQ6IDIsXG4gICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgcmVnaW9uOiBGbi5zdWIoJyR7QVdTOjpSZWdpb259JyksXG4gICAgICAgIGFsYXJtOiBwcm9wcy5yZWdpb25hbEVuZHBvaW50QXZhaWxhYmlsaXR5QWxhcm0sXG4gICAgICAgIHRpdGxlOiAnU3VjY2VzcyBSYXRlJyxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByb3BzLmF2YWlsYWJpbGl0eVpvbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyA9IHByb3BzLmF2YWlsYWJpbGl0eVpvbmVJZHNbaV07XG5cbiAgICAgIGxldCBrZXlQcmVmaXgzOiBzdHJpbmcgPSBBdmFpbGFiaWxpdHlBbmRMYXRlbmN5TWV0cmljcy5uZXh0Q2hhcignJyk7XG4gICAgICBsZXQga2V5UHJlZml4NDogc3RyaW5nID1cbiAgICAgICAgQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeU1ldHJpY3MubmV4dENoYXIoa2V5UHJlZml4Myk7XG5cbiAgICAgIGF2YWlsYWJpbGl0eVdpZGdldHMucHVzaChcbiAgICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgICBoZWlnaHQ6IDYsXG4gICAgICAgICAgd2lkdGg6IDgsXG4gICAgICAgICAgdGl0bGU6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgQXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgICBsZWZ0OiBbXG4gICAgICAgICAgICBab25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQ6IGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgYXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICAgICAgbWV0cmljRGV0YWlsczogcHJvcHMuYXZhaWxhYmlsaXR5TWV0cmljRGV0YWlscyxcbiAgICAgICAgICAgICAgbWV0cmljVHlwZTogQXZhaWxhYmlsaXR5TWV0cmljVHlwZS5TVUNDRVNTX1JBVEUsXG4gICAgICAgICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4MyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgc3RhdGlzdGljOiAnU3VtJyxcbiAgICAgICAgICBsZWZ0WUF4aXM6IHtcbiAgICAgICAgICAgIG1heDogMTAwLFxuICAgICAgICAgICAgbWluOiA5NSxcbiAgICAgICAgICAgIGxhYmVsOiAnQXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICAgIHNob3dVbml0czogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBsZWZ0QW5ub3RhdGlvbnM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdmFsdWU6IHByb3BzLmF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkLFxuICAgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICAgICAgICBjb2xvcjogQ29sb3IuUkVELFxuICAgICAgICAgICAgICBsYWJlbDogJ0hpZ2ggU2V2ZXJpdHknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJpZ2h0OiBbXG4gICAgICAgICAgICBab25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQ6IGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgZmF1bHQgY291bnQnLFxuICAgICAgICAgICAgICBtZXRyaWNEZXRhaWxzOiBwcm9wcy5hdmFpbGFiaWxpdHlNZXRyaWNEZXRhaWxzLFxuICAgICAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLkZBVUxUX0NPVU5ULFxuICAgICAgICAgICAgICBrZXlQcmVmaXg6IGtleVByZWZpeDQsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJpZ2h0WUF4aXM6IHtcbiAgICAgICAgICAgIGxhYmVsOiAnRmF1bHQgQ291bnQnLFxuICAgICAgICAgICAgc2hvd1VuaXRzOiBmYWxzZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIC8vV2UncmUgb24gdGhlIHRoaXJkIG9uZSBmb3IgdGhpcyBzZXQsIGFkZCAzIGFsYXJtc1xuICAgICAgLy9vciBpZiB3ZSdyZSBhdCB0aGUgZW5kLCBhdCB0aGUgbmVjZXNzYXJ5IGFtb3VudFxuICAgICAgLy9vZiBhbGFybXMsIDEsIDIsIG9yIDNcbiAgICAgIGlmIChpICUgMyA9PSAyIHx8IGkgLSAxID09IHByb3BzLmF2YWlsYWJpbGl0eVpvbmVJZHMubGVuZ3RoKSB7XG4gICAgICAgIGZvciAobGV0IGsgPSByb3dUcmFja2VyOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgIGF2YWlsYWJpbGl0eVdpZGdldHMucHVzaChcbiAgICAgICAgICAgIG5ldyBBbGFybVdpZGdldCh7XG4gICAgICAgICAgICAgIGhlaWdodDogMixcbiAgICAgICAgICAgICAgd2lkdGg6IDgsXG4gICAgICAgICAgICAgIHJlZ2lvbjogRm4uc3ViKCcke0FXUzo6UmVnaW9ufScpLFxuICAgICAgICAgICAgICBhbGFybTogcHJvcHMuem9uYWxFbmRwb2ludEF2YWlsYWJpbGl0eUFsYXJtc1trXSxcbiAgICAgICAgICAgICAgdGl0bGU6ICdTdWNjZXNzIFJhdGUnLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvd1RyYWNrZXIgKz0gaSArIDE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgIXByb3BzLmlzQ2FuYXJ5ICYmXG4gICAgICBwcm9wcy5pbnN0YW5jZUNvbnRyaWJ1dG9yc1RvRmF1bHRzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHByb3BzLmluc3RhbmNlQ29udHJpYnV0b3JzVG9GYXVsdHMgIT0gbnVsbFxuICAgICkge1xuICAgICAgYXZhaWxhYmlsaXR5V2lkZ2V0cy5wdXNoKFxuICAgICAgICBuZXcgQ29udHJpYnV0b3JJbnNpZ2h0c1dpZGdldCh7XG4gICAgICAgICAgaGVpZ2h0OiA2LFxuICAgICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgICB0aXRsZTogJ0luZGl2aWR1YWwgSW5zdGFuY2UgQ29udHJpYnV0b3JzIHRvIEZhdWx0IENvdW50JyxcbiAgICAgICAgICBpbnNpZ2h0UnVsZTogcHJvcHMuaW5zdGFuY2VDb250cmlidXRvcnNUb0ZhdWx0cyxcbiAgICAgICAgICBwZXJpb2Q6IHByb3BzLmF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMucGVyaW9kLFxuICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uOiBMZWdlbmRQb3NpdGlvbi5CT1RUT00sXG4gICAgICAgICAgb3JkZXJTdGF0aXN0aWM6ICdTdW0nLFxuICAgICAgICAgIGFjY291bnRJZDogRm4ucmVmKCdBV1M6OkFjY291bnRJZCcpLFxuICAgICAgICAgIHRvcENvbnRyaWJ1dG9yczogMTAsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXZhaWxhYmlsaXR5V2lkZ2V0cztcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWF0ZUxhdGVuY3lXaWRnZXRzKFxuICAgIHByb3BzOiBPcGVyYXRpb25MYXRlbmN5V2lkZ2V0UHJvcHMsXG4gICAgdGl0bGU6IHN0cmluZyxcbiAgKTogSVdpZGdldFtdIHtcbiAgICBsZXQgbGF0ZW5jeVdpZGdldHM6IElXaWRnZXRbXSA9IFtdO1xuICAgIGxhdGVuY3lXaWRnZXRzLnB1c2goXG4gICAgICBuZXcgVGV4dFdpZGdldCh7IGhlaWdodDogMiwgd2lkdGg6IDI0LCBtYXJrZG93bjogdGl0bGUgfSksXG4gICAgKTtcblxuICAgIGxldCByb3dUcmFja2VyOiBudW1iZXIgPSAwO1xuICAgIGxldCBrZXlQcmVmaXg6IHN0cmluZyA9ICcnO1xuXG4gICAgbGV0IGxhdGVuY3lNZXRyaWNzOiBJTWV0cmljW10gPSBbXTtcblxuICAgIGxldCBzdGF0czogc3RyaW5nW10gPVxuICAgICAgcHJvcHMubGF0ZW5jeU1ldHJpY0RldGFpbHMuZ3JhcGhlZFN1Y2Nlc3NTdGF0aXN0aWNzICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5ncmFwaGVkU3VjY2Vzc1N0YXRpc3RpY3NcbiAgICAgICAgOiBbJ3A5OSddO1xuXG4gICAgbGV0IGxhdGVuY3lTdWNjZXNzTWV0cmljczogSU1ldHJpY1tdID0gc3RhdHMubWFwKCh4KSA9PiB7XG4gICAgICBrZXlQcmVmaXggPSBBdmFpbGFiaWxpdHlBbmRMYXRlbmN5TWV0cmljcy5uZXh0Q2hhcihrZXlQcmVmaXgpO1xuICAgICAgcmV0dXJuIFJlZ2lvbmFsTGF0ZW5jeU1ldHJpY3MuY3JlYXRlUmVnaW9uYWxBdmVyYWdlTGF0ZW5jeU1ldHJpYyh7XG4gICAgICAgIGxhYmVsOiB4ICsgJyBTdWNjZXNzIExhdGVuY3knLFxuICAgICAgICBtZXRyaWNEZXRhaWxzOiBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscyxcbiAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuU1VDQ0VTU19MQVRFTkNZLFxuICAgICAgICBzdGF0aXN0aWM6IHgsXG4gICAgICAgIGtleVByZWZpeDoga2V5UHJlZml4LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBzdGF0cyA9XG4gICAgICBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5ncmFwaGVkRmF1bHRTdGF0aXN0aWNzICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5ncmFwaGVkRmF1bHRTdGF0aXN0aWNzXG4gICAgICAgIDogWydwOTknXTtcblxuICAgIGxldCBsYXRlbmN5RmF1bHRNZXRyaWNzOiBJTWV0cmljW10gPSBzdGF0cy5tYXAoKHgpID0+IHtcbiAgICAgIGtleVByZWZpeCA9IEF2YWlsYWJpbGl0eUFuZExhdGVuY3lNZXRyaWNzLm5leHRDaGFyKGtleVByZWZpeCk7XG4gICAgICByZXR1cm4gUmVnaW9uYWxMYXRlbmN5TWV0cmljcy5jcmVhdGVSZWdpb25hbEF2ZXJhZ2VMYXRlbmN5TWV0cmljKHtcbiAgICAgICAgbGFiZWw6IHggKyAnIEZhdWx0IExhdGVuY3knLFxuICAgICAgICBtZXRyaWNEZXRhaWxzOiBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscyxcbiAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuRkFVTFRfTEFURU5DWSxcbiAgICAgICAgc3RhdGlzdGljOiB4LFxuICAgICAgICBrZXlQcmVmaXg6IGtleVByZWZpeCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgbGF0ZW5jeU1ldHJpY3MgPSBsYXRlbmN5U3VjY2Vzc01ldHJpY3MuY29uY2F0KGxhdGVuY3lGYXVsdE1ldHJpY3MpO1xuXG4gICAgaWYgKGxhdGVuY3lNZXRyaWNzLmxlbmd0aCA+IDApIHtcbiAgICAgIGxhdGVuY3lXaWRnZXRzLnB1c2goXG4gICAgICAgIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgICAgaGVpZ2h0OiA4LFxuICAgICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgICB0aXRsZTogRm4uc3ViKCcke0FXUzo6UmVnaW9ufSBMYXRlbmN5JyksXG4gICAgICAgICAgcmVnaW9uOiBGbi5zdWIoJyR7QVdTOjpSZWdpb259JyksXG4gICAgICAgICAgbGVmdDogbGF0ZW5jeU1ldHJpY3MsXG4gICAgICAgICAgbGVmdFlBeGlzOiB7XG4gICAgICAgICAgICBtYXg6IHByb3BzLmxhdGVuY3lNZXRyaWNEZXRhaWxzLnN1Y2Nlc3NBbGFybVRocmVzaG9sZCAqIDEuNSxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGxhYmVsOiAnTGF0ZW5jeScsXG4gICAgICAgICAgICBzaG93VW5pdHM6IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbGVmdEFubm90YXRpb25zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHZhbHVlOiBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5zdWNjZXNzQWxhcm1UaHJlc2hvbGQsXG4gICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgICAgICAgIGNvbG9yOiBDb2xvci5SRUQsXG4gICAgICAgICAgICAgIGxhYmVsOiAnSGlnaCBTZXZlcml0eScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsYXRlbmN5V2lkZ2V0cy5wdXNoKFxuICAgICAgbmV3IEFsYXJtV2lkZ2V0KHtcbiAgICAgICAgaGVpZ2h0OiAyLFxuICAgICAgICB3aWR0aDogMjQsXG4gICAgICAgIHJlZ2lvbjogRm4uc3ViKCcke0FXUzo6UmVnaW9ufScpLFxuICAgICAgICBhbGFybTogcHJvcHMucmVnaW9uYWxFbmRwb2ludExhdGVuY3lBbGFybSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBrZXlQcmVmaXggPSAnJztcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJvcHMuYXZhaWxhYmlsaXR5Wm9uZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID0gcHJvcHMuYXZhaWxhYmlsaXR5Wm9uZUlkc1tpXTtcblxuICAgICAgbGV0IGxhdGVuY3lNZXRyaWNzMjogSU1ldHJpY1tdID0gW107XG5cbiAgICAgIGxldCBzdGF0czI6IHN0cmluZ1tdID0gcHJvcHMubGF0ZW5jeU1ldHJpY0RldGFpbHMuZ3JhcGhlZFN1Y2Nlc3NTdGF0aXN0aWNzXG4gICAgICAgID8gcHJvcHMubGF0ZW5jeU1ldHJpY0RldGFpbHMuZ3JhcGhlZFN1Y2Nlc3NTdGF0aXN0aWNzXG4gICAgICAgIDogWydwOTknXTtcblxuICAgICAgbGV0IHpvbmFsU3VjY2Vzc0xhdGVuY3lNZXRyaWNzOiBJTWV0cmljW10gPSBzdGF0czIubWFwKCh4KSA9PiB7XG4gICAgICAgIGtleVByZWZpeCA9IEF2YWlsYWJpbGl0eUFuZExhdGVuY3lNZXRyaWNzLm5leHRDaGFyKGtleVByZWZpeCk7XG4gICAgICAgIHJldHVybiBab25hbExhdGVuY3lNZXRyaWNzLmNyZWF0ZVpvbmFsQXZlcmFnZUxhdGVuY3lNZXRyaWMoe1xuICAgICAgICAgIGxhYmVsOiB4ICsgJyBTdWNjZXNzIExhdGVuY3knLFxuICAgICAgICAgIG1ldHJpY0RldGFpbHM6IHByb3BzLmxhdGVuY3lNZXRyaWNEZXRhaWxzLFxuICAgICAgICAgIG1ldHJpY1R5cGU6IExhdGVuY3lNZXRyaWNUeXBlLlNVQ0NFU1NfTEFURU5DWSxcbiAgICAgICAgICBzdGF0aXN0aWM6IHgsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAga2V5UHJlZml4OiBrZXlQcmVmaXgsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHN0YXRzMiA9IHByb3BzLmxhdGVuY3lNZXRyaWNEZXRhaWxzLmdyYXBoZWRGYXVsdFN0YXRpc3RpY3NcbiAgICAgICAgPyBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5ncmFwaGVkRmF1bHRTdGF0aXN0aWNzXG4gICAgICAgIDogWydwOTknXTtcblxuICAgICAgbGV0IHpvbmFsRmF1bHRMYXRlbmN5TWV0cmljczogSU1ldHJpY1tdID0gc3RhdHMyLm1hcCgoeCkgPT4ge1xuICAgICAgICBrZXlQcmVmaXggPSBBdmFpbGFiaWxpdHlBbmRMYXRlbmN5TWV0cmljcy5uZXh0Q2hhcihrZXlQcmVmaXgpO1xuICAgICAgICByZXR1cm4gWm9uYWxMYXRlbmN5TWV0cmljcy5jcmVhdGVab25hbEF2ZXJhZ2VMYXRlbmN5TWV0cmljKHtcbiAgICAgICAgICBsYWJlbDogeCArICcgRmF1bHQgTGF0ZW5jeScsXG4gICAgICAgICAgbWV0cmljRGV0YWlsczogcHJvcHMubGF0ZW5jeU1ldHJpY0RldGFpbHMsXG4gICAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuRkFVTFRfTEFURU5DWSxcbiAgICAgICAgICBzdGF0aXN0aWM6IHgsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAga2V5UHJlZml4OiBrZXlQcmVmaXgsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGxhdGVuY3lNZXRyaWNzMiA9IHpvbmFsU3VjY2Vzc0xhdGVuY3lNZXRyaWNzLmNvbmNhdChcbiAgICAgICAgem9uYWxGYXVsdExhdGVuY3lNZXRyaWNzLFxuICAgICAgKTtcblxuICAgICAgaWYgKGxhdGVuY3lNZXRyaWNzMi5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxhdGVuY3lXaWRnZXRzLnB1c2goXG4gICAgICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgICAgIGhlaWdodDogNixcbiAgICAgICAgICAgIHdpZHRoOiA4LFxuICAgICAgICAgICAgdGl0bGU6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgTGF0ZW5jeScsXG4gICAgICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgICAgIGxlZnQ6IGxhdGVuY3lNZXRyaWNzMixcbiAgICAgICAgICAgIGxlZnRBbm5vdGF0aW9uczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHByb3BzLmxhdGVuY3lNZXRyaWNEZXRhaWxzLnN1Y2Nlc3NBbGFybVRocmVzaG9sZCxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBDb2xvci5SRUQsXG4gICAgICAgICAgICAgICAgbGFiZWw6ICdIaWdoIFNldmVyaXR5JyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBsZWZ0WUF4aXM6IHtcbiAgICAgICAgICAgICAgbWF4OiBwcm9wcy5sYXRlbmN5TWV0cmljRGV0YWlscy5zdWNjZXNzQWxhcm1UaHJlc2hvbGQgKiAxLjUsXG4gICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgbGFiZWw6ICdMYXRlbmN5JyxcbiAgICAgICAgICAgICAgc2hvd1VuaXRzOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vV2UncmUgb24gdGhlIHRoaXJkIG9uZSBmb3IgdGhpcyBzZXQsIGFkZCAzIGFsYXJtc1xuICAgICAgLy9vciBpZiB3ZSdyZSBhdCB0aGUgZW5kLCBhdCB0aGUgbmVjZXNzYXJ5IGFtb3VudFxuICAgICAgLy9vZiBhbGFybXMsIDEsIDIsIG9yIDNcbiAgICAgIGlmIChpICUgMyA9PSAyIHx8IGkgLSAxID09IHByb3BzLmF2YWlsYWJpbGl0eVpvbmVJZHMubGVuZ3RoKSB7XG4gICAgICAgIGZvciAobGV0IGsgPSByb3dUcmFja2VyOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgIGxhdGVuY3lXaWRnZXRzLnB1c2goXG4gICAgICAgICAgICBuZXcgQWxhcm1XaWRnZXQoe1xuICAgICAgICAgICAgICBoZWlnaHQ6IDIsXG4gICAgICAgICAgICAgIHdpZHRoOiA4LFxuICAgICAgICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgICAgICAgYWxhcm06IHByb3BzLnpvbmFsRW5kcG9pbnRMYXRlbmN5QWxhcm1zW2tdLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByb3dUcmFja2VyICs9IGkgKyAxO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgICFwcm9wcy5pc0NhbmFyeSAmJlxuICAgICAgcHJvcHMuaW5zdGFuY2VDb250cmlidXRvcnNUb0hpZ2hMYXRlbmN5ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHByb3BzLmluc3RhbmNlQ29udHJpYnV0b3JzVG9IaWdoTGF0ZW5jeSAhPSBudWxsXG4gICAgKSB7XG4gICAgICBsYXRlbmN5V2lkZ2V0cy5wdXNoKFxuICAgICAgICBuZXcgQ29udHJpYnV0b3JJbnNpZ2h0c1dpZGdldCh7XG4gICAgICAgICAgaGVpZ2h0OiA2LFxuICAgICAgICAgIHdpZHRoOiAyNCxcbiAgICAgICAgICB0aXRsZTogJ0luZGl2aWR1YWwgSW5zdGFuY2UgQ29udHJpYnV0b3JzIHRvIEhpZ2ggTGF0ZW5jeScsXG4gICAgICAgICAgaW5zaWdodFJ1bGU6IHByb3BzLmluc3RhbmNlQ29udHJpYnV0b3JzVG9IaWdoTGF0ZW5jeSxcbiAgICAgICAgICBwZXJpb2Q6IHByb3BzLmxhdGVuY3lNZXRyaWNEZXRhaWxzLnBlcmlvZCxcbiAgICAgICAgICBsZWdlbmRQb3NpdGlvbjogTGVnZW5kUG9zaXRpb24uQk9UVE9NLFxuICAgICAgICAgIG9yZGVyU3RhdGlzdGljOiAnU3VtJyxcbiAgICAgICAgICBhY2NvdW50SWQ6IEZuLnJlZignQVdTOjpBY2NvdW50SWQnKSxcbiAgICAgICAgICB0b3BDb250cmlidXRvcnM6IDEwLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhdGVuY3lXaWRnZXRzO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY3JlYXRlQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJXaWRnZXRzKFxuICAgIHByb3BzOiBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkUHJvcHMsXG4gICAgdGl0bGU6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lTmFtZXM6IHN0cmluZ1tdLFxuICApOiBJV2lkZ2V0W10ge1xuICAgIGxldCBhbGJXaWRnZXRzOiBJV2lkZ2V0W10gPSBbXTtcbiAgICBsZXQgbG9hZEJhbGFuY2VyRnVsbE5hbWU6IHN0cmluZyA9IChwcm9wcy5sb2FkQmFsYW5jZXIgYXMgQmFzZUxvYWRCYWxhbmNlcilcbiAgICAgIC5sb2FkQmFsYW5jZXJGdWxsTmFtZTtcblxuICAgIGFsYldpZGdldHMucHVzaChuZXcgVGV4dFdpZGdldCh7IGhlaWdodDogMiwgd2lkdGg6IDI0LCBtYXJrZG93bjogdGl0bGUgfSkpO1xuXG4gICAgYWxiV2lkZ2V0cy5wdXNoKFxuICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgaGVpZ2h0OiA4LFxuICAgICAgICB3aWR0aDogMjQsXG4gICAgICAgIHRpdGxlOiBGbi5zdWIoJyR7QVdTOjpSZWdpb259IFByb2Nlc3NlZCBCeXRlcycpLFxuICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgbGVmdDogW1xuICAgICAgICAgIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcy5jcmVhdGVSZWdpb25hbEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvY2Vzc2VkQnl0ZXNNZXRyaWMoXG4gICAgICAgICAgICBsb2FkQmFsYW5jZXJGdWxsTmFtZSxcbiAgICAgICAgICAgIHByb3BzLm9wZXJhdGlvbi5zZXJ2ZXJTaWRlQXZhaWxhYmlsaXR5TWV0cmljRGV0YWlscy5wZXJpb2QsXG4gICAgICAgICAgKSxcbiAgICAgICAgXSxcbiAgICAgICAgbGVmdFlBeGlzOiB7XG4gICAgICAgICAgbGFiZWw6ICdQcm9jZXNzZWQgQnl0ZXMnLFxuICAgICAgICAgIHNob3dVbml0czogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBhdmFpbGFiaWxpdHlab25lTmFtZXMuZm9yRWFjaCgoYXZhaWxhYmlsaXR5Wm9uZU5hbWUpID0+IHtcbiAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyA9XG4gICAgICAgIHByb3BzLmF6TWFwcGVyLmF2YWlsYWJpbGl0eVpvbmVJZEZyb21BdmFpbGFiaWxpdHlab25lTGV0dGVyKFxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVOYW1lLnN1YnN0cmluZyhhdmFpbGFiaWxpdHlab25lTmFtZS5sZW5ndGggLSAxKSxcbiAgICAgICAgKTtcblxuICAgICAgYWxiV2lkZ2V0cy5wdXNoKFxuICAgICAgICBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICAgIGhlaWdodDogNixcbiAgICAgICAgICB3aWR0aDogOCxcbiAgICAgICAgICB0aXRsZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBQcm9jZXNzZWQgQnl0ZXMnLFxuICAgICAgICAgIHJlZ2lvbjogRm4uc3ViKCcke0FXUzo6UmVnaW9ufScpLFxuICAgICAgICAgIGxlZnQ6IFtcbiAgICAgICAgICAgIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcy5jcmVhdGVab25hbEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvY2Vzc2VkQnl0ZXNNZXRyaWMoXG4gICAgICAgICAgICAgIGxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lTmFtZSxcbiAgICAgICAgICAgICAgcHJvcHMub3BlcmF0aW9uLnNlcnZlclNpZGVBdmFpbGFiaWxpdHlNZXRyaWNEZXRhaWxzLnBlcmlvZCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgXSxcbiAgICAgICAgICBsZWZ0WUF4aXM6IHtcbiAgICAgICAgICAgIGxhYmVsOiAnUHJvY2Vzc2VkIEJ5dGVzJyxcbiAgICAgICAgICAgIHNob3dVbml0czogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYWxiV2lkZ2V0cztcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWF0ZU5ldHdvcmtMb2FkQmFsYW5jZXJXaWRnZXRzKFxuICAgIHByb3BzOiBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkUHJvcHMsXG4gICAgdGl0bGU6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lTmFtZXM6IHN0cmluZ1tdLFxuICApOiBJV2lkZ2V0W10ge1xuICAgIGxldCBubGJXaWRnZXRzOiBJV2lkZ2V0W10gPSBbXTtcbiAgICBsZXQgbG9hZEJhbGFuY2VyRnVsbE5hbWU6IHN0cmluZyA9IChwcm9wcy5sb2FkQmFsYW5jZXIgYXMgQmFzZUxvYWRCYWxhbmNlcilcbiAgICAgIC5sb2FkQmFsYW5jZXJGdWxsTmFtZTtcblxuICAgIG5sYldpZGdldHMucHVzaChuZXcgVGV4dFdpZGdldCh7IGhlaWdodDogMiwgd2lkdGg6IDI0LCBtYXJrZG93bjogdGl0bGUgfSkpO1xuXG4gICAgbmxiV2lkZ2V0cy5wdXNoKFxuICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgaGVpZ2h0OiA4LFxuICAgICAgICB3aWR0aDogMjQsXG4gICAgICAgIHRpdGxlOiBGbi5zdWIoJyR7QVdTOjpSZWdpb259IFByb2Nlc3NlZCBCeXRlcycpLFxuICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgbGVmdDogW1xuICAgICAgICAgIE5ldHdvcmtMb2FkQmFsYW5jZXJNZXRyaWNzLmNyZWF0ZVJlZ2lvbmFsTmV0d29ya0xvYWRCYWxhbmNlclByb2Nlc3NlZEJ5dGVzTWV0cmljKFxuICAgICAgICAgICAgbG9hZEJhbGFuY2VyRnVsbE5hbWUsXG4gICAgICAgICAgICBwcm9wcy5vcGVyYXRpb24uc2VydmVyU2lkZUF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMucGVyaW9kLFxuICAgICAgICAgICksXG4gICAgICAgIF0sXG4gICAgICAgIGxlZnRZQXhpczoge1xuICAgICAgICAgIGxhYmVsOiAnUHJvY2Vzc2VkIEJ5dGVzJyxcbiAgICAgICAgICBzaG93VW5pdHM6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgYXZhaWxhYmlsaXR5Wm9uZU5hbWVzLmZvckVhY2goKGF2YWlsYWJpbGl0eVpvbmVOYW1lKSA9PiB7XG4gICAgICBsZXQgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcgPVxuICAgICAgICBwcm9wcy5hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lTmFtZS5zdWJzdHJpbmcoYXZhaWxhYmlsaXR5Wm9uZU5hbWUubGVuZ3RoIC0gMSksXG4gICAgICAgICk7XG5cbiAgICAgIG5sYldpZGdldHMucHVzaChcbiAgICAgICAgbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgICBoZWlnaHQ6IDYsXG4gICAgICAgICAgd2lkdGg6IDgsXG4gICAgICAgICAgdGl0bGU6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgUHJvY2Vzc2VkIEJ5dGVzJyxcbiAgICAgICAgICByZWdpb246IEZuLnN1YignJHtBV1M6OlJlZ2lvbn0nKSxcbiAgICAgICAgICBsZWZ0OiBbXG4gICAgICAgICAgICBOZXR3b3JrTG9hZEJhbGFuY2VyTWV0cmljcy5jcmVhdGVab25hbE5ldHdvcmtMb2FkQmFsYW5jZXJQcm9jZXNzZWRCeXRlc01ldHJpYyhcbiAgICAgICAgICAgICAgbG9hZEJhbGFuY2VyRnVsbE5hbWUsXG4gICAgICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVOYW1lLFxuICAgICAgICAgICAgICBwcm9wcy5vcGVyYXRpb24uc2VydmVyU2lkZUF2YWlsYWJpbGl0eU1ldHJpY0RldGFpbHMucGVyaW9kLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGxlZnRZQXhpczoge1xuICAgICAgICAgICAgbGFiZWw6ICdQcm9jZXNzZWQgQnl0ZXMnLFxuICAgICAgICAgICAgc2hvd1VuaXRzOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBubGJXaWRnZXRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvcGVyYXRpb24gbGV2ZWwgZGFzaGJvYXJkXG4gICAqL1xuICBkYXNoYm9hcmQ6IERhc2hib2FyZDtcblxuICBwcml2YXRlIGF6TWFwcGVyOiBJQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IE9wZXJhdGlvbkF2YWlsYWJpbGl0eUFuZExhdGVuY3lEYXNoYm9hcmRQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGxldCB3aWRnZXRzOiBJV2lkZ2V0W11bXSA9IFtdO1xuXG4gICAgdGhpcy5hek1hcHBlciA9IHByb3BzLmF6TWFwcGVyO1xuXG4gICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZHM6IHN0cmluZ1tdID1cbiAgICAgIHByb3BzLm9wZXJhdGlvbi5zZXJ2aWNlLmF2YWlsYWJpbGl0eVpvbmVOYW1lcy5tYXAoKHgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoXG4gICAgICAgICAgeC5zdWJzdHJpbmcoeC5sZW5ndGggLSAxKSxcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgd2lkZ2V0cy5wdXNoKFxuICAgICAgT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZC5jcmVhdGVUb3BMZXZlbEFnZ3JlZ2F0ZUFsYXJtV2lkZ2V0cyhcbiAgICAgICAgcHJvcHMsXG4gICAgICAgICcqKlRvcCBMZXZlbCBBZ2dyZWdhdGUgQWxhcm1zKionLFxuICAgICAgICBhdmFpbGFiaWxpdHlab25lSWRzLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgd2lkZ2V0cy5wdXNoKFxuICAgICAgT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZC5jcmVhdGVBdmFpbGFiaWxpdHlXaWRnZXRzKFxuICAgICAgICB7XG4gICAgICAgICAgb3BlcmF0aW9uOiBwcm9wcy5vcGVyYXRpb24sXG4gICAgICAgICAgYXZhaWxhYmlsaXR5TWV0cmljRGV0YWlsczpcbiAgICAgICAgICAgIHByb3BzLm9wZXJhdGlvbi5zZXJ2ZXJTaWRlQXZhaWxhYmlsaXR5TWV0cmljRGV0YWlscyxcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWRzOiBhdmFpbGFiaWxpdHlab25lSWRzLFxuICAgICAgICAgIGlzQ2FuYXJ5OiBmYWxzZSxcbiAgICAgICAgICB6b25hbEVuZHBvaW50QXZhaWxhYmlsaXR5QWxhcm1zOlxuICAgICAgICAgICAgcHJvcHMuem9uYWxFbmRwb2ludFNlcnZlckF2YWlsYWJpbGl0eUFsYXJtcyxcbiAgICAgICAgICByZWdpb25hbEVuZHBvaW50QXZhaWxhYmlsaXR5QWxhcm06XG4gICAgICAgICAgICBwcm9wcy5yZWdpb25hbEVuZHBvaW50U2VydmVyQXZhaWxhYmlsaXR5QWxhcm0sXG4gICAgICAgICAgaW5zdGFuY2VDb250cmlidXRvcnNUb0ZhdWx0czogcHJvcHMuaW5zdGFuY2VDb250cmlidXRvcnNUb0ZhdWx0cyxcbiAgICAgICAgfSxcbiAgICAgICAgJyoqU2VydmVyLXNpZGUgQXZhaWxhYmlsaXR5KionLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgd2lkZ2V0cy5wdXNoKFxuICAgICAgT3BlcmF0aW9uQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeURhc2hib2FyZC5jcmVhdGVMYXRlbmN5V2lkZ2V0cyhcbiAgICAgICAge1xuICAgICAgICAgIG9wZXJhdGlvbjogcHJvcHMub3BlcmF0aW9uLFxuICAgICAgICAgIGxhdGVuY3lNZXRyaWNEZXRhaWxzOiBwcm9wcy5vcGVyYXRpb24uc2VydmVyU2lkZUxhdGVuY3lNZXRyaWNEZXRhaWxzLFxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZHM6IGF2YWlsYWJpbGl0eVpvbmVJZHMsXG4gICAgICAgICAgaXNDYW5hcnk6IGZhbHNlLFxuICAgICAgICAgIHpvbmFsRW5kcG9pbnRMYXRlbmN5QWxhcm1zOiBwcm9wcy56b25hbEVuZHBvaW50U2VydmVyTGF0ZW5jeUFsYXJtcyxcbiAgICAgICAgICByZWdpb25hbEVuZHBvaW50TGF0ZW5jeUFsYXJtOlxuICAgICAgICAgICAgcHJvcHMucmVnaW9uYWxFbmRwb2ludFNlcnZlckxhdGVuY3lBbGFybSxcbiAgICAgICAgICBpbnN0YW5jZUNvbnRyaWJ1dG9yc1RvSGlnaExhdGVuY3k6XG4gICAgICAgICAgICBwcm9wcy5pbnN0YW5jZUNvbnRyaWJ1dG9yc1RvSGlnaExhdGVuY3ksXG4gICAgICAgIH0sXG4gICAgICAgICcqKlNlcnZlci1zaWRlIExhdGVuY3kqKicsXG4gICAgICApLFxuICAgICk7XG5cbiAgICBsZXQgbGI6IENmbkxvYWRCYWxhbmNlciA9IHByb3BzLmxvYWRCYWxhbmNlcj8ubm9kZVxuICAgICAgLmRlZmF1bHRDaGlsZCBhcyBDZm5Mb2FkQmFsYW5jZXI7XG5cbiAgICBpZiAobGIgIT09IHVuZGVmaW5lZCAmJiBsYiAhPSBudWxsKSB7XG4gICAgICBpZiAobGIudHlwZSA9PSAnYXBwbGljYXRpb24nKSB7XG4gICAgICAgIHdpZGdldHMucHVzaChcbiAgICAgICAgICBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkLmNyZWF0ZUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyV2lkZ2V0cyhcbiAgICAgICAgICAgIHByb3BzLFxuICAgICAgICAgICAgJyoqQXBwbGljYXRpb24gTG9hZCBCYWxhbmNlciBNZXRyaWNzKionLFxuICAgICAgICAgICAgcHJvcHMub3BlcmF0aW9uLnNlcnZpY2UuYXZhaWxhYmlsaXR5Wm9uZU5hbWVzLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKGxiLnR5cGUgPT0gJ25ldHdvcmsnKSB7XG4gICAgICAgIHdpZGdldHMucHVzaChcbiAgICAgICAgICBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkLmNyZWF0ZU5ldHdvcmtMb2FkQmFsYW5jZXJXaWRnZXRzKFxuICAgICAgICAgICAgcHJvcHMsXG4gICAgICAgICAgICAnKipOZXR3b3JrIExvYWQgQmFsYW5jZXIgTWV0cmljcyoqJyxcbiAgICAgICAgICAgIHByb3BzLm9wZXJhdGlvbi5zZXJ2aWNlLmF2YWlsYWJpbGl0eVpvbmVOYW1lcyxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHByb3BzLm9wZXJhdGlvbi5jYW5hcnlNZXRyaWNEZXRhaWxzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHByb3BzLm9wZXJhdGlvbi5jYW5hcnlNZXRyaWNEZXRhaWxzICE9IG51bGxcbiAgICApIHtcbiAgICAgIGlmIChcbiAgICAgICAgcHJvcHMuem9uYWxFbmRwb2ludENhbmFyeUF2YWlsYWJpbGl0eUFsYXJtcyAmJlxuICAgICAgICBwcm9wcy56b25hbEVuZHBvaW50Q2FuYXJ5TGF0ZW5jeUFsYXJtcyAmJlxuICAgICAgICBwcm9wcy5yZWdpb25hbEVuZHBvaW50Q2FuYXJ5QXZhaWxhYmlsaXR5QWxhcm0gJiZcbiAgICAgICAgcHJvcHMucmVnaW9uYWxFbmRwb2ludENhbmFyeUxhdGVuY3lBbGFybVxuICAgICAgKSB7XG4gICAgICAgIHdpZGdldHMucHVzaChcbiAgICAgICAgICBPcGVyYXRpb25BdmFpbGFiaWxpdHlBbmRMYXRlbmN5RGFzaGJvYXJkLmNyZWF0ZUF2YWlsYWJpbGl0eVdpZGdldHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG9wZXJhdGlvbjogcHJvcHMub3BlcmF0aW9uLFxuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlNZXRyaWNEZXRhaWxzOlxuICAgICAgICAgICAgICAgIHByb3BzLm9wZXJhdGlvbi5jYW5hcnlNZXRyaWNEZXRhaWxzXG4gICAgICAgICAgICAgICAgICAuY2FuYXJ5QXZhaWxhYmlsaXR5TWV0cmljRGV0YWlscyxcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkczogYXZhaWxhYmlsaXR5Wm9uZUlkcyxcbiAgICAgICAgICAgICAgaXNDYW5hcnk6IHRydWUsXG4gICAgICAgICAgICAgIHpvbmFsRW5kcG9pbnRBdmFpbGFiaWxpdHlBbGFybXM6XG4gICAgICAgICAgICAgICAgcHJvcHMuem9uYWxFbmRwb2ludENhbmFyeUF2YWlsYWJpbGl0eUFsYXJtcyxcbiAgICAgICAgICAgICAgcmVnaW9uYWxFbmRwb2ludEF2YWlsYWJpbGl0eUFsYXJtOlxuICAgICAgICAgICAgICAgIHByb3BzLnJlZ2lvbmFsRW5kcG9pbnRDYW5hcnlBdmFpbGFiaWxpdHlBbGFybSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnKipDYW5hcnkgTWVhc3VyZWQgQXZhaWxhYmlsaXR5KionLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG5cbiAgICAgICAgd2lkZ2V0cy5wdXNoKFxuICAgICAgICAgIE9wZXJhdGlvbkF2YWlsYWJpbGl0eUFuZExhdGVuY3lEYXNoYm9hcmQuY3JlYXRlTGF0ZW5jeVdpZGdldHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG9wZXJhdGlvbjogcHJvcHMub3BlcmF0aW9uLFxuICAgICAgICAgICAgICBsYXRlbmN5TWV0cmljRGV0YWlsczpcbiAgICAgICAgICAgICAgICBwcm9wcy5vcGVyYXRpb24uY2FuYXJ5TWV0cmljRGV0YWlscy5jYW5hcnlMYXRlbmN5TWV0cmljRGV0YWlscyxcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkczogYXZhaWxhYmlsaXR5Wm9uZUlkcyxcbiAgICAgICAgICAgICAgaXNDYW5hcnk6IHRydWUsXG4gICAgICAgICAgICAgIHpvbmFsRW5kcG9pbnRMYXRlbmN5QWxhcm1zOlxuICAgICAgICAgICAgICAgIHByb3BzLnpvbmFsRW5kcG9pbnRDYW5hcnlMYXRlbmN5QWxhcm1zLFxuICAgICAgICAgICAgICByZWdpb25hbEVuZHBvaW50TGF0ZW5jeUFsYXJtOlxuICAgICAgICAgICAgICAgIHByb3BzLnJlZ2lvbmFsRW5kcG9pbnRDYW5hcnlMYXRlbmN5QWxhcm0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJyoqQ2FuYXJ5IE1lYXN1cmVkIExhdGVuY3kqKicsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRhc2hib2FyZCA9IG5ldyBEYXNoYm9hcmQodGhpcywgJ0Rhc2hib2FyZCcsIHtcbiAgICAgIGRhc2hib2FyZE5hbWU6XG4gICAgICAgIHByb3BzLm9wZXJhdGlvbi5zZXJ2aWNlLnNlcnZpY2VOYW1lLnRvTG93ZXJDYXNlKCkgK1xuICAgICAgICAnLScgK1xuICAgICAgICBwcm9wcy5vcGVyYXRpb24ub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpICtcbiAgICAgICAgRm4uc3ViKCctb3BlcmF0aW9uLWF2YWlsYWJpbGl0eS1hbmQtbGF0ZW5jeS0ke0FXUzo6UmVnaW9ufScpLFxuICAgICAgZGVmYXVsdEludGVydmFsOiBwcm9wcy5pbnRlcnZhbCxcbiAgICAgIHBlcmlvZE92ZXJyaWRlOiBQZXJpb2RPdmVycmlkZS5JTkhFUklULFxuICAgICAgd2lkZ2V0czogd2lkZ2V0cyxcbiAgICB9KTtcbiAgfVxufVxuIl19
|