@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,763 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AvailabilityAndLatencyAlarmsAndRules = 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 InsightRuleBody_1 = require("./InsightRuleBody");
|
|
9
|
+
const RegionalAvailabilityMetrics_1 = require("../metrics/RegionalAvailabilityMetrics");
|
|
10
|
+
const RegionalLatencyMetrics_1 = require("../metrics/RegionalLatencyMetrics");
|
|
11
|
+
const ZonalAvailabilityMetrics_1 = require("../metrics/ZonalAvailabilityMetrics");
|
|
12
|
+
const ZonalLatencyMetrics_1 = require("../metrics/ZonalLatencyMetrics");
|
|
13
|
+
const AvailabilityMetricType_1 = require("../utilities/AvailabilityMetricType");
|
|
14
|
+
const LatencyMetricType_1 = require("../utilities/LatencyMetricType");
|
|
15
|
+
/**
|
|
16
|
+
* Class used to create availability and latency alarms and Contributor Insight rules
|
|
17
|
+
*/
|
|
18
|
+
class AvailabilityAndLatencyAlarmsAndRules {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a zonal availability alarm
|
|
21
|
+
* @param scope
|
|
22
|
+
* @param metricDetails
|
|
23
|
+
* @param availabilityZoneId
|
|
24
|
+
* @param nameSuffix
|
|
25
|
+
* @param counter
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
static createZonalAvailabilityAlarm(scope, metricDetails, availabilityZoneId, counter, nameSuffix) {
|
|
29
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName + 'AZ' + counter + 'AvailabilityAlarm', {
|
|
30
|
+
alarmName: availabilityZoneId +
|
|
31
|
+
'-' +
|
|
32
|
+
metricDetails.operationName.toLowerCase() +
|
|
33
|
+
'-success-rate' +
|
|
34
|
+
nameSuffix,
|
|
35
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
36
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
37
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.LESS_THAN_THRESHOLD,
|
|
38
|
+
threshold: metricDetails.successAlarmThreshold,
|
|
39
|
+
actionsEnabled: false,
|
|
40
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
41
|
+
metric: ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
42
|
+
availabilityZoneId: availabilityZoneId,
|
|
43
|
+
label: availabilityZoneId + ' availability',
|
|
44
|
+
metricDetails: metricDetails,
|
|
45
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.SUCCESS_RATE,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Creates a zonal latency alarm
|
|
51
|
+
* @param scope
|
|
52
|
+
* @param metricDetails
|
|
53
|
+
* @param availabilityZoneId
|
|
54
|
+
* @param nameSuffix
|
|
55
|
+
* @param counter
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
static createZonalLatencyAlarm(scope, metricDetails, availabilityZoneId, counter, nameSuffix) {
|
|
59
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName + 'AZ' + counter + 'LatencyAlarm', {
|
|
60
|
+
alarmName: availabilityZoneId +
|
|
61
|
+
'-' +
|
|
62
|
+
metricDetails.operationName.toLowerCase() +
|
|
63
|
+
'-success-latency' +
|
|
64
|
+
nameSuffix,
|
|
65
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
66
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
67
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
68
|
+
threshold: metricDetails.successAlarmThreshold,
|
|
69
|
+
actionsEnabled: false,
|
|
70
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
71
|
+
metric: ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalAverageLatencyMetric({
|
|
72
|
+
availabilityZoneId: availabilityZoneId,
|
|
73
|
+
label: availabilityZoneId +
|
|
74
|
+
' ' +
|
|
75
|
+
metricDetails.alarmStatistic +
|
|
76
|
+
' latency',
|
|
77
|
+
metricDetails: metricDetails,
|
|
78
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
79
|
+
statistic: metricDetails.alarmStatistic,
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a composite alarm when either latency or availability is breached in the Availabiltiy Zone
|
|
85
|
+
* @param scope
|
|
86
|
+
* @param operation
|
|
87
|
+
* @param availabilityZoneId
|
|
88
|
+
* @param nameSuffix
|
|
89
|
+
* @param counter
|
|
90
|
+
* @param zonalAvailabilityAlarm
|
|
91
|
+
* @param zonalLatencyAlarm
|
|
92
|
+
* @returns
|
|
93
|
+
*/
|
|
94
|
+
static createZonalAvailabilityOrLatencyCompositeAlarm(scope, operationName, availabilityZoneId, counter, zonalAvailabilityAlarm, zonalLatencyAlarm, nameSuffix) {
|
|
95
|
+
return new aws_cloudwatch_1.CompositeAlarm(scope, 'AZ' + counter + 'ZonalImpactAlarm', {
|
|
96
|
+
actionsEnabled: false,
|
|
97
|
+
alarmDescription: availabilityZoneId +
|
|
98
|
+
' has latency or availability impact. This does not indicate it is an outlier and shows isolated impact.',
|
|
99
|
+
compositeAlarmName: availabilityZoneId +
|
|
100
|
+
`-${operationName.toLowerCase()}-impact-aggregate-alarm` +
|
|
101
|
+
nameSuffix,
|
|
102
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(zonalAvailabilityAlarm, zonalLatencyAlarm),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* An alarm that compares error rate in this AZ to the overall region error based only on metric data
|
|
107
|
+
* @param scope
|
|
108
|
+
* @param metricDetails
|
|
109
|
+
* @param availabilityZoneId
|
|
110
|
+
* @param nameSuffix
|
|
111
|
+
* @param counter
|
|
112
|
+
* @param outlierThreshold
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
static createZonalFaultRateStaticOutlierAlarm(scope, metricDetails, availabilityZoneId, counter, outlierThreshold, nameSuffix) {
|
|
116
|
+
let zonalFaults = ZonalAvailabilityMetrics_1.ZonalAvailabilityMetrics.createZonalAvailabilityMetric({
|
|
117
|
+
availabilityZoneId: availabilityZoneId,
|
|
118
|
+
metricDetails: metricDetails,
|
|
119
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
120
|
+
keyPrefix: 'a',
|
|
121
|
+
});
|
|
122
|
+
let regionalFaults = RegionalAvailabilityMetrics_1.RegionalAvailabilityMetrics.createRegionalAvailabilityMetric({
|
|
123
|
+
metricDetails: metricDetails,
|
|
124
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
|
|
125
|
+
keyPrefix: 'b',
|
|
126
|
+
});
|
|
127
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'IsolatedImpactAlarmStatic', {
|
|
128
|
+
alarmName: availabilityZoneId +
|
|
129
|
+
`-${metricDetails.operationName.toLowerCase()}-static-majority-errors-impact` +
|
|
130
|
+
nameSuffix,
|
|
131
|
+
metric: new aws_cloudwatch_1.MathExpression({
|
|
132
|
+
expression: 'IF(m2 > 0, (m1 / m2), 0)',
|
|
133
|
+
usingMetrics: {
|
|
134
|
+
m1: zonalFaults,
|
|
135
|
+
m2: regionalFaults,
|
|
136
|
+
},
|
|
137
|
+
period: metricDetails.period,
|
|
138
|
+
label: availabilityZoneId + ' percent faults',
|
|
139
|
+
}),
|
|
140
|
+
threshold: outlierThreshold,
|
|
141
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
142
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
143
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
144
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
static createZonalFaultRateOutlierAlarm(scope, metricDetails, availabilityZoneId, allAvailabilityZoneIds, outlierThreshold, outlierDetectionFunction, outlierDetectionAlgorithm, counter, nameSuffix) {
|
|
148
|
+
let metricDimensions = {};
|
|
149
|
+
allAvailabilityZoneIds.forEach((azId) => {
|
|
150
|
+
metricDimensions[azId] = [
|
|
151
|
+
metricDetails.metricDimensions.zonalDimensions(azId, aws_cdk_lib_1.Fn.ref('AWS::Region')),
|
|
152
|
+
];
|
|
153
|
+
});
|
|
154
|
+
let str = JSON.stringify(metricDimensions)
|
|
155
|
+
.replace(/[\\]/g, '\\\\')
|
|
156
|
+
.replace(/[\"]/g, '\\"')
|
|
157
|
+
.replace(/[\/]/g, '\\/')
|
|
158
|
+
.replace(/[\b]/g, '\\b')
|
|
159
|
+
.replace(/[\f]/g, '\\f')
|
|
160
|
+
.replace(/[\n]/g, '\\n')
|
|
161
|
+
.replace(/[\r]/g, '\\r')
|
|
162
|
+
.replace(/[\t]/g, '\\t');
|
|
163
|
+
let outlierMetrics = new aws_cloudwatch_1.MathExpression({
|
|
164
|
+
expression: `MAX(LAMBDA("${outlierDetectionFunction.functionName}",` +
|
|
165
|
+
`"${outlierDetectionAlgorithm.toString()}",` +
|
|
166
|
+
`"${outlierThreshold}",` +
|
|
167
|
+
`"${availabilityZoneId}",` +
|
|
168
|
+
`"${str}",` +
|
|
169
|
+
`"${metricDetails.metricNamespace}",` +
|
|
170
|
+
`"${metricDetails.faultMetricNames.join(':')}",` +
|
|
171
|
+
'"Sum",' +
|
|
172
|
+
'"Count"' +
|
|
173
|
+
'))',
|
|
174
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
175
|
+
});
|
|
176
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'FaultIsolatedImpactAlarmOutlier', {
|
|
177
|
+
alarmName: availabilityZoneId +
|
|
178
|
+
`-${metricDetails.operationName.toLowerCase()}-majority-errors-impact` +
|
|
179
|
+
nameSuffix,
|
|
180
|
+
metric: outlierMetrics,
|
|
181
|
+
threshold: 1,
|
|
182
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
183
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
184
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
185
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
static createZonalFaultRateOutlierAlarmForAlb(scope, loadBalancers, availabilityZoneId, outlierThreshold, outlierDetectionFunction, outlierDetectionAlgorithm, azMapper, counter, evaluationPeriods, datapointsToAlarm, nameSuffix) {
|
|
189
|
+
let metricDimensions = {};
|
|
190
|
+
loadBalancers.forEach((x) => {
|
|
191
|
+
x.vpc?.availabilityZones.forEach((az) => {
|
|
192
|
+
let azId = azMapper.availabilityZoneIdFromAvailabilityZoneLetter(az.substring(az.length - 1));
|
|
193
|
+
if (!(azId in metricDimensions)) {
|
|
194
|
+
metricDimensions[azId] = [];
|
|
195
|
+
}
|
|
196
|
+
metricDimensions[azId].push({
|
|
197
|
+
AvailabilityZone: az,
|
|
198
|
+
LoadBalancer: x
|
|
199
|
+
.loadBalancerFullName,
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
let str = JSON.stringify(metricDimensions)
|
|
204
|
+
.replace(/[\\]/g, '\\\\')
|
|
205
|
+
.replace(/[\"]/g, '\\"')
|
|
206
|
+
.replace(/[\/]/g, '\\/')
|
|
207
|
+
.replace(/[\b]/g, '\\b')
|
|
208
|
+
.replace(/[\f]/g, '\\f')
|
|
209
|
+
.replace(/[\n]/g, '\\n')
|
|
210
|
+
.replace(/[\r]/g, '\\r')
|
|
211
|
+
.replace(/[\t]/g, '\\t');
|
|
212
|
+
let outlierMetrics = new aws_cloudwatch_1.MathExpression({
|
|
213
|
+
expression: `MAX(LAMBDA("${outlierDetectionFunction.functionName}",` +
|
|
214
|
+
`"${outlierDetectionAlgorithm.toString()}",` +
|
|
215
|
+
`"${outlierThreshold}",` +
|
|
216
|
+
`"${availabilityZoneId}",` +
|
|
217
|
+
`"${str}",` +
|
|
218
|
+
'"AWS/ApplicationELB",' +
|
|
219
|
+
'"HTTPCode_ELB_5XX_Count:HTTPCode_Target_5XX_Count",' +
|
|
220
|
+
'"Sum",' +
|
|
221
|
+
'"Count"' +
|
|
222
|
+
'))',
|
|
223
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
224
|
+
});
|
|
225
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'AlbIsolatedImpactAlarmOutlier', {
|
|
226
|
+
alarmName: availabilityZoneId + '-alb-majority-errors-impact' + nameSuffix,
|
|
227
|
+
metric: outlierMetrics,
|
|
228
|
+
threshold: 1,
|
|
229
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
230
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
231
|
+
evaluationPeriods: evaluationPeriods,
|
|
232
|
+
datapointsToAlarm: datapointsToAlarm,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
static createZonalFaultRateOutlierAlarmForNatGW(scope, natGateways, availabilityZoneId, outlierThreshold, outlierDetectionFunction, outlierDetectionAlgorithm, azMapper, counter, evaluationPeriods, datapointsToAlarm, nameSuffix) {
|
|
236
|
+
let metricDimensions = {};
|
|
237
|
+
Object.keys(natGateways).forEach((az) => {
|
|
238
|
+
let azId = azMapper.availabilityZoneIdFromAvailabilityZoneLetter(az.substring(az.length - 1));
|
|
239
|
+
if (!(azId in metricDimensions)) {
|
|
240
|
+
metricDimensions[azId] = [];
|
|
241
|
+
}
|
|
242
|
+
natGateways[az].forEach((natgw) => {
|
|
243
|
+
metricDimensions[azId].push({
|
|
244
|
+
NatGatewayId: natgw.attrNatGatewayId,
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
let str = JSON.stringify(metricDimensions)
|
|
249
|
+
.replace(/[\\]/g, '\\\\')
|
|
250
|
+
.replace(/[\"]/g, '\\"')
|
|
251
|
+
.replace(/[\/]/g, '\\/')
|
|
252
|
+
.replace(/[\b]/g, '\\b')
|
|
253
|
+
.replace(/[\f]/g, '\\f')
|
|
254
|
+
.replace(/[\n]/g, '\\n')
|
|
255
|
+
.replace(/[\r]/g, '\\r')
|
|
256
|
+
.replace(/[\t]/g, '\\t');
|
|
257
|
+
let outlierMetrics = new aws_cloudwatch_1.MathExpression({
|
|
258
|
+
expression: `MAX(LAMBDA("${outlierDetectionFunction.functionName}",` +
|
|
259
|
+
`"${outlierDetectionAlgorithm.toString()}",` +
|
|
260
|
+
`"${outlierThreshold}",` +
|
|
261
|
+
`"${availabilityZoneId}",` +
|
|
262
|
+
`"${str}",` +
|
|
263
|
+
'"AWS/NATGateway",' +
|
|
264
|
+
'"PacketsDropCount",' +
|
|
265
|
+
'"Sum",' +
|
|
266
|
+
'"Count"' +
|
|
267
|
+
'))',
|
|
268
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
269
|
+
});
|
|
270
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'NatGWIsolatedImpactAlarmOutlier', {
|
|
271
|
+
alarmName: availabilityZoneId + '-nat-gw-majority-errors-impact' + nameSuffix,
|
|
272
|
+
metric: outlierMetrics,
|
|
273
|
+
threshold: 1,
|
|
274
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
275
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
276
|
+
evaluationPeriods: evaluationPeriods,
|
|
277
|
+
datapointsToAlarm: datapointsToAlarm,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
static createZonalHighLatencyOutlierAlarm(scope, metricDetails, availabilityZoneId, allAvailabilityZoneIds, outlierThreshold, outlierDetectionFunction, outlierDetectionAlgorithm, counter, nameSuffix) {
|
|
281
|
+
let metricDimensions = {};
|
|
282
|
+
allAvailabilityZoneIds.forEach((azId) => {
|
|
283
|
+
metricDimensions[azId] = [
|
|
284
|
+
metricDetails.metricDimensions.zonalDimensions(azId, aws_cdk_lib_1.Fn.ref('AWS::Region')),
|
|
285
|
+
];
|
|
286
|
+
});
|
|
287
|
+
let str = JSON.stringify(metricDimensions)
|
|
288
|
+
.replace(/[\\]/g, '\\\\')
|
|
289
|
+
.replace(/[\"]/g, '\\"')
|
|
290
|
+
.replace(/[\/]/g, '\\/')
|
|
291
|
+
.replace(/[\b]/g, '\\b')
|
|
292
|
+
.replace(/[\f]/g, '\\f')
|
|
293
|
+
.replace(/[\n]/g, '\\n')
|
|
294
|
+
.replace(/[\r]/g, '\\r')
|
|
295
|
+
.replace(/[\t]/g, '\\t');
|
|
296
|
+
let outlierMetrics = new aws_cloudwatch_1.MathExpression({
|
|
297
|
+
expression: `MAX(LAMBDA("${outlierDetectionFunction.functionName}",` +
|
|
298
|
+
`"${outlierDetectionAlgorithm.toString()}",` +
|
|
299
|
+
`"${outlierThreshold}",` +
|
|
300
|
+
`"${availabilityZoneId}",` +
|
|
301
|
+
`"${str}",` +
|
|
302
|
+
`"${metricDetails.metricNamespace}",` +
|
|
303
|
+
`"${metricDetails.successMetricNames.join(':')}",` +
|
|
304
|
+
`"TC(${metricDetails.successAlarmThreshold}:)",` +
|
|
305
|
+
'"Milliseconds"' +
|
|
306
|
+
'))',
|
|
307
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
308
|
+
});
|
|
309
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName +
|
|
310
|
+
'AZ' +
|
|
311
|
+
counter +
|
|
312
|
+
'LatencyIsolatedImpactAlarmOutlier', {
|
|
313
|
+
alarmName: availabilityZoneId +
|
|
314
|
+
`-${metricDetails.operationName.toLowerCase()}-majority-high-latency-impact` +
|
|
315
|
+
nameSuffix,
|
|
316
|
+
metric: outlierMetrics,
|
|
317
|
+
threshold: 1,
|
|
318
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
319
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
320
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
321
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
static createZonalHighLatencyStaticOutlierAlarm(scope, metricDetails, availabilityZoneId, counter, outlierThreshold, nameSuffix) {
|
|
325
|
+
let zonalLatency = ZonalLatencyMetrics_1.ZonalLatencyMetrics.createZonalCountLatencyMetric({
|
|
326
|
+
availabilityZoneId: availabilityZoneId,
|
|
327
|
+
label: availabilityZoneId +
|
|
328
|
+
'-' +
|
|
329
|
+
metricDetails.operationName +
|
|
330
|
+
'-high-latency-requests',
|
|
331
|
+
metricDetails: metricDetails,
|
|
332
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
333
|
+
statistic: `TC(${metricDetails.successAlarmThreshold}:)`,
|
|
334
|
+
keyPrefix: 'a',
|
|
335
|
+
});
|
|
336
|
+
let regionalLatency = RegionalLatencyMetrics_1.RegionalLatencyMetrics.createRegionalLatencyCountMetric({
|
|
337
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
338
|
+
'-' +
|
|
339
|
+
metricDetails.operationName +
|
|
340
|
+
'-high-latency-requests',
|
|
341
|
+
metricDetails: metricDetails,
|
|
342
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
343
|
+
statistic: `TC(${metricDetails.successAlarmThreshold}:)`,
|
|
344
|
+
keyPrefix: 'b',
|
|
345
|
+
});
|
|
346
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName +
|
|
347
|
+
'AZ' +
|
|
348
|
+
counter +
|
|
349
|
+
'IsolatedImpactAlarmStatic', {
|
|
350
|
+
alarmName: availabilityZoneId +
|
|
351
|
+
`-${metricDetails.operationName.toLowerCase()}-static-majority-high-latency-impact` +
|
|
352
|
+
nameSuffix,
|
|
353
|
+
metric: new aws_cloudwatch_1.MathExpression({
|
|
354
|
+
expression: 'IF(m2 > 0, (m1 / m2), 0)',
|
|
355
|
+
usingMetrics: {
|
|
356
|
+
m1: zonalLatency,
|
|
357
|
+
m2: regionalLatency,
|
|
358
|
+
},
|
|
359
|
+
period: metricDetails.period,
|
|
360
|
+
label: availabilityZoneId + ' percent high latency requests',
|
|
361
|
+
}),
|
|
362
|
+
threshold: outlierThreshold,
|
|
363
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
364
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
365
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
366
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* An insight rule that calculates how many instances are responding to requests in
|
|
371
|
+
* the specified AZ. Only useful for server-side metrics since the canary doesn't record instance id metrics.
|
|
372
|
+
* @param scope
|
|
373
|
+
* @param metricDetails
|
|
374
|
+
* @param availabilityZoneId
|
|
375
|
+
* @param logGroups
|
|
376
|
+
* @param nameSuffix
|
|
377
|
+
* @param counter
|
|
378
|
+
* @param instanceIdPath
|
|
379
|
+
* @param operationNamePath
|
|
380
|
+
* @param availabilityZoneIdPath
|
|
381
|
+
* @returns
|
|
382
|
+
*/
|
|
383
|
+
static createServerSideInstancesHandlingRequestsInThisAZRule(scope, operationName, availabilityZoneId, ruleDetails, counter, nameSuffix) {
|
|
384
|
+
let ruleBody = new InsightRuleBody_1.InsightRuleBody();
|
|
385
|
+
ruleBody.logGroupNames = ruleDetails.logGroups.map((x) => x.logGroupName);
|
|
386
|
+
ruleBody.aggregateOn = 'Count';
|
|
387
|
+
ruleBody.logFormat = 'JSON';
|
|
388
|
+
ruleBody.contribution = {
|
|
389
|
+
keys: [ruleDetails.instanceIdJsonPath],
|
|
390
|
+
filters: [
|
|
391
|
+
{
|
|
392
|
+
Match: ruleDetails.availabilityZoneIdJsonPath,
|
|
393
|
+
In: [availabilityZoneId],
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
Match: ruleDetails.operationNameJsonPath,
|
|
397
|
+
In: [operationName],
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
};
|
|
401
|
+
return new aws_cloudwatch_1.CfnInsightRule(scope, 'AZ' + counter + 'InstancesInTheAZRule', {
|
|
402
|
+
ruleName: availabilityZoneId +
|
|
403
|
+
`-${operationName.toLowerCase()}-instances-in-the-az` +
|
|
404
|
+
nameSuffix,
|
|
405
|
+
ruleState: 'ENABLED',
|
|
406
|
+
ruleBody: ruleBody.toJson(),
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* An insight rule that calculates the instances contributing to errors
|
|
411
|
+
* in this AZ. Only useful for server-side metrics since the canary doesn't record instance id metrics.
|
|
412
|
+
* @param scope
|
|
413
|
+
* @param operation
|
|
414
|
+
* @param availabilityZoneId
|
|
415
|
+
* @param logGroups
|
|
416
|
+
* @param nameSuffix
|
|
417
|
+
* @param counter
|
|
418
|
+
* @param instanceIdPath
|
|
419
|
+
* @param operationNamePath
|
|
420
|
+
* @param availabilityZoneIdPath
|
|
421
|
+
* @param errorMetricPath
|
|
422
|
+
* @returns
|
|
423
|
+
*/
|
|
424
|
+
static createServerSideInstanceFaultContributorsInThisAZRule(scope, operationName, availabilityZoneId, ruleDetails, counter, nameSuffix) {
|
|
425
|
+
let ruleBody = new InsightRuleBody_1.InsightRuleBody();
|
|
426
|
+
ruleBody.logGroupNames = ruleDetails.logGroups.map((x) => x.logGroupName);
|
|
427
|
+
ruleBody.aggregateOn = 'Count';
|
|
428
|
+
ruleBody.logFormat = 'JSON';
|
|
429
|
+
ruleBody.contribution = {
|
|
430
|
+
keys: [ruleDetails.instanceIdJsonPath],
|
|
431
|
+
filters: [
|
|
432
|
+
{
|
|
433
|
+
Match: ruleDetails.availabilityZoneIdJsonPath,
|
|
434
|
+
In: [availabilityZoneId],
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
Match: ruleDetails.operationNameJsonPath,
|
|
438
|
+
In: [operationName],
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
Match: ruleDetails.faultMetricJsonPath,
|
|
442
|
+
GreaterThan: 0,
|
|
443
|
+
},
|
|
444
|
+
],
|
|
445
|
+
};
|
|
446
|
+
return new aws_cloudwatch_1.CfnInsightRule(scope, 'AZ' + counter + 'InstanceErrorContributionRule', {
|
|
447
|
+
ruleName: availabilityZoneId +
|
|
448
|
+
`-${operationName.toLowerCase()}-per-instance-faults` +
|
|
449
|
+
nameSuffix,
|
|
450
|
+
ruleState: 'ENABLED',
|
|
451
|
+
ruleBody: ruleBody.toJson(),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* An insight rule that calculates instances contributing to high latency in this AZ. Only
|
|
456
|
+
* useful for server-side metrics since the canary doesn't record instance id metrics.
|
|
457
|
+
* @param scope
|
|
458
|
+
* @param metricDetails
|
|
459
|
+
* @param availabilityZoneId
|
|
460
|
+
* @param logGroups
|
|
461
|
+
* @param nameSuffix
|
|
462
|
+
* @param counter
|
|
463
|
+
* @returns
|
|
464
|
+
*/
|
|
465
|
+
static createServerSideInstanceHighLatencyContributorsInThisAZRule(scope, metricDetails, availabilityZoneId, ruleDetails, counter, nameSuffix) {
|
|
466
|
+
let ruleBody = new InsightRuleBody_1.InsightRuleBody();
|
|
467
|
+
ruleBody.logGroupNames = ruleDetails.logGroups.map((x) => x.logGroupName);
|
|
468
|
+
ruleBody.aggregateOn = 'Count';
|
|
469
|
+
ruleBody.logFormat = 'JSON';
|
|
470
|
+
ruleBody.contribution = {
|
|
471
|
+
keys: [ruleDetails.instanceIdJsonPath],
|
|
472
|
+
filters: [
|
|
473
|
+
{
|
|
474
|
+
Match: ruleDetails.availabilityZoneIdJsonPath,
|
|
475
|
+
In: [availabilityZoneId],
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
Match: ruleDetails.operationNameJsonPath,
|
|
479
|
+
In: [metricDetails.operationName],
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
Match: ruleDetails.successLatencyMetricJsonPath,
|
|
483
|
+
GreaterThan: metricDetails.successAlarmThreshold,
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
};
|
|
487
|
+
return new aws_cloudwatch_1.CfnInsightRule(scope, 'AZ' + counter + 'LatencyContributorsRule', {
|
|
488
|
+
ruleName: availabilityZoneId +
|
|
489
|
+
`-${metricDetails.operationName.toLowerCase()}-per-instance-high-latency` +
|
|
490
|
+
nameSuffix,
|
|
491
|
+
ruleState: 'ENABLED',
|
|
492
|
+
ruleBody: ruleBody.toJson(),
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* An alarm that indicates some percentage of the instances in this AZ are producing errors. Only
|
|
497
|
+
* useful for server-side metrics since the canary doesn't record instance id metrics.
|
|
498
|
+
* @param scope
|
|
499
|
+
* @param metricDetails
|
|
500
|
+
* @param availabilityZoneId
|
|
501
|
+
* @param nameSuffix
|
|
502
|
+
* @param counter
|
|
503
|
+
* @param outlierThreshold
|
|
504
|
+
* @param instanceFaultRateContributorsInThisAZ
|
|
505
|
+
* @param instancesHandlingRequestsInThisAZ
|
|
506
|
+
* @returns
|
|
507
|
+
*/
|
|
508
|
+
static createServerSideZonalMoreThanOneInstanceProducingFaultsAlarm(scope, metricDetails, availabilityZoneId, counter, outlierThreshold, instanceFaultRateContributorsInThisAZ, instancesHandlingRequestsInThisAZ, nameSuffix) {
|
|
509
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'MoreThanOneAlarmForErrors', {
|
|
510
|
+
alarmName: availabilityZoneId +
|
|
511
|
+
`-${metricDetails.operationName.toLowerCase()}-multiple-instances-faults` +
|
|
512
|
+
nameSuffix,
|
|
513
|
+
metric: new aws_cloudwatch_1.MathExpression({
|
|
514
|
+
expression: `INSIGHT_RULE_METRIC(\"${instanceFaultRateContributorsInThisAZ.attrRuleName}\", \"UniqueContributors\") / INSIGHT_RULE_METRIC(\"${instancesHandlingRequestsInThisAZ.attrRuleName}\", \"UniqueContributors\")`,
|
|
515
|
+
period: metricDetails.period,
|
|
516
|
+
}),
|
|
517
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
518
|
+
threshold: outlierThreshold,
|
|
519
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
520
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
521
|
+
actionsEnabled: false,
|
|
522
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* An alarm indicating more than some percentage of instances in this AZ
|
|
527
|
+
* are contributing to high latency. Only useful for server-side metrics since
|
|
528
|
+
* the canary doesn't record instance id metrics.
|
|
529
|
+
* @param scope
|
|
530
|
+
* @param metricDetails
|
|
531
|
+
* @param availabilityZoneId
|
|
532
|
+
* @param nameSuffix
|
|
533
|
+
* @param counter
|
|
534
|
+
* @param outlierThreshold
|
|
535
|
+
* @param instanceHighLatencyContributorsInThisAZ
|
|
536
|
+
* @param instancesHandlingRequestsInThisAZ
|
|
537
|
+
* @returns
|
|
538
|
+
*/
|
|
539
|
+
static createServerSideZonalMoreThanOneInstanceProducingHighLatencyAlarm(scope, metricDetails, availabilityZoneId, counter, outlierThreshold, instanceHighLatencyContributorsInThisAZ, instancesHandlingRequestsInThisAZ, nameSuffix) {
|
|
540
|
+
return new aws_cloudwatch_1.Alarm(scope, 'AZ' + counter + 'MoreThanOneAlarmForHighLatency', {
|
|
541
|
+
alarmName: availabilityZoneId +
|
|
542
|
+
`-${metricDetails.operationName.toLowerCase()}-multiple-instances-high-latency` +
|
|
543
|
+
nameSuffix,
|
|
544
|
+
metric: new aws_cloudwatch_1.MathExpression({
|
|
545
|
+
expression: `INSIGHT_RULE_METRIC(\"${instanceHighLatencyContributorsInThisAZ.attrRuleName}\", \"UniqueContributors\") / INSIGHT_RULE_METRIC(\"${instancesHandlingRequestsInThisAZ.attrRuleName}\", \"UniqueContributors\")`,
|
|
546
|
+
period: metricDetails.period,
|
|
547
|
+
}),
|
|
548
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
549
|
+
threshold: outlierThreshold,
|
|
550
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
551
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
552
|
+
actionsEnabled: false,
|
|
553
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* An alarm that indicates this AZ as an outlier
|
|
558
|
+
* for availability or latency. This does not ensure that the errors
|
|
559
|
+
* or latency originate from more than one instance.
|
|
560
|
+
* @param scope
|
|
561
|
+
* @param operation
|
|
562
|
+
* @param availabilityZoneId
|
|
563
|
+
* @param logGroups
|
|
564
|
+
* @param nameSuffix
|
|
565
|
+
* @param counter
|
|
566
|
+
* @param azIsOutlierForFaultsAlarm
|
|
567
|
+
* @param availabilityImpactAlarm
|
|
568
|
+
* @param azIsOutlierForLatencyAlarm
|
|
569
|
+
* @param latencyImpactAlarm
|
|
570
|
+
* @returns
|
|
571
|
+
*/
|
|
572
|
+
static createCanaryIsolatedAZImpactAlarm(scope, operationName, availabilityZoneId, counter, azIsOutlierForFaultsAlarm, availabilityImpactAlarm, azIsOutlierForLatencyAlarm, latencyImpactAlarm, nameSuffix) {
|
|
573
|
+
return new aws_cloudwatch_1.CompositeAlarm(scope, operationName + 'AZ' + counter + 'IsolatedImpactAlarm' + nameSuffix, {
|
|
574
|
+
compositeAlarmName: availabilityZoneId +
|
|
575
|
+
`-${operationName.toLowerCase()}-isolated-impact-alarm` +
|
|
576
|
+
nameSuffix,
|
|
577
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForFaultsAlarm, availabilityImpactAlarm), aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForLatencyAlarm, latencyImpactAlarm)),
|
|
578
|
+
actionsEnabled: false,
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Creates the server side alarm to identify isolated single AZ
|
|
583
|
+
* impact meaning that this one AZ is affected and the others aren't
|
|
584
|
+
* @param scope
|
|
585
|
+
* @param operation
|
|
586
|
+
* @param availabilityZoneId
|
|
587
|
+
* @param nameSuffix
|
|
588
|
+
* @param counter
|
|
589
|
+
* @param azIsOutlierForFaultsAlarm
|
|
590
|
+
* @param availabilityImpactAlarm
|
|
591
|
+
* @param moreThanOneInstanceContributingToFaults
|
|
592
|
+
* @param azIsOutlierForLatencyAlarm
|
|
593
|
+
* @param latencyImpactAlarm
|
|
594
|
+
* @param moreThanOneInstanceContributingToLatency
|
|
595
|
+
* @returns
|
|
596
|
+
*/
|
|
597
|
+
static createServerSideIsolatedAZImpactAlarm(scope, operationName, availabilityZoneId, counter, azIsOutlierForFaultsAlarm, availabilityImpactAlarm, moreThanOneInstanceContributingToFaults, azIsOutlierForLatencyAlarm, latencyImpactAlarm, moreThanOneInstanceContributingToLatency, nameSuffix) {
|
|
598
|
+
return new aws_cloudwatch_1.CompositeAlarm(scope, operationName + 'AZ' + counter + 'IsolatedImpactAlarm' + nameSuffix, {
|
|
599
|
+
compositeAlarmName: availabilityZoneId +
|
|
600
|
+
`-${operationName.toLowerCase()}-isolated-impact-alarm` +
|
|
601
|
+
nameSuffix,
|
|
602
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(moreThanOneInstanceContributingToFaults === undefined ||
|
|
603
|
+
moreThanOneInstanceContributingToFaults == null
|
|
604
|
+
? aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForFaultsAlarm, availabilityImpactAlarm)
|
|
605
|
+
: aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForFaultsAlarm, availabilityImpactAlarm, moreThanOneInstanceContributingToFaults), moreThanOneInstanceContributingToLatency === undefined ||
|
|
606
|
+
moreThanOneInstanceContributingToLatency == null
|
|
607
|
+
? aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForLatencyAlarm, latencyImpactAlarm)
|
|
608
|
+
: aws_cloudwatch_1.AlarmRule.allOf(azIsOutlierForLatencyAlarm, latencyImpactAlarm, moreThanOneInstanceContributingToLatency)),
|
|
609
|
+
actionsEnabled: false,
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Creates an alarm that fires if either the canary or the
|
|
614
|
+
* server side detect single AZ isolated impact
|
|
615
|
+
* @param scope
|
|
616
|
+
* @param operation
|
|
617
|
+
* @param availabilityZoneId
|
|
618
|
+
* @param counter
|
|
619
|
+
* @param serverSideAlarm
|
|
620
|
+
* @param canaryAlarm
|
|
621
|
+
* @returns
|
|
622
|
+
*/
|
|
623
|
+
static createAggregateIsolatedAZImpactAlarm(scope, operation, availabilityZoneId, counter, serverSideAlarm, canaryAlarm) {
|
|
624
|
+
return new aws_cloudwatch_1.CompositeAlarm(scope, operation.operationName + 'AZ' + counter + 'AggregateIsolatedImpactAlarm', {
|
|
625
|
+
compositeAlarmName: availabilityZoneId +
|
|
626
|
+
`-${operation.operationName.toLowerCase()}-aggregate-isolated-impact-alarm`,
|
|
627
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(serverSideAlarm, canaryAlarm),
|
|
628
|
+
actionsEnabled: false,
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Creates a regional availability alarm for the operation
|
|
633
|
+
* @param scope
|
|
634
|
+
* @param metricDetails
|
|
635
|
+
* @param nameSuffix
|
|
636
|
+
* @param counter
|
|
637
|
+
* @returns
|
|
638
|
+
*/
|
|
639
|
+
static createRegionalAvailabilityAlarm(scope, metricDetails, nameSuffix) {
|
|
640
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName + 'RegionalAvailabilityAlarm', {
|
|
641
|
+
alarmName: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
642
|
+
'-' +
|
|
643
|
+
metricDetails.operationName.toLowerCase() +
|
|
644
|
+
'-success-rate' +
|
|
645
|
+
nameSuffix,
|
|
646
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
647
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
648
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.LESS_THAN_THRESHOLD,
|
|
649
|
+
threshold: metricDetails.successAlarmThreshold,
|
|
650
|
+
actionsEnabled: false,
|
|
651
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
652
|
+
metric: RegionalAvailabilityMetrics_1.RegionalAvailabilityMetrics.createRegionalAvailabilityMetric({
|
|
653
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') + ' availability',
|
|
654
|
+
metricDetails: metricDetails,
|
|
655
|
+
metricType: AvailabilityMetricType_1.AvailabilityMetricType.SUCCESS_RATE,
|
|
656
|
+
}),
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Creates a regional latency alarm for the operation
|
|
661
|
+
* @param scope
|
|
662
|
+
* @param metricDetails
|
|
663
|
+
* @param nameSuffix
|
|
664
|
+
* @param counter
|
|
665
|
+
* @returns
|
|
666
|
+
*/
|
|
667
|
+
static createRegionalLatencyAlarm(scope, metricDetails, nameSuffix) {
|
|
668
|
+
return new aws_cloudwatch_1.Alarm(scope, metricDetails.operationName + 'RegionalLatencyAlarm', {
|
|
669
|
+
alarmName: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
670
|
+
'-' +
|
|
671
|
+
metricDetails.operationName.toLowerCase() +
|
|
672
|
+
'-success-latency' +
|
|
673
|
+
nameSuffix,
|
|
674
|
+
evaluationPeriods: metricDetails.evaluationPeriods,
|
|
675
|
+
datapointsToAlarm: metricDetails.datapointsToAlarm,
|
|
676
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
677
|
+
threshold: metricDetails.successAlarmThreshold,
|
|
678
|
+
actionsEnabled: false,
|
|
679
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE,
|
|
680
|
+
metric: RegionalLatencyMetrics_1.RegionalLatencyMetrics.createRegionalAverageLatencyMetric({
|
|
681
|
+
label: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
682
|
+
' ' +
|
|
683
|
+
metricDetails.alarmStatistic +
|
|
684
|
+
' latency',
|
|
685
|
+
metricDetails: metricDetails,
|
|
686
|
+
metricType: LatencyMetricType_1.LatencyMetricType.SUCCESS_LATENCY,
|
|
687
|
+
statistic: metricDetails.alarmStatistic,
|
|
688
|
+
}),
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* A composite alarm combining latency and availability alarms for this operation in the region
|
|
693
|
+
* as measured from either the server side or canary
|
|
694
|
+
* @param scope
|
|
695
|
+
* @param operation
|
|
696
|
+
* @param nameSuffix
|
|
697
|
+
* @param regionalAvailabilityAlarm
|
|
698
|
+
* @param regionalLatencyAlarm
|
|
699
|
+
* @returns
|
|
700
|
+
*/
|
|
701
|
+
static createRegionalCustomerExperienceAlarm(scope, operationName, nameSuffix, regionalAvailabilityAlarm, regionalLatencyAlarm) {
|
|
702
|
+
return new aws_cloudwatch_1.CompositeAlarm(scope, operationName + 'RegionalCustomerExperienceAlarm', {
|
|
703
|
+
compositeAlarmName: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
704
|
+
'-' +
|
|
705
|
+
operationName.toLowerCase() +
|
|
706
|
+
'-customer-experience-imact' +
|
|
707
|
+
nameSuffix,
|
|
708
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(regionalAvailabilityAlarm, regionalLatencyAlarm),
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
static createRegionalInstanceContributorsToHighLatency(scope, metricDetails, ruleDetails) {
|
|
712
|
+
let ruleBody = new InsightRuleBody_1.InsightRuleBody();
|
|
713
|
+
ruleBody.logGroupNames = ruleDetails.logGroups.map((x) => x.logGroupName);
|
|
714
|
+
ruleBody.aggregateOn = 'Count';
|
|
715
|
+
ruleBody.logFormat = 'JSON';
|
|
716
|
+
ruleBody.contribution = {
|
|
717
|
+
keys: [ruleDetails.instanceIdJsonPath],
|
|
718
|
+
filters: [
|
|
719
|
+
{
|
|
720
|
+
Match: ruleDetails.successLatencyMetricJsonPath,
|
|
721
|
+
GreaterThan: metricDetails.successAlarmThreshold,
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
Match: ruleDetails.operationNameJsonPath,
|
|
725
|
+
In: [metricDetails.operationName],
|
|
726
|
+
},
|
|
727
|
+
],
|
|
728
|
+
};
|
|
729
|
+
return new aws_cloudwatch_1.CfnInsightRule(scope, 'RegionPerInstanceHighLatencyRule', {
|
|
730
|
+
ruleName: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
731
|
+
`-${metricDetails.operationName.toLowerCase()}-per-instance-high-latency-server`,
|
|
732
|
+
ruleState: 'ENABLED',
|
|
733
|
+
ruleBody: ruleBody.toJson(),
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
static createRegionalInstanceContributorsToFaults(scope, metricDetails, ruleDetails) {
|
|
737
|
+
let ruleBody = new InsightRuleBody_1.InsightRuleBody();
|
|
738
|
+
ruleBody.logGroupNames = ruleDetails.logGroups.map((x) => x.logGroupName);
|
|
739
|
+
ruleBody.aggregateOn = 'Count';
|
|
740
|
+
ruleBody.logFormat = 'JSON';
|
|
741
|
+
ruleBody.contribution = {
|
|
742
|
+
keys: [ruleDetails.instanceIdJsonPath],
|
|
743
|
+
filters: [
|
|
744
|
+
{
|
|
745
|
+
Match: ruleDetails.faultMetricJsonPath,
|
|
746
|
+
GreaterThan: 0,
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
Match: ruleDetails.operationNameJsonPath,
|
|
750
|
+
In: [metricDetails.operationName],
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
};
|
|
754
|
+
return new aws_cloudwatch_1.CfnInsightRule(scope, 'RegionPerInstanceErrorRule', {
|
|
755
|
+
ruleName: aws_cdk_lib_1.Fn.ref('AWS::Region') +
|
|
756
|
+
`-${metricDetails.operationName.toLowerCase()}-per-instance-faults-server`,
|
|
757
|
+
ruleState: 'ENABLED',
|
|
758
|
+
ruleBody: ruleBody.toJson(),
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
exports.AvailabilityAndLatencyAlarmsAndRules = AvailabilityAndLatencyAlarmsAndRules;
|
|
763
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeUFsYXJtc0FuZFJ1bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsYXJtc2FuZHJ1bGVzL0F2YWlsYWJpbGl0eUFuZExhdGVuY3lBbGFybXNBbmRSdWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBcUU7QUFDckUsc0NBQXNDO0FBQ3RDLDZDQUEyQztBQUMzQywrREFVb0M7QUFTcEMsdURBQTZFO0FBRTdFLHdGQUFxRjtBQUNyRiw4RUFBMkU7QUFDM0Usa0ZBQStFO0FBQy9FLHdFQUFxRTtBQUlyRSxnRkFBNkU7QUFDN0Usc0VBQW1FO0FBR25FOztHQUVHO0FBQ0gsTUFBYSxvQ0FBb0M7SUFDL0M7Ozs7Ozs7O09BUUc7SUFDSCxNQUFNLENBQUMsNEJBQTRCLENBQ2pDLEtBQWdCLEVBQ2hCLGFBQXNDLEVBQ3RDLGtCQUEwQixFQUMxQixPQUFlLEVBQ2YsVUFBbUI7UUFFbkIsT0FBTyxJQUFJLHNCQUFLLENBQ2QsS0FBSyxFQUNMLGFBQWEsQ0FBQyxhQUFhLEdBQUcsSUFBSSxHQUFHLE9BQU8sR0FBRyxtQkFBbUIsRUFDbEU7WUFDRSxTQUFTLEVBQ1Asa0JBQWtCO2dCQUNsQixHQUFHO2dCQUNILGFBQWEsQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFO2dCQUN6QyxlQUFlO2dCQUNmLFVBQVU7WUFDWixpQkFBaUIsRUFBRSxhQUFhLENBQUMsaUJBQWlCO1lBQ2xELGlCQUFpQixFQUFFLGFBQWEsQ0FBQyxpQkFBaUI7WUFDbEQsa0JBQWtCLEVBQUUsbUNBQWtCLENBQUMsbUJBQW1CO1lBQzFELFNBQVMsRUFBRSxhQUFhLENBQUMscUJBQXFCO1lBQzlDLGNBQWMsRUFBRSxLQUFLO1lBQ3JCLGdCQUFnQixFQUFFLGlDQUFnQixDQUFDLE1BQU07WUFDekMsTUFBTSxFQUFFLG1EQUF3QixDQUFDLDZCQUE2QixDQUFDO2dCQUM3RCxrQkFBa0IsRUFBRSxrQkFBa0I7Z0JB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UUFDL0IsUUFBUSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUM7UUFDNUIsUUFBUSxDQUFDLFlBQVksR0FBRztZQUN0QixJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUM7WUFDdEMsT0FBTyxFQUFFO2dCQUNQO29CQUNFLEtBQUssRUFBRSxXQUFXLENBQUMsbUJBQW1CO29CQUN0QyxXQUFXLEVBQUUsQ0FBQztpQkFDZjtnQkFDRDtvQkFDRSxLQUFLLEVBQUUsV0FBVyxDQUFDLHFCQUFxQjtvQkFDeEMsRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQztpQkFDbEM7YUFDRjtTQUNvQyxDQUFDO1FBRXhDLE9BQU8sSUFBSSwrQkFBYyxDQUFDLEtBQUssRUFBRSw0QkFBNEIsRUFBRTtZQUM3RCxRQUFRLEVBQ04sZ0JBQUUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO2dCQUNyQixJQUFJLGFBQWEsQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLDZCQUE2QjtZQUM1RSxTQUFTLEVBQUUsU0FBUztZQUNwQixRQUFRLEVBQUUsUUFBUSxDQUFDLE1BQU0sRUFBRTtTQUM1QixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUE5akNELG9GQThqQ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5pbXBvcnQgeyBEdXJhdGlvbiwgRm4gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQge1xuICBJQWxhcm0sXG4gIEFsYXJtLFxuICBJTWV0cmljLFxuICBDb21wb3NpdGVBbGFybSxcbiAgQWxhcm1SdWxlLFxuICBNYXRoRXhwcmVzc2lvbixcbiAgQ2ZuSW5zaWdodFJ1bGUsXG4gIENvbXBhcmlzb25PcGVyYXRvcixcbiAgVHJlYXRNaXNzaW5nRGF0YSxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0IHsgQ2ZuTmF0R2F0ZXdheSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHtcbiAgQmFzZUxvYWRCYWxhbmNlcixcbiAgSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICBJTG9hZEJhbGFuY2VyVjIsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyJztcbmltcG9ydCB7IElGdW5jdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBJQ29udHJpYnV0aW9uRGVmaW5pdGlvbiwgSW5zaWdodFJ1bGVCb2R5IH0gZnJvbSAnLi9JbnNpZ2h0UnVsZUJvZHknO1xuaW1wb3J0IHsgSUF2YWlsYWJpbGl0eVpvbmVNYXBwZXIgfSBmcm9tICcuLi9hem1hcHBlci9JQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcic7XG5pbXBvcnQgeyBSZWdpb25hbEF2YWlsYWJpbGl0eU1ldHJpY3MgfSBmcm9tICcuLi9tZXRyaWNzL1JlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljcyc7XG5pbXBvcnQgeyBSZWdpb25hbExhdGVuY3lNZXRyaWNzIH0gZnJvbSAnLi4vbWV0cmljcy9SZWdpb25hbExhdGVuY3lNZXRyaWNzJztcbmltcG9ydCB7IFpvbmFsQXZhaWxhYmlsaXR5TWV0cmljcyB9IGZyb20gJy4uL21ldHJpY3MvWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzJztcbmltcG9ydCB7IFpvbmFsTGF0ZW5jeU1ldHJpY3MgfSBmcm9tICcuLi9tZXRyaWNzL1pvbmFsTGF0ZW5jeU1ldHJpY3MnO1xuaW1wb3J0IHsgSUNvbnRyaWJ1dG9ySW5zaWdodFJ1bGVEZXRhaWxzIH0gZnJvbSAnLi4vc2VydmljZXMvSUNvbnRyaWJ1dG9ySW5zaWdodFJ1bGVEZXRhaWxzJztcbmltcG9ydCB7IElPcGVyYXRpb24gfSBmcm9tICcuLi9zZXJ2aWNlcy9JT3BlcmF0aW9uJztcbmltcG9ydCB7IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzIH0gZnJvbSAnLi4vc2VydmljZXMvSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMnO1xuaW1wb3J0IHsgQXZhaWxhYmlsaXR5TWV0cmljVHlwZSB9IGZyb20gJy4uL3V0aWxpdGllcy9BdmFpbGFiaWxpdHlNZXRyaWNUeXBlJztcbmltcG9ydCB7IExhdGVuY3lNZXRyaWNUeXBlIH0gZnJvbSAnLi4vdXRpbGl0aWVzL0xhdGVuY3lNZXRyaWNUeXBlJztcbmltcG9ydCB7IE91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0gfSBmcm9tICcuLi91dGlsaXRpZXMvT3V0bGllckRldGVjdGlvbkFsZ29yaXRobSc7XG5cbi8qKlxuICogQ2xhc3MgdXNlZCB0byBjcmVhdGUgYXZhaWxhYmlsaXR5IGFuZCBsYXRlbmN5IGFsYXJtcyBhbmQgQ29udHJpYnV0b3IgSW5zaWdodCBydWxlc1xuICovXG5leHBvcnQgY2xhc3MgQXZhaWxhYmlsaXR5QW5kTGF0ZW5jeUFsYXJtc0FuZFJ1bGVzIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSB6b25hbCBhdmFpbGFiaWxpdHkgYWxhcm1cbiAgICogQHBhcmFtIHNjb3BlXG4gICAqIEBwYXJhbSBtZXRyaWNEZXRhaWxzXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVab25hbEF2YWlsYWJpbGl0eUFsYXJtKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgbWV0cmljRGV0YWlsczogSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lICsgJ0FaJyArIGNvdW50ZXIgKyAnQXZhaWxhYmlsaXR5QWxhcm0nLFxuICAgICAge1xuICAgICAgICBhbGFybU5hbWU6XG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICtcbiAgICAgICAgICAnLScgK1xuICAgICAgICAgIG1ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpICtcbiAgICAgICAgICAnLXN1Y2Nlc3MtcmF0ZScgK1xuICAgICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBtZXRyaWNEZXRhaWxzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogbWV0cmljRGV0YWlscy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBDb21wYXJpc29uT3BlcmF0b3IuTEVTU19USEFOX1RIUkVTSE9MRCxcbiAgICAgICAgdGhyZXNob2xkOiBtZXRyaWNEZXRhaWxzLnN1Y2Nlc3NBbGFybVRocmVzaG9sZCxcbiAgICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICAgICAgbWV0cmljOiBab25hbEF2YWlsYWJpbGl0eU1ldHJpY3MuY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWMoe1xuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICAgIGxhYmVsOiBhdmFpbGFiaWxpdHlab25lSWQgKyAnIGF2YWlsYWJpbGl0eScsXG4gICAgICAgICAgbWV0cmljRGV0YWlsczogbWV0cmljRGV0YWlscyxcbiAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLlNVQ0NFU1NfUkFURSxcbiAgICAgICAgfSksXG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHpvbmFsIGxhdGVuY3kgYWxhcm1cbiAgICogQHBhcmFtIHNjb3BlXG4gICAqIEBwYXJhbSBtZXRyaWNEZXRhaWxzXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVab25hbExhdGVuY3lBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG1ldHJpY0RldGFpbHM6IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzLFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBuYW1lU3VmZml4Pzogc3RyaW5nLFxuICApOiBJQWxhcm0ge1xuICAgIHJldHVybiBuZXcgQWxhcm0oXG4gICAgICBzY29wZSxcbiAgICAgIG1ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZSArICdBWicgKyBjb3VudGVyICsgJ0xhdGVuY3lBbGFybScsXG4gICAgICB7XG4gICAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICAgICctJyArXG4gICAgICAgICAgbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCkgK1xuICAgICAgICAgICctc3VjY2Vzcy1sYXRlbmN5JyArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IG1ldHJpY0RldGFpbHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgIGRhdGFwb2ludHNUb0FsYXJtOiBtZXRyaWNEZXRhaWxzLmRhdGFwb2ludHNUb0FsYXJtLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICB0aHJlc2hvbGQ6IG1ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgICAgICBtZXRyaWM6IFpvbmFsTGF0ZW5jeU1ldHJpY3MuY3JlYXRlWm9uYWxBdmVyYWdlTGF0ZW5jeU1ldHJpYyh7XG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgbGFiZWw6XG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgIG1ldHJpY0RldGFpbHMuYWxhcm1TdGF0aXN0aWMgK1xuICAgICAgICAgICAgJyBsYXRlbmN5JyxcbiAgICAgICAgICBtZXRyaWNEZXRhaWxzOiBtZXRyaWNEZXRhaWxzLFxuICAgICAgICAgIG1ldHJpY1R5cGU6IExhdGVuY3lNZXRyaWNUeXBlLlNVQ0NFU1NfTEFURU5DWSxcbiAgICAgICAgICBzdGF0aXN0aWM6IG1ldHJpY0RldGFpbHMuYWxhcm1TdGF0aXN0aWMsXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjb21wb3NpdGUgYWxhcm0gd2hlbiBlaXRoZXIgbGF0ZW5jeSBvciBhdmFpbGFiaWxpdHkgaXMgYnJlYWNoZWQgaW4gdGhlIEF2YWlsYWJpbHRpeSBab25lXG4gICAqIEBwYXJhbSBzY29wZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9uXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHBhcmFtIHpvbmFsQXZhaWxhYmlsaXR5QWxhcm1cbiAgICogQHBhcmFtIHpvbmFsTGF0ZW5jeUFsYXJtXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlWm9uYWxBdmFpbGFiaWxpdHlPckxhdGVuY3lDb21wb3NpdGVBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG9wZXJhdGlvbk5hbWU6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBjb3VudGVyOiBudW1iZXIsXG4gICAgem9uYWxBdmFpbGFiaWxpdHlBbGFybTogSUFsYXJtLFxuICAgIHpvbmFsTGF0ZW5jeUFsYXJtOiBJQWxhcm0sXG4gICAgbmFtZVN1ZmZpeD86IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICByZXR1cm4gbmV3IENvbXBvc2l0ZUFsYXJtKHNjb3BlLCAnQVonICsgY291bnRlciArICdab25hbEltcGFjdEFsYXJtJywge1xuICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICtcbiAgICAgICAgJyBoYXMgbGF0ZW5jeSBvciBhdmFpbGFiaWxpdHkgaW1wYWN0LiBUaGlzIGRvZXMgbm90IGluZGljYXRlIGl0IGlzIGFuIG91dGxpZXIgYW5kIHNob3dzIGlzb2xhdGVkIGltcGFjdC4nLFxuICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOlxuICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICBgLSR7b3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpfS1pbXBhY3QtYWdncmVnYXRlLWFsYXJtYCArXG4gICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZih6b25hbEF2YWlsYWJpbGl0eUFsYXJtLCB6b25hbExhdGVuY3lBbGFybSksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQW4gYWxhcm0gdGhhdCBjb21wYXJlcyBlcnJvciByYXRlIGluIHRoaXMgQVogdG8gdGhlIG92ZXJhbGwgcmVnaW9uIGVycm9yIGJhc2VkIG9ubHkgb24gbWV0cmljIGRhdGFcbiAgICogQHBhcmFtIHNjb3BlXG4gICAqIEBwYXJhbSBtZXRyaWNEZXRhaWxzXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHBhcmFtIG91dGxpZXJUaHJlc2hvbGRcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVab25hbEZhdWx0UmF0ZVN0YXRpY091dGxpZXJBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG1ldHJpY0RldGFpbHM6IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzLFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBvdXRsaWVyVGhyZXNob2xkOiBudW1iZXIsXG4gICAgbmFtZVN1ZmZpeD86IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICBsZXQgem9uYWxGYXVsdHM6IElNZXRyaWMgPVxuICAgICAgWm9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzLmNyZWF0ZVpvbmFsQXZhaWxhYmlsaXR5TWV0cmljKHtcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgIG1ldHJpY0RldGFpbHM6IG1ldHJpY0RldGFpbHMsXG4gICAgICAgIG1ldHJpY1R5cGU6IEF2YWlsYWJpbGl0eU1ldHJpY1R5cGUuRkFVTFRfQ09VTlQsXG4gICAgICAgIGtleVByZWZpeDogJ2EnLFxuICAgICAgfSk7XG5cbiAgICBsZXQgcmVnaW9uYWxGYXVsdHM6IElNZXRyaWMgPVxuICAgICAgUmVnaW9uYWxBdmFpbGFiaWxpdHlNZXRyaWNzLmNyZWF0ZVJlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljKHtcbiAgICAgICAgbWV0cmljRGV0YWlsczogbWV0cmljRGV0YWlscyxcbiAgICAgICAgbWV0cmljVHlwZTogQXZhaWxhYmlsaXR5TWV0cmljVHlwZS5GQVVMVF9DT1VOVCxcbiAgICAgICAga2V5UHJlZml4OiAnYicsXG4gICAgICB9KTtcblxuICAgIHJldHVybiBuZXcgQWxhcm0oc2NvcGUsICdBWicgKyBjb3VudGVyICsgJ0lzb2xhdGVkSW1wYWN0QWxhcm1TdGF0aWMnLCB7XG4gICAgICBhbGFybU5hbWU6XG4gICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgIGAtJHttZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0tc3RhdGljLW1ham9yaXR5LWVycm9ycy1pbXBhY3RgICtcbiAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgIG1ldHJpYzogbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgICAgZXhwcmVzc2lvbjogJ0lGKG0yID4gMCwgKG0xIC8gbTIpLCAwKScsXG4gICAgICAgIHVzaW5nTWV0cmljczoge1xuICAgICAgICAgIG0xOiB6b25hbEZhdWx0cyxcbiAgICAgICAgICBtMjogcmVnaW9uYWxGYXVsdHMsXG4gICAgICAgIH0sXG4gICAgICAgIHBlcmlvZDogbWV0cmljRGV0YWlscy5wZXJpb2QsXG4gICAgICAgIGxhYmVsOiBhdmFpbGFiaWxpdHlab25lSWQgKyAnIHBlcmNlbnQgZmF1bHRzJyxcbiAgICAgIH0pLFxuICAgICAgdGhyZXNob2xkOiBvdXRsaWVyVGhyZXNob2xkLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBtZXRyaWNEZXRhaWxzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm06IG1ldHJpY0RldGFpbHMuZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlWm9uYWxGYXVsdFJhdGVPdXRsaWVyQWxhcm0oXG4gICAgc2NvcGU6IElDb25zdHJ1Y3QsXG4gICAgbWV0cmljRGV0YWlsczogSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgYWxsQXZhaWxhYmlsaXR5Wm9uZUlkczogc3RyaW5nW10sXG4gICAgb3V0bGllclRocmVzaG9sZDogbnVtYmVyLFxuICAgIG91dGxpZXJEZXRlY3Rpb25GdW5jdGlvbjogSUZ1bmN0aW9uLFxuICAgIG91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG06IE91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0sXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgbGV0IG1ldHJpY0RpbWVuc2lvbnM6IHsgW2tleTogc3RyaW5nXTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfVtdIH0gPSB7fTtcblxuICAgIGFsbEF2YWlsYWJpbGl0eVpvbmVJZHMuZm9yRWFjaCgoYXpJZDogc3RyaW5nKSA9PiB7XG4gICAgICBtZXRyaWNEaW1lbnNpb25zW2F6SWRdID0gW1xuICAgICAgICBtZXRyaWNEZXRhaWxzLm1ldHJpY0RpbWVuc2lvbnMuem9uYWxEaW1lbnNpb25zKFxuICAgICAgICAgIGF6SWQsXG4gICAgICAgICAgRm4ucmVmKCdBV1M6OlJlZ2lvbicpLFxuICAgICAgICApLFxuICAgICAgXTtcbiAgICB9KTtcblxuICAgIGxldCBzdHI6IHN0cmluZyA9IEpTT04uc3RyaW5naWZ5KG1ldHJpY0RpbWVuc2lvbnMpXG4gICAgICAucmVwbGFjZSgvW1xcXFxdL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvW1xcXCJdL2csICdcXFxcXCInKVxuICAgICAgLnJlcGxhY2UoL1tcXC9dL2csICdcXFxcLycpXG4gICAgICAucmVwbGFjZSgvW1xcYl0vZywgJ1xcXFxiJylcbiAgICAgIC5yZXBsYWNlKC9bXFxmXS9nLCAnXFxcXGYnKVxuICAgICAgLnJlcGxhY2UoL1tcXG5dL2csICdcXFxcbicpXG4gICAgICAucmVwbGFjZSgvW1xccl0vZywgJ1xcXFxyJylcbiAgICAgIC5yZXBsYWNlKC9bXFx0XS9nLCAnXFxcXHQnKTtcblxuICAgIGxldCBvdXRsaWVyTWV0cmljczogSU1ldHJpYyA9IG5ldyBNYXRoRXhwcmVzc2lvbih7XG4gICAgICBleHByZXNzaW9uOlxuICAgICAgICBgTUFYKExBTUJEQShcIiR7b3V0bGllckRldGVjdGlvbkZ1bmN0aW9uLmZ1bmN0aW9uTmFtZX1cIixgICtcbiAgICAgICAgYFwiJHtvdXRsaWVyRGV0ZWN0aW9uQWxnb3JpdGhtLnRvU3RyaW5nKCl9XCIsYCArXG4gICAgICAgIGBcIiR7b3V0bGllclRocmVzaG9sZH1cIixgICtcbiAgICAgICAgYFwiJHthdmFpbGFiaWxpdHlab25lSWR9XCIsYCArXG4gICAgICAgIGBcIiR7c3RyfVwiLGAgK1xuICAgICAgICBgXCIke21ldHJpY0RldGFpbHMubWV0cmljTmFtZXNwYWNlfVwiLGAgK1xuICAgICAgICBgXCIke21ldHJpY0RldGFpbHMuZmF1bHRNZXRyaWNOYW1lcy5qb2luKCc6Jyl9XCIsYCArXG4gICAgICAgICdcIlN1bVwiLCcgK1xuICAgICAgICAnXCJDb3VudFwiJyArXG4gICAgICAgICcpKScsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgJ0FaJyArIGNvdW50ZXIgKyAnRmF1bHRJc29sYXRlZEltcGFjdEFsYXJtT3V0bGllcicsXG4gICAgICB7XG4gICAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICAgIGAtJHttZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0tbWFqb3JpdHktZXJyb3JzLWltcGFjdGAgK1xuICAgICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICAgIG1ldHJpYzogb3V0bGllck1ldHJpY3MsXG4gICAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOlxuICAgICAgICAgIENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xELFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLk5PVF9CUkVBQ0hJTkcsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBtZXRyaWNEZXRhaWxzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogbWV0cmljRGV0YWlscy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVab25hbEZhdWx0UmF0ZU91dGxpZXJBbGFybUZvckFsYihcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBsb2FkQmFsYW5jZXJzOiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJbXSxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBvdXRsaWVyVGhyZXNob2xkOiBudW1iZXIsXG4gICAgb3V0bGllckRldGVjdGlvbkZ1bmN0aW9uOiBJRnVuY3Rpb24sXG4gICAgb3V0bGllckRldGVjdGlvbkFsZ29yaXRobTogT3V0bGllckRldGVjdGlvbkFsZ29yaXRobSxcbiAgICBhek1hcHBlcjogSUF2YWlsYWJpbGl0eVpvbmVNYXBwZXIsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIGV2YWx1YXRpb25QZXJpb2RzOiBudW1iZXIsXG4gICAgZGF0YXBvaW50c1RvQWxhcm06IG51bWJlcixcbiAgICBuYW1lU3VmZml4Pzogc3RyaW5nLFxuICApOiBJQWxhcm0ge1xuICAgIGxldCBtZXRyaWNEaW1lbnNpb25zOiB7IFtrZXk6IHN0cmluZ106IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH1bXSB9ID0ge307XG5cbiAgICBsb2FkQmFsYW5jZXJzLmZvckVhY2goKHgpID0+IHtcbiAgICAgIHgudnBjPy5hdmFpbGFiaWxpdHlab25lcy5mb3JFYWNoKChheikgPT4ge1xuICAgICAgICBsZXQgYXpJZCA9IGF6TWFwcGVyLmF2YWlsYWJpbGl0eVpvbmVJZEZyb21BdmFpbGFiaWxpdHlab25lTGV0dGVyKFxuICAgICAgICAgIGF6LnN1YnN0cmluZyhhei5sZW5ndGggLSAxKSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCEoYXpJZCBpbiBtZXRyaWNEaW1lbnNpb25zKSkge1xuICAgICAgICAgIG1ldHJpY0RpbWVuc2lvbnNbYXpJZF0gPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1ldHJpY0RpbWVuc2lvbnNbYXpJZF0ucHVzaCh7XG4gICAgICAgICAgQXZhaWxhYmlsaXR5Wm9uZTogYXosXG4gICAgICAgICAgTG9hZEJhbGFuY2VyOiAoeCBhcyBJTG9hZEJhbGFuY2VyVjIgYXMgQmFzZUxvYWRCYWxhbmNlcilcbiAgICAgICAgICAgIC5sb2FkQmFsYW5jZXJGdWxsTmFtZSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGxldCBzdHI6IHN0cmluZyA9IEpTT04uc3RyaW5naWZ5KG1ldHJpY0RpbWVuc2lvbnMpXG4gICAgICAucmVwbGFjZSgvW1xcXFxdL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvW1xcXCJdL2csICdcXFxcXCInKVxuICAgICAgLnJlcGxhY2UoL1tcXC9dL2csICdcXFxcLycpXG4gICAgICAucmVwbGFjZSgvW1xcYl0vZywgJ1xcXFxiJylcbiAgICAgIC5yZXBsYWNlKC9bXFxmXS9nLCAnXFxcXGYnKVxuICAgICAgLnJlcGxhY2UoL1tcXG5dL2csICdcXFxcbicpXG4gICAgICAucmVwbGFjZSgvW1xccl0vZywgJ1xcXFxyJylcbiAgICAgIC5yZXBsYWNlKC9bXFx0XS9nLCAnXFxcXHQnKTtcblxuICAgIGxldCBvdXRsaWVyTWV0cmljczogSU1ldHJpYyA9IG5ldyBNYXRoRXhwcmVzc2lvbih7XG4gICAgICBleHByZXNzaW9uOlxuICAgICAgICBgTUFYKExBTUJEQShcIiR7b3V0bGllckRldGVjdGlvbkZ1bmN0aW9uLmZ1bmN0aW9uTmFtZX1cIixgICtcbiAgICAgICAgYFwiJHtvdXRsaWVyRGV0ZWN0aW9uQWxnb3JpdGhtLnRvU3RyaW5nKCl9XCIsYCArXG4gICAgICAgIGBcIiR7b3V0bGllclRocmVzaG9sZH1cIixgICtcbiAgICAgICAgYFwiJHthdmFpbGFiaWxpdHlab25lSWR9XCIsYCArXG4gICAgICAgIGBcIiR7c3RyfVwiLGAgK1xuICAgICAgICAnXCJBV1MvQXBwbGljYXRpb25FTEJcIiwnICtcbiAgICAgICAgJ1wiSFRUUENvZGVfRUxCXzVYWF9Db3VudDpIVFRQQ29kZV9UYXJnZXRfNVhYX0NvdW50XCIsJyArXG4gICAgICAgICdcIlN1bVwiLCcgK1xuICAgICAgICAnXCJDb3VudFwiJyArXG4gICAgICAgICcpKScsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBBbGFybShzY29wZSwgJ0FaJyArIGNvdW50ZXIgKyAnQWxiSXNvbGF0ZWRJbXBhY3RBbGFybU91dGxpZXInLCB7XG4gICAgICBhbGFybU5hbWU6XG4gICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArICctYWxiLW1ham9yaXR5LWVycm9ycy1pbXBhY3QnICsgbmFtZVN1ZmZpeCxcbiAgICAgIG1ldHJpYzogb3V0bGllck1ldHJpY3MsXG4gICAgICB0aHJlc2hvbGQ6IDEsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xELFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm06IGRhdGFwb2ludHNUb0FsYXJtLFxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZVpvbmFsRmF1bHRSYXRlT3V0bGllckFsYXJtRm9yTmF0R1coXG4gICAgc2NvcGU6IElDb25zdHJ1Y3QsXG4gICAgbmF0R2F0ZXdheXM6IHsgW2tleTogc3RyaW5nXTogQ2ZuTmF0R2F0ZXdheVtdIH0sXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgb3V0bGllclRocmVzaG9sZDogbnVtYmVyLFxuICAgIG91dGxpZXJEZXRlY3Rpb25GdW5jdGlvbjogSUZ1bmN0aW9uLFxuICAgIG91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG06IE91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0sXG4gICAgYXpNYXBwZXI6IElBdmFpbGFiaWxpdHlab25lTWFwcGVyLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBldmFsdWF0aW9uUGVyaW9kczogbnVtYmVyLFxuICAgIGRhdGFwb2ludHNUb0FsYXJtOiBudW1iZXIsXG4gICAgbmFtZVN1ZmZpeD86IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICBsZXQgbWV0cmljRGltZW5zaW9uczogeyBba2V5OiBzdHJpbmddOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9W10gfSA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMobmF0R2F0ZXdheXMpLmZvckVhY2goKGF6KSA9PiB7XG4gICAgICBsZXQgYXpJZCA9IGF6TWFwcGVyLmF2YWlsYWJpbGl0eVpvbmVJZEZyb21BdmFpbGFiaWxpdHlab25lTGV0dGVyKFxuICAgICAgICBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSksXG4gICAgICApO1xuXG4gICAgICBpZiAoIShheklkIGluIG1ldHJpY0RpbWVuc2lvbnMpKSB7XG4gICAgICAgIG1ldHJpY0RpbWVuc2lvbnNbYXpJZF0gPSBbXTtcbiAgICAgIH1cblxuICAgICAgbmF0R2F0ZXdheXNbYXpdLmZvckVhY2goKG5hdGd3KSA9PiB7XG4gICAgICAgIG1ldHJpY0RpbWVuc2lvbnNbYXpJZF0ucHVzaCh7XG4gICAgICAgICAgTmF0R2F0ZXdheUlkOiBuYXRndy5hdHRyTmF0R2F0ZXdheUlkLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgbGV0IHN0cjogc3RyaW5nID0gSlNPTi5zdHJpbmdpZnkobWV0cmljRGltZW5zaW9ucylcbiAgICAgIC5yZXBsYWNlKC9bXFxcXF0vZywgJ1xcXFxcXFxcJylcbiAgICAgIC5yZXBsYWNlKC9bXFxcIl0vZywgJ1xcXFxcIicpXG4gICAgICAucmVwbGFjZSgvW1xcL10vZywgJ1xcXFwvJylcbiAgICAgIC5yZXBsYWNlKC9bXFxiXS9nLCAnXFxcXGInKVxuICAgICAgLnJlcGxhY2UoL1tcXGZdL2csICdcXFxcZicpXG4gICAgICAucmVwbGFjZSgvW1xcbl0vZywgJ1xcXFxuJylcbiAgICAgIC5yZXBsYWNlKC9bXFxyXS9nLCAnXFxcXHInKVxuICAgICAgLnJlcGxhY2UoL1tcXHRdL2csICdcXFxcdCcpO1xuXG4gICAgbGV0IG91dGxpZXJNZXRyaWNzOiBJTWV0cmljID0gbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgIGV4cHJlc3Npb246XG4gICAgICAgIGBNQVgoTEFNQkRBKFwiJHtvdXRsaWVyRGV0ZWN0aW9uRnVuY3Rpb24uZnVuY3Rpb25OYW1lfVwiLGAgK1xuICAgICAgICBgXCIke291dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0udG9TdHJpbmcoKX1cIixgICtcbiAgICAgICAgYFwiJHtvdXRsaWVyVGhyZXNob2xkfVwiLGAgK1xuICAgICAgICBgXCIke2F2YWlsYWJpbGl0eVpvbmVJZH1cIixgICtcbiAgICAgICAgYFwiJHtzdHJ9XCIsYCArXG4gICAgICAgICdcIkFXUy9OQVRHYXRld2F5XCIsJyArXG4gICAgICAgICdcIlBhY2tldHNEcm9wQ291bnRcIiwnICtcbiAgICAgICAgJ1wiU3VtXCIsJyArXG4gICAgICAgICdcIkNvdW50XCInICtcbiAgICAgICAgJykpJyxcbiAgICAgIHBlcmlvZDogRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbmV3IEFsYXJtKFxuICAgICAgc2NvcGUsXG4gICAgICAnQVonICsgY291bnRlciArICdOYXRHV0lzb2xhdGVkSW1wYWN0QWxhcm1PdXRsaWVyJyxcbiAgICAgIHtcbiAgICAgICAgYWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArICctbmF0LWd3LW1ham9yaXR5LWVycm9ycy1pbXBhY3QnICsgbmFtZVN1ZmZpeCxcbiAgICAgICAgbWV0cmljOiBvdXRsaWVyTWV0cmljcyxcbiAgICAgICAgdGhyZXNob2xkOiAxLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6XG4gICAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlWm9uYWxIaWdoTGF0ZW5jeU91dGxpZXJBbGFybShcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBtZXRyaWNEZXRhaWxzOiBJT3BlcmF0aW9uTWV0cmljRGV0YWlscyxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBhbGxBdmFpbGFiaWxpdHlab25lSWRzOiBzdHJpbmdbXSxcbiAgICBvdXRsaWVyVGhyZXNob2xkOiBudW1iZXIsXG4gICAgb3V0bGllckRldGVjdGlvbkZ1bmN0aW9uOiBJRnVuY3Rpb24sXG4gICAgb3V0bGllckRldGVjdGlvbkFsZ29yaXRobTogT3V0bGllckRldGVjdGlvbkFsZ29yaXRobSxcbiAgICBjb3VudGVyOiBudW1iZXIsXG4gICAgbmFtZVN1ZmZpeD86IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICBsZXQgbWV0cmljRGltZW5zaW9uczogeyBba2V5OiBzdHJpbmddOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9W10gfSA9IHt9O1xuXG4gICAgYWxsQXZhaWxhYmlsaXR5Wm9uZUlkcy5mb3JFYWNoKChheklkOiBzdHJpbmcpID0+IHtcbiAgICAgIG1ldHJpY0RpbWVuc2lvbnNbYXpJZF0gPSBbXG4gICAgICAgIG1ldHJpY0RldGFpbHMubWV0cmljRGltZW5zaW9ucy56b25hbERpbWVuc2lvbnMoXG4gICAgICAgICAgYXpJZCxcbiAgICAgICAgICBGbi5yZWYoJ0FXUzo6UmVnaW9uJyksXG4gICAgICAgICksXG4gICAgICBdO1xuICAgIH0pO1xuXG4gICAgbGV0IHN0cjogc3RyaW5nID0gSlNPTi5zdHJpbmdpZnkobWV0cmljRGltZW5zaW9ucylcbiAgICAgIC5yZXBsYWNlKC9bXFxcXF0vZywgJ1xcXFxcXFxcJylcbiAgICAgIC5yZXBsYWNlKC9bXFxcIl0vZywgJ1xcXFxcIicpXG4gICAgICAucmVwbGFjZSgvW1xcL10vZywgJ1xcXFwvJylcbiAgICAgIC5yZXBsYWNlKC9bXFxiXS9nLCAnXFxcXGInKVxuICAgICAgLnJlcGxhY2UoL1tcXGZdL2csICdcXFxcZicpXG4gICAgICAucmVwbGFjZSgvW1xcbl0vZywgJ1xcXFxuJylcbiAgICAgIC5yZXBsYWNlKC9bXFxyXS9nLCAnXFxcXHInKVxuICAgICAgLnJlcGxhY2UoL1tcXHRdL2csICdcXFxcdCcpO1xuXG4gICAgbGV0IG91dGxpZXJNZXRyaWNzOiBJTWV0cmljID0gbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgIGV4cHJlc3Npb246XG4gICAgICAgIGBNQVgoTEFNQkRBKFwiJHtvdXRsaWVyRGV0ZWN0aW9uRnVuY3Rpb24uZnVuY3Rpb25OYW1lfVwiLGAgK1xuICAgICAgICBgXCIke291dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0udG9TdHJpbmcoKX1cIixgICtcbiAgICAgICAgYFwiJHtvdXRsaWVyVGhyZXNob2xkfVwiLGAgK1xuICAgICAgICBgXCIke2F2YWlsYWJpbGl0eVpvbmVJZH1cIixgICtcbiAgICAgICAgYFwiJHtzdHJ9XCIsYCArXG4gICAgICAgIGBcIiR7bWV0cmljRGV0YWlscy5tZXRyaWNOYW1lc3BhY2V9XCIsYCArXG4gICAgICAgIGBcIiR7bWV0cmljRGV0YWlscy5zdWNjZXNzTWV0cmljTmFtZXMuam9pbignOicpfVwiLGAgK1xuICAgICAgICBgXCJUQygke21ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkfTopXCIsYCArXG4gICAgICAgICdcIk1pbGxpc2Vjb25kc1wiJyArXG4gICAgICAgICcpKScsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lICtcbiAgICAgICAgJ0FaJyArXG4gICAgICAgIGNvdW50ZXIgK1xuICAgICAgICAnTGF0ZW5jeUlzb2xhdGVkSW1wYWN0QWxhcm1PdXRsaWVyJyxcbiAgICAgIHtcbiAgICAgICAgYWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgYC0ke21ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpfS1tYWpvcml0eS1oaWdoLWxhdGVuY3ktaW1wYWN0YCArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgbWV0cmljOiBvdXRsaWVyTWV0cmljcyxcbiAgICAgICAgdGhyZXNob2xkOiAxLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6XG4gICAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IG1ldHJpY0RldGFpbHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgIGRhdGFwb2ludHNUb0FsYXJtOiBtZXRyaWNEZXRhaWxzLmRhdGFwb2ludHNUb0FsYXJtLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZVpvbmFsSGlnaExhdGVuY3lTdGF0aWNPdXRsaWVyQWxhcm0oXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBtZXRyaWNEZXRhaWxzOiBJT3BlcmF0aW9uTWV0cmljRGV0YWlscyxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBjb3VudGVyOiBudW1iZXIsXG4gICAgb3V0bGllclRocmVzaG9sZDogbnVtYmVyLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgbGV0IHpvbmFsTGF0ZW5jeTogSU1ldHJpYyA9XG4gICAgICBab25hbExhdGVuY3lNZXRyaWNzLmNyZWF0ZVpvbmFsQ291bnRMYXRlbmN5TWV0cmljKHtcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgIGxhYmVsOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgJy0nICtcbiAgICAgICAgICBtZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUgK1xuICAgICAgICAgICctaGlnaC1sYXRlbmN5LXJlcXVlc3RzJyxcbiAgICAgICAgbWV0cmljRGV0YWlsczogbWV0cmljRGV0YWlscyxcbiAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuU1VDQ0VTU19MQVRFTkNZLFxuICAgICAgICBzdGF0aXN0aWM6IGBUQygke21ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkfTopYCxcbiAgICAgICAga2V5UHJlZml4OiAnYScsXG4gICAgICB9KTtcblxuICAgIGxldCByZWdpb25hbExhdGVuY3k6IElNZXRyaWMgPVxuICAgICAgUmVnaW9uYWxMYXRlbmN5TWV0cmljcy5jcmVhdGVSZWdpb25hbExhdGVuY3lDb3VudE1ldHJpYyh7XG4gICAgICAgIGxhYmVsOlxuICAgICAgICAgIEZuLnJlZignQVdTOjpSZWdpb24nKSArXG4gICAgICAgICAgJy0nICtcbiAgICAgICAgICBtZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUgK1xuICAgICAgICAgICctaGlnaC1sYXRlbmN5LXJlcXVlc3RzJyxcbiAgICAgICAgbWV0cmljRGV0YWlsczogbWV0cmljRGV0YWlscyxcbiAgICAgICAgbWV0cmljVHlwZTogTGF0ZW5jeU1ldHJpY1R5cGUuU1VDQ0VTU19MQVRFTkNZLFxuICAgICAgICBzdGF0aXN0aWM6IGBUQygke21ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkfTopYCxcbiAgICAgICAga2V5UHJlZml4OiAnYicsXG4gICAgICB9KTtcblxuICAgIHJldHVybiBuZXcgQWxhcm0oXG4gICAgICBzY29wZSxcbiAgICAgIG1ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZSArXG4gICAgICAgICdBWicgK1xuICAgICAgICBjb3VudGVyICtcbiAgICAgICAgJ0lzb2xhdGVkSW1wYWN0QWxhcm1TdGF0aWMnLFxuICAgICAge1xuICAgICAgICBhbGFybU5hbWU6XG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICtcbiAgICAgICAgICBgLSR7bWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCl9LXN0YXRpYy1tYWpvcml0eS1oaWdoLWxhdGVuY3ktaW1wYWN0YCArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgbWV0cmljOiBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgICAgIGV4cHJlc3Npb246ICdJRihtMiA+IDAsIChtMSAvIG0yKSwgMCknLFxuICAgICAgICAgIHVzaW5nTWV0cmljczoge1xuICAgICAgICAgICAgbTE6IHpvbmFsTGF0ZW5jeSxcbiAgICAgICAgICAgIG0yOiByZWdpb25hbExhdGVuY3ksXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwZXJpb2Q6IG1ldHJpY0RldGFpbHMucGVyaW9kLFxuICAgICAgICAgIGxhYmVsOiBhdmFpbGFiaWxpdHlab25lSWQgKyAnIHBlcmNlbnQgaGlnaCBsYXRlbmN5IHJlcXVlc3RzJyxcbiAgICAgICAgfSksXG4gICAgICAgIHRocmVzaG9sZDogb3V0bGllclRocmVzaG9sZCxcbiAgICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOlxuICAgICAgICAgIENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xELFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLk5PVF9CUkVBQ0hJTkcsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBtZXRyaWNEZXRhaWxzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogbWV0cmljRGV0YWlscy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpbnNpZ2h0IHJ1bGUgdGhhdCBjYWxjdWxhdGVzIGhvdyBtYW55IGluc3RhbmNlcyBhcmUgcmVzcG9uZGluZyB0byByZXF1ZXN0cyBpblxuICAgKiB0aGUgc3BlY2lmaWVkIEFaLiBPbmx5IHVzZWZ1bCBmb3Igc2VydmVyLXNpZGUgbWV0cmljcyBzaW5jZSB0aGUgY2FuYXJ5IGRvZXNuJ3QgcmVjb3JkIGluc3RhbmNlIGlkIG1ldHJpY3MuXG4gICAqIEBwYXJhbSBzY29wZVxuICAgKiBAcGFyYW0gbWV0cmljRGV0YWlsc1xuICAgKiBAcGFyYW0gYXZhaWxhYmlsaXR5Wm9uZUlkXG4gICAqIEBwYXJhbSBsb2dHcm91cHNcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHBhcmFtIGluc3RhbmNlSWRQYXRoXG4gICAqIEBwYXJhbSBvcGVyYXRpb25OYW1lUGF0aFxuICAgKiBAcGFyYW0gYXZhaWxhYmlsaXR5Wm9uZUlkUGF0aFxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgc3RhdGljIGNyZWF0ZVNlcnZlclNpZGVJbnN0YW5jZXNIYW5kbGluZ1JlcXVlc3RzSW5UaGlzQVpSdWxlKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgb3BlcmF0aW9uTmFtZTogc3RyaW5nLFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIHJ1bGVEZXRhaWxzOiBJQ29udHJpYnV0b3JJbnNpZ2h0UnVsZURldGFpbHMsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IENmbkluc2lnaHRSdWxlIHtcbiAgICBsZXQgcnVsZUJvZHkgPSBuZXcgSW5zaWdodFJ1bGVCb2R5KCk7XG4gICAgcnVsZUJvZHkubG9nR3JvdXBOYW1lcyA9IHJ1bGVEZXRhaWxzLmxvZ0dyb3Vwcy5tYXAoKHgpID0+IHgubG9nR3JvdXBOYW1lKTtcbiAgICBydWxlQm9keS5hZ2dyZWdhdGVPbiA9ICdDb3VudCc7XG4gICAgcnVsZUJvZHkubG9nRm9ybWF0ID0gJ0pTT04nO1xuXG4gICAgcnVsZUJvZHkuY29udHJpYnV0aW9uID0ge1xuICAgICAga2V5czogW3J1bGVEZXRhaWxzLmluc3RhbmNlSWRKc29uUGF0aF0sXG4gICAgICBmaWx0ZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMuYXZhaWxhYmlsaXR5Wm9uZUlkSnNvblBhdGgsXG4gICAgICAgICAgSW46IFthdmFpbGFiaWxpdHlab25lSWRdLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgTWF0Y2g6IHJ1bGVEZXRhaWxzLm9wZXJhdGlvbk5hbWVKc29uUGF0aCxcbiAgICAgICAgICBJbjogW29wZXJhdGlvbk5hbWVdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9IGFzIHVua25vd24gYXMgSUNvbnRyaWJ1dGlvbkRlZmluaXRpb247XG5cbiAgICByZXR1cm4gbmV3IENmbkluc2lnaHRSdWxlKHNjb3BlLCAnQVonICsgY291bnRlciArICdJbnN0YW5jZXNJblRoZUFaUnVsZScsIHtcbiAgICAgIHJ1bGVOYW1lOlxuICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICBgLSR7b3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpfS1pbnN0YW5jZXMtaW4tdGhlLWF6YCArXG4gICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICBydWxlU3RhdGU6ICdFTkFCTEVEJyxcbiAgICAgIHJ1bGVCb2R5OiBydWxlQm9keS50b0pzb24oKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpbnNpZ2h0IHJ1bGUgdGhhdCBjYWxjdWxhdGVzIHRoZSBpbnN0YW5jZXMgY29udHJpYnV0aW5nIHRvIGVycm9yc1xuICAgKiBpbiB0aGlzIEFaLiBPbmx5IHVzZWZ1bCBmb3Igc2VydmVyLXNpZGUgbWV0cmljcyBzaW5jZSB0aGUgY2FuYXJ5IGRvZXNuJ3QgcmVjb3JkIGluc3RhbmNlIGlkIG1ldHJpY3MuXG4gICAqIEBwYXJhbSBzY29wZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9uXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIGxvZ0dyb3Vwc1xuICAgKiBAcGFyYW0gbmFtZVN1ZmZpeFxuICAgKiBAcGFyYW0gY291bnRlclxuICAgKiBAcGFyYW0gaW5zdGFuY2VJZFBhdGhcbiAgICogQHBhcmFtIG9wZXJhdGlvbk5hbWVQYXRoXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRQYXRoXG4gICAqIEBwYXJhbSBlcnJvck1ldHJpY1BhdGhcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVTZXJ2ZXJTaWRlSW5zdGFuY2VGYXVsdENvbnRyaWJ1dG9yc0luVGhpc0FaUnVsZShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG9wZXJhdGlvbk5hbWU6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBydWxlRGV0YWlsczogSUNvbnRyaWJ1dG9ySW5zaWdodFJ1bGVEZXRhaWxzLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBuYW1lU3VmZml4Pzogc3RyaW5nLFxuICApOiBDZm5JbnNpZ2h0UnVsZSB7XG4gICAgbGV0IHJ1bGVCb2R5ID0gbmV3IEluc2lnaHRSdWxlQm9keSgpO1xuICAgIHJ1bGVCb2R5LmxvZ0dyb3VwTmFtZXMgPSBydWxlRGV0YWlscy5sb2dHcm91cHMubWFwKCh4KSA9PiB4LmxvZ0dyb3VwTmFtZSk7XG4gICAgcnVsZUJvZHkuYWdncmVnYXRlT24gPSAnQ291bnQnO1xuICAgIHJ1bGVCb2R5LmxvZ0Zvcm1hdCA9ICdKU09OJztcbiAgICBydWxlQm9keS5jb250cmlidXRpb24gPSB7XG4gICAgICBrZXlzOiBbcnVsZURldGFpbHMuaW5zdGFuY2VJZEpzb25QYXRoXSxcbiAgICAgIGZpbHRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIE1hdGNoOiBydWxlRGV0YWlscy5hdmFpbGFiaWxpdHlab25lSWRKc29uUGF0aCxcbiAgICAgICAgICBJbjogW2F2YWlsYWJpbGl0eVpvbmVJZF0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMub3BlcmF0aW9uTmFtZUpzb25QYXRoLFxuICAgICAgICAgIEluOiBbb3BlcmF0aW9uTmFtZV0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMuZmF1bHRNZXRyaWNKc29uUGF0aCxcbiAgICAgICAgICBHcmVhdGVyVGhhbjogMCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSBhcyB1bmtub3duIGFzIElDb250cmlidXRpb25EZWZpbml0aW9uO1xuXG4gICAgcmV0dXJuIG5ldyBDZm5JbnNpZ2h0UnVsZShcbiAgICAgIHNjb3BlLFxuICAgICAgJ0FaJyArIGNvdW50ZXIgKyAnSW5zdGFuY2VFcnJvckNvbnRyaWJ1dGlvblJ1bGUnLFxuICAgICAge1xuICAgICAgICBydWxlTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICAgIGAtJHtvcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCl9LXBlci1pbnN0YW5jZS1mYXVsdHNgICtcbiAgICAgICAgICBuYW1lU3VmZml4LFxuICAgICAgICBydWxlU3RhdGU6ICdFTkFCTEVEJyxcbiAgICAgICAgcnVsZUJvZHk6IHJ1bGVCb2R5LnRvSnNvbigpLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGluc2lnaHQgcnVsZSB0aGF0IGNhbGN1bGF0ZXMgaW5zdGFuY2VzIGNvbnRyaWJ1dGluZyB0byBoaWdoIGxhdGVuY3kgaW4gdGhpcyBBWi4gT25seVxuICAgKiB1c2VmdWwgZm9yIHNlcnZlci1zaWRlIG1ldHJpY3Mgc2luY2UgdGhlIGNhbmFyeSBkb2Vzbid0IHJlY29yZCBpbnN0YW5jZSBpZCBtZXRyaWNzLlxuICAgKiBAcGFyYW0gc2NvcGVcbiAgICogQHBhcmFtIG1ldHJpY0RldGFpbHNcbiAgICogQHBhcmFtIGF2YWlsYWJpbGl0eVpvbmVJZFxuICAgKiBAcGFyYW0gbG9nR3JvdXBzXG4gICAqIEBwYXJhbSBuYW1lU3VmZml4XG4gICAqIEBwYXJhbSBjb3VudGVyXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlU2VydmVyU2lkZUluc3RhbmNlSGlnaExhdGVuY3lDb250cmlidXRvcnNJblRoaXNBWlJ1bGUoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBtZXRyaWNEZXRhaWxzOiBJT3BlcmF0aW9uTWV0cmljRGV0YWlscyxcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBydWxlRGV0YWlsczogSUNvbnRyaWJ1dG9ySW5zaWdodFJ1bGVEZXRhaWxzLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBuYW1lU3VmZml4Pzogc3RyaW5nLFxuICApOiBDZm5JbnNpZ2h0UnVsZSB7XG4gICAgbGV0IHJ1bGVCb2R5ID0gbmV3IEluc2lnaHRSdWxlQm9keSgpO1xuICAgIHJ1bGVCb2R5LmxvZ0dyb3VwTmFtZXMgPSBydWxlRGV0YWlscy5sb2dHcm91cHMubWFwKCh4KSA9PiB4LmxvZ0dyb3VwTmFtZSk7XG4gICAgcnVsZUJvZHkuYWdncmVnYXRlT24gPSAnQ291bnQnO1xuICAgIHJ1bGVCb2R5LmxvZ0Zvcm1hdCA9ICdKU09OJztcbiAgICBydWxlQm9keS5jb250cmlidXRpb24gPSB7XG4gICAgICBrZXlzOiBbcnVsZURldGFpbHMuaW5zdGFuY2VJZEpzb25QYXRoXSxcbiAgICAgIGZpbHRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIE1hdGNoOiBydWxlRGV0YWlscy5hdmFpbGFiaWxpdHlab25lSWRKc29uUGF0aCxcbiAgICAgICAgICBJbjogW2F2YWlsYWJpbGl0eVpvbmVJZF0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMub3BlcmF0aW9uTmFtZUpzb25QYXRoLFxuICAgICAgICAgIEluOiBbbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lXSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIE1hdGNoOiBydWxlRGV0YWlscy5zdWNjZXNzTGF0ZW5jeU1ldHJpY0pzb25QYXRoLFxuICAgICAgICAgIEdyZWF0ZXJUaGFuOiBtZXRyaWNEZXRhaWxzLnN1Y2Nlc3NBbGFybVRocmVzaG9sZCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSBhcyB1bmtub3duIGFzIElDb250cmlidXRpb25EZWZpbml0aW9uO1xuXG4gICAgcmV0dXJuIG5ldyBDZm5JbnNpZ2h0UnVsZShcbiAgICAgIHNjb3BlLFxuICAgICAgJ0FaJyArIGNvdW50ZXIgKyAnTGF0ZW5jeUNvbnRyaWJ1dG9yc1J1bGUnLFxuICAgICAge1xuICAgICAgICBydWxlTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICAgIGAtJHttZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0tcGVyLWluc3RhbmNlLWhpZ2gtbGF0ZW5jeWAgK1xuICAgICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICAgIHJ1bGVTdGF0ZTogJ0VOQUJMRUQnLFxuICAgICAgICBydWxlQm9keTogcnVsZUJvZHkudG9Kc29uKCksXG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQW4gYWxhcm0gdGhhdCBpbmRpY2F0ZXMgc29tZSBwZXJjZW50YWdlIG9mIHRoZSBpbnN0YW5jZXMgaW4gdGhpcyBBWiBhcmUgcHJvZHVjaW5nIGVycm9ycy4gT25seVxuICAgKiB1c2VmdWwgZm9yIHNlcnZlci1zaWRlIG1ldHJpY3Mgc2luY2UgdGhlIGNhbmFyeSBkb2Vzbid0IHJlY29yZCBpbnN0YW5jZSBpZCBtZXRyaWNzLlxuICAgKiBAcGFyYW0gc2NvcGVcbiAgICogQHBhcmFtIG1ldHJpY0RldGFpbHNcbiAgICogQHBhcmFtIGF2YWlsYWJpbGl0eVpvbmVJZFxuICAgKiBAcGFyYW0gbmFtZVN1ZmZpeFxuICAgKiBAcGFyYW0gY291bnRlclxuICAgKiBAcGFyYW0gb3V0bGllclRocmVzaG9sZFxuICAgKiBAcGFyYW0gaW5zdGFuY2VGYXVsdFJhdGVDb250cmlidXRvcnNJblRoaXNBWlxuICAgKiBAcGFyYW0gaW5zdGFuY2VzSGFuZGxpbmdSZXF1ZXN0c0luVGhpc0FaXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlU2VydmVyU2lkZVpvbmFsTW9yZVRoYW5PbmVJbnN0YW5jZVByb2R1Y2luZ0ZhdWx0c0FsYXJtKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgbWV0cmljRGV0YWlsczogSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIG91dGxpZXJUaHJlc2hvbGQ6IG51bWJlcixcbiAgICBpbnN0YW5jZUZhdWx0UmF0ZUNvbnRyaWJ1dG9yc0luVGhpc0FaOiBDZm5JbnNpZ2h0UnVsZSxcbiAgICBpbnN0YW5jZXNIYW5kbGluZ1JlcXVlc3RzSW5UaGlzQVo6IENmbkluc2lnaHRSdWxlLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBBbGFybShzY29wZSwgJ0FaJyArIGNvdW50ZXIgKyAnTW9yZVRoYW5PbmVBbGFybUZvckVycm9ycycsIHtcbiAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICtcbiAgICAgICAgYC0ke21ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpfS1tdWx0aXBsZS1pbnN0YW5jZXMtZmF1bHRzYCArXG4gICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICBtZXRyaWM6IG5ldyBNYXRoRXhwcmVzc2lvbih7XG4gICAgICAgIGV4cHJlc3Npb246IGBJTlNJR0hUX1JVTEVfTUVUUklDKFxcXCIke2luc3RhbmNlRmF1bHRSYXRlQ29udHJpYnV0b3JzSW5UaGlzQVouYXR0clJ1bGVOYW1lfVxcXCIsIFxcXCJVbmlxdWVDb250cmlidXRvcnNcXFwiKSAvIElOU0lHSFRfUlVMRV9NRVRSSUMoXFxcIiR7aW5zdGFuY2VzSGFuZGxpbmdSZXF1ZXN0c0luVGhpc0FaLmF0dHJSdWxlTmFtZX1cXFwiLCBcXFwiVW5pcXVlQ29udHJpYnV0b3JzXFxcIilgLFxuICAgICAgICBwZXJpb2Q6IG1ldHJpY0RldGFpbHMucGVyaW9kLFxuICAgICAgfSksXG4gICAgICBldmFsdWF0aW9uUGVyaW9kczogbWV0cmljRGV0YWlscy5ldmFsdWF0aW9uUGVyaW9kcyxcbiAgICAgIHRocmVzaG9sZDogb3V0bGllclRocmVzaG9sZCxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICBkYXRhcG9pbnRzVG9BbGFybTogbWV0cmljRGV0YWlscy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGFsYXJtIGluZGljYXRpbmcgbW9yZSB0aGFuIHNvbWUgcGVyY2VudGFnZSBvZiBpbnN0YW5jZXMgaW4gdGhpcyBBWlxuICAgKiBhcmUgY29udHJpYnV0aW5nIHRvIGhpZ2ggbGF0ZW5jeS4gT25seSB1c2VmdWwgZm9yIHNlcnZlci1zaWRlIG1ldHJpY3Mgc2luY2VcbiAgICogdGhlIGNhbmFyeSBkb2Vzbid0IHJlY29yZCBpbnN0YW5jZSBpZCBtZXRyaWNzLlxuICAgKiBAcGFyYW0gc2NvcGVcbiAgICogQHBhcmFtIG1ldHJpY0RldGFpbHNcbiAgICogQHBhcmFtIGF2YWlsYWJpbGl0eVpvbmVJZFxuICAgKiBAcGFyYW0gbmFtZVN1ZmZpeFxuICAgKiBAcGFyYW0gY291bnRlclxuICAgKiBAcGFyYW0gb3V0bGllclRocmVzaG9sZFxuICAgKiBAcGFyYW0gaW5zdGFuY2VIaWdoTGF0ZW5jeUNvbnRyaWJ1dG9yc0luVGhpc0FaXG4gICAqIEBwYXJhbSBpbnN0YW5jZXNIYW5kbGluZ1JlcXVlc3RzSW5UaGlzQVpcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVTZXJ2ZXJTaWRlWm9uYWxNb3JlVGhhbk9uZUluc3RhbmNlUHJvZHVjaW5nSGlnaExhdGVuY3lBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG1ldHJpY0RldGFpbHM6IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzLFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBvdXRsaWVyVGhyZXNob2xkOiBudW1iZXIsXG4gICAgaW5zdGFuY2VIaWdoTGF0ZW5jeUNvbnRyaWJ1dG9yc0luVGhpc0FaOiBDZm5JbnNpZ2h0UnVsZSxcbiAgICBpbnN0YW5jZXNIYW5kbGluZ1JlcXVlc3RzSW5UaGlzQVo6IENmbkluc2lnaHRSdWxlLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBBbGFybShzY29wZSwgJ0FaJyArIGNvdW50ZXIgKyAnTW9yZVRoYW5PbmVBbGFybUZvckhpZ2hMYXRlbmN5Jywge1xuICAgICAgYWxhcm1OYW1lOlxuICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgK1xuICAgICAgICBgLSR7bWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCl9LW11bHRpcGxlLWluc3RhbmNlcy1oaWdoLWxhdGVuY3lgICtcbiAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgIG1ldHJpYzogbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgICAgZXhwcmVzc2lvbjogYElOU0lHSFRfUlVMRV9NRVRSSUMoXFxcIiR7aW5zdGFuY2VIaWdoTGF0ZW5jeUNvbnRyaWJ1dG9yc0luVGhpc0FaLmF0dHJSdWxlTmFtZX1cXFwiLCBcXFwiVW5pcXVlQ29udHJpYnV0b3JzXFxcIikgLyBJTlNJR0hUX1JVTEVfTUVUUklDKFxcXCIke2luc3RhbmNlc0hhbmRsaW5nUmVxdWVzdHNJblRoaXNBWi5hdHRyUnVsZU5hbWV9XFxcIiwgXFxcIlVuaXF1ZUNvbnRyaWJ1dG9yc1xcXCIpYCxcbiAgICAgICAgcGVyaW9kOiBtZXRyaWNEZXRhaWxzLnBlcmlvZCxcbiAgICAgIH0pLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IG1ldHJpY0RldGFpbHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICB0aHJlc2hvbGQ6IG91dGxpZXJUaHJlc2hvbGQsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xELFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm06IG1ldHJpY0RldGFpbHMuZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBhbGFybSB0aGF0IGluZGljYXRlcyB0aGlzIEFaIGFzIGFuIG91dGxpZXJcbiAgICogZm9yIGF2YWlsYWJpbGl0eSBvciBsYXRlbmN5LiBUaGlzIGRvZXMgbm90IGVuc3VyZSB0aGF0IHRoZSBlcnJvcnNcbiAgICogb3IgbGF0ZW5jeSBvcmlnaW5hdGUgZnJvbSBtb3JlIHRoYW4gb25lIGluc3RhbmNlLlxuICAgKiBAcGFyYW0gc2NvcGVcbiAgICogQHBhcmFtIG9wZXJhdGlvblxuICAgKiBAcGFyYW0gYXZhaWxhYmlsaXR5Wm9uZUlkXG4gICAqIEBwYXJhbSBsb2dHcm91cHNcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHBhcmFtIGF6SXNPdXRsaWVyRm9yRmF1bHRzQWxhcm1cbiAgICogQHBhcmFtIGF2YWlsYWJpbGl0eUltcGFjdEFsYXJtXG4gICAqIEBwYXJhbSBheklzT3V0bGllckZvckxhdGVuY3lBbGFybVxuICAgKiBAcGFyYW0gbGF0ZW5jeUltcGFjdEFsYXJtXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlQ2FuYXJ5SXNvbGF0ZWRBWkltcGFjdEFsYXJtKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgb3BlcmF0aW9uTmFtZTogc3RyaW5nLFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIGNvdW50ZXI6IG51bWJlcixcbiAgICBheklzT3V0bGllckZvckZhdWx0c0FsYXJtOiBJQWxhcm0sXG4gICAgYXZhaWxhYmlsaXR5SW1wYWN0QWxhcm06IElBbGFybSxcbiAgICBheklzT3V0bGllckZvckxhdGVuY3lBbGFybTogSUFsYXJtLFxuICAgIGxhdGVuY3lJbXBhY3RBbGFybTogSUFsYXJtLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb3NpdGVBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgb3BlcmF0aW9uTmFtZSArICdBWicgKyBjb3VudGVyICsgJ0lzb2xhdGVkSW1wYWN0QWxhcm0nICsgbmFtZVN1ZmZpeCxcbiAgICAgIHtcbiAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgYC0ke29wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0taXNvbGF0ZWQtaW1wYWN0LWFsYXJtYCArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgYWxhcm1SdWxlOiBBbGFybVJ1bGUuYW55T2YoXG4gICAgICAgICAgQWxhcm1SdWxlLmFsbE9mKGF6SXNPdXRsaWVyRm9yRmF1bHRzQWxhcm0sIGF2YWlsYWJpbGl0eUltcGFjdEFsYXJtKSxcbiAgICAgICAgICBBbGFybVJ1bGUuYWxsT2YoYXpJc091dGxpZXJGb3JMYXRlbmN5QWxhcm0sIGxhdGVuY3lJbXBhY3RBbGFybSksXG4gICAgICAgICksXG4gICAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBzZXJ2ZXIgc2lkZSBhbGFybSB0byBpZGVudGlmeSBpc29sYXRlZCBzaW5nbGUgQVpcbiAgICogaW1wYWN0IG1lYW5pbmcgdGhhdCB0aGlzIG9uZSBBWiBpcyBhZmZlY3RlZCBhbmQgdGhlIG90aGVycyBhcmVuJ3RcbiAgICogQHBhcmFtIHNjb3BlXG4gICAqIEBwYXJhbSBvcGVyYXRpb25cbiAgICogQHBhcmFtIGF2YWlsYWJpbGl0eVpvbmVJZFxuICAgKiBAcGFyYW0gbmFtZVN1ZmZpeFxuICAgKiBAcGFyYW0gY291bnRlclxuICAgKiBAcGFyYW0gYXpJc091dGxpZXJGb3JGYXVsdHNBbGFybVxuICAgKiBAcGFyYW0gYXZhaWxhYmlsaXR5SW1wYWN0QWxhcm1cbiAgICogQHBhcmFtIG1vcmVUaGFuT25lSW5zdGFuY2VDb250cmlidXRpbmdUb0ZhdWx0c1xuICAgKiBAcGFyYW0gYXpJc091dGxpZXJGb3JMYXRlbmN5QWxhcm1cbiAgICogQHBhcmFtIGxhdGVuY3lJbXBhY3RBbGFybVxuICAgKiBAcGFyYW0gbW9yZVRoYW5PbmVJbnN0YW5jZUNvbnRyaWJ1dGluZ1RvTGF0ZW5jeVxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgc3RhdGljIGNyZWF0ZVNlcnZlclNpZGVJc29sYXRlZEFaSW1wYWN0QWxhcm0oXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBvcGVyYXRpb25OYW1lOiBzdHJpbmcsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIGF6SXNPdXRsaWVyRm9yRmF1bHRzQWxhcm06IElBbGFybSxcbiAgICBhdmFpbGFiaWxpdHlJbXBhY3RBbGFybTogSUFsYXJtLFxuICAgIG1vcmVUaGFuT25lSW5zdGFuY2VDb250cmlidXRpbmdUb0ZhdWx0czogSUFsYXJtLFxuICAgIGF6SXNPdXRsaWVyRm9yTGF0ZW5jeUFsYXJtOiBJQWxhcm0sXG4gICAgbGF0ZW5jeUltcGFjdEFsYXJtOiBJQWxhcm0sXG4gICAgbW9yZVRoYW5PbmVJbnN0YW5jZUNvbnRyaWJ1dGluZ1RvTGF0ZW5jeTogSUFsYXJtLFxuICAgIG5hbWVTdWZmaXg/OiBzdHJpbmcsXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb3NpdGVBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgb3BlcmF0aW9uTmFtZSArICdBWicgKyBjb3VudGVyICsgJ0lzb2xhdGVkSW1wYWN0QWxhcm0nICsgbmFtZVN1ZmZpeCxcbiAgICAgIHtcbiAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgYC0ke29wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0taXNvbGF0ZWQtaW1wYWN0LWFsYXJtYCArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgYWxhcm1SdWxlOiBBbGFybVJ1bGUuYW55T2YoXG4gICAgICAgICAgbW9yZVRoYW5PbmVJbnN0YW5jZUNvbnRyaWJ1dGluZ1RvRmF1bHRzID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgIG1vcmVUaGFuT25lSW5zdGFuY2VDb250cmlidXRpbmdUb0ZhdWx0cyA9PSBudWxsXG4gICAgICAgICAgICA/IEFsYXJtUnVsZS5hbGxPZihcbiAgICAgICAgICAgICAgYXpJc091dGxpZXJGb3JGYXVsdHNBbGFybSxcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5SW1wYWN0QWxhcm0sXG4gICAgICAgICAgICApXG4gICAgICAgICAgICA6IEFsYXJtUnVsZS5hbGxPZihcbiAgICAgICAgICAgICAgYXpJc091dGxpZXJGb3JGYXVsdHNBbGFybSxcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5SW1wYWN0QWxhcm0sXG4gICAgICAgICAgICAgIG1vcmVUaGFuT25lSW5zdGFuY2VDb250cmlidXRpbmdUb0ZhdWx0cyxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgbW9yZVRoYW5PbmVJbnN0YW5jZUNvbnRyaWJ1dGluZ1RvTGF0ZW5jeSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICBtb3JlVGhhbk9uZUluc3RhbmNlQ29udHJpYnV0aW5nVG9MYXRlbmN5ID09IG51bGxcbiAgICAgICAgICAgID8gQWxhcm1SdWxlLmFsbE9mKGF6SXNPdXRsaWVyRm9yTGF0ZW5jeUFsYXJtLCBsYXRlbmN5SW1wYWN0QWxhcm0pXG4gICAgICAgICAgICA6IEFsYXJtUnVsZS5hbGxPZihcbiAgICAgICAgICAgICAgYXpJc091dGxpZXJGb3JMYXRlbmN5QWxhcm0sXG4gICAgICAgICAgICAgIGxhdGVuY3lJbXBhY3RBbGFybSxcbiAgICAgICAgICAgICAgbW9yZVRoYW5PbmVJbnN0YW5jZUNvbnRyaWJ1dGluZ1RvTGF0ZW5jeSxcbiAgICAgICAgICAgICksXG4gICAgICAgICksXG4gICAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGFsYXJtIHRoYXQgZmlyZXMgaWYgZWl0aGVyIHRoZSBjYW5hcnkgb3IgdGhlXG4gICAqIHNlcnZlciBzaWRlIGRldGVjdCBzaW5nbGUgQVogaXNvbGF0ZWQgaW1wYWN0XG4gICAqIEBwYXJhbSBzY29wZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9uXG4gICAqIEBwYXJhbSBhdmFpbGFiaWxpdHlab25lSWRcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHBhcmFtIHNlcnZlclNpZGVBbGFybVxuICAgKiBAcGFyYW0gY2FuYXJ5QWxhcm1cbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVBZ2dyZWdhdGVJc29sYXRlZEFaSW1wYWN0QWxhcm0oXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBvcGVyYXRpb246IElPcGVyYXRpb24sXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgY291bnRlcjogbnVtYmVyLFxuICAgIHNlcnZlclNpZGVBbGFybTogSUFsYXJtLFxuICAgIGNhbmFyeUFsYXJtOiBJQWxhcm0sXG4gICk6IElBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb3NpdGVBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAgb3BlcmF0aW9uLm9wZXJhdGlvbk5hbWUgKyAnQVonICsgY291bnRlciArICdBZ2dyZWdhdGVJc29sYXRlZEltcGFjdEFsYXJtJyxcbiAgICAgIHtcbiAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgYC0ke29wZXJhdGlvbi5vcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCl9LWFnZ3JlZ2F0ZS1pc29sYXRlZC1pbXBhY3QtYWxhcm1gLFxuICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZihzZXJ2ZXJTaWRlQWxhcm0sIGNhbmFyeUFsYXJtKSxcbiAgICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSByZWdpb25hbCBhdmFpbGFiaWxpdHkgYWxhcm0gZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHBhcmFtIHNjb3BlXG4gICAqIEBwYXJhbSBtZXRyaWNEZXRhaWxzXG4gICAqIEBwYXJhbSBuYW1lU3VmZml4XG4gICAqIEBwYXJhbSBjb3VudGVyXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlUmVnaW9uYWxBdmFpbGFiaWxpdHlBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG1ldHJpY0RldGFpbHM6IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzLFxuICAgIG5hbWVTdWZmaXg6IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICByZXR1cm4gbmV3IEFsYXJtKFxuICAgICAgc2NvcGUsXG4gICAgICBtZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUgKyAnUmVnaW9uYWxBdmFpbGFiaWxpdHlBbGFybScsXG4gICAgICB7XG4gICAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgICBGbi5yZWYoJ0FXUzo6UmVnaW9uJykgK1xuICAgICAgICAgICctJyArXG4gICAgICAgICAgbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lLnRvTG93ZXJDYXNlKCkgK1xuICAgICAgICAgICctc3VjY2Vzcy1yYXRlJyArXG4gICAgICAgICAgbmFtZVN1ZmZpeCxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IG1ldHJpY0RldGFpbHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgIGRhdGFwb2ludHNUb0FsYXJtOiBtZXRyaWNEZXRhaWxzLmRhdGFwb2ludHNUb0FsYXJtLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICB0aHJlc2hvbGQ6IG1ldHJpY0RldGFpbHMuc3VjY2Vzc0FsYXJtVGhyZXNob2xkLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IFRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgICAgICBtZXRyaWM6IFJlZ2lvbmFsQXZhaWxhYmlsaXR5TWV0cmljcy5jcmVhdGVSZWdpb25hbEF2YWlsYWJpbGl0eU1ldHJpYyh7XG4gICAgICAgICAgbGFiZWw6IEZuLnJlZignQVdTOjpSZWdpb24nKSArICcgYXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICBtZXRyaWNEZXRhaWxzOiBtZXRyaWNEZXRhaWxzLFxuICAgICAgICAgIG1ldHJpY1R5cGU6IEF2YWlsYWJpbGl0eU1ldHJpY1R5cGUuU1VDQ0VTU19SQVRFLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcmVnaW9uYWwgbGF0ZW5jeSBhbGFybSBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcGFyYW0gc2NvcGVcbiAgICogQHBhcmFtIG1ldHJpY0RldGFpbHNcbiAgICogQHBhcmFtIG5hbWVTdWZmaXhcbiAgICogQHBhcmFtIGNvdW50ZXJcbiAgICogQHJldHVybnNcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVSZWdpb25hbExhdGVuY3lBbGFybShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIG1ldHJpY0RldGFpbHM6IElPcGVyYXRpb25NZXRyaWNEZXRhaWxzLFxuICAgIG5hbWVTdWZmaXg6IHN0cmluZyxcbiAgKTogSUFsYXJtIHtcbiAgICByZXR1cm4gbmV3IEFsYXJtKFxuICAgICAgc2NvcGUsXG4gICAgICBtZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUgKyAnUmVnaW9uYWxMYXRlbmN5QWxhcm0nLFxuICAgICAge1xuICAgICAgICBhbGFybU5hbWU6XG4gICAgICAgICAgRm4ucmVmKCdBV1M6OlJlZ2lvbicpICtcbiAgICAgICAgICAnLScgK1xuICAgICAgICAgIG1ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpICtcbiAgICAgICAgICAnLXN1Y2Nlc3MtbGF0ZW5jeScgK1xuICAgICAgICAgIG5hbWVTdWZmaXgsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBtZXRyaWNEZXRhaWxzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogbWV0cmljRGV0YWlscy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgICAgdGhyZXNob2xkOiBtZXRyaWNEZXRhaWxzLnN1Y2Nlc3NBbGFybVRocmVzaG9sZCxcbiAgICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICAgICAgbWV0cmljOiBSZWdpb25hbExhdGVuY3lNZXRyaWNzLmNyZWF0ZVJlZ2lvbmFsQXZlcmFnZUxhdGVuY3lNZXRyaWMoe1xuICAgICAgICAgIGxhYmVsOlxuICAgICAgICAgICAgRm4ucmVmKCdBV1M6OlJlZ2lvbicpICtcbiAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICBtZXRyaWNEZXRhaWxzLmFsYXJtU3RhdGlzdGljICtcbiAgICAgICAgICAgICcgbGF0ZW5jeScsXG4gICAgICAgICAgbWV0cmljRGV0YWlsczogbWV0cmljRGV0YWlscyxcbiAgICAgICAgICBtZXRyaWNUeXBlOiBMYXRlbmN5TWV0cmljVHlwZS5TVUNDRVNTX0xBVEVOQ1ksXG4gICAgICAgICAgc3RhdGlzdGljOiBtZXRyaWNEZXRhaWxzLmFsYXJtU3RhdGlzdGljLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGNvbXBvc2l0ZSBhbGFybSBjb21iaW5pbmcgbGF0ZW5jeSBhbmQgYXZhaWxhYmlsaXR5IGFsYXJtcyBmb3IgdGhpcyBvcGVyYXRpb24gaW4gdGhlIHJlZ2lvblxuICAgKiBhcyBtZWFzdXJlZCBmcm9tIGVpdGhlciB0aGUgc2VydmVyIHNpZGUgb3IgY2FuYXJ5XG4gICAqIEBwYXJhbSBzY29wZVxuICAgKiBAcGFyYW0gb3BlcmF0aW9uXG4gICAqIEBwYXJhbSBuYW1lU3VmZml4XG4gICAqIEBwYXJhbSByZWdpb25hbEF2YWlsYWJpbGl0eUFsYXJtXG4gICAqIEBwYXJhbSByZWdpb25hbExhdGVuY3lBbGFybVxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgc3RhdGljIGNyZWF0ZVJlZ2lvbmFsQ3VzdG9tZXJFeHBlcmllbmNlQWxhcm0oXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBvcGVyYXRpb25OYW1lOiBzdHJpbmcsXG4gICAgbmFtZVN1ZmZpeDogc3RyaW5nLFxuICAgIHJlZ2lvbmFsQXZhaWxhYmlsaXR5QWxhcm06IElBbGFybSxcbiAgICByZWdpb25hbExhdGVuY3lBbGFybTogSUFsYXJtLFxuICApOiBJQWxhcm0ge1xuICAgIHJldHVybiBuZXcgQ29tcG9zaXRlQWxhcm0oXG4gICAgICBzY29wZSxcbiAgICAgIG9wZXJhdGlvbk5hbWUgKyAnUmVnaW9uYWxDdXN0b21lckV4cGVyaWVuY2VBbGFybScsXG4gICAgICB7XG4gICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTpcbiAgICAgICAgICBGbi5yZWYoJ0FXUzo6UmVnaW9uJykgK1xuICAgICAgICAgICctJyArXG4gICAgICAgICAgb3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpICtcbiAgICAgICAgICAnLWN1c3RvbWVyLWV4cGVyaWVuY2UtaW1hY3QnICtcbiAgICAgICAgICBuYW1lU3VmZml4LFxuICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZihcbiAgICAgICAgICByZWdpb25hbEF2YWlsYWJpbGl0eUFsYXJtLFxuICAgICAgICAgIHJlZ2lvbmFsTGF0ZW5jeUFsYXJtLFxuICAgICAgICApLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZVJlZ2lvbmFsSW5zdGFuY2VDb250cmlidXRvcnNUb0hpZ2hMYXRlbmN5KFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgbWV0cmljRGV0YWlsczogSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMsXG4gICAgcnVsZURldGFpbHM6IElDb250cmlidXRvckluc2lnaHRSdWxlRGV0YWlscyxcbiAgKTogQ2ZuSW5zaWdodFJ1bGUge1xuICAgIGxldCBydWxlQm9keSA9IG5ldyBJbnNpZ2h0UnVsZUJvZHkoKTtcbiAgICBydWxlQm9keS5sb2dHcm91cE5hbWVzID0gcnVsZURldGFpbHMubG9nR3JvdXBzLm1hcCgoeCkgPT4geC5sb2dHcm91cE5hbWUpO1xuICAgIHJ1bGVCb2R5LmFnZ3JlZ2F0ZU9uID0gJ0NvdW50JztcbiAgICBydWxlQm9keS5sb2dGb3JtYXQgPSAnSlNPTic7XG4gICAgcnVsZUJvZHkuY29udHJpYnV0aW9uID0ge1xuICAgICAga2V5czogW3J1bGVEZXRhaWxzLmluc3RhbmNlSWRKc29uUGF0aF0sXG4gICAgICBmaWx0ZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMuc3VjY2Vzc0xhdGVuY3lNZXRyaWNKc29uUGF0aCxcbiAgICAgICAgICBHcmVhdGVyVGhhbjogbWV0cmljRGV0YWlscy5zdWNjZXNzQWxhcm1UaHJlc2hvbGQsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMub3BlcmF0aW9uTmFtZUpzb25QYXRoLFxuICAgICAgICAgIEluOiBbbWV0cmljRGV0YWlscy5vcGVyYXRpb25OYW1lXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSBhcyB1bmtub3duIGFzIElDb250cmlidXRpb25EZWZpbml0aW9uO1xuXG4gICAgcmV0dXJuIG5ldyBDZm5JbnNpZ2h0UnVsZShzY29wZSwgJ1JlZ2lvblBlckluc3RhbmNlSGlnaExhdGVuY3lSdWxlJywge1xuICAgICAgcnVsZU5hbWU6XG4gICAgICAgIEZuLnJlZignQVdTOjpSZWdpb24nKSArXG4gICAgICAgIGAtJHttZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWUudG9Mb3dlckNhc2UoKX0tcGVyLWluc3RhbmNlLWhpZ2gtbGF0ZW5jeS1zZXJ2ZXJgLFxuICAgICAgcnVsZVN0YXRlOiAnRU5BQkxFRCcsXG4gICAgICBydWxlQm9keTogcnVsZUJvZHkudG9Kc29uKCksXG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlUmVnaW9uYWxJbnN0YW5jZUNvbnRyaWJ1dG9yc1RvRmF1bHRzKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgbWV0cmljRGV0YWlsczogSU9wZXJhdGlvbk1ldHJpY0RldGFpbHMsXG4gICAgcnVsZURldGFpbHM6IElDb250cmlidXRvckluc2lnaHRSdWxlRGV0YWlscyxcbiAgKTogQ2ZuSW5zaWdodFJ1bGUge1xuICAgIGxldCBydWxlQm9keSA9IG5ldyBJbnNpZ2h0UnVsZUJvZHkoKTtcbiAgICBydWxlQm9keS5sb2dHcm91cE5hbWVzID0gcnVsZURldGFpbHMubG9nR3JvdXBzLm1hcCgoeCkgPT4geC5sb2dHcm91cE5hbWUpO1xuICAgIHJ1bGVCb2R5LmFnZ3JlZ2F0ZU9uID0gJ0NvdW50JztcbiAgICBydWxlQm9keS5sb2dGb3JtYXQgPSAnSlNPTic7XG4gICAgcnVsZUJvZHkuY29udHJpYnV0aW9uID0ge1xuICAgICAga2V5czogW3J1bGVEZXRhaWxzLmluc3RhbmNlSWRKc29uUGF0aF0sXG4gICAgICBmaWx0ZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBNYXRjaDogcnVsZURldGFpbHMuZmF1bHRNZXRyaWNKc29uUGF0aCxcbiAgICAgICAgICBHcmVhdGVyVGhhbjogMCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIE1hdGNoOiBydWxlRGV0YWlscy5vcGVyYXRpb25OYW1lSnNvblBhdGgsXG4gICAgICAgICAgSW46IFttZXRyaWNEZXRhaWxzLm9wZXJhdGlvbk5hbWVdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9IGFzIHVua25vd24gYXMgSUNvbnRyaWJ1dGlvbkRlZmluaXRpb247XG5cbiAgICByZXR1cm4gbmV3IENmbkluc2lnaHRSdWxlKHNjb3BlLCAnUmVnaW9uUGVySW5zdGFuY2VFcnJvclJ1bGUnLCB7XG4gICAgICBydWxlTmFtZTpcbiAgICAgICAgRm4ucmVmKCdBV1M6OlJlZ2lvbicpICtcbiAgICAgICAgYC0ke21ldHJpY0RldGFpbHMub3BlcmF0aW9uTmFtZS50b0xvd2VyQ2FzZSgpfS1wZXItaW5zdGFuY2UtZmF1bHRzLXNlcnZlcmAsXG4gICAgICBydWxlU3RhdGU6ICdFTkFCTEVEJyxcbiAgICAgIHJ1bGVCb2R5OiBydWxlQm9keS50b0pzb24oKSxcbiAgICB9KTtcbiAgfVxufVxuIl19
|