@cdklabs/multi-az-observability 0.0.1-alpha.6 → 0.0.1-alpha.60

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 (188) hide show
  1. package/.jsii +2826 -1008
  2. package/.jsii.tabl.json +1 -0
  3. package/API.md +5406 -1585
  4. package/README.md +176 -152
  5. package/lib/alarmsandrules/AvailabilityAndLatencyAlarmsAndRules.d.ts +18 -14
  6. package/lib/alarmsandrules/AvailabilityAndLatencyAlarmsAndRules.js +98 -60
  7. package/lib/alarmsandrules/BaseOperationRegionalAlarmsAndRules.d.ts +3 -3
  8. package/lib/alarmsandrules/BaseOperationRegionalAlarmsAndRules.js +2 -2
  9. package/lib/alarmsandrules/BaseOperationZonalAlarmsAndRules.d.ts +6 -15
  10. package/lib/alarmsandrules/BaseOperationZonalAlarmsAndRules.js +2 -10
  11. package/lib/alarmsandrules/CanaryOperationZonalAlarmsAndRules.d.ts +11 -3
  12. package/lib/alarmsandrules/CanaryOperationZonalAlarmsAndRules.js +29 -13
  13. package/lib/alarmsandrules/IBaseOperationZonalAlarmsAndRules.d.ts +0 -8
  14. package/lib/alarmsandrules/IBaseOperationZonalAlarmsAndRules.js +1 -1
  15. package/lib/alarmsandrules/IOperationAlarmsAndRules.d.ts +26 -23
  16. package/lib/alarmsandrules/IOperationAlarmsAndRules.js +1 -1
  17. package/lib/alarmsandrules/IServerSideOperationRegionalAlarmsAndRules.js +1 -1
  18. package/lib/alarmsandrules/IServiceAlarmsAndRules.d.ts +19 -15
  19. package/lib/alarmsandrules/IServiceAlarmsAndRules.js +1 -1
  20. package/lib/alarmsandrules/OperationAlarmsAndRules.d.ts +21 -18
  21. package/lib/alarmsandrules/OperationAlarmsAndRules.js +60 -72
  22. package/lib/alarmsandrules/ServerSideOperationRegionalAlarmsAndRules.d.ts +5 -5
  23. package/lib/alarmsandrules/ServerSideOperationRegionalAlarmsAndRules.js +2 -3
  24. package/lib/alarmsandrules/ServerSideOperationZonalAlarmsAndRules.d.ts +21 -13
  25. package/lib/alarmsandrules/ServerSideOperationZonalAlarmsAndRules.js +48 -29
  26. package/lib/alarmsandrules/ServiceAlarmsAndRules.d.ts +19 -15
  27. package/lib/alarmsandrules/ServiceAlarmsAndRules.js +34 -136
  28. package/lib/alarmsandrules/props/BaseOperationRegionalAlarmsAndRulesProps.d.ts +4 -3
  29. package/lib/alarmsandrules/props/BaseOperationRegionalAlarmsAndRulesProps.js +1 -1
  30. package/lib/alarmsandrules/props/BaseOperationZonalAlarmsAndRulesProps.d.ts +6 -44
  31. package/lib/alarmsandrules/props/BaseOperationZonalAlarmsAndRulesProps.js +1 -1
  32. package/lib/alarmsandrules/props/OperationAlarmsAndRulesProps.d.ts +39 -7
  33. package/lib/alarmsandrules/props/OperationAlarmsAndRulesProps.js +1 -1
  34. package/lib/azmapper/AvailabilityZoneMapper.js +8 -9
  35. package/lib/basic_observability/BasicServiceDashboard.d.ts +0 -3
  36. package/lib/basic_observability/BasicServiceDashboard.js +24 -112
  37. package/lib/basic_observability/BasicServiceMultiAZObservability.d.ts +8 -9
  38. package/lib/basic_observability/BasicServiceMultiAZObservability.js +97 -349
  39. package/lib/basic_observability/props/ApplicationLoadBalancerDetectionProps.d.ts +66 -0
  40. package/lib/basic_observability/props/ApplicationLoadBalancerDetectionProps.js +3 -0
  41. package/lib/basic_observability/props/BasicServiceDashboardProps.d.ts +27 -13
  42. package/lib/basic_observability/props/BasicServiceDashboardProps.js +1 -1
  43. package/lib/basic_observability/props/BasicServiceMultiAZObservabilityProps.d.ts +10 -44
  44. package/lib/basic_observability/props/BasicServiceMultiAZObservabilityProps.js +1 -1
  45. package/lib/basic_observability/props/NatGatewayDetectionProps.d.ts +31 -0
  46. package/lib/basic_observability/props/NatGatewayDetectionProps.js +3 -0
  47. package/lib/canaries/CanaryFunction.js +14 -13
  48. package/lib/canaries/CanaryTest.js +4 -4
  49. package/lib/canaries/src/canary.zip +0 -0
  50. package/lib/dashboards/ContributorInsightsWidget.d.ts +1 -1
  51. package/lib/dashboards/ContributorInsightsWidget.js +13 -17
  52. package/lib/dashboards/OperationAvailabilityAndLatencyDashboard.d.ts +2 -6
  53. package/lib/dashboards/OperationAvailabilityAndLatencyDashboard.js +436 -510
  54. package/lib/dashboards/ServiceAvailabilityAndLatencyDashboard.d.ts +2 -10
  55. package/lib/dashboards/ServiceAvailabilityAndLatencyDashboard.js +420 -416
  56. package/lib/dashboards/props/OperationAvailabilityAndLatencyDashboardProps.d.ts +3 -66
  57. package/lib/dashboards/props/OperationAvailabilityAndLatencyDashboardProps.js +1 -1
  58. package/lib/dashboards/props/OperationAvailabilityWidgetProps.d.ts +7 -2
  59. package/lib/dashboards/props/OperationAvailabilityWidgetProps.js +1 -1
  60. package/lib/dashboards/props/OperationLatencyWidgetProps.d.ts +7 -2
  61. package/lib/dashboards/props/OperationLatencyWidgetProps.js +1 -1
  62. package/lib/dashboards/props/ServiceAvailabilityAndLatencyDashboardProps.d.ts +8 -8
  63. package/lib/dashboards/props/ServiceAvailabilityAndLatencyDashboardProps.js +1 -1
  64. package/lib/index.d.ts +56 -25
  65. package/lib/index.js +37 -19
  66. package/lib/metrics/ApplicationLoadBalancerMetrics.d.ts +79 -2
  67. package/lib/metrics/ApplicationLoadBalancerMetrics.js +883 -26
  68. package/lib/metrics/AvailabilityAndLatencyMetrics.d.ts +23 -0
  69. package/lib/metrics/AvailabilityAndLatencyMetrics.js +125 -31
  70. package/lib/metrics/NatGatewayMetrics.d.ts +113 -0
  71. package/lib/metrics/NatGatewayMetrics.js +357 -0
  72. package/lib/metrics/RegionalAvailabilityMetrics.js +9 -10
  73. package/lib/metrics/RegionalLatencyMetrics.d.ts +1 -1
  74. package/lib/metrics/RegionalLatencyMetrics.js +27 -20
  75. package/lib/metrics/ZonalAvailabilityMetrics.d.ts +2 -8
  76. package/lib/metrics/ZonalAvailabilityMetrics.js +13 -28
  77. package/lib/metrics/ZonalLatencyMetrics.d.ts +2 -1
  78. package/lib/metrics/ZonalLatencyMetrics.js +33 -23
  79. package/lib/metrics/props/AvailabilityAndLatencyMetricProps.d.ts +4 -0
  80. package/lib/metrics/props/AvailabilityAndLatencyMetricProps.js +1 -1
  81. package/lib/metrics/props/LatencyMetricProps.d.ts +6 -0
  82. package/lib/metrics/props/LatencyMetricProps.js +1 -1
  83. package/lib/metrics/props/ZonalAvailabilityMetricProps.d.ts +4 -0
  84. package/lib/metrics/props/ZonalAvailabilityMetricProps.js +1 -1
  85. package/lib/metrics/props/ZonalLatencyMetricProps.d.ts +4 -0
  86. package/lib/metrics/props/ZonalLatencyMetricProps.js +1 -1
  87. package/lib/monitoring/src/monitoring-layer.zip +0 -0
  88. package/lib/outlier-detection/ApplicationLoadBalancerAvailabilityOutlierAlgorithm.d.ts +10 -0
  89. package/lib/outlier-detection/ApplicationLoadBalancerAvailabilityOutlierAlgorithm.js +15 -0
  90. package/lib/{basic_observability/props/ApplicationLoadBalancerLatencyOutlierCalculation.d.ts → outlier-detection/ApplicationLoadBalancerLatencyOutlierAlgorithm.d.ts} +1 -1
  91. package/lib/outlier-detection/ApplicationLoadBalancerLatencyOutlierAlgorithm.js +23 -0
  92. package/lib/outlier-detection/LatencyOutlierMetricAggregation.d.ts +22 -0
  93. package/lib/outlier-detection/LatencyOutlierMetricAggregation.js +27 -0
  94. package/lib/outlier-detection/OutlierDetectionFunction.js +7 -6
  95. package/lib/outlier-detection/PacketLossOutlierAlgorithm.d.ts +10 -0
  96. package/lib/outlier-detection/PacketLossOutlierAlgorithm.js +15 -0
  97. package/lib/outlier-detection/src/outlier-detection.zip +0 -0
  98. package/lib/outlier-detection/src/scipy-layer.zip +0 -0
  99. package/lib/services/CanaryMetrics.d.ts +4 -3
  100. package/lib/services/CanaryMetrics.js +3 -4
  101. package/lib/services/CanaryTestAvailabilityMetricsOverride.d.ts +21 -0
  102. package/lib/services/CanaryTestAvailabilityMetricsOverride.js +23 -0
  103. package/lib/services/CanaryTestLatencyMetricsOverride.d.ts +15 -0
  104. package/lib/services/CanaryTestLatencyMetricsOverride.js +20 -0
  105. package/lib/services/CanaryTestMetricsOverride.d.ts +1 -13
  106. package/lib/services/CanaryTestMetricsOverride.js +2 -4
  107. package/lib/services/ContributorInsightRuleDetails.js +1 -1
  108. package/lib/services/ICanaryMetrics.d.ts +4 -3
  109. package/lib/services/ICanaryMetrics.js +1 -1
  110. package/lib/services/ICanaryTestAvailabilityMetricsOverride.d.ts +23 -0
  111. package/lib/services/ICanaryTestAvailabilityMetricsOverride.js +3 -0
  112. package/lib/services/ICanaryTestLatencyMetricsOverride.d.ts +13 -0
  113. package/lib/services/ICanaryTestLatencyMetricsOverride.js +3 -0
  114. package/lib/services/ICanaryTestMetricsOverride.d.ts +0 -12
  115. package/lib/services/ICanaryTestMetricsOverride.js +1 -1
  116. package/lib/services/IInstrumentedServiceMultiAZObservability.d.ts +13 -3
  117. package/lib/services/IInstrumentedServiceMultiAZObservability.js +1 -1
  118. package/lib/services/IOperation.d.ts +8 -6
  119. package/lib/services/IOperation.js +1 -1
  120. package/lib/services/IOperationAvailabilityMetricDetails.d.ts +18 -0
  121. package/lib/services/IOperationAvailabilityMetricDetails.js +3 -0
  122. package/lib/services/IOperationLatencyMetricDetails.d.ts +12 -0
  123. package/lib/services/IOperationLatencyMetricDetails.js +3 -0
  124. package/lib/services/IOperationMetricDetails.d.ts +0 -12
  125. package/lib/services/IOperationMetricDetails.js +1 -1
  126. package/lib/services/IService.d.ts +18 -4
  127. package/lib/services/IService.js +1 -1
  128. package/lib/services/IServiceAvailabilityMetricDetails.d.ts +18 -0
  129. package/lib/services/IServiceAvailabilityMetricDetails.js +3 -0
  130. package/lib/services/IServiceLatencyMetricDetails.d.ts +12 -0
  131. package/lib/services/IServiceLatencyMetricDetails.js +3 -0
  132. package/lib/services/IServiceMetricDetails.d.ts +0 -12
  133. package/lib/services/IServiceMetricDetails.js +1 -1
  134. package/lib/services/InstrumentedServiceMultiAZObservability.d.ts +15 -3
  135. package/lib/services/InstrumentedServiceMultiAZObservability.js +252 -228
  136. package/lib/services/Operation.d.ts +8 -6
  137. package/lib/services/Operation.js +4 -3
  138. package/lib/services/OperationAvailabilityMetricDetails.d.ts +22 -0
  139. package/lib/services/OperationAvailabilityMetricDetails.js +24 -0
  140. package/lib/services/OperationLatencyMetricDetails.d.ts +16 -0
  141. package/lib/services/OperationLatencyMetricDetails.js +21 -0
  142. package/lib/services/OperationMetricDetails.d.ts +1 -13
  143. package/lib/services/OperationMetricDetails.js +2 -8
  144. package/lib/services/Service.d.ts +18 -4
  145. package/lib/services/Service.js +4 -2
  146. package/lib/services/ServiceAvailabilityMetricDetails.d.ts +21 -0
  147. package/lib/services/ServiceAvailabilityMetricDetails.js +20 -0
  148. package/lib/services/ServiceLatencyMetricDetails.d.ts +15 -0
  149. package/lib/services/ServiceLatencyMetricDetails.js +19 -0
  150. package/lib/services/ServiceMetricDetails.d.ts +1 -13
  151. package/lib/services/ServiceMetricDetails.js +2 -4
  152. package/lib/services/props/CanaryMetricProps.d.ts +4 -3
  153. package/lib/services/props/CanaryMetricProps.js +1 -1
  154. package/lib/services/props/CanaryTestAvailabilityMetricsOverrideProps.d.ts +22 -0
  155. package/lib/services/props/CanaryTestAvailabilityMetricsOverrideProps.js +3 -0
  156. package/lib/services/props/CanaryTestLatencyMetricsOverrideProps.d.ts +14 -0
  157. package/lib/services/props/CanaryTestLatencyMetricsOverrideProps.js +3 -0
  158. package/lib/services/props/CanaryTestMetricsOverrideProps.d.ts +0 -16
  159. package/lib/services/props/CanaryTestMetricsOverrideProps.js +1 -1
  160. package/lib/services/props/InstrumentedServiceMultiAZObservabilityProps.d.ts +50 -5
  161. package/lib/services/props/InstrumentedServiceMultiAZObservabilityProps.js +1 -1
  162. package/lib/services/props/MetricDimensions.js +1 -1
  163. package/lib/services/props/OperationAvailabilityMetricDetailsProps.d.ts +22 -0
  164. package/lib/services/props/OperationAvailabilityMetricDetailsProps.js +3 -0
  165. package/lib/services/props/OperationLatencyMetricDetailsProps.d.ts +14 -0
  166. package/lib/services/props/OperationLatencyMetricDetailsProps.js +3 -0
  167. package/lib/services/props/OperationMetricDetailsProps.d.ts +0 -16
  168. package/lib/services/props/OperationMetricDetailsProps.js +1 -1
  169. package/lib/services/props/OperationProps.d.ts +4 -3
  170. package/lib/services/props/OperationProps.js +1 -1
  171. package/lib/services/props/ServiceAvailabilityMetricDetailsProps.d.ts +18 -0
  172. package/lib/services/props/ServiceAvailabilityMetricDetailsProps.js +3 -0
  173. package/lib/services/props/ServiceLatencyMetricDetailsProps.d.ts +12 -0
  174. package/lib/services/props/ServiceLatencyMetricDetailsProps.js +3 -0
  175. package/lib/services/props/ServiceMetricDetailsProps.d.ts +0 -12
  176. package/lib/services/props/ServiceMetricDetailsProps.js +1 -1
  177. package/lib/services/props/ServiceProps.d.ts +18 -4
  178. package/lib/services/props/ServiceProps.js +1 -1
  179. package/lib/utilities/MetricsHelper.d.ts +17 -9
  180. package/lib/utilities/MetricsHelper.js +34 -10
  181. package/lib/utilities/MinimumUnhealthyTargets.d.ts +25 -0
  182. package/lib/utilities/MinimumUnhealthyTargets.js +3 -0
  183. package/package.json +14 -14
  184. package/rosetta/default.ts-fixture +72 -0
  185. package/rosetta/service.ts-fixture +144 -0
  186. package/lib/basic_observability/props/ApplicationLoadBalancerLatencyOutlierCalculation.js +0 -23
  187. package/lib/services/IBasicServiceMultiAZObservability.d.ts +0 -45
  188. package/lib/services/IBasicServiceMultiAZObservability.js +0 -3
@@ -11,9 +11,11 @@ const constructs_1 = require("constructs");
11
11
  const AvailabilityZoneMapper_1 = require("../azmapper/AvailabilityZoneMapper");
12
12
  const BasicServiceDashboard_1 = require("./BasicServiceDashboard");
13
13
  const ApplicationLoadBalancerMetrics_1 = require("../metrics/ApplicationLoadBalancerMetrics");
14
- const AvailabilityMetricType_1 = require("../utilities/AvailabilityMetricType");
15
14
  const MetricsHelper_1 = require("../utilities/MetricsHelper");
