@cdklabs/multi-az-observability 0.0.1-alpha.2 → 0.0.1-alpha.20

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