@cdklabs/multi-az-observability 0.0.0-alpha.0

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