UNPKG

@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
"use strict"; 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=