UNPKG

cdk-monitoring-constructs

Version:

[![NPM version](https://badge.fury.io/js/cdk-monitoring-constructs.svg)](https://badge.fury.io/js/cdk-monitoring-constructs) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.cdklabs/cdkmonitoringconstructs/badge.svg)](https://m

258 lines 50.1 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamoTableMonitoring = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch"); const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb"); const DynamoTableMetricFactory_1 = require("./DynamoTableMetricFactory"); const common_1 = require("../../common"); const dashboard_1 = require("../../dashboard"); class DynamoTableMonitoring extends common_1.Monitoring { constructor(scope, props) { super(scope, props); const namingStrategy = new dashboard_1.MonitoringNamingStrategy({ ...props, namedConstruct: props.table, fallbackConstructName: this.resolveTableName(props.table), }); this.title = namingStrategy.resolveHumanReadableName(); this.tableUrl = scope .createAwsConsoleUrlFactory() .getDynamoTableUrl(props.table.tableName); this.tableBillingMode = props.billingMode ?? this.resolveTableBillingMode(props.table); this.alarmFactory = this.createAlarmFactory(namingStrategy.resolveAlarmFriendlyName()); this.errorAlarmFactory = new common_1.ErrorAlarmFactory(this.alarmFactory); this.latencyAlarmFactory = new common_1.LatencyAlarmFactory(this.alarmFactory); this.dynamoCapacityAlarmFactory = new common_1.DynamoAlarmFactory(this.alarmFactory); this.usageAlarmFactory = new common_1.UsageAlarmFactory(this.alarmFactory); this.errorCountAnnotations = []; this.latencyAnnotations = []; this.dynamoReadCapacityAnnotations = []; this.dynamoWriteCapacityAnnotations = []; this.throttledEventsAnnotations = []; const metricFactory = new DynamoTableMetricFactory_1.DynamoTableMetricFactory(scope.createMetricFactory(), props); this.provisionedReadUnitsMetric = metricFactory.metricProvisionedReadCapacityUnits(); this.provisionedWriteUnitsMetric = metricFactory.metricProvisionedWriteCapacityUnits(); this.consumedReadUnitsMetric = metricFactory.metricConsumedReadCapacityUnits(); this.consumedWriteUnitsMetric = metricFactory.metricConsumedWriteCapacityUnits(); this.readThrottleCountMetric = metricFactory.metricThrottledReadRequestCount(); this.writeThrottleCountMetric = metricFactory.metricThrottledWriteRequestCount(); this.systemErrorMetric = metricFactory.metricSystemErrorsCount(); this.timeToLiveDeletedItemCountMetric = metricFactory.metricTimeToLiveDeletedItemCount(); this.latencyAverageSearchMetrics = metricFactory.metricSearchAverageSuccessfulRequestLatencyInMillis(); this.averagePerOperationLatencyMetrics = { [aws_dynamodb_1.Operation.GET_RECORDS]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.GET_RECORDS), [aws_dynamodb_1.Operation.QUERY]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.QUERY), [aws_dynamodb_1.Operation.SCAN]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.SCAN), [aws_dynamodb_1.Operation.PUT_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.PUT_ITEM), [aws_dynamodb_1.Operation.GET_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.GET_ITEM), [aws_dynamodb_1.Operation.UPDATE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.UPDATE_ITEM), [aws_dynamodb_1.Operation.DELETE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.DELETE_ITEM), [aws_dynamodb_1.Operation.BATCH_GET_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.BATCH_GET_ITEM), [aws_dynamodb_1.Operation.BATCH_WRITE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.BATCH_WRITE_ITEM), }; this.readCapacityUsageMetric = metricFactory.metricReadCapacityUtilizationPercentage(); this.writeCapacityUsageMetric = metricFactory.metricWriteCapacityUtilizationPercentage(); for (const disambiguator in props.addConsumedReadCapacityAlarm) { const alarmProps = props.addConsumedReadCapacityAlarm[disambiguator]; const createdAlarm = this.dynamoCapacityAlarmFactory.addConsumedCapacityAlarm(this.consumedReadUnitsMetric, common_1.CapacityType.READ, alarmProps, disambiguator); this.dynamoReadCapacityAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } for (const disambiguator in props.addConsumedWriteCapacityAlarm) { const alarmProps = props.addConsumedWriteCapacityAlarm[disambiguator]; const createdAlarm = this.dynamoCapacityAlarmFactory.addConsumedCapacityAlarm(this.consumedWriteUnitsMetric, common_1.CapacityType.WRITE, alarmProps, disambiguator); this.dynamoWriteCapacityAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } for (const disambiguator in props.addReadThrottledEventsCountAlarm) { const alarmProps = props.addReadThrottledEventsCountAlarm[disambiguator]; const createdAlarm = this.dynamoCapacityAlarmFactory.addThrottledEventsAlarm(this.readThrottleCountMetric, common_1.CapacityType.READ, alarmProps, disambiguator); this.throttledEventsAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } for (const disambiguator in props.addWriteThrottledEventsCountAlarm) { const alarmProps = props.addWriteThrottledEventsCountAlarm[disambiguator]; const createdAlarm = this.dynamoCapacityAlarmFactory.addThrottledEventsAlarm(this.writeThrottleCountMetric, common_1.CapacityType.WRITE, alarmProps, disambiguator); this.throttledEventsAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } for (const disambiguator in props.addSystemErrorCountAlarm) { const alarmProps = props.addSystemErrorCountAlarm[disambiguator]; const createdAlarm = this.errorAlarmFactory.addErrorCountAlarm(this.systemErrorMetric, common_1.ErrorType.SYSTEM_ERROR, alarmProps, disambiguator); this.errorCountAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } for (const disambiguator in props.addMinTimeToLiveDeletedItemCountAlarm) { const alarmProps = { // Missing data is bad if we expect TTL to be enabled treatMissingDataOverride: aws_cloudwatch_1.TreatMissingData.BREACHING, ...props.addMinTimeToLiveDeletedItemCountAlarm[disambiguator], }; const createdAlarm = this.usageAlarmFactory.addMinCountAlarm(this.timeToLiveDeletedItemCountMetric, alarmProps, disambiguator); this.addAlarm(createdAlarm); } this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.GET_RECORDS, props.addAverageSuccessfulGetRecordsLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.QUERY, props.addAverageSuccessfulQueryLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.SCAN, props.addAverageSuccessfulScanLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.PUT_ITEM, props.addAverageSuccessfulPutItemLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.GET_ITEM, props.addAverageSuccessfulGetItemLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.UPDATE_ITEM, props.addAverageSuccessfulUpdateItemLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.DELETE_ITEM, props.addAverageSuccessfulDeleteItemLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.BATCH_GET_ITEM, props.addAverageSuccessfulBatchGetItemLatencyAlarm); this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.BATCH_WRITE_ITEM, props.addAverageSuccessfulBatchWriteItemLatencyAlarm); props.useCreatedAlarms?.consume(this.createdAlarms()); } forEachOperationLatencyAlarmDefinition(operation, alarm) { for (const disambiguator in alarm) { const alarmProps = alarm[disambiguator]; const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.averagePerOperationLatencyMetrics[operation], common_1.LatencyType.AVERAGE, alarmProps, disambiguator, operation); this.latencyAnnotations.push(createdAlarm.annotation); this.addAlarm(createdAlarm); } } summaryWidgets() { return [ // Title this.createTitleWidget(), // Read units this.createReadCapacityWidget(common_1.HalfWidth, common_1.DefaultSummaryWidgetHeight), // Write units this.createWriteCapacityWidget(common_1.HalfWidth, common_1.DefaultSummaryWidgetHeight), ]; } widgets() { return [ // Title this.createTitleWidget(), new aws_cloudwatch_1.Column( // Read units this.createReadCapacityWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHalfHeight), // Write units this.createWriteCapacityWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHalfHeight)), // Latency this.createLatencyWidget(common_1.QuarterWidth + common_1.HalfQuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight), // Throttles this.createThrottlesWidget(common_1.HalfQuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight), // Errors this.createErrorsWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight), ]; } createLatencyWidget(width, height) { return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Latency (Average)", left: [this.latencyAverageSearchMetrics], leftYAxis: common_1.TimeAxisMillisFromZero, leftAnnotations: this.latencyAnnotations, legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT, }); } createThrottlesWidget(width, height) { return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Throttles", left: [this.readThrottleCountMetric, this.writeThrottleCountMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.throttledEventsAnnotations, }); } createErrorsWidget(width, height) { return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Errors", left: [this.systemErrorMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.errorCountAnnotations, }); } createReadCapacityWidget(width, height) { if (this.tableBillingMode === aws_dynamodb_1.BillingMode.PAY_PER_REQUEST) { // simplified view for on-demand table return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Read Usage", left: [this.consumedReadUnitsMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.dynamoReadCapacityAnnotations, }); } return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Read Usage", left: [this.consumedReadUnitsMetric, this.provisionedReadUnitsMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.dynamoReadCapacityAnnotations, right: [this.readCapacityUsageMetric], rightYAxis: common_1.PercentageAxisFromZeroToHundred, legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT, }); } createWriteCapacityWidget(width, height) { if (this.tableBillingMode === aws_dynamodb_1.BillingMode.PAY_PER_REQUEST) { // simplified view for on-demand table return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Write Usage", left: [this.consumedWriteUnitsMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.dynamoWriteCapacityAnnotations, }); } return new aws_cloudwatch_1.GraphWidget({ width, height, title: "Write Usage", left: [this.consumedWriteUnitsMetric, this.provisionedWriteUnitsMetric], leftYAxis: common_1.CountAxisFromZero, leftAnnotations: this.dynamoWriteCapacityAnnotations, right: [this.writeCapacityUsageMetric], rightYAxis: common_1.PercentageAxisFromZeroToHundred, legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT, }); } createTitleWidget() { return new dashboard_1.MonitoringHeaderWidget({ family: "Dynamo Table", title: this.title, goToLinkUrl: this.tableUrl, }); } resolveTableName(dynamoTable) { // try to take the name (if specified) instead of token return dynamoTable.node.defaultChild?.tableName; } resolveTableBillingMode(dynamoTable) { const billingMode = dynamoTable.node.defaultChild ?.billingMode; if (billingMode) { return billingMode; } // fallback to default (for backwards compatibility) return aws_dynamodb_1.BillingMode.PROVISIONED; } } exports.DynamoTableMonitoring = DynamoTableMonitoring; _a = JSII_RTTI_SYMBOL_1; DynamoTableMonitoring[_a] = { fqn: "cdk-monitoring-constructs.DynamoTableMonitoring", version: "9.15.2" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRHluYW1vVGFibGVNb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiRHluYW1vVGFibGVNb25pdG9yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0RBUW9DO0FBQ3BDLDJEQUtrQztBQUVsQyx5RUFHb0M7QUFDcEMseUNBMkJzQjtBQUN0QiwrQ0FHeUI7QUFxRXpCLE1BQWEscUJBQXNCLFNBQVEsbUJBQVU7SUFrQ25ELFlBQVksS0FBc0IsRUFBRSxLQUFpQztRQUNuRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXBCLE1BQU0sY0FBYyxHQUFHLElBQUksb0NBQXdCLENBQUM7WUFDbEQsR0FBRyxLQUFLO1lBQ1IsY0FBYyxFQUFFLEtBQUssQ0FBQyxLQUFLO1lBQzNCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1NBQzFELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDdkQsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLO2FBQ2xCLDBCQUEwQixFQUFFO2FBQzVCLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDLGdCQUFnQjtZQUNuQixLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQ3pDLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksMEJBQWlCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLDRCQUFtQixDQUFD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aFdpZGdldCxcbiAgSG9yaXpvbnRhbEFubm90YXRpb24sXG4gIElNZXRyaWMsXG4gIElXaWRnZXQsXG4gIExlZ2VuZFBvc2l0aW9uLFxuICBUcmVhdE1pc3NpbmdEYXRhLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIjtcbmltcG9ydCB7XG4gIEJpbGxpbmdNb2RlLFxuICBDZm5UYWJsZSxcbiAgSVRhYmxlLFxuICBPcGVyYXRpb24sXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGJcIjtcblxuaW1wb3J0IHtcbiAgRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5LFxuICBEeW5hbW9UYWJsZU1ldHJpY0ZhY3RvcnlQcm9wcyxcbn0gZnJvbSBcIi4vRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5XCI7XG5pbXBvcnQge1xuICBBbGFybUZhY3RvcnksXG4gIEJhc2VNb25pdG9yaW5nUHJvcHMsXG4gIENhcGFjaXR5VHlwZSxcbiAgQ29uc3VtZWRDYXBhY2l0eVRocmVzaG9sZCxcbiAgQ291bnRBeGlzRnJvbVplcm8sXG4gIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0LFxuICBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhhbGZIZWlnaHQsXG4gIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGVpZ2h0LFxuICBEeW5hbW9BbGFybUZhY3RvcnksXG4gIEVycm9yQWxhcm1GYWN0b3J5LFxuICBFcnJvckNvdW50VGhyZXNob2xkLFxuICBFcnJvclR5cGUsXG4gIEhhbGZRdWFydGVyV2lkdGgsXG4gIEhhbGZXaWR0aCxcbiAgTGF0ZW5jeUFsYXJtRmFjdG9yeSxcbiAgTGF0ZW5jeVRocmVzaG9sZCxcbiAgTGF0ZW5jeVR5cGUsXG4gIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gIE1pblVzYWdlQ291bnRUaHJlc2hvbGQsXG4gIE1vbml0b3JpbmcsXG4gIE1vbml0b3JpbmdTY29wZSxcbiAgUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgUXVhcnRlcldpZHRoLFxuICBUaHJvdHRsZWRFdmVudHNUaHJlc2hvbGQsXG4gIFRpbWVBeGlzTWlsbGlzRnJvbVplcm8sXG4gIFVzYWdlQWxhcm1GYWN0b3J5LFxufSBmcm9tIFwiLi4vLi4vY29tbW9uXCI7XG5pbXBvcnQge1xuICBNb25pdG9yaW5nSGVhZGVyV2lkZ2V0LFxuICBNb25pdG9yaW5nTmFtaW5nU3RyYXRlZ3ksXG59IGZyb20gXCIuLi8uLi9kYXNoYm9hcmRcIjtcblxuZXhwb3J0IGludGVyZmFjZSBEeW5hbW9UYWJsZU1vbml0b3JpbmdPcHRpb25zIGV4dGVuZHMgQmFzZU1vbml0b3JpbmdQcm9wcyB7XG4gIHJlYWRvbmx5IGFkZENvbnN1bWVkUmVhZENhcGFjaXR5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIENvbnN1bWVkQ2FwYWNpdHlUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQ29uc3VtZWRXcml0ZUNhcGFjaXR5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIENvbnN1bWVkQ2FwYWNpdHlUaHJlc2hvbGRcbiAgPjtcblxuICByZWFkb25seSBhZGRSZWFkVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgVGhyb3R0bGVkRXZlbnRzVGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZFdyaXRlVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgVGhyb3R0bGVkRXZlbnRzVGhyZXNob2xkXG4gID47XG5cbiAgcmVhZG9ubHkgYWRkU3lzdGVtRXJyb3JDb3VudEFsYXJtPzogUmVjb3JkPHN0cmluZywgRXJyb3JDb3VudFRocmVzaG9sZD47XG4gIHJlYWRvbmx5IGFkZE1pblRpbWVUb0xpdmVEZWxldGVkSXRlbUNvdW50QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIE1pblVzYWdlQ291bnRUaHJlc2hvbGRcbiAgPjtcblxuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bEdldFJlY29yZHNMYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxRdWVyeUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFNjYW5MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxQdXRJdGVtTGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsR2V0SXRlbUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFVwZGF0ZUl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxEZWxldGVJdGVtTGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsQmF0Y2hHZXRJdGVtTGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsQmF0Y2hXcml0ZUl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEeW5hbW9UYWJsZU1vbml0b3JpbmdQcm9wc1xuICBleHRlbmRzIER5bmFtb1RhYmxlTWV0cmljRmFjdG9yeVByb3BzLFxuICAgIER5bmFtb1RhYmxlTW9uaXRvcmluZ09wdGlvbnMge31cblxuZXhwb3J0IGNsYXNzIER5bmFtb1RhYmxlTW9uaXRvcmluZyBleHRlbmRzIE1vbml0b3Jpbmcge1xuICByZWFkb25seSB0aXRsZTogc3RyaW5nO1xuICByZWFkb25seSB0YWJsZVVybD86IHN0cmluZztcbiAgcmVhZG9ubHkgdGFibGVCaWxsaW5nTW9kZTogQmlsbGluZ01vZGU7XG5cbiAgcmVhZG9ubHkgYWxhcm1GYWN0b3J5OiBBbGFybUZhY3Rvcnk7XG4gIHJlYWRvbmx5IGVycm9yQWxhcm1GYWN0b3J5OiBFcnJvckFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgbGF0ZW5jeUFsYXJtRmFjdG9yeTogTGF0ZW5jeUFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgZHluYW1vQ2FwYWNpdHlBbGFybUZhY3Rvcnk6IER5bmFtb0FsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgdXNhZ2VBbGFybUZhY3Rvcnk6IFVzYWdlQWxhcm1GYWN0b3J5O1xuXG4gIHJlYWRvbmx5IGxhdGVuY3lBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgZXJyb3JDb3VudEFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSBkeW5hbW9SZWFkQ2FwYWNpdHlBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcbiAgcmVhZG9ubHkgZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSB0aHJvdHRsZWRFdmVudHNBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcblxuICByZWFkb25seSBwcm92aXNpb25lZFJlYWRVbml0c01ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgcHJvdmlzaW9uZWRXcml0ZVVuaXRzTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBjb25zdW1lZFJlYWRVbml0c01ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSByZWFkVGhyb3R0bGVDb3VudE1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgd3JpdGVUaHJvdHRsZUNvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBzeXN0ZW1FcnJvck1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgdGltZVRvTGl2ZURlbGV0ZWRJdGVtQ291bnRNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IGxhdGVuY3lBdmVyYWdlU2VhcmNoTWV0cmljczogSU1ldHJpYztcbiAgLy8ga2V5cyBhcmUgT3BlcmF0aW9uLCBidXQgSlNJSSBkb2Vzbid0IGxpa2Ugbm9uLXN0cmluZyB0eXBlc1xuICByZWFkb25seSBhdmVyYWdlUGVyT3BlcmF0aW9uTGF0ZW5jeU1ldHJpY3M6IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTWV0cmljV2l0aEFsYXJtU3VwcG9ydFxuICA+O1xuICByZWFkb25seSByZWFkQ2FwYWNpdHlVc2FnZU1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgd3JpdGVDYXBhY2l0eVVzYWdlTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBNb25pdG9yaW5nU2NvcGUsIHByb3BzOiBEeW5hbW9UYWJsZU1vbml0b3JpbmdQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBwcm9wcyk7XG5cbiAgICBjb25zdCBuYW1pbmdTdHJhdGVneSA9IG5ldyBNb25pdG9yaW5nTmFtaW5nU3RyYXRlZ3koe1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBuYW1lZENvbnN0cnVjdDogcHJvcHMudGFibGUsXG4gICAgICBmYWxsYmFja0NvbnN0cnVjdE5hbWU6IHRoaXMucmVzb2x2ZVRhYmxlTmFtZShwcm9wcy50YWJsZSksXG4gICAgfSk7XG5cbiAgICB0aGlzLnRpdGxlID0gbmFtaW5nU3RyYXRlZ3kucmVzb2x2ZUh1bWFuUmVhZGFibGVOYW1lKCk7XG4gICAgdGhpcy50YWJsZVVybCA9IHNjb3BlXG4gICAgICAuY3JlYXRlQXdzQ29uc29sZVVybEZhY3RvcnkoKVxuICAgICAgLmdldER5bmFtb1RhYmxlVXJsKHByb3BzLnRhYmxlLnRhYmxlTmFtZSk7XG5cbiAgICB0aGlzLnRhYmxlQmlsbGluZ01vZGUgPVxuICAgICAgcHJvcHMuYmlsbGluZ01vZGUgPz8gdGhpcy5yZXNvbHZlVGFibGVCaWxsaW5nTW9kZShwcm9wcy50YWJsZSk7XG5cbiAgICB0aGlzLmFsYXJtRmFjdG9yeSA9IHRoaXMuY3JlYXRlQWxhcm1GYWN0b3J5KFxuICAgICAgbmFtaW5nU3RyYXRlZ3kucmVzb2x2ZUFsYXJtRnJpZW5kbHlOYW1lKCksXG4gICAgKTtcbiAgICB0aGlzLmVycm9yQWxhcm1GYWN0b3J5ID0gbmV3IEVycm9yQWxhcm1GYWN0b3J5KHRoaXMuYWxhcm1GYWN0b3J5KTtcbiAgICB0aGlzLmxhdGVuY3lBbGFybUZhY3RvcnkgPSBuZXcgTGF0ZW5jeUFsYXJtRmFjdG9yeSh0aGlzLmFsYXJtRmFjdG9yeSk7XG4gICAgdGhpcy5keW5hbW9DYXBhY2l0eUFsYXJtRmFjdG9yeSA9IG5ldyBEeW5hbW9BbGFybUZhY3RvcnkodGhpcy5hbGFybUZhY3RvcnkpO1xuICAgIHRoaXMudXNhZ2VBbGFybUZhY3RvcnkgPSBuZXcgVXNhZ2VBbGFybUZhY3RvcnkodGhpcy5hbGFybUZhY3RvcnkpO1xuXG4gICAgdGhpcy5lcnJvckNvdW50QW5ub3RhdGlvbnMgPSBbXTtcbiAgICB0aGlzLmxhdGVuY3lBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMuZHluYW1vUmVhZENhcGFjaXR5QW5ub3RhdGlvbnMgPSBbXTtcbiAgICB0aGlzLmR5bmFtb1dyaXRlQ2FwYWNpdHlBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMgPSBbXTtcblxuICAgIGNvbnN0IG1ldHJpY0ZhY3RvcnkgPSBuZXcgRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5KFxuICAgICAgc2NvcGUuY3JlYXRlTWV0cmljRmFjdG9yeSgpLFxuICAgICAgcHJvcHMsXG4gICAgKTtcbiAgICB0aGlzLnByb3Zpc2lvbmVkUmVhZFVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljUHJvdmlzaW9uZWRSZWFkQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMucHJvdmlzaW9uZWRXcml0ZVVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljUHJvdmlzaW9uZWRXcml0ZUNhcGFjaXR5VW5pdHMoKTtcbiAgICB0aGlzLmNvbnN1bWVkUmVhZFVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQ29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMuY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQ29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHMoKTtcbiAgICB0aGlzLnJlYWRUaHJvdHRsZUNvdW50TWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljVGhyb3R0bGVkUmVhZFJlcXVlc3RDb3VudCgpO1xuICAgIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljVGhyb3R0bGVkV3JpdGVSZXF1ZXN0Q291bnQoKTtcbiAgICB0aGlzLnN5c3RlbUVycm9yTWV0cmljID0gbWV0cmljRmFjdG9yeS5tZXRyaWNTeXN0ZW1FcnJvcnNDb3VudCgpO1xuICAgIHRoaXMudGltZVRvTGl2ZURlbGV0ZWRJdGVtQ291bnRNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNUaW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudCgpO1xuICAgIHRoaXMubGF0ZW5jeUF2ZXJhZ2VTZWFyY2hNZXRyaWNzID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljU2VhcmNoQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKCk7XG4gICAgdGhpcy5hdmVyYWdlUGVyT3BlcmF0aW9uTGF0ZW5jeU1ldHJpY3MgPSB7XG4gICAgICBbT3BlcmF0aW9uLkdFVF9SRUNPUkRTXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLkdFVF9SRUNPUkRTLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5RVUVSWV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5RVUVSWSxcbiAgICAgICAgKSxcbiAgICAgIFtPcGVyYXRpb24uU0NBTl06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5TQ0FOLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5QVVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5QVVRfSVRFTSxcbiAgICAgICAgKSxcbiAgICAgIFtPcGVyYXRpb24uR0VUX0lURU1dOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uR0VUX0lURU0sXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLlVQREFURV9JVEVNXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLlVQREFURV9JVEVNLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5ERUxFVEVfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5ERUxFVEVfSVRFTSxcbiAgICAgICAgKSxcbiAgICAgIFtPcGVyYXRpb24uQkFUQ0hfR0VUX0lURU1dOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uQkFUQ0hfR0VUX0lURU0sXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLkJBVENIX1dSSVRFX0lURU1dOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uQkFUQ0hfV1JJVEVfSVRFTSxcbiAgICAgICAgKSxcbiAgICB9O1xuICAgIHRoaXMucmVhZENhcGFjaXR5VXNhZ2VNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNSZWFkQ2FwYWNpdHlVdGlsaXphdGlvblBlcmNlbnRhZ2UoKTtcbiAgICB0aGlzLndyaXRlQ2FwYWNpdHlVc2FnZU1ldHJpYyA9XG4gICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY1dyaXRlQ2FwYWNpdHlVdGlsaXphdGlvblBlcmNlbnRhZ2UoKTtcblxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRDb25zdW1lZFJlYWRDYXBhY2l0eUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkQ29uc3VtZWRSZWFkQ2FwYWNpdHlBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkQ29uc3VtZWRDYXBhY2l0eUFsYXJtKFxuICAgICAgICAgIHRoaXMuY29uc3VtZWRSZWFkVW5pdHNNZXRyaWMsXG4gICAgICAgICAgQ2FwYWNpdHlUeXBlLlJFQUQsXG4gICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICApO1xuICAgICAgdGhpcy5keW5hbW9SZWFkQ2FwYWNpdHlBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZENvbnN1bWVkV3JpdGVDYXBhY2l0eUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkQ29uc3VtZWRXcml0ZUNhcGFjaXR5QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICB0aGlzLmR5bmFtb0NhcGFjaXR5QWxhcm1GYWN0b3J5LmFkZENvbnN1bWVkQ2FwYWNpdHlBbGFybShcbiAgICAgICAgICB0aGlzLmNvbnN1bWVkV3JpdGVVbml0c01ldHJpYyxcbiAgICAgICAgICBDYXBhY2l0eVR5cGUuV1JJVEUsXG4gICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICApO1xuICAgICAgdGhpcy5keW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRSZWFkVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZFJlYWRUaHJvdHRsZWRFdmVudHNDb3VudEFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgdGhpcy5keW5hbW9DYXBhY2l0eUFsYXJtRmFjdG9yeS5hZGRUaHJvdHRsZWRFdmVudHNBbGFybShcbiAgICAgICAgICB0aGlzLnJlYWRUaHJvdHRsZUNvdW50TWV0cmljLFxuICAgICAgICAgIENhcGFjaXR5VHlwZS5SRUFELFxuICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgKTtcbiAgICAgIHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRXcml0ZVRocm90dGxlZEV2ZW50c0NvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRXcml0ZVRocm90dGxlZEV2ZW50c0NvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICB0aGlzLmR5bmFtb0NhcGFjaXR5QWxhcm1GYWN0b3J5LmFkZFRocm90dGxlZEV2ZW50c0FsYXJtKFxuICAgICAgICAgIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljLFxuICAgICAgICAgIENhcGFjaXR5VHlwZS5XUklURSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICk7XG4gICAgICB0aGlzLnRocm90dGxlZEV2ZW50c0Fubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkU3lzdGVtRXJyb3JDb3VudEFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkU3lzdGVtRXJyb3JDb3VudEFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy5lcnJvckFsYXJtRmFjdG9yeS5hZGRFcnJvckNvdW50QWxhcm0oXG4gICAgICAgIHRoaXMuc3lzdGVtRXJyb3JNZXRyaWMsXG4gICAgICAgIEVycm9yVHlwZS5TWVNURU1fRVJST1IsXG4gICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICApO1xuICAgICAgdGhpcy5lcnJvckNvdW50QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRNaW5UaW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudEFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0ge1xuICAgICAgICAvLyBNaXNzaW5nIGRhdGEgaXMgYmFkIGlmIHdlIGV4cGVjdCBUVEwgdG8gYmUgZW5hYmxlZFxuICAgICAgICB0cmVhdE1pc3NpbmdEYXRhT3ZlcnJpZGU6IFRyZWF0TWlzc2luZ0RhdGEuQlJFQUNISU5HLFxuICAgICAgICAuLi5wcm9wcy5hZGRNaW5UaW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudEFsYXJtW2Rpc2FtYmlndWF0b3JdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMudXNhZ2VBbGFybUZhY3RvcnkuYWRkTWluQ291bnRBbGFybShcbiAgICAgICAgdGhpcy50aW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudE1ldHJpYyxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uR0VUX1JFQ09SRFMsXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bEdldFJlY29yZHNMYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLlFVRVJZLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxRdWVyeUxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uU0NBTixcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsU2NhbkxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uUFVUX0lURU0sXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bFB1dEl0ZW1MYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkdFVF9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxHZXRJdGVtTGF0ZW5jeUFsYXJtLFxuICAgICk7XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5VUERBVEVfSVRFTSxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsVXBkYXRlSXRlbUxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uREVMRVRFX0lURU0sXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bERlbGV0ZUl0ZW1MYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkJBVENIX0dFVF9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaEdldEl0ZW1MYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkJBVENIX1dSSVRFX0lURU0sXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bEJhdGNoV3JpdGVJdGVtTGF0ZW5jeUFsYXJtLFxuICAgICk7XG4gICAgcHJvcHMudXNlQ3JlYXRlZEFsYXJtcz8uY29uc3VtZSh0aGlzLmNyZWF0ZWRBbGFybXMoKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgb3BlcmF0aW9uOiBPcGVyYXRpb24sXG4gICAgYWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBMYXRlbmN5VGhyZXNob2xkPixcbiAgKSB7XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIGFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gYWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLmxhdGVuY3lBbGFybUZhY3RvcnkuYWRkTGF0ZW5jeUFsYXJtKFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmF2ZXJhZ2VQZXJPcGVyYXRpb25MYXRlbmN5TWV0cmljc1tvcGVyYXRpb25dISxcbiAgICAgICAgTGF0ZW5jeVR5cGUuQVZFUkFHRSxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgb3BlcmF0aW9uLFxuICAgICAgKTtcbiAgICAgIHRoaXMubGF0ZW5jeUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgfVxuXG4gIHN1bW1hcnlXaWRnZXRzKCk6IElXaWRnZXRbXSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIFRpdGxlXG4gICAgICB0aGlzLmNyZWF0ZVRpdGxlV2lkZ2V0KCksXG4gICAgICAvLyBSZWFkIHVuaXRzXG4gICAgICB0aGlzLmNyZWF0ZVJlYWRDYXBhY2l0eVdpZGdldChIYWxmV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICAgIC8vIFdyaXRlIHVuaXRzXG4gICAgICB0aGlzLmNyZWF0ZVdyaXRlQ2FwYWNpdHlXaWRnZXQoSGFsZldpZHRoLCBEZWZhdWx0U3VtbWFyeVdpZGdldEhlaWdodCksXG4gICAgXTtcbiAgfVxuXG4gIHdpZGdldHMoKTogSVdpZGdldFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgLy8gVGl0bGVcbiAgICAgIHRoaXMuY3JlYXRlVGl0bGVXaWRnZXQoKSxcbiAgICAgIG5ldyBDb2x1bW4oXG4gICAgICAgIC8vIFJlYWQgdW5pdHNcbiAgICAgICAgdGhpcy5jcmVhdGVSZWFkQ2FwYWNpdHlXaWRnZXQoXG4gICAgICAgICAgUXVhcnRlcldpZHRoLFxuICAgICAgICAgIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGFsZkhlaWdodCxcbiAgICAgICAgKSxcbiAgICAgICAgLy8gV3JpdGUgdW5pdHNcbiAgICAgICAgdGhpcy5jcmVhdGVXcml0ZUNhcGFjaXR5V2lkZ2V0KFxuICAgICAgICAgIFF1YXJ0ZXJXaWR0aCxcbiAgICAgICAgICBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhhbGZIZWlnaHQsXG4gICAgICAgICksXG4gICAgICApLFxuICAgICAgLy8gTGF0ZW5jeVxuICAgICAgdGhpcy5jcmVhdGVMYXRlbmN5V2lkZ2V0KFxuICAgICAgICBRdWFydGVyV2lkdGggKyBIYWxmUXVhcnRlcldpZHRoLFxuICAgICAgICBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhlaWdodCxcbiAgICAgICksXG4gICAgICAvLyBUaHJvdHRsZXNcbiAgICAgIHRoaXMuY3JlYXRlVGhyb3R0bGVzV2lkZ2V0KFxuICAgICAgICBIYWxmUXVhcnRlcldpZHRoLFxuICAgICAgICBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhlaWdodCxcbiAgICAgICksXG4gICAgICAvLyBFcnJvcnNcbiAgICAgIHRoaXMuY3JlYXRlRXJyb3JzV2lkZ2V0KFF1YXJ0ZXJXaWR0aCwgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgIF07XG4gIH1cblxuICBjcmVhdGVMYXRlbmN5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIkxhdGVuY3kgKEF2ZXJhZ2UpXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5sYXRlbmN5QXZlcmFnZVNlYXJjaE1ldHJpY3NdLFxuICAgICAgbGVmdFlBeGlzOiBUaW1lQXhpc01pbGxpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmxhdGVuY3lBbm5vdGF0aW9ucyxcbiAgICAgIGxlZ2VuZFBvc2l0aW9uOiBMZWdlbmRQb3NpdGlvbi5SSUdIVCxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZVRocm90dGxlc1dpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJUaHJvdHRsZXNcIixcbiAgICAgIGxlZnQ6IFt0aGlzLnJlYWRUaHJvdHRsZUNvdW50TWV0cmljLCB0aGlzLndyaXRlVGhyb3R0bGVDb3VudE1ldHJpY10sXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLnRocm90dGxlZEV2ZW50c0Fubm90YXRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlRXJyb3JzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIkVycm9yc1wiLFxuICAgICAgbGVmdDogW3RoaXMuc3lzdGVtRXJyb3JNZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5lcnJvckNvdW50QW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVSZWFkQ2FwYWNpdHlXaWRnZXQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy50YWJsZUJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIC8vIHNpbXBsaWZpZWQgdmlldyBmb3Igb24tZGVtYW5kIHRhYmxlXG4gICAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodCxcbiAgICAgICAgdGl0bGU6IFwiUmVhZCBVc2FnZVwiLFxuICAgICAgICBsZWZ0OiBbdGhpcy5jb25zdW1lZFJlYWRVbml0c01ldHJpY10sXG4gICAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5keW5hbW9SZWFkQ2FwYWNpdHlBbm5vdGF0aW9ucyxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiUmVhZCBVc2FnZVwiLFxuICAgICAgbGVmdDogW3RoaXMuY29uc3VtZWRSZWFkVW5pdHNNZXRyaWMsIHRoaXMucHJvdmlzaW9uZWRSZWFkVW5pdHNNZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5keW5hbW9SZWFkQ2FwYWNpdHlBbm5vdGF0aW9ucyxcbiAgICAgIHJpZ2h0OiBbdGhpcy5yZWFkQ2FwYWNpdHlVc2FnZU1ldHJpY10sXG4gICAgICByaWdodFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVnZW5kUG9zaXRpb246IExlZ2VuZFBvc2l0aW9uLlJJR0hULFxuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlV3JpdGVDYXBhY2l0eVdpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIGlmICh0aGlzLnRhYmxlQmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgLy8gc2ltcGxpZmllZCB2aWV3IGZvciBvbi1kZW1hbmQgdGFibGVcbiAgICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0LFxuICAgICAgICB0aXRsZTogXCJXcml0ZSBVc2FnZVwiLFxuICAgICAgICBsZWZ0OiBbdGhpcy5jb25zdW1lZFdyaXRlVW5pdHNNZXRyaWNdLFxuICAgICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMuZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJXcml0ZSBVc2FnZVwiLFxuICAgICAgbGVmdDogW3RoaXMuY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljLCB0aGlzLnByb3Zpc2lvbmVkV3JpdGVVbml0c01ldHJpY10sXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmR5bmFtb1dyaXRlQ2FwYWNpdHlBbm5vdGF0aW9ucyxcbiAgICAgIHJpZ2h0OiBbdGhpcy53cml0ZUNhcGFjaXR5VXNhZ2VNZXRyaWNdLFxuICAgICAgcmlnaHRZQXhpczogUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgICAgIGxlZ2VuZFBvc2l0aW9uOiBMZWdlbmRQb3NpdGlvbi5SSUdIVCxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZVRpdGxlV2lkZ2V0KCkge1xuICAgIHJldHVybiBuZXcgTW9uaXRvcmluZ0hlYWRlcldpZGdldCh7XG4gICAgICBmYW1pbHk6IFwiRHluYW1vIFRhYmxlXCIsXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICAgIGdvVG9MaW5rVXJsOiB0aGlzLnRhYmxlVXJsLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlVGFibGVOYW1lKGR5bmFtb1RhYmxlOiBJVGFibGUpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIC8vIHRyeSB0byB0YWtlIHRoZSBuYW1lIChpZiBzcGVjaWZpZWQpIGluc3RlYWQgb2YgdG9rZW5cbiAgICByZXR1cm4gKGR5bmFtb1RhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblRhYmxlKT8udGFibGVOYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlVGFibGVCaWxsaW5nTW9kZShkeW5hbW9UYWJsZTogSVRhYmxlKTogQmlsbGluZ01vZGUge1xuICAgIGNvbnN0IGJpbGxpbmdNb2RlID0gKGR5bmFtb1RhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblRhYmxlKVxuICAgICAgPy5iaWxsaW5nTW9kZTtcbiAgICBpZiAoYmlsbGluZ01vZGUpIHtcbiAgICAgIHJldHVybiBiaWxsaW5nTW9kZSBhcyBCaWxsaW5nTW9kZTtcbiAgICB9XG4gICAgLy8gZmFsbGJhY2sgdG8gZGVmYXVsdCAoZm9yIGJ