@cdklabs/multi-az-observability 0.0.1-alpha.3 → 0.0.1-alpha.31

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