16
- const ApplicationLoadBalancerLatencyOutlierCalculation_1 = require("./props/ApplicationLoadBalancerLatencyOutlierCalculation");
15
+ const ApplicationLoadBalancerLatencyOutlierAlgorithm_1 = require("../outlier-detection/ApplicationLoadBalancerLatencyOutlierAlgorithm");
16
+ const NatGatewayMetrics_1 = require("../metrics/NatGatewayMetrics");
17
+ const ApplicationLoadBalancerAvailabilityOutlierAlgorithm_1 = require("../outlier-detection/ApplicationLoadBalancerAvailabilityOutlierAlgorithm");
18
+ const PacketLossOutlierAlgorithm_1 = require("../outlier-detection/PacketLossOutlierAlgorithm");
17
19
  /**
18
20
  * Basic observability for a service using metrics from
19
21
  * ALBs and NAT Gateways
@@ -21,10 +23,13 @@ const ApplicationLoadBalancerLatencyOutlierCalculation_1 = require("./props/Appl
21
23
  class BasicServiceMultiAZObservability extends constructs_1.Construct {
22
24
  constructor(scope, id, props) {
23
25
  super(scope, id);
26
+ if (!(props.applicationLoadBalancerProps) && !(props.natGatewayProps)) {
27
+ throw new Error("You must define either ALBs or NAT Gateways for this service in order to create a dashboard.");
28
+ }
24
29
  // Initialize class properties
25
30
  this.serviceName = props.serviceName;
26
- this.applicationLoadBalancers = props.applicationLoadBalancers;
27
- this.natGateways = props.natGateways;
31
+ this.applicationLoadBalancers = props.applicationLoadBalancerProps?.albTargetGroupMap.map(entry => entry.applicationLoadBalancer);
32
+ this.natGateways = props.natGatewayProps?.natGateways;
28
33
  this.aggregateZonalIsolatedImpactAlarms = {};
29
34
  this.albZonalIsolatedImpactAlarms = {};
30
35
  this.natGWZonalIsolatedImpactAlarms = {};
@@ -32,26 +37,25 @@ class BasicServiceMultiAZObservability extends constructs_1.Construct {
32
37
  this._azMapper = new AvailabilityZoneMapper_1.AvailabilityZoneMapper(this, 'availability-zone-mapper');
33
38
  // Create ALB metrics and alarms per AZ
34
39
  if (this.applicationLoadBalancers) {
35
- this.albZonalIsolatedImpactAlarms = this.doAlbMetrics(props);
40
+ this.albZonalIsolatedImpactAlarms = this.createAlbZonalImpactAlarms(props);
36
41
  }
37
42
  // Create NAT Gateway metrics and alarms per AZ
38
43
  if (this.natGateways) {
39
- this.natGWZonalIsolatedImpactAlarms = this.doNatGatewayMetrics(props);
44
+ this.natGWZonalIsolatedImpactAlarms = this.createNatGatewayZonalImpactAlarms(props);
40
45
  }
41
46
  // Look through all of the per AZ ALB alarms, if there's also a NAT GW alarm
42
47
  // create a composite alarm if either of them trigger
43
- Object.keys(this.albZonalIsolatedImpactAlarms).forEach((az) => {
44
- let azLetter = az.substring(az.length - 1);
48
+ Object.keys(this.albZonalIsolatedImpactAlarms).forEach((azLetter) => {
45
49
  let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
46
- if (az in this.natGWZonalIsolatedImpactAlarms) {
47
- this.aggregateZonalIsolatedImpactAlarms[az] = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-isolated-impact-alarm", {
48
- alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.albZonalIsolatedImpactAlarms[az], this.natGWZonalIsolatedImpactAlarms[az]),
50
+ if (azLetter in this.natGWZonalIsolatedImpactAlarms) {
51
+ this.aggregateZonalIsolatedImpactAlarms[azLetter] = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-isolated-impact-alarm", {
52
+ alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.albZonalIsolatedImpactAlarms[azLetter], this.natGWZonalIsolatedImpactAlarms[azLetter]),
49
53
  compositeAlarmName: availabilityZoneId + "-isolated-impact-alarm"
50
54
  });
51
55
  }
52
56
  else {
53
- this.aggregateZonalIsolatedImpactAlarms[az] = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-isolated-impact-alarm", {
54
- alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.albZonalIsolatedImpactAlarms[az]),
57
+ this.aggregateZonalIsolatedImpactAlarms[azLetter] = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-isolated-impact-alarm", {
58
+ alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.albZonalIsolatedImpactAlarms[azLetter]),
55
59
  compositeAlarmName: availabilityZoneId + "-isolated-impact-alarm"
56
60
  });
57
61
  }
@@ -59,12 +63,11 @@ class BasicServiceMultiAZObservability extends constructs_1.Construct {
59
63
  // Look through all of the per AZ NAT GW alarms. If there's an AZ we haven't seen in the ALB
60
64
  // alarms yet, then it will just be a NAT GW alarm that we'll turn into the same kind of
61
65
  // composite alarm
62
- Object.keys(this.natGWZonalIsolatedImpactAlarms).forEach((az) => {
63
- if (!(az in this.aggregateZonalIsolatedImpactAlarms)) {
64
- let azLetter = az.substring(az.length - 1);
66
+ Object.keys(this.natGWZonalIsolatedImpactAlarms).forEach((azLetter) => {
67
+ if (!(azLetter in this.aggregateZonalIsolatedImpactAlarms)) {
65
68
  let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
66
- this.aggregateZonalIsolatedImpactAlarms[az] = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-isolated-impact-alarm", {
67
- alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.natGWZonalIsolatedImpactAlarms[az]),
69
+ this.aggregateZonalIsolatedImpactAlarms[azLetter] = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-isolated-impact-alarm", {
70
+ alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(this.natGWZonalIsolatedImpactAlarms[azLetter]),
68
71
  compositeAlarmName: availabilityZoneId + "-isolated-impact-alarm"
69
72
  });
70
73
  }
@@ -74,167 +77,59 @@ class BasicServiceMultiAZObservability extends constructs_1.Construct {
74
77
  this.dashboard = new BasicServiceDashboard_1.BasicServiceDashboard(this, 'BasicServiceDashboard', {
75
78
  serviceName: props.serviceName.toLowerCase(),
76
79
  zonalAggregateIsolatedImpactAlarms: this.aggregateZonalIsolatedImpactAlarms,
77
- zonalLoadBalancerIsolatedImpactAlarms: this.albZonalIsolatedImpactAlarms,
78
- zonalNatGatewayIsolatedImpactAlarms: this.natGWZonalIsolatedImpactAlarms,
79
80
  interval: props.interval,
80
- zonalLoadBalancerFaultRateMetrics: ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getTotalAlbFaultCountPerZone(props.applicationLoadBalancers ? props.applicationLoadBalancers : [], props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), this._azMapper),
81
- zonalNatGatewayPacketDropMetrics: this.getTotalPacketDropsPerZone(props.natGateways ? props.natGateways : {}, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1)),
82
- azMapper: this._azMapper,
81
+ natgws: props.natGatewayProps,
82
+ albs: props.applicationLoadBalancerProps,
83
+ period: props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1),
84
+ azMapper: this._azMapper
83
85
  }).dashboard;
84
86
  }
85
87
  }
86
- static isThereAnAZAvailabilityImpactAlb(scope, alb, availabilityZoneId, availabilityZone, threshold, keyprefix, period, evaluationPeriods, datapointsToAlarm) {
87
- // Create a fault rate alarm for the ALB in the specified AZ
88
- return new aws_cloudwatch_1.Alarm(scope, keyprefix + '-fault-rate-alarm', {
89
- alarmName: availabilityZoneId + '-' + alb.loadBalancerArn + '-fault-rate',
90
- actionsEnabled: false,
91
- metric: ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getPerAZAvailabilityMetric(alb, {
92
- period: period,
93
- label: availabilityZoneId + '-' + alb.loadBalancerArn + '-fault-rate',
94
- availabilityZone: availabilityZone,
95
- availabilityZoneId: availabilityZoneId,
96
- metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_RATE
97
- }),
98
- evaluationPeriods: evaluationPeriods,
99
- datapointsToAlarm: datapointsToAlarm,
100
- threshold: threshold,
101
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
102
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
103
- });
104
- }
105
- static isThereAZLatencyImpactAlb(scope, alb, availabilityZoneId, availabilityZone, threshold, statistic, keyprefix, period, evaluationPeriods, datapointsToAlarm) {
106
- // Create a fault rate alarm for the ALB in the specified AZ
107
- return new aws_cloudwatch_1.Alarm(scope, keyprefix + '-latency-alarm', {
108
- alarmName: availabilityZoneId + '-' + alb.loadBalancerArn + '-latency',
109
- actionsEnabled: false,
110
- metric: ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getPerAZLatencyMetric({
111
- alb: alb,
112
- availabilityZone: availabilityZone,
113
- availabilityZoneId: availabilityZoneId,
114
- label: availabilityZoneId + "-" + alb.loadBalancerArn + "-target-latency",
115
- period: period,
116
- statistic: statistic
117
- }),
118
- evaluationPeriods: evaluationPeriods,
119
- datapointsToAlarm: datapointsToAlarm,
120
- threshold: threshold,
121
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
122
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
123
- });
124
- }
125
- static isAZAnOutlierForAvailabilityAlb(scope, alb, availabilityZoneId, availabilityZone, threshold, keyprefix, period, evaluationPeriods, datapointsToAlarm) {
126
- let usingMetrics = {};
127
- let azMetricId = "";
128
- alb.vpc.availabilityZones.forEach((az) => {
129
- let azFaultCount = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getPerAZAvailabilityMetric(alb, {
130
- metricType: AvailabilityMetricType_1.AvailabilityMetricType.FAULT_COUNT,
131
- availabilityZone: availabilityZone,
132
- availabilityZoneId: availabilityZoneId,
133
- period: period,
134
- label: availabilityZoneId + "-" + alb.loadBalancerArn + "-fault-count",
135
- keyprefix: keyprefix
136
- });
137
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
138
- usingMetrics[`${keyprefix}1`] = azFaultCount;
139
- if (az == availabilityZone) {
140
- azMetricId = `${keyprefix}1`;
141
- }
142
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
143
- });
144
- return new aws_cloudwatch_1.Alarm(scope, keyprefix + '-availability-outlier-alarm', {
145
- alarmName: availabilityZoneId + '-' + alb.loadBalancerArn + '-availability-impact-outlier',
146
- actionsEnabled: false,
147
- metric: new aws_cloudwatch_1.MathExpression({
148
- expression: `${azMetricId}/(${Object.keys(usingMetrics).join("+")})`,
149
- usingMetrics: usingMetrics,
150
- label: availabilityZoneId + '-' + alb.loadBalancerArn + '-percent-of-faults',
151
- period: period,
152
- }),
153
- evaluationPeriods: evaluationPeriods,
154
- datapointsToAlarm: datapointsToAlarm,
155
- threshold: threshold,
156
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
157
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
158
- });
159
- }
160
- static isAZAnOutlierForLatencyAlb(scope, alb, algorithm, availabilityZoneId, availabilityZone, statistic, threshold, period, evaluationPeriods, datapointsToAlarm, keyprefix) {
161
- let usingMetrics = {};
162
- let azMetricId = "";
163
- switch (algorithm) {
164
- case ApplicationLoadBalancerLatencyOutlierCalculation_1.ApplicationLoadBalancerLatencyOutlierCalculation.Z_SCORE:
165
- default:
166
- alb.vpc.availabilityZones.forEach((az, index) => {
167
- // Target response time
168
- let targetResponseTime = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getPerAZLatencyMetric({
169
- alb: alb,
170
- availabilityZone: az,
171
- label: az + "-target-response-time",
172
- statistic: statistic,
173
- period: period
174
- });
175
- if (az == availabilityZone) {
176
- azMetricId = `a${index}`;
177
- usingMetrics[`a${index}`] = targetResponseTime;
178
- }
179
- else {
180
- usingMetrics[`b${index}`] = targetResponseTime;
181
- }
182
- });
183
- return new aws_cloudwatch_1.Alarm(scope, keyprefix + "-latency-outlier-alarm", {
184
- alarmName: availabilityZoneId + '-' + alb.loadBalancerArn + '-latency-impact-outlier',
185
- actionsEnabled: false,
186
- metric: new aws_cloudwatch_1.MathExpression({
187
- expression: `(${azMetricId} - AVG(METRICS("b"))) / AVG(STDDEV(METRICS("b")))`,
188
- usingMetrics: usingMetrics,
189
- label: availabilityZoneId + '-' + alb.loadBalancerArn + '-latency-z-score',
190
- period: period,
191
- }),
192
- evaluationPeriods: evaluationPeriods,
193
- datapointsToAlarm: datapointsToAlarm,
194
- threshold: threshold,
195
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
196
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
197
- });
198
- case ApplicationLoadBalancerLatencyOutlierCalculation_1.ApplicationLoadBalancerLatencyOutlierCalculation.STATIC:
199
- alb.vpc.availabilityZones.forEach((az, index) => {
200
- // Target response time
201
- let targetResponseTime = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.getPerAZLatencyMetric({
202
- alb: alb,
203
- availabilityZone: az,
204
- label: az + "-target-response-time",
205
- statistic: `TC(${threshold}:)`,
206
- period: period
207
- });
208
- if (az == availabilityZone) {
209
- azMetricId = `a${index}`;
210
- usingMetrics[`a${index}`] = targetResponseTime;
211
- }
212
- else {
213
- usingMetrics[`b${index}`] = targetResponseTime;
214
- }
215
- });
216
- return new aws_cloudwatch_1.Alarm(scope, keyprefix + "-latency-outlier-alarm", {
217
- alarmName: availabilityZoneId + '-' + alb.loadBalancerArn + '-latency-impact-outlier',
218
- actionsEnabled: false,
219
- metric: new aws_cloudwatch_1.MathExpression({
220
- expression: `${azMetricId}/(${Object.keys(usingMetrics).join("+")})`,
221
- usingMetrics: usingMetrics,
222
- label: availabilityZoneId + '-' + alb.loadBalancerArn + '-latency-static',
223
- period: period,
224
- }),
225
- evaluationPeriods: evaluationPeriods,
226
- datapointsToAlarm: datapointsToAlarm,
227
- threshold: .66,
228
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
229
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
230
- });
231
- }
232
- }
233
- doAlbMetrics(props) {
88
+ /**
89
+ *
90
+ * @param props
91
+ * @returns A composite alarm per AZ to indicate isolated zonal impact. The dictionary
92
+ * is keyed by the az letter, like "a", "b", "c".
93
+ */
94
+ createAlbZonalImpactAlarms(props) {
234
95
  // Create impact alarms per AZ, with each ALB providing
235
96
  // an alarm for its AZs
236
97
  let perAZImpactAlarms = {};
237
98
  let keyPrefix = MetricsHelper_1.MetricsHelper.nextChar();
99
+ let availabilityOutlierDetectionAlgorithm = props.applicationLoadBalancerProps?.availabilityOutlierAlgorithm ?
100
+ props.applicationLoadBalancerProps.availabilityOutlierAlgorithm :
101
+ ApplicationLoadBalancerAvailabilityOutlierAlgorithm_1.ApplicationLoadBalancerAvailabilityOutlierAlgorithm.STATIC;
102
+ let latencyOutlierDetectionAlgorithm = props.applicationLoadBalancerProps?.latencyOutlierAlgorithm ?
103
+ props.applicationLoadBalancerProps.latencyOutlierAlgorithm :
104
+ ApplicationLoadBalancerLatencyOutlierAlgorithm_1.ApplicationLoadBalancerLatencyOutlierAlgorithm.Z_SCORE;
105
+ let availabilityOutlierThreshold;
106
+ if (props.applicationLoadBalancerProps?.availabilityOutlierThreshold) {
107
+ availabilityOutlierThreshold = props.applicationLoadBalancerProps.availabilityOutlierThreshold;
108
+ }
109
+ else {
110
+ switch (availabilityOutlierDetectionAlgorithm) {
111
+ case ApplicationLoadBalancerAvailabilityOutlierAlgorithm_1.ApplicationLoadBalancerAvailabilityOutlierAlgorithm.STATIC:
112
+ default:
113
+ availabilityOutlierThreshold = 66;
114
+ break;
115
+ }
116
+ }
117
+ let latencyOutlierThreshold;
118
+ if (props.applicationLoadBalancerProps?.latencyOutlierThreshold) {
119
+ latencyOutlierThreshold = props.applicationLoadBalancerProps.latencyOutlierThreshold;
120
+ }
121
+ else {
122
+ switch (latencyOutlierDetectionAlgorithm) {
123
+ case ApplicationLoadBalancerLatencyOutlierAlgorithm_1.ApplicationLoadBalancerLatencyOutlierAlgorithm.Z_SCORE:
124
+ default:
125
+ latencyOutlierThreshold = 3;
126
+ break;
127
+ case ApplicationLoadBalancerLatencyOutlierAlgorithm_1.ApplicationLoadBalancerLatencyOutlierAlgorithm.STATIC:
128
+ latencyOutlierThreshold = 66;
129
+ break;
130
+ }
131
+ }
132
+ let period = props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1);
238
133
  // Iterate each ALB
