@liflig/cdk 3.22.18 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ import * as cdk from "aws-cdk-lib";
2
+ import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
3
+ import * as constructs from "constructs";
4
+ /**
5
+ * This construct provides a thin wrapper that creates two alarms for
6
+ * SQS queues.
7
+ *
8
+ * Unlike RDS and ECS alarm constructs in this package, `QueueAlarms` is
9
+ * set up manually by consumers (it doesn't auto-wire to resources).
10
+ *
11
+ * Defaults:
12
+ * - Messages-not-being-processed alarm -> sent to `alarmAction` by default
13
+ * - Approximate-age alarm -> sent to `warningAction` by default
14
+ */
15
+ export class QueueAlarms extends constructs.Construct {
16
+ alarmAction;
17
+ warningAction;
18
+ queueName;
19
+ constructor(scope, id, props) {
20
+ super(scope, id);
21
+ this.alarmAction = props.alarmAction;
22
+ this.warningAction = props.warningAction;
23
+ this.queueName = props.queueName;
24
+ }
25
+ /**
26
+ * Sets up a CloudWatch Composite Alarm that triggers if messages are not being deleted
27
+ * from queue, and there are visible messages on the queue.
28
+ */
29
+ addMessagesNotBeingProcessedAlarm(props) {
30
+ const period = props?.period ?? cdk.Duration.seconds(300);
31
+ const evaluationPeriodsMessagesVisible = props?.evaluationPeriodsMessagesVisible ?? 2;
32
+ const thresholdMessagesVisible = props?.thresholdMessagesVisible ?? 1;
33
+ const evaluationPeriodsMessagesDeleted = props?.evaluationPeriodsMessagesDeleted ?? 4;
34
+ const thresholdMessagesDeleted = props?.thresholdMessagesDeleted ?? 0;
35
+ const messagesVisibleAlarm = new cloudwatch.Metric({
36
+ metricName: "ApproximateNumberOfMessagesVisible",
37
+ namespace: "AWS/SQS",
38
+ statistic: "Minimum",
39
+ period,
40
+ dimensionsMap: {
41
+ QueueName: this.queueName,
42
+ },
43
+ }).createAlarm(this, "MessagesVisibleAlarm", {
44
+ alarmDescription: "Service might be unavailable! It has available messages on the SQS queue, but these messages are not being deleted (processed).",
45
+ comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
46
+ evaluationPeriods: evaluationPeriodsMessagesVisible,
47
+ threshold: thresholdMessagesVisible,
48
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
49
+ });
50
+ const messagesNotBeingDeletedAlarm = new cloudwatch.Metric({
51
+ metricName: "NumberOfMessagesDeleted",
52
+ namespace: "AWS/SQS",
53
+ statistic: "Sum",
54
+ period,
55
+ dimensionsMap: {
56
+ QueueName: this.queueName,
57
+ },
58
+ }).createAlarm(this, "MessagesNotBeingDeleted", {
59
+ alarmDescription: "Service might be unavailable! It has available messages on the SQS queue, but these messages are not being deleted (processed).",
60
+ comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
61
+ evaluationPeriods: evaluationPeriodsMessagesDeleted,
62
+ threshold: thresholdMessagesDeleted,
63
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
64
+ });
65
+ const messagesNotBeingProcessedAlarm = new cloudwatch.CompositeAlarm(this, "MessagesNotBeingProcessedAlarm", {
66
+ alarmRule: cloudwatch.AlarmRule.allOf(messagesVisibleAlarm, messagesNotBeingDeletedAlarm),
67
+ actionsEnabled: true,
68
+ alarmDescription: "Service might be unavailable! It has available messages on the SQS queue, but these messages are not being deleted (processed).",
69
+ });
70
+ // Sent to alarm channel by default
71
+ const action = props?.action ?? this.alarmAction;
72
+ messagesNotBeingProcessedAlarm.addAlarmAction(action);
73
+ if (props?.enableOkAlarm ?? true) {
74
+ messagesNotBeingProcessedAlarm.addOkAction(action);
75
+ }
76
+ }
77
+ /**
78
+ * Alerts when the ApproximateAgeOfOldestMessage metric is high.
79
+ */
80
+ addApproximateAgeOfOldestMessageAlarm(props) {
81
+ const period = props?.period ?? cdk.Duration.seconds(900);
82
+ const evaluationPeriods = props?.evaluationPeriods ?? 2;
83
+ const threshold = props?.thresholdSeconds ?? 900;
84
+ const ageMetric = new cloudwatch.Metric({
85
+ metricName: "ApproximateAgeOfOldestMessage",
86
+ namespace: "AWS/SQS",
87
+ statistic: "Maximum",
88
+ period,
89
+ dimensionsMap: {
90
+ QueueName: this.queueName,
91
+ },
92
+ });
93
+ const ageAlarm = ageMetric.createAlarm(this, "ApproximateAgeOfOldestMessageAlarm", {
94
+ alarmDescription: props?.alarmDescription ??
95
+ `${this.queueName} has an oldest message older than ${threshold} seconds`,
96
+ comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
97
+ evaluationPeriods,
98
+ threshold,
99
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
100
+ });
101
+ // Sent to warnings channel by default
102
+ const action = props?.action ?? this.warningAction;
103
+ ageAlarm.addAlarmAction(action);
104
+ if (props?.enableOkAlarm ?? true) {
105
+ ageAlarm.addOkAction(action);
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVldWUtYWxhcm1zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsYXJtcy9xdWV1ZS1hbGFybXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEdBQUcsTUFBTSxhQUFhLENBQUE7QUFFbEMsT0FBTyxLQUFLLFVBQVUsTUFBTSw0QkFBNEIsQ0FBQTtBQUN4RCxPQUFPLEtBQUssVUFBVSxNQUFNLFlBQVksQ0FBQTtBQVV4Qzs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxPQUFPLFdBQVksU0FBUSxVQUFVLENBQUMsU0FBUztJQUNsQyxXQUFXLENBQXlCO0lBQ3BDLGFBQWEsQ0FBeUI7SUFDdEMsU0FBUyxDQUFRO0lBRWxDLFlBQ0UsS0FBMkIsRUFDM0IsRUFBVSxFQUNWLEtBQXVCO1FBRXZCLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFFaEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFBO1FBQ3BDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQTtRQUN4QyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUE7SUFDbEMsQ0FBQztJQUNEOzs7T0FHRztJQUNILGlDQUFpQyxDQUFDLEtBZ0NqQztRQUNDLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxNQUFNLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDekQsTUFBTSxnQ0FBZ0MsR0FDcEMsS0FBSyxFQUFFLGdDQUFnQyxJQUFJLENBQUMsQ0FBQTtRQUM5QyxNQUFNLHdCQUF3QixHQUFHLEtBQUssRUFBRSx3QkFBd0IsSUFBSSxDQUFDLENBQUE7UUFDckUsTUFBTSxnQ0FBZ0MsR0FDcEMsS0FBSyxFQUFFLGdDQUFnQyxJQUFJLENBQUMsQ0FBQTtRQUM5QyxNQUFNLHdCQUF3QixHQUFHLEtBQUssRUFBRSx3QkFBd0Is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cUMsU0FBUyxVQUFVO1lBQzNFLGtCQUFrQixFQUNoQixVQUFVLENBQUMsa0JBQWtCLENBQUMsa0NBQWtDO1lBQ2xFLGlCQUFpQjtZQUNqQixTQUFTO1lBQ1QsZ0JBQWdCLEVBQUUsVUFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU07U0FDckQsQ0FDRixDQUFBO1FBRUQsc0NBQXNDO1FBQ3RDLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxNQUFNLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQTtRQUNsRCxRQUFRLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQy9CLElBQUksS0FBSyxFQUFFLGFBQWEsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNqQyxRQUFRLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzlCLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCJcbmltcG9ydCB0eXBlIHsgSUFsYXJtQWN0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCJcbmltcG9ydCAqIGFzIGNsb3Vkd2F0Y2ggZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCJcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSBcImNvbnN0cnVjdHNcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXVlQWxhcm1zUHJvcHMge1xuICAvLyBBY3Rpb24gdG8gdXNlIGZvciBoaWdoLXNldmVyaXR5IGFsYXJtc1xuICBhbGFybUFjdGlvbjogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgLy8gQWN0aW9uIHRvIHVzZSBmb3Igd2FybmluZ3NcbiAgd2FybmluZ0FjdGlvbjogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgcXVldWVOYW1lOiBzdHJpbmdcbn1cblxuLyoqXG4gKiBUaGlzIGNvbnN0cnVjdCBwcm92aWRlcyBhIHRoaW4gd3JhcHBlciB0aGF0IGNyZWF0ZXMgdHdvIGFsYXJtcyBmb3JcbiAqIFNRUyBxdWV1ZXMuXG4gKlxuICogVW5saWtlIFJEUyBhbmQgRUNTIGFsYXJtIGNvbnN0cnVjdHMgaW4gdGhpcyBwYWNrYWdlLCBgUXVldWVBbGFybXNgIGlzXG4gKiBzZXQgdXAgbWFudWFsbHkgYnkgY29uc3VtZXJzIChpdCBkb2Vzbid0IGF1dG8td2lyZSB0byByZXNvdXJjZXMpLlxuICpcbiAqIERlZmF1bHRzOlxuICogIC0gTWVzc2FnZXMtbm90LWJlaW5nLXByb2Nlc3NlZCBhbGFybSAtPiBzZW50IHRvIGBhbGFybUFjdGlvbmAgYnkgZGVmYXVsdFxuICogIC0gQXBwcm94aW1hdGUtYWdlIGFsYXJtIC0+IHNlbnQgdG8gYHdhcm5pbmdBY3Rpb25gIGJ5IGRlZmF1bHRcbiAqL1xuZXhwb3J0IGNsYXNzIFF1ZXVlQWxhcm1zIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IGFsYXJtQWN0aW9uOiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICBwcml2YXRlIHJlYWRvbmx5IHdhcm5pbmdBY3Rpb246IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uXG4gIHByaXZhdGUgcmVhZG9ubHkgcXVldWVOYW1lOiBzdHJpbmdcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogY29uc3RydWN0cy5Db25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogUXVldWVBbGFybXNQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKVxuXG4gICAgdGhpcy5hbGFybUFjdGlvbiA9IHByb3BzLmFsYXJtQWN0aW9uXG4gICAgdGhpcy53YXJuaW5nQWN0aW9uID0gcHJvcHMud2FybmluZ0FjdGlvblxuICAgIHRoaXMucXVldWVOYW1lID0gcHJvcHMucXVldWVOYW1lXG4gIH1cbiAgLyoqXG4gICAqIFNldHMgdXAgYSBDbG91ZFdhdGNoIENvbXBvc2l0ZSBBbGFybSB0aGF0IHRyaWdnZXJzIGlmIG1lc3NhZ2VzIGFyZSBub3QgYmVpbmcgZGVsZXRlZFxuICAgKiBmcm9tIHF1ZXVlLCBhbmQgdGhlcmUgYXJlIHZpc2libGUgbWVzc2FnZXMgb24gdGhlIHF1ZXVlLlxuICAgKi9cbiAgYWRkTWVzc2FnZXNOb3RCZWluZ1Byb2Nlc3NlZEFsYXJtKHByb3BzPzoge1xuICAgIC8qKlxuICAgICAqIFBlcmlvZCBmb3IgbWV0cmljIGV2YWx1YXRpb24gYXMgYSBDREsgRHVyYXRpb25cbiAgICAgKiBAZGVmYXVsdCBjZGsuRHVyYXRpb24uc2Vjb25kcygzMDApXG4gICAgICovXG4gICAgcGVyaW9kPzogY2RrLkR1cmF0aW9uXG4gICAgLyoqXG4gICAgICogRXZhbHVhdGlvbiBwZXJpb2RzIGZvciBNZXNzYWdlc1Zpc2libGUgbWV0cmljXG4gICAgICogQGRlZmF1bHQgMlxuICAgICAqL1xuICAgIGV2YWx1YXRpb25QZXJpb2RzTWVzc2FnZXNWaXNpYmxlPzogbnVtYmVyXG4gICAgLyoqXG4gICAgICogVGhyZXNob2xkIGZvciBNZXNzYWdlc1Zpc2libGUgbWV0cmljIChtaW5pbXVtKVxuICAgICAqIEBkZWZhdWx0IDFcbiAgICAgKi9cbiAgICB0aHJlc2hvbGRNZXNzYWdlc1Zpc2libGU/OiBudW1iZXJcbiAgICAvKipcbiAgICAgKiBFdmFsdWF0aW9uIHBlcmlvZHMgZm9yIE51bWJlck9mTWVzc2FnZXNEZWxldGVkIG1ldHJpY1xuICAgICAqIEBkZWZhdWx0IDRcbiAgICAgKi9cbiAgICBldmFsdWF0aW9uUGVyaW9kc01lc3NhZ2VzRGVsZXRlZD86IG51bWJlclxuICAgIC8qKlxuICAgICAqIFRocmVzaG9sZCBmb3IgTnVtYmVyT2ZNZXNzYWdlc0RlbGV0ZWQgKHN1bSlcbiAgICAgKiBAZGVmYXVsdCAwXG4gICAgICovXG4gICAgdGhyZXNob2xkTWVzc2FnZXNEZWxldGVkPzogbnVtYmVyXG4gICAgLyoqXG4gICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAqL1xuICAgIGVuYWJsZU9rQWxhcm0/OiBib29sZWFuXG4gICAgLyoqIFBlci1hbGFybSBvdmVycmlkZSBvZiB0aGUgYWN0aW9uIHRvIHVzZSBpbnN0ZWFkIG9mIHRoZSBjb25zdHJ1Y3QgYWxhcm1BY3Rpb24gKi9cbiAgICBhY3Rpb24/OiBJQWxhcm1BY3Rpb25cbiAgfSk6IHZvaWQge1xuICAgIGNvbnN0IHBlcmlvZCA9IHByb3BzPy5wZXJpb2QgPz8gY2RrLkR1cmF0aW9uLnNlY29uZHMoMzAwKVxuICAgIGNvbnN0IGV2YWx1YXRpb25QZXJpb2RzTWVzc2FnZXNWaXNpYmxlID1cbiAgICAgIHByb3BzPy5ldmFsdWF0aW9uUGVyaW9kc01lc3NhZ2VzVmlzaWJsZSA/PyAyXG4gICAgY29uc3QgdGhyZXNob2xkTWVzc2FnZXNWaXNpYmxlID0gcHJvcHM/LnRocmVzaG9sZE1lc3NhZ2VzVmlzaWJsZSA/PyAxXG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHNNZXNzYWdlc0RlbGV0ZWQgPVxuICAgICAgcHJvcHM/LmV2YWx1YXRpb25QZXJpb2RzTWVzc2FnZXNEZWxldGVkID8/IDRcbiAgICBjb25zdCB0aHJlc2hvbGRNZXNzYWdlc0RlbGV0ZWQgPSBwcm9wcz8udGhyZXNob2xkTWVzc2FnZXNEZWxldGVkID8/IDBcblxuICAgIGNvbnN0IG1lc3NhZ2VzVmlzaWJsZUFsYXJtID0gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIG1ldHJpY05hbWU6IFwiQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzVmlzaWJsZVwiLFxuICAgICAgbmFtZXNwYWNlOiBcIkFXUy9TUVNcIixcbiAgICAgIHN0YXRpc3RpYzogXCJNaW5pbXVtXCIsXG4gICAgICBwZXJpb2QsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFF1ZXVlTmFtZTogdGhpcy5xdWV1ZU5hbWUsXG4gICAgICB9LFxuICAgIH0pLmNyZWF0ZUFsYXJtKHRoaXMsIFwiTWVzc2FnZXNWaXNpYmxlQWxhcm1cIiwge1xuICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgXCJTZXJ2aWNlIG1pZ2h0IGJlIHVuYXZhaWxhYmxlISBJdCBoYXMgYXZhaWxhYmxlIG1lc3NhZ2VzIG9uIHRoZSBTUVMgcXVldWUsIGJ1dCB0aGVzZSBtZXNzYWdlcyBhcmUgbm90IGJlaW5nIGRlbGV0ZWQgKHByb2Nlc3NlZCkuXCIsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6XG4gICAgICAgIGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICBldmFsdWF0aW9uUGVyaW9kczogZXZhbHVhdGlvblBlcmlvZHNNZXNzYWdlc1Zpc2libGUsXG4gICAgICB0aHJlc2hvbGQ6IHRocmVzaG9sZE1lc3NhZ2VzVmlzaWJsZSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5JR05PUkUsXG4gICAgfSlcblxuICAgIGNvbnN0IG1lc3NhZ2VzTm90QmVpbmdEZWxldGVkQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJOdW1iZXJPZk1lc3NhZ2VzRGVsZXRlZFwiLFxuICAgICAgbmFtZXNwYWNlOiBcIkFXUy9TUVNcIixcbiAgICAgIHN0YXRpc3RpYzogXCJTdW1cIixcbiAgICAgIHBlcmlvZCxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgUXVldWVOYW1lOiB0aGlzLnF1ZXVlTmFtZSxcbiAgICAgIH0sXG4gICAgfSkuY3JlYXRlQWxhcm0odGhpcywgXCJNZXNzYWdlc05vdEJlaW5nRGVsZXRlZFwiLCB7XG4gICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICBcIlNlcnZpY2UgbWlnaHQgYmUgdW5hdmFpbGFibGUhIEl0IGhhcyBhdmFpbGFibGUgbWVzc2FnZXMgb24gdGhlIFNRUyBxdWV1ZSwgYnV0IHRoZXNlIG1lc3NhZ2VzIGFyZSBub3QgYmVpbmcgZGVsZXRlZCAocHJvY2Vzc2VkKS5cIixcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjpcbiAgICAgICAgY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuTEVTU19USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBldmFsdWF0aW9uUGVyaW9kc01lc3NhZ2VzRGVsZXRlZCxcbiAgICAgIHRocmVzaG9sZDogdGhyZXNob2xkTWVzc2FnZXNEZWxldGVkLFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICB9KVxuXG4gICAgY29uc3QgbWVzc2FnZXNOb3RCZWluZ1Byb2Nlc3NlZEFsYXJtID0gbmV3IGNsb3Vkd2F0Y2guQ29tcG9zaXRlQWxhcm0oXG4gICAgICB0aGlzLFxuICAgICAgXCJNZXNzYWdlc05vdEJlaW5nUHJvY2Vzc2VkQWxhcm1cIixcbiAgICAgIHtcbiAgICAgICAgYWxhcm1SdWxlOiBjbG91ZHdhdGNoLkFsYXJtUnVsZS5hbGxPZihcbiAgICAgICAgICBtZXNzYWdlc1Zpc2libGVBbGFybSxcbiAgICAgICAgICBtZXNzYWdlc05vdEJlaW5nRGVsZXRlZEFsYXJtLFxuICAgICAgICApLFxuICAgICAgICBhY3Rpb25zRW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgICBcIlNlcnZpY2UgbWlnaHQgYmUgdW5hdmFpbGFibGUhIEl0IGhhcyBhdmFpbGFibGUgbWVzc2FnZXMgb24gdGhlIFNRUyBxdWV1ZSwgYnV0IHRoZXNlIG1lc3NhZ2VzIGFyZSBub3QgYmVpbmcgZGVsZXRlZCAocHJvY2Vzc2VkKS5cIixcbiAgICAgIH0sXG4gICAgKVxuXG4gICAgLy8gU2VudCB0byBhbGFybSBjaGFubmVsIGJ5IGRlZmF1bHRcbiAgICBjb25zdCBhY3Rpb24gPSBwcm9wcz8uYWN0aW9uID8/IHRoaXMuYWxhcm1BY3Rpb25cbiAgICBtZXNzYWdlc05vdEJlaW5nUHJvY2Vzc2VkQWxhcm0uYWRkQWxhcm1BY3Rpb24oYWN0aW9uKVxuICAgIGlmIChwcm9wcz8uZW5hYmxlT2tBbGFybSA/PyB0cnVlKSB7XG4gICAgICBtZXNzYWdlc05vdEJlaW5nUHJvY2Vzc2VkQWxhcm0uYWRkT2tBY3Rpb24oYWN0aW9uKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBbGVydHMgd2hlbiB0aGUgQXBwcm94aW1hdGVBZ2VPZk9sZGVzdE1lc3NhZ2UgbWV0cmljIGlzIGhpZ2guXG4gICAqL1xuICBhZGRBcHByb3hpbWF0ZUFnZU9mT2xkZXN0TWVzc2FnZUFsYXJtKHByb3BzPzoge1xuICAgIGFsYXJtRGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICAvKipcbiAgICAgKiBAZGVmYXVsdCBjZGsuRHVyYXRpb24uc2Vjb25kcyg5MDApICgxNSBtaW51dGVzKVxuICAgICAqL1xuICAgIHBlcmlvZD86IGNkay5EdXJhdGlvblxuICAgIC8qKlxuICAgICAqIEBkZWZhdWx0IDJcbiAgICAgKi9cbiAgICBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlclxuICAgIC8qKlxuICAgICAqIFRocmVzaG9sZCBpbiBzZWNvbmRzIGZvciB0aGUgYWdlIG9mIHRoZSBvbGRlc3QgbWVzc2FnZVxuICAgICAqIEBkZWZhdWx0IDkwMCBzZWNvbmRzICgxNSBtaW51dGVzKVxuICAgICAqL1xuICAgIHRocmVzaG9sZFNlY29uZHM/OiBudW1iZXJcbiAgICAvKipcbiAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICovXG4gICAgZW5hYmxlT2tBbGFybT86IGJvb2xlYW5cbiAgICAvKiogQW4gYWN0aW9uIHRvIHVzZSBmb3IgQ2xvdWRXYXRjaCBhbGFybSBzdGF0ZSBjaGFuZ2VzIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgd2FybmluZ0FjdGlvbiAqL1xuICAgIGFjdGlvbj86IElBbGFybUFjdGlvblxuICB9KTogdm9pZCB7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHM/LnBlcmlvZCA/PyBjZGsuRHVyYXRpb24uc2Vjb25kcyg5MDApXG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcz8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMlxuICAgIGNvbnN0IHRocmVzaG9sZCA9IHByb3BzPy50aHJlc2hvbGRTZWNvbmRzID8/IDkwMFxuXG4gICAgY29uc3QgYWdlTWV0cmljID0gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIG1ldHJpY05hbWU6IFwiQXBwcm94aW1hdGVBZ2VPZk9sZGVzdE1lc3NhZ2VcIixcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvU1FTXCIsXG4gICAgICBzdGF0aXN0aWM6IFwiTWF4aW11bVwiLFxuICAgICAgcGVyaW9kLFxuICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICBRdWV1ZU5hbWU6IHRoaXMucXVldWVOYW1lLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgYWdlQWxhcm0gPSBhZ2VNZXRyaWMuY3JlYXRlQWxhcm0oXG4gICAgICB0aGlzLFxuICAgICAgXCJBcHByb3hpbWF0ZUFnZU9mT2xkZXN0TWVzc2FnZUFsYXJtXCIsXG4gICAgICB7XG4gICAgICAgIGFsYXJtRGVzY3JpcHRpb246XG4gICAgICAgICAgcHJvcHM/LmFsYXJtRGVzY3JpcHRpb24gPz9cbiAgICAgICAgICBgJHt0aGlzLnF1ZXVlTmFtZX0gaGFzIGFuIG9sZGVzdCBtZXNzYWdlIG9sZGVyIHRoYW4gJHt0aHJlc2hvbGR9IHNlY29uZHNgLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6XG4gICAgICAgICAgY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgIHRocmVzaG9sZCxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICAgIH0sXG4gICAgKVxuXG4gICAgLy8gU2VudCB0byB3YXJuaW5ncyBjaGFubmVsIGJ5IGRlZmF1bHRcbiAgICBjb25zdCBhY3Rpb24gPSBwcm9wcz8uYWN0aW9uID8/IHRoaXMud2FybmluZ0FjdGlvblxuICAgIGFnZUFsYXJtLmFkZEFsYXJtQWN0aW9uKGFjdGlvbilcbiAgICBpZiAocHJvcHM/LmVuYWJsZU9rQWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgYWdlQWxhcm0uYWRkT2tBY3Rpb24oYWN0aW9uKVxuICAgIH1cbiAgfVxufVxuIl19
@@ -1,16 +1,26 @@
1
1
  import * as cdk from "aws-cdk-lib";
2
2
  import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
3
+ import type * as lambda from "aws-cdk-lib/aws-lambda";
3
4
  import * as logs from "aws-cdk-lib/aws-logs";
4
5
  import * as constructs from "constructs";
5
6
  export interface ServiceAlarmsProps extends cdk.StackProps {
6
7
  /**
7
- * The default action to use for CloudWatch alarm state changes
8
+ * The CloudWatch Alarm action to use for high-severity alarms.
8
9
  */
9
- action: cloudwatch.IAlarmAction;
10
+ alarmAction: cloudwatch.IAlarmAction;
11
+ /**
12
+ * The CloudWatch Alarm action to use for warnings.
13
+ */
14
+ warningAction: cloudwatch.IAlarmAction;
10
15
  /**
11
16
  * The name of the ECS service.
12
17
  */
13
18
  serviceName: string;
19
+ /**
20
+ * Optional Lambda function that will receive forwarded log events.
21
+ * If provided, subscription filters will be created to forward matching logs.
22
+ */
23
+ logHandler?: lambda.IFunction;
14
24
  }
15
25
  /**
16
26
  * Various alarms and monitoring.
@@ -21,8 +31,10 @@ export interface ServiceAlarmsProps extends cdk.StackProps {
21
31
  * See SlackAlarm construct for SNS Action.
22
32
  */
23
33
  export declare class ServiceAlarms extends constructs.Construct {
24
- private readonly action;
34
+ private readonly alarmAction;
35
+ private readonly warningAction;
25
36
  private readonly serviceName;
37
+ private readonly logHandler?;
26
38
  constructor(scope: constructs.Construct, id: string, props: ServiceAlarmsProps);
27
39
  /**
28
40
  * For logs stored as JSON, monitor log entries logged
@@ -35,18 +47,29 @@ export declare class ServiceAlarms extends constructs.Construct {
35
47
  /**
36
48
  * Set to `false` to stop the alarm from sending OK events.
37
49
  * @default true
38
- * */
39
- enableOkAction?: boolean;
50
+ */
51
+ enableOkAlarm?: boolean;
40
52
  /**
41
53
  * An action to use for CloudWatch alarm state changes instead of the default action
42
54
  */
43
55
  action?: cloudwatch.IAlarmAction;
44
56
  }): void;
57
+ addUncaughtJavaExceptionAlarm(props: {
58
+ logGroup: logs.ILogGroup;
59
+ alarmDescription?: string;
60
+ /**
61
+ * @default false
62
+ */
63
+ enabled?: boolean;
64
+ enableOkAlarm?: boolean;
65
+ action?: cloudwatch.IAlarmAction;
66
+ }): void;
45
67
  /**
46
- * Sets up three CloudWatch Alarms for monitoring an ECS service behind a target group:
47
- * 1) one that triggers if the target is responding with too many 5xx errors.
68
+ * Sets up CloudWatch alarms for monitoring an ECS service behind a target group:
69
+ * 1) one that triggers if the target is responding with too many 5xx errors (aggregate 5xx count).
48
70
  * 2) one that triggers if the 95% percentile of response times from the target is too high.
49
71
  * 3) one that triggers if there are no healthy targets or if the load balancer fails to connect to targets.
72
+ * 4) a single5xxResponseAlarm which triggers on a single 5xx response from a target.
50
73
  */
51
74
  addTargetGroupAlarms(props: {
52
75
  /**
@@ -67,6 +90,10 @@ export declare class ServiceAlarms extends constructs.Construct {
67
90
  * @default true
68
91
  */
69
92
  enabled?: boolean;
93
+ /**
94
+ * Whether to attach OK actions for this alarm. @default true
95
+ */
96
+ enableOkAlarm?: boolean;
70
97
  /**
71
98
  * An action to use for CloudWatch alarm state changes instead of the default action
72
99
  */
@@ -95,6 +122,10 @@ export declare class ServiceAlarms extends constructs.Construct {
95
122
  * @default true
96
123
  */
97
124
  enabled?: boolean;
125
+ /**
126
+ * Whether to attach OK actions for this alarm. @default true
127
+ */
128
+ enableOkAlarm?: boolean;
98
129
  /**
99
130
  * An action to use for CloudWatch alarm state changes instead of the default action
100
131
  */
@@ -123,6 +154,10 @@ export declare class ServiceAlarms extends constructs.Construct {
123
154
  * @default true
124
155
  */
125
156
  enabled?: boolean;
157
+ /**
158
+ * Whether to attach OK actions for this alarm. @default true
159
+ */
160
+ enableOkAlarm?: boolean;
126
161
  /**
127
162
  * An action to use for CloudWatch alarm state changes instead of the default action
128
163
  */
@@ -136,10 +171,42 @@ export declare class ServiceAlarms extends constructs.Construct {
136
171
  */
137
172
  evaluationPeriods?: number;
138
173
  /**
139
- * @default 500 milliseconds
174
+ * @default 1s
140
175
  */
141
176
  threshold?: cdk.Duration;
142
177
  description?: string;
143
178
  };
179
+ /**
180
+ * Configuration for an alarm.
181
+ *
182
+ * @default Configured with sane defaults.
183
+ */
184
+ single5xxResponseAlarm?: {
185
+ /**
186
+ * @default true
187
+ */
188
+ enabled?: boolean;
189
+ /**
190
+ * Whether to attach OK actions for this alarm. @default true
191
+ */
192
+ enableOkAlarm?: boolean;
193
+ /**
194
+ * An action to use for CloudWatch alarm state changes instead of the default action
195
+ */
196
+ action?: cloudwatch.IAlarmAction;
197
+ /**
198
+ * @default 60 seconds
199
+ */
200
+ period?: cdk.Duration;
201
+ /**
202
+ * @default 1
203
+ */
204
+ evaluationPeriods?: number;
205
+ /**
206
+ * @default 1
207
+ */
208
+ threshold?: number;
209
+ description?: string;
210
+ };
144
211
  }): void;
145
212
  }
@@ -1,7 +1,9 @@
1
1
  import * as cdk from "aws-cdk-lib";
2
2
  import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
3
3
  import * as logs from "aws-cdk-lib/aws-logs";
4
+ import * as logsDestinations from "aws-cdk-lib/aws-logs-destinations";
4
5
  import * as constructs from "constructs";
6
+ import { jsonErrorFilterPattern } from "./log-filter-patterns";
5
7
  /**
6
8
  * Various alarms and monitoring.
7
9
  *
@@ -11,12 +13,16 @@ import * as constructs from "constructs";
11
13
  * See SlackAlarm construct for SNS Action.
12
14
  */
13
15
  export class ServiceAlarms extends constructs.Construct {
14
- action;
16
+ alarmAction;
17
+ warningAction;
15
18
  serviceName;
19
+ logHandler;
16
20
  constructor(scope, id, props) {
17
21
  super(scope, id);
18
- this.action = props.action;
22
+ this.alarmAction = props.alarmAction;
23
+ this.warningAction = props.warningAction;
19
24
  this.serviceName = props.serviceName;
25
+ this.logHandler = props.logHandler;
20
26
  }
21
27
  /**
22
28
  * For logs stored as JSON, monitor log entries logged
@@ -24,40 +30,114 @@ export class ServiceAlarms extends constructs.Construct {
24
30
  * that causes 500 for logging with liflig-logging.
25
31
  */
26
32
  addJsonErrorAlarm(props) {
27
- const errorMetricFilter = props.logGroup.addMetricFilter("ErrorMetricFilter", {
28
- filterPattern: logs.FilterPattern.any(logs.FilterPattern.stringValue("$.level", "=", "ERROR"),
29
- // FATAL covers some applications we run that uses log4j or
30
- // other libraries. It is not existent in slf4j.
31
- logs.FilterPattern.stringValue("$.level", "=", "FATAL"), logs.FilterPattern.stringValue(
32
- // For liflig-logging.
33
- "$.requestInfo.status.code", "=", "INTERNAL_SERVER_ERROR")),
34
- metricName: "Errors",
35
- metricNamespace: `stack/${cdk.Stack.of(this).stackName}/${this.serviceName}/Errors`,
36
- });
37
- const errorAlarm = errorMetricFilter
38
- .metric()
39
- .with({
40
- statistic: "Sum",
41
- period: cdk.Duration.seconds(60),
42
- })
43
- .createAlarm(this, "ErrorLogAlarm", {
44
- alarmDescription: props.alarmDescription ?? `${this.serviceName} logged an error`,
45
- evaluationPeriods: 1,
46
- threshold: 1,
47
- treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
48
- });
49
- errorAlarm.addAlarmAction(props.action ?? this.action);
50
- if (props.enableOkAction ?? true) {
51
- errorAlarm.addOkAction(props.action ?? this.action);
33
+ const groupToUse = props.logGroup;
34
+ // If no log handler is configured, we create
35
+ // the simple "ERROR" metric alarm.
36
+ if (!this.logHandler) {
37
+ const errorMetricFilter = groupToUse.addMetricFilter("ErrorMetricFilter", {
38
+ filterPattern: jsonErrorFilterPattern(),
39
+ metricName: "Errors",
40
+ metricNamespace: `stack/${cdk.Stack.of(this).stackName}/${this.serviceName}/Errors`,
41
+ });
42
+ const errorAlarm = errorMetricFilter
43
+ .metric()
44
+ .with({
45
+ statistic: "Sum",
46
+ period: cdk.Duration.seconds(60),
47
+ })
48
+ .createAlarm(this, "ErrorLogAlarm", {
49
+ alarmDescription: props.alarmDescription ?? `${this.serviceName} logged an error`,
50
+ evaluationPeriods: 1,
51
+ threshold: 1,
52
+ treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
53
+ });
54
+ // Default to the warning action
55
+ const actionToUse = props.action ?? this.warningAction;
56
+ errorAlarm.addAlarmAction(actionToUse);
57
+ if (props.enableOkAlarm ?? true) {
58
+ errorAlarm.addOkAction(actionToUse);
59
+ }
60
+ }
61
+ if (this.logHandler) {
62
+ props.logGroup.addSubscriptionFilter("liflig-cdk-log-content-to-slack-error-subscription", {
63
+ destination: new logsDestinations.LambdaDestination(this.logHandler),
64
+ filterPattern: jsonErrorFilterPattern(),
65
+ });
66
+ }
67
+ }
68
+ addUncaughtJavaExceptionAlarm(props) {
69
+ if (props.enabled) {
70
+ const filterPattern = logs.FilterPattern.allTerms("Exception in thread");
71
+ // If no log handler is configured, create a simple metric alarm.
72
+ if (!this.logHandler) {
73
+ const errorMetricFilter = props.logGroup.addMetricFilter("UncaughtJavaExceptionFilter", {
74
+ filterPattern: filterPattern,
75
+ metricName: "UncaughtJavaException",
76
+ metricNamespace: `stack/${cdk.Stack.of(this).stackName}/${this.serviceName}/UncaughtJavaException`,
77
+ });
78
+ const errorAlarm = errorMetricFilter
79
+ .metric()
80
+ .with({
81
+ statistic: "Sum",
82
+ period: cdk.Duration.seconds(60),
83
+ })
84
+ .createAlarm(this, "UncaughtJavaExceptionLogAlarm", {
85
+ alarmDescription: props.alarmDescription ??
86
+ `${this.serviceName} logged an uncaught Java exception`,
87
+ evaluationPeriods: 1,
88
+ threshold: 1,
89
+ treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
90
+ });
91
+ // Default to the warning action
92
+ const actionToUse = props.action ?? this.warningAction;
93
+ errorAlarm.addAlarmAction(actionToUse);
94
+ if (props.enableOkAlarm ?? true) {
95
+ errorAlarm.addOkAction(actionToUse);
96
+ }
97
+ }
98
+ // If a log handler is configured, forward matching logs to it.
99
+ if (this.logHandler) {
100
+ props.logGroup.addSubscriptionFilter("liflig-cdk-log-content-to-slack-uncaught-exception-subscription", {
101
+ destination: new logsDestinations.LambdaDestination(this.logHandler),
102
+ filterPattern: filterPattern,
103
+ });
104
+ }
52
105
  }
53
106
  }
54
107
  /**
55
- * Sets up three CloudWatch Alarms for monitoring an ECS service behind a target group:
56
- * 1) one that triggers if the target is responding with too many 5xx errors.
108
+ * Sets up CloudWatch alarms for monitoring an ECS service behind a target group:
109
+ * 1) one that triggers if the target is responding with too many 5xx errors (aggregate 5xx count).
57
110
  * 2) one that triggers if the 95% percentile of response times from the target is too high.
58
111
  * 3) one that triggers if there are no healthy targets or if the load balancer fails to connect to targets.
112
+ * 4) a single5xxResponseAlarm which triggers on a single 5xx response from a target.
59
113
  */
60
114
  addTargetGroupAlarms(props) {
115
+ if (props.single5xxResponseAlarm?.enabled !== false) {
116
+ const single5xxMetric = new cloudwatch.Metric({
117
+ metricName: "HTTPCode_Target_5XX_Count",
118
+ namespace: "AWS/ApplicationELB",
119
+ statistic: "Sum",
120
+ period: props.single5xxResponseAlarm?.period ?? cdk.Duration.seconds(60),
121
+ dimensionsMap: {
122
+ TargetGroup: props.targetGroupFullName,
123
+ LoadBalancer: props.loadBalancerFullName,
124
+ },
125
+ });
126
+ const single5xxAlarm = single5xxMetric.createAlarm(this, "AlbTargetsSingle5xxAlarm", {
127
+ actionsEnabled: true,
128
+ alarmDescription: props.single5xxResponseAlarm?.description ??
129
+ `Load balancer received a 5XX response from target(s) in ECS service '${this.serviceName}'.`,
130
+ evaluationPeriods: props.single5xxResponseAlarm?.evaluationPeriods ?? 1,
131
+ threshold: props.single5xxResponseAlarm?.threshold ?? 1,
132
+ treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
133
+ });
134
+ // Sent to warnings channel by default
135
+ const single5xxAction = props.single5xxResponseAlarm?.action ?? this.warningAction;
136
+ single5xxAlarm.addAlarmAction(single5xxAction);
137
+ if (props.single5xxResponseAlarm?.enableOkAlarm ?? true) {
138
+ single5xxAlarm.addOkAction(single5xxAction);
139
+ }
140
+ }
61
141
  const targetConnectionErrorAlarm = new cloudwatch.Metric({
62
142
  metricName: "TargetConnectionErrorCount",
63
143
  namespace: "AWS/ApplicationELB",
@@ -96,8 +176,12 @@ export class ServiceAlarms extends constructs.Construct {
96
176
  `The load balancer is either receiving bad health checks from or is unable to connect to target(s) in ECS service '${this.serviceName}'`,
97
177
  });
98
178
  if (props.targetHealthAlarm?.enabled ?? true) {
99
- targetHealthAlarm.addAlarmAction(props.targetHealthAlarm?.action ?? this.action);
100
- targetHealthAlarm.addOkAction(props.targetHealthAlarm?.action ?? this.action);
179
+ // Default to the alarm action
180
+ const thAction = props.targetHealthAlarm?.action ?? this.alarmAction;
181
+ targetHealthAlarm.addAlarmAction(thAction);
182
+ if (props.targetHealthAlarm?.enableOkAlarm ?? true) {
183
+ targetHealthAlarm.addOkAction(thAction);
184
+ }
101
185
  }
102
186
  const tooMany5xxResponsesFromTargetsAlarm = new cloudwatch.Metric({
103
187
  metricName: "HTTPCode_Target_5XX_Count",
@@ -118,8 +202,12 @@ export class ServiceAlarms extends constructs.Construct {
118
202
  treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
119
203
  });
120
204
  if (props.tooMany5xxResponsesFromTargetsAlarm?.enabled ?? true) {
121
- tooMany5xxResponsesFromTargetsAlarm.addAlarmAction(props.tooMany5xxResponsesFromTargetsAlarm?.action ?? this.action);
122
- tooMany5xxResponsesFromTargetsAlarm.addOkAction(props.tooMany5xxResponsesFromTargetsAlarm?.action ?? this.action);
205
+ // Default to the alarm action
206
+ const fiveXAction = props.tooMany5xxResponsesFromTargetsAlarm?.action ?? this.alarmAction;
207
+ tooMany5xxResponsesFromTargetsAlarm.addAlarmAction(fiveXAction);
208
+ if (props.tooMany5xxResponsesFromTargetsAlarm?.enableOkAlarm ?? true) {
209
+ tooMany5xxResponsesFromTargetsAlarm.addOkAction(fiveXAction);
210
+ }
123
211
  }
124
212
  const targetResponseTimeAlarm = new cloudwatch.Metric({
125
213
  metricName: "TargetResponseTime",
@@ -132,16 +220,20 @@ export class ServiceAlarms extends constructs.Construct {
132
220
  },
133
221
  }).createAlarm(this, "TargetResponseTimeAlarm", {
134
222
  alarmDescription: props.targetResponseTimeAlarm?.description ??
135
- `5% of responses from ECS service '${this.serviceName}' are taking longer than the expected duration of ${(props.targetResponseTimeAlarm?.threshold ?? cdk.Duration.millis(500)).toMilliseconds()} ms.`,
223
+ `5% of responses from ECS service '${this.serviceName}' are taking longer than the expected duration of ${(props.targetResponseTimeAlarm?.threshold ?? cdk.Duration.seconds(1)).toSeconds({ integral: false })} s.`,
136
224
  comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
137
225
  evaluationPeriods: props.targetResponseTimeAlarm?.evaluationPeriods ?? 1,
138
- threshold: (props.targetResponseTimeAlarm?.threshold ?? cdk.Duration.millis(500)).toSeconds({ integral: false }),
226
+ threshold: (props.targetResponseTimeAlarm?.threshold ?? cdk.Duration.seconds(1)).toSeconds({ integral: false }),
139
227
  treatMissingData: cloudwatch.TreatMissingData.IGNORE,
140
228
  });
141
229
  if (props.targetResponseTimeAlarm?.enabled ?? true) {
142
- targetResponseTimeAlarm.addAlarmAction(props.targetResponseTimeAlarm?.action ?? this.action);
143
- targetResponseTimeAlarm.addOkAction(props.targetResponseTimeAlarm?.action ?? this.action);
230
+ // Default to the warning action
231
+ const rtAction = props.targetResponseTimeAlarm?.action ?? this.warningAction;
232
+ targetResponseTimeAlarm.addAlarmAction(rtAction);
233
+ if (props.targetResponseTimeAlarm?.enableOkAlarm ?? true) {
234
+ targetResponseTimeAlarm.addOkAction(rtAction);
235
+ }
144
236
  }
145
237
  }
146
238
  }
147
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS1hbGFybXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWxhcm1zL3NlcnZpY2UtYWxhcm1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0sYUFBYSxDQUFBO0FBQ2xDLE9BQU8sS0FBSyxVQUFVLE1BQU0sNEJBQTRCLENBQUE7QUFDeEQsT0FBTyxLQUFLLElBQUksTUFBTSxzQkFBc0IsQ0FBQTtBQUM1QyxPQUFPLEtBQUssVUFBVSxNQUFNLFlBQVksQ0FBQTtBQWF4Qzs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLGFBQWMsU0FBUSxVQUFVLENBQUMsU0FBUztJQUNwQyxNQUFNLENBQXlCO0lBQy9CLFdBQVcsQ0FBUTtJQUVwQyxZQUNFLEtBQTJCLEVBQzNCLEVBQVUsRUFDVixLQUF5QjtRQUV6QixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQTtRQUMxQixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUE7SUFDdEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxpQkFBaUIsQ0FBQyxLQVlqQjtRQUNDLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQ3RELG1CQUFtQixFQUNuQjtZQUNFLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FDbkMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUM7WUFDdkQsMkRBQTJEO1lBQzNELGdEQUFnRDtZQUNoRCxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxFQUN2RCxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVc7WUFDNUIsc0JBQXNCO1lBQ3RCLDJC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bGliXCJcbmltcG9ydCAqIGFzIGNsb3Vkd2F0Y2ggZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCJcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sb2dzXCJcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSBcImNvbnN0cnVjdHNcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VBbGFybXNQcm9wcyBleHRlbmRzIGNkay5TdGFja1Byb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBkZWZhdWx0IGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlc1xuICAgKi9cbiAgYWN0aW9uOiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIEVDUyBzZXJ2aWNlLlxuICAgKi9cbiAgc2VydmljZU5hbWU6IHN0cmluZ1xufVxuXG4vKipcbiAqIFZhcmlvdXMgYWxhcm1zIGFuZCBtb25pdG9yaW5nLlxuICpcbiAqIEJ5IGl0c2VsZiBubyBhbGFybXMgaXMgY3JlYXRlZC4gVXNlIHRoZSBtZXRob2RzIGF2YWlsYWJsZVxuICogdG8gYWRkIGFsYXJtcy5cbiAqXG4gKiBTZWUgU2xhY2tBbGFybSBjb25zdHJ1Y3QgZm9yIFNOUyBBY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJ2aWNlQWxhcm1zIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbjogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlTmFtZTogc3RyaW5nXG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IFNlcnZpY2VBbGFybXNQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKVxuXG4gICAgdGhpcy5hY3Rpb24gPSBwcm9wcy5hY3Rpb25cbiAgICB0aGlzLnNlcnZpY2VOYW1lID0gcHJvcHMuc2VydmljZU5hbWVcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgbG9ncyBzdG9yZWQgYXMgSlNPTiwgbW9uaXRvciBsb2cgZW50cmllcyBsb2dnZWRcbiAgICogd2l0aCBsZXZlbCBFUlJPUiBvciBoaWdoZXIsIGFzIHdlbGwgYXMgYW55IHJlcXVlc3RzXG4gICAqIHRoYXQgY2F1c2VzIDUwMCBmb3IgbG9nZ2luZyB3aXRoIGxpZmxpZy1sb2dnaW5nLlxuICAgKi9cbiAgYWRkSnNvbkVycm9yQWxhcm0ocHJvcHM6IHtcbiAgICBsb2dHcm91cDogbG9ncy5JTG9nR3JvdXBcbiAgICBhbGFybURlc2NyaXB0aW9uPzogc3RyaW5nXG4gICAgLyoqXG4gICAgICogU2V0IHRvIGBmYWxzZWAgdG8gc3RvcCB0aGUgYWxhcm0gZnJvbSBzZW5kaW5nIE9LIGV2ZW50cy5cbiAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICogKi9cbiAgICBlbmFibGVPa0FjdGlvbj86IGJvb2xlYW5cbiAgICAvKipcbiAgICAgKiBBbiBhY3Rpb24gdG8gdXNlIGZvciBDbG91ZFdhdGNoIGFsYXJtIHN0YXRlIGNoYW5nZXMgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBhY3Rpb25cbiAgICAgKi9cbiAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICB9KTogdm9pZCB7XG4gICAgY29uc3QgZXJyb3JNZXRyaWNGaWx0ZXIgPSBwcm9wcy5sb2dHcm91cC5hZGRNZXRyaWNGaWx0ZXIoXG4gICAgICBcIkVycm9yTWV0cmljRmlsdGVyXCIsXG4gICAgICB7XG4gICAgICAgIGZpbHRlclBhdHRlcm46IGxvZ3MuRmlsdGVyUGF0dGVybi5hbnkoXG4gICAgICAgICAgbG9ncy5GaWx0ZXJQYXR0ZXJuLnN0cmluZ1ZhbHVlKFwiJC5sZXZlbFwiLCBcIj1cIiwgXCJFUlJPUlwiKSxcbiAgICAgICAgICAvLyBGQVRBTCBjb3ZlcnMgc29tZSBhcHBsaWNhdGlvbnMgd2UgcnVuIHRoYXQgdXNlcyBsb2c0aiBvclxuICAgICAgICAgIC8vIG90aGVyIGxpYnJhcmllcy4gSXQgaXMgbm90IGV4aXN0ZW50IGluIHNsZjRqLlxuICAgICAgICAgIGxvZ3MuRmlsdGVyUGF0dGVybi5zdHJpbmdWYWx1ZShcIiQubGV2ZWxcIiwgXCI9XCIsIFwiRkFUQUxcIiksXG4gICAgICAgICAgbG9ncy5GaWx0ZXJQYXR0ZXJuLnN0cmluZ1ZhbHVlKFxuICAgICAgICAgICAgLy8gRm9yIGxpZmxpZy1sb2dnaW5nLlxuICAgICAgICAgICAgXCIkLnJlcXVlc3RJbmZvLnN0YXR1cy5jb2RlXCIsXG4gICAgICAgICAgICBcIj1cIixcbiAgICAgICAgICAgIFwiSU5URVJOQUxfU0VSVkVSX0VSUk9SXCIsXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICAgbWV0cmljTmFtZTogXCJFcnJvcnNcIixcbiAgICAgICAgbWV0cmljTmFtZXNwYWNlOiBgc3RhY2svJHtjZGsuU3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS8ke1xuICAgICAgICAgIHRoaXMuc2VydmljZU5hbWVcbiAgICAgICAgfS9FcnJvcnNgLFxuICAgICAgfSxcbiAgICApXG5cbiAgICBjb25zdCBlcnJvckFsYXJtID0gZXJyb3JNZXRyaWNGaWx0ZXJcbiAgICAgIC5tZXRyaWMoKVxuICAgICAgLndpdGgoe1xuICAgICAgICBzdGF0aXN0aWM6IFwiU3VtXCIsXG4gICAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgfSlcbiAgICAgIC5jcmVhdGVBbGFybSh0aGlzLCBcIkVycm9yTG9nQWxhcm1cIiwge1xuICAgICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICAgIHByb3BzLmFsYXJtRGVzY3JpcHRpb24gPz8gYCR7dGhpcy5zZXJ2aWNlTmFtZX0gbG9nZ2VkIGFuIGVycm9yYCxcbiAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IDEsXG4gICAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLk5PVF9CUkVBQ0hJTkcsXG4gICAgICB9KVxuXG4gICAgZXJyb3JBbGFybS5hZGRBbGFybUFjdGlvbihwcm9wcy5hY3Rpb24gPz8gdGhpcy5hY3Rpb24pXG4gICAgaWYgKHByb3BzLmVuYWJsZU9rQWN0aW9uID8/IHRydWUpIHtcbiAgICAgIGVycm9yQWxhcm0uYWRkT2tBY3Rpb24ocHJvcHMuYWN0aW9uID8/IHRoaXMuYWN0aW9uKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIHRocmVlIENsb3VkV2F0Y2ggQWxhcm1zIGZvciBtb25pdG9yaW5nIGFuIEVDUyBzZXJ2aWNlIGJlaGluZCBhIHRhcmdldCBncm91cDpcbiAgICogMSkgb25lIHRoYXQgdHJpZ2dlcnMgaWYgdGhlIHRhcmdldCBpcyByZXNwb25kaW5nIHdpdGggdG9vIG1hbnkgNXh4IGVycm9ycy5cbiAgICogMikgb25lIHRoYXQgdHJpZ2dlcnMgaWYgdGhlIDk1JSBwZXJjZW50aWxlIG9mIHJlc3BvbnNlIHRpbWVzIGZyb20gdGhlIHRhcmdldCBpcyB0b28gaGlnaC5cbiAgICogMykgb25lIHRoYXQgdHJpZ2dlcnMgaWYgdGhlcmUgYXJlIG5vIGhlYWx0aHkgdGFyZ2V0cyBvciBpZiB0aGUgbG9hZCBiYWxhbmNlciBmYWlscyB0byBjb25uZWN0IHRvIHRhcmdldHMuXG4gICAqL1xuICBhZGRUYXJnZXRHcm91cEFsYXJtcyhwcm9wczoge1xuICAgIC8qKlxuICAgICAqIFRoZSBmdWxsIG5hbWUgb2YgdGhlIHRhcmdldCBncm91cC5cbiAgICAgKi9cbiAgICB0YXJnZXRHcm91cEZ1bGxOYW1lOiBzdHJpbmdcbiAgICAvKipcbiAgICAgKiBUaGUgZnVsbCBuYW1lIG9mIHRoZSBhcHBsaWNhdGlvbiBsb2FkIGJhbGFuY2VyLlxuICAgICAqL1xuICAgIGxvYWRCYWxhbmNlckZ1bGxOYW1lOiBzdHJpbmdcbiAgICAvKipcbiAgICAgKiBDb25maWd1cmF0aW9uIGZvciBhIGNvbXBvc2l0ZSBhbGFybS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IENvbmZpZ3VyZWQgd2l0aCBzYW5lIGRlZmF1bHRzLlxuICAgICAqL1xuICAgIHRhcmdldEhlYWx0aEFsYXJtPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZWQ/OiBib29sZWFuXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlcyBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGFjdGlvblxuICAgICAgICovXG4gICAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA2MCBzZWNvbmRzXG4gICAgICAgKi9cbiAgICAgIHBlcmlvZD86IGNkay5EdXJhdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgKi9cbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAqL1xuICAgICAgdGhyZXNob2xkPzogbnVtYmVyXG4gICAgICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb25maWd1cmF0aW9uIGZvciBhbiBhbGFybS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IENvbmZpZ3VyZWQgd2l0aCBzYW5lIGRlZmF1bHRzLlxuICAgICAqL1xuICAgIHRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZWQ/OiBib29sZWFuXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlcyBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGFjdGlvblxuICAgICAgICovXG4gICAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA2MCBzZWNvbmRzXG4gICAgICAgKi9cbiAgICAgIHBlcmlvZD86IGNkay5EdXJhdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAzXG4gICAgICAgKi9cbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDEwXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IG51bWJlclxuICAgICAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiBmb3IgYW4gYWxhcm0uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBDb25maWd1cmVkIHdpdGggc2FuZSBkZWZhdWx0cy5cbiAgICAgKi9cbiAgICB0YXJnZXRSZXNwb25zZVRpbWVBbGFybT86IHtcbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICovXG4gICAgICBlbmFibGVkPzogYm9vbGVhblxuICAgICAgLyoqXG4gICAgICAgKiBBbiBhY3Rpb24gdG8gdXNlIGZvciBDbG91ZFdhdGNoIGFsYXJtIHN0YXRlIGNoYW5nZXMgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBhY3Rpb25cbiAgICAgICAqL1xuICAgICAgYWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgNSBtaW51dGVzXG4gICAgICAgKi9cbiAgICAgIHBlcmlvZD86IGNkay5EdXJhdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgKi9cbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDUwMCBtaWxsaXNlY29uZHNcbiAgICAgICAqL1xuICAgICAgdGhyZXNob2xkPzogY2RrLkR1cmF0aW9uXG4gICAgICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuICAgIH1cbiAgfSk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldENvbm5lY3Rpb25FcnJvckFsYXJtID0gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIG1ldHJpY05hbWU6IFwiVGFyZ2V0Q29ubmVjdGlvbkVycm9yQ291bnRcIixcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvQXBwbGljYXRpb25FTEJcIixcbiAgICAgIHN0YXRpc3RpYzogXCJTdW1cIixcbiAgICAgIHBlcmlvZDogcHJvcHMudGFyZ2V0SGVhbHRoQWxhcm0/LnBlcmlvZCA/PyBjZGsuRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFRhcmdldEdyb3VwOiBwcm9wcy50YXJnZXRHcm91cEZ1bGxOYW1lLFxuICAgICAgICBMb2FkQmFsYW5jZXI6IHByb3BzLmxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgfSxcbiAgICB9KS5jcmVhdGVBbGFybSh0aGlzLCBcIkNvbm5lY3Rpb25BbGFybVwiLCB7XG4gICAgICBhY3Rpb25zRW5hYmxlZDogdHJ1ZSxcbiAgICAgIGFsYXJtRGVzY3JpcHRpb246IGBMb2FkIGJhbGFuY2VyIGlzIGZhaWxpbmcgdG8gY29ubmVjdCB0byB0YXJnZXQocykgaW4gRUNTIHNlcnZpY2UgJyR7dGhpcy5zZXJ2aWNlTmFtZX0nLmAsXG4gICAgICBldmFsdWF0aW9uUGVyaW9kczogcHJvcHMudGFyZ2V0SGVhbHRoQWxhcm0/LmV2YWx1YXRpb25QZXJpb2RzID8/IDEsXG4gICAgICB0aHJlc2hvbGQ6IDEsXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICB9KVxuXG4gICAgY29uc3QgaGVhbHRoQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJIZWFsdGh5SG9zdENvdW50XCIsXG4gICAgICBuYW1lc3BhY2U6IFwiQVdTL0FwcGxpY2F0aW9uRUxCXCIsXG4gICAgICBzdGF0aXN0aWM6IFwiTWluaW11bVwiLFxuICAgICAgcGVyaW9kOiBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8ucGVyaW9kID8/IGNkay5EdXJhdGlvbi5zZWNvbmRzKDYwKSxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgVGFyZ2V0R3JvdXA6IHByb3BzLnRhcmdldEdyb3VwRnVsbE5hbWUsXG4gICAgICAgIExvYWRCYWxhbmNlcjogcHJvcHMubG9hZEJhbGFuY2VyRnVsbE5hbWUsXG4gICAgICB9LFxuICAgIH0pLmNyZWF0ZUFsYXJtKHRoaXMsIFwiSGVhbHRoQWxhcm1cIiwge1xuICAgICAgYWxhcm1EZXNjcmlwdGlvbjogYFRoZXJlIGFyZSBubyBoZWFsdGh5IHRhcmdldChzKSBpbiBFQ1Mgc2VydmljZSAnJHt0aGlzLnNlcnZpY2VOYW1lfScuYCxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuTEVTU19USEFOX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMSxcbiAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5CUkVBQ0hJTkcsXG4gICAgfSlcblxuICAgIGNvbnN0IHRhcmdldEhlYWx0aEFsYXJtID0gbmV3IGNsb3Vkd2F0Y2guQ29tcG9zaXRlQWxhcm0oXG4gICAgICB0aGlzLFxuICAgICAgXCJUYXJnZXRIZWFsdGhBbGFybVwiLFxuICAgICAge1xuICAgICAgICBhbGFybVJ1bGU6IGNkay5hd3NfY2xvdWR3YXRjaC5BbGFybVJ1bGUuYW55T2YoXG4gICAgICAgICAgY2RrLmF3c19jbG91ZHdhdGNoLkFsYXJtUnVsZS5mcm9tQWxhcm0oXG4gICAgICAgICAgICB0YXJnZXRDb25uZWN0aW9uRXJyb3JBbGFybSxcbiAgICAgICAgICAgIGNsb3Vkd2F0Y2guQWxhcm1TdGF0ZS5BTEFSTSxcbiAgICAgICAgICApLFxuICAgICAgICAgIGNkay5hd3NfY2xvdWR3YXRjaC5BbGFybVJ1bGUuZnJvbUFsYXJtKFxuICAgICAgICAgICAgaGVhbHRoQWxhcm0sXG4gICAgICAgICAgICBjbG91ZHdhdGNoLkFsYXJtU3RhdGUuQUxBUk0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgICBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8uZGVzY3JpcHRpb24gPz9cbiAgICAgICAgICBgVGhlIGxvYWQgYmFsYW5jZXIgaXMgZWl0aGVyIHJlY2VpdmluZyBiYWQgaGVhbHRoIGNoZWNrcyBmcm9tIG9yIGlzIHVuYWJsZSB0byBjb25uZWN0IHRvIHRhcmdldChzKSBpbiBFQ1Mgc2VydmljZSAnJHt0aGlzLnNlcnZpY2VOYW1lfSdgLFxuICAgICAgfSxcbiAgICApXG4gICAgaWYgKHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5lbmFibGVkID8/IHRydWUpIHtcbiAgICAgIHRhcmdldEhlYWx0aEFsYXJtLmFkZEFsYXJtQWN0aW9uKFxuICAgICAgICBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8uYWN0aW9uID8/IHRoaXMuYWN0aW9uLFxuICAgICAgKVxuICAgICAgdGFyZ2V0SGVhbHRoQWxhcm0uYWRkT2tBY3Rpb24oXG4gICAgICAgIHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5hY3Rpb24gPz8gdGhpcy5hY3Rpb24sXG4gICAgICApXG4gICAgfVxuXG4gICAgY29uc3QgdG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJIVFRQQ29kZV9UYXJnZXRfNVhYX0NvdW50XCIsXG4gICAgICBuYW1lc3BhY2U6IFwiQVdTL0FwcGxpY2F0aW9uRUxCXCIsXG4gICAgICBzdGF0aXN0aWM6IFwiU3VtXCIsXG4gICAgICBwZXJpb2Q6XG4gICAgICAgIHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5wZXJpb2QgPz9cbiAgICAgICAgY2RrLkR1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICBUYXJnZXRHcm91cDogcHJvcHMudGFyZ2V0R3JvdXBGdWxsTmFtZSxcbiAgICAgICAgTG9hZEJhbGFuY2VyOiBwcm9wcy5sb2FkQmFsYW5jZXJGdWxsTmFtZSxcbiAgICAgIH0sXG4gICAgfSkuY3JlYXRlQWxhcm0odGhpcywgXCJBbGJUYXJnZXRzNXh4QWxhcm1cIiwge1xuICAgICAgYWN0aW9uc0VuYWJsZWQ6IHRydWUsXG4gICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICBwcm9wcy50b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybT8uZGVzY3JpcHRpb24gPz9cbiAgICAgICAgYExvYWQgYmFsYW5jZXIgcmVjZWl2ZWQgdG9vIG1hbnkgNVhYIHJlc3BvbnNlcyBmcm9tIHRhcmdldChzKSBpbiBFQ1Mgc2VydmljZSAnJHt0aGlzLnNlcnZpY2VOYW1lfScuYCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOlxuICAgICAgICBwcm9wcy50b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybT8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMyxcbiAgICAgIHRocmVzaG9sZDogcHJvcHMudG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0/LnRocmVzaG9sZCA/PyAxMCxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgIH0pXG4gICAgaWYgKHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5lbmFibGVkID8/IHRydWUpIHtcbiAgICAgIHRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtLmFkZEFsYXJtQWN0aW9uKFxuICAgICAgICBwcm9wcy50b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybT8uYWN0aW9uID8/IHRoaXMuYWN0aW9uLFxuICAgICAgKVxuICAgICAgdG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0uYWRkT2tBY3Rpb24oXG4gICAgICAgIHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5hY3Rpb24gPz8gdGhpcy5hY3Rpb24sXG4gICAgICApXG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJUYXJnZXRSZXNwb25zZVRpbWVcIixcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvQXBwbGljYXRpb25FTEJcIixcbiAgICAgIHN0YXRpc3RpYzogXCJwOTVcIixcbiAgICAgIHBlcmlvZDogcHJvcHMudGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0/LnBlcmlvZCA/PyBjZGsuRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgTG9hZEJhbGFuY2VyOiBwcm9wcy5sb2FkQmFsYW5jZXJGdWxsTmFtZSxcbiAgICAgICAgVGFyZ2V0R3JvdXA6IHByb3BzLnRhcmdldEdyb3VwRnVsbE5hbWUsXG4gICAgICB9LFxuICAgIH0pLmNyZWF0ZUFsYXJtKHRoaXMsIFwiVGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm1cIiwge1xuICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgcHJvcHMudGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0/LmRlc2NyaXB0aW9uID8/XG4gICAgICAgIGA1JSBvZiByZXNwb25zZXMgZnJvbSBFQ1Mgc2VydmljZSAnJHtcbiAgICAgICAgICB0aGlzLnNlcnZpY2VOYW1lXG4gICAgICAgIH0nIGFyZSB0YWtpbmcgbG9uZ2VyIHRoYW4gdGhlIGV4cGVjdGVkIGR1cmF0aW9uIG9mICR7KFxuICAgICAgICAgIHByb3BzLnRhcmdldFJlc3BvbnNlVGltZUFsYXJtPy50aHJlc2hvbGQgPz8gY2RrLkR1cmF0aW9uLm1pbGxpcyg1MDApXG4gICAgICAgICkudG9NaWxsaXNlY29uZHMoKX0gbXMuYCxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMSxcbiAgICAgIHRocmVzaG9sZDogKFxuICAgICAgICBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8udGhyZXNob2xkID8/IGNkay5EdXJhdGlvbi5taWxsaXMoNTAwKVxuICAgICAgKS50b1NlY29uZHMoeyBpbnRlZ3JhbDogZmFsc2UgfSksXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgIH0pXG4gICAgaWYgKHByb3BzLnRhcmdldFJlc3BvbnNlVGltZUFsYXJtPy5lbmFibGVkID8/IHRydWUpIHtcbiAgICAgIHRhcmdldFJlc3BvbnNlVGltZUFsYXJtLmFkZEFsYXJtQWN0aW9uKFxuICAgICAgICBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8uYWN0aW9uID8/IHRoaXMuYWN0aW9uLFxuICAgICAgKVxuICAgICAgdGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0uYWRkT2tBY3Rpb24oXG4gICAgICAgIHByb3BzLnRhcmdldFJlc3BvbnNlVGltZUFsYXJtPy5hY3Rpb24gPz8gdGhpcy5hY3Rpb24sXG4gICAgICApXG4gICAgfVxuICB9XG59XG4iXX0=
239
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS1hbGFybXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWxhcm1zL3NlcnZpY2UtYWxhcm1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0sYUFBYSxDQUFBO0FBQ2xDLE9BQU8sS0FBSyxVQUFVLE1BQU0sNEJBQTRCLENBQUE7QUFFeEQsT0FBTyxLQUFLLElBQUksTUFBTSxzQkFBc0IsQ0FBQTtBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sbUNBQW1DLENBQUE7QUFDckUsT0FBTyxLQUFLLFVBQVUsTUFBTSxZQUFZLENBQUE7QUFDeEMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFzQjlEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sYUFBYyxTQUFRLFVBQVUsQ0FBQyxTQUFTO0lBQ3BDLFdBQVcsQ0FBeUI7SUFDcEMsYUFBYSxDQUF5QjtJQUN0QyxXQUFXLENBQVE7SUFDbkIsVUFBVSxDQUFtQjtJQUU5QyxZQUNFLEtBQTJCLEVBQzNCLEVBQVUsRUFDVixLQUF5QjtRQUV6QixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQTtRQUNwQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUE7UUFDeEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFBO1FBQ3BDLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQTtJQUNwQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEtBWWpCO1FBQ0MsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQTtRQUVqQyw2Q0FBNkM7UUFDN0MsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENB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dCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIlxuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIlxuaW1wb3J0IHR5cGUgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIlxuaW1wb3J0ICogYXMgbG9ncyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxvZ3NcIlxuaW1wb3J0ICogYXMgbG9nc0Rlc3RpbmF0aW9ucyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxvZ3MtZGVzdGluYXRpb25zXCJcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSBcImNvbnN0cnVjdHNcIlxuaW1wb3J0IHsganNvbkVycm9yRmlsdGVyUGF0dGVybiB9IGZyb20gXCIuL2xvZy1maWx0ZXItcGF0dGVybnNcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VBbGFybXNQcm9wcyBleHRlbmRzIGNkay5TdGFja1Byb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBDbG91ZFdhdGNoIEFsYXJtIGFjdGlvbiB0byB1c2UgZm9yIGhpZ2gtc2V2ZXJpdHkgYWxhcm1zLlxuICAgKi9cbiAgYWxhcm1BY3Rpb246IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uXG4gIC8qKlxuICAgKiBUaGUgQ2xvdWRXYXRjaCBBbGFybSBhY3Rpb24gdG8gdXNlIGZvciB3YXJuaW5ncy5cbiAgICovXG4gIHdhcm5pbmdBY3Rpb246IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgRUNTIHNlcnZpY2UuXG4gICAqL1xuICBzZXJ2aWNlTmFtZTogc3RyaW5nXG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYW1iZGEgZnVuY3Rpb24gdGhhdCB3aWxsIHJlY2VpdmUgZm9yd2FyZGVkIGxvZyBldmVudHMuXG4gICAqIElmIHByb3ZpZGVkLCBzdWJzY3JpcHRpb24gZmlsdGVycyB3aWxsIGJlIGNyZWF0ZWQgdG8gZm9yd2FyZCBtYXRjaGluZyBsb2dzLlxuICAgKi9cbiAgbG9nSGFuZGxlcj86IGxhbWJkYS5JRnVuY3Rpb25cbn1cblxuLyoqXG4gKiBWYXJpb3VzIGFsYXJtcyBhbmQgbW9uaXRvcmluZy5cbiAqXG4gKiBCeSBpdHNlbGYgbm8gYWxhcm1zIGlzIGNyZWF0ZWQuIFVzZSB0aGUgbWV0aG9kcyBhdmFpbGFibGVcbiAqIHRvIGFkZCBhbGFybXMuXG4gKlxuICogU2VlIFNsYWNrQWxhcm0gY29uc3RydWN0IGZvciBTTlMgQWN0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgU2VydmljZUFsYXJtcyBleHRlbmRzIGNvbnN0cnVjdHMuQ29uc3RydWN0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhbGFybUFjdGlvbjogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgcHJpdmF0ZSByZWFkb25seSB3YXJuaW5nQWN0aW9uOiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2VOYW1lOiBzdHJpbmdcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dIYW5kbGVyPzogbGFtYmRhLklGdW5jdGlvblxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBTZXJ2aWNlQWxhcm1zUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZClcblxuICAgIHRoaXMuYWxhcm1BY3Rpb24gPSBwcm9wcy5hbGFybUFjdGlvblxuICAgIHRoaXMud2FybmluZ0FjdGlvbiA9IHByb3BzLndhcm5pbmdBY3Rpb25cbiAgICB0aGlzLnNlcnZpY2VOYW1lID0gcHJvcHMuc2VydmljZU5hbWVcbiAgICB0aGlzLmxvZ0hhbmRsZXIgPSBwcm9wcy5sb2dIYW5kbGVyXG4gIH1cblxuICAvKipcbiAgICogRm9yIGxvZ3Mgc3RvcmVkIGFzIEpTT04sIG1vbml0b3IgbG9nIGVudHJpZXMgbG9nZ2VkXG4gICAqIHdpdGggbGV2ZWwgRVJST1Igb3IgaGlnaGVyLCBhcyB3ZWxsIGFzIGFueSByZXF1ZXN0c1xuICAgKiB0aGF0IGNhdXNlcyA1MDAgZm9yIGxvZ2dpbmcgd2l0aCBsaWZsaWctbG9nZ2luZy5cbiAgICovXG4gIGFkZEpzb25FcnJvckFsYXJtKHByb3BzOiB7XG4gICAgbG9nR3JvdXA6IGxvZ3MuSUxvZ0dyb3VwXG4gICAgYWxhcm1EZXNjcmlwdGlvbj86IHN0cmluZ1xuICAgIC8qKlxuICAgICAqIFNldCB0byBgZmFsc2VgIHRvIHN0b3AgdGhlIGFsYXJtIGZyb20gc2VuZGluZyBPSyBldmVudHMuXG4gICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAqL1xuICAgIGVuYWJsZU9rQWxhcm0/OiBib29sZWFuXG4gICAgLyoqXG4gICAgICogQW4gYWN0aW9uIHRvIHVzZSBmb3IgQ2xvdWRXYXRjaCBhbGFybSBzdGF0ZSBjaGFuZ2VzIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgYWN0aW9uXG4gICAgICovXG4gICAgYWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgfSk6IHZvaWQge1xuICAgIGNvbnN0IGdyb3VwVG9Vc2UgPSBwcm9wcy5sb2dHcm91cFxuXG4gICAgLy8gSWYgbm8gbG9nIGhhbmRsZXIgaXMgY29uZmlndXJlZCwgd2UgY3JlYXRlXG4gICAgLy8gdGhlIHNpbXBsZSBcIkVSUk9SXCIgbWV0cmljIGFsYXJtLlxuICAgIGlmICghdGhpcy5sb2dIYW5kbGVyKSB7XG4gICAgICBjb25zdCBlcnJvck1ldHJpY0ZpbHRlciA9IGdyb3VwVG9Vc2UuYWRkTWV0cmljRmlsdGVyKFxuICAgICAgICBcIkVycm9yTWV0cmljRmlsdGVyXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBmaWx0ZXJQYXR0ZXJuOiBqc29uRXJyb3JGaWx0ZXJQYXR0ZXJuKCksXG4gICAgICAgICAgbWV0cmljTmFtZTogXCJFcnJvcnNcIixcbiAgICAgICAgICBtZXRyaWNOYW1lc3BhY2U6IGBzdGFjay8ke2Nkay5TdGFjay5vZih0aGlzKS5zdGFja05hbWV9LyR7dGhpcy5zZXJ2aWNlTmFtZX0vRXJyb3JzYCxcbiAgICAgICAgfSxcbiAgICAgIClcblxuICAgICAgY29uc3QgZXJyb3JBbGFybSA9IGVycm9yTWV0cmljRmlsdGVyXG4gICAgICAgIC5tZXRyaWMoKVxuICAgICAgICAud2l0aCh7XG4gICAgICAgICAgc3RhdGlzdGljOiBcIlN1bVwiLFxuICAgICAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgICB9KVxuICAgICAgICAuY3JlYXRlQWxhcm0odGhpcywgXCJFcnJvckxvZ0FsYXJtXCIsIHtcbiAgICAgICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICAgICAgcHJvcHMuYWxhcm1EZXNjcmlwdGlvbiA/PyBgJHt0aGlzLnNlcnZpY2VOYW1lfSBsb2dnZWQgYW4gZXJyb3JgLFxuICAgICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiAxLFxuICAgICAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgICAgfSlcblxuICAgICAgLy8gRGVmYXVsdCB0byB0aGUgd2FybmluZyBhY3Rpb25cbiAgICAgIGNvbnN0IGFjdGlvblRvVXNlID0gcHJvcHMuYWN0aW9uID8/IHRoaXMud2FybmluZ0FjdGlvblxuICAgICAgZXJyb3JBbGFybS5hZGRBbGFybUFjdGlvbihhY3Rpb25Ub1VzZSlcbiAgICAgIGlmIChwcm9wcy5lbmFibGVPa0FsYXJtID8/IHRydWUpIHtcbiAgICAgICAgZXJyb3JBbGFybS5hZGRPa0FjdGlvbihhY3Rpb25Ub1VzZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5sb2dIYW5kbGVyKSB7XG4gICAgICBwcm9wcy5sb2dHcm91cC5hZGRTdWJzY3JpcHRpb25GaWx0ZXIoXG4gICAgICAgIFwibGlmbGlnLWNkay1sb2ctY29udGVudC10by1zbGFjay1lcnJvci1zdWJzY3JpcHRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIGRlc3RpbmF0aW9uOiBuZXcgbG9nc0Rlc3RpbmF0aW9ucy5MYW1iZGFEZXN0aW5hdGlvbih0aGlzLmxvZ0hhbmRsZXIpLFxuICAgICAgICAgIGZpbHRlclBhdHRlcm46IGpzb25FcnJvckZpbHRlclBhdHRlcm4oKSxcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBhZGRVbmNhdWdodEphdmFFeGNlcHRpb25BbGFybShwcm9wczoge1xuICAgIGxvZ0dyb3VwOiBsb2dzLklMb2dHcm91cFxuICAgIGFsYXJtRGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICAvKipcbiAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAqL1xuICAgIGVuYWJsZWQ/OiBib29sZWFuXG4gICAgZW5hYmxlT2tBbGFybT86IGJvb2xlYW5cbiAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICB9KTogdm9pZCB7XG4gICAgaWYgKHByb3BzLmVuYWJsZWQpIHtcbiAgICAgIGNvbnN0IGZpbHRlclBhdHRlcm4gPSBsb2dzLkZpbHRlclBhdHRlcm4uYWxsVGVybXMoXCJFeGNlcHRpb24gaW4gdGhyZWFkXCIpXG5cbiAgICAgIC8vIElmIG5vIGxvZyBoYW5kbGVyIGlzIGNvbmZpZ3VyZWQsIGNyZWF0ZSBhIHNpbXBsZSBtZXRyaWMgYWxhcm0uXG4gICAgICBpZiAoIXRoaXMubG9nSGFuZGxlcikge1xuICAgICAgICBjb25zdCBlcnJvck1ldHJpY0ZpbHRlciA9IHByb3BzLmxvZ0dyb3VwLmFkZE1ldHJpY0ZpbHRlcihcbiAgICAgICAgICBcIlVuY2F1Z2h0SmF2YUV4Y2VwdGlvbkZpbHRlclwiLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpbHRlclBhdHRlcm46IGZpbHRlclBhdHRlcm4sXG4gICAgICAgICAgICBtZXRyaWNOYW1lOiBcIlVuY2F1Z2h0SmF2YUV4Y2VwdGlvblwiLFxuICAgICAgICAgICAgbWV0cmljTmFtZXNwYWNlOiBgc3RhY2svJHtjZGsuU3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS8ke3RoaXMuc2VydmljZU5hbWV9L1VuY2F1Z2h0SmF2YUV4Y2VwdGlvbmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgKVxuXG4gICAgICAgIGNvbnN0IGVycm9yQWxhcm0gPSBlcnJvck1ldHJpY0ZpbHRlclxuICAgICAgICAgIC5tZXRyaWMoKVxuICAgICAgICAgIC53aXRoKHtcbiAgICAgICAgICAgIHN0YXRpc3RpYzogXCJTdW1cIixcbiAgICAgICAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNyZWF0ZUFsYXJtKHRoaXMsIFwiVW5jYXVnaHRKYXZhRXhjZXB0aW9uTG9nQWxhcm1cIiwge1xuICAgICAgICAgICAgYWxhcm1EZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgcHJvcHMuYWxhcm1EZXNjcmlwdGlvbiA/P1xuICAgICAgICAgICAgICBgJHt0aGlzLnNlcnZpY2VOYW1lfSBsb2dnZWQgYW4gdW5jYXVnaHQgSmF2YSBleGNlcHRpb25gLFxuICAgICAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IDEsXG4gICAgICAgICAgICB0aHJlc2hvbGQ6IDEsXG4gICAgICAgICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgICAgICB9KVxuXG4gICAgICAgIC8vIERlZmF1bHQgdG8gdGhlIHdhcm5pbmcgYWN0aW9uXG4gICAgICAgIGNvbnN0IGFjdGlvblRvVXNlID0gcHJvcHMuYWN0aW9uID8/IHRoaXMud2FybmluZ0FjdGlvblxuICAgICAgICBlcnJvckFsYXJtLmFkZEFsYXJtQWN0aW9uKGFjdGlvblRvVXNlKVxuICAgICAgICBpZiAocHJvcHMuZW5hYmxlT2tBbGFybSA/PyB0cnVlKSB7XG4gICAgICAgICAgZXJyb3JBbGFybS5hZGRPa0FjdGlvbihhY3Rpb25Ub1VzZSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiBhIGxvZyBoYW5kbGVyIGlzIGNvbmZpZ3VyZWQsIGZvcndhcmQgbWF0Y2hpbmcgbG9ncyB0byBpdC5cbiAgICAgIGlmICh0aGlzLmxvZ0hhbmRsZXIpIHtcbiAgICAgICAgcHJvcHMubG9nR3JvdXAuYWRkU3Vic2NyaXB0aW9uRmlsdGVyKFxuICAgICAgICAgIFwibGlmbGlnLWNkay1sb2ctY29udGVudC10by1zbGFjay11bmNhdWdodC1leGNlcHRpb24tc3Vic2NyaXB0aW9uXCIsXG4gICAgICAgICAge1xuICAgICAgICAgICAgZGVzdGluYXRpb246IG5ldyBsb2dzRGVzdGluYXRpb25zLkxhbWJkYURlc3RpbmF0aW9uKFxuICAgICAgICAgICAgICB0aGlzLmxvZ0hhbmRsZXIsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZmlsdGVyUGF0dGVybjogZmlsdGVyUGF0dGVybixcbiAgICAgICAgICB9LFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdXAgQ2xvdWRXYXRjaCBhbGFybXMgZm9yIG1vbml0b3JpbmcgYW4gRUNTIHNlcnZpY2UgYmVoaW5kIGEgdGFyZ2V0IGdyb3VwOlxuICAgKiAxKSBvbmUgdGhhdCB0cmlnZ2VycyBpZiB0aGUgdGFyZ2V0IGlzIHJlc3BvbmRpbmcgd2l0aCB0b28gbWFueSA1eHggZXJyb3JzIChhZ2dyZWdhdGUgNXh4IGNvdW50KS5cbiAgICogMikgb25lIHRoYXQgdHJpZ2dlcnMgaWYgdGhlIDk1JSBwZXJjZW50aWxlIG9mIHJlc3BvbnNlIHRpbWVzIGZyb20gdGhlIHRhcmdldCBpcyB0b28gaGlnaC5cbiAgICogMykgb25lIHRoYXQgdHJpZ2dlcnMgaWYgdGhlcmUgYXJlIG5vIGhlYWx0aHkgdGFyZ2V0cyBvciBpZiB0aGUgbG9hZCBiYWxhbmNlciBmYWlscyB0byBjb25uZWN0IHRvIHRhcmdldHMuXG4gICAqIDQpIGEgc2luZ2xlNXh4UmVzcG9uc2VBbGFybSB3aGljaCB0cmlnZ2VycyBvbiBhIHNpbmdsZSA1eHggcmVzcG9uc2UgZnJvbSBhIHRhcmdldC5cbiAgICovXG4gIGFkZFRhcmdldEdyb3VwQWxhcm1zKHByb3BzOiB7XG4gICAgLyoqXG4gICAgICogVGhlIGZ1bGwgbmFtZSBvZiB0aGUgdGFyZ2V0IGdyb3VwLlxuICAgICAqL1xuICAgIHRhcmdldEdyb3VwRnVsbE5hbWU6IHN0cmluZ1xuICAgIC8qKlxuICAgICAqIFRoZSBmdWxsIG5hbWUgb2YgdGhlIGFwcGxpY2F0aW9uIGxvYWQgYmFsYW5jZXIuXG4gICAgICovXG4gICAgbG9hZEJhbGFuY2VyRnVsbE5hbWU6IHN0cmluZ1xuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIGEgY29tcG9zaXRlIGFsYXJtLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgQ29uZmlndXJlZCB3aXRoIHNhbmUgZGVmYXVsdHMuXG4gICAgICovXG4gICAgdGFyZ2V0SGVhbHRoQWxhcm0/OiB7XG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAqL1xuICAgICAgZW5hYmxlZD86IGJvb2xlYW5cbiAgICAgIC8qKlxuICAgICAgICogV2hldGhlciB0byBhdHRhY2ggT0sgYWN0aW9ucyBmb3IgdGhpcyBhbGFybS4gQGRlZmF1bHQgdHJ1ZVxuICAgICAgICovXG4gICAgICBlbmFibGVPa0FsYXJtPzogYm9vbGVhblxuICAgICAgLyoqXG4gICAgICAgKiBBbiBhY3Rpb24gdG8gdXNlIGZvciBDbG91ZFdhdGNoIGFsYXJtIHN0YXRlIGNoYW5nZXMgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBhY3Rpb25cbiAgICAgICAqL1xuICAgICAgYWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgNjAgc2Vjb25kc1xuICAgICAgICovXG4gICAgICBwZXJpb2Q/OiBjZGsuRHVyYXRpb25cbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICovXG4gICAgICBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlclxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IG51bWJlclxuICAgICAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiBmb3IgYW4gYWxhcm0uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBDb25maWd1cmVkIHdpdGggc2FuZSBkZWZhdWx0cy5cbiAgICAgKi9cbiAgICB0b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybT86IHtcbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICovXG4gICAgICBlbmFibGVkPzogYm9vbGVhblxuICAgICAgLyoqXG4gICAgICAgKiBXaGV0aGVyIHRvIGF0dGFjaCBPSyBhY3Rpb25zIGZvciB0aGlzIGFsYXJtLiBAZGVmYXVsdCB0cnVlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZU9rQWxhcm0/OiBib29sZWFuXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlcyBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGFjdGlvblxuICAgICAgICovXG4gICAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA2MCBzZWNvbmRzXG4gICAgICAgKi9cbiAgICAgIHBlcmlvZD86IGNkay5EdXJhdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAzXG4gICAgICAgKi9cbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDEwXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IG51bWJlclxuICAgICAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiBmb3IgYW4gYWxhcm0uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBDb25maWd1cmVkIHdpdGggc2FuZSBkZWZhdWx0cy5cbiAgICAgKi9cbiAgICB0YXJnZXRSZXNwb25zZVRpbWVBbGFybT86IHtcbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICovXG4gICAgICBlbmFibGVkPzogYm9vbGVhblxuICAgICAgLyoqXG4gICAgICAgKiBXaGV0aGVyIHRvIGF0dGFjaCBPSyBhY3Rpb25zIGZvciB0aGlzIGFsYXJtLiBAZGVmYXVsdCB0cnVlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZU9rQWxhcm0/OiBib29sZWFuXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlcyBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGFjdGlvblxuICAgICAgICovXG4gICAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA1IG1pbnV0ZXNcbiAgICAgICAqL1xuICAgICAgcGVyaW9kPzogY2RrLkR1cmF0aW9uXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAqL1xuICAgICAgZXZhbHVhdGlvblBlcmlvZHM/OiBudW1iZXJcbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgMXNcbiAgICAgICAqL1xuICAgICAgdGhyZXNob2xkPzogY2RrLkR1cmF0aW9uXG4gICAgICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb25maWd1cmF0aW9uIGZvciBhbiBhbGFybS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IENvbmZpZ3VyZWQgd2l0aCBzYW5lIGRlZmF1bHRzLlxuICAgICAqL1xuICAgIHNpbmdsZTV4eFJlc3BvbnNlQWxhcm0/OiB7XG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAqL1xuICAgICAgZW5hYmxlZD86IGJvb2xlYW5cbiAgICAgIC8qKlxuICAgICAgICogV2hldGhlciB0byBhdHRhY2ggT0sgYWN0aW9ucyBmb3IgdGhpcyBhbGFybS4gQGRlZmF1bHQgdHJ1ZVxuICAgICAgICovXG4gICAgICBlbmFibGVPa0FsYXJtPzogYm9vbGVhblxuICAgICAgLyoqXG4gICAgICAgKiBBbiBhY3Rpb24gdG8gdXNlIGZvciBDbG91ZFdhdGNoIGFsYXJtIHN0YXRlIGNoYW5nZXMgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBhY3Rpb25cbiAgICAgICAqL1xuICAgICAgYWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgNjAgc2Vjb25kc1xuICAgICAgICovXG4gICAgICBwZXJpb2Q/OiBjZGsuRHVyYXRpb25cbiAgICAgIC8qKlxuICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICovXG4gICAgICBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlclxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IG51bWJlclxuICAgICAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgICB9XG4gIH0pOiB2b2lkIHtcbiAgICBpZiAocHJvcHMuc2luZ2xlNXh4UmVzcG9uc2VBbGFybT8uZW5hYmxlZCAhPT0gZmFsc2UpIHtcbiAgICAgIGNvbnN0IHNpbmdsZTV4eE1ldHJpYyA9IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAgIG1ldHJpY05hbWU6IFwiSFRUUENvZGVfVGFyZ2V0XzVYWF9Db3VudFwiLFxuICAgICAgICBuYW1lc3BhY2U6IFwiQVdTL0FwcGxpY2F0aW9uRUxCXCIsXG4gICAgICAgIHN0YXRpc3RpYzogXCJTdW1cIixcbiAgICAgICAgcGVyaW9kOlxuICAgICAgICAgIHByb3BzLnNpbmdsZTV4eFJlc3BvbnNlQWxhcm0/LnBlcmlvZCA/PyBjZGsuRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICBUYXJnZXRHcm91cDogcHJvcHMudGFyZ2V0R3JvdXBGdWxsTmFtZSxcbiAgICAgICAgICBMb2FkQmFsYW5jZXI6IHByb3BzLmxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgICB9LFxuICAgICAgfSlcblxuICAgICAgY29uc3Qgc2luZ2xlNXh4QWxhcm0gPSBzaW5nbGU1eHhNZXRyaWMuY3JlYXRlQWxhcm0oXG4gICAgICAgIHRoaXMsXG4gICAgICAgIFwiQWxiVGFyZ2V0c1NpbmdsZTV4eEFsYXJtXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBhY3Rpb25zRW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICAgICAgcHJvcHMuc2luZ2xlNXh4UmVzcG9uc2VBbGFybT8uZGVzY3JpcHRpb24gPz9cbiAgICAgICAgICAgIGBMb2FkIGJhbGFuY2VyIHJlY2VpdmVkIGEgNVhYIHJlc3BvbnNlIGZyb20gdGFyZ2V0KHMpIGluIEVDUyBzZXJ2aWNlICcke3RoaXMuc2VydmljZU5hbWV9Jy5gLFxuICAgICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOlxuICAgICAgICAgICAgcHJvcHMuc2luZ2xlNXh4UmVzcG9uc2VBbGFybT8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMSxcbiAgICAgICAgICB0aHJlc2hvbGQ6IHByb3BzLnNpbmdsZTV4eFJlc3BvbnNlQWxhcm0/LnRocmVzaG9sZCA/PyAxLFxuICAgICAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgICAgICB9LFxuICAgICAgKVxuXG4gICAgICAvLyBTZW50IHRvIHdhcm5pbmdzIGNoYW5uZWwgYnkgZGVmYXVsdFxuICAgICAgY29uc3Qgc2luZ2xlNXh4QWN0aW9uID1cbiAgICAgICAgcHJvcHMuc2luZ2xlNXh4UmVzcG9uc2VBbGFybT8uYWN0aW9uID8/IHRoaXMud2FybmluZ0FjdGlvblxuICAgICAgc2luZ2xlNXh4QWxhcm0uYWRkQWxhcm1BY3Rpb24oc2luZ2xlNXh4QWN0aW9uKVxuICAgICAgaWYgKHByb3BzLnNpbmdsZTV4eFJlc3BvbnNlQWxhcm0/LmVuYWJsZU9rQWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICBzaW5nbGU1eHhBbGFybS5hZGRPa0FjdGlvbihzaW5nbGU1eHhBY3Rpb24pXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0Q29ubmVjdGlvbkVycm9yQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJUYXJnZXRDb25uZWN0aW9uRXJyb3JDb3VudFwiLFxuICAgICAgbmFtZXNwYWNlOiBcIkFXUy9BcHBsaWNhdGlvbkVMQlwiLFxuICAgICAgc3RhdGlzdGljOiBcIlN1bVwiLFxuICAgICAgcGVyaW9kOiBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8ucGVyaW9kID8/IGNkay5EdXJhdGlvbi5zZWNvbmRzKDYwKSxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgVGFyZ2V0R3JvdXA6IHByb3BzLnRhcmdldEdyb3VwRnVsbE5hbWUsXG4gICAgICAgIExvYWRCYWxhbmNlcjogcHJvcHMubG9hZEJhbGFuY2VyRnVsbE5hbWUsXG4gICAgICB9LFxuICAgIH0pLmNyZWF0ZUFsYXJtKHRoaXMsIFwiQ29ubmVjdGlvbkFsYXJtXCIsIHtcbiAgICAgIGFjdGlvbnNFbmFibGVkOiB0cnVlLFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbjogYExvYWQgYmFsYW5jZXIgaXMgZmFpbGluZyB0byBjb25uZWN0IHRvIHRhcmdldChzKSBpbiBFQ1Mgc2VydmljZSAnJHt0aGlzLnNlcnZpY2VOYW1lfScuYCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBwcm9wcy50YXJnZXRIZWFsdGhBbGFybT8uZXZhbHVhdGlvblBlcmlvZHMgPz8gMSxcbiAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgIH0pXG5cbiAgICBjb25zdCBoZWFsdGhBbGFybSA9IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBtZXRyaWNOYW1lOiBcIkhlYWx0aHlIb3N0Q291bnRcIixcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvQXBwbGljYXRpb25FTEJcIixcbiAgICAgIHN0YXRpc3RpYzogXCJNaW5pbXVtXCIsXG4gICAgICBwZXJpb2Q6IHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5wZXJpb2QgPz8gY2RrLkR1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICBUYXJnZXRHcm91cDogcHJvcHMudGFyZ2V0R3JvdXBGdWxsTmFtZSxcbiAgICAgICAgTG9hZEJhbGFuY2VyOiBwcm9wcy5sb2FkQmFsYW5jZXJGdWxsTmFtZSxcbiAgICAgIH0sXG4gICAgfSkuY3JlYXRlQWxhcm0odGhpcywgXCJIZWFsdGhBbGFybVwiLCB7XG4gICAgICBhbGFybURlc2NyaXB0aW9uOiBgVGhlcmUgYXJlIG5vIGhlYWx0aHkgdGFyZ2V0KHMpIGluIEVDUyBzZXJ2aWNlICcke3RoaXMuc2VydmljZU5hbWV9Jy5gLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fVEhSRVNIT0xELFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAxLFxuICAgICAgdGhyZXNob2xkOiAxLFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLkJSRUFDSElORyxcbiAgICB9KVxuXG4gICAgY29uc3QgdGFyZ2V0SGVhbHRoQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5Db21wb3NpdGVBbGFybShcbiAgICAgIHRoaXMsXG4gICAgICBcIlRhcmdldEhlYWx0aEFsYXJtXCIsXG4gICAgICB7XG4gICAgICAgIGFsYXJtUnVsZTogY2RrLmF3c19jbG91ZHdhdGNoLkFsYXJtUnVsZS5hbnlPZihcbiAgICAgICAgICBjZGsuYXdzX2Nsb3Vkd2F0Y2guQWxhcm1SdWxlLmZyb21BbGFybShcbiAgICAgICAgICAgIHRhcmdldENvbm5lY3Rpb25FcnJvckFsYXJtLFxuICAgICAgICAgICAgY2xvdWR3YXRjaC5BbGFybVN0YXRlLkFMQVJNLFxuICAgICAgICAgICksXG4gICAgICAgICAgY2RrLmF3c19jbG91ZHdhdGNoLkFsYXJtUnVsZS5mcm9tQWxhcm0oXG4gICAgICAgICAgICBoZWFsdGhBbGFybSxcbiAgICAgICAgICAgIGNsb3Vkd2F0Y2guQWxhcm1TdGF0ZS5BTEFSTSxcbiAgICAgICAgICApLFxuICAgICAgICApLFxuICAgICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICAgIHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5kZXNjcmlwdGlvbiA/P1xuICAgICAgICAgIGBUaGUgbG9hZCBiYWxhbmNlciBpcyBlaXRoZXIgcmVjZWl2aW5nIGJhZCBoZWFsdGggY2hlY2tzIGZyb20gb3IgaXMgdW5hYmxlIHRvIGNvbm5lY3QgdG8gdGFyZ2V0KHMpIGluIEVDUyBzZXJ2aWNlICcke3RoaXMuc2VydmljZU5hbWV9J2AsXG4gICAgICB9LFxuICAgIClcbiAgICBpZiAocHJvcHMudGFyZ2V0SGVhbHRoQWxhcm0/LmVuYWJsZWQgPz8gdHJ1ZSkge1xuICAgICAgLy8gRGVmYXVsdCB0byB0aGUgYWxhcm0gYWN0aW9uXG4gICAgICBjb25zdCB0aEFjdGlvbiA9IHByb3BzLnRhcmdldEhlYWx0aEFsYXJtPy5hY3Rpb24gPz8gdGhpcy5hbGFybUFjdGlvblxuICAgICAgdGFyZ2V0SGVhbHRoQWxhcm0uYWRkQWxhcm1BY3Rpb24odGhBY3Rpb24pXG4gICAgICBpZiAocHJvcHMudGFyZ2V0SGVhbHRoQWxhcm0/LmVuYWJsZU9rQWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICB0YXJnZXRIZWFsdGhBbGFybS5hZGRPa0FjdGlvbih0aEFjdGlvbilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybSA9IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBtZXRyaWNOYW1lOiBcIkhUVFBDb2RlX1RhcmdldF81WFhfQ291bnRcIixcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvQXBwbGljYXRpb25FTEJcIixcbiAgICAgIHN0YXRpc3RpYzogXCJTdW1cIixcbiAgICAgIHBlcmlvZDpcbiAgICAgICAgcHJvcHMudG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0/LnBlcmlvZCA/P1xuICAgICAgICBjZGsuRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFRhcmdldEdyb3VwOiBwcm9wcy50YXJnZXRHcm91cEZ1bGxOYW1lLFxuICAgICAgICBMb2FkQmFsYW5jZXI6IHByb3BzLmxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgfSxcbiAgICB9KS5jcmVhdGVBbGFybSh0aGlzLCBcIkFsYlRhcmdldHM1eHhBbGFybVwiLCB7XG4gICAgICBhY3Rpb25zRW5hYmxlZDogdHJ1ZSxcbiAgICAgIGFsYXJtRGVzY3JpcHRpb246XG4gICAgICAgIHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5kZXNjcmlwdGlvbiA/P1xuICAgICAgICBgTG9hZCBiYWxhbmNlciByZWNlaXZlZCB0b28gbWFueSA1WFggcmVzcG9uc2VzIGZyb20gdGFyZ2V0KHMpIGluIEVDUyBzZXJ2aWNlICcke3RoaXMuc2VydmljZU5hbWV9Jy5gLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6XG4gICAgICAgIHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAzLFxuICAgICAgdGhyZXNob2xkOiBwcm9wcy50b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybT8udGhyZXNob2xkID8/IDEwLFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLk5PVF9CUkVBQ0hJTkcsXG4gICAgfSlcbiAgICBpZiAocHJvcHMudG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0/LmVuYWJsZWQgPz8gdHJ1ZSkge1xuICAgICAgLy8gRGVmYXVsdCB0byB0aGUgYWxhcm0gYWN0aW9uXG4gICAgICBjb25zdCBmaXZlWEFjdGlvbiA9XG4gICAgICAgIHByb3BzLnRvb01hbnk1eHhSZXNwb25zZXNGcm9tVGFyZ2V0c0FsYXJtPy5hY3Rpb24gPz8gdGhpcy5hbGFybUFjdGlvblxuICAgICAgdG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0uYWRkQWxhcm1BY3Rpb24oZml2ZVhBY3Rpb24pXG4gICAgICBpZiAocHJvcHMudG9vTWFueTV4eFJlc3BvbnNlc0Zyb21UYXJnZXRzQWxhcm0/LmVuYWJsZU9rQWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICB0b29NYW55NXh4UmVzcG9uc2VzRnJvbVRhcmdldHNBbGFybS5hZGRPa0FjdGlvbihmaXZlWEFjdGlvbilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXRSZXNwb25zZVRpbWVBbGFybSA9IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBtZXRyaWNOYW1lOiBcIlRhcmdldFJlc3BvbnNlVGltZVwiLFxuICAgICAgbmFtZXNwYWNlOiBcIkFXUy9BcHBsaWNhdGlvbkVMQlwiLFxuICAgICAgc3RhdGlzdGljOiBcInA5NVwiLFxuICAgICAgcGVyaW9kOiBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8ucGVyaW9kID8/IGNkay5EdXJhdGlvbi5taW51dGVzKDUpLFxuICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICBMb2FkQmFsYW5jZXI6IHByb3BzLmxvYWRCYWxhbmNlckZ1bGxOYW1lLFxuICAgICAgICBUYXJnZXRHcm91cDogcHJvcHMudGFyZ2V0R3JvdXBGdWxsTmFtZSxcbiAgICAgIH0sXG4gICAgfSkuY3JlYXRlQWxhcm0odGhpcywgXCJUYXJnZXRSZXNwb25zZVRpbWVBbGFybVwiLCB7XG4gICAgICBhbGFybURlc2NyaXB0aW9uOlxuICAgICAgICBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8uZGVzY3JpcHRpb24gPz9cbiAgICAgICAgYDUlIG9mIHJlc3BvbnNlcyBmcm9tIEVDUyBzZXJ2aWNlICcke1xuICAgICAgICAgIHRoaXMuc2VydmljZU5hbWVcbiAgICAgICAgfScgYXJlIHRha2luZyBsb25nZXIgdGhhbiB0aGUgZXhwZWN0ZWQgZHVyYXRpb24gb2YgJHsoXG4gICAgICAgICAgcHJvcHMudGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0/LnRocmVzaG9sZCA/PyBjZGsuRHVyYXRpb24uc2Vjb25kcygxKVxuICAgICAgICApLnRvU2Vjb25kcyh7IGludGVncmFsOiBmYWxzZSB9KX0gcy5gLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IHByb3BzLnRhcmdldFJlc3BvbnNlVGltZUFsYXJtPy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAxLFxuICAgICAgdGhyZXNob2xkOiAoXG4gICAgICAgIHByb3BzLnRhcmdldFJlc3BvbnNlVGltZUFsYXJtPy50aHJlc2hvbGQgPz8gY2RrLkR1cmF0aW9uLnNlY29uZHMoMSlcbiAgICAgICkudG9TZWNvbmRzKHsgaW50ZWdyYWw6IGZhbHNlIH0pLFxuICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICB9KVxuICAgIGlmIChwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8uZW5hYmxlZCA/PyB0cnVlKSB7XG4gICAgICAvLyBEZWZhdWx0IHRvIHRoZSB3YXJuaW5nIGFjdGlvblxuICAgICAgY29uc3QgcnRBY3Rpb24gPVxuICAgICAgICBwcm9wcy50YXJnZXRSZXNwb25zZVRpbWVBbGFybT8uYWN0aW9uID8/IHRoaXMud2FybmluZ0FjdGlvblxuICAgICAgdGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0uYWRkQWxhcm1BY3Rpb24ocnRBY3Rpb24pXG4gICAgICBpZiAocHJvcHMudGFyZ2V0UmVzcG9uc2VUaW1lQWxhcm0/LmVuYWJsZU9rQWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICB0YXJnZXRSZXNwb25zZVRpbWVBbGFybS5hZGRPa0FjdGlvbihydEFjdGlvbilcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==