cdk-monitoring-constructs
Version:
[](https://gitpod.io/#https://github.com/cdklabs/cdk-monitoring-constructs) [](https://badge
246 lines • 47.8 kB
JavaScript
"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 common_1 = require("../../common");
const dashboard_1 = require("../../dashboard");
const DynamoTableMetricFactory_1 = require("./DynamoTableMetricFactory");
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.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.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);
}
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, operation + "-" + disambiguator);
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: "1.21.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRHluYW1vVGFibGVNb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiRHluYW1vVGFibGVNb25pdG9yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0RBT29DO0FBQ3BDLDJEQUtrQztBQUVsQyx5Q0F5QnNCO0FBQ3RCLCtDQUd5QjtBQUN6Qix5RUFHb0M7QUFpRXBDLE1BQWEscUJBQXNCLFNBQVEsbUJBQVU7SUFnQ25ELFlBQVksS0FBc0IsRUFBRSxLQUFpQztRQUNuRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXBCLE1BQU0sY0FBYyxHQUFHLElBQUksb0NBQXdCLENBQUM7WUFDbEQsR0FBRyxLQUFLO1lBQ1IsY0FBYyxFQUFFLEtBQUssQ0FBQyxLQUFLO1lBQzNCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1NBQzFELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDdkQsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLO2FBQ2xCLDBCQUEwQixFQUFFO2FBQzVCLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDLGdCQUFnQjtZQUNuQixLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQ3pDLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksMEJBQWlCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLDRCQUFtQixDQUFD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O1lBQ2hDLE1BQU0sRUFBRSxjQUFjO1lBQ3RCLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixXQUFXLEVBQUUsSUFBSSxDQUFDLFFBQVE7U0FDM0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQixDQUFDLFdBQW1CO1FBQzFDLHVEQUF1RDtRQUN2RCxPQUFRLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBeUIsRUFBRSxTQUFTLENBQUM7SUFDaEUsQ0FBQztJQUVPLHVCQUF1QixDQUFDLFdBQW1CO1FBQ2pELE1BQU0sV0FBVyxHQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBeUI7WUFDN0QsRUFBRSxXQUFXLENBQUM7UUFDaEIsSUFBSSxXQUFXLEVBQUU7WUFDZixPQUFPLFdBQTBCLENBQUM7U0FDbkM7UUFDRCxvREFBb0Q7UUFDcEQsT0FBTywwQkFBVyxDQUFDLFdBQVcsQ0FBQztJQUNqQyxDQUFDOztBQWxZSCxzREFtWUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb2x1bW4sXG4gIEdyYXBoV2lkZ2V0LFxuICBIb3Jpem9udGFsQW5ub3RhdGlvbixcbiAgSU1ldHJpYyxcbiAgSVdpZGdldCxcbiAgTGVnZW5kUG9zaXRpb24sXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaFwiO1xuaW1wb3J0IHtcbiAgQmlsbGluZ01vZGUsXG4gIENmblRhYmxlLFxuICBJVGFibGUsXG4gIE9wZXJhdGlvbixcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1keW5hbW9kYlwiO1xuXG5pbXBvcnQge1xuICBBbGFybUZhY3RvcnksXG4gIEJhc2VNb25pdG9yaW5nUHJvcHMsXG4gIENhcGFjaXR5VHlwZSxcbiAgQ29uc3VtZWRDYXBhY2l0eVRocmVzaG9sZCxcbiAgQ291bnRBeGlzRnJvbVplcm8sXG4gIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0LFxuICBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhhbGZIZWlnaHQsXG4gIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGVpZ2h0LFxuICBEeW5hbW9BbGFybUZhY3RvcnksXG4gIEVycm9yQWxhcm1GYWN0b3J5LFxuICBFcnJvckNvdW50VGhyZXNob2xkLFxuICBFcnJvclR5cGUsXG4gIEhhbGZRdWFydGVyV2lkdGgsXG4gIEhhbGZXaWR0aCxcbiAgTGF0ZW5jeUFsYXJtRmFjdG9yeSxcbiAgTGF0ZW5jeVRocmVzaG9sZCxcbiAgTGF0ZW5jeVR5cGUsXG4gIE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gIE1vbml0b3JpbmcsXG4gIE1vbml0b3JpbmdTY29wZSxcbiAgUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgUXVhcnRlcldpZHRoLFxuICBUaHJvdHRsZWRFdmVudHNUaHJlc2hvbGQsXG4gIFRpbWVBeGlzTWlsbGlzRnJvbVplcm8sXG59IGZyb20gXCIuLi8uLi9jb21tb25cIjtcbmltcG9ydCB7XG4gIE1vbml0b3JpbmdIZWFkZXJXaWRnZXQsXG4gIE1vbml0b3JpbmdOYW1pbmdTdHJhdGVneSxcbn0gZnJvbSBcIi4uLy4uL2Rhc2hib2FyZFwiO1xuaW1wb3J0IHtcbiAgRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5LFxuICBEeW5hbW9UYWJsZU1ldHJpY0ZhY3RvcnlQcm9wcyxcbn0gZnJvbSBcIi4vRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHluYW1vVGFibGVNb25pdG9yaW5nT3B0aW9ucyBleHRlbmRzIEJhc2VNb25pdG9yaW5nUHJvcHMge1xuICByZWFkb25seSBhZGRDb25zdW1lZFJlYWRDYXBhY2l0eUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBDb25zdW1lZENhcGFjaXR5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZENvbnN1bWVkV3JpdGVDYXBhY2l0eUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBDb25zdW1lZENhcGFjaXR5VGhyZXNob2xkXG4gID47XG5cbiAgcmVhZG9ubHkgYWRkUmVhZFRocm90dGxlZEV2ZW50c0NvdW50QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFRocm90dGxlZEV2ZW50c1RocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRXcml0ZVRocm90dGxlZEV2ZW50c0NvdW50QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFRocm90dGxlZEV2ZW50c1RocmVzaG9sZFxuICA+O1xuXG4gIHJlYWRvbmx5IGFkZFN5c3RlbUVycm9yQ291bnRBbGFybT86IFJlY29yZDxzdHJpbmcsIEVycm9yQ291bnRUaHJlc2hvbGQ+O1xuXG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsR2V0UmVjb3Jkc0xhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFF1ZXJ5TGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsU2NhbkxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFB1dEl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxHZXRJdGVtTGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsVXBkYXRlSXRlbUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bERlbGV0ZUl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaEdldEl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaFdyaXRlSXRlbUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER5bmFtb1RhYmxlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5UHJvcHMsXG4gICAgRHluYW1vVGFibGVNb25pdG9yaW5nT3B0aW9ucyB7fVxuXG5leHBvcnQgY2xhc3MgRHluYW1vVGFibGVNb25pdG9yaW5nIGV4dGVuZHMgTW9uaXRvcmluZyB7XG4gIHByb3RlY3RlZCByZWFkb25seSB0aXRsZTogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdGFibGVVcmw/OiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSB0YWJsZUJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWxhcm1GYWN0b3J5OiBBbGFybUZhY3Rvcnk7XG4gIHByb3RlY3RlZCByZWFkb25seSBlcnJvckFsYXJtRmFjdG9yeTogRXJyb3JBbGFybUZhY3Rvcnk7XG4gIHByb3RlY3RlZCByZWFkb25seSBsYXRlbmN5QWxhcm1GYWN0b3J5OiBMYXRlbmN5QWxhcm1GYWN0b3J5O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZHluYW1vQ2FwYWNpdHlBbGFybUZhY3Rvcnk6IER5bmFtb0FsYXJtRmFjdG9yeTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbGF0ZW5jeUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXJyb3JDb3VudEFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZHluYW1vUmVhZENhcGFjaXR5QW5ub3RhdGlvbnM6IEhvcml6b250YWxBbm5vdGF0aW9uW107XG4gIHByb3RlY3RlZCByZWFkb25seSBkeW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnM6IEhvcml6b250YWxBbm5vdGF0aW9uW107XG4gIHByb3RlY3RlZCByZWFkb25seSB0aHJvdHRsZWRFdmVudHNBbm5vdGF0aW9uczogSG9yaXpvbnRhbEFubm90YXRpb25bXTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcHJvdmlzaW9uZWRSZWFkVW5pdHNNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHByb3RlY3RlZCByZWFkb25seSBwcm92aXNpb25lZFdyaXRlVW5pdHNNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHByb3RlY3RlZCByZWFkb25seSBjb25zdW1lZFJlYWRVbml0c01ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbnN1bWVkV3JpdGVVbml0c01ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlYWRUaHJvdHRsZUNvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgd3JpdGVUaHJvdHRsZUNvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3lzdGVtRXJyb3JNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHByb3RlY3RlZCByZWFkb25seSBsYXRlbmN5QXZlcmFnZVNlYXJjaE1ldHJpY3M6IElNZXRyaWM7XG4gIC8vIGtleXMgYXJlIE9wZXJhdGlvbiwgYnV0IEpTSUkgZG9lc24ndCBsaWtlIG5vbi1zdHJpbmcgdHlwZXNcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGF2ZXJhZ2VQZXJPcGVyYXRpb25MYXRlbmN5TWV0cmljczogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0XG4gID47XG4gIHByb3RlY3RlZCByZWFkb25seSByZWFkQ2FwYWNpdHlVc2FnZU1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHdyaXRlQ2FwYWNpdHlVc2FnZU1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogTW9uaXRvcmluZ1Njb3BlLCBwcm9wczogRHluYW1vVGFibGVNb25pdG9yaW5nUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgcHJvcHMpO1xuXG4gICAgY29uc3QgbmFtaW5nU3RyYXRlZ3kgPSBuZXcgTW9uaXRvcmluZ05hbWluZ1N0cmF0ZWd5KHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgbmFtZWRDb25zdHJ1Y3Q6IHByb3BzLnRhYmxlLFxuICAgICAgZmFsbGJhY2tDb25zdHJ1Y3ROYW1lOiB0aGlzLnJlc29sdmVUYWJsZU5hbWUocHJvcHMudGFibGUpLFxuICAgIH0pO1xuXG4gICAgdGhpcy50aXRsZSA9IG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVIdW1hblJlYWRhYmxlTmFtZSgpO1xuICAgIHRoaXMudGFibGVVcmwgPSBzY29wZVxuICAgICAgLmNyZWF0ZUF3c0NvbnNvbGVVcmxGYWN0b3J5KClcbiAgICAgIC5nZXREeW5hbW9UYWJsZVVybChwcm9wcy50YWJsZS50YWJsZU5hbWUpO1xuXG4gICAgdGhpcy50YWJsZUJpbGxpbmdNb2RlID1cbiAgICAgIHByb3BzLmJpbGxpbmdNb2RlID8/IHRoaXMucmVzb2x2ZVRhYmxlQmlsbGluZ01vZGUocHJvcHMudGFibGUpO1xuXG4gICAgdGhpcy5hbGFybUZhY3RvcnkgPSB0aGlzLmNyZWF0ZUFsYXJtRmFjdG9yeShcbiAgICAgIG5hbWluZ1N0cmF0ZWd5LnJlc29sdmVBbGFybUZyaWVuZGx5TmFtZSgpXG4gICAgKTtcbiAgICB0aGlzLmVycm9yQWxhcm1GYWN0b3J5ID0gbmV3IEVycm9yQWxhcm1GYWN0b3J5KHRoaXMuYWxhcm1GYWN0b3J5KTtcbiAgICB0aGlzLmxhdGVuY3lBbGFybUZhY3RvcnkgPSBuZXcgTGF0ZW5jeUFsYXJtRmFjdG9yeSh0aGlzLmFsYXJtRmFjdG9yeSk7XG4gICAgdGhpcy5keW5hbW9DYXBhY2l0eUFsYXJtRmFjdG9yeSA9IG5ldyBEeW5hbW9BbGFybUZhY3RvcnkodGhpcy5hbGFybUZhY3RvcnkpO1xuICAgIHRoaXMuZXJyb3JDb3VudEFubm90YXRpb25zID0gW107XG4gICAgdGhpcy5sYXRlbmN5QW5ub3RhdGlvbnMgPSBbXTtcbiAgICB0aGlzLmR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zID0gW107XG4gICAgdGhpcy5keW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnMgPSBbXTtcbiAgICB0aGlzLnRocm90dGxlZEV2ZW50c0Fubm90YXRpb25zID0gW107XG5cbiAgICBjb25zdCBtZXRyaWNGYWN0b3J5ID0gbmV3IER5bmFtb1RhYmxlTWV0cmljRmFjdG9yeShcbiAgICAgIHNjb3BlLmNyZWF0ZU1ldHJpY0ZhY3RvcnkoKSxcbiAgICAgIHByb3BzXG4gICAgKTtcbiAgICB0aGlzLnByb3Zpc2lvbmVkUmVhZFVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljUHJvdmlzaW9uZWRSZWFkQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMucHJvdmlzaW9uZWRXcml0ZVVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljUHJvdmlzaW9uZWRXcml0ZUNhcGFjaXR5VW5pdHMoKTtcbiAgICB0aGlzLmNvbnN1bWVkUmVhZFVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQ29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMuY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQ29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHMoKTtcbiAgICB0aGlzLnJlYWRUaHJvdHRsZUNvdW50TWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljVGhyb3R0bGVkUmVhZFJlcXVlc3RDb3VudCgpO1xuICAgIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljVGhyb3R0bGVkV3JpdGVSZXF1ZXN0Q291bnQoKTtcbiAgICB0aGlzLnN5c3RlbUVycm9yTWV0cmljID0gbWV0cmljRmFjdG9yeS5tZXRyaWNTeXN0ZW1FcnJvcnNDb3VudCgpO1xuICAgIHRoaXMubGF0ZW5jeUF2ZXJhZ2VTZWFyY2hNZXRyaWNzID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljU2VhcmNoQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKCk7XG4gICAgdGhpcy5hdmVyYWdlUGVyT3BlcmF0aW9uTGF0ZW5jeU1ldHJpY3MgPSB7XG4gICAgICBbT3BlcmF0aW9uLkdFVF9SRUNPUkRTXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLkdFVF9SRUNPUkRTXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLlFVRVJZXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLlFVRVJZXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLlNDQU5dOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uU0NBTlxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5QVVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5QVVRfSVRFTVxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5HRVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5HRVRfSVRFTVxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5VUERBVEVfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5VUERBVEVfSVRFTVxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5ERUxFVEVfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5ERUxFVEVfSVRFTVxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5CQVRDSF9HRVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5CQVRDSF9HRVRfSVRFTVxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5CQVRDSF9XUklURV9JVEVNXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLkJBVENIX1dSSVRFX0lURU1cbiAgICAgICAgKSxcbiAgICB9O1xuICAgIHRoaXMucmVhZENhcGFjaXR5VXNhZ2VNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNSZWFkQ2FwYWNpdHlVdGlsaXphdGlvblBlcmNlbnRhZ2UoKTtcbiAgICB0aGlzLndyaXRlQ2FwYWNpdHlVc2FnZU1ldHJpYyA9XG4gICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY1dyaXRlQ2FwYWNpdHlVdGlsaXphdGlvblBlcmNlbnRhZ2UoKTtcblxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRDb25zdW1lZFJlYWRDYXBhY2l0eUFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkQ29uc3VtZWRSZWFkQ2FwYWNpdHlBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkQ29uc3VtZWRDYXBhY2l0eUFsYXJtKFxuICAgICAgICAgIHRoaXMuY29uc3VtZWRSZWFkVW5pdHNNZXRyaWMsXG4gICAgICAgICAgQ2FwYWNpdHlUeXBlLlJFQUQsXG4gICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICBkaXNhbWJpZ3VhdG9yXG4gICAgICAgICk7XG4gICAgICB0aGlzLmR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkQ29uc3VtZWRXcml0ZUNhcGFjaXR5QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRDb25zdW1lZFdyaXRlQ2FwYWNpdHlBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkQ29uc3VtZWRDYXBhY2l0eUFsYXJtKFxuICAgICAgICAgIHRoaXMuY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljLFxuICAgICAgICAgIENhcGFjaXR5VHlwZS5XUklURSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3JcbiAgICAgICAgKTtcbiAgICAgIHRoaXMuZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkUmVhZFRocm90dGxlZEV2ZW50c0NvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRSZWFkVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkVGhyb3R0bGVkRXZlbnRzQWxhcm0oXG4gICAgICAgICAgdGhpcy5yZWFkVGhyb3R0bGVDb3VudE1ldHJpYyxcbiAgICAgICAgICBDYXBhY2l0eVR5cGUuUkVBRCxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3JcbiAgICAgICAgKTtcbiAgICAgIHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRXcml0ZVRocm90dGxlZEV2ZW50c0NvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRXcml0ZVRocm90dGxlZEV2ZW50c0NvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICB0aGlzLmR5bmFtb0NhcGFjaXR5QWxhcm1GYWN0b3J5LmFkZFRocm90dGxlZEV2ZW50c0FsYXJtKFxuICAgICAgICAgIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljLFxuICAgICAgICAgIENhcGFjaXR5VHlwZS5XUklURSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3JcbiAgICAgICAgKTtcbiAgICAgIHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRTeXN0ZW1FcnJvckNvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRTeXN0ZW1FcnJvckNvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLmVycm9yQWxhcm1GYWN0b3J5LmFkZEVycm9yQ291bnRBbGFybShcbiAgICAgICAgdGhpcy5zeXN0ZW1FcnJvck1ldHJpYyxcbiAgICAgICAgRXJyb3JUeXBlLlNZU1RFTV9FUlJPUixcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvclxuICAgICAgKTtcbiAgICAgIHRoaXMuZXJyb3JDb3VudEFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkdFVF9SRUNPUkRTLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxHZXRSZWNvcmRzTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLlFVRVJZLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxRdWVyeUxhdGVuY3lBbGFybVxuICAgICk7XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5TQ0FOLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxTY2FuTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLlBVVF9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxQdXRJdGVtTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkdFVF9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxHZXRJdGVtTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLlVQREFURV9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxVcGRhdGVJdGVtTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkRFTEVURV9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxEZWxldGVJdGVtTGF0ZW5jeUFsYXJtXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLkJBVENIX0dFVF9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaEdldEl0ZW1MYXRlbmN5QWxhcm1cbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uQkFUQ0hfV1JJVEVfSVRFTSxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsQmF0Y2hXcml0ZUl0ZW1MYXRlbmN5QWxhcm1cbiAgICApO1xuICAgIHByb3BzLnVzZUNyZWF0ZWRBbGFybXM/LmNvbnN1bWUodGhpcy5jcmVhdGVkQWxhcm1zKCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uLFxuICAgIGFsYXJtPzogUmVjb3JkPHN0cmluZywgTGF0ZW5jeVRocmVzaG9sZD5cbiAgKSB7XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIGFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gYWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLmxhdGVuY3lBbGFybUZhY3RvcnkuYWRkTGF0ZW5jeUFsYXJtKFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmF2ZXJhZ2VQZXJPcGVyYXRpb25MYXRlbmN5TWV0cmljc1tvcGVyYXRpb25dISxcbiAgICAgICAgTGF0ZW5jeVR5cGUuQVZFUkFHRSxcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgb3BlcmF0aW9uICsgXCItXCIgKyBkaXNhbWJpZ3VhdG9yXG4gICAgICApO1xuICAgICAgdGhpcy5sYXRlbmN5QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICB9XG5cbiAgc3VtbWFyeVdpZGdldHMoKTogSVdpZGdldFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgLy8gVGl0bGVcbiAgICAgIHRoaXMuY3JlYXRlVGl0bGVXaWRnZXQoKSxcbiAgICAgIC8vIFJlYWQgdW5pdHNcbiAgICAgIHRoaXMuY3JlYXRlUmVhZENhcGFjaXR5V2lkZ2V0KEhhbGZXaWR0aCwgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQpLFxuICAgICAgLy8gV3JpdGUgdW5pdHNcbiAgICAgIHRoaXMuY3JlYXRlV3JpdGVDYXBhY2l0eVdpZGdldChIYWxmV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICBdO1xuICB9XG5cbiAgd2lkZ2V0cygpOiBJV2lkZ2V0W10ge1xuICAgIHJldHVybiBbXG4gICAgICAvLyBUaXRsZVxuICAgICAgdGhpcy5jcmVhdGVUaXRsZVdpZGdldCgpLFxuICAgICAgbmV3IENvbHVtbihcbiAgICAgICAgLy8gUmVhZCB1bml0c1xuICAgICAgICB0aGlzLmNyZWF0ZVJlYWRDYXBhY2l0eVdpZGdldChcbiAgICAgICAgICBRdWFydGVyV2lkdGgsXG4gICAgICAgICAgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIYWxmSGVpZ2h0XG4gICAgICAgICksXG4gICAgICAgIC8vIFdyaXRlIHVuaXRzXG4gICAgICAgIHRoaXMuY3JlYXRlV3JpdGVDYXBhY2l0eVdpZGdldChcbiAgICAgICAgICBRdWFydGVyV2lkdGgsXG4gICAgICAgICAgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIYWxmSGVpZ2h0XG4gICAgICAgIClcbiAgICAgICksXG4gICAgICAvLyBMYXRlbmN5XG4gICAgICB0aGlzLmNyZWF0ZUxhdGVuY3lXaWRnZXQoXG4gICAgICAgIFF1YXJ0ZXJXaWR0aCArIEhhbGZRdWFydGVyV2lkdGgsXG4gICAgICAgIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGVpZ2h0XG4gICAgICApLFxuICAgICAgLy8gVGhyb3R0bGVzXG4gICAgICB0aGlzLmNyZWF0ZVRocm90dGxlc1dpZGdldChcbiAgICAgICAgSGFsZlF1YXJ0ZXJXaWR0aCxcbiAgICAgICAgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIZWlnaHRcbiAgICAgICksXG4gICAgICAvLyBFcnJvcnNcbiAgICAgIHRoaXMuY3JlYXRlRXJyb3JzV2lkZ2V0KFF1YXJ0ZXJXaWR0aCwgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIZWlnaHQpLFxuICAgIF07XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlTGF0ZW5jeVdpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJMYXRlbmN5IChBdmVyYWdlKVwiLFxuICAgICAgbGVmdDogW3RoaXMubGF0ZW5jeUF2ZXJhZ2VTZWFyY2hNZXRyaWNzXSxcbiAgICAgIGxlZnRZQXhpczogVGltZUF4aXNNaWxsaXNGcm9tWmVybyxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5sYXRlbmN5QW5ub3RhdGlvbnMsXG4gICAgICBsZWdlbmRQb3NpdGlvbjogTGVnZW5kUG9zaXRpb24uUklHSFQsXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlVGhyb3R0bGVzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIlRocm90dGxlc1wiLFxuICAgICAgbGVmdDogW3RoaXMucmVhZFRocm90dGxlQ291bnRNZXRyaWMsIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlRXJyb3JzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIkVycm9yc1wiLFxuICAgICAgbGVmdDogW3RoaXMuc3lzdGVtRXJyb3JNZXRyaWNdLFxuICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5lcnJvckNvdW50QW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlUmVhZENhcGFjaXR5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMudGFibGVCaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNUKSB7XG4gICAgICAvLyBzaW1wbGlmaWVkIHZpZXcgZm9yIG9uLWRlbWFuZCB0YWJsZVxuICAgICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgIHdpZHRoLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIHRpdGxlOiBcIlJlYWQgVXNhZ2VcIixcbiAgICAgICAgbGVmdDogW3RoaXMuY29uc3VtZWRSZWFkVW5pdHNNZXRyaWNdLFxuICAgICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMuZHluYW1vUmVhZENhcGFjaXR5QW5ub3RhdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIlJlYWQgVXNhZ2VcIixcbiAgICAgIGxlZnQ6IFt0aGlzLmNvbnN1bWVkUmVhZFVuaXRzTWV0cmljLCB0aGlzLnByb3Zpc2lvbmVkUmVhZFVuaXRzTWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMuZHluYW1vUmVhZENhcGFjaXR5QW5ub3RhdGlvbnMsXG4gICAgICByaWdodDogW3RoaXMucmVhZENhcGFjaXR5VXNhZ2VNZXRyaWNdLFxuICAgICAgcmlnaHRZQXhpczogUGVyY2VudGFnZUF4aXNGcm9tWmVyb1RvSHVuZHJlZCxcbiAgICAgIGxlZ2VuZFBvc2l0aW9uOiBMZWdlbmRQb3NpdGlvbi5SSUdIVCxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjcmVhdGVXcml0ZUNhcGFjaXR5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMudGFibGVCaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNUKSB7XG4gICAgICAvLyBzaW1wbGlmaWVkIHZpZXcgZm9yIG9uLWRlbWFuZCB0YWJsZVxuICAgICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgIHdpZHRoLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIHRpdGxlOiBcIldyaXRlIFVzYWdlXCIsXG4gICAgICAgIGxlZnQ6IFt0aGlzLmNvbnN1bWVkV3JpdGVVbml0c01ldHJpY10sXG4gICAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5keW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIldyaXRlIFVzYWdlXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5jb25zdW1lZFdyaXRlVW5pdHNNZXRyaWMsIHRoaXMucHJvdmlzaW9uZWRXcml0ZVVuaXRzTWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMuZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zLFxuICAgICAgcmlnaHQ6IFt0aGlzLndyaXRlQ2FwYWNpdHlVc2FnZU1ldHJpY10sXG4gICAgICByaWdodFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVnZW5kUG9zaXRpb246IExlZ2VuZFBvc2l0aW9uLlJJR0hULFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVRpdGxlV2lkZ2V0KCkge1xuICAgIHJldHVybiBuZXcgTW9uaXRvcmluZ0hlYWRlcldpZGdldCh7XG4gICAgICBmYW1pbHk6IFwiRHluYW1vIFRhYmxlXCIsXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICAgIGdvVG9MaW5rVXJsOiB0aGlzLnRhYmxlVXJsLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlVGFibGVOYW1lKGR5bmFtb1RhYmxlOiBJVGFibGUpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIC8vIHRyeSB0byB0YWtlIHRoZSBuYW1lIChpZiBzcGVjaWZpZWQpIGluc3RlYWQgb2YgdG9rZW5cbiAgICByZXR1cm4gKGR5bmFtb1RhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblRhYmxlKT8udGFibGVOYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlVGFibGVCaWxsaW5nTW9kZShkeW5hbW9UYWJsZTogSVRhYmxlKTogQmlsbGluZ01vZGUge1xuICAgIGNvbnN0IGJpbGxpbmdNb2RlID0gKGR5bmFtb1RhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblRhYmxlKVxuICAgICAgPy5iaWxsaW5nTW9kZTtcbiAgICBpZiAoYmlsbGluZ01vZGUpIHtcbiAgICAgIHJldHVybiBiaWxsaW5nTW9kZSBhcyBCaWxsaW5nTW9kZTtcbiAgICB9XG4gICAgLy8gZmFsbGJhY2sgdG8gZGVmYXVsdCAoZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5KVxuICAgIHJldHVybiBCaWxsaW5nTW9kZS5QUk9WSVNJT05FRDtcbiAgfVxufVxuIl19