239
134
  this.applicationLoadBalancers.forEach((alb) => {
240
135
  // Iterate each AZ in the VPC
@@ -247,15 +142,15 @@ class BasicServiceMultiAZObservability extends constructs_1.Construct {
247
142
  // Map letter to AZ ID
248
143
  let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
249
144
  // Is there availability impact in this AZ?
250
- let availabilityImpact = BasicServiceMultiAZObservability.isThereAnAZAvailabilityImpactAlb(this, alb, availabilityZoneId, az, props.faultCountPercentageThreshold ? props.faultCountPercentageThreshold : 0.05, keyPrefix, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
145
+ let availabilityImpact = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createAZAvailabilityImpactAlarm(this, alb, availabilityZoneId, az, props.applicationLoadBalancerProps.faultCountPercentThreshold, keyPrefix, period, props.evaluationPeriods, props.datapointsToAlarm);
251
146
  // Is there latency impact in this AZ?
252
- let latencyImpact = BasicServiceMultiAZObservability.isThereAZLatencyImpactAlb(this, alb, availabilityZoneId, az, props.latencyThreshold, props.latencyStatistic, keyPrefix, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
147
+ let latencyImpact = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createAZLatencyImpactAlarm(this, alb, availabilityZoneId, az, props.applicationLoadBalancerProps.latencyThreshold, props.applicationLoadBalancerProps.latencyStatistic, keyPrefix, period, props.evaluationPeriods, props.datapointsToAlarm);
253
148
  // Is the AZ an outlier for faults
254
- let availabilityOutlier = BasicServiceMultiAZObservability.isAZAnOutlierForAvailabilityAlb(this, alb, availabilityZoneId, az, props.faultCountPercentageThreshold ? props.faultCountPercentageThreshold : 0.05, keyPrefix, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
149
+ let availabilityOutlier = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createAZAvailabilityOutlierAlarm(this, alb, availabilityOutlierDetectionAlgorithm, availabilityZoneId, az, availabilityOutlierThreshold, keyPrefix, period, props.evaluationPeriods, props.datapointsToAlarm);
255
150
  // Is the AZ an outlier for latency
256
- let latencyOutlier = BasicServiceMultiAZObservability.isAZAnOutlierForLatencyAlb(this, alb, props.latencyOutlierCalculation ? props.latencyOutlierCalculation : ApplicationLoadBalancerLatencyOutlierCalculation_1.ApplicationLoadBalancerLatencyOutlierCalculation.Z_SCORE, availabilityZoneId, az, props.latencyStatistic, props.latencyOutlierCalculation == ApplicationLoadBalancerLatencyOutlierCalculation_1.ApplicationLoadBalancerLatencyOutlierCalculation.Z_SCORE ? 3 : props.latencyThreshold, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm, azLetter);
151
+ let latencyOutlier = ApplicationLoadBalancerMetrics_1.ApplicationLoadBalancerMetrics.createAZLatencyOutlierAlarm(this, alb, latencyOutlierDetectionAlgorithm, az, props.applicationLoadBalancerProps.latencyStatistic, props.applicationLoadBalancerProps.latencyThreshold, latencyOutlierThreshold, period, props.evaluationPeriods, props.datapointsToAlarm, this._azMapper);
257
152
  // Alarm if the AZ shows impact and is an outlier
258
- let azImpactAlarm = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-composite-impact-alarm", {
153
+ let azImpactAlarm = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-composite-impact-alarm", {
259
154
  alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(aws_cloudwatch_1.AlarmRule.allOf(availabilityImpact, availabilityOutlier), aws_cloudwatch_1.AlarmRule.allOf(latencyImpact, latencyOutlier)),
260
155
  compositeAlarmName: availabilityZoneId + "-" +
261
156
  alb.loadBalancerName +
@@ -274,199 +169,52 @@ class BasicServiceMultiAZObservability extends constructs_1.Construct {
274
169
  Object.keys(perAZImpactAlarms).forEach((az) => {
275
170
  let azLetter = az.substring(az.length - 1);
276
171
  let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
277
- azCompositeAlarms[az] = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-alb-impact-composite-alarm", {
172
+ azCompositeAlarms[azLetter] = new aws_cloudwatch_1.CompositeAlarm(this, azLetter + "-alb-impact-composite-alarm", {
278
173
  alarmRule: aws_cloudwatch_1.AlarmRule.anyOf(...perAZImpactAlarms[az]),
279
174
  compositeAlarmName: availabilityZoneId + "-alb-impact-composite-alarm"
280
175
  });
281
176
  });
282
177
  return azCompositeAlarms;
283
178
  }
284
- static isThereAnAZPacketLossImpactNATGW(scope, natgws, availabilityZoneId, availabilityZone, threshold, period, evaluationPeriods, datapointsToAlarm) {
285
- let keyprefix = MetricsHelper_1.MetricsHelper.nextChar();
286
- let packetDropCountMetrics = {};
287
- let packetsInFromSourceMetrics = {};
288
- let packetsInFromDestinationMetrics = {};
289
- natgws.forEach((natgw) => {
290
- packetDropCountMetrics[`${keyprefix}1`] = new aws_cloudwatch_1.Metric({
291
- metricName: 'PacketsDropCount',
292
- namespace: 'AWS/NATGateway',
293
- statistic: aws_cloudwatch_1.Stats.SUM,
294
- unit: aws_cloudwatch_1.Unit.COUNT,
295
- label: availabilityZoneId + ' packet drops',
296
- dimensionsMap: {
297
- NatGatewayId: natgw.attrNatGatewayId,
298
- },
299
- period: period,
300
- });
301
- // Calculate packets in from source
302
- packetsInFromSourceMetrics[`${keyprefix}2`] = new aws_cloudwatch_1.Metric({
303
- metricName: 'PacketsInFromSource',
304
- namespace: 'AWS/NATGateway',
305
- statistic: aws_cloudwatch_1.Stats.SUM,
306
- unit: aws_cloudwatch_1.Unit.COUNT,
307
- label: availabilityZoneId + ' packets in from source',
308
- dimensionsMap: {
309
- NatGatewayId: natgw.attrNatGatewayId,
310
- },
311
- period: period,
312
- });
313
- // Calculate packets in from destination
314
- packetsInFromDestinationMetrics[`${keyprefix}3`] = new aws_cloudwatch_1.Metric({
315
- metricName: 'PacketsInFromDestination',
316
- namespace: 'AWS/NATGateway',
317
- statistic: aws_cloudwatch_1.Stats.SUM,
318
- unit: aws_cloudwatch_1.Unit.COUNT,
319
- label: availabilityZoneId + ' packets in from destination',
320
- dimensionsMap: {
321
- NatGatewayId: natgw.attrNatGatewayId,
322
- },
323
- period: period,
324
- });
325
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
326
- });
327
- let packetDropTotal = new aws_cloudwatch_1.MathExpression({
328
- expression: Object.keys(packetDropCountMetrics).join("+"),
329
- usingMetrics: packetDropCountMetrics,
330
- period: period
331
- });
332
- let packetsInFromSourceTotal = new aws_cloudwatch_1.MathExpression({
333
- expression: Object.keys(packetsInFromSourceMetrics).join("+"),
334
- usingMetrics: packetsInFromSourceMetrics,
335
- period: period
336
- });
337
- let packetsInFromDestinationTotal = new aws_cloudwatch_1.MathExpression({
338
- expression: Object.keys(packetsInFromDestinationMetrics).join("+"),
339
- usingMetrics: packetsInFromDestinationMetrics,
340
- period: period
341
- });
342
- let usingMetrics = {};
343
- usingMetrics[`${keyprefix}1`] = packetDropTotal;
344
- usingMetrics[`${keyprefix}2`] = packetsInFromSourceTotal;
345
- usingMetrics[`${keyprefix}3`] = packetsInFromDestinationTotal;
346
- // Calculate a percentage of dropped packets for the NAT GW
347
- let packetDropPercentage = new aws_cloudwatch_1.MathExpression({
348
- expression: `(${keyprefix}1 / (${keyprefix}2 + ${keyprefix}3))`,
349
- usingMetrics: usingMetrics,
350
- label: availabilityZoneId + ' packet drop percentage',
351
- period: period,
352
- });
353
- // Create an alarm for this NAT GW if packet drops exceed the specified threshold
354
- return new aws_cloudwatch_1.Alarm(scope, availabilityZone.substring(availabilityZone.length - 1) + "-packet-drop-impact-alarm", {
355
- alarmName: availabilityZoneId +
356
- '-packet-drop-impact',
357
- actionsEnabled: false,
358
- metric: packetDropPercentage,
359
- threshold: threshold,
360
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
361
- evaluationPeriods: evaluationPeriods,
362
- datapointsToAlarm: datapointsToAlarm,
363
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
364
- });
365
- }
366
- static isAZAnOutlierForPacketLossNATGW(scope, natgws, availabilityZoneId, availabilityZone, threshold, period, evaluationPeriods, datapointsToAlarm) {
367
- let keyprefix = MetricsHelper_1.MetricsHelper.nextChar();
368
- let azPacketDropCountMetrics = {};
369
- let azKey = "";
370
- Object.keys(natgws).forEach((az) => {
371
- let packetDropCountMetrics = {};
372
- natgws[az].forEach((natgw, index) => {
373
- packetDropCountMetrics[`${keyprefix}${index}`] = new aws_cloudwatch_1.Metric({
374
- metricName: 'PacketsDropCount',
375
- namespace: 'AWS/NATGateway',
376
- statistic: aws_cloudwatch_1.Stats.SUM,
377
- unit: aws_cloudwatch_1.Unit.COUNT,
378
- label: availabilityZoneId + ' packet drops',
379
- dimensionsMap: {
380
- NatGatewayId: natgw.attrNatGatewayId,
381
- },
382
- period: period,
383
- });
384
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
385
- });
386
- azPacketDropCountMetrics[`${keyprefix}${natgws[az].length}`] = new aws_cloudwatch_1.MathExpression({
387
- expression: Object.keys(packetDropCountMetrics).join("+"),
388
- usingMetrics: packetDropCountMetrics,
389
- period: period
390
- });
391
- if (az == availabilityZone) {
392
- azKey = `${keyprefix}${natgws[az].length}`;
393
- }
394
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
395
- });
396
- return new aws_cloudwatch_1.Alarm(scope, availabilityZone.substring(availabilityZone.length - 1) + "-packet-loss-outlier", {
397
- metric: new aws_cloudwatch_1.MathExpression({
398
- expression: `${azKey} / (${Object.keys(azPacketDropCountMetrics).join("+")})`,
399
- usingMetrics: azPacketDropCountMetrics,
400
- period: period
401
- }),
402
- threshold: threshold,
403
- evaluationPeriods: evaluationPeriods,
404
- datapointsToAlarm: datapointsToAlarm,
405
- comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
406
- treatMissingData: aws_cloudwatch_1.TreatMissingData.IGNORE
407
- });
408
- }
409
- doNatGatewayMetrics(props) {
179
+ createNatGatewayZonalImpactAlarms(props) {
410
180
  // Collect alarms for packet drops exceeding a threshold per NAT GW
411
181
  let packetLossPerAZAlarms = {};
182
+ let packetLossOutlierAlgorithm = props.natGatewayProps?.packetLossOutlierAlgorithm ?
183
+ props.natGatewayProps?.packetLossOutlierAlgorithm :
184
+ PacketLossOutlierAlgorithm_1.PacketLossOutlierAlgorithm.STATIC;
185
+ let packetLossThreshold = props.natGatewayProps?.packetLossPercentThreshold ?
186
+ props.natGatewayProps.packetLossPercentThreshold :
187
+ 0.01;
188
+ let outlierThreshold;
189
+ if (props.natGatewayProps?.packetLossOutlierThreshold) {
190
+ outlierThreshold = props.natGatewayProps.packetLossOutlierThreshold;
191
+ }
192
+ else {
193
+ switch (packetLossOutlierAlgorithm) {
194
+ case PacketLossOutlierAlgorithm_1.PacketLossOutlierAlgorithm.STATIC:
195
+ default:
196
+ outlierThreshold = 66;
197
+ break;
198
+ }
199
+ }
200
+ let period = props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1);
412
201
  // For each AZ, create metrics for each NAT GW
413
202
  Object.keys(this.natGateways).forEach((az) => {
414
203
  let azLetter = az.substring(az.length - 1);
415
204
  let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
416
205
  // Is there packet loss impact?
417
- let packetLossImpact = BasicServiceMultiAZObservability.isThereAnAZPacketLossImpactNATGW(this, this.natGateways[az], availabilityZoneId, az, props.packetLossImpactPercentageThreshold ? props.packetLossImpactPercentageThreshold : 0.01, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
206
+ let packetLossImpact = NatGatewayMetrics_1.NatGatewayMetrics.isThereAnAZPacketLossImpactNATGW(this, this.natGateways[az], availabilityZoneId, az, packetLossThreshold, period, props.evaluationPeriods, props.datapointsToAlarm);
418
207
  // Is this AZ an outlier for this NATGW?
419
- let packetLossOutlier = BasicServiceMultiAZObservability.isAZAnOutlierForPacketLossNATGW(this, this.natGateways, availabilityZoneId, az, 0.66, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
420
- packetLossPerAZAlarms[az] = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-packet-loss-composite-alarm", {
208
+ let packetLossOutlier = NatGatewayMetrics_1.NatGatewayMetrics.isAZAnOutlierForPacketLossNATGW(this, this.natGateways, packetLossOutlierAlgorithm, az, this._azMapper, outlierThreshold, props.period ? props.period : aws_cdk_lib_1.Duration.minutes(1), props.evaluationPeriods, props.datapointsToAlarm);
209
+ packetLossPerAZAlarms[azLetter] = new aws_cloudwatch_1.CompositeAlarm(this, az.substring(az.length - 1) + "-packet-loss-composite-alarm", {
421
210
  alarmRule: aws_cloudwatch_1.AlarmRule.allOf(packetLossImpact, packetLossOutlier),
422
211
  compositeAlarmName: availabilityZoneId + "-packet-loss-composite-alarm"
423
212
  });
424
213
  });
425
214
  return packetLossPerAZAlarms;
426
215
  }
427
- getTotalPacketDropsPerZone(natgws, period) {
428
- let dropsPerZone = {};
429
- let metricsPerAZ = {};
430
- let keyprefix = MetricsHelper_1.MetricsHelper.nextChar();
431
- Object.keys(natgws).forEach((availabilityZone) => {
432
- let azLetter = availabilityZone.substring(availabilityZone.length - 1);
433
- let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
434
- if (!(availabilityZone in metricsPerAZ)) {
435
- metricsPerAZ[availabilityZone] = [];
436
- }
437
- natgws[availabilityZone].forEach((natgw) => {
438
- metricsPerAZ[availabilityZone].push(new aws_cloudwatch_1.Metric({
439
- metricName: 'PacketsDropCount',
440
- namespace: 'AWS/NATGateway',
441
- statistic: aws_cloudwatch_1.Stats.SUM,
442
- unit: aws_cloudwatch_1.Unit.COUNT,
443
- label: availabilityZoneId + ' packet drops',
444
- dimensionsMap: {
445
- NatGatewayId: natgw.attrNatGatewayId,
446
- },
447
- period: period,
448
- }));
449
- });
450
- });
451
- Object.keys(metricsPerAZ).forEach((availabilityZone) => {
452
- let azLetter = availabilityZone.substring(availabilityZone.length - 1);
453
- let availabilityZoneId = this._azMapper.availabilityZoneIdFromAvailabilityZoneLetter(azLetter);
454
- let usingMetrics = {};
455
- metricsPerAZ[availabilityZone].forEach((metric) => {
456
- usingMetrics[`${keyprefix}1`] = metric;
457
- keyprefix = MetricsHelper_1.MetricsHelper.nextChar(keyprefix);
458
- });
459
- dropsPerZone[availabilityZone] = new aws_cloudwatch_1.MathExpression({
460
- expression: Object.keys(usingMetrics).join("+"),
461
- usingMetrics: usingMetrics,
462
- label: availabilityZoneId + " total packet drops",
463
- period: period
464
- });
465
- });
466
- return dropsPerZone;
467
- }
468
216
  }
469
217
  exports.BasicServiceMultiAZObservability = BasicServiceMultiAZObservability;
470
218
  _a = JSII_RTTI_SYMBOL_1;
471
- BasicServiceMultiAZObservability[_a] = { fqn: "@cdklabs/multi-az-observability.BasicServiceMultiAZObservability", version: "0.0.1-alpha.6" };
472
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmFzaWNfb2JzZXJ2YWJpbGl0eS9CYXNpY1NlcnZpY2VNdWx0aUFaT2JzZXJ2YWJpbGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsNkNBQXVDO0FBQ3ZDLCtEQWFvQztBQU9wQywyQ0FBbUQ7QUFHbkQsK0VBQTRFO0FBRTVFLG1FQUFnRTtBQUNoRSw4RkFBMkY7QUFDM0YsZ0ZBQTZFO0FBQzdFLDhEQUEyRDtBQUMzRCwrSEFBNEg7QUFFNUg7OztHQUdHO0FBQ0gsTUFBYSxnQ0FDWCxTQUFRLHNCQUFTO0lBOENqQixZQUNFLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixLQUE0QztRQUU1QyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLDhCQUE4QjtRQUM5QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQztRQUMvRCxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFFckMsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLEVBQUUsQ0FBQztRQUM3QyxJQUFJLENBQUMsNEJBQTRCLEdBQUcsRUFBRSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyw4QkFBOEIsR0FBRyxFQUFFLENBQUM7UUFFekMsNkRBQTZEO1FBQzdELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSwrQ0FBc0IsQ0FBQyxJQUFJLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUU5RSx1Q0FBdUM7UUFDdkMsSUFBSSxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsNEJBQTRCLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFL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Z0I7cUJBQ3JDO29CQUNELE1BQU0sRUFBRSxNQUFNO2lCQUNmLENBQUMsQ0FBQyxDQUFDO1lBQ04sQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsZ0JBQXdCLEVBQUUsRUFBRTtZQUM3RCxJQUFJLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3ZFLElBQUksa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyw0Q0FBNEMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUvRixJQUFJLFlBQVksR0FBNkIsRUFBRSxDQUFDO1lBRWhELFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQWUsRUFBRSxFQUFFO2dCQUN6RCxZQUFZLENBQUMsR0FBRyxTQUFTLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQztnQkFDdkMsU0FBUyxHQUFHLDZCQUFhLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2hELENBQUMsQ0FBQyxDQUFDO1lBRUgsWUFBWSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsSUFBSSwrQkFBYyxDQUFDO2dCQUNsRCxVQUFVLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO2dCQUMvQyxZQUFZLEVBQUUsWUFBWTtnQkFDMUIsS0FBSyxFQUFFLGtCQUFrQixHQUFHLHFCQUFxQjtnQkFDakQsTUFBTSxFQUFFLE1BQU07YUFDZixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7O0FBN3dCSCw0RUE4d0JDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBEdXJhdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7XG4gIEFsYXJtLFxuICBBbGFybVJ1bGUsXG4gIENvbXBhcmlzb25PcGVyYXRvcixcbiAgQ29tcG9zaXRlQWxhcm0sXG4gIERhc2hib2FyZCxcbiAgSUFsYXJtLFxuICBJTWV0cmljLFxuICBNYXRoRXhwcmVzc2lvbixcbiAgTWV0cmljLFxuICBTdGF0cyxcbiAgVHJlYXRNaXNzaW5nRGF0YSxcbiAgVW5pdCxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0IHsgQ2ZuTmF0R2F0ZXdheSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHtcbiAgQmFzZUxvYWRCYWxhbmNlcixcbiAgSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICBJTG9hZEJhbGFuY2VyVjIsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyJztcbmltcG9ydCB7IENvbnN0cnVjdCwgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgSUJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5IH0gZnJvbSAnLi9JQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHknO1xuaW1wb3J0IHsgQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wcyB9IGZyb20gJy4vcHJvcHMvQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wcyc7XG5pbXBvcnQgeyBBdmFpbGFiaWxpdHlab25lTWFwcGVyIH0gZnJvbSAnLi4vYXptYXBwZXIvQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcic7XG5pbXBvcnQgeyBJQXZhaWxhYmlsaXR5Wm9uZU1hcHBlciB9IGZyb20gJy4uL2F6bWFwcGVyL0lBdmFpbGFiaWxpdHlab25lTWFwcGVyJztcbmltcG9ydCB7IEJhc2ljU2VydmljZURhc2hib2FyZCB9IGZyb20gJy4vQmFzaWNTZXJ2aWNlRGFzaGJvYXJkJztcbmltcG9ydCB7IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcyB9IGZyb20gJy4uL21ldHJpY3MvQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzJztcbmltcG9ydCB7IEF2YWlsYWJpbGl0eU1ldHJpY1R5cGUgfSBmcm9tICcuLi91dGlsaXRpZXMvQXZhaWxhYmlsaXR5TWV0cmljVHlwZSc7XG5pbXBvcnQgeyBNZXRyaWNzSGVscGVyIH0gZnJvbSAnLi4vdXRpbGl0aWVzL01ldHJpY3NIZWxwZXInO1xuaW1wb3J0IHsgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJMYXRlbmN5T3V0bGllckNhbGN1bGF0aW9uIH0gZnJvbSAnLi9wcm9wcy9BcHBsaWNhdGlvbkxvYWRCYWxhbmNlckxhdGVuY3lPdXRsaWVyQ2FsY3VsYXRpb24nO1xuXG4vKipcbiAqIEJhc2ljIG9ic2VydmFiaWxpdHkgZm9yIGEgc2VydmljZSB1c2luZyBtZXRyaWNzIGZyb21cbiAqIEFMQnMgYW5kIE5BVCBHYXRld2F5c1xuICovXG5leHBvcnQgY2xhc3MgQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlcbiAgZXh0ZW5kcyBDb25zdHJ1Y3RcbiAgaW1wbGVtZW50cyBJQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkge1xuICAvKipcbiAgICogVGhlIE5BVCBHYXRld2F5cyBiZWluZyB1c2VkIGluIHRoZSBzZXJ2aWNlLCBlYWNoIHNldCBvZiBOQVQgR2F0ZXdheXNcbiAgICogYXJlIGtleWVkIGJ5IHRoZWlyIEF2YWlsYWJpbGl0eSBab25lIElkXG4gICAqL1xuICBuYXRHYXRld2F5cz86IHsgW2tleTogc3RyaW5nXTogQ2ZuTmF0R2F0ZXdheVtdIH07XG5cbiAgLyoqXG4gICAqIFRoZSBhcHBsaWNhdGlvbiBsb2FkIGJhbGFuY2VycyBiZWluZyB1c2VkIGJ5IHRoZSBzZXJ2aWNlXG4gICAqL1xuICBhcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnM/OiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJbXTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2VcbiAgICovXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhbGFybXMgaW5kaWNhdGluZyBpZiBhbiBBWiBpcyBhbiBvdXRsaWVyIGZvciBOQVQgR1dcbiAgICogcGFja2V0IGxvc3MgYW5kIGhhcyBpc29sYXRlZCBpbXBhY3RcbiAgICovXG4gIG5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcz86IHsgW2tleTogc3RyaW5nXTogSUFsYXJtIH07XG5cbiAgLyoqXG4gICAqIFRoZSBhbGFybXMgaW5kaWNhdGluZyBpZiBhbiBBWiBpcyBhbiBvdXRsaWVyIGZvciBBTEJcbiAgICogZmF1bHRzIGFuZCBoYXMgaXNvbGF0ZWQgaW1wYWN0XG4gICAqL1xuICBhbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zPzogeyBba2V5OiBzdHJpbmddOiBJQWxhcm0gfTtcblxuICAvKipcbiAgICogVGhlIGFsYXJtcyBpbmRpY2F0aW5nIGlmIGFuIEFaIGhhcyBpc29sYXRlZCBpbXBhY3RcbiAgICogZnJvbSBlaXRoZXIgQUxCIG9yIE5BVCBHVyBtZXRyaWNzXG4gICAqL1xuICBhZ2dyZWdhdGVab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zOiB7IFtrZXk6IHN0cmluZ106IElBbGFybSB9O1xuXG4gIC8qKlxuICAgKiBUaGUgZGFzaGJvYXJkIHRoYXQgaXMgb3B0aW9uYWxseSBjcmVhdGVkXG4gICAqL1xuICBkYXNoYm9hcmQ/OiBEYXNoYm9hcmQ7XG5cbiAgLyoqXG4gICAqIFRoZSBBWiBtYXBwZXIgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgX2F6TWFwcGVyOiBJQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IEJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5UHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICAvLyBJbml0aWFsaXplIGNsYXNzIHByb3BlcnRpZXNcbiAgICB0aGlzLnNlcnZpY2VOYW1lID0gcHJvcHMuc2VydmljZU5hbWU7XG4gICAgdGhpcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnMgPSBwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnM7XG4gICAgdGhpcy5uYXRHYXRld2F5cyA9IHByb3BzLm5hdEdhdGV3YXlzO1xuXG4gICAgdGhpcy5hZ2dyZWdhdGVab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zID0ge307XG4gICAgdGhpcy5hbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zID0ge307XG4gICAgdGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMgPSB7fTtcblxuICAgIC8vIENyZWF0ZSB0aGUgQVogbWFwcGVyIHJlc291cmNlIHRvIHRyYW5zbGF0ZSBBWiBuYW1lcyB0byBpZHNcbiAgICB0aGlzLl9hek1hcHBlciA9IG5ldyBBdmFpbGFiaWxpdHlab25lTWFwcGVyKHRoaXMsICdhdmFpbGFiaWxpdHktem9uZS1tYXBwZXInKTtcblxuICAgIC8vIENyZWF0ZSBBTEIgbWV0cmljcyBhbmQgYWxhcm1zIHBlciBBWlxuICAgIGlmICh0aGlzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2Vycykge1xuICAgICAgdGhpcy5hbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zID0gdGhpcy5kb0FsYk1ldHJpY3MocHJvcHMpO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBOQVQgR2F0ZXdheSBtZXRyaWNzIGFuZCBhbGFybXMgcGVyIEFaXG4gICAgaWYgKHRoaXMubmF0R2F0ZXdheXMpIHtcbiAgICAgIHRoaXMubmF0R1dab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zID0gdGhpcy5kb05hdEdhdGV3YXlNZXRyaWNzKHByb3BzKTtcbiAgICB9XG5cbiAgICAvLyBMb29rIHRocm91Z2ggYWxsIG9mIHRoZSBwZXIgQVogQUxCIGFsYXJtcywgaWYgdGhlcmUncyBhbHNvIGEgTkFUIEdXIGFsYXJtXG4gICAgLy8gY3JlYXRlIGEgY29tcG9zaXRlIGFsYXJtIGlmIGVpdGhlciBvZiB0aGVtIHRyaWdnZXJcbiAgICBPYmplY3Qua2V5cyh0aGlzLmFsYlpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMpLmZvckVhY2goKGF6OiBzdHJpbmcpID0+IHtcbiAgICAgIGxldCBhekxldHRlciA9IGF6LnN1YnN0cmluZyhhei5sZW5ndGggLSAxKTtcbiAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQgPSB0aGlzLl9hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihhekxldHRlcik7XG4gICAgICBpZiAoYXogaW4gdGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMhKSB7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtc1thel0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpICsgXCItaXNvbGF0ZWQtaW1wYWN0LWFsYXJtXCIsIHtcbiAgICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZih0aGlzLmFsYlpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMhW2F6XSwgdGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMhW2F6XSksXG4gICAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOiBhdmFpbGFiaWxpdHlab25lSWQgKyBcIi1pc29sYXRlZC1pbXBhY3QtYWxhcm1cIlxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0aGlzLmFnZ3JlZ2F0ZVpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXNbYXpdID0gbmV3IENvbXBvc2l0ZUFsYXJtKHRoaXMsIGF6LnN1YnN0cmluZyhhei5sZW5ndGggLSAxKSArIFwiLWlzb2xhdGVkLWltcGFjdC1hbGFybVwiLCB7XG4gICAgICAgICAgYWxhcm1SdWxlOiBBbGFybVJ1bGUuYW55T2YodGhpcy5hbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zIVthel0pLFxuICAgICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItaXNvbGF0ZWQtaW1wYWN0LWFsYXJtXCJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBMb29rIHRocm91Z2ggYWxsIG9mIHRoZSBwZXIgQVogTkFUIEdXIGFsYXJtcy4gSWYgdGhlcmUncyBhbiBBWiB3ZSBoYXZlbid0IHNlZW4gaW4gdGhlIEFMQlxuICAgIC8vIGFsYXJtcyB5ZXQsIHRoZW4gaXQgd2lsbCBqdXN0IGJlIGEgTkFUIEdXIGFsYXJtIHRoYXQgd2UnbGwgdHVybiBpbnRvIHRoZSBzYW1lIGtpbmQgb2ZcbiAgICAvLyBjb21wb3NpdGUgYWxhcm1cbiAgICBPYmplY3Qua2V5cyh0aGlzLm5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcykuZm9yRWFjaCgoYXo6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCEoYXogaW4gdGhpcy5hZ2dyZWdhdGVab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zKSkge1xuICAgICAgICBsZXQgYXpMZXR0ZXIgPSBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSk7XG4gICAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQgPSB0aGlzLl9hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihhekxldHRlcik7XG5cbiAgICAgICAgdGhpcy5hZ2dyZWdhdGVab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zW2F6XSA9IG5ldyBDb21wb3NpdGVBbGFybSh0aGlzLCBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSkgKyBcIi1pc29sYXRlZC1pbXBhY3QtYWxhcm1cIiwge1xuICAgICAgICAgIGFsYXJtUnVsZTogQWxhcm1SdWxlLmFueU9mKHRoaXMubmF0R1dab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zIVthel0pLFxuICAgICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItaXNvbGF0ZWQtaW1wYWN0LWFsYXJtXCJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgLy8gU2hvdWxkIHdlIGNyZWF0ZSB0aGUgZGFzaGJvYXJkXG4gICAgaWYgKHByb3BzLmNyZWF0ZURhc2hib2FyZCA9PSB0cnVlKSB7XG4gICAgICB0aGlzLmRhc2hib2FyZCA9IG5ldyBCYXNpY1NlcnZpY2VEYXNoYm9hcmQoXG4gICAgICAgIHRoaXMsXG4gICAgICAgICdCYXNpY1NlcnZpY2VEYXNoYm9hcmQnLFxuICAgICAgICB7XG4gICAgICAgICAgc2VydmljZU5hbWU6IHByb3BzLnNlcnZpY2VOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAgICAgICAgem9uYWxBZ2dyZWdhdGVJc29sYXRlZEltcGFjdEFsYXJtczpcbiAgICAgICAgICAgIHRoaXMuYWdncmVnYXRlWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyxcbiAgICAgICAgICB6b25hbExvYWRCYWxhbmNlcklzb2xhdGVkSW1wYWN0QWxhcm1zOlxuICAgICAgICAgICAgdGhpcy5hbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zLFxuICAgICAgICAgIHpvbmFsTmF0R2F0ZXdheUlzb2xhdGVkSW1wYWN0QWxhcm1zOlxuICAgICAgICAgICAgdGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMsXG4gICAgICAgICAgaW50ZXJ2YWw6IHByb3BzLmludGVydmFsLFxuICAgICAgICAgIHpvbmFsTG9hZEJhbGFuY2VyRmF1bHRSYXRlTWV0cmljczogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzLmdldFRvdGFsQWxiRmF1bHRDb3VudFBlclpvbmUoXG4gICAgICAgICAgICBwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnMgPyBwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnMgOiBbXSwgXG4gICAgICAgICAgICBwcm9wcy5wZXJpb2QgPyBwcm9wcy5wZXJpb2QgOiBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgICAgICAgdGhpcy5fYXpNYXBwZXJcbiAgICAgICAgICApLFxuICAgICAgICAgIHpvbmFsTmF0R2F0ZXdheVBhY2tldERyb3BNZXRyaWNzOiB0aGlzLmdldFRvdGFsUGFja2V0RHJvcHNQZXJab25lKFxuICAgICAgICAgICAgcHJvcHMubmF0R2F0ZXdheXMgPyBwcm9wcy5uYXRHYXRld2F5cyA6IHt9LFxuICAgICAgICAgICAgcHJvcHMucGVyaW9kID8gcHJvcHMucGVyaW9kIDogRHVyYXRpb24ubWludXRlcygxKVxuICAgICAgICAgICksXG4gICAgICAgICAgYXpNYXBwZXI6IHRoaXMuX2F6TWFwcGVyLFxuICAgICAgICB9LFxuICAgICAgKS5kYXNoYm9hcmQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaXNUaGVyZUFuQVpBdmFpbGFiaWxpdHlJbXBhY3RBbGIoXG4gICAgc2NvcGU6IElDb25zdHJ1Y3QsXG4gICAgYWxiOiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIsIFxuICAgIGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nLFxuICAgIGF2YWlsYWJpbGl0eVpvbmU6IHN0cmluZyxcbiAgICB0aHJlc2hvbGQ6IG51bWJlcixcbiAgICBrZXlwcmVmaXg6IHN0cmluZyxcbiAgICBwZXJpb2Q6IER1cmF0aW9uLFxuICAgIGV2YWx1YXRpb25QZXJpb2RzOiBudW1iZXIsXG4gICAgZGF0YXBvaW50c1RvQWxhcm06IG51bWJlclxuICApIDogSUFsYXJtIHtcbiAgIFxuICAgIC8vIENyZWF0ZSBhIGZhdWx0IHJhdGUgYWxhcm0gZm9yIHRoZSBBTEIgaW4gdGhlIHNwZWNpZmllZCBBWlxuICAgIHJldHVybiBuZXcgQWxhcm0oXG4gICAgICBzY29wZSxcbiAgICAgIGtleXByZWZpeCArICctZmF1bHQtcmF0ZS1hbGFybScsXG4gICAgICB7XG4gICAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgKyAnLScgKyBhbGIubG9hZEJhbGFuY2VyQXJuICsgJy1mYXVsdC1yYXRlJyxcbiAgICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgICBtZXRyaWM6IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcy5nZXRQZXJBWkF2YWlsYWJpbGl0eU1ldHJpYyhhbGIsIHtcbiAgICAgICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJy0nICsgYWxiLmxvYWRCYWxhbmNlckFybiArICctZmF1bHQtcmF0ZScsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogYXZhaWxhYmlsaXR5Wm9uZSxcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQ6IGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLkZBVUxUX1JBVEVcbiAgICAgICAgfSksXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBldmFsdWF0aW9uUGVyaW9kcyxcbiAgICAgICAgZGF0YXBvaW50c1RvQWxhcm06IGRhdGFwb2ludHNUb0FsYXJtLFxuICAgICAgICB0aHJlc2hvbGQ6IHRocmVzaG9sZCxcbiAgICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogVHJlYXRNaXNzaW5nRGF0YS5JR05PUkVcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaXNUaGVyZUFaTGF0ZW5jeUltcGFjdEFsYihcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBhbGI6IElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlciwgXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICAgIHN0YXRpc3RpYzogc3RyaW5nLFxuICAgIGtleXByZWZpeDogc3RyaW5nLFxuICAgIHBlcmlvZDogRHVyYXRpb24sXG4gICAgZXZhbHVhdGlvblBlcmlvZHM6IG51bWJlcixcbiAgICBkYXRhcG9pbnRzVG9BbGFybTogbnVtYmVyXG4gICk6IElBbGFybSB7XG4gICAgXG4gICAgLy8gQ3JlYXRlIGEgZmF1bHQgcmF0ZSBhbGFybSBmb3IgdGhlIEFMQiBpbiB0aGUgc3BlY2lmaWVkIEFaXG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAga2V5cHJlZml4ICsgJy1sYXRlbmN5LWFsYXJtJyxcbiAgICAgIHtcbiAgICAgICAgYWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArICctJyArIGFsYi5sb2FkQmFsYW5jZXJBcm4gKyAnLWxhdGVuY3knLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICAgIG1ldHJpYzogQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzLmdldFBlckFaTGF0ZW5jeU1ldHJpYyh7XG4gICAgICAgICAgYWxiOiBhbGIsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogYXZhaWxhYmlsaXR5Wm9uZSxcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQ6IGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItXCIgKyBhbGIubG9hZEJhbGFuY2VyQXJuICsgXCItdGFyZ2V0LWxhdGVuY3lcIixcbiAgICAgICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICAgICAgICBzdGF0aXN0aWM6IHN0YXRpc3RpY1xuICAgICAgICB9KSxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgIHRocmVzaG9sZDogdGhyZXNob2xkLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRVxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBpc0FaQW5PdXRsaWVyRm9yQXZhaWxhYmlsaXR5QWxiKFxuICAgIHNjb3BlOiBJQ29uc3RydWN0LFxuICAgIGFsYjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLCBcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lOiBzdHJpbmcsXG4gICAgdGhyZXNob2xkOiBudW1iZXIsXG4gICAga2V5cHJlZml4OiBzdHJpbmcsXG4gICAgcGVyaW9kOiBEdXJhdGlvbixcbiAgICBldmFsdWF0aW9uUGVyaW9kczogbnVtYmVyLFxuICAgIGRhdGFwb2ludHNUb0FsYXJtOiBudW1iZXJcbiAgKSA6IElBbGFybSB7XG5cbiAgICBsZXQgdXNpbmdNZXRyaWNzOiB7IFtrZXk6IHN0cmluZ106IElNZXRyaWMgfSA9IHt9O1xuICAgIGxldCBhek1ldHJpY0lkOiBzdHJpbmcgPSBcIlwiO1xuXG4gICAgYWxiLnZwYyEuYXZhaWxhYmlsaXR5Wm9uZXMuZm9yRWFjaCgoYXo6IHN0cmluZykgPT4ge1xuXG4gICAgICBsZXQgYXpGYXVsdENvdW50ID0gQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzLmdldFBlckFaQXZhaWxhYmlsaXR5TWV0cmljKFxuICAgICAgICBhbGIsXG4gICAgICAgIHtcbiAgICAgICAgICBtZXRyaWNUeXBlOiBBdmFpbGFiaWxpdHlNZXRyaWNUeXBlLkZBVUxUX0NPVU5ULFxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmU6IGF2YWlsYWJpbGl0eVpvbmUsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgcGVyaW9kOiBwZXJpb2QsXG4gICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiLVwiICsgYWxiLmxvYWRCYWxhbmNlckFybiArIFwiLWZhdWx0LWNvdW50XCIsXG4gICAgICAgICAga2V5cHJlZml4OiBrZXlwcmVmaXhcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAga2V5cHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcihrZXlwcmVmaXgpO1xuXG4gICAgICB1c2luZ01ldHJpY3NbYCR7a2V5cHJlZml4fTFgXSA9IGF6RmF1bHRDb3VudDtcblxuICAgICAgaWYgKGF6ID09IGF2YWlsYWJpbGl0eVpvbmUpIHtcbiAgICAgICAgYXpNZXRyaWNJZCA9IGAke2tleXByZWZpeH0xYDtcbiAgICAgIH1cblxuICAgICAga2V5cHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcihrZXlwcmVmaXgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLFxuICAgICAga2V5cHJlZml4ICsgJy1hdmFpbGFiaWxpdHktb3V0bGllci1hbGFybScsXG4gICAgICB7XG4gICAgICAgIGFsYXJtTmFtZTpcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgKyAnLScgKyBhbGIubG9hZEJhbGFuY2VyQXJuICsgJy1hdmFpbGFiaWxpdHktaW1wYWN0LW91dGxpZXInLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICAgIG1ldHJpYzogbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgICAgICBleHByZXNzaW9uOiBgJHthek1ldHJpY0lkIX0vKCR7T2JqZWN0LmtleXModXNpbmdNZXRyaWNzKS5qb2luKFwiK1wiKX0pYCxcbiAgICAgICAgICB1c2luZ01ldHJpY3M6IHVzaW5nTWV0cmljcyxcbiAgICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJy0nICsgYWxiLmxvYWRCYWxhbmNlckFybiArICctcGVyY2VudC1vZi1mYXVsdHMnLFxuICAgICAgICAgIHBlcmlvZDogcGVyaW9kLFxuICAgICAgICB9KSxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgIHRocmVzaG9sZDogdGhyZXNob2xkLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRVxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBpc0FaQW5PdXRsaWVyRm9yTGF0ZW5jeUFsYihcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBhbGI6IElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlciwgXG4gICAgYWxnb3JpdGhtOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckxhdGVuY3lPdXRsaWVyQ2FsY3VsYXRpb24sXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nLFxuICAgIHN0YXRpc3RpYzogc3RyaW5nLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICAgIHBlcmlvZDogRHVyYXRpb24sXG4gICAgZXZhbHVhdGlvblBlcmlvZHM6IG51bWJlcixcbiAgICBkYXRhcG9pbnRzVG9BbGFybTogbnVtYmVyLFxuICAgIGtleXByZWZpeDogc3RyaW5nXG4gICkgOiBJQWxhcm0ge1xuXG4gICAgbGV0IHVzaW5nTWV0cmljczogeyBba2V5OiBzdHJpbmddOiBJTWV0cmljIH0gPSB7fTtcbiAgICBsZXQgYXpNZXRyaWNJZDogc3RyaW5nID0gXCJcIjtcblxuICAgIHN3aXRjaCAoYWxnb3JpdGhtKVxuICAgIHtcbiAgICAgIGNhc2UgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJMYXRlbmN5T3V0bGllckNhbGN1bGF0aW9uLlpfU0NPUkU6XG4gICAgICBkZWZhdWx0OlxuXG4gICAgICAgIGFsYi52cGMhLmF2YWlsYWJpbGl0eVpvbmVzLmZvckVhY2goKGF6OiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcblxuICAgICAgICAgIC8vIFRhcmdldCByZXNwb25zZSB0aW1lXG4gICAgICAgICAgbGV0IHRhcmdldFJlc3BvbnNlVGltZTogSU1ldHJpYyA9IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcy5nZXRQZXJBWkxhdGVuY3lNZXRyaWMoe1xuICAgICAgICAgICAgYWxiOiBhbGIsXG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiBheixcbiAgICAgICAgICAgIGxhYmVsOiBheiArIFwiLXRhcmdldC1yZXNwb25zZS10aW1lXCIsXG4gICAgICAgICAgICBzdGF0aXN0aWM6IHN0YXRpc3RpYyxcbiAgICAgICAgICAgIHBlcmlvZDogcGVyaW9kXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoYXogPT0gYXZhaWxhYmlsaXR5Wm9uZSkgeyAgICAgICBcbiAgICAgICAgICAgIGF6TWV0cmljSWQgPSBgYSR7aW5kZXh9YFxuICAgICAgICAgICAgdXNpbmdNZXRyaWNzW2BhJHtpbmRleH1gXSA9IHRhcmdldFJlc3BvbnNlVGltZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB1c2luZ01ldHJpY3NbYGIke2luZGV4fWBdID0gdGFyZ2V0UmVzcG9uc2VUaW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgICAgICBzY29wZSxcbiAgICAgICAgICBrZXlwcmVmaXggKyBcIi1sYXRlbmN5LW91dGxpZXItYWxhcm1cIixcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhbGFybU5hbWU6XG4gICAgICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArICctJyArIGFsYi5sb2FkQmFsYW5jZXJBcm4gKyAnLWxhdGVuY3ktaW1wYWN0LW91dGxpZXInLFxuICAgICAgICAgICAgYWN0aW9uc0VuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgICAgbWV0cmljOiBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgICAgICAgICBleHByZXNzaW9uOiBgKCR7YXpNZXRyaWNJZCF9IC0gQVZHKE1FVFJJQ1MoXCJiXCIpKSkgLyBBVkcoU1REREVWKE1FVFJJQ1MoXCJiXCIpKSlgLFxuICAgICAgICAgICAgICB1c2luZ01ldHJpY3M6IHVzaW5nTWV0cmljcyxcbiAgICAgICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICctJyArIGFsYi5sb2FkQmFsYW5jZXJBcm4gKyAnLWxhdGVuY3ktei1zY29yZScsXG4gICAgICAgICAgICAgIHBlcmlvZDogcGVyaW9kLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBldmFsdWF0aW9uUGVyaW9kczogZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgICAgICB0aHJlc2hvbGQ6IHRocmVzaG9sZCxcbiAgICAgICAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIGNhc2UgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJMYXRlbmN5T3V0bGllckNhbGN1bGF0aW9uLlNUQVRJQzpcbiAgICAgICAgXG4gICAgICAgIGFsYi52cGMhLmF2YWlsYWJpbGl0eVpvbmVzLmZvckVhY2goKGF6OiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAvLyBUYXJnZXQgcmVzcG9uc2UgdGltZVxuICAgICAgICAgIGxldCB0YXJnZXRSZXNwb25zZVRpbWU6IElNZXRyaWMgPSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY3MuZ2V0UGVyQVpMYXRlbmN5TWV0cmljKHtcbiAgICAgICAgICAgIGFsYjogYWxiLFxuICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogYXosXG4gICAgICAgICAgICBsYWJlbDogYXogKyBcIi10YXJnZXQtcmVzcG9uc2UtdGltZVwiLFxuICAgICAgICAgICAgc3RhdGlzdGljOiBgVEMoJHt0aHJlc2hvbGR9OilgLFxuICAgICAgICAgICAgcGVyaW9kOiBwZXJpb2RcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChheiA9PSBhdmFpbGFiaWxpdHlab25lKSB7ICAgICAgIFxuICAgICAgICAgICAgYXpNZXRyaWNJZCA9IGBhJHtpbmRleH1gXG4gICAgICAgICAgICB1c2luZ01ldHJpY3NbYGEke2luZGV4fWBdID0gdGFyZ2V0UmVzcG9uc2VUaW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHVzaW5nTWV0cmljc1tgYiR7aW5kZXh9YF0gPSB0YXJnZXRSZXNwb25zZVRpbWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBuZXcgQWxhcm0oXG4gICAgICAgICAgc2NvcGUsXG4gICAgICAgICAga2V5cHJlZml4ICsgXCItbGF0ZW5jeS1vdXRsaWVyLWFsYXJtXCIsXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWxhcm1OYW1lOlxuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQgKyAnLScgKyBhbGIubG9hZEJhbGFuY2VyQXJuICsgJy1sYXRlbmN5LWltcGFjdC1vdXRsaWVyJyxcbiAgICAgICAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZSxcbiAgICAgICAgICAgIG1ldHJpYzogbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgICAgICAgICAgZXhwcmVzc2lvbjogYCR7YXpNZXRyaWNJZH0vKCR7T2JqZWN0LmtleXModXNpbmdNZXRyaWNzKS5qb2luKFwiK1wiKX0pYCxcbiAgICAgICAgICAgICAgdXNpbmdNZXRyaWNzOiB1c2luZ01ldHJpY3MsXG4gICAgICAgICAgICAgIGxhYmVsOiBhdmFpbGFiaWxpdHlab25lSWQgKyAnLScgKyBhbGIubG9hZEJhbGFuY2VyQXJuICsgJy1sYXRlbmN5LXN0YXRpYycsXG4gICAgICAgICAgICAgIHBlcmlvZDogcGVyaW9kLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBldmFsdWF0aW9uUGVyaW9kczogZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgICAgICB0aHJlc2hvbGQ6IC42NixcbiAgICAgICAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBUcmVhdE1pc3NpbmdEYXRhLklHTk9SRVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRvQWxiTWV0cmljcyhcbiAgICBwcm9wczogQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wc1xuICApIDogeyBba2V5OiBzdHJpbmddOiBJQWxhcm0gfSB7XG5cbiAgICAvLyBDcmVhdGUgaW1wYWN0IGFsYXJtcyBwZXIgQVosIHdpdGggZWFjaCBBTEIgcHJvdmlkaW5nXG4gICAgLy8gYW4gYWxhcm0gZm9yIGl0cyBBWnNcbiAgICBsZXQgcGVyQVpJbXBhY3RBbGFybXM6IHsgW2tleTogc3RyaW5nXTogSUFsYXJtW10gfSA9IHt9O1xuXG4gICAgbGV0IGtleVByZWZpeDogc3RyaW5nID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcigpO1xuXG4gICAgLy8gSXRlcmF0ZSBlYWNoIEFMQlxuICAgIHRoaXMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJzIS5mb3JFYWNoKChhbGIpID0+IHtcbiAgICAgIFxuICAgICAgLy8gSXRlcmF0ZSBlYWNoIEFaIGluIHRoZSBWUENcbiAgICAgIGFsYi52cGM/LmF2YWlsYWJpbGl0eVpvbmVzLmZvckVhY2goKGF6KSA9PiB7XG5cbiAgICAgICAgaWYgKCEoYXogaW4gcGVyQVpJbXBhY3RBbGFybXMpKSB7XG4gICAgICAgICAgcGVyQVpJbXBhY3RBbGFybXNbYXpdID0gW107XG4gICAgICAgIH1cbiAgICAgXG4gICAgICAgIC8vIEdldCBBWiBsZXR0ZXJcbiAgICAgICAgbGV0IGF6TGV0dGVyID0gYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpO1xuXG4gICAgICAgIC8vIE1hcCBsZXR0ZXIgdG8gQVogSURcbiAgICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID1cbiAgICAgICAgICB0aGlzLl9hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihhekxldHRlcik7XG5cbiAgICAgICAgLy8gSXMgdGhlcmUgYXZhaWxhYmlsaXR5IGltcGFjdCBpbiB0aGlzIEFaP1xuICAgICAgICBsZXQgYXZhaWxhYmlsaXR5SW1wYWN0OiBJQWxhcm0gPSBCYXNpY1NlcnZpY2VNdWx0aUFaT2JzZXJ2YWJpbGl0eS5pc1RoZXJlQW5BWkF2YWlsYWJpbGl0eUltcGFjdEFsYihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGFsYixcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgYXosXG4gICAgICAgICAgcHJvcHMuZmF1bHRDb3VudFBlcmNlbnRhZ2VUaHJlc2hvbGQgPyBwcm9wcy5mYXVsdENvdW50UGVyY2VudGFnZVRocmVzaG9sZCA6IDAuMDUsXG4gICAgICAgICAga2V5UHJlZml4LFxuICAgICAgICAgIHByb3BzLnBlcmlvZCA/IHByb3BzLnBlcmlvZCA6IER1cmF0aW9uLm1pbnV0ZXMoMSksXG4gICAgICAgICAgcHJvcHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgcHJvcHMuZGF0YXBvaW50c1RvQWxhcm1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBJcyB0aGVyZSBsYXRlbmN5IGltcGFjdCBpbiB0aGlzIEFaP1xuICAgICAgICBsZXQgbGF0ZW5jeUltcGFjdDogSUFsYXJtID0gQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuaXNUaGVyZUFaTGF0ZW5jeUltcGFjdEFsYihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGFsYixcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgYXosXG4gICAgICAgICAgcHJvcHMubGF0ZW5jeVRocmVzaG9sZCxcbiAgICAgICAgICBwcm9wcy5sYXRlbmN5U3RhdGlzdGljLFxuICAgICAgICAgIGtleVByZWZpeCxcbiAgICAgICAgICBwcm9wcy5wZXJpb2QgPyBwcm9wcy5wZXJpb2QgOiBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICAgIHByb3BzLmRhdGFwb2ludHNUb0FsYXJtXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gSXMgdGhlIEFaIGFuIG91dGxpZXIgZm9yIGZhdWx0c1xuICAgICAgICBsZXQgYXZhaWxhYmlsaXR5T3V0bGllciA9IEJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5LmlzQVpBbk91dGxpZXJGb3JBdmFpbGFiaWxpdHlBbGIoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBhbGIsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICAgIGF6LFxuICAgICAgICAgIHByb3BzLmZhdWx0Q291bnRQZXJjZW50YWdlVGhyZXNob2xkID8gcHJvcHMuZmF1bHRDb3VudFBlcmNlbnRhZ2VUaHJlc2hvbGQgOiAwLjA1LFxuICAgICAgICAgIGtleVByZWZpeCxcbiAgICAgICAgICBwcm9wcy5wZXJpb2QgPyBwcm9wcy5wZXJpb2QgOiBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICAgIHByb3BzLmRhdGFwb2ludHNUb0FsYXJtXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gSXMgdGhlIEFaIGFuIG91dGxpZXIgZm9yIGxhdGVuY3lcbiAgICAgICAgbGV0IGxhdGVuY3lPdXRsaWVyID0gQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuaXNBWkFuT3V0bGllckZvckxhdGVuY3lBbGIoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBhbGIsXG4gICAgICAgICAgcHJvcHMubGF0ZW5jeU91dGxpZXJDYWxjdWxhdGlvbiA/IHByb3BzLmxhdGVuY3lPdXRsaWVyQ2FsY3VsYXRpb24gOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckxhdGVuY3lPdXRsaWVyQ2FsY3VsYXRpb24uWl9TQ09SRSxcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgYXosXG4gICAgICAgICAgcHJvcHMubGF0ZW5jeVN0YXRpc3RpYyxcbiAgICAgICAgICBwcm9wcy5sYXRlbmN5T3V0bGllckNhbGN1bGF0aW9uID09IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTGF0ZW5jeU91dGxpZXJDYWxjdWxhdGlvbi5aX1NDT1JFID8gMyA6IHByb3BzLmxhdGVuY3lUaHJlc2hvbGQsXG4gICAgICAgICAgcHJvcHMucGVyaW9kID8gcHJvcHMucGVyaW9kIDogRHVyYXRpb24ubWludXRlcygxKSxcbiAgICAgICAgICBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyxcbiAgICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgICAgICBhekxldHRlclxuICAgICAgICApO1xuXG4gICAgICAgIC8vIEFsYXJtIGlmIHRoZSBBWiBzaG93cyBpbXBhY3QgYW5kIGlzIGFuIG91dGxpZXJcbiAgICAgICAgbGV0IGF6SW1wYWN0QWxhcm06IElBbGFybSA9IG5ldyBDb21wb3NpdGVBbGFybSh0aGlzLCBcbiAgICAgICAgICBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSkgKyAgXCItY29tcG9zaXRlLWltcGFjdC1hbGFybVwiLCBcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZihcbiAgICAgICAgICAgICAgQWxhcm1SdWxlLmFsbE9mKGF2YWlsYWJpbGl0eUltcGFjdCwgYXZhaWxhYmlsaXR5T3V0bGllciksIFxuICAgICAgICAgICAgICBBbGFybVJ1bGUuYWxsT2YobGF0ZW5jeUltcGFjdCwgbGF0ZW5jeU91dGxpZXIpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOiBcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItXCIgKyBcbiAgICAgICAgICAgICAgKGFsYiBhcyBJTG9hZEJhbGFuY2VyVjIgYXMgQmFzZUxvYWRCYWxhbmNlcikubG9hZEJhbGFuY2VyTmFtZSArIFxuICAgICAgICAgICAgICBcIi1sYXRlbmN5LW9yLWF2YWlsYWJpbGl0eS1pbXBhY3RcIixcbiAgICAgICAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBBZGQgdGhpcyBBTEIncyBmYXVsdCByYXRlIGFsYXJtXG4gICAgICAgIHBlckFaSW1wYWN0QWxhcm1zW2F6XS5wdXNoKGF6SW1wYWN0QWxhcm0pO1xuXG4gICAgICAgIC8vIEdldCBuZXh0IHVuaXF1ZSBrZXlcbiAgICAgICAga2V5UHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcihrZXlQcmVmaXgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBsZXQgYXpDb21wb3NpdGVBbGFybXM6IHtba2V5OiBzdHJpbmddOiBJQWxhcm19ID0ge307XG5cbiAgICAvLyBJdGVyYXRlIEFacyBmb3IgdGhlIEFMQiBpbXBhY3QgYWxhcm1zIHNvIHdlIGNhbiBqb2luIHRoZW1cbiAgICAvLyBpbnRvIGEgc2luZ2xlIGNvbXBvc2l0ZSBhbGFybSBmb3IgZWFjaCBBWlxuICAgIE9iamVjdC5rZXlzKHBlckFaSW1wYWN0QWxhcm1zKS5mb3JFYWNoKChheikgPT4ge1xuICAgICAgbGV0IGF6TGV0dGVyID0gYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpO1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID0gdGhpcy5fYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoYXpMZXR0ZXIpO1xuXG4gICAgICBhekNvbXBvc2l0ZUFsYXJtc1thel0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXpMZXR0ZXIgKyBcIi1hbGItaW1wYWN0LWNvbXBvc2l0ZS1hbGFybVwiLCB7XG4gICAgICAgIGFsYXJtUnVsZTogQWxhcm1SdWxlLmFueU9mKC4uLnBlckFaSW1wYWN0QWxhcm1zW2F6XSksXG4gICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItYWxiLWltcGFjdC1jb21wb3NpdGUtYWxhcm1cIlxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXpDb21wb3NpdGVBbGFybXM7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBpc1RoZXJlQW5BWlBhY2tldExvc3NJbXBhY3ROQVRHVyhcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBuYXRnd3M6IENmbk5hdEdhdGV3YXlbXSwgXG4gICAgYXZhaWxhYmlsaXR5Wm9uZUlkOiBzdHJpbmcsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICAgIHBlcmlvZDogRHVyYXRpb24sXG4gICAgZXZhbHVhdGlvblBlcmlvZHM6IG51bWJlcixcbiAgICBkYXRhcG9pbnRzVG9BbGFybTogbnVtYmVyXG4gICkgOiBJQWxhcm0ge1xuICAgIFxuICAgIGxldCBrZXlwcmVmaXggPSBNZXRyaWNzSGVscGVyLm5leHRDaGFyKCk7XG5cbiAgICBsZXQgcGFja2V0RHJvcENvdW50TWV0cmljczoge1trZXk6IHN0cmluZ106IElNZXRyaWN9ID0ge307XG4gICAgbGV0IHBhY2tldHNJbkZyb21Tb3VyY2VNZXRyaWNzOiB7W2tleTogc3RyaW5nXTogSU1ldHJpY30gPSB7fTtcbiAgICBsZXQgcGFja2V0c0luRnJvbURlc3RpbmF0aW9uTWV0cmljczoge1trZXk6IHN0cmluZ106IElNZXRyaWN9ID0ge307XG4gICBcbiAgICBuYXRnd3MuZm9yRWFjaCgobmF0Z3c6IENmbk5hdEdhdGV3YXkpPT4ge1xuXG4gICAgICBwYWNrZXREcm9wQ291bnRNZXRyaWNzW2Ake2tleXByZWZpeH0xYF0gPSBuZXcgTWV0cmljKHtcbiAgICAgICAgbWV0cmljTmFtZTogJ1BhY2tldHNEcm9wQ291bnQnLFxuICAgICAgICBuYW1lc3BhY2U6ICdBV1MvTkFUR2F0ZXdheScsXG4gICAgICAgIHN0YXRpc3RpYzogU3RhdHMuU1VNLFxuICAgICAgICB1bml0OiBVbml0LkNPVU5ULFxuICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBwYWNrZXQgZHJvcHMnLFxuICAgICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgICAgTmF0R2F0ZXdheUlkOiBuYXRndy5hdHRyTmF0R2F0ZXdheUlkLFxuICAgICAgICB9LFxuICAgICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICAgIH0pO1xuICBcbiAgICAgIC8vIENhbGN1bGF0ZSBwYWNrZXRzIGluIGZyb20gc291cmNlXG4gICAgICBwYWNrZXRzSW5Gcm9tU291cmNlTWV0cmljc1tgJHtrZXlwcmVmaXh9MmBdID0gbmV3IE1ldHJpYyh7XG4gICAgICAgIG1ldHJpY05hbWU6ICdQYWNrZXRzSW5Gcm9tU291cmNlJyxcbiAgICAgICAgbmFtZXNwYWNlOiAnQVdTL05BVEdhdGV3YXknLFxuICAgICAgICBzdGF0aXN0aWM6IFN0YXRzLlNVTSxcbiAgICAgICAgdW5pdDogVW5pdC5DT1VOVCxcbiAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgcGFja2V0cyBpbiBmcm9tIHNvdXJjZScsXG4gICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICBOYXRHYXRld2F5SWQ6IG5hdGd3LmF0dHJOYXRHYXRld2F5SWQsXG4gICAgICAgIH0sXG4gICAgICAgIHBlcmlvZDogcGVyaW9kLFxuICAgICAgfSk7XG4gIFxuICAgICAgLy8gQ2FsY3VsYXRlIHBhY2tldHMgaW4gZnJvbSBkZXN0aW5hdGlvblxuICAgICAgcGFja2V0c0luRnJvbURlc3RpbmF0aW9uTWV0cmljc1tgJHtrZXlwcmVmaXh9M2BdID0gbmV3IE1ldHJpYyh7XG4gICAgICAgIG1ldHJpY05hbWU6ICdQYWNrZXRzSW5Gcm9tRGVzdGluYXRpb24nLFxuICAgICAgICBuYW1lc3BhY2U6ICdBV1MvTkFUR2F0ZXdheScsXG4gICAgICAgIHN0YXRpc3RpYzogU3RhdHMuU1VNLFxuICAgICAgICB1bml0OiBVbml0LkNPVU5ULFxuICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBwYWNrZXRzIGluIGZyb20gZGVzdGluYXRpb24nLFxuICAgICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgICAgTmF0R2F0ZXdheUlkOiBuYXRndy5hdHRyTmF0R2F0ZXdheUlkLFxuICAgICAgICB9LFxuICAgICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICAgIH0pO1xuXG4gICAgICBrZXlwcmVmaXggPSBNZXRyaWNzSGVscGVyLm5leHRDaGFyKGtleXByZWZpeCk7XG4gICAgfSk7XG5cbiAgICBsZXQgcGFja2V0RHJvcFRvdGFsOiBJTWV0cmljID0gbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgIGV4cHJlc3Npb246IE9iamVjdC5rZXlzKHBhY2tldERyb3BDb3VudE1ldHJpY3MpLmpvaW4oXCIrXCIpLFxuICAgICAgdXNpbmdNZXRyaWNzOiBwYWNrZXREcm9wQ291bnRNZXRyaWNzLFxuICAgICAgcGVyaW9kOiBwZXJpb2RcbiAgICB9KTtcblxuICAgIGxldCBwYWNrZXRzSW5Gcm9tU291cmNlVG90YWw6IElNZXRyaWMgPSBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgZXhwcmVzc2lvbjogT2JqZWN0LmtleXMocGFja2V0c0luRnJvbVNvdXJjZU1ldHJpY3MpLmpvaW4oXCIrXCIpLFxuICAgICAgdXNpbmdNZXRyaWNzOiBwYWNrZXRzSW5Gcm9tU291cmNlTWV0cmljcyxcbiAgICAgIHBlcmlvZDogcGVyaW9kXG4gICAgfSk7XG5cbiAgICBsZXQgcGFja2V0c0luRnJvbURlc3RpbmF0aW9uVG90YWw6IElNZXRyaWMgPSBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgZXhwcmVzc2lvbjogT2JqZWN0LmtleXMocGFja2V0c0luRnJvbURlc3RpbmF0aW9uTWV0cmljcykuam9pbihcIitcIiksXG4gICAgICB1c2luZ01ldHJpY3M6IHBhY2tldHNJbkZyb21EZXN0aW5hdGlvbk1ldHJpY3MsXG4gICAgICBwZXJpb2Q6IHBlcmlvZFxuICAgIH0pO1xuICAgIFxuICAgIGxldCB1c2luZ01ldHJpY3M6IHsgW2tleTogc3RyaW5nXTogSU1ldHJpYyB9ID0ge307XG4gICAgdXNpbmdNZXRyaWNzW2Ake2tleXByZWZpeH0xYF0gPSBwYWNrZXREcm9wVG90YWw7XG4gICAgdXNpbmdNZXRyaWNzW2Ake2tleXByZWZpeH0yYF0gPSBwYWNrZXRzSW5Gcm9tU291cmNlVG90YWw7XG4gICAgdXNpbmdNZXRyaWNzW2Ake2tleXByZWZpeH0zYF0gPSBwYWNrZXRzSW5Gcm9tRGVzdGluYXRpb25Ub3RhbDtcblxuICAgIC8vIENhbGN1bGF0ZSBhIHBlcmNlbnRhZ2Ugb2YgZHJvcHBlZCBwYWNrZXRzIGZvciB0aGUgTkFUIEdXXG4gICAgbGV0IHBhY2tldERyb3BQZXJjZW50YWdlOiBJTWV0cmljID0gbmV3IE1hdGhFeHByZXNzaW9uKHtcbiAgICAgIGV4cHJlc3Npb246IGAoJHtrZXlwcmVmaXh9MSAvICgke2tleXByZWZpeH0yICsgJHtrZXlwcmVmaXh9MykpYCxcbiAgICAgIHVzaW5nTWV0cmljczogdXNpbmdNZXRyaWNzLFxuICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgcGFja2V0IGRyb3AgcGVyY2VudGFnZScsXG4gICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBhbiBhbGFybSBmb3IgdGhpcyBOQVQgR1cgaWYgcGFja2V0IGRyb3BzIGV4Y2VlZCB0aGUgc3BlY2lmaWVkIHRocmVzaG9sZFxuICAgIHJldHVybiBuZXcgQWxhcm0oXG4gICAgICBzY29wZSxcbiAgICAgIGF2YWlsYWJpbGl0eVpvbmUuc3Vic3RyaW5nKGF2YWlsYWJpbGl0eVpvbmUubGVuZ3RoIC0gMSkgKyBcIi1wYWNrZXQtZHJvcC1pbXBhY3QtYWxhcm1cIixcbiAgICAgIHtcbiAgICAgICAgYWxhcm1OYW1lOlxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCArXG4gICAgICAgICAgJy1wYWNrZXQtZHJvcC1pbXBhY3QnLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogZmFsc2UsXG4gICAgICAgIG1ldHJpYzogcGFja2V0RHJvcFBlcmNlbnRhZ2UsXG4gICAgICAgIHRocmVzaG9sZDogdGhyZXNob2xkLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICBldmFsdWF0aW9uUGVyaW9kczogZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgIGRhdGFwb2ludHNUb0FsYXJtOiBkYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogVHJlYXRNaXNzaW5nRGF0YS5JR05PUkVcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaXNBWkFuT3V0bGllckZvclBhY2tldExvc3NOQVRHVyhcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBuYXRnd3M6IHtba2V5OiBzdHJpbmddOiBDZm5OYXRHYXRld2F5W119LCBcbiAgICBhdmFpbGFiaWxpdHlab25lSWQ6IHN0cmluZyxcbiAgICBhdmFpbGFiaWxpdHlab25lOiBzdHJpbmcsXG4gICAgdGhyZXNob2xkOiBudW1iZXIsXG4gICAgcGVyaW9kOiBEdXJhdGlvbixcbiAgICBldmFsdWF0aW9uUGVyaW9kczogbnVtYmVyLFxuICAgIGRhdGFwb2ludHNUb0FsYXJtOiBudW1iZXJcbiAgKSA6IElBbGFybSB7XG5cbiAgICBsZXQga2V5cHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcigpO1xuICAgIGxldCBhelBhY2tldERyb3BDb3VudE1ldHJpY3M6IHtba2V5OiBzdHJpbmddOiBJTWV0cmljfSA9IHt9O1xuICAgIGxldCBhektleTogc3RyaW5nID0gXCJcIjtcblxuICAgIE9iamVjdC5rZXlzKG5hdGd3cykuZm9yRWFjaCgoYXo6IHN0cmluZykgPT4ge1xuICAgICAgXG4gICAgICBsZXQgcGFja2V0RHJvcENvdW50TWV0cmljczoge1trZXk6IHN0cmluZ106IElNZXRyaWN9ID0ge307XG5cbiAgICAgIFxuXG4gICAgICBuYXRnd3NbYXpdLmZvckVhY2goKG5hdGd3OiBDZm5OYXRHYXRld2F5LCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgIHBhY2tldERyb3BDb3VudE1ldHJpY3NbYCR7a2V5cHJlZml4fSR7aW5kZXh9YF0gPSBuZXcgTWV0cmljKHtcbiAgICAgICAgICBtZXRyaWNOYW1lOiAnUGFja2V0c0Ryb3BDb3VudCcsXG4gICAgICAgICAgbmFtZXNwYWNlOiAnQVdTL05BVEdhdGV3YXknLFxuICAgICAgICAgIHN0YXRpc3RpYzogU3RhdHMuU1VNLFxuICAgICAgICAgIHVuaXQ6IFVuaXQuQ09VTlQsXG4gICAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArICcgcGFja2V0IGRyb3BzJyxcbiAgICAgICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgICAgICBOYXRHYXRld2F5SWQ6IG5hdGd3LmF0dHJOYXRHYXRld2F5SWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwZXJpb2Q6IHBlcmlvZCxcbiAgICAgICAgfSk7XG4gICAgICAgIGtleXByZWZpeCA9IE1ldHJpY3NIZWxwZXIubmV4dENoYXIoa2V5cHJlZml4KTtcbiAgICAgIH0pO1xuXG4gICAgICBhelBhY2tldERyb3BDb3VudE1ldHJpY3NbYCR7a2V5cHJlZml4fSR7bmF0Z3dzW2F6XS5sZW5ndGh9YF0gPSBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgICBleHByZXNzaW9uOiBPYmplY3Qua2V5cyhwYWNrZXREcm9wQ291bnRNZXRyaWNzKS5qb2luKFwiK1wiKSxcbiAgICAgICAgdXNpbmdNZXRyaWNzOiBwYWNrZXREcm9wQ291bnRNZXRyaWNzLFxuICAgICAgICBwZXJpb2Q6IHBlcmlvZFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChheiA9PSBhdmFpbGFiaWxpdHlab25lKSB7XG4gICAgICAgIGF6S2V5ID0gYCR7a2V5cHJlZml4fSR7bmF0Z3dzW2F6XS5sZW5ndGh9YDtcbiAgICAgIH1cblxuICAgICAga2V5cHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcihrZXlwcmVmaXgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBBbGFybShcbiAgICAgIHNjb3BlLCBcbiAgICAgIGF2YWlsYWJpbGl0eVpvbmUuc3Vic3RyaW5nKGF2YWlsYWJpbGl0eVpvbmUubGVuZ3RoIC0gMSkgKyBcIi1wYWNrZXQtbG9zcy1vdXRsaWVyXCIsIFxuICAgICAge1xuICAgICAgICAgbWV0cmljOiBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgICAgICAgZXhwcmVzc2lvbjogYCR7YXpLZXl9IC8gKCR7T2JqZWN0LmtleXMoYXpQYWNrZXREcm9wQ291bnRNZXRyaWNzKS5qb2luKFwiK1wiKX0pYCxcbiAgICAgICAgICAgIHVzaW5nTWV0cmljczogYXpQYWNrZXREcm9wQ291bnRNZXRyaWNzLFxuICAgICAgICAgICAgcGVyaW9kOiBwZXJpb2RcbiAgICAgICAgIH0pLFxuICAgICAgICAgdGhyZXNob2xkOiB0aHJlc2hvbGQsXG4gICAgICAgICBldmFsdWF0aW9uUGVyaW9kczogZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogVHJlYXRNaXNzaW5nRGF0YS5JR05PUkVcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBkb05hdEdhdGV3YXlNZXRyaWNzKFxuICAgIHByb3BzOiBCYXNpY1NlcnZpY2VNdWx0aUFaT2JzZXJ2YWJpbGl0eVByb3BzXG4gICk6IHtba2V5OiBzdHJpbmddOiBJQWxhcm19IHtcblxuICAgIC8vIENvbGxlY3QgYWxhcm1zIGZvciBwYWNrZXQgZHJvcHMgZXhjZWVkaW5nIGEgdGhyZXNob2xkIHBlciBOQVQgR1dcbiAgICBsZXQgcGFja2V0TG9zc1BlckFaQWxhcm1zOiB7IFtrZXk6IHN0cmluZ106IElBbGFybSB9ID0ge307XG5cbiAgICAvLyBGb3IgZWFjaCBBWiwgY3JlYXRlIG1ldHJpY3MgZm9yIGVhY2ggTkFUIEdXXG4gICAgT2JqZWN0LmtleXModGhpcy5uYXRHYXRld2F5cyEpLmZvckVhY2goKGF6OiBzdHJpbmcpID0+IHtcblxuICAgICAgbGV0IGF6TGV0dGVyOiBzdHJpbmcgPSBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSk7XG4gICAgICBsZXQgYXZhaWxhYmlsaXR5Wm9uZUlkID1cbiAgICAgICAgdGhpcy5fYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoYXpMZXR0ZXIpO1xuXG4gICAgICAvLyBJcyB0aGVyZSBwYWNrZXQgbG9zcyBpbXBhY3Q/XG4gICAgICBsZXQgcGFja2V0TG9zc0ltcGFjdDogSUFsYXJtID0gQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuaXNUaGVyZUFuQVpQYWNrZXRMb3NzSW1wYWN0TkFUR1coXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHRoaXMubmF0R2F0ZXdheXMhW2F6XSxcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICBheixcbiAgICAgICAgcHJvcHMucGFja2V0TG9zc0ltcGFjdFBlcmNlbnRhZ2VUaHJlc2hvbGQgPyBwcm9wcy5wYWNrZXRMb3NzSW1wYWN0UGVyY2VudGFnZVRocmVzaG9sZCA6IDAuMDEsXG4gICAgICAgIHByb3BzLnBlcmlvZCA/IHByb3BzLnBlcmlvZCA6IER1cmF0aW9uLm1pbnV0ZXMoMSksXG4gICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybVxuICAgICAgKTtcbiAgICAgIC8vIElzIHRoaXMgQVogYW4gb3V0bGllciBmb3IgdGhpcyBOQVRHVz9cbiAgICAgIGxldCBwYWNrZXRMb3NzT3V0bGllcjogSUFsYXJtID0gQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuaXNBWkFuT3V0bGllckZvclBhY2tldExvc3NOQVRHVyhcbiAgICAgICAgdGhpcyxcbiAgICAgICAgdGhpcy5uYXRHYXRld2F5cyEsXG4gICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgYXosXG4gICAgICAgIDAuNjYsXG4gICAgICAgIHByb3BzLnBlcmlvZCA/IHByb3BzLnBlcmlvZCA6IER1cmF0aW9uLm1pbnV0ZXMoMSksXG4gICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybVxuICAgICAgKTtcbiAgICAgIHBhY2tldExvc3NQZXJBWkFsYXJtc1thel0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpICsgXCItcGFja2V0LWxvc3MtY29tcG9zaXRlLWFsYXJtXCIsIHtcbiAgICAgICAgYWxhcm1SdWxlOiBBbGFybVJ1bGUuYWxsT2YocGFja2V0TG9zc0ltcGFjdCwgcGFja2V0TG9zc091dGxpZXIpLFxuICAgICAgICBjb21wb3NpdGVBbGFybU5hbWU6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiLXBhY2tldC1sb3NzLWNvbXBvc2l0ZS1hbGFybVwiXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiBwYWNrZXRMb3NzUGVyQVpBbGFybXM7XG4gIH1cblxuICBwcml2YXRlIGdldFRvdGFsUGFja2V0RHJvcHNQZXJab25lKFxuICAgIG5hdGd3czoge1trZXk6IHN0cmluZ106IENmbk5hdEdhdGV3YXlbXX0sXG4gICAgcGVyaW9kOiBEdXJhdGlvblxuICApIDoge1trZXk6IHN0cmluZ106IElNZXRyaWN9XG4gIHtcbiAgICBsZXQgZHJvcHNQZXJab25lOiB7W2tleTogc3RyaW5nXTogSU1ldHJpY30gPSB7fTtcbiAgICBsZXQgbWV0cmljc1BlckFaOiB7W2tleTogc3RyaW5nXTogSU1ldHJpY1tdfSA9IHt9O1xuICAgIGxldCBrZXlwcmVmaXg6IHN0cmluZyA9IE1ldHJpY3NIZWxwZXIubmV4dENoYXIoKTtcblxuICAgIE9iamVjdC5rZXlzKG5hdGd3cykuZm9yRWFjaCgoYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nKSA9PiB7XG5cbiAgICAgIGxldCBhekxldHRlciA9IGF2YWlsYWJpbGl0eVpvbmUuc3Vic3RyaW5nKGF2YWlsYWJpbGl0eVpvbmUubGVuZ3RoIC0gMSk7XG4gICAgICBsZXQgYXZhaWxhYmlsaXR5Wm9uZUlkID0gdGhpcy5fYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoYXpMZXR0ZXIpO1xuXG4gICAgICBpZiAoIShhdmFpbGFiaWxpdHlab25lIGluIG1ldHJpY3NQZXJBWikpIHtcbiAgICAgICAgbWV0cmljc1BlckFaW2F2YWlsYWJpbGl0eVpvbmVdID0gW107XG4gICAgICB9XG5cbiAgICAgIG5hdGd3c1thdmFpbGFiaWxpdHlab25lXS5mb3JFYWNoKChuYXRndzogQ2ZuTmF0R2F0ZXdheSkgPT4ge1xuXG4gICAgICAgIG1ldHJpY3NQZXJBWlthdmFpbGFiaWxpdHlab25lXS5wdXNoKG5ldyBNZXRyaWMoe1xuICAgICAgICAgIG1ldHJpY05hbWU6ICdQYWNrZXRzRHJvcENvdW50JyxcbiAgICAgICAgICBuYW1lc3BhY2U6ICdBV1MvTkFUR2F0ZXdheScsXG4gICAgICAgICAgc3RhdGlzdGljOiBTdGF0cy5TVU0sXG4gICAgICAgICAgdW5pdDogVW5pdC5DT1VOVCxcbiAgICAgICAgICBsYWJlbDogYXZhaWxhYmlsaXR5Wm9uZUlkICsgJyBwYWNrZXQgZHJvcHMnLFxuICAgICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICAgIE5hdEdhdGV3YXlJZDogbmF0Z3cuYXR0ck5hdEdhdGV3YXlJZCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBlcmlvZDogcGVyaW9kLFxuICAgICAgICB9KSk7XG4gICAgICB9KTsgICBcbiAgICB9KTtcblxuICAgIE9iamVjdC5rZXlzKG1ldHJpY3NQZXJBWikuZm9yRWFjaCgoYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nKSA9PiB7XG4gICAgICBsZXQgYXpMZXR0ZXIgPSBhdmFpbGFiaWxpdHlab25lLnN1YnN0cmluZyhhdmFpbGFiaWxpdHlab25lLmxlbmd0aCAtIDEpO1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZCA9IHRoaXMuX2F6TWFwcGVyLmF2YWlsYWJpbGl0eVpvbmVJZEZyb21BdmFpbGFiaWxpdHlab25lTGV0dGVyKGF6TGV0dGVyKTtcblxuICAgICAgbGV0IHVzaW5nTWV0cmljczoge1trZXk6IHN0cmluZ106IElNZXRyaWN9ID0ge307XG5cbiAgICAgIG1ldHJpY3NQZXJBWlthdmFpbGFiaWxpdHlab25lXS5mb3JFYWNoKChtZXRyaWM6IElNZXRyaWMpID0+IHtcbiAgICAgICAgdXNpbmdNZXRyaWNzW2Ake2tleXByZWZpeH0xYF0gPSBtZXRyaWM7XG4gICAgICAgIGtleXByZWZpeCA9IE1ldHJpY3NIZWxwZXIubmV4dENoYXIoa2V5cHJlZml4KTtcbiAgICAgIH0pO1xuXG4gICAgICBkcm9wc1BlclpvbmVbYXZhaWxhYmlsaXR5Wm9uZV0gPSBuZXcgTWF0aEV4cHJlc3Npb24oe1xuICAgICAgICBleHByZXNzaW9uOiBPYmplY3Qua2V5cyh1c2luZ01ldHJpY3MpLmpvaW4oXCIrXCIpLFxuICAgICAgICB1c2luZ01ldHJpY3M6IHVzaW5nTWV0cmljcyxcbiAgICAgICAgbGFiZWw6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiIHRvdGFsIHBhY2tldCBkcm9wc1wiLFxuICAgICAgICBwZXJpb2Q6IHBlcmlvZFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZHJvcHNQZXJab25lO1xuICB9XG59XG4iXX0=
219
+ BasicServiceMultiAZObservability[_a] = { fqn: "@cdklabs/multi-az-observability.BasicServiceMultiAZObservability", version: "0.0.1-alpha.60" };
220
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmFzaWNfb2JzZXJ2YWJpbGl0eS9CYXNpY1NlcnZpY2VNdWx0aUFaT2JzZXJ2YWJpbGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsNkNBQXVDO0FBQ3ZDLCtEQUtvQztBQU9wQywyQ0FBdUM7QUFHdkMsK0VBQTRFO0FBRTVFLG1FQUFnRTtBQUNoRSw4RkFBMkY7QUFDM0YsOERBQTJEO0FBQzNELHdJQUFxSTtBQUNySSxvRUFBaUU7QUFDakUsa0pBQStJO0FBQy9JLGdHQUE2RjtBQUU3Rjs7O0dBR0c7QUFDSCxNQUFhLGdDQUNYLFNBQVEsc0JBQVM7SUE4Q2pCLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQTRDO1FBRTVDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQ3RFLE1BQU0sSUFBSSxLQUFLLENBQUMsOEZBQThGLENBQUMsQ0FBQztRQUNsSCxDQUFDO1FBRUQsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNyQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsS0FBSyxDQUFDLDRCQUE0QixFQUFFLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2xJLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLGVBQWUsRUFBRSxXQUFXLENBQUM7UUFFdEQsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLEVBQUUsQ0FBQztRQUM3QyxJQUFJLENBQUMs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QkFBYyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsOEJBQThCLEVBQUU7Z0JBQ3ZILFNBQVMsRUFBRSwwQkFBUyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQztnQkFDL0Qsa0JBQWtCLEVBQUUsa0JBQWtCLEdBQUcsOEJBQThCO2FBQ3hFLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxxQkFBcUIsQ0FBQztJQUMvQixDQUFDOztBQXRYSCw0RUF1WEMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgQWxhcm1SdWxlLFxuICBDb21wb3NpdGVBbGFybSxcbiAgRGFzaGJvYXJkLFxuICBJQWxhcm1cbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0IHsgQ2ZuTmF0R2F0ZXdheSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHtcbiAgQmFzZUxvYWRCYWxhbmNlcixcbiAgSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICBJTG9hZEJhbGFuY2VyVjIsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgSUJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5IH0gZnJvbSAnLi9JQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHknO1xuaW1wb3J0IHsgQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wcyB9IGZyb20gJy4vcHJvcHMvQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wcyc7XG5pbXBvcnQgeyBBdmFpbGFiaWxpdHlab25lTWFwcGVyIH0gZnJvbSAnLi4vYXptYXBwZXIvQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcic7XG5pbXBvcnQgeyBJQXZhaWxhYmlsaXR5Wm9uZU1hcHBlciB9IGZyb20gJy4uL2F6bWFwcGVyL0lBdmFpbGFiaWxpdHlab25lTWFwcGVyJztcbmltcG9ydCB7IEJhc2ljU2VydmljZURhc2hib2FyZCB9IGZyb20gJy4vQmFzaWNTZXJ2aWNlRGFzaGJvYXJkJztcbmltcG9ydCB7IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcyB9IGZyb20gJy4uL21ldHJpY3MvQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJNZXRyaWNzJztcbmltcG9ydCB7IE1ldHJpY3NIZWxwZXIgfSBmcm9tICcuLi91dGlsaXRpZXMvTWV0cmljc0hlbHBlcic7XG5pbXBvcnQgeyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckxhdGVuY3lPdXRsaWVyQWxnb3JpdGhtIH0gZnJvbSAnLi4vb3V0bGllci1kZXRlY3Rpb24vQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJMYXRlbmN5T3V0bGllckFsZ29yaXRobSc7XG5pbXBvcnQgeyBOYXRHYXRld2F5TWV0cmljcyB9IGZyb20gJy4uL21ldHJpY3MvTmF0R2F0ZXdheU1ldHJpY3MnO1xuaW1wb3J0IHsgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJBdmFpbGFiaWxpdHlPdXRsaWVyQWxnb3JpdGhtIH0gZnJvbSAnLi4vb3V0bGllci1kZXRlY3Rpb24vQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJBdmFpbGFiaWxpdHlPdXRsaWVyQWxnb3JpdGhtJztcbmltcG9ydCB7IFBhY2tldExvc3NPdXRsaWVyQWxnb3JpdGhtIH0gZnJvbSAnLi4vb3V0bGllci1kZXRlY3Rpb24vUGFja2V0TG9zc091dGxpZXJBbGdvcml0aG0nO1xuXG4vKipcbiAqIEJhc2ljIG9ic2VydmFiaWxpdHkgZm9yIGEgc2VydmljZSB1c2luZyBtZXRyaWNzIGZyb21cbiAqIEFMQnMgYW5kIE5BVCBHYXRld2F5c1xuICovXG5leHBvcnQgY2xhc3MgQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlcbiAgZXh0ZW5kcyBDb25zdHJ1Y3RcbiAgaW1wbGVtZW50cyBJQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHkge1xuICAvKipcbiAgICogVGhlIE5BVCBHYXRld2F5cyBiZWluZyB1c2VkIGluIHRoZSBzZXJ2aWNlLCBlYWNoIHNldCBvZiBOQVQgR2F0ZXdheXNcbiAgICogYXJlIGtleWVkIGJ5IHRoZWlyIEF2YWlsYWJpbGl0eSBab25lIElkXG4gICAqL1xuICBuYXRHYXRld2F5cz86IHsgW2tleTogc3RyaW5nXTogQ2ZuTmF0R2F0ZXdheVtdIH07XG5cbiAgLyoqXG4gICAqIFRoZSBhcHBsaWNhdGlvbiBsb2FkIGJhbGFuY2VycyBiZWluZyB1c2VkIGJ5IHRoZSBzZXJ2aWNlXG4gICAqL1xuICBhcHBsaWNhdGlvbkxvYWRCYWxhbmNlcnM/OiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJbXTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2VcbiAgICovXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhbGFybXMgaW5kaWNhdGluZyBpZiBhbiBBWiBpcyBhbiBvdXRsaWVyIGZvciBOQVQgR1dcbiAgICogcGFja2V0IGxvc3MgYW5kIGhhcyBpc29sYXRlZCBpbXBhY3RcbiAgICovXG4gIG5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcz86IHsgW2tleTogc3RyaW5nXTogSUFsYXJtIH07XG5cbiAgLyoqXG4gICAqIFRoZSBhbGFybXMgaW5kaWNhdGluZyBpZiBhbiBBWiBpcyBhbiBvdXRsaWVyIGZvciBBTEJcbiAgICogZmF1bHRzIGFuZCBoYXMgaXNvbGF0ZWQgaW1wYWN0XG4gICAqL1xuICBhbGJab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zPzogeyBba2V5OiBzdHJpbmddOiBJQWxhcm0gfTtcblxuICAvKipcbiAgICogVGhlIGFsYXJtcyBpbmRpY2F0aW5nIGlmIGFuIEFaIGhhcyBpc29sYXRlZCBpbXBhY3RcbiAgICogZnJvbSBlaXRoZXIgQUxCIG9yIE5BVCBHVyBtZXRyaWNzXG4gICAqL1xuICBhZ2dyZWdhdGVab25hbElzb2xhdGVkSW1wYWN0QWxhcm1zOiB7IFtrZXk6IHN0cmluZ106IElBbGFybSB9O1xuXG4gIC8qKlxuICAgKiBUaGUgZGFzaGJvYXJkIHRoYXQgaXMgb3B0aW9uYWxseSBjcmVhdGVkXG4gICAqL1xuICBkYXNoYm9hcmQ/OiBEYXNoYm9hcmQ7XG5cbiAgLyoqXG4gICAqIFRoZSBBWiBtYXBwZXIgcmVzb3VyY2VcbiAgICovXG4gIHByaXZhdGUgX2F6TWFwcGVyOiBJQXZhaWxhYmlsaXR5Wm9uZU1hcHBlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IEJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5UHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBpZiAoIShwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlclByb3BzKSAmJiAhKHByb3BzLm5hdEdhdGV3YXlQcm9wcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIllvdSBtdXN0IGRlZmluZSBlaXRoZXIgQUxCcyBvciBOQVQgR2F0ZXdheXMgZm9yIHRoaXMgc2VydmljZSBpbiBvcmRlciB0byBjcmVhdGUgYSBkYXNoYm9hcmQuXCIpO1xuICAgIH1cblxuICAgIC8vIEluaXRpYWxpemUgY2xhc3MgcHJvcGVydGllc1xuICAgIHRoaXMuc2VydmljZU5hbWUgPSBwcm9wcy5zZXJ2aWNlTmFtZTtcbiAgICB0aGlzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VycyA9IHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHM/LmFsYlRhcmdldEdyb3VwTWFwLm1hcChlbnRyeSA9PiBlbnRyeS5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlcik7XG4gICAgdGhpcy5uYXRHYXRld2F5cyA9IHByb3BzLm5hdEdhdGV3YXlQcm9wcz8ubmF0R2F0ZXdheXM7XG5cbiAgICB0aGlzLmFnZ3JlZ2F0ZVpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMgPSB7fTtcbiAgICB0aGlzLmFsYlpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMgPSB7fTtcbiAgICB0aGlzLm5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyA9IHt9O1xuXG4gICAgLy8gQ3JlYXRlIHRoZSBBWiBtYXBwZXIgcmVzb3VyY2UgdG8gdHJhbnNsYXRlIEFaIG5hbWVzIHRvIGlkc1xuICAgIHRoaXMuX2F6TWFwcGVyID0gbmV3IEF2YWlsYWJpbGl0eVpvbmVNYXBwZXIodGhpcywgJ2F2YWlsYWJpbGl0eS16b25lLW1hcHBlcicpO1xuXG4gICAgLy8gQ3JlYXRlIEFMQiBtZXRyaWNzIGFuZCBhbGFybXMgcGVyIEFaXG4gICAgaWYgKHRoaXMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJzKSB7XG4gICAgICB0aGlzLmFsYlpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMgPSB0aGlzLmNyZWF0ZUFsYlpvbmFsSW1wYWN0QWxhcm1zKHByb3BzKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgTkFUIEdhdGV3YXkgbWV0cmljcyBhbmQgYWxhcm1zIHBlciBBWlxuICAgIGlmICh0aGlzLm5hdEdhdGV3YXlzKSB7XG4gICAgICB0aGlzLm5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyA9IHRoaXMuY3JlYXRlTmF0R2F0ZXdheVpvbmFsSW1wYWN0QWxhcm1zKHByb3BzKTtcbiAgICB9XG5cbiAgICAvLyBMb29rIHRocm91Z2ggYWxsIG9mIHRoZSBwZXIgQVogQUxCIGFsYXJtcywgaWYgdGhlcmUncyBhbHNvIGEgTkFUIEdXIGFsYXJtXG4gICAgLy8gY3JlYXRlIGEgY29tcG9zaXRlIGFsYXJtIGlmIGVpdGhlciBvZiB0aGVtIHRyaWdnZXJcbiAgICBPYmplY3Qua2V5cyh0aGlzLmFsYlpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMpLmZvckVhY2goKGF6TGV0dGVyOiBzdHJpbmcpID0+IHtcbiAgICAgIGxldCBhdmFpbGFiaWxpdHlab25lSWQgPSB0aGlzLl9hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihhekxldHRlcik7XG4gICAgICBpZiAoYXpMZXR0ZXIgaW4gdGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMhKSB7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtc1thekxldHRlcl0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXpMZXR0ZXIgKyBcIi1pc29sYXRlZC1pbXBhY3QtYWxhcm1cIiwge1xuICAgICAgICAgIGFsYXJtUnVsZTogQWxhcm1SdWxlLmFueU9mKHRoaXMuYWxiWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyFbYXpMZXR0ZXJdLCB0aGlzLm5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyFbYXpMZXR0ZXJdKSxcbiAgICAgICAgICBjb21wb3NpdGVBbGFybU5hbWU6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiLWlzb2xhdGVkLWltcGFjdC1hbGFybVwiXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtc1thekxldHRlcl0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXpMZXR0ZXIgKyBcIi1pc29sYXRlZC1pbXBhY3QtYWxhcm1cIiwge1xuICAgICAgICAgIGFsYXJtUnVsZTogQWxhcm1SdWxlLmFueU9mKHRoaXMuYWxiWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyFbYXpMZXR0ZXJdKSxcbiAgICAgICAgICBjb21wb3NpdGVBbGFybU5hbWU6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiLWlzb2xhdGVkLWltcGFjdC1hbGFybVwiXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gTG9vayB0aHJvdWdoIGFsbCBvZiB0aGUgcGVyIEFaIE5BVCBHVyBhbGFybXMuIElmIHRoZXJlJ3MgYW4gQVogd2UgaGF2ZW4ndCBzZWVuIGluIHRoZSBBTEJcbiAgICAvLyBhbGFybXMgeWV0LCB0aGVuIGl0IHdpbGwganVzdCBiZSBhIE5BVCBHVyBhbGFybSB0aGF0IHdlJ2xsIHR1cm4gaW50byB0aGUgc2FtZSBraW5kIG9mXG4gICAgLy8gY29tcG9zaXRlIGFsYXJtXG4gICAgT2JqZWN0LmtleXModGhpcy5uYXRHV1pvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMpLmZvckVhY2goKGF6TGV0dGVyOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghKGF6TGV0dGVyIGluIHRoaXMuYWdncmVnYXRlWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcykpIHtcbiAgICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZCA9IHRoaXMuX2F6TWFwcGVyLmF2YWlsYWJpbGl0eVpvbmVJZEZyb21BdmFpbGFiaWxpdHlab25lTGV0dGVyKGF6TGV0dGVyKTtcblxuICAgICAgICB0aGlzLmFnZ3JlZ2F0ZVpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXNbYXpMZXR0ZXJdID0gbmV3IENvbXBvc2l0ZUFsYXJtKHRoaXMsIGF6TGV0dGVyICsgXCItaXNvbGF0ZWQtaW1wYWN0LWFsYXJtXCIsIHtcbiAgICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZih0aGlzLm5hdEdXWm9uYWxJc29sYXRlZEltcGFjdEFsYXJtcyFbYXpMZXR0ZXJdKSxcbiAgICAgICAgICBjb21wb3NpdGVBbGFybU5hbWU6IGF2YWlsYWJpbGl0eVpvbmVJZCArIFwiLWlzb2xhdGVkLWltcGFjdC1hbGFybVwiXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIFxuICAgIC8vIFNob3VsZCB3ZSBjcmVhdGUgdGhlIGRhc2hib2FyZFxuICAgIGlmIChwcm9wcy5jcmVhdGVEYXNoYm9hcmQgPT0gdHJ1ZSkge1xuICAgICAgdGhpcy5kYXNoYm9hcmQgPSBuZXcgQmFzaWNTZXJ2aWNlRGFzaGJvYXJkKFxuICAgICAgICB0aGlzLFxuICAgICAgICAnQmFzaWNTZXJ2aWNlRGFzaGJvYXJkJyxcbiAgICAgICAge1xuICAgICAgICAgIHNlcnZpY2VOYW1lOiBwcm9wcy5zZXJ2aWNlTmFtZS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgIHpvbmFsQWdncmVnYXRlSXNvbGF0ZWRJbXBhY3RBbGFybXM6XG4gICAgICAgICAgICB0aGlzLmFnZ3JlZ2F0ZVpvbmFsSXNvbGF0ZWRJbXBhY3RBbGFybXMsXG4gICAgICAgICAgaW50ZXJ2YWw6IHByb3BzLmludGVydmFsLFxuICAgICAgICAgIG5hdGd3czogcHJvcHMubmF0R2F0ZXdheVByb3BzLFxuICAgICAgICAgIGFsYnM6IHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHMsXG4gICAgICAgICAgcGVyaW9kOiBwcm9wcy5wZXJpb2QgPyBwcm9wcy5wZXJpb2QgOiBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgICAgIGF6TWFwcGVyOiB0aGlzLl9hek1hcHBlclxuICAgICAgICB9LFxuICAgICAgKS5kYXNoYm9hcmQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFxuICAgKiBAcGFyYW0gcHJvcHMgXG4gICAqIEByZXR1cm5zIEEgY29tcG9zaXRlIGFsYXJtIHBlciBBWiB0byBpbmRpY2F0ZSBpc29sYXRlZCB6b25hbCBpbXBhY3QuIFRoZSBkaWN0aW9uYXJ5XG4gICAqIGlzIGtleWVkIGJ5IHRoZSBheiBsZXR0ZXIsIGxpa2UgXCJhXCIsIFwiYlwiLCBcImNcIi5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQWxiWm9uYWxJbXBhY3RBbGFybXMoXG4gICAgcHJvcHM6IEJhc2ljU2VydmljZU11bHRpQVpPYnNlcnZhYmlsaXR5UHJvcHNcbiAgKSA6IHsgW2tleTogc3RyaW5nXTogSUFsYXJtIH0ge1xuXG4gICAgLy8gQ3JlYXRlIGltcGFjdCBhbGFybXMgcGVyIEFaLCB3aXRoIGVhY2ggQUxCIHByb3ZpZGluZ1xuICAgIC8vIGFuIGFsYXJtIGZvciBpdHMgQVpzXG4gICAgbGV0IHBlckFaSW1wYWN0QWxhcm1zOiB7IFtrZXk6IHN0cmluZ106IElBbGFybVtdIH0gPSB7fTtcblxuICAgIGxldCBrZXlQcmVmaXg6IHN0cmluZyA9IE1ldHJpY3NIZWxwZXIubmV4dENoYXIoKTtcblxuICAgIGxldCBhdmFpbGFiaWxpdHlPdXRsaWVyRGV0ZWN0aW9uQWxnb3JpdGhtOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckF2YWlsYWJpbGl0eU91dGxpZXJBbGdvcml0aG0gPSBcbiAgICAgIHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHM/LmF2YWlsYWJpbGl0eU91dGxpZXJBbGdvcml0aG0gP1xuICAgICAgcHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcy5hdmFpbGFiaWxpdHlPdXRsaWVyQWxnb3JpdGhtIDpcbiAgICAgIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyQXZhaWxhYmlsaXR5T3V0bGllckFsZ29yaXRobS5TVEFUSUM7XG5cbiAgICBsZXQgbGF0ZW5jeU91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG06IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTGF0ZW5jeU91dGxpZXJBbGdvcml0aG0gPVxuICAgICAgcHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcz8ubGF0ZW5jeU91dGxpZXJBbGdvcml0aG0gPyBcbiAgICAgIHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHMubGF0ZW5jeU91dGxpZXJBbGdvcml0aG0gOlxuICAgICAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXJMYXRlbmN5T3V0bGllckFsZ29yaXRobS5aX1NDT1JFO1xuXG4gICAgbGV0IGF2YWlsYWJpbGl0eU91dGxpZXJUaHJlc2hvbGQ6IG51bWJlcjtcbiAgICBpZiAocHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcz8uYXZhaWxhYmlsaXR5T3V0bGllclRocmVzaG9sZCkge1xuICAgICAgYXZhaWxhYmlsaXR5T3V0bGllclRocmVzaG9sZCA9IHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHMuYXZhaWxhYmlsaXR5T3V0bGllclRocmVzaG9sZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBzd2l0Y2ggKGF2YWlsYWJpbGl0eU91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0pIHtcbiAgICAgICAgY2FzZSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckF2YWlsYWJpbGl0eU91dGxpZXJBbGdvcml0aG0uU1RBVElDOlxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGF2YWlsYWJpbGl0eU91dGxpZXJUaHJlc2hvbGQgPSA2NjtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbGF0ZW5jeU91dGxpZXJUaHJlc2hvbGQ6IG51bWJlcjtcblxuICAgIGlmIChwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlclByb3BzPy5sYXRlbmN5T3V0bGllclRocmVzaG9sZCkge1xuICAgICAgbGF0ZW5jeU91dGxpZXJUaHJlc2hvbGQgPSBwcm9wcy5hcHBsaWNhdGlvbkxvYWRCYWxhbmNlclByb3BzLmxhdGVuY3lPdXRsaWVyVGhyZXNob2xkO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHN3aXRjaCAobGF0ZW5jeU91dGxpZXJEZXRlY3Rpb25BbGdvcml0aG0pIHtcbiAgICAgICAgY2FzZSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlckxhdGVuY3lPdXRsaWVyQWxnb3JpdGhtLlpfU0NPUkU6XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgbGF0ZW5jeU91dGxpZXJUaHJlc2hvbGQgPSAzO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTGF0ZW5jeU91dGxpZXJBbGdvcml0aG0uU1RBVElDOlxuICAgICAgICAgIGxhdGVuY3lPdXRsaWVyVGhyZXNob2xkID0gNjY7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHBlcmlvZDogRHVyYXRpb24gPSBwcm9wcy5wZXJpb2QgPyBwcm9wcy5wZXJpb2QgOiBEdXJhdGlvbi5taW51dGVzKDEpO1xuXG4gICAgLy8gSXRlcmF0ZSBlYWNoIEFMQlxuICAgIHRoaXMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJzIS5mb3JFYWNoKChhbGIpID0+IHtcbiAgICAgIFxuICAgICAgLy8gSXRlcmF0ZSBlYWNoIEFaIGluIHRoZSBWUENcbiAgICAgIGFsYi52cGM/LmF2YWlsYWJpbGl0eVpvbmVzLmZvckVhY2goKGF6KSA9PiB7XG5cbiAgICAgICAgaWYgKCEoYXogaW4gcGVyQVpJbXBhY3RBbGFybXMpKSB7XG4gICAgICAgICAgcGVyQVpJbXBhY3RBbGFybXNbYXpdID0gW107XG4gICAgICAgIH1cbiAgICAgXG4gICAgICAgIC8vIEdldCBBWiBsZXR0ZXJcbiAgICAgICAgbGV0IGF6TGV0dGVyID0gYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpO1xuXG4gICAgICAgIC8vIE1hcCBsZXR0ZXIgdG8gQVogSURcbiAgICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID1cbiAgICAgICAgICB0aGlzLl9hek1hcHBlci5hdmFpbGFiaWxpdHlab25lSWRGcm9tQXZhaWxhYmlsaXR5Wm9uZUxldHRlcihhekxldHRlcik7XG5cbiAgICAgICAgLy8gSXMgdGhlcmUgYXZhaWxhYmlsaXR5IGltcGFjdCBpbiB0aGlzIEFaP1xuICAgICAgICBsZXQgYXZhaWxhYmlsaXR5SW1wYWN0OiBJQWxhcm0gPSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY3MuY3JlYXRlQVpBdmFpbGFiaWxpdHlJbXBhY3RBbGFybShcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGFsYixcbiAgICAgICAgICBhdmFpbGFiaWxpdHlab25lSWQsXG4gICAgICAgICAgYXosXG4gICAgICAgICAgcHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcyEuZmF1bHRDb3VudFBlcmNlbnRUaHJlc2hvbGQsXG4gICAgICAgICAga2V5UHJlZml4LFxuICAgICAgICAgIHBlcmlvZCxcbiAgICAgICAgICBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyxcbiAgICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIElzIHRoZXJlIGxhdGVuY3kgaW1wYWN0IGluIHRoaXMgQVo/XG4gICAgICAgIGxldCBsYXRlbmN5SW1wYWN0OiBJQWxhcm0gPSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY3MuY3JlYXRlQVpMYXRlbmN5SW1wYWN0QWxhcm0oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBhbGIsXG4gICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICAgIGF6LFxuICAgICAgICAgIHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHMhLmxhdGVuY3lUaHJlc2hvbGQsXG4gICAgICAgICAgcHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcyEubGF0ZW5jeVN0YXRpc3RpYyxcbiAgICAgICAgICBrZXlQcmVmaXgsXG4gICAgICAgICAgcGVyaW9kLFxuICAgICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICAgIHByb3BzLmRhdGFwb2ludHNUb0FsYXJtXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gSXMgdGhlIEFaIGFuIG91dGxpZXIgZm9yIGZhdWx0c1xuICAgICAgICBsZXQgYXZhaWxhYmlsaXR5T3V0bGllciA9IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyTWV0cmljcy5jcmVhdGVBWkF2YWlsYWJpbGl0eU91dGxpZXJBbGFybShcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGFsYixcbiAgICAgICAgICBhdmFpbGFiaWxpdHlPdXRsaWVyRGV0ZWN0aW9uQWxnb3JpdGhtLFxuICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmVJZCxcbiAgICAgICAgICBheixcbiAgICAgICAgICBhdmFpbGFiaWxpdHlPdXRsaWVyVGhyZXNob2xkLFxuICAgICAgICAgIGtleVByZWZpeCxcbiAgICAgICAgICBwZXJpb2QsXG4gICAgICAgICAgcHJvcHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgcHJvcHMuZGF0YXBvaW50c1RvQWxhcm1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBJcyB0aGUgQVogYW4gb3V0bGllciBmb3IgbGF0ZW5jeVxuICAgICAgICBsZXQgbGF0ZW5jeU91dGxpZXIgPSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlck1ldHJpY3MuY3JlYXRlQVpMYXRlbmN5T3V0bGllckFsYXJtKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgYWxiLFxuICAgICAgICAgIGxhdGVuY3lPdXRsaWVyRGV0ZWN0aW9uQWxnb3JpdGhtLFxuICAgICAgICAgIGF6LFxuICAgICAgICAgIHByb3BzLmFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyUHJvcHMhLmxhdGVuY3lTdGF0aXN0aWMsXG4gICAgICAgICAgcHJvcHMuYXBwbGljYXRpb25Mb2FkQmFsYW5jZXJQcm9wcyEubGF0ZW5jeVRocmVzaG9sZCxcbiAgICAgICAgICBsYXRlbmN5T3V0bGllclRocmVzaG9sZCxcbiAgICAgICAgICBwZXJpb2QsXG4gICAgICAgICAgcHJvcHMuZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgICAgdGhpcy5fYXpNYXBwZXJcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBBbGFybSBpZiB0aGUgQVogc2hvd3MgaW1wYWN0IGFuZCBpcyBhbiBvdXRsaWVyXG4gICAgICAgIGxldCBhekltcGFjdEFsYXJtOiBJQWxhcm0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgXG4gICAgICAgICAgYXpMZXR0ZXIgKyAgXCItY29tcG9zaXRlLWltcGFjdC1hbGFybVwiLCBcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbnlPZihcbiAgICAgICAgICAgICAgQWxhcm1SdWxlLmFsbE9mKGF2YWlsYWJpbGl0eUltcGFjdCwgYXZhaWxhYmlsaXR5T3V0bGllciksIFxuICAgICAgICAgICAgICBBbGFybVJ1bGUuYWxsT2YobGF0ZW5jeUltcGFjdCwgbGF0ZW5jeU91dGxpZXIpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgY29tcG9zaXRlQWxhcm1OYW1lOiBcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItXCIgKyBcbiAgICAgICAgICAgICAgKGFsYiBhcyBJTG9hZEJhbGFuY2VyVjIgYXMgQmFzZUxvYWRCYWxhbmNlcikubG9hZEJhbGFuY2VyTmFtZSArIFxuICAgICAgICAgICAgICBcIi1sYXRlbmN5LW9yLWF2YWlsYWJpbGl0eS1pbXBhY3RcIixcbiAgICAgICAgICAgIGFjdGlvbnNFbmFibGVkOiBmYWxzZVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBBZGQgdGhpcyBBTEIncyBmYXVsdCByYXRlIGFsYXJtXG4gICAgICAgIHBlckFaSW1wYWN0QWxhcm1zW2F6XS5wdXNoKGF6SW1wYWN0QWxhcm0pO1xuXG4gICAgICAgIC8vIEdldCBuZXh0IHVuaXF1ZSBrZXlcbiAgICAgICAga2V5UHJlZml4ID0gTWV0cmljc0hlbHBlci5uZXh0Q2hhcihrZXlQcmVmaXgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBsZXQgYXpDb21wb3NpdGVBbGFybXM6IHtba2V5OiBzdHJpbmddOiBJQWxhcm19ID0ge307XG5cbiAgICAvLyBJdGVyYXRlIEFacyBmb3IgdGhlIEFMQiBpbXBhY3QgYWxhcm1zIHNvIHdlIGNhbiBqb2luIHRoZW1cbiAgICAvLyBpbnRvIGEgc2luZ2xlIGNvbXBvc2l0ZSBhbGFybSBmb3IgZWFjaCBBWlxuICAgIE9iamVjdC5rZXlzKHBlckFaSW1wYWN0QWxhcm1zKS5mb3JFYWNoKChheikgPT4ge1xuICAgICAgbGV0IGF6TGV0dGVyID0gYXouc3Vic3RyaW5nKGF6Lmxlbmd0aCAtIDEpO1xuICAgICAgbGV0IGF2YWlsYWJpbGl0eVpvbmVJZDogc3RyaW5nID0gdGhpcy5fYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoYXpMZXR0ZXIpO1xuXG4gICAgICBhekNvbXBvc2l0ZUFsYXJtc1thekxldHRlcl0gPSBuZXcgQ29tcG9zaXRlQWxhcm0odGhpcywgYXpMZXR0ZXIgKyBcIi1hbGItaW1wYWN0LWNvbXBvc2l0ZS1hbGFybVwiLCB7XG4gICAgICAgIGFsYXJtUnVsZTogQWxhcm1SdWxlLmFueU9mKC4uLnBlckFaSW1wYWN0QWxhcm1zW2F6XSksXG4gICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItYWxiLWltcGFjdC1jb21wb3NpdGUtYWxhcm1cIlxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXpDb21wb3NpdGVBbGFybXM7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU5hdEdhdGV3YXlab25hbEltcGFjdEFsYXJtcyhcbiAgICBwcm9wczogQmFzaWNTZXJ2aWNlTXVsdGlBWk9ic2VydmFiaWxpdHlQcm9wc1xuICApOiB7W2tleTogc3RyaW5nXTogSUFsYXJtfSB7XG5cbiAgICAvLyBDb2xsZWN0IGFsYXJtcyBmb3IgcGFja2V0IGRyb3BzIGV4Y2VlZGluZyBhIHRocmVzaG9sZCBwZXIgTkFUIEdXXG4gICAgbGV0IHBhY2tldExvc3NQZXJBWkFsYXJtczogeyBba2V5OiBzdHJpbmddOiBJQWxhcm0gfSA9IHt9O1xuXG4gICAgbGV0IHBhY2tldExvc3NPdXRsaWVyQWxnb3JpdGhtOiBQYWNrZXRMb3NzT3V0bGllckFsZ29yaXRobSA9IHByb3BzLm5hdEdhdGV3YXlQcm9wcz8ucGFja2V0TG9zc091dGxpZXJBbGdvcml0aG0gP1xuICAgICAgcHJvcHMubmF0R2F0ZXdheVByb3BzPy5wYWNrZXRMb3NzT3V0bGllckFsZ29yaXRobSA6XG4gICAgICBQYWNrZXRMb3NzT3V0bGllckFsZ29yaXRobS5TVEFUSUM7XG5cbiAgICBsZXQgcGFja2V0TG9zc1RocmVzaG9sZDogbnVtYmVyID0gcHJvcHMubmF0R2F0ZXdheVByb3BzPy5wYWNrZXRMb3NzUGVyY2VudFRocmVzaG9sZCA/IFxuICAgICAgcHJvcHMubmF0R2F0ZXdheVByb3BzLnBhY2tldExvc3NQZXJjZW50VGhyZXNob2xkIDpcbiAgICAgIDAuMDE7XG5cbiAgICBsZXQgb3V0bGllclRocmVzaG9sZDogbnVtYmVyO1xuXG4gICAgaWYgKHByb3BzLm5hdEdhdGV3YXlQcm9wcz8ucGFja2V0TG9zc091dGxpZXJUaHJlc2hvbGQpIHtcbiAgICAgIG91dGxpZXJUaHJlc2hvbGQgPSBwcm9wcy5uYXRHYXRld2F5UHJvcHMucGFja2V0TG9zc091dGxpZXJUaHJlc2hvbGQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgc3dpdGNoIChwYWNrZXRMb3NzT3V0bGllckFsZ29yaXRobSkge1xuICAgICAgICBjYXNlIFBhY2tldExvc3NPdXRsaWVyQWxnb3JpdGhtLlNUQVRJQzpcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBvdXRsaWVyVGhyZXNob2xkID0gNjY7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgICAgXG5cbiAgICBsZXQgcGVyaW9kOiBEdXJhdGlvbiA9IHByb3BzLnBlcmlvZCA/IHByb3BzLnBlcmlvZCA6IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG5cbiAgICAvLyBGb3IgZWFjaCBBWiwgY3JlYXRlIG1ldHJpY3MgZm9yIGVhY2ggTkFUIEdXXG4gICAgT2JqZWN0LmtleXModGhpcy5uYXRHYXRld2F5cyEpLmZvckVhY2goKGF6OiBzdHJpbmcpID0+IHtcblxuICAgICAgbGV0IGF6TGV0dGVyOiBzdHJpbmcgPSBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSk7XG4gICAgICBsZXQgYXZhaWxhYmlsaXR5Wm9uZUlkID1cbiAgICAgICAgdGhpcy5fYXpNYXBwZXIuYXZhaWxhYmlsaXR5Wm9uZUlkRnJvbUF2YWlsYWJpbGl0eVpvbmVMZXR0ZXIoYXpMZXR0ZXIpO1xuXG4gICAgICAvLyBJcyB0aGVyZSBwYWNrZXQgbG9zcyBpbXBhY3Q/XG4gICAgICBsZXQgcGFja2V0TG9zc0ltcGFjdDogSUFsYXJtID0gTmF0R2F0ZXdheU1ldHJpY3MuaXNUaGVyZUFuQVpQYWNrZXRMb3NzSW1wYWN0TkFUR1coXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHRoaXMubmF0R2F0ZXdheXMhW2F6XSxcbiAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZUlkLFxuICAgICAgICBheixcbiAgICAgICAgcGFja2V0TG9zc1RocmVzaG9sZCxcbiAgICAgICAgcGVyaW9kLFxuICAgICAgICBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyxcbiAgICAgICAgcHJvcHMuZGF0YXBvaW50c1RvQWxhcm1cbiAgICAgICk7XG5cbiAgICAgIC8vIElzIHRoaXMgQVogYW4gb3V0bGllciBmb3IgdGhpcyBOQVRHVz9cbiAgICAgIGxldCBwYWNrZXRMb3NzT3V0bGllcjogSUFsYXJtID0gTmF0R2F0ZXdheU1ldHJpY3MuaXNBWkFuT3V0bGllckZvclBhY2tldExvc3NOQVRHVyhcbiAgICAgICAgdGhpcyxcbiAgICAgICAgdGhpcy5uYXRHYXRld2F5cyEsXG4gICAgICAgIHBhY2tldExvc3NPdXRsaWVyQWxnb3JpdGhtLFxuICAgICAgICBheixcbiAgICAgICAgdGhpcy5fYXpNYXBwZXIsXG4gICAgICAgIG91dGxpZXJUaHJlc2hvbGQsXG4gICAgICAgIHByb3BzLnBlcmlvZCA/IHByb3BzLnBlcmlvZCA6IER1cmF0aW9uLm1pbnV0ZXMoMSksXG4gICAgICAgIHByb3BzLmV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybVxuICAgICAgKTtcblxuICAgICAgcGFja2V0TG9zc1BlckFaQWxhcm1zW2F6TGV0dGVyXSA9IG5ldyBDb21wb3NpdGVBbGFybSh0aGlzLCBhei5zdWJzdHJpbmcoYXoubGVuZ3RoIC0gMSkgKyBcIi1wYWNrZXQtbG9zcy1jb21wb3NpdGUtYWxhcm1cIiwge1xuICAgICAgICBhbGFybVJ1bGU6IEFsYXJtUnVsZS5hbGxPZihwYWNrZXRMb3NzSW1wYWN0LCBwYWNrZXRMb3NzT3V0bGllciksXG4gICAgICAgIGNvbXBvc2l0ZUFsYXJtTmFtZTogYXZhaWxhYmlsaXR5Wm9uZUlkICsgXCItcGFja2V0LWxvc3MtY29tcG9zaXRlLWFsYXJtXCJcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHBhY2tldExvc3NQZXJBWkFsYXJtcztcbiAgfVxufVxuIl19