UNPKG

@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.

384 lines 66.5 kB
"use strict"; var _a, _b, _c, _d, _e, _f, _g; Object.defineProperty(exports, "__esModule", { value: true }); exports.EcsRecommendedAlarmsAspect = exports.FargateService = exports.EcsServiceRecommendedAlarms = exports.EcsServiceRunningTaskCountAlarm = exports.EcsServiceEphemeralStorageUtilizedAlarm = exports.EcsServiceMemoryUtilizationAlarm = exports.EcsServiceCpuUtilizationAlarm = exports.EcsRecommendedAlarmsMetrics = 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 ECS alarms. */ var EcsRecommendedAlarmsMetrics; (function (EcsRecommendedAlarmsMetrics) { /** * The percentage of CPU units that is used by the cluster or service. */ EcsRecommendedAlarmsMetrics["CPU_UTILIZATION"] = "CPUUtilization"; /** * The percentage of memory in use by the cluster or service. */ EcsRecommendedAlarmsMetrics["MEMORY_UTILIZATION"] = "MemoryUtilization"; /** * The ephemeral storage in GB that is used by the cluster or service. */ EcsRecommendedAlarmsMetrics["EPHEMERAL_STORAGE_UTILIZED"] = "EphemeralStorageUtilized"; /** * The number of tasks in your services that are in the RUNNING state. */ EcsRecommendedAlarmsMetrics["RUNNING_TASK_COUNT"] = "RunningTaskCount"; })(EcsRecommendedAlarmsMetrics || (exports.EcsRecommendedAlarmsMetrics = EcsRecommendedAlarmsMetrics = {})); /** * This alarm is used to detect high CPU utilization for the ECS service. * * Consistent high CPU utilization can indicate a resource bottleneck or * application performance problems. * * The alarm is triggered when CPU utilization exceeds % threshold. */ class EcsServiceCpuUtilizationAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.service.cluster.clusterName}-${props.service.serviceName} - ${EcsRecommendedAlarmsMetrics.CPU_UTILIZATION}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold ?? 90; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect high CPU utilization for the ECS service.' + ' Consistent high CPU utilization can indicate a resource bottleneck or application performance problems.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: props.service.metricCpuUtilization({ period, }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_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.EcsServiceCpuUtilizationAlarm = EcsServiceCpuUtilizationAlarm; _a = JSII_RTTI_SYMBOL_1; EcsServiceCpuUtilizationAlarm[_a] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsServiceCpuUtilizationAlarm", version: "0.0.13" }; ; /** * This alarm is used to detect high memory utilization for the ECS service. * * Consistent high memory utilization can indicate a resource bottleneck or * application performance problems. * * The alarm is triggered when memory utilization exceeds % threshold. */ class EcsServiceMemoryUtilizationAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.service.cluster.clusterName}-${props.service.serviceName} - ${EcsRecommendedAlarmsMetrics.MEMORY_UTILIZATION}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold ?? 90; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect high memory utilization for the ECS service.' + ' Consistent high memory utilization can indicate a resource bottleneck or application performance problems.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: props.service.metricMemoryUtilization({ period, }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_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.EcsServiceMemoryUtilizationAlarm = EcsServiceMemoryUtilizationAlarm; _b = JSII_RTTI_SYMBOL_1; EcsServiceMemoryUtilizationAlarm[_b] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsServiceMemoryUtilizationAlarm", version: "0.0.13" }; ; /** * This alarm is used to detect high ephemeral storage usage for the Fargate cluster. * * Consistent high ephemeral storage utilized can indicate that the disk is full and it * might lead to failure of the container. * * The alarm is triggered when the storage utilized (GB) exceeds the threshold. */ class EcsServiceEphemeralStorageUtilizedAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.service.cluster.clusterName}-${props.service.serviceName} - ${EcsRecommendedAlarmsMetrics.EPHEMERAL_STORAGE_UTILIZED}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect high ephemeral storage usage for the' + ' Fargate cluster. Consistent high ephemeral storage utilized can indicate that the disk is full and it might lead' + ' to failure of the container.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'ECS/ContainerInsights', metricName: EcsRecommendedAlarmsMetrics.EPHEMERAL_STORAGE_UTILIZED, dimensionsMap: { ServiceName: props.service.serviceName, ClusterName: props.service.cluster.clusterName, }, statistic: 'Average', period, }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_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.EcsServiceEphemeralStorageUtilizedAlarm = EcsServiceEphemeralStorageUtilizedAlarm; _c = JSII_RTTI_SYMBOL_1; EcsServiceEphemeralStorageUtilizedAlarm[_c] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsServiceEphemeralStorageUtilizedAlarm", version: "0.0.13" }; ; /** * This alarm helps you detect a low running task count of the ECS service. * * If the running task count is too low, it can can indicate that the application * can’t handle the service load and it might lead to performance issues. If there * is no running task, the Amazon ECS service might be unavailable or there might * be deployment issues. * * The alarm is triggered when the number of running tasks is less than or equal to * threshold. */ class EcsServiceRunningTaskCountAlarm extends aws_cdk_lib_1.aws_cloudwatch.Alarm { constructor(scope, id, props) { const alarmName = props.alarmName ?? `${props.service.cluster.clusterName}-${props.service.serviceName} - ${EcsRecommendedAlarmsMetrics.RUNNING_TASK_COUNT}`; const period = props.period ?? aws_cdk_lib_1.Duration.minutes(1); const evaluationPeriods = props.evaluationPeriods ?? 5; const datapointsToAlarm = props.datapointsToAlarm ?? 5; const threshold = props.threshold ?? 0; const treatMissingData = props.treatMissingData ?? aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.MISSING; const alarmDescription = props.alarmDescription ?? 'This alarm is used to detect whether the number of running tasks' + ' are too low. A consistent low running task count can indicate ECS service deployment or performance issues.'; (0, common_1.validateTotalAlarmPeriod)(period, evaluationPeriods, alarmName); super(scope, id, { alarmName, metric: new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: 'ECS/ContainerInsights', metricName: EcsRecommendedAlarmsMetrics.RUNNING_TASK_COUNT, dimensionsMap: { ServiceName: props.service.serviceName, ClusterName: props.service.cluster.clusterName, }, statistic: 'Average', period, }), threshold, evaluationPeriods, datapointsToAlarm, treatMissingData, comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD, alarmDescription, }); if (props.alarmAction) this.addAlarmAction(props.alarmAction); if (props.okAction) this.addOkAction(props.okAction); if (props.insufficientDataAction) this.addInsufficientDataAction(props.insufficientDataAction); } } exports.EcsServiceRunningTaskCountAlarm = EcsServiceRunningTaskCountAlarm; _d = JSII_RTTI_SYMBOL_1; EcsServiceRunningTaskCountAlarm[_d] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsServiceRunningTaskCountAlarm", version: "0.0.13" }; ; /** * A construct that creates the recommended alarms for an ECS service. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#ECS */ class EcsServiceRecommendedAlarms extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); if (!props.excludeAlarms?.includes(EcsRecommendedAlarmsMetrics.CPU_UTILIZATION)) { this.alarmCpuUtilization = new EcsServiceCpuUtilizationAlarm(this, `${props.service.node.id}_CpuUtilization`, { service: props.service, treatMissingData: props.treatMissingData, ...props.configCpuUtilizationAlarm, }); if (props.defaultAlarmAction && !props.configCpuUtilizationAlarm?.alarmAction) { this.alarmCpuUtilization.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configCpuUtilizationAlarm?.okAction) { this.alarmCpuUtilization.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configCpuUtilizationAlarm?.insufficientDataAction) { this.alarmCpuUtilization.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (!props.excludeAlarms?.includes(EcsRecommendedAlarmsMetrics.MEMORY_UTILIZATION)) { this.alarmMemoryUtilization = new EcsServiceMemoryUtilizationAlarm(this, `${props.service.node.id}_MemoryUtilization`, { service: props.service, treatMissingData: props.treatMissingData, ...props.configMemoryUtilizationAlarm, }); if (props.defaultAlarmAction && !props.configMemoryUtilizationAlarm?.alarmAction) { this.alarmMemoryUtilization.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configMemoryUtilizationAlarm?.okAction) { this.alarmMemoryUtilization.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configMemoryUtilizationAlarm?.insufficientDataAction) { this.alarmMemoryUtilization.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (!props.excludeAlarms?.includes(EcsRecommendedAlarmsMetrics.EPHEMERAL_STORAGE_UTILIZED)) { this.alarmEphemeralStorageUtilized = new EcsServiceEphemeralStorageUtilizedAlarm(this, `${props.service.node.id}_EphemeralStorageUtilized`, { service: props.service, treatMissingData: props.treatMissingData, ...props.configEphemeralStorageUtilizedAlarm, }); if (props.defaultAlarmAction && !props.configEphemeralStorageUtilizedAlarm.alarmAction) { this.alarmEphemeralStorageUtilized.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configEphemeralStorageUtilizedAlarm.okAction) { this.alarmEphemeralStorageUtilized.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configEphemeralStorageUtilizedAlarm.insufficientDataAction) { this.alarmEphemeralStorageUtilized.addInsufficientDataAction(props.defaultInsufficientDataAction); } } if (!props.excludeAlarms?.includes(EcsRecommendedAlarmsMetrics.RUNNING_TASK_COUNT)) { this.alarmRunningTaskCount = new EcsServiceRunningTaskCountAlarm(this, `${props.service.node.id}_RunningTaskCount`, { service: props.service, treatMissingData: props.treatMissingData, ...props.configRunningTaskCountAlarm, }); if (props.defaultAlarmAction && !props.configRunningTaskCountAlarm?.alarmAction) { this.alarmRunningTaskCount.addAlarmAction(props.defaultAlarmAction); } if (props.defaultOkAction && !props.configRunningTaskCountAlarm?.okAction) { this.alarmRunningTaskCount.addOkAction(props.defaultOkAction); } if (props.defaultInsufficientDataAction && !props.configRunningTaskCountAlarm?.insufficientDataAction) { this.alarmRunningTaskCount.addInsufficientDataAction(props.defaultInsufficientDataAction); } } } } exports.EcsServiceRecommendedAlarms = EcsServiceRecommendedAlarms; _e = JSII_RTTI_SYMBOL_1; EcsServiceRecommendedAlarms[_e] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsServiceRecommendedAlarms", version: "0.0.13" }; /** * An extension for the FargateService construct that provides methods * to create recommended alarms. */ class FargateService extends aws_cdk_lib_1.aws_ecs.FargateService { constructor(scope, id, props) { super(scope, id, props); } /** * Creates an alarm that monitors the CPU utilization for the Fargate service. */ alarmCpuUtilization(props) { return new EcsServiceCpuUtilizationAlarm(this, 'CpuUtilizationAlarm', { service: this, ...props, }); } /** * Creates an alarm that monitors the memory utilization for the Fargate service. */ alarmMemoryUtilization(props) { return new EcsServiceMemoryUtilizationAlarm(this, 'MemoryUtilizationAlarm', { service: this, ...props, }); } /** * Creates an alarm that monitors the ephemeral storage utilized for the Fargate service. */ alarmEphemeralStorageUtilized(props) { return new EcsServiceEphemeralStorageUtilizedAlarm(this, 'EphemeralStorageUtilizedAlarm', { service: this, ...props, }); } /** * Creates an alarm that monitors the number of task running. */ alarmRunningTaskCount(props) { return new EcsServiceRunningTaskCountAlarm(this, 'RunningTaskCountAlarm', { service: this, ...props, }); } /** * Creates the recommended alarms for the ECS service. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#ECS */ applyRecommendedAlarms(props) { return new EcsServiceRecommendedAlarms(this, 'EcsServiceRecommendedAlarms', { service: this, ...props, }); } } exports.FargateService = FargateService; _f = JSII_RTTI_SYMBOL_1; FargateService[_f] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.FargateService", version: "0.0.13" }; /** * Configures the recommended alarms for an ECS service. * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#ECS */ class EcsRecommendedAlarmsAspect { constructor(props) { this.props = props; } visit(node) { if (node instanceof aws_cdk_lib_1.aws_ecs.FargateService) { if (this.props.excludeResources && this.props.excludeResources.includes(node.node.id)) { return; } else { const service = node; new EcsServiceRecommendedAlarms(service, 'EcsServiceRecommendedAlarmsFromAspect', { service, ...this.props, }); } } } } exports.EcsRecommendedAlarmsAspect = EcsRecommendedAlarmsAspect; _g = JSII_RTTI_SYMBOL_1; EcsRecommendedAlarmsAspect[_g] = { fqn: "@renovosolutions/cdk-library-cloudwatch-alarms.EcsRecommendedAlarmsAspect", version: "0.0.13" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Vjcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUtxQjtBQUNyQiwyQ0FBbUQ7QUFDbkQscUNBQW9FO0FBRXBFOztHQUVHO0FBQ0gsSUFBWSwyQkFpQlg7QUFqQkQsV0FBWSwyQkFBMkI7SUFDckM7O09BRUc7SUFDSCxpRUFBa0MsQ0FBQTtJQUNsQzs7T0FFRztJQUNILHVFQUF3QyxDQUFBO0lBQ3hDOztPQUVHO0lBQ0gsc0ZBQXVELENBQUE7SUFDdkQ7O09BRUc7SUFDSCxzRUFBdUMsQ0FBQTtBQUN6QyxDQUFDLEVBakJXLDJCQUEyQiwyQ0FBM0IsMkJBQTJCLFFBaUJ0QztBQXVFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBYSw2QkFBOEIsU0FBUSw0QkFBVSxDQUFDLEtBQUs7SUFDakUsWUFBWSxLQUFpQixFQUFFLEVBQVUsRUFBRSxLQUF5QztRQUNsRixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxNQUFNLDJCQUEyQixDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQzFKLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQztRQUN2RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztRQUN4QyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSw0QkFBVSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztR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QUFNLENBQUM7Z0JBQ04sTUFBTSxPQUFPLEdBQUcsSUFBMEIsQ0FBQztnQkFFM0MsSUFBSSwyQkFBMkIsQ0FBQyxPQUFPLEVBQUUsdUNBQXVDLEVBQUU7b0JBQ2hGLE9BQU87b0JBQ1AsR0FBRyxJQUFJLENBQUMsS0FBSztpQkFDZCxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7O0FBaEJILGdFQWlCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElBc3BlY3QsXG4gIGF3c19lY3MgYXMgZWNzLFxuICBhd3NfY2xvdWR3YXRjaCBhcyBjbG91ZHdhdGNoLFxuICBEdXJhdGlvbixcbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbGFybUJhc2VQcm9wcywgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kIH0gZnJvbSAnLi9jb21tb24nO1xuXG4vKipcbiAqIFRoZSByZWNvbW1lbmRlZCBtZXRyaWNzIGZvciBFQ1MgYWxhcm1zLlxuICovXG5leHBvcnQgZW51bSBFY3NSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3Mge1xuICAvKipcbiAgICogVGhlIHBlcmNlbnRhZ2Ugb2YgQ1BVIHVuaXRzIHRoYXQgaXMgdXNlZCBieSB0aGUgY2x1c3RlciBvciBzZXJ2aWNlLlxuICAgKi9cbiAgQ1BVX1VUSUxJWkFUSU9OID0gJ0NQVVV0aWxpemF0aW9uJyxcbiAgLyoqXG4gICAqIFRoZSBwZXJjZW50YWdlIG9mIG1lbW9yeSBpbiB1c2UgYnkgdGhlIGNsdXN0ZXIgb3Igc2VydmljZS5cbiAgICovXG4gIE1FTU9SWV9VVElMSVpBVElPTiA9ICdNZW1vcnlVdGlsaXphdGlvbicsXG4gIC8qKlxuICAgKiBUaGUgZXBoZW1lcmFsIHN0b3JhZ2UgaW4gR0IgdGhhdCBpcyB1c2VkIGJ5IHRoZSBjbHVzdGVyIG9yIHNlcnZpY2UuXG4gICAqL1xuICBFUEhFTUVSQUxfU1RPUkFHRV9VVElMSVpFRCA9ICdFcGhlbWVyYWxTdG9yYWdlVXRpbGl6ZWQnLFxuICAvKipcbiAgICogVGhlIG51bWJlciBvZiB0YXNrcyBpbiB5b3VyIHNlcnZpY2VzIHRoYXQgYXJlIGluIHRoZSBSVU5OSU5HIHN0YXRlLlxuICAgKi9cbiAgUlVOTklOR19UQVNLX0NPVU5UID0gJ1J1bm5pbmdUYXNrQ291bnQnLFxufVxuXG4vKipcbiAqIFRoZSBjb21tb24gb3B0aW9uYWwgY29uZmlndXJhdGlvbiBmb3IgdGhlIGFsYXJtcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NBbGFybUJhc2VDb25maWcgZXh0ZW5kcyBBbGFybUJhc2VQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgcGVyaW9kIG92ZXIgd2hpY2ggdGhlIHNwZWNpZmllZCBzdGF0aXN0aWMgaXMgYXBwbGllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcygxKVxuICAgKi9cbiAgcmVhZG9ubHkgcGVyaW9kPzogRHVyYXRpb247XG59XG5cbi8qKlxuICogVGhlIGNvbW1vbiBwcm9wZXJ0aWVzIGZvciB0aGUgRUNTIHNlcnZpY2UgYWxhcm1zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVjc1NlcnZpY2VBbGFybVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBFQ1Mgc2VydmljZSB0byBtb25pdG9yLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZTogZWNzLkZhcmdhdGVTZXJ2aWNlO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBDcHVVdGlsaXphdGlvbiBhbGFybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NDcHVVdGlsaXphdGlvbkFsYXJtQ29uZmlnIGV4dGVuZHMgRWNzQWxhcm1CYXNlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSBwZXJjZW50YWdlICgwLTEwMCkgdmFsdWUgYWdhaW5zdCB3aGljaCB0aGUgc3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBjb21wYXJlZC5cbiAgICogVGhlIHNlcnZpY2UgbWV0cmljcyBmb3IgQ1BVIHV0aWxpemF0aW9uIG1pZ2h0IGV4Y2VlZCAxMDAlIHV0aWxpemF0aW9uLiBIb3dldmVyLFxuICAgKiB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgbW9uaXRvciB0aGUgbWV0cmljIGZvciBoaWdoIENQVSB1dGlsaXphdGlvbiB0byBhdm9pZCBpbXBhY3RpbmdcbiAgICogb3RoZXIgc2VydmljZXMuIFNldCB0aGUgdGhyZXNob2xkIHRvIGFib3V0IDkwLTk1JS4gV2UgcmVjb21tZW5kIHRoYXQgeW91IHVwZGF0ZSB5b3VyXG4gICAqIHRhc2sgZGVmaW5pdGlvbnMgdG8gcmVmbGVjdCBhY3R1YWwgdXNhZ2UgdG8gcHJldmVudCBmdXR1cmUgaXNzdWVzIHdpdGggb3RoZXIgc2VydmljZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IDkwXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgb3ZlciB3aGljaCBkYXRhIGlzIGNvbXBhcmVkIHRvIHRoZSBzcGVjaWZpZWQgdGhyZXNob2xkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBtdXN0IGJlIGJyZWFjaGluZyB0byB0cmlnZ2VyIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgNVxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YXBvaW50c1RvQWxhcm0/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYWxhcm0gbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBjbHVzdGVyTmFtZSArICcgLSAnICsgc2VydmljZU5hbWUgKyAnIC0gQ1BVVXRpbGl6YXRpb24nXG4gICAqL1xuICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3QgaGlnaCBDUFUgdXRpbGl6YXRpb24gZm9yIHRoZSBFQ1Mgc2VydmljZS5cbiAgICogQ29uc2lzdGVudCBoaWdoIENQVSB1dGlsaXphdGlvbiBjYW4gaW5kaWNhdGUgYSByZXNvdXJjZSBib3R0bGVuZWNrIG9yIGFwcGxpY2F0aW9uXG4gICAqIHBlcmZvcm1hbmNlIHByb2JsZW1zLlxuICAgKi9cbiAgcmVhZG9ubHkgYWxhcm1EZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgdGhlIEVjc1NlcnZpY2VDcHVVdGlsaXphdGlvbkFsYXJtIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NTZXJ2aWNlQ3B1VXRpbGl6YXRpb25BbGFybVByb3BzIGV4dGVuZHMgRWNzU2VydmljZUFsYXJtUHJvcHMsIEVjc0NwdVV0aWxpemF0aW9uQWxhcm1Db25maWcge31cblxuLyoqXG4gKiBUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IGhpZ2ggQ1BVIHV0aWxpemF0aW9uIGZvciB0aGUgRUNTIHNlcnZpY2UuXG4gKlxuICogQ29uc2lzdGVudCBoaWdoIENQVSB1dGlsaXphdGlvbiBjYW4gaW5kaWNhdGUgYSByZXNvdXJjZSBib3R0bGVuZWNrIG9yXG4gKiBhcHBsaWNhdGlvbiBwZXJmb3JtYW5jZSBwcm9ibGVtcy5cbiAqXG4gKiBUaGUgYWxhcm0gaXMgdHJpZ2dlcmVkIHdoZW4gQ1BVIHV0aWxpemF0aW9uIGV4Y2VlZHMgJSB0aHJlc2hvbGQuXG4gKi9cbmV4cG9ydCBjbGFzcyBFY3NTZXJ2aWNlQ3B1VXRpbGl6YXRpb25BbGFybSBleHRlbmRzIGNsb3Vkd2F0Y2guQWxhcm0ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogSUNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEVjc1NlcnZpY2VDcHVVdGlsaXphdGlvbkFsYXJtUHJvcHMpIHtcbiAgICBjb25zdCBhbGFybU5hbWUgPSBwcm9wcy5hbGFybU5hbWUgPz8gYCR7cHJvcHMuc2VydmljZS5jbHVzdGVyLmNsdXN0ZXJOYW1lfS0ke3Byb3BzLnNlcnZpY2Uuc2VydmljZU5hbWV9IC0gJHtFY3NSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3MuQ1BVX1VUSUxJWkFUSU9OfWA7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHMucGVyaW9kID8/IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyA/PyA1O1xuICAgIGNvbnN0IGRhdGFwb2ludHNUb0FsYXJtID0gcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0gPz8gNTtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSBwcm9wcy50aHJlc2hvbGQgPz8gOTA7XG4gICAgY29uc3QgdHJlYXRNaXNzaW5nRGF0YSA9IHByb3BzLnRyZWF0TWlzc2luZ0RhdGEgPz8gY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLk1JU1NJTkc7XG4gICAgY29uc3QgYWxhcm1EZXNjcmlwdGlvbiA9IHByb3BzLmFsYXJtRGVzY3JpcHRpb24gPz8gJ1RoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3QgaGlnaCBDUFUgdXRpbGl6YXRpb24gZm9yIHRoZSBFQ1Mgc2VydmljZS4nXG4gICAgKyAnIENvbnNpc3RlbnQgaGlnaCBDUFUgdXRpbGl6YXRpb24gY2FuIGluZGljYXRlIGEgcmVzb3VyY2UgYm90dGxlbmVjayBvciBhcHBsaWNhdGlvbiBwZXJmb3JtYW5jZSBwcm9ibGVtcy4nO1xuXG4gICAgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kKHBlcmlvZCwgZXZhbHVhdGlvblBlcmlvZHMsIGFsYXJtTmFtZSk7XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGFsYXJtTmFtZSxcbiAgICAgIG1ldHJpYzogcHJvcHMuc2VydmljZS5tZXRyaWNDcHVVdGlsaXphdGlvbih7XG4gICAgICAgIHBlcmlvZCxcbiAgICAgIH0pLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICBkYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGEsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6IGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9USFJFU0hPTEQsXG4gICAgICBhbGFybURlc2NyaXB0aW9uLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmFsYXJtQWN0aW9uKSB0aGlzLmFkZEFsYXJtQWN0aW9uKHByb3BzLmFsYXJtQWN0aW9uKTtcbiAgICBpZiAocHJvcHMub2tBY3Rpb24pIHRoaXMuYWRkT2tBY3Rpb24ocHJvcHMub2tBY3Rpb24pO1xuICAgIGlmIChwcm9wcy5pbnN1ZmZpY2llbnREYXRhQWN0aW9uKSB0aGlzLmFkZEluc3VmZmljaWVudERhdGFBY3Rpb24ocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbik7XG4gIH1cbn07XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIE1lbW9yeVV0aWxpemF0aW9uIGFsYXJtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVjc01lbW9yeVV0aWxpemF0aW9uQWxhcm1Db25maWcgZXh0ZW5kcyBFY3NBbGFybUJhc2VDb25maWcge1xuICAvKipcbiAgICogVGhlIHBlcmNlbnRhZ2UgKDAtMTAwKSB2YWx1ZSBhZ2FpbnN0IHdoaWNoIHRoZSBzcGVjaWZpZWQgc3RhdGlzdGljIGlzIGNvbXBhcmVkLlxuICAgKiBUaGUgbWVtb3J5IHV0aWxpemF0aW9uIGlzIG1lYXN1cmVkIGFzIHRoZSB0b3RhbCBtZW1vcnkgaW4gdXNlIGJ5IHRoZSB0YXNrcyB0aGF0XG4gICAqIGJlbG9uZyB0byB0aGUgc2VydmljZSwgZGl2aWRlZCBieSB0aGUgdG90YWwgbWVtb3J5IHJlc2VydmVkIGZvciB0aGUgdGFza3MgdGhhdFxuICAgKiBiZWxvbmcgdG8gdGhlIHNlcnZpY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IDkwXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgb3ZlciB3aGljaCBkYXRhIGlzIGNvbXBhcmVkIHRvIHRoZSBzcGVjaWZpZWQgdGhyZXNob2xkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSBldmFsdWF0aW9uUGVyaW9kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBtdXN0IGJlIGJyZWFjaGluZyB0byB0cmlnZ2VyIHRoZSBhbGFybS5cbiAgICpcbiAgICogQGRlZmF1bHQgNVxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YXBvaW50c1RvQWxhcm0/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYWxhcm0gbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBjbHVzdGVyTmFtZSArICcgLSAnICsgc2VydmljZU5hbWUgKyAnIC0gTWVtb3J5VXRpbGl6YXRpb24nXG4gICAqL1xuICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3QgaGlnaCBtZW1vcnkgdXRpbGl6YXRpb24gZm9yIHRoZSBFQ1Mgc2VydmljZS5cbiAgICogQ29uc2lzdGVudCBoaWdoIG1lbW9yeSB1dGlsaXphdGlvbiBjYW4gaW5kaWNhdGUgYSByZXNvdXJjZSBib3R0bGVuZWNrIG9yIGFwcGxpY2F0aW9uXG4gICAqIHBlcmZvcm1hbmNlIHByb2JsZW1zLlxuICAgKi9cbiAgcmVhZG9ubHkgYWxhcm1EZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgdGhlIEVjc1NlcnZpY2VNZW1vcnlVdGlsaXphdGlvbkFsYXJtIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NTZXJ2aWNlTWVtb3J5VXRpbGl6YXRpb25BbGFybVByb3BzIGV4dGVuZHMgRWNzU2VydmljZUFsYXJtUHJvcHMsIEVjc01lbW9yeVV0aWxpemF0aW9uQWxhcm1Db25maWcge31cblxuLyoqXG4gKiBUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IGhpZ2ggbWVtb3J5IHV0aWxpemF0aW9uIGZvciB0aGUgRUNTIHNlcnZpY2UuXG4gKlxuICogQ29uc2lzdGVudCBoaWdoIG1lbW9yeSB1dGlsaXphdGlvbiBjYW4gaW5kaWNhdGUgYSByZXNvdXJjZSBib3R0bGVuZWNrIG9yXG4gKiBhcHBsaWNhdGlvbiBwZXJmb3JtYW5jZSBwcm9ibGVtcy5cbiAqXG4gKiBUaGUgYWxhcm0gaXMgdHJpZ2dlcmVkIHdoZW4gbWVtb3J5IHV0aWxpemF0aW9uIGV4Y2VlZHMgJSB0aHJlc2hvbGQuXG4gKi9cbmV4cG9ydCBjbGFzcyBFY3NTZXJ2aWNlTWVtb3J5VXRpbGl6YXRpb25BbGFybSBleHRlbmRzIGNsb3Vkd2F0Y2guQWxhcm0ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogSUNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEVjc1NlcnZpY2VNZW1vcnlVdGlsaXphdGlvbkFsYXJtUHJvcHMpIHtcbiAgICBjb25zdCBhbGFybU5hbWUgPSBwcm9wcy5hbGFybU5hbWUgPz8gYCR7cHJvcHMuc2VydmljZS5jbHVzdGVyLmNsdXN0ZXJOYW1lfS0ke3Byb3BzLnNlcnZpY2Uuc2VydmljZU5hbWV9IC0gJHtFY3NSZWNvbW1lbmRlZEFsYXJtc01ldHJpY3MuTUVNT1JZX1VUSUxJWkFUSU9OfWA7XG4gICAgY29uc3QgcGVyaW9kID0gcHJvcHMucGVyaW9kID8/IER1cmF0aW9uLm1pbnV0ZXMoMSk7XG4gICAgY29uc3QgZXZhbHVhdGlvblBlcmlvZHMgPSBwcm9wcy5ldmFsdWF0aW9uUGVyaW9kcyA/PyA1O1xuICAgIGNvbnN0IGRhdGFwb2ludHNUb0FsYXJtID0gcHJvcHMuZGF0YXBvaW50c1RvQWxhcm0gPz8gNTtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSBwcm9wcy50aHJlc2hvbGQgPz8gOTA7XG4gICAgY29uc3QgdHJlYXRNaXNzaW5nRGF0YSA9IHByb3BzLnRyZWF0TWlzc2luZ0RhdGEgPz8gY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLk1JU1NJTkc7XG4gICAgY29uc3QgYWxhcm1EZXNjcmlwdGlvbiA9IHByb3BzLmFsYXJtRGVzY3JpcHRpb24gPz8gJ1RoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3QgaGlnaCBtZW1vcnkgdXRpbGl6YXRpb24gZm9yIHRoZSBFQ1Mgc2VydmljZS4nXG4gICAgKyAnIENvbnNpc3RlbnQgaGlnaCBtZW1vcnkgdXRpbGl6YXRpb24gY2FuIGluZGljYXRlIGEgcmVzb3VyY2UgYm90dGxlbmVjayBvciBhcHBsaWNhdGlvbiBwZXJmb3JtYW5jZSBwcm9ibGVtcy4nO1xuXG4gICAgdmFsaWRhdGVUb3RhbEFsYXJtUGVyaW9kKHBlcmlvZCwgZXZhbHVhdGlvblBlcmlvZHMsIGFsYXJtTmFtZSk7XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGFsYXJtTmFtZSxcbiAgICAgIG1ldHJpYzogcHJvcHMuc2VydmljZS5tZXRyaWNNZW1vcnlVdGlsaXphdGlvbih7XG4gICAgICAgIHBlcmlvZCxcbiAgICAgIH0pLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICBkYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGEsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6IGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9USFJFU0hPTEQsXG4gICAgICBhbGFybURlc2NyaXB0aW9uLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmFsYXJtQWN0aW9uKSB0aGlzLmFkZEFsYXJtQWN0aW9uKHByb3BzLmFsYXJtQWN0aW9uKTtcbiAgICBpZiAocHJvcHMub2tBY3Rpb24pIHRoaXMuYWRkT2tBY3Rpb24ocHJvcHMub2tBY3Rpb24pO1xuICAgIGlmIChwcm9wcy5pbnN1ZmZpY2llbnREYXRhQWN0aW9uKSB0aGlzLmFkZEluc3VmZmljaWVudERhdGFBY3Rpb24ocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbik7XG4gIH1cbn07XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIEVwaGVtZXJhbFN0b3JhZ2VVdGlsaXplZCBhbGFybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NFcGhlbWVyYWxTdG9yYWdlVXRpbGl6ZWRBbGFybUNvbmZpZyBleHRlbmRzIEVjc0FsYXJtQmFzZUNvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgdmFsdWUgaW4gR0IgYWdhaW5zdCB3aGljaCB0aGUgc3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBjb21wYXJlZC5cbiAgICogU2V0IHRoZSB0aHJlc2hvbGQgdG8gYWJvdXQgOTAlIG9mIHRoZSBlcGhlbWVyYWwgc3RvcmFnZSBzaXplLiBZb3UgY2FuIGFkanVzdCB0aGlzXG4gICAqIHZhbHVlIGJhc2VkIG9uIHlvdXIgYWNjZXB0YWJsZSBlcGhlbWVyYWwgc3RvcmFnZSB1dGlsaXphdGlvbiBvZiB0aGUgRmFyZ2F0ZSBjbHVzdGVyLlxuICAgKiBGb3Igc29tZSBzeXN0ZW1zLCBhIGNvbnNpc3RlbnRseSBoaWdoIGVwaGVtZXJhbCBzdG9yYWdlIHV0aWxpemVkIG1pZ2h0IGJlIG5vcm1hbCxcbiAgICogd2hpbGUgZm9yIG90aGVycywgaXQgbWlnaHQgbGVhZCB0byBmYWlsdXJlIG9mIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgcGVyaW9kcyBvdmVyIHdoaWNoIGRhdGEgaXMgY29tcGFyZWQgdG8gdGhlIHNwZWNpZmllZCB0aHJlc2hvbGQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBkYXRhIHBvaW50cyB0aGF0IG11c3QgYmUgYnJlYWNoaW5nIHRvIHRyaWdnZXIgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSBkYXRhcG9pbnRzVG9BbGFybT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBhbGFybSBuYW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGNsdXN0ZXJOYW1lICsgJyAtICcgKyBzZXJ2aWNlTmFtZSArICcgLSBFcGhlbWVyYWxTdG9yYWdlVXRpbGl6ZWQnXG4gICAqL1xuICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3QgaGlnaCBlcGhlbWVyYWwgc3RvcmFnZSB1c2FnZSBmb3IgdGhlIEZhcmdhdGUgY2x1c3Rlci5cbiAgICogQ29uc2lzdGVudCBoaWdoIGVwaGVtZXJhbCBzdG9yYWdlIHV0aWxpemVkIGNhbiBpbmRpY2F0ZSB0aGF0IHRoZSBkaXNrIGlzIGZ1bGwgYW5kIGl0IG1pZ2h0XG4gICAqIGxlYWQgdG8gZmFpbHVyZSBvZiB0aGUgY29udGFpbmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgYWxhcm1EZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgdGhlIEVjc1NlcnZpY2VFcGhlbWVyYWxTdG9yYWdlVXRpbGl6ZWRBbGFybSBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNzU2VydmljZUVwaGVtZXJhbFN0b3JhZ2VVdGlsaXplZEFsYXJtUHJvcHMgZXh0ZW5kcyBFY3NTZXJ2aWNlQWxhcm1Qcm9wcywgRWNzRXBoZW1lcmFsU3RvcmFnZVV0aWxpemVkQWxhcm1Db25maWcge31cblxuLyoqXG4gKiBUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IGhpZ2ggZXBoZW1lcmFsIHN0b3JhZ2UgdXNhZ2UgZm9yIHRoZSBGYXJnYXRlIGNsdXN0ZXIuXG4gKlxuICogQ29uc2lzdGVudCBoaWdoIGVwaGVtZXJhbCBzdG9yYWdlIHV0aWxpemVkIGNhbiBpbmRpY2F0ZSB0aGF0IHRoZSBkaXNrIGlzIGZ1bGwgYW5kIGl0XG4gKiBtaWdodCBsZWFkIHRvIGZhaWx1cmUgb2YgdGhlIGNvbnRhaW5lci5cbiAqXG4gKiBUaGUgYWxhcm0gaXMgdHJpZ2dlcmVkIHdoZW4gdGhlIHN0b3JhZ2UgdXRpbGl6ZWQgKEdCKSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKi9cbmV4cG9ydCBjbGFzcyBFY3NTZXJ2aWNlRXBoZW1lcmFsU3RvcmFnZVV0aWxpemVkQWxhcm0gZXh0ZW5kcyBjbG91ZHdhdGNoLkFsYXJtIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IElDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBFY3NTZXJ2aWNlRXBoZW1lcmFsU3RvcmFnZVV0aWxpemVkQWxhcm1Qcm9wcykge1xuICAgIGNvbnN0IGFsYXJtTmFtZSA9IHByb3BzLmFsYXJtTmFtZSA/PyBgJHtwcm9wcy5zZXJ2aWNlLmNsdXN0ZXIuY2x1c3Rlck5hbWV9LSR7cHJvcHMuc2VydmljZS5zZXJ2aWNlTmFtZX0gLSAke0Vjc1JlY29tbWVuZGVkQWxhcm1zTWV0cmljcy5FUEhFTUVSQUxfU1RPUkFHRV9VVElMSVpFRH1gO1xuICAgIGNvbnN0IHBlcmlvZCA9IHByb3BzLnBlcmlvZCA/PyBEdXJhdGlvbi5taW51dGVzKDEpO1xuICAgIGNvbnN0IGV2YWx1YXRpb25QZXJpb2RzID0gcHJvcHMuZXZhbHVhdGlvblBlcmlvZHMgPz8gNTtcbiAgICBjb25zdCBkYXRhcG9pbnRzVG9BbGFybSA9IHByb3BzLmRhdGFwb2ludHNUb0FsYXJtID8/IDU7XG4gICAgY29uc3QgdGhyZXNob2xkID0gcHJvcHMudGhyZXNob2xkO1xuICAgIGNvbnN0IHRyZWF0TWlzc2luZ0RhdGEgPSBwcm9wcy50cmVhdE1pc3NpbmdEYXRhID8/IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5NSVNTSU5HO1xuICAgIGNvbnN0IGFsYXJtRGVzY3JpcHRpb24gPSBwcm9wcy5hbGFybURlc2NyaXB0aW9uID8/ICdUaGlzIGFsYXJtIGlzIHVzZWQgdG8gZGV0ZWN0IGhpZ2ggZXBoZW1lcmFsIHN0b3JhZ2UgdXNhZ2UgZm9yIHRoZSdcbiAgICAgICsgJyBGYXJnYXRlIGNsdXN0ZXIuIENvbnNpc3RlbnQgaGlnaCBlcGhlbWVyYWwgc3RvcmFnZSB1dGlsaXplZCBjYW4gaW5kaWNhdGUgdGhhdCB0aGUgZGlzayBpcyBmdWxsIGFuZCBpdCBtaWdodCBsZWFkJ1xuICAgICAgKyAnICB0byBmYWlsdXJlIG9mIHRoZSBjb250YWluZXIuJztcblxuICAgIHZhbGlkYXRlVG90YWxBbGFybVBlcmlvZChwZXJpb2QsIGV2YWx1YXRpb25QZXJpb2RzLCBhbGFybU5hbWUpO1xuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBhbGFybU5hbWUsXG4gICAgICBtZXRyaWM6IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAgIG5hbWVzcGFjZTogJ0VDUy9Db250YWluZXJJbnNpZ2h0cycsXG4gICAgICAgIG1ldHJpY05hbWU6IEVjc1JlY29tbWVuZGVkQWxhcm1zTWV0cmljcy5FUEhFTUVSQUxfU1RPUkFHRV9VVElMSVpFRCxcbiAgICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICAgIFNlcnZpY2VOYW1lOiBwcm9wcy5zZXJ2aWNlLnNlcnZpY2VOYW1lLFxuICAgICAgICAgIENsdXN0ZXJOYW1lOiBwcm9wcy5zZXJ2aWNlLmNsdXN0ZXIuY2x1c3Rlck5hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHN0YXRpc3RpYzogJ0F2ZXJhZ2UnLFxuICAgICAgICBwZXJpb2QsXG4gICAgICB9KSxcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzLFxuICAgICAgZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcy5hbGFybUFjdGlvbikgdGhpcy5hZGRBbGFybUFjdGlvbihwcm9wcy5hbGFybUFjdGlvbik7XG4gICAgaWYgKHByb3BzLm9rQWN0aW9uKSB0aGlzLmFkZE9rQWN0aW9uKHByb3BzLm9rQWN0aW9uKTtcbiAgICBpZiAocHJvcHMuaW5zdWZmaWNpZW50RGF0YUFjdGlvbikgdGhpcy5hZGRJbnN1ZmZpY2llbnREYXRhQWN0aW9uKHByb3BzLmluc3VmZmljaWVudERhdGFBY3Rpb24pO1xuICB9XG59O1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBSdW5uaW5nVGFza0NvdW50IGFsYXJtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVjc1J1bm5pbmdUYXNrQ291bnRBbGFybUNvbmZpZyBleHRlbmRzIEVjc0FsYXJtQmFzZUNvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgdmFsdWUgYWdhaW5zdCB3aGljaCB0aGUgc3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBjb21wYXJlZC5cbiAgICogWW91IGNhbiBhZGp1c3QgdGhlIHRocmVzaG9sZCBiYXNlZCBvbiB0aGUgbWluaW11bSBydW5uaW5nIHRhc2sgY291bnQgb2YgdGhlIEVDU1xuICAgKiBzZXJ2aWNlLiBJZiB0aGUgcnVubmluZyB0YXNrIGNvdW50IGlzIDAsIHRoZSBBbWF6b24gRUNTIHNlcnZpY2Ugd2lsbCBiZSB1bmF2YWlsYWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgMFxuICAgKi9cbiAgcmVhZG9ubHkgdGhyZXNob2xkPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBwZXJpb2RzIG92ZXIgd2hpY2ggZGF0YSBpcyBjb21wYXJlZCB0byB0aGUgc3BlY2lmaWVkIHRocmVzaG9sZC5cbiAgICpcbiAgICogQGRlZmF1bHQgNVxuICAgKi9cbiAgcmVhZG9ubHkgZXZhbHVhdGlvblBlcmlvZHM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIHRoYXQgbXVzdCBiZSBicmVhY2hpbmcgdG8gdHJpZ2dlciB0aGUgYWxhcm0uXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IGRhdGFwb2ludHNUb0FsYXJtPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIGFsYXJtIG5hbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gY2x1c3Rlck5hbWUgKyAnIC0gJyArIHNlcnZpY2VOYW1lICsgJyAtIFJ1bm5pbmdUYXNrQ291bnQnXG4gICAqL1xuICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIGFsYXJtLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgYWxhcm0gaXMgdXNlZCB0byBkZXRlY3Qgd2hldGhlciB0aGUgbnVtYmVyIG9mIHJ1bm5pbmcgdGFza3MgYXJlIHRvbyBsb3cuXG4gICAqIEEgY29uc2lzdGVudCBsb3cgcnVubmluZyB0YXNrIGNvdW50IGNhbiBpbmRpY2F0ZSBFQ1Mgc2VydmljZ