@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.tags.renderedTags,
});
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.710" };
/**
* 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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RSxVQUFVLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDL0YsQ0FBQzs7QUFoS0gsa0RBaUtDOzs7QUFFRDs7R0FFRztBQUNILElBQVksUUFJWDtBQUpELFdBQVksUUFBUTtJQUNsQix5QkFBYSxDQUFBO0lBQ2IsMkJBQWUsQ0FBQTtJQUNmLHVCQUFXLENBQUE7QUFDYixDQUFDLEVBSlcsUUFBUSx3QkFBUixRQUFRLFFBSW5CO0FBRUQ7O0dBRUc7QUFDSCxJQUFZLG9CQVNYO0FBVEQsV0FBWSxvQkFBb0I7SUFDOUIsK0NBQXVCLENBQUE7SUFDdkIsK0NBQXVCLENBQUE7SUFDdkIsK0NBQXVCLENBQUE7SUFDdkIsK0NBQXVCLENBQUE7SUFDdkIseURBQWlDLENBQUE7SUFDakMseURBQWlDLENBQUE7SUFDakMseURBQWlDLENBQUE7SUFDakMsK0NBQXVCLENBQUE7QUFDekIsQ0FBQyxFQVRXLG9CQUFvQixvQ0FBcEIsb0JBQW9CLFFBUy9CO0FBRUQsTUFBTSx3QkFBd0IsR0FDNUIsd3dCQUF3d0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFubm90YXRpb25zLCBUYWdzIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgKiBhcyBjbG91ZHdhdGNoIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaFwiO1xuaW1wb3J0ICogYXMgcm91dGU1MyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJvdXRlNTNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBIZWFsdGhDaGVja0Jhc2UsIEhlYWx0aENoZWNrT3B0aW9ucyB9IGZyb20gXCIuL2hlYWx0aC1jaGVja1wiO1xuaW1wb3J0IHsgSGVhbHRoQ2hlY2tUeXBlIH0gZnJvbSBcIi4vaGVhbHRoLWNoZWNrLXR5cGVcIjtcblxuZXhwb3J0IGludGVyZmFjZSBFbmRwb2ludEhlYWx0aENoZWNrUHJvcHMgZXh0ZW5kcyBIZWFsdGhDaGVja09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGRvbWFpbiBuYW1lIHRoYXQgUm91dGU1MyBwZXJmb3JtcyBoZWFsdGggY2hlY2tzIG9uLiBSb3V0ZTUzIHJlc29sdmVzIHRoZSBJUCBhZGRyZXNzIGFuZCBwZXJmb3JtcyB0aGUgbG9va3VwLlxuICAgKlxuICAgKiBJZiBJUCBhZGRyZXNzIGlzIGdpdmVuLCBpdCdzIHVzZWQgYXMgdGhlIGhvc3QgbmFtZS5cbiAgICpcbiAgICogPGI+RWl0aGVyIERvbWFpbk5hbWUgb3IgSXBBZGRyZXNzIG11c3QgYmUgc3BlY2lmaWVkPC9iPlxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBpcCBhZGRyZXNzIHRoYXQgUm91dGU1MyBwZXJmb3JtcyBoZWFsdGggY2hlY2tzIG9uLiBPcHRpb25hbGx5IGEgZG9tYWluIG5hbWUgbWF5IGJlIGdpdmVuLlxuICAgKlxuICAgKiA8Yj5BbiBJUCBhZGRyZXNzIG11c3QgYmUgc3BlY2lmaWVkIGlmIHByb3RvY29sIFRDUDwvYj5cbiAgICovXG4gIHJlYWRvbmx5IGlwQWRkcmVzcz86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwcm90b2NvbCB0aGF0IFJvdXRlNTMgdXNlcyB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBlbmRwb2ludC5cbiAgICpcbiAgICogPGI+QW4gSVAgYWRkcmVzcyBtdXN0IGJlIHNwZWNpZmllZCBpZiBwcm90b2NvbCBUQ1A8L2I+XG4gICAqXG4gICAqIEBkZWZhdWx0IEhUVFBTXG4gICAqL1xuICByZWFkb25seSBwcm90b2NvbD86IFByb3RvY29sO1xuICAvKipcbiAgICogVGhlIHBvcnQgdGhhdCBSb3V0ZTUzIHBlcmZvcm1zIGhlYWx0aCBjaGVja3MuIFRoZSBwb3J0IG11c3QgYmUgYmV0d2VlbiAxIGFuZCA2NTUzNS5cbiAgICpcbiAgICogQGRlZmF1bHQgODAgZm9yIEhUVFA7IDQ0MyBmb3IgSFRUUFNcbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoYXQgUm91dGU1MyBzZW5kcyB0aGUgaG9zdCBuYW1lIGZvciBUTFMgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWUgZm9yIEhUVFBTXG4gICAqL1xuICByZWFkb25seSBlbmFibGVTbmk/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIHBhdGggZm9yIEhUVFAgb3IgSFRUUFMgaGVhbHRoIGNoZWNrcy4gUHJvdmlkZSBhIHN0cmluZyBiZXR3ZWVuIDEgYW5kIDI1NSBsZW5ndGguXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgc2VhcmNoIHN0cmluZyBmb3IgSFRUUCBvciBIVFRQUyBoZWFsdGggY2hlY2tzLiBSb3V0ZTUzIHdpbGwgc2VhcmNoIGluIHRoZSByZXNwb25zZSBib2R5LiBQcm92aWRlIGEgc3RyaW5nIGJldHdlZW4gMSBhbmQgMjU1IGxlbmd0aC5cbiAgICovXG4gIHJlYWRvbmx5IHNlYXJjaFN0cmluZz86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBzZWNvbmRzIGJldHdlZW4gdGhlIHRpbWUgdGhhdCBSb3V0ZTUzIGdldHMgYSByZXNwb25zZSBmcm9tIHlvdXIgZW5kcG9pbnQgYW5kIHRoZSB0aW1lIHRoYXQgaXQgc2VuZHMgdGhlIG5leHQgaGVhbHRoIGNoZWNrIHJlcXVlc3QuIEVhY2ggUm91dGU1MyBoZWFsdGggY2hlY2tlciBtYWtlcyByZXF1ZXN0cyBhdCB0aGlzIGludGVydmFsLiBQcm92aWRlIGEgbnVtYmVyIGJldHdlZW4gMTAgYW5kIDMwLlxuICAgKlxuICAgKiA8aT5JZiB5b3UgY2hvb3NlIGFuIGludGVydmFsIG9mIDEwIGFuZCB0aGVyZSBhcmUgMTUgaGVhbHRoIGNoZWNrZXJzLCB0aGUgZW5kcG9pbnQgd2lsbCByZWNlaXZlIGFwcHJveGltYXRlbHkgMSByZXF1ZXN0IHBlciBzZWNvbmQuPC9pPlxuICAgKlxuICAgKiA8Yj5DYW4ndCBiZSBjaGFuZ2VkIGFmdGVyIEhlYWx0aENoZWNrIGlzIGRlcGxveWVkPC9iPlxuICAgKi9cbiAgcmVhZG9ubHkgcmVxdWVzdEludGVydmFsPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBjb25zZWN1dGl2ZSBoZWFsdGggY2hlY2tzIHRoYXQgYW4gZW5kcG9pbnQgbXVzdCBwYXNzIG9yIGZhaWwgZm9yIFJvdXRlNTMgdG8gY2hhbmdlIHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgZW5kcG9pbnQgYmV0d2VlbiBoZWFsdGh5IGFuZCB1bmhlYWx0aHkuIFByb3ZpZGUgYSBudW1iZXIgYmV0d2VlbiAxIGFuZCAxMC5cbiAgICovXG4gIHJlYWRvbmx5IGZhaWx1cmVUaHJlc2hvbGQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBXaGV0aGVyIFJvdXRlNTMgbWVhc3VyZXMgdGhlIGxhdGVuY3kgYmV0d2VlbiBoZWFsdGggY2hlY2tlcnMgaW4gbXVsdGlwbGUgQVdTIHJlZ2lvbnMgYW5kIHlvdXIgZW5kcG9pbnQsIGFuZCBkaXNwbGF5cyBhIENsb3VkV2F0Y2ggbGF0ZW5jeSBncmFwaHMgaW4gdGhlIFJvdXRlNTMgY29uc29sZS5cbiAgICpcbiAgICogPGI+Q2FuJ3QgYmUgY2hhbmdlZCBhZnRlciBIZWFsdGhDaGVjayBpcyBkZXBsb3llZDwvYj5cbiAgICovXG4gIHJlYWRvbmx5IGxhdGVuY3lHcmFwaHM/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgcmVnaW9ucyBmcm9tIHdoaWNoIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXJzIGNoZWNrIHRoZSBlbmRwb2ludC5cbiAgICpcbiAgICogPGI+SWYgb21pdHRlZCBSb3V0ZTUzIHBlcmZvcm1zIGNoZWNrcyBmcm9tIGFsbCBoZWFsdGggY2hlY2tlciByZWdpb25zLjwvYj5cbiAgICovXG4gIHJlYWRvbmx5IHJlZ2lvbnM/OiBIZWFsdGhDaGVja2VyUmVnaW9uc1tdO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIFJvdXRlNTMgSGVhbHRoQ2hlY2sgdGhhdCBtb25pdG9ycyBhbiBlbmRwb2ludCBlaXRoZXIgYnkgZG9tYWluIG5hbWUgb3IgYnkgSVAgYWRkcmVzcy5cbiAqXG4gKiA8Yj5FeGFtcGxlPC9iPlxuICogYGBgdHlwZXNjcmlwdFxuICogbmV3IEVuZHBvaW50SGVhbHRoQ2hlY2soc3RhY2ssIFwiSGVhbHRoQ2hlY2tcIiwge1xuICogICBkb21haW5OYW1lOiBcInBlcHBlcml6ZS5jb21cIixcbiAqIH0pO1xuICogYGBgXG4gKiBHZW5lcmF0ZXNcbiAqIGBgYHlhbWxcbiAqIFJlc291cmNlczpcbiAqICAgVHlwZTogQVdTOjpSb3V0ZTUzOjpIZWFsdGhDaGVja1xuICogICBQcm9wZXJ0aWVzOlxuICogICAgIEhlYWx0aENoZWNrQ29uZmlnOlxuICogICAgICAgRnVsbHlRdWFsaWZpZWREb21haW5OYW1lOiBcInBlcHBlcml6ZS5jb21cIlxuICogICAgICAgUG9ydDogNDQzXG4gKiAgICAgICBUeXBlOiBcIkhUVFBTXCJcbiAqICAgICAgIEVuYWJsZVNOSTogdHJ1ZVxuICogYGBgXG4gKiBAbGluayBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZGVfZGUvQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2Utcm91dGU1My1oZWFsdGhjaGVjay5odG1sI2F3cy1yZXNvdXJjZS1yb3V0ZTUzLWhlYWx0aGNoZWNrLXByb3BlcnRpZXNcbiAqXG4gKiBAcmVzb3VyY2UgQVdTOjpSb3V0ZTUzOjpIZWFsdGhDaGVja1xuICovXG5leHBvcnQgY2xhc3MgRW5kcG9pbnRIZWFsdGhDaGVjayBleHRlbmRzIEhlYWx0aENoZWNrQmFzZSB7XG4gIHB1YmxpYyByZWFkb25seSBoZWFsdGhDaGVja0lkOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEVuZHBvaW50SGVhbHRoQ2hlY2tQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBwcm90b2NvbCA9IHByb3BzLnByb3RvY29sIHx8IFByb3RvY29sLkhUVFBTO1xuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmhlYWx0aENoZWNrVHlwZShwcm90b2NvbCwgcHJvcHMuc2VhcmNoU3RyaW5nKTtcbiAgICBjb25zdCBwb3J0ID0gdGhpcy5kZWZhdWx0UG9ydChwcm9wcy5wb3J0LCB0eXBlKTtcbiAgICBjb25zdCBlbmFibGVTbmkgPSB0aGlzLmVuYWJsZVNuaUZvckh0dHBzKHR5cGUsIHByb3BzLmVuYWJsZVNuaSk7XG5cbiAgICBpZiAoIXByb3BzLmRvbWFpbk5hbWUgJiYgIXByb3BzLmlwQWRkcmVzcykge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJFaXRoZXIgRG9tYWluTmFtZSBvciBJcEFkZHJlc3MgaGFzIHRvIGJlIHNwZWNpZmllZFwiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuaXBBZGRyZXNzICYmICFuZXcgUmVnRXhwKElQX0FERFJFU1NfUkVHRVhfUEFUVEVSTikudGVzdChwcm9wcy5pcEFkZHJlc3MpKSB7XG4gICAgICBBbm5vdGF0aW9ucy5vZih0aGlzKS5hZGRFcnJvcihcIklwQWRkcmVzcyBtdXN0IGJlIHZhbGlkXCIpO1xuICAgIH1cblxuICAgIGlmICh1bmRlZmluZWQgIT0gcHJvcHMucG9ydCAmJiAocHJvcHMucG9ydCA8IDEgfHwgcHJvcHMucG9ydCA+IDY1NTM1KSkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJQb3J0IGhhcyB0byBiZSBiZXR3ZWVuIDEgYW5kIDY1NTM1XCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5yZXNvdXJjZVBhdGggJiYgcHJvcHMucmVzb3VyY2VQYXRoLmxlbmd0aCA+IDI1NSkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJSZXNvdXJjZVBhdGggbXVzdCBiZSBhdCBsZWFzdCAyNTUgY2hhcmFjdGVyIGxvbmdcIik7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnNlYXJjaFN0cmluZyAmJiBwcm9wcy5zZWFyY2hTdHJpbmcubGVuZ3RoID4gMjU1KSB7XG4gICAgICBBbm5vdGF0aW9ucy5vZih0aGlzKS5hZGRFcnJvcihcIlNlYXJjaFN0cmluZyBtdXN0IGJlIGF0IGxlYXN0IDI1NSBjaGFyYWN0ZXIgbG9uZ1wiKTtcbiAgICB9XG5cbiAgICBpZiAodW5kZWZpbmVkICE9IHByb3BzLmZhaWx1cmVUaHJlc2hvbGQgJiYgKHByb3BzLmZhaWx1cmVUaHJlc2hvbGQgPCAxIHx8IHByb3BzLmZhaWx1cmVUaHJlc2hvbGQgPiAxMCkpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFwiRmFpbHVyZVRocmVzaG9sZCBoYXMgdG8gYmUgYmV0d2VlbiAxMCBhbmQgMzBcIik7XG4gICAgfVxuXG4gICAgaWYgKHVuZGVmaW5lZCAhPSBwcm9wcy5yZXF1ZXN0SW50ZXJ2YWwgJiYgKHByb3BzLnJlcXVlc3RJbnRlcnZhbCA8IDEwIHx8IHByb3BzLnJlcXVlc3RJbnRlcnZhbCA+IDMwKSkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJSZXF1ZXN0SW50ZXJ2YWwgaGFzIHRvIGJlIGJldHdlZW4gMTAgYW5kIDMwXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5yZWdpb25zICYmIHByb3BzLnJlZ2lvbnMubGVuZ3RoIDwgMykge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXCJBdCBsZWFzdCB0aHJlZSBIZWFsdGhDaGVja2VyUmVnaW9ucyBoYXZlIHRvIGJlIGdpdmVuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IHJvdXRlNTMuQ2ZuSGVhbHRoQ2hlY2sodGhpcywgXCJSZXNvdXJjZVwiLCB7XG4gICAgICBoZWFsdGhDaGVja0NvbmZpZzoge1xuICAgICAgICBlbmFibGVTbmk6IGVuYWJsZVNuaSxcbiAgICAgICAgZnVsbHlRdWFsaWZpZWREb21haW5OYW1lOiBwcm9wcy5kb21haW5OYW1lLFxuICAgICAgICBpcEFkZHJlc3M6IHByb3BzLmlwQWRkcmVzcyxcbiAgICAgICAgaW52ZXJ0ZWQ6IHByb3BzLmludmVydGVkLFxuICAgICAgICBwb3J0OiBwb3J0LFxuICAgICAgICByZXNvdXJjZVBhdGg6IHByb3BzLnJlc291cmNlUGF0aCxcbiAgICAgICAgc2VhcmNoU3RyaW5nOiBwcm9wcy5zZWFyY2hTdHJpbmcsXG4gICAgICAgIHR5cGU6IHR5cGUsXG5cbiAgICAgICAgcmVxdWVzdEludGVydmFsOiBwcm9wcy5yZXF1ZXN0SW50ZXJ2YWwsXG4gICAgICAgIGZhaWx1cmVUaHJlc2hvbGQ6IHByb3BzLmZhaWx1cmVUaHJlc2hvbGQsXG4gICAgICAgIG1lYXN1cmVMYXRlbmN5OiBwcm9wcy5sYXRlbmN5R3JhcGhzLFxuICAgICAgICByZWdpb25zOiBwcm9wcy5yZWdpb25zLFxuICAgICAgfSxcbiAgICAgIGhlYWx0aENoZWNrVGFnczogdGhpcy50YWdzLnJlbmRlcmVkVGFncyxcbiAgICB9KTtcblxuICAgIHRoaXMuaGVhbHRoQ2hlY2tJZCA9IHJlc291cmNlLmF0dHJIZWFsdGhDaGVja0lkO1xuXG4gICAgY29uc3QgaGVhbHRoQ2hlY2tOYW1lID0gcHJvcHMuaGVhbHRoQ2hlY2tOYW1lIHx8IHByb3BzLmRvbWFpbk5hbWU7XG4gICAgaWYgKGhlYWx0aENoZWNrTmFtZSkge1xuICAgICAgVGFncy5vZih0aGlzKS5hZGQoXCJOYW1lXCIsIGhlYWx0aENoZWNrTmFtZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIENGTiBIZWFsdGhDaGVja1R5cGUgZm9yIHRoZSBnaXZlbiBwcm90b2NvbC4gSWYgdW5kZWZpbmVkIHJldHVybnMgZGVmYXVsdCBIVFRQUy5cbiAgICovXG4gIHByaXZhdGUgaGVhbHRoQ2hlY2tUeXBlKHByb3RvY29sPzogUHJvdG9jb2wsIHNlYXJjaFN0cmluZz86IHN0cmluZyk6IEhlYWx0aENoZWNrVHlwZSB7XG4gICAgc3dpdGNoICh0cnVlKSB7XG4gICAgICBjYXNlIFByb3RvY29sLlRDUCA9PSBwcm90b2NvbDpcbiAgICAgICAgcmV0dXJuIEhlYWx0aENoZWNrVHlwZS5UQ1A7XG4gICAgICBjYXNlIFByb3RvY29sLkhUVFBTID09IHByb3RvY29sICYmICEhc2VhcmNoU3RyaW5nOlxuICAgICAgICByZXR1cm4gSGVhbHRoQ2hlY2tUeXBlLkhUVFBTX1NUUl9NQVRDSDtcbiAgICAgIGNhc2UgUHJvdG9jb2wuSFRUUFMgPT0gcHJvdG9jb2w6XG4gICAgICAgIHJldHVybiBIZWFsdGhDaGVja1R5cGUuSFRUUFM7XG4gICAgICBjYXNlIFByb3RvY29sLkhUVFAgPT0gcHJvdG9jb2wgJiYgISFzZWFyY2hTdHJpbmc6XG4gICAgICAgIHJldHVybiBIZWFsdGhDaGVja1R5cGUuSFRUUF9TVFJfTUFUQ0g7XG4gICAgICBjYXNlIFByb3RvY29sLkhUVFAgPT0gcHJvdG9jb2w6XG4gICAgICAgIHJldHVybiBIZWFsdGhDaGVja1R5cGUuSFRUUDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBIZWFsdGhDaGVja1R5cGUuSFRUUFM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGRlZmF1bHQgaWYgdW5kZWZpbmVkIGZvciBIVFRQIGFuZCBIVFRQU1xuICAgKi9cbiAgcHJpdmF0ZSBkZWZhdWx0UG9ydChwb3J0PzogbnVtYmVyLCB0eXBlPzogSGVhbHRoQ2hlY2tUeXBlKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICBzd2l0Y2ggKHRydWUpIHtcbiAgICAgIGNhc2UgcG9ydCAmJiBwb3J0ID4gMTpcbiAgICAgICAgcmV0dXJuIHBvcnQ7XG4gICAgICBjYXNlIEhlYWx0aENoZWNrVHlwZS5IVFRQUyA9PSB0eXBlOlxuICAgICAgICByZXR1cm4gNDQzO1xuICAgICAgY2FzZSBIZWFsdGhDaGVja1R5cGUuSFRUUFNfU1RSX01BVENIID09IHR5cGU6XG4gICAgICAgIHJldHVybiA0NDM7XG4gICAgICBjYXNlIEhlYWx0aENoZWNrVHlwZS5IVFRQID09IHR5cGU6XG4gICAgICAgIHJldHVybiA4MDtcbiAgICAgIGNhc2UgSGVhbHRoQ2hlY2tUeXBlLkhUVFBfU1RSX01BVENIID09IHR5cGU6XG4gICAgICAgIHJldHVybiA4MDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgU05JIGJ5IGRlZmF1bHQgZm9yIEhUVFBTIGlmIG9taXR0ZWQsIG90aGVyd2lzZSB1bmRlZmluZWRcbiAgICovXG4gIHByaXZhdGUgZW5hYmxlU25pRm9ySHR0cHModHlwZT86IEhlYWx0aENoZWNrVHlwZSwgZW5hYmxlU25pPzogYm9vbGVhbik6IGJvb2xlYW4gfCB1bmRlZmluZWQge1xuICAgIGlmIChIZWFsdGhDaGVja1R5cGUuSFRUUFMgIT0gdHlwZSAmJiBIZWFsdGhDaGVja1R5cGUuSFRUUFNfU1RSX01BVENIICE9IHR5cGUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGlmICh1bmRlZmluZWQgPT0gZW5hYmxlU25pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZW5hYmxlU25pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBwZXJjZW50YWdlIG9mIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXJzIHRoYXQgcmVwb3J0IHRoYXQgdGhlIHN0YXR1cyBvZiB0aGUgaGVhbHRoIGNoZWNrIGlzIGhlYWx0aHlcbiAgICpcbiAgICogPGI+TGF0ZW5jeUdyYXBocyBoYXMgdG8gYmUgZW5hYmxlZDwvYj5cbiAgICpcbiAgICogVmFsaWQgc3RhdGlzdGljczogQXZlcmFnZSAocmVjb21tZW5kZWQpLCBNaW5pbXVtLCBNYXhpbXVtXG4gICAqL1xuICBwdWJsaWMgbWV0cmljSGVhbHRoQ2hlY2tQZXJjZW50YWdlSGVhbHRoeShwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJIZWFsdGhDaGVja1BlcmNlbnRhZ2VIZWFsdGh5XCIsIHsgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRpc3RpYy5BVkVSQUdFLCAuLi5wcm9wcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBpdCB0b29rIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXJzIHRvIGVzdGFibGlzaCBhIFRDUCBjb25uZWN0aW9uIHdpdGggdGhlIGVuZHBvaW50XG4gICAqXG4gICAqIFZhbGlkIHN0YXRpc3RpY3M6IEF2ZXJhZ2UgKHJlY29tbWVuZGVkKSwgTWluaW11bSwgTWF4aW11bVxuICAgKi9cbiAgcHVibGljIG1ldHJpY0Nvbm5lY3Rpb25UaW1lKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYyhcIkNvbm5lY3Rpb25UaW1lXCIsIHsgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRpc3RpYy5BVkVSQUdFLCAuLi5wcm9wcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBpdCB0b29rIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXJzIHRvIGNvbXBsZXRlIHRoZSBTU0wvVExTIGhhbmRzaGFrZVxuICAgKlxuICAgKiBWYWxpZCBzdGF0aXN0aWNzOiBBdmVyYWdlLCBNaW5pbXVtLCBNYXhpbXVtXG4gICAqL1xuICBwdWJsaWMgbWV0cmljU1NMSGFuZHNoYWtlVGltZShwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJTU0xIYW5kc2hha2VUaW1lXCIsIHsgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRpc3RpYy5BVkVSQUdFLCAuLi5wcm9wcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBpdCB0b29rIFJvdXRlNTMgaGVhbHRoIGNoZWNrZXJzIHRvIHJlY2VpdmUgdGhlIGZpcnN0IGJ5dGUgb2YgdGhlIHJlc3BvbnNlIHRvIGFuIEhUVFAgb3IgSFRUUFMgcmVxdWVzdFxuICAgKlxuICAgKiBWYWxpZCBzdGF0aXN0aWNzOiBBdmVyYWdlIChyZWNvbW1lbmRlZCksIE1pbmltdW0sIE1heGltdW1cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNUaW1lVG9GaXJzdEJ5dGUocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiVGltZVRvRmlyc3RCeXRlXCIsIHsgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRpc3RpYy5BVkVSQUdFLCAuLi5wcm9wcyB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBwcm90b2NvbCB0aGF0IFJvdXRlNTMgdXNlcyB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBlbmRwb2ludC5cbiAqL1xuZXhwb3J0IGVudW0gUHJvdG9jb2wge1xuICBIVFRQID0gXCJIVFRQXCIsXG4gIEhUVFBTID0gXCJIVFRQU1wiLFxuICBUQ1AgPSBcIlRDUFwiLFxufVxuXG4vKipcbiAqIFRoZSByZWdpb25zIG9mIGhlYWx0aCBjaGVja2VyIGZyb20gd2hpY2ggUm91dGU1MyBwZXJmb3JtcyBjaGVja3Mgb24gdGhlIGVuZHBvaW50LlxuICovXG5leHBvcnQgZW51bSBIZWFsdGhDaGVja2VyUmVnaW9ucyB7XG4gIFVTX0VBU1RfMSA9IFwidXMtZWFzdC0xXCIsXG4gIFVTX1dFU1RfMSA9IFwidXMtd2VzdC0xXCIsXG4gIFVTX1dFU1RfMiA9IFwidXMtd2VzdC0yXCIsXG4gIEVVX1dFU1RfMSA9IFwiZXUtd2VzdC0xXCIsXG4gIEFQX1NPVVRIRUFTVF8xID0gXCJhcC1zb3V0aGVhc3QtMVwiLFxuICBBUF9TT1VUSEVBU1RfMiA9IFwiYXAtc291dGhlYXN0LTJcIixcbiAgQVBfTk9SVEhFQVNUXzEgPSBcImFwLW5vcnRoZWFzdC0xXCIsXG4gIFNBX0VBU1RfMSA9IFwic2EtZWFzdC0xXCIsXG59XG5cbmNvbnN0IElQX0FERFJFU1NfUkVHRVhfUEFUVEVSTiA9XG4gIFwiKF4oKChbMC05XXxbMS05XVswLTldfDFbMC05XXsyfXwyWzAtNF1bMC05XXwyNVswLTVdKVxcXFwuKXszfShbMC05XXxbMS05XVswLTldfDFbMC05XXsyfXwyWzAtNF1bMC05XXwyNVswLTVdKSkkfF4oKFswLTlhLWZBLUZdezEsNH06KXs3LDd9WzAtOWEtZkEtRl17MSw0fXwoWzAtOWEtZkEtRl17MSw0fTopezEsN306fChbMC05YS1mQS1GXXsxLDR9Oil7MSw2fTpbMC05YS1mQS1GXXsxLDR9fChbMC05YS1mQS1GXXsxLDR9Oil7MSw1fSg6WzAtOWEtZkEtRl17MSw0fSl7MSwyfXwoWzAtOWEtZkEtRl17MSw0fTopezEsNH0oOlswLTlhLWZBLUZdezEsNH0pezEsM318KFswLTlhLWZBLUZdezEsNH06KXsxLDN9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDR9fChbMC05YS1mQS1GXXsxLDR9Oil7MSwyfSg6WzAtOWEtZkEtRl17MSw0fSl7MSw1fXxbMC05YS1mQS1GXXsxLDR9OigoOlswLTlhLWZBLUZdezEsNH0pezEsNn0pfDooKDpbMC05YS1mQS1GXXsxLDR9KXsxLDd9fDopfGZlODA6KDpbMC05YS1mQS1GXXswLDR9KXswLDR9JVswLTlhLXpBLVpdezEsfXw6OihmZmZmKDowezEsNH0pezAsMX06KXswLDF9KCgyNVswLTVdfCgyWzAtNF18MXswLDF9WzAtOV0pezAsMX1bMC05XSlcXFxcLil7MywzfSgyNVswLTVdfCgyWzAtNF18MXswLDF9WzAtOV0pezAsMX1bMC05XSl8KFswLTlhLWZBLUZdezEsNH06KXsxLDR9OigoMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pXFxcXC4pezMsM30oMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pKSQpXCI7XG4iXX0=