@renovosolutions/cdk-library-cloudwatch-alarms
Version:
AWS CDK Construct Library to automatically create CloudWatch Alarms for resources in a CDK app based on resource type.
156 lines • 25.6 kB
JavaScript
;
var _a, _b, _c, _d;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoScalingRecommendedAlarmsAspect = exports.AutoScalingGroup = exports.AutoScalingGroupRecommendedAlarms = exports.AutoScalingGroupGroupInServiceCapacityAlarm = exports.AutoScalingRecommendedAlarmsMetrics = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const common_1 = require("./common");
/**
* The recommended metrics for EC2 AutoScaling alarms.
*/
var AutoScalingRecommendedAlarmsMetrics;
(function (AutoScalingRecommendedAlarmsMetrics) {
/**
* The number of capacity units that are running as part of the Auto Scaling group.
*/
AutoScalingRecommendedAlarmsMetrics["GROUP_IN_SERVICE_CAPACITY"] = "GroupInServiceCapacity";
})(AutoScalingRecommendedAlarmsMetrics || (exports.AutoScalingRecommendedAlarmsMetrics = AutoScalingRecommendedAlarmsMetrics = {}));
/**
* This alarm helps to detect when the capacity in the group is below the desired capacity required for your workload.
*
* To troubleshoot, check your scaling activities for launch failures and confirm that your desired capacity configuration
* is correct.
*
* The alarm is triggered when the capacity in the group is less than threshold.
*/
class AutoScalingGroupGroupInServiceCapacityAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm {
constructor(scope, id, props) {
const alarmName = props.alarmName ?? `${props.autoScalingGroup.autoScalingGroupName} - ${AutoScalingRecommendedAlarmsMetrics.GROUP_IN_SERVICE_CAPACITY}`;
const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1);
const evaluationPeriods = props.evaluationPeriods ?? 10;
const datapointsToAlarm = props.datapointsToAlarm ?? 10;
const threshold = props.threshold;
const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING;
const alarmDescription = props.alarmDescription ?? 'This alarm can detect a low availability in your auto scaling group'
+ ' because of launch failures or suspended launches.';
(0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName);
super(scope, id, {
alarmName,
metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({
namespace: 'AWS/AutoScaling',
metricName: AutoScalingRecommendedAlarmsMetrics.GROUP_IN_SERVICE_CAPACITY,
dimensionsMap: {
AutoScalingGroupId: props.autoScalingGroup.autoScalingGroupName,
},
period,
statistic: 'Average',
}),
threshold,
evaluationPeriods,
datapointsToAlarm,
treatMissingData,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
alarmDescription,
});
if (props.alarmAction)
this.addAlarmAction(props.alarmAction);
if (props.okAction)
this.addOkAction(props.okAction);
if (props.insufficientDataAction)
this.addInsufficientDataAction(props.insufficientDataAction);
}
}
exports.AutoScalingGroupGroupInServiceCapacityAlarm = AutoScalingGroupGroupInServiceCapacityAlarm;
_a = JSII_RTTI_SYMBOL_1;
AutoScalingGroupGroupInServiceCapacityAlarm[_a] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.AutoScalingGroupGroupInServiceCapacityAlarm", version: "0.0.13" };
;
/**
* A construct that creates the recommended alarms for an EC2 AutoScalingGroup.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#AutoScaling
*/
class AutoScalingGroupRecommendedAlarms extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
if (!props.excludeAlarms?.includes(AutoScalingRecommendedAlarmsMetrics.GROUP_IN_SERVICE_CAPACITY)) {
this.alarmGroupInServiceCapacity = new AutoScalingGroupGroupInServiceCapacityAlarm(this, `${props.autoScalingGroup.node.id}_GroupInServiceCapacity`, {
autoScalingGroup: props.autoScalingGroup,
treatMissingData: props.treatMissingData,
...props.configGroupInServiceCapacityAlarm,
});
if (props.defaultAlarmAction && !props.configGroupInServiceCapacityAlarm.alarmAction) {
this.alarmGroupInServiceCapacity.addAlarmAction(props.defaultAlarmAction);
}
if (props.defaultOkAction && !props.configGroupInServiceCapacityAlarm.okAction) {
this.alarmGroupInServiceCapacity.addOkAction(props.defaultOkAction);
}
if (props.defaultInsufficientDataAction && !props.configGroupInServiceCapacityAlarm.insufficientDataAction) {
this.alarmGroupInServiceCapacity.addInsufficientDataAction(props.defaultInsufficientDataAction);
}
}
}
}
exports.AutoScalingGroupRecommendedAlarms = AutoScalingGroupRecommendedAlarms;
_b = JSII_RTTI_SYMBOL_1;
AutoScalingGroupRecommendedAlarms[_b] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.AutoScalingGroupRecommendedAlarms", version: "0.0.13" };
/**
* An extension for the AutoScalingGroup construct that provides methods
* to create recommended alarms.
*/
class AutoScalingGroup extends aws_cdk_lib_1.aws_autoscaling.AutoScalingGroup {
constructor(scope, id, props) {
super(scope, id, props);
}
/**
* Creates an alarm that monitors the GroupInServiceCapacity for the EC2 autoScalingGroup.
*/
alarmGroupInServiceCapacity(props) {
return new AutoScalingGroupGroupInServiceCapacityAlarm(this, 'GroupInServiceCapacityAlarm', {
autoScalingGroup: this,
...props,
});
}
/**
* Creates the recommended alarms for the EC2 AutoScalingGroup.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#AutoScaling
*/
applyRecommendedAlarms(props) {
return new AutoScalingGroupRecommendedAlarms(this, 'AutoScalingGroupRecommendedAlarms', {
autoScalingGroup: this,
...props,
});
}
}
exports.AutoScalingGroup = AutoScalingGroup;
_c = JSII_RTTI_SYMBOL_1;
AutoScalingGroup[_c] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.AutoScalingGroup", version: "0.0.13" };
/**
* Configures the recommended alarms for an EC2 AutoScalingGroup.
*
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#AutoScaling
*/
class AutoScalingRecommendedAlarmsAspect {
constructor(props) {
this.props = props;
}
visit(node) {
if (node instanceof aws_cdk_lib_1.aws_autoscaling.AutoScalingGroup) {
if (this.props.excludeResources && this.props.excludeResources.includes(node.node.id)) {
return;
}
else {
const autoScalingGroup = node;
new AutoScalingGroupRecommendedAlarms(autoScalingGroup, 'AutoScalingGroupRecommendedAlarmsFromAspect', {
autoScalingGroup,
...this.props,
});
}
}
}
}
exports.AutoScalingRecommendedAlarmsAspect = AutoScalingRecommendedAlarmsAspect;
_d = JSII_RTTI_SYMBOL_1;
AutoScalingRecommendedAlarmsAspect[_d] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.AutoScalingRecommendedAlarmsAspect", version: "0.0.13" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b3NjYWxpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYXV0b3NjYWxpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FLcUI7QUFDckIsMkNBQW1EO0FBQ25ELHFDQUFvRTtBQUVwRTs7R0FFRztBQUNILElBQVksbUNBS1g7QUFMRCxXQUFZLG1DQUFtQztJQUM3Qzs7T0FFRztJQUNILDJGQUFvRCxDQUFBO0FBQ3RELENBQUMsRUFMVyxtQ0FBbUMsbURBQW5DLG1DQUFtQyxRQUs5QztBQWlFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBYSwyQ0FBNEMsU0FBUSw0QkFBVSxDQUFDLEtBQUs7SUFDL0UsWUFBWSxLQUFpQixFQUFFLEVBQVUsRUFBRSxLQUF1RDtRQUNoRyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixDQUFDLG9CQUFvQixNQUFNLG1DQUFtQyxDQUFDLHlCQUF5QixFQUFFLENBQUM7UUFDekosTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRCxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUM7UUFDeEQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksRUFBRSxDQUFDO1FBQ3hELE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDbEMsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksNEJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDdkYsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUkscUVBQXFFO2NBQ3BILG9EQUFvRCxDQUFDO1FBRXpELElBQUEsaUNBQXdCLEVBQUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLFNBQVMs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LEVBQUUsNkJBQTZCLEVBQUU7WUFDMUYsZ0JBQWdCLEVBQUUsSUFBSTtZQUN0QixHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLHNCQUFzQixDQUFDLEtBQThDO1FBQzFFLE9BQU8sSUFBSSxpQ0FBaUMsQ0FBQyxJQUFJLEVBQUUsbUNBQW1DLEVBQUU7WUFDdEYsZ0JBQWdCLEVBQUUsSUFBSTtZQUN0QixHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDOztBQXpCSCw0Q0EwQkM7OztBQUVEOzs7O0dBSUc7QUFDSCxNQUFhLGtDQUFrQztJQUM3QyxZQUE2QixLQUE4QztRQUE5QyxVQUFLLEdBQUwsS0FBSyxDQUF5QztJQUFHLENBQUM7SUFFeEUsS0FBSyxDQUFDLElBQWdCO1FBQzNCLElBQUksSUFBSSxZQUFZLDZCQUFXLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNqRCxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUN0RixPQUFPO1lBQ1QsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sZ0JBQWdCLEdBQUcsSUFBb0MsQ0FBQztnQkFFOUQsSUFBSSxpQ0FBaUMsQ0FBQyxnQkFBZ0IsRUFBRSw2Q0FBNkMsRUFBRTtvQkFDckcsZ0JBQWdCO29CQUNoQixHQUFHLElBQUksQ0FBQyxLQUFLO2lCQUNkLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzs7QUFoQkgsZ0ZBaUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgSUFzcGVjdCxcbiAgYXdzX2F1dG9zY2FsaW5nIGFzIGF1dG9zY2FsaW5nLFxuICBhd3NfY2xvdWR3YXRjaCBhcyBjbG91ZHdhdGNoLFxuICBEdXJhdGlvbixcbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbGFybUJhc2VQcm9wcywgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kIH0gZnJvbSAnLi9jb21tb24nO1xuXG4vKipcbiAqIFRoZSByZWNvbW1lbmRlZCBtZXRyaWNzIGZvciBFQzIgQXV0b1NjYWxpbmcgYWxhcm1zLlxuICovXG5leHBvcnQgZW51bSBBdXRvU2NhbGluZ1JlY29tbWVuZGVkQWxhcm1zTWV0cmljcyB7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGNhcGFjaXR5IHVuaXRzIHRoYXQgYXJlIHJ1bm5pbmcgYXMgcGFydCBvZiB0aGUgQXV0byBTY2FsaW5nIGdyb3VwLlxuICAgKi9cbiAgR1JPVVBfSU5fU0VSVklDRV9DQVBBQ0lUWSA9ICdHcm91cEluU2VydmljZUNhcGFjaXR5Jyxcbn1cblxuLyoqXG4gKiBUaGUgY29tbW9uIG9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBhbGFybXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXV0b1NjYWxpbmdBbGFybUJhc2VDb25maWcgZXh0ZW5kcyBBbGFybUJhc2VQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgcGVyaW9kIG92ZXIgd2hpY2ggdGhlIHNwZWNpZmllZCBzdGF0aXN0aWMgaXMgYXBwbGllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcygxKVxuICAgKi9cbiAgcmVhZG9ubHkgcGVyaW9kPzogRHVyYXRpb247XG59XG5cbi8qKlxuICogVGhlIGNvbW1vbiBwcm9wZXJ0aWVzIGZvciB0aGUgRUMyIEF1dG9TY2FsaW5nR3JvdXAgYWxhcm1zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9TY2FsaW5nR3JvdXBBbGFybVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBFQzIgQXV0b1NjYWxpbmdHcm91cCB0byBtb25pdG9yLlxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b1NjYWxpbmdHcm91cDogYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cDtcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgR3JvdXBJblNlcnZpY2VDYXBhY2l0eSBhbGFybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRvU2NhbGluZ0dyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybUNvbmZpZyBleHRlbmRzIEF1dG9TY2FsaW5nQWxhcm1CYXNlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSB0aHJlc2hvbGQgdmFsdWUgc2hvdWxkIGJlIHRoZSBtaW5pbXVtIGNhcGFjaXR5IHJlcXVpcmVkIHRvIHJ1biB5b3VyIHdvcmtsb2FkLiBJbiBtb3N0IGNhc2VzLFxuICAgKiB5b3UgY2FuIHNldCB0aGlzIHRvIG1hdGNoIHRoZSBHcm91cERlc2lyZWRDYXBhY2l0eSBtZXRyaWMuXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgcGVyaW9kcyBvdmVyIHdoaWNoIGRhdGEgaXMgY29tcGFyZWQgdG8gdGhlIHNwZWNpZmllZCB0aHJlc2hvbGQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwXG4gICAqL1xuICByZWFkb25seSBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBtdXN0IGJlIGJyZWFjaGluZyB0byB0cmlnZ2VyIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgMTBcbiAgICovXG4gIHJlYWRvbmx5IGRhdGFwb2ludHNUb0FsYXJtPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIGFsYXJtIG5hbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYXV0b1NjYWxpbmdHcm91cE5hbWUgKyAnIC0gR3JvdXBJblNlcnZpY2VDYXBhY2l0eSdcbiAgICovXG4gIHJlYWRvbmx5IGFsYXJtTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgYWxhcm0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhpcyBhbGFybSBjYW4gZGV0ZWN0IGEgbG93IGF2YWlsYWJpbGl0eSBpbiB5b3VyIGF1dG8gc2NhbGluZyBncm91cCBiZWNhdXNlIG9mIGxhdW5jaCBmYWlsdXJlc1xuICAgKiBvciBzdXNwZW5kZWQgbGF1bmNoZXMuXG4gICAqL1xuICByZWFkb25seSBhbGFybURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgQXV0b1NjYWxpbmdHcm91cEdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybSBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXV0b1NjYWxpbmdHcm91cEdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybVByb3BzIGV4dGVuZHMgQXV0b1NjYWxpbmdHcm91cEFsYXJtUHJvcHMsIEF1dG9TY2FsaW5nR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtQ29uZmlnIHt9XG5cbi8qKlxuICogVGhpcyBhbGFybSBoZWxwcyB0byBkZXRlY3Qgd2hlbiB0aGUgY2FwYWNpdHkgaW4gdGhlIGdyb3VwIGlzIGJlbG93IHRoZSBkZXNpcmVkIGNhcGFjaXR5IHJlcXVpcmVkIGZvciB5b3VyIHdvcmtsb2FkLlxuICpcbiAqIFRvIHRyb3VibGVzaG9vdCwgY2hlY2sgeW91ciBzY2FsaW5nIGFjdGl2aXRpZXMgZm9yIGxhdW5jaCBmYWlsdXJlcyBhbmQgY29uZmlybSB0aGF0IHlvdXIgZGVzaXJlZCBjYXBhY2l0eSBjb25maWd1cmF0aW9uXG4gKiBpcyBjb3JyZWN0LlxuICpcbiAqIFRoZSBhbGFybSBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgY2FwYWNpdHkgaW4gdGhlIGdyb3VwIGlzIGxlc3MgdGhhbiB0aHJlc2hvbGQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRvU2NhbGluZ0dyb3VwR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtIGV4dGVuZHMgY2xvdWR3YXRjaC5BbGFybSB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBJQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQXV0b1NjYWxpbmdHcm91cEdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybVByb3BzKSB7XG4gICAgY29uc3QgYWxhcm1OYW1lID0gcHJvcHMuYWxhcm1OYW1lID8/IGAke3Byb3BzLmF1dG9TY2FsaW5nR3JvdXAuYXV0b1NjYWxpbmdHcm91cE5hbWV9IC0gJHtBdXRvU2NhbGluZ1JlY29tbWVuZGVkQWxhcm1zTWV0cmljcy5HUk9VUF9JTl9TRVJWSUNFX0NBUEFDSVRZfWA7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHMucGVyaW9kID8/IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyA/PyAxMDtcbiAgICBjb25zdCBkYXRhcG9pbnRzVG9BbGFybSA9IHByb3BzLmRhdGFwb2ludHNUb0FsYXJtID8/IDEwO1xuICAgIGNvbnN0IHRocmVzaG9sZCA9IHByb3BzLnRocmVzaG9sZDtcbiAgICBjb25zdCB0cmVhdE1pc3NpbmdEYXRhID0gcHJvcHMudHJlYXRNaXNzaW5nRGF0YSA/PyBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuTUlTU0lORztcbiAgICBjb25zdCBhbGFybURlc2NyaXB0aW9uID0gcHJvcHMuYWxhcm1EZXNjcmlwdGlvbiA/PyAnVGhpcyBhbGFybSBjYW4gZGV0ZWN0IGEgbG93IGF2YWlsYWJpbGl0eSBpbiB5b3VyIGF1dG8gc2NhbGluZyBncm91cCdcbiAgICAgICsgJyBiZWNhdXNlIG9mIGxhdW5jaCBmYWlsdXJlcyBvciBzdXNwZW5kZWQgbGF1bmNoZXMuJztcblxuICAgIHZhbGlkYXRlVG90YWxBbGFybVBlcmlvZChwZXJpb2QsIGV2YWx1YXRpb25QZXJpb2RzLCBhbGFybU5hbWUpO1xuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBhbGFybU5hbWUsXG4gICAgICBtZXRyaWM6IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAgIG5hbWVzcGFjZTogJ0FXUy9BdXRvU2NhbGluZycsXG4gICAgICAgIG1ldHJpY05hbWU6IEF1dG9TY2FsaW5nUmVjb21tZW5kZWRBbGFybXNNZXRyaWNzLkdST1VQX0lOX1NFUlZJQ0VfQ0FQQUNJVFksXG4gICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICBBdXRvU2NhbGluZ0dyb3VwSWQ6IHByb3BzLmF1dG9TY2FsaW5nR3JvdXAuYXV0b1NjYWxpbmdHcm91cE5hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHBlcmlvZCxcbiAgICAgICAgc3RhdGlzdGljOiAnQXZlcmFnZScsXG4gICAgICB9KSxcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fVEhSRVNIT0xELFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcy5hbGFybUFjdGlvbikgdGhpcy5hZGRBbGFybUFjdGlvbihwcm9wcy5hbGFybUFjdGlvbik7XG4gICAgaWYgKHByb3BzLm9rQWN0aW9uKSB0aGlzLmFkZE9rQWN0aW9uKHByb3BzLm9rQWN0aW9uKTtcbiAgICBpZiAocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbikgdGhpcy5hZGRJbnN1ZmZpY2llbnREYXRhQWN0aW9uKHByb3BzLmluc3VmZmljaWVudERhdGFBY3Rpb24pO1xuICB9XG59O1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb25zIGZvciB0aGUgcmVjb21tZW5kZWQgYWxhcm1zIGZvciBhbiBFQzIgQXV0b1NjYWxpbmdHcm91cC5cbiAqXG4gKiBEZWZhdWx0IGFjdGlvbnMgYXJlIG92ZXJyaWRkZW4gYnkgdGhlIGFjdGlvbnMgc3BlY2lmaWVkIGluIHRoZVxuICogaW5kaXZpZHVhbCBhbGFybSBjb25maWd1cmF0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXNDb25maWcge1xuICAvKipcbiAgICogVGhlIGRlZmF1bHQgYWN0aW9uIHRvIHRha2Ugd2hlbiBhbiBhbGFybSBpcyB0cmlnZ2VyZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdEFsYXJtQWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb247XG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBhY3Rpb24gdG8gdGFrZSB3aGVuIGFuIGFsYXJtIGVudGVycyB0aGUgb2sgc3RhdGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdE9rQWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb247XG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBhY3Rpb24gdG8gdGFrZSB3aGVuIGFuIGFsYXJtIGhhcyBpbnN1ZmZpY2llbnQgZGF0YS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0SW5zdWZmaWNpZW50RGF0YUFjdGlvbj86IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uO1xuICAvKipcbiAgICogSG93IHRvIGhhbmRsZSBtaXNzaW5nIGRhdGEgZm9yIHRoaXMgYWxhcm0uXG4gICAqXG4gICAqIEBkZWZhdWx0IFRyZWF0TWlzc2luZ0RhdGEuTUlTU0lOR1xuICAgKi9cbiAgcmVhZG9ubHkgdHJlYXRNaXNzaW5nRGF0YT86IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YTtcbiAgLyoqXG4gICAqIEFsYXJtIG1ldHJpY3MgdG8gZXhjbHVkZSBmcm9tIHRoZSByZWNvbW1lbmRlZCBhbGFybXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZUFsYXJtcz86IEF1dG9TY2FsaW5nUmVjb21tZW5kZWRBbGFybXNNZXRyaWNzW107XG4gIC8qKlxuICAgKiBUaGUgcmVzb3VyY2VzIHRvIGV4Y2x1ZGUgZnJvbSB0aGUgcmVjb21tZW5kZWQgYWxhcm1zLlxuICAgKlxuICAgKiBVc2UgYSByZXNvdXJjZXMgaWQgdG8gZXhjbHVkZSBhIHNwZWNpZmljIHJlc291cmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZVJlc291cmNlcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogVGhlIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBHcm91cEluU2VydmljZUNhcGFjaXR5IGFsYXJtLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtOiBBdXRvU2NhbGluZ0dyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybUNvbmZpZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciB0aGUgQXV0b1NjYWxpbmdHcm91cFJlY29tbWVuZGVkQWxhcm1zIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXNQcm9wcyBleHRlbmRzIEF1dG9TY2FsaW5nR3JvdXBSZWNvbW1lbmRlZEFsYXJtc0NvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgRUMyIEF1dG9TY2FsaW5nR3JvdXAgdG8gbW9uaXRvci5cbiAgICovXG4gIHJlYWRvbmx5IGF1dG9TY2FsaW5nR3JvdXA6IGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXA7XG59XG5cbi8qKlxuICogQSBjb25zdHJ1Y3QgdGhhdCBjcmVhdGVzIHRoZSByZWNvbW1lbmRlZCBhbGFybXMgZm9yIGFuIEVDMiBBdXRvU2NhbGluZ0dyb3VwLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L21vbml0b3JpbmcvQmVzdF9QcmFjdGljZV9SZWNvbW1lbmRlZF9BbGFybXNfQVdTX1NlcnZpY2VzLmh0bWwjQXV0b1NjYWxpbmdcbiAqL1xuZXhwb3J0IGNsYXNzIEF1dG9TY2FsaW5nR3JvdXBSZWNvbW1lbmRlZEFsYXJtcyBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBUaGUgR3JvdXBJblNlcnZpY2VDYXBhY2l0eSBhbGFybS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhbGFybUdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHk/OiBBdXRvU2NhbGluZ0dyb3VwR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXNQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBpZiAoIXByb3BzLmV4Y2x1ZGVBbGFybXM/LmluY2x1ZGVzKEF1dG9TY2FsaW5nUmVjb21tZW5kZWRBbGFybXNNZXRyaWNzLkdST1VQX0lOX1NFUlZJQ0VfQ0FQQUNJVFkpKSB7XG4gICAgICB0aGlzLmFsYXJtR3JvdXBJblNlcnZpY2VDYXBhY2l0eSA9IG5ldyBBdXRvU2NhbGluZ0dyb3VwR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtKHRoaXMsIGAke3Byb3BzLmF1dG9TY2FsaW5nR3JvdXAubm9kZS5pZH1fR3JvdXBJblNlcnZpY2VDYXBhY2l0eWAsIHtcbiAgICAgICAgYXV0b1NjYWxpbmdHcm91cDogcHJvcHMuYXV0b1NjYWxpbmdHcm91cCxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogcHJvcHMudHJlYXRNaXNzaW5nRGF0YSxcbiAgICAgICAgLi4ucHJvcHMuY29uZmlnR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChwcm9wcy5kZWZhdWx0QWxhcm1BY3Rpb24gJiYgIXByb3BzLmNvbmZpZ0dyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybS5hbGFybUFjdGlvbikge1xuICAgICAgICB0aGlzLmFsYXJtR3JvdXBJblNlcnZpY2VDYXBhY2l0eS5hZGRBbGFybUFjdGlvbihwcm9wcy5kZWZhdWx0QWxhcm1BY3Rpb24pO1xuICAgICAgfVxuXG4gICAgICBpZiAocHJvcHMuZGVmYXVsdE9rQWN0aW9uICYmICFwcm9wcy5jb25maWdHcm91cEluU2VydmljZUNhcGFjaXR5QWxhcm0ub2tBY3Rpb24pIHtcbiAgICAgICAgdGhpcy5hbGFybUdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHkuYWRkT2tBY3Rpb24ocHJvcHMuZGVmYXVsdE9rQWN0aW9uKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHByb3BzLmRlZmF1bHRJbnN1ZmZpY2llbnREYXRhQWN0aW9uICYmICFwcm9wcy5jb25maWdHcm91cEluU2VydmljZUNhcGFjaXR5QWxhcm0uaW5zdWZmaWNpZW50RGF0YUFjdGlvbikge1xuICAgICAgICB0aGlzLmFsYXJtR3JvdXBJblNlcnZpY2VDYXBhY2l0eS5hZGRJbnN1ZmZpY2llbnREYXRhQWN0aW9uKHByb3BzLmRlZmF1bHRJbnN1ZmZpY2llbnREYXRhQWN0aW9uKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBBbiBleHRlbnNpb24gZm9yIHRoZSBBdXRvU2NhbGluZ0dyb3VwIGNvbnN0cnVjdCB0aGF0IHByb3ZpZGVzIG1ldGhvZHNcbiAqIHRvIGNyZWF0ZSByZWNvbW1lbmRlZCBhbGFybXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRvU2NhbGluZ0dyb3VwIGV4dGVuZHMgYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cCB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBhdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGFsYXJtIHRoYXQgbW9uaXRvcnMgdGhlIEdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHkgZm9yIHRoZSBFQzIgYXV0b1NjYWxpbmdHcm91cC5cbiAgICovXG4gIHB1YmxpYyBhbGFybUdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHkocHJvcHM6IEF1dG9TY2FsaW5nR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtQ29uZmlnKTogQXV0b1NjYWxpbmdHcm91cEdyb3VwSW5TZXJ2aWNlQ2FwYWNpdHlBbGFybSB7XG4gICAgcmV0dXJuIG5ldyBBdXRvU2NhbGluZ0dyb3VwR3JvdXBJblNlcnZpY2VDYXBhY2l0eUFsYXJtKHRoaXMsICdHcm91cEluU2VydmljZUNhcGFjaXR5QWxhcm0nLCB7XG4gICAgICBhdXRvU2NhbGluZ0dyb3VwOiB0aGlzLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgcmVjb21tZW5kZWQgYWxhcm1zIGZvciB0aGUgRUMyIEF1dG9TY2FsaW5nR3JvdXAuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L21vbml0b3JpbmcvQmVzdF9QcmFjdGljZV9SZWNvbW1lbmRlZF9BbGFybXNfQVdTX1NlcnZpY2VzLmh0bWwjQXV0b1NjYWxpbmdcbiAgICovXG4gIHB1YmxpYyBhcHBseVJlY29tbWVuZGVkQWxhcm1zKHByb3BzOiBBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXNDb25maWcpOiBBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXMge1xuICAgIHJldHVybiBuZXcgQXV0b1NjYWxpbmdHcm91cFJlY29tbWVuZGVkQWxhcm1zKHRoaXMsICdBdXRvU2NhbGluZ0dyb3VwUmVjb21tZW5kZWRBbGFybXMnLCB7XG4gICAgICBhdXRvU2NhbGluZ0dyb3VwOiB0aGlzLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25maWd1cmVzIHRoZSByZWNvbW1lbmRlZCBhbGFybXMgZm9yIGFuIEVDMiBBdXRvU2NhbGluZ0dyb3VwLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L21vbml0b3JpbmcvQmVzdF9QcmFjdGljZV9SZWNvbW1lbmRlZF9BbGFybXNfQVdTX1NlcnZpY2VzLmh0bWwjQXV0b1NjYWxpbmdcbiAqL1xuZXhwb3J0IGNsYXNzIEF1dG9TY2FsaW5nUmVjb21tZW5kZWRBbGFybXNBc3BlY3QgaW1wbGVtZW50cyBJQXNwZWN0IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwcm9wczogQXV0b1NjYWxpbmdHcm91cFJlY29tbWVuZGVkQWxhcm1zQ29uZmlnKSB7fVxuXG4gIHB1YmxpYyB2aXNpdChub2RlOiBJQ29uc3RydWN0KTogdm9pZCB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBhdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwKSB7XG4gICAgICBpZiAodGhpcy5wcm9wcy5leGNsdWRlUmVzb3VyY2VzICYmIHRoaXMucHJvcHMuZXhjbHVkZVJlc291cmNlcy5pbmNsdWRlcyhub2RlLm5vZGUuaWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGF1dG9TY2FsaW5nR3JvdXAgPSBub2RlIGFzIGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXA7XG5cbiAgICAgICAgbmV3IEF1dG9TY2FsaW5nR3JvdXBSZWNvbW1lbmRlZEFsYXJtcyhhdXRvU2NhbGluZ0dyb3VwLCAnQXV0b1NjYWxpbmdHcm91cFJlY29tbWVuZGVkQWxhcm1zRnJvbUFzcGVjdCcsIHtcbiAgICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLFxuICAgICAgICAgIC4uLnRoaXMucHJvcHMsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19