@pepperize/cdk-route53-health-check
Version:
Create Route53 HealthChecks to monitor TCP, HTTP, HTTPS endpoints, CloudWatch Alarms and other Route53 HealthChecks.
201 lines • 31.2 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HealthCheckerRegions = exports.Protocol = exports.EndpointHealthCheck = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const cloudwatch = require("aws-cdk-lib/aws-cloudwatch");
const route53 = require("aws-cdk-lib/aws-route53");
const health_check_1 = require("./health-check");
const health_check_type_1 = require("./health-check-type");
/**
* Create a Route53 HealthCheck that monitors an endpoint either by domain name or by IP address.
*
* <b>Example</b>
* ```typescript
* new EndpointHealthCheck(stack, "HealthCheck", {
* domainName: "pepperize.com",
* });
* ```
* Generates
* ```yaml
* Resources:
* Type: AWS::Route53::HealthCheck
* Properties:
* HealthCheckConfig:
* FullyQualifiedDomainName: "pepperize.com"
* Port: 443
* Type: "HTTPS"
* EnableSNI: true
* ```
* @link https://docs.aws.amazon.com/de_de/AWSCloudFormation/latest/UserGuide/aws-resource-route53-healthcheck.html#aws-resource-route53-healthcheck-properties
*
* @resource AWS::Route53::HealthCheck
*/
class EndpointHealthCheck extends health_check_1.HealthCheckBase {
constructor(scope, id, props) {
super(scope, id);
const protocol = props.protocol || Protocol.HTTPS;
const type = this.healthCheckType(protocol, props.searchString);
const port = this.defaultPort(props.port, type);
const enableSni = this.enableSniForHttps(type, props.enableSni);
if (!props.domainName && !props.ipAddress) {
aws_cdk_lib_1.Annotations.of(this).addError("Either DomainName or IpAddress has to be specified");
}
if (props.ipAddress && !new RegExp(IP_ADDRESS_REGEX_PATTERN).test(props.ipAddress)) {
aws_cdk_lib_1.Annotations.of(this).addError("IpAddress must be valid");
}
if (undefined != props.port && (props.port < 1 || props.port > 65535)) {
aws_cdk_lib_1.Annotations.of(this).addError("Port has to be between 1 and 65535");
}
if (props.resourcePath && props.resourcePath.length > 255) {
aws_cdk_lib_1.Annotations.of(this).addError("ResourcePath must be at least 255 character long");
}
if (props.searchString && props.searchString.length > 255) {
aws_cdk_lib_1.Annotations.of(this).addError("SearchString must be at least 255 character long");
}
if (undefined != props.failureThreshold && (props.failureThreshold < 1 || props.failureThreshold > 10)) {
aws_cdk_lib_1.Annotations.of(this).addError("FailureThreshold has to be between 10 and 30");
}
if (undefined != props.requestInterval && (props.requestInterval < 10 || props.requestInterval > 30)) {
aws_cdk_lib_1.Annotations.of(this).addError("RequestInterval has to be between 10 and 30");
}
if (props.regions && props.regions.length < 3) {
aws_cdk_lib_1.Annotations.of(this).addError("At least three HealthCheckerRegions have to be given");
}
const resource = new route53.CfnHealthCheck(this, "Resource", {
healthCheckConfig: {
enableSni: enableSni,
fullyQualifiedDomainName: props.domainName,
ipAddress: props.ipAddress,
inverted: props.inverted,
port: port,
resourcePath: props.resourcePath,
searchString: props.searchString,
type: type,
requestInterval: props.requestInterval,
failureThreshold: props.failureThreshold,
measureLatency: props.latencyGraphs,
regions: props.regions,
},
healthCheckTags: this.resolveSafeTags(),
});
this.healthCheckId = resource.attrHealthCheckId;
const healthCheckName = props.healthCheckName || props.domainName;
if (healthCheckName) {
aws_cdk_lib_1.Tags.of(this).add("Name", healthCheckName);
}
}
/**
* Returns the CFN HealthCheckType for the given protocol. If undefined returns default HTTPS.
*/
healthCheckType(protocol, searchString) {
switch (true) {
case Protocol.TCP == protocol:
return health_check_type_1.HealthCheckType.TCP;
case Protocol.HTTPS == protocol && !!searchString:
return health_check_type_1.HealthCheckType.HTTPS_STR_MATCH;
case Protocol.HTTPS == protocol:
return health_check_type_1.HealthCheckType.HTTPS;
case Protocol.HTTP == protocol && !!searchString:
return health_check_type_1.HealthCheckType.HTTP_STR_MATCH;
case Protocol.HTTP == protocol:
return health_check_type_1.HealthCheckType.HTTP;
default:
return health_check_type_1.HealthCheckType.HTTPS;
}
}
/**
* Sets the default if undefined for HTTP and HTTPS
*/
defaultPort(port, type) {
switch (true) {
case port && port > 1:
return port;
case health_check_type_1.HealthCheckType.HTTPS == type:
return 443;
case health_check_type_1.HealthCheckType.HTTPS_STR_MATCH == type:
return 443;
case health_check_type_1.HealthCheckType.HTTP == type:
return 80;
case health_check_type_1.HealthCheckType.HTTP_STR_MATCH == type:
return 80;
default:
return undefined;
}
}
/**
* Enables SNI by default for HTTPS if omitted, otherwise undefined
*/
enableSniForHttps(type, enableSni) {
if (health_check_type_1.HealthCheckType.HTTPS != type && health_check_type_1.HealthCheckType.HTTPS_STR_MATCH != type) {
return undefined;
}
if (undefined == enableSni) {
return true;
}
return enableSni;
}
/**
* The percentage of Route53 health checkers that report that the status of the health check is healthy
*
* <b>LatencyGraphs has to be enabled</b>
*
* Valid statistics: Average (recommended), Minimum, Maximum
*/
metricHealthCheckPercentageHealthy(props) {
return this.metric("HealthCheckPercentageHealthy", { statistic: cloudwatch.Statistic.AVERAGE, ...props });
}
/**
* The time in milliseconds that it took Route53 health checkers to establish a TCP connection with the endpoint
*
* Valid statistics: Average (recommended), Minimum, Maximum
*/
metricConnectionTime(props) {
return this.metric("ConnectionTime", { statistic: cloudwatch.Statistic.AVERAGE, ...props });
}
/**
* The time in milliseconds that it took Route53 health checkers to complete the SSL/TLS handshake
*
* Valid statistics: Average, Minimum, Maximum
*/
metricSSLHandshakeTime(props) {
return this.metric("SSLHandshakeTime", { statistic: cloudwatch.Statistic.AVERAGE, ...props });
}
/**
* The time in milliseconds that it took Route53 health checkers to receive the first byte of the response to an HTTP or HTTPS request
*
* Valid statistics: Average (recommended), Minimum, Maximum
*/
metricTimeToFirstByte(props) {
return this.metric("TimeToFirstByte", { statistic: cloudwatch.Statistic.AVERAGE, ...props });
}
}
exports.EndpointHealthCheck = EndpointHealthCheck;
_a = JSII_RTTI_SYMBOL_1;
EndpointHealthCheck[_a] = { fqn: "@pepperize/cdk-route53-health-check.EndpointHealthCheck", version: "0.0.755" };
/**
* The protocol that Route53 uses to communicate with the endpoint.
*/
var Protocol;
(function (Protocol) {
Protocol["HTTP"] = "HTTP";
Protocol["HTTPS"] = "HTTPS";
Protocol["TCP"] = "TCP";
})(Protocol || (exports.Protocol = Protocol = {}));
/**
* The regions of health checker from which Route53 performs checks on the endpoint.
*/
var HealthCheckerRegions;
(function (HealthCheckerRegions) {
HealthCheckerRegions["US_EAST_1"] = "us-east-1";
HealthCheckerRegions["US_WEST_1"] = "us-west-1";
HealthCheckerRegions["US_WEST_2"] = "us-west-2";
HealthCheckerRegions["EU_WEST_1"] = "eu-west-1";
HealthCheckerRegions["AP_SOUTHEAST_1"] = "ap-southeast-1";
HealthCheckerRegions["AP_SOUTHEAST_2"] = "ap-southeast-2";
HealthCheckerRegions["AP_NORTHEAST_1"] = "ap-northeast-1";
HealthCheckerRegions["SA_EAST_1"] = "sa-east-1";
})(HealthCheckerRegions || (exports.HealthCheckerRegions = HealthCheckerRegions = {}));
const IP_ADDRESS_REGEX_PATTERN = "(^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$|^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$)";
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5kcG9pbnQtaGVhbHRoLWNoZWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2VuZHBvaW50LWhlYWx0aC1jaGVjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUFnRDtBQUNoRCx5REFBeUQ7QUFDekQsbURBQW1EO0FBRW5ELGlEQUFxRTtBQUNyRSwyREFBc0Q7QUF3RXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVCRztBQUNILE1BQWEsbUJBQW9CLFNBQVEsOEJBQWU7SUFHdEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUErQjtRQUN2RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQztRQUNsRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRWhFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFDLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3RGLENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNuRix5QkFBVyxD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VSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQy9GLENBQUM7O0FBaEtILGtEQWlLQzs7O0FBRUQ7O0dBRUc7QUFDSCxJQUFZLFFBSVg7QUFKRCxXQUFZLFFBQVE7SUFDbEIseUJBQWEsQ0FBQTtJQUNiLDJCQUFlLENBQUE7SUFDZix1QkFBVyxDQUFBO0FBQ2IsQ0FBQyxFQUpXLFFBQVEsd0JBQVIsUUFBUSxRQUluQjtBQUVEOztHQUVHO0FBQ0gsSUFBWSxvQkFTWDtBQVRELFdBQVksb0JBQW9CO0lBQzlCLCtDQUF1QixDQUFBO0lBQ3ZCLCtDQUF1QixDQUFBO0lBQ3ZCLCtDQUF1QixDQUFBO0lBQ3ZCLCtDQUF1QixDQUFBO0lBQ3ZCLHlEQUFpQyxDQUFBO0lBQ2pDLHlEQUFpQyxDQUFBO0lBQ2pDLHlEQUFpQyxDQUFBO0lBQ2pDLCtDQUF1QixDQUFBO0FBQ3pCLENBQUMsRUFUVyxvQkFBb0Isb0NBQXBCLG9CQUFvQixRQVMvQjtBQUVELE1BQU0sd0JBQXdCLEdBQzVCLHd3QkFBd3dCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbm5vdGF0aW9ucywgVGFncyB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIjtcbmltcG9ydCAqIGFzIHJvdXRlNTMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1yb3V0ZTUzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgSGVhbHRoQ2hlY2tCYXNlLCBIZWFsdGhDaGVja09wdGlvbnMgfSBmcm9tIFwiLi9oZWFsdGgtY2hlY2tcIjtcbmltcG9ydCB7IEhlYWx0aENoZWNrVHlwZSB9IGZyb20gXCIuL2hlYWx0aC1jaGVjay10eXBlXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5kcG9pbnRIZWFsdGhDaGVja1Byb3BzIGV4dGVuZHMgSGVhbHRoQ2hlY2tPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBkb21haW4gbmFtZSB0aGF0IFJvdXRlNTMgcGVyZm9ybXMgaGVhbHRoIGNoZWNrcyBvbi4gUm91dGU1MyByZXNvbHZlcyB0aGUgSVAgYWRkcmVzcyBhbmQgcGVyZm9ybXMgdGhlIGxvb2t1cC5cbiAgICpcbiAgICogSWYgSVAgYWRkcmVzcyBpcyBnaXZlbiwgaXQncyB1c2VkIGFzIHRoZSBob3N0IG5hbWUuXG4gICAqXG4gICAqIDxiPkVpdGhlciBEb21haW5OYW1lIG9yIElwQWRkcmVzcyBtdXN0IGJlIHNwZWNpZmllZDwvYj5cbiAgICovXG4gIHJlYWRvbmx5IGRvbWFpbk5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgaXAgYWRkcmVzcyB0aGF0IFJvdXRlNTMgcGVyZm9ybXMgaGVhbHRoIGNoZWNrcyBvbi4gT3B0aW9uYWxseSBhIGRvbWFpbiBuYW1lIG1heSBiZSBnaXZlbi5cbiAgICpcbiAgICogPGI+QW4gSVAgYWRkcmVzcyBtdXN0IGJlIHNwZWNpZmllZCBpZiBwcm90b2NvbCBUQ1A8L2I+XG4gICAqL1xuICByZWFkb25seSBpcEFkZHJlc3M/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcHJvdG9jb2wgdGhhdCBSb3V0ZTUzIHVzZXMgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgZW5kcG9pbnQuXG4gICAqXG4gICAqIDxiPkFuIElQIGFkZHJlc3MgbXVzdCBiZSBzcGVjaWZpZWQgaWYgcHJvdG9jb2wgVENQPC9iPlxuICAgKlxuICAgKiBAZGVmYXVsdCBIVFRQU1xuICAgKi9cbiAgcmVhZG9ubHkgcHJvdG9jb2w/OiBQcm90b2NvbDtcbiAgLyoqXG4gICAqIFRoZSBwb3J0IHRoYXQgUm91dGU1MyBwZXJmb3JtcyBoZWFsdGggY2hlY2tzLiBUaGUgcG9ydCBtdXN0IGJlIGJldHdlZW4gMSBhbmQgNjU1MzUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDgwIGZvciBIVFRQOyA0NDMgZm9yIEhUVFBTXG4gICAqL1xuICByZWFkb25seSBwb3J0PzogbnVtYmVyO1xuICAvKipcbiAgICogU3BlY2lmeSB0aGF0IFJvdXRlNTMgc2VuZHMgdGhlIGhvc3QgbmFtZSBmb3IgVExTIG5lZ290aWF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlIGZvciBIVFRQU1xuICAgKi9cbiAgcmVhZG9ubHkgZW5hYmxlU25pPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBwYXRoIGZvciBIVFRQIG9yIEhUVFBTIGhlYWx0aCBjaGVja3MuIFByb3ZpZGUgYSBzdHJpbmcgYmV0d2VlbiAxIGFuZCAyNTUgbGVuZ3RoLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHNlYXJjaCBzdHJpbmcgZm9yIEhUVFAgb3IgSFRUUFMgaGVhbHRoIGNoZWNrcy4gUm91dGU1MyB3aWxsIHNlYXJjaCBpbiB0aGUgcmVzcG9uc2UgYm9keS4gUHJvdmlkZSBhIHN0cmluZyBiZXR3ZWVuIDEgYW5kIDI1NSBsZW5ndGguXG4gICAqL1xuICByZWFkb25seSBzZWFyY2hTdHJpbmc/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyBiZXR3ZWVuIHRoZSB0aW1lIHRoYXQgUm91dGU1MyBnZXRzIGEgcmVzcG9uc2UgZnJvbSB5b3VyIGVuZHBvaW50IGFuZCB0aGUgdGltZSB0aGF0IGl0IHNlbmRzIHRoZSBuZXh0IGhlYWx0aCBjaGVjayByZXF1ZXN0LiBFYWNoIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXIgbWFrZXMgcmVxdWVzdHMgYXQgdGhpcyBpbnRlcnZhbC4gUHJvdmlkZSBhIG51bWJlciBiZXR3ZWVuIDEwIGFuZCAzMC5cbiAgICpcbiAgICogPGk+SWYgeW91IGNob29zZSBhbiBpbnRlcnZhbCBvZiAxMCBhbmQgdGhlcmUgYXJlIDE1IGhlYWx0aCBjaGVja2VycywgdGhlIGVuZHBvaW50IHdpbGwgcmVjZWl2ZSBhcHByb3hpbWF0ZWx5IDEgcmVxdWVzdCBwZXIgc2Vjb25kLjwvaT5cbiAgICpcbiAgICogPGI+Q2FuJ3QgYmUgY2hhbmdlZCBhZnRlciBIZWFsdGhDaGVjayBpcyBkZXBsb3llZDwvYj5cbiAgICovXG4gIHJlYWRvbmx5IHJlcXVlc3RJbnRlcnZhbD86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgY29uc2VjdXRpdmUgaGVhbHRoIGNoZWNrcyB0aGF0IGFuIGVuZHBvaW50IG11c3QgcGFzcyBvciBmYWlsIGZvciBSb3V0ZTUzIHRvIGNoYW5nZSB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIGVuZHBvaW50IGJldHdlZW4gaGVhbHRoeSBhbmQgdW5oZWFsdGh5LiBQcm92aWRlIGEgbnVtYmVyIGJldHdlZW4gMSBhbmQgMTAuXG4gICAqL1xuICByZWFkb25seSBmYWlsdXJlVGhyZXNob2xkPzogbnVtYmVyO1xuICAvKipcbiAgICogV2hldGhlciBSb3V0ZTUzIG1lYXN1cmVzIHRoZSBsYXRlbmN5IGJldHdlZW4gaGVhbHRoIGNoZWNrZXJzIGluIG11bHRpcGxlIEFXUyByZWdpb25zIGFuZCB5b3VyIGVuZHBvaW50LCBhbmQgZGlzcGxheXMgYSBDbG91ZFdhdGNoIGxhdGVuY3kgZ3JhcGhzIGluIHRoZSBSb3V0ZTUzIGNvbnNvbGUuXG4gICAqXG4gICAqIDxiPkNhbid0IGJlIGNoYW5nZWQgYWZ0ZXIgSGVhbHRoQ2hlY2sgaXMgZGVwbG95ZWQ8L2I+XG4gICAqL1xuICByZWFkb25seSBsYXRlbmN5R3JhcGhzPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBsaXN0IG9mIHJlZ2lvbnMgZnJvbSB3aGljaCBSb3V0ZTUzIGhlYWx0aCBjaGVja2VycyBjaGVjayB0aGUgZW5kcG9pbnQuXG4gICAqXG4gICAqIDxiPklmIG9taXR0ZWQgUm91dGU1MyBwZXJmb3JtcyBjaGVja3MgZnJvbSBhbGwgaGVhbHRoIGNoZWNrZXIgcmVnaW9ucy48L2I+XG4gICAqL1xuICByZWFkb25seSByZWdpb25zPzogSGVhbHRoQ2hlY2tlclJlZ2lvbnNbXTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBSb3V0ZTUzIEhlYWx0aENoZWNrIHRoYXQgbW9uaXRvcnMgYW4gZW5kcG9pbnQgZWl0aGVyIGJ5IGRvbWFpbiBuYW1lIG9yIGJ5IElQIGFkZHJlc3MuXG4gKlxuICogPGI+RXhhbXBsZTwvYj5cbiAqIGBgYHR5cGVzY3JpcHRcbiAqIG5ldyBFbmRwb2ludEhlYWx0aENoZWNrKHN0YWNrLCBcIkhlYWx0aENoZWNrXCIsIHtcbiAqICAgZG9tYWluTmFtZTogXCJwZXBwZXJpemUuY29tXCIsXG4gKiB9KTtcbiAqIGBgYFxuICogR2VuZXJhdGVzXG4gKiBgYGB5YW1sXG4gKiBSZXNvdXJjZXM6XG4gKiAgIFR5cGU6IEFXUzo6Um91dGU1Mzo6SGVhbHRoQ2hlY2tcbiAqICAgUHJvcGVydGllczpcbiAqICAgICBIZWFsdGhDaGVja0NvbmZpZzpcbiAqICAgICAgIEZ1bGx5UXVhbGlmaWVkRG9tYWluTmFtZTogXCJwZXBwZXJpemUuY29tXCJcbiAqICAgICAgIFBvcnQ6IDQ0M1xuICogICAgICAgVHlwZTogXCJIVFRQU1wiXG4gKiAgICAgICBFbmFibGVTTkk6IHRydWVcbiAqIGBgYFxuICogQGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2RlX2RlL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLXJvdXRlNTMtaGVhbHRoY2hlY2suaHRtbCNhd3MtcmVzb3VyY2Utcm91dGU1My1oZWFsdGhjaGVjay1wcm9wZXJ0aWVzXG4gKlxuICogQHJlc291cmNlIEFXUzo6Um91dGU1Mzo6SGVhbHRoQ2hlY2tcbiAqL1xuZXhwb3J0IGNsYXNzIEVuZHBvaW50SGVhbHRoQ2hlY2sgZXh0ZW5kcyBIZWFsdGhDaGVja0Jhc2Uge1xuICBwdWJsaWMgcmVhZG9ubHkgaGVhbHRoQ2hlY2tJZDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBFbmRwb2ludEhlYWx0aENoZWNrUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgcHJvdG9jb2wgPSBwcm9wcy5wcm90b2NvbCB8fCBQcm90b2NvbC5IVFRQUztcbiAgICBjb25zdCB0eXBlID0gdGhpcy5oZWFsdGhDaGVja1R5cGUocHJvdG9jb2wsIHByb3BzLnNlYXJjaFN0cmluZyk7XG4gICAgY29uc3QgcG9ydCA9IHRoaXMuZGVmYXVsdFBvcnQocHJvcHMucG9ydCwgdHlwZSk7XG4gICAgY29uc3QgZW5hYmxlU25pID0gdGhpcy5lbmFibGVTbmlGb3JIdHRwcyh0eXBlLCBwcm9wcy5lbmFibGVTbmkpO1xuXG4gICAgaWYgKCFwcm9wcy5kb21haW5OYW1lICYmICFwcm9wcy5pcEFkZHJlc3MpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiRWl0aGVyIERvbWFpbk5hbWUgb3IgSXBBZGRyZXNzIGhhcyB0byBiZSBzcGVjaWZpZWRcIik7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmlwQWRkcmVzcyAmJiAhbmV3IFJlZ0V4cChJUF9BRERSRVNTX1JFR0VYX1BBVFRFUk4pLnRlc3QocHJvcHMuaXBBZGRyZXNzKSkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJJcEFkZHJlc3MgbXVzdCBiZSB2YWxpZFwiKTtcbiAgICB9XG5cbiAgICBpZiAodW5kZWZpbmVkICE9IHByb3BzLnBvcnQgJiYgKHByb3BzLnBvcnQgPCAxIHx8IHByb3BzLnBvcnQgPiA2NTUzNSkpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiUG9ydCBoYXMgdG8gYmUgYmV0d2VlbiAxIGFuZCA2NTUzNVwiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMucmVzb3VyY2VQYXRoICYmIHByb3BzLnJlc291cmNlUGF0aC5sZW5ndGggPiAyNTUpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiUmVzb3VyY2VQYXRoIG11c3QgYmUgYXQgbGVhc3QgMjU1IGNoYXJhY3RlciBsb25nXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5zZWFyY2hTdHJpbmcgJiYgcHJvcHMuc2VhcmNoU3RyaW5nLmxlbmd0aCA+IDI1NSkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJTZWFyY2hTdHJpbmcgbXVzdCBiZSBhdCBsZWFzdCAyNTUgY2hhcmFjdGVyIGxvbmdcIik7XG4gICAgfVxuXG4gICAgaWYgKHVuZGVmaW5lZCAhPSBwcm9wcy5mYWlsdXJlVGhyZXNob2xkICYmIChwcm9wcy5mYWlsdXJlVGhyZXNob2xkIDwgMSB8fCBwcm9wcy5mYWlsdXJlVGhyZXNob2xkID4gMTApKSB7XG4gICAgICBBbm5vdGF0aW9ucy5vZih0aGlzKS5hZGRFcnJvcihcIkZhaWx1cmVUaHJlc2hvbGQgaGFzIHRvIGJlIGJldHdlZW4gMTAgYW5kIDMwXCIpO1xuICAgIH1cblxuICAgIGlmICh1bmRlZmluZWQgIT0gcHJvcHMucmVxdWVzdEludGVydmFsICYmIChwcm9wcy5yZXF1ZXN0SW50ZXJ2YWwgPCAxMCB8fCBwcm9wcy5yZXF1ZXN0SW50ZXJ2YWwgPiAzMCkpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiUmVxdWVzdEludGVydmFsIGhhcyB0byBiZSBiZXR3ZWVuIDEwIGFuZCAzMFwiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMucmVnaW9ucyAmJiBwcm9wcy5yZWdpb25zLmxlbmd0aCA8IDMpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiQXQgbGVhc3QgdGhyZWUgSGVhbHRoQ2hlY2tlclJlZ2lvbnMgaGF2ZSB0byBiZSBnaXZlblwiKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZSA9IG5ldyByb3V0ZTUzLkNmbkhlYWx0aENoZWNrKHRoaXMsIFwiUmVzb3VyY2VcIiwge1xuICAgICAgaGVhbHRoQ2hlY2tDb25maWc6IHtcbiAgICAgICAgZW5hYmxlU25pOiBlbmFibGVTbmksXG4gICAgICAgIGZ1bGx5UXVhbGlmaWVkRG9tYWluTmFtZTogcHJvcHMuZG9tYWluTmFtZSxcbiAgICAgICAgaXBBZGRyZXNzOiBwcm9wcy5pcEFkZHJlc3MsXG4gICAgICAgIGludmVydGVkOiBwcm9wcy5pbnZlcnRlZCxcbiAgICAgICAgcG9ydDogcG9ydCxcbiAgICAgICAgcmVzb3VyY2VQYXRoOiBwcm9wcy5yZXNvdXJjZVBhdGgsXG4gICAgICAgIHNlYXJjaFN0cmluZzogcHJvcHMuc2VhcmNoU3RyaW5nLFxuICAgICAgICB0eXBlOiB0eXBlLFxuXG4gICAgICAgIHJlcXVlc3RJbnRlcnZhbDogcHJvcHMucmVxdWVzdEludGVydmFsLFxuICAgICAgICBmYWlsdXJlVGhyZXNob2xkOiBwcm9wcy5mYWlsdXJlVGhyZXNob2xkLFxuICAgICAgICBtZWFzdXJlTGF0ZW5jeTogcHJvcHMubGF0ZW5jeUdyYXBocyxcbiAgICAgICAgcmVnaW9uczogcHJvcHMucmVnaW9ucyxcbiAgICAgIH0sXG4gICAgICBoZWFsdGhDaGVja1RhZ3M6IHRoaXMucmVzb2x2ZVNhZmVUYWdzKCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmhlYWx0aENoZWNrSWQgPSByZXNvdXJjZS5hdHRySGVhbHRoQ2hlY2tJZDtcblxuICAgIGNvbnN0IGhlYWx0aENoZWNrTmFtZSA9IHByb3BzLmhlYWx0aENoZWNrTmFtZSB8fCBwcm9wcy5kb21haW5OYW1lO1xuICAgIGlmIChoZWFsdGhDaGVja05hbWUpIHtcbiAgICAgIFRhZ3Mub2YodGhpcykuYWRkKFwiTmFtZVwiLCBoZWFsdGhDaGVja05hbWUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBDRk4gSGVhbHRoQ2hlY2tUeXBlIGZvciB0aGUgZ2l2ZW4gcHJvdG9jb2wuIElmIHVuZGVmaW5lZCByZXR1cm5zIGRlZmF1bHQgSFRUUFMuXG4gICAqL1xuICBwcml2YXRlIGhlYWx0aENoZWNrVHlwZShwcm90b2NvbD86IFByb3RvY29sLCBzZWFyY2hTdHJpbmc/OiBzdHJpbmcpOiBIZWFsdGhDaGVja1R5cGUge1xuICAgIHN3aXRjaCAodHJ1ZSkge1xuICAgICAgY2FzZSBQcm90b2NvbC5UQ1AgPT0gcHJvdG9jb2w6XG4gICAgICAgIHJldHVybiBIZWFsdGhDaGVja1R5cGUuVENQO1xuICAgICAgY2FzZSBQcm90b2NvbC5IVFRQUyA9PSBwcm90b2NvbCAmJiAhIXNlYXJjaFN0cmluZzpcbiAgICAgICAgcmV0dXJuIEhlYWx0aENoZWNrVHlwZS5IVFRQU19TVFJfTUFUQ0g7XG4gICAgICBjYXNlIFByb3RvY29sLkhUVFBTID09IHByb3RvY29sOlxuICAgICAgICByZXR1cm4gSGVhbHRoQ2hlY2tUeXBlLkhUVFBTO1xuICAgICAgY2FzZSBQcm90b2NvbC5IVFRQID09IHByb3RvY29sICYmICEhc2VhcmNoU3RyaW5nOlxuICAgICAgICByZXR1cm4gSGVhbHRoQ2hlY2tUeXBlLkhUVFBfU1RSX01BVENIO1xuICAgICAgY2FzZSBQcm90b2NvbC5IVFRQID09IHByb3RvY29sOlxuICAgICAgICByZXR1cm4gSGVhbHRoQ2hlY2tUeXBlLkhUVFA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gSGVhbHRoQ2hlY2tUeXBlLkhUVFBTO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IGlmIHVuZGVmaW5lZCBmb3IgSFRUUCBhbmQgSFRUUFNcbiAgICovXG4gIHByaXZhdGUgZGVmYXVsdFBvcnQocG9ydD86IG51bWJlciwgdHlwZT86IEhlYWx0aENoZWNrVHlwZSk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgc3dpdGNoICh0cnVlKSB7XG4gICAgICBjYXNlIHBvcnQgJiYgcG9ydCA+IDE6XG4gICAgICAgIHJldHVybiBwb3J0O1xuICAgICAgY2FzZSBIZWFsdGhDaGVja1R5cGUuSFRUUFMgPT0gdHlwZTpcbiAgICAgICAgcmV0dXJuIDQ0MztcbiAgICAgIGNhc2UgSGVhbHRoQ2hlY2tUeXBlLkhUVFBTX1NUUl9NQVRDSCA9PSB0eXBlOlxuICAgICAgICByZXR1cm4gNDQzO1xuICAgICAgY2FzZSBIZWFsdGhDaGVja1R5cGUuSFRUUCA9PSB0eXBlOlxuICAgICAgICByZXR1cm4gODA7XG4gICAgICBjYXNlIEhlYWx0aENoZWNrVHlwZS5IVFRQX1NUUl9NQVRDSCA9PSB0eXBlOlxuICAgICAgICByZXR1cm4gODA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIFNOSSBieSBkZWZhdWx0IGZvciBIVFRQUyBpZiBvbWl0dGVkLCBvdGhlcndpc2UgdW5kZWZpbmVkXG4gICAqL1xuICBwcml2YXRlIGVuYWJsZVNuaUZvckh0dHBzKHR5cGU/OiBIZWFsdGhDaGVja1R5cGUsIGVuYWJsZVNuaT86IGJvb2xlYW4pOiBib29sZWFuIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoSGVhbHRoQ2hlY2tUeXBlLkhUVFBTICE9IHR5cGUgJiYgSGVhbHRoQ2hlY2tUeXBlLkhUVFBTX1NUUl9NQVRDSCAhPSB0eXBlKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAodW5kZWZpbmVkID09IGVuYWJsZVNuaSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVuYWJsZVNuaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcGVyY2VudGFnZSBvZiBSb3V0ZTUzIGhlYWx0aCBjaGVja2VycyB0aGF0IHJlcG9ydCB0aGF0IHRoZSBzdGF0dXMgb2YgdGhlIGhlYWx0aCBjaGVjayBpcyBoZWFsdGh5XG4gICAqXG4gICAqIDxiPkxhdGVuY3lHcmFwaHMgaGFzIHRvIGJlIGVuYWJsZWQ8L2I+XG4gICAqXG4gICAqIFZhbGlkIHN0YXRpc3RpY3M6IEF2ZXJhZ2UgKHJlY29tbWVuZGVkKSwgTWluaW11bSwgTWF4aW11bVxuICAgKi9cbiAgcHVibGljIG1ldHJpY0hlYWx0aENoZWNrUGVyY2VudGFnZUhlYWx0aHkocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiSGVhbHRoQ2hlY2tQZXJjZW50YWdlSGVhbHRoeVwiLCB7IHN0YXRpc3RpYzogY2xvdWR3YXRjaC5TdGF0aXN0aWMuQVZFUkFHRSwgLi4ucHJvcHMgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgaXQgdG9vayBSb3V0ZTUzIGhlYWx0aCBjaGVja2VycyB0byBlc3RhYmxpc2ggYSBUQ1AgY29ubmVjdGlvbiB3aXRoIHRoZSBlbmRwb2ludFxuICAgKlxuICAgKiBWYWxpZCBzdGF0aXN0aWNzOiBBdmVyYWdlIChyZWNvbW1lbmRlZCksIE1pbmltdW0sIE1heGltdW1cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDb25uZWN0aW9uVGltZShwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJDb25uZWN0aW9uVGltZVwiLCB7IHN0YXRpc3RpYzogY2xvdWR3YXRjaC5TdGF0aXN0aWMuQVZFUkFHRSwgLi4ucHJvcHMgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgaXQgdG9vayBSb3V0ZTUzIGhlYWx0aCBjaGVja2VycyB0byBjb21wbGV0ZSB0aGUgU1NML1RMUyBoYW5kc2hha2VcbiAgICpcbiAgICogVmFsaWQgc3RhdGlzdGljczogQXZlcmFnZSwgTWluaW11bSwgTWF4aW11bVxuICAgKi9cbiAgcHVibGljIG1ldHJpY1NTTEhhbmRzaGFrZVRpbWUocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiU1NMSGFuZHNoYWtlVGltZVwiLCB7IHN0YXRpc3RpYzogY2xvdWR3YXRjaC5TdGF0aXN0aWMuQVZFUkFHRSwgLi4ucHJvcHMgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgaXQgdG9vayBSb3V0ZTUzIGhlYWx0aCBjaGVja2VycyB0byByZWNlaXZlIHRoZSBmaXJzdCBieXRlIG9mIHRoZSByZXNwb25zZSB0byBhbiBIVFRQIG9yIEhUVFBTIHJlcXVlc3RcbiAgICpcbiAgICogVmFsaWQgc3RhdGlzdGljczogQXZlcmFnZSAocmVjb21tZW5kZWQpLCBNaW5pbXVtLCBNYXhpbXVtXG4gICAqL1xuICBwdWJsaWMgbWV0cmljVGltZVRvRmlyc3RCeXRlKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYyhcIlRpbWVUb0ZpcnN0Qnl0ZVwiLCB7IHN0YXRpc3RpYzogY2xvdWR3YXRjaC5TdGF0aXN0aWMuQVZFUkFHRSwgLi4ucHJvcHMgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgcHJvdG9jb2wgdGhhdCBSb3V0ZTUzIHVzZXMgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgZW5kcG9pbnQuXG4gKi9cbmV4cG9ydCBlbnVtIFByb3RvY29sIHtcbiAgSFRUUCA9IFwiSFRUUFwiLFxuICBIVFRQUyA9IFwiSFRUUFNcIixcbiAgVENQID0gXCJUQ1BcIixcbn1cblxuLyoqXG4gKiBUaGUgcmVnaW9ucyBvZiBoZWFsdGggY2hlY2tlciBmcm9tIHdoaWNoIFJvdXRlNTMgcGVyZm9ybXMgY2hlY2tzIG9uIHRoZSBlbmRwb2ludC5cbiAqL1xuZXhwb3J0IGVudW0gSGVhbHRoQ2hlY2tlclJlZ2lvbnMge1xuICBVU19FQVNUXzEgPSBcInVzLWVhc3QtMVwiLFxuICBVU19XRVNUXzEgPSBcInVzLXdlc3QtMVwiLFxuICBVU19XRVNUXzIgPSBcInVzLXdlc3QtMlwiLFxuICBFVV9XRVNUXzEgPSBcImV1LXdlc3QtMVwiLFxuICBBUF9TT1VUSEVBU1RfMSA9IFwiYXAtc291dGhlYXN0LTFcIixcbiAgQVBfU09VVEhFQVNUXzIgPSBcImFwLXNvdXRoZWFzdC0yXCIsXG4gIEFQX05PUlRIRUFTVF8xID0gXCJhcC1ub3J0aGVhc3QtMVwiLFxuICBTQV9FQVNUXzEgPSBcInNhLWVhc3QtMVwiLFxufVxuXG5jb25zdCBJUF9BRERSRVNTX1JFR0VYX1BBVFRFUk4gPVxuICBcIiheKCgoWzAtOV18WzEtOV1bMC05XXwxWzAtOV17Mn18MlswLTRdWzAtOV18MjVbMC01XSlcXFxcLil7M30oWzAtOV18WzEtOV1bMC05XXwxWzAtOV17Mn18MlswLTRdWzAtOV18MjVbMC01XSkpJHxeKChbMC05YS1mQS1GXXsxLDR9Oil7Nyw3fVswLTlhLWZBLUZdezEsNH18KFswLTlhLWZBLUZdezEsNH06KXsxLDd9OnwoWzAtOWEtZkEtRl17MSw0fTopezEsNn06WzAtOWEtZkEtRl17MSw0fXwoWzAtOWEtZkEtRl17MSw0fTopezEsNX0oOlswLTlhLWZBLUZdezEsNH0pezEsMn18KFswLTlhLWZBLUZdezEsNH06KXsxLDR9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDN9fChbMC05YS1mQS1GXXsxLDR9Oil7MSwzfSg6WzAtOWEtZkEtRl17MSw0fSl7MSw0fXwoWzAtOWEtZkEtRl17MSw0fTopezEsMn0oOlswLTlhLWZBLUZdezEsNH0pezEsNX18WzAtOWEtZkEtRl17MSw0fTooKDpbMC05YS1mQS1GXXsxLDR9KXsxLDZ9KXw6KCg6WzAtOWEtZkEtRl17MSw0fSl7MSw3fXw6KXxmZTgwOig6WzAtOWEtZkEtRl17MCw0fSl7MCw0fSVbMC05YS16QS1aXXsxLH18OjooZmZmZig6MHsxLDR9KXswLDF9Oil7MCwxfSgoMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pXFxcXC4pezMsM30oMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pfChbMC05YS1mQS1GXXsxLDR9Oil7MSw0fTooKDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKVxcXFwuKXszLDN9KDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKSkkKVwiO1xuIl19