1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.TableClass = exports.StreamViewType = exports.ProjectionType = exports.BillingMode = exports.AttributeType = exports.Table = exports.TableEncryption = exports.Operation = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const appscaling = require("@aws-cdk/aws-applicationautoscaling");
|
8 | const cloudwatch = require("@aws-cdk/aws-cloudwatch");
|
9 | const iam = require("@aws-cdk/aws-iam");
|
10 | const kms = require("@aws-cdk/aws-kms");
|
11 | const core_1 = require("@aws-cdk/core");
|
12 | const dynamodb_canned_metrics_generated_1 = require("./dynamodb-canned-metrics.generated");
|
13 | const dynamodb_generated_1 = require("./dynamodb.generated");
|
14 | const perms = require("./perms");
|
15 | const replica_provider_1 = require("./replica-provider");
|
16 | const scalable_table_attribute_1 = require("./scalable-table-attribute");
|
17 | // keep this import separate from other imports to reduce chance for merge conflicts with v2-main
|
18 | // eslint-disable-next-line no-duplicate-imports, import/order
|
19 | const core_2 = require("@aws-cdk/core");
|
20 | const HASH_KEY_TYPE = 'HASH';
|
21 | const RANGE_KEY_TYPE = 'RANGE';
|
22 | // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
|
23 | const MAX_LOCAL_SECONDARY_INDEX_COUNT = 5;
|
24 | /**
|
25 | * Supported DynamoDB table operations.
|
26 | */
|
27 | var Operation;
|
28 | (function (Operation) {
|
29 | /** GetItem */
|
30 | Operation["GET_ITEM"] = "GetItem";
|
31 | /** BatchGetItem */
|
32 | Operation["BATCH_GET_ITEM"] = "BatchGetItem";
|
33 | /** Scan */
|
34 | Operation["SCAN"] = "Scan";
|
35 | /** Query */
|
36 | Operation["QUERY"] = "Query";
|
37 | /** GetRecords */
|
38 | Operation["GET_RECORDS"] = "GetRecords";
|
39 | /** PutItem */
|
40 | Operation["PUT_ITEM"] = "PutItem";
|
41 | /** DeleteItem */
|
42 | Operation["DELETE_ITEM"] = "DeleteItem";
|
43 | /** UpdateItem */
|
44 | Operation["UPDATE_ITEM"] = "UpdateItem";
|
45 | /** BatchWriteItem */
|
46 | Operation["BATCH_WRITE_ITEM"] = "BatchWriteItem";
|
47 | /** TransactWriteItems */
|
48 | Operation["TRANSACT_WRITE_ITEMS"] = "TransactWriteItems";
|
49 | /** TransactGetItems */
|
50 | Operation["TRANSACT_GET_ITEMS"] = "TransactGetItems";
|
51 | /** ExecuteTransaction */
|
52 | Operation["EXECUTE_TRANSACTION"] = "ExecuteTransaction";
|
53 | /** BatchExecuteStatement */
|
54 | Operation["BATCH_EXECUTE_STATEMENT"] = "BatchExecuteStatement";
|
55 | /** ExecuteStatement */
|
56 | Operation["EXECUTE_STATEMENT"] = "ExecuteStatement";
|
57 | })(Operation = exports.Operation || (exports.Operation = {}));
|
58 | /**
|
59 | * What kind of server-side encryption to apply to this table.
|
60 | */
|
61 | var TableEncryption;
|
62 | (function (TableEncryption) {
|
63 | /**
|
64 | * Server-side KMS encryption with a master key owned by AWS.
|
65 | */
|
66 | TableEncryption["DEFAULT"] = "AWS_OWNED";
|
67 | /**
|
68 | * Server-side KMS encryption with a customer master key managed by customer.
|
69 | * If `encryptionKey` is specified, this key will be used, otherwise, one will be defined.
|
70 | *
|
71 | * > **NOTE**: if `encryptionKey` is not specified and the `Table` construct creates
|
72 | * > a KMS key for you, the key will be created with default permissions. If you are using
|
73 | * > CDKv2, these permissions will be sufficient to enable the key for use with DynamoDB tables.
|
74 | * > If you are using CDKv1, make sure the feature flag `@aws-cdk/aws-kms:defaultKeyPolicies`
|
75 | * > is set to `true` in your `cdk.json`.
|
76 | */
|
77 | TableEncryption["CUSTOMER_MANAGED"] = "CUSTOMER_MANAGED";
|
78 | /**
|
79 | * Server-side KMS encryption with a master key managed by AWS.
|
80 | */
|
81 | TableEncryption["AWS_MANAGED"] = "AWS_MANAGED";
|
82 | })(TableEncryption = exports.TableEncryption || (exports.TableEncryption = {}));
|
83 | class TableBase extends core_1.Resource {
|
84 | constructor() {
|
85 | super(...arguments);
|
86 | this.regionalArns = new Array();
|
87 | }
|
88 | /**
|
89 | * Adds an IAM policy statement associated with this table to an IAM
|
90 | * principal's policy.
|
91 | *
|
92 | * If `encryptionKey` is present, appropriate grants to the key needs to be added
|
93 | * separately using the `table.encryptionKey.grant*` methods.
|
94 | *
|
95 | * @param grantee The principal (no-op if undefined)
|
96 | * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...)
|
97 | */
|
98 | grant(grantee, ...actions) {
|
99 | return iam.Grant.addToPrincipal({
|
100 | grantee,
|
101 | actions,
|
102 | resourceArns: [
|
103 | this.tableArn,
|
104 | core_1.Lazy.string({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : core_1.Aws.NO_VALUE }),
|
105 | ...this.regionalArns,
|
106 | ...this.regionalArns.map(arn => core_1.Lazy.string({
|
107 | produce: () => this.hasIndex ? `${arn}/index/*` : core_1.Aws.NO_VALUE,
|
108 | })),
|
109 | ],
|
110 | scope: this,
|
111 | });
|
112 | }
|
113 | /**
|
114 | * Adds an IAM policy statement associated with this table's stream to an
|
115 | * IAM principal's policy.
|
116 | *
|
117 | * If `encryptionKey` is present, appropriate grants to the key needs to be added
|
118 | * separately using the `table.encryptionKey.grant*` methods.
|
119 | *
|
120 | * @param grantee The principal (no-op if undefined)
|
121 | * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...)
|
122 | */
|
123 | grantStream(grantee, ...actions) {
|
124 | if (!this.tableStreamArn) {
|
125 | throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
|
126 | }
|
127 | return iam.Grant.addToPrincipal({
|
128 | grantee,
|
129 | actions,
|
130 | resourceArns: [this.tableStreamArn],
|
131 | scope: this,
|
132 | });
|
133 | }
|
134 | /**
|
135 | * Permits an IAM principal all data read operations from this table:
|
136 | * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan, DescribeTable.
|
137 | *
|
138 | * Appropriate grants will also be added to the customer-managed KMS key
|
139 | * if one was configured.
|
140 | *
|
141 | * @param grantee The principal to grant access to
|
142 | */
|
143 | grantReadData(grantee) {
|
144 | const tableActions = perms.READ_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE);
|
145 | return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, tableActions });
|
146 | }
|
147 | /**
|
148 | * Permits an IAM Principal to list streams attached to current dynamodb table.
|
149 | *
|
150 | * @param grantee The principal (no-op if undefined)
|
151 | */
|
152 | grantTableListStreams(grantee) {
|
153 | if (!this.tableStreamArn) {
|
154 | throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
|
155 | }
|
156 | return iam.Grant.addToPrincipal({
|
157 | grantee,
|
158 | actions: ['dynamodb:ListStreams'],
|
159 | resourceArns: ['*'],
|
160 | });
|
161 | }
|
162 | /**
|
163 | * Permits an IAM principal all stream data read operations for this
|
164 | * table's stream:
|
165 | * DescribeStream, GetRecords, GetShardIterator, ListStreams.
|
166 | *
|
167 | * Appropriate grants will also be added to the customer-managed KMS key
|
168 | * if one was configured.
|
169 | *
|
170 | * @param grantee The principal to grant access to
|
171 | */
|
172 | grantStreamRead(grantee) {
|
173 | this.grantTableListStreams(grantee);
|
174 | return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, streamActions: perms.READ_STREAM_DATA_ACTIONS });
|
175 | }
|
176 | /**
|
177 | * Permits an IAM principal all data write operations to this table:
|
178 | * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable.
|
179 | *
|
180 | * Appropriate grants will also be added to the customer-managed KMS key
|
181 | * if one was configured.
|
182 | *
|
183 | * @param grantee The principal to grant access to
|
184 | */
|
185 | grantWriteData(grantee) {
|
186 | const tableActions = perms.WRITE_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE);
|
187 | const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
|
188 | return this.combinedGrant(grantee, { keyActions, tableActions });
|
189 | }
|
190 | /**
|
191 | * Permits an IAM principal to all data read/write operations to this table.
|
192 | * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan,
|
193 | * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable
|
194 | *
|
195 | * Appropriate grants will also be added to the customer-managed KMS key
|
196 | * if one was configured.
|
197 | *
|
198 | * @param grantee The principal to grant access to
|
199 | */
|
200 | grantReadWriteData(grantee) {
|
201 | const tableActions = perms.READ_DATA_ACTIONS.concat(perms.WRITE_DATA_ACTIONS).concat(perms.DESCRIBE_TABLE);
|
202 | const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
|
203 | return this.combinedGrant(grantee, { keyActions, tableActions });
|
204 | }
|
205 | /**
|
206 | * Permits all DynamoDB operations ("dynamodb:*") to an IAM principal.
|
207 | *
|
208 | * Appropriate grants will also be added to the customer-managed KMS key
|
209 | * if one was configured.
|
210 | *
|
211 | * @param grantee The principal to grant access to
|
212 | */
|
213 | grantFullAccess(grantee) {
|
214 | const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
|
215 | return this.combinedGrant(grantee, { keyActions, tableActions: ['dynamodb:*'] });
|
216 | }
|
217 | /**
|
218 | * Return the given named metric for this Table
|
219 | *
|
220 | * By default, the metric will be calculated as a sum over a period of 5 minutes.
|
221 | * You can customize this by using the `statistic` and `period` properties.
|
222 | */
|
223 | metric(metricName, props) {
|
224 | return new cloudwatch.Metric({
|
225 | namespace: 'AWS/DynamoDB',
|
226 | metricName,
|
227 | dimensionsMap: {
|
228 | TableName: this.tableName,
|
229 | },
|
230 | ...props,
|
231 | }).attachTo(this);
|
232 | }
|
233 | /**
|
234 | * Metric for the consumed read capacity units this table
|
235 | *
|
236 | * By default, the metric will be calculated as a sum over a period of 5 minutes.
|
237 | * You can customize this by using the `statistic` and `period` properties.
|
238 | */
|
239 | metricConsumedReadCapacityUnits(props) {
|
240 | return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedReadCapacityUnitsSum, props);
|
241 | }
|
242 | /**
|
243 | * Metric for the consumed write capacity units this table
|
244 | *
|
245 | * By default, the metric will be calculated as a sum over a period of 5 minutes.
|
246 | * You can customize this by using the `statistic` and `period` properties.
|
247 | */
|
248 | metricConsumedWriteCapacityUnits(props) {
|
249 | return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedWriteCapacityUnitsSum, props);
|
250 | }
|
251 | /**
|
252 | * Metric for the system errors this table
|
253 | *
|
254 | * @deprecated use `metricSystemErrorsForOperations`.
|
255 | */
|
256 | metricSystemErrors(props) {
|
257 | if (!props?.dimensions?.Operation && !props?.dimensionsMap?.Operation) {
|
258 | // 'Operation' must be passed because its an operational metric.
|
259 | throw new Error("'Operation' dimension must be passed for the 'SystemErrors' metric.");
|
260 | }
|
261 | const dimensionsMap = {
|
262 | TableName: this.tableName,
|
263 | ...props?.dimensions ?? {},
|
264 | ...props?.dimensionsMap ?? {},
|
265 | };
|
266 | return this.metric('SystemErrors', { statistic: 'sum', ...props, dimensionsMap });
|
267 | }
|
268 | /**
|
269 | * Metric for the user errors. Note that this metric reports user errors across all
|
270 | * the tables in the account and region the table resides in.
|
271 | *
|
272 | * By default, the metric will be calculated as a sum over a period of 5 minutes.
|
273 | * You can customize this by using the `statistic` and `period` properties.
|
274 | */
|
275 | metricUserErrors(props) {
|
276 | if (props?.dimensions) {
|
277 | throw new Error("'dimensions' is not supported for the 'UserErrors' metric");
|
278 | }
|
279 | // overriding 'dimensions' here because this metric is an account metric.
|
280 | // see 'UserErrors' in https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html
|
281 | return this.metric('UserErrors', { statistic: 'sum', ...props, dimensionsMap: {} });
|
282 | }
|
283 | /**
|
284 | * Metric for the conditional check failed requests this table
|
285 | *
|
286 | * By default, the metric will be calculated as a sum over a period of 5 minutes.
|
287 | * You can customize this by using the `statistic` and `period` properties.
|
288 | */
|
289 | metricConditionalCheckFailedRequests(props) {
|
290 | return this.metric('ConditionalCheckFailedRequests', { statistic: 'sum', ...props });
|
291 | }
|
292 | /**
|
293 | * How many requests are throttled on this table
|
294 | *
|
295 | * Default: sum over 5 minutes
|
296 | *
|
297 | * @deprecated Do not use this function. It returns an invalid metric. Use `metricThrottledRequestsForOperation` instead.
|
298 | */
|
299 | metricThrottledRequests(props) {
|
300 | return this.metric('ThrottledRequests', { statistic: 'sum', ...props });
|
301 | }
|
302 | /**
|
303 | * How many requests are throttled on this table, for the given operation
|
304 | *
|
305 | * Default: sum over 5 minutes
|
306 | */
|
307 | metricThrottledRequestsForOperation(operation, props) {
|
308 | return new cloudwatch.Metric({
|
309 | ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.throttledRequestsSum({ Operation: operation, TableName: this.tableName }),
|
310 | ...props,
|
311 | }).attachTo(this);
|
312 | }
|
313 | /**
|
314 | * Metric for the successful request latency this table.
|
315 | *
|
316 | * By default, the metric will be calculated as an average over a period of 5 minutes.
|
317 | * You can customize this by using the `statistic` and `period` properties.
|
318 | */
|
319 | metricSuccessfulRequestLatency(props) {
|
320 | if (!props?.dimensions?.Operation && !props?.dimensionsMap?.Operation) {
|
321 | throw new Error("'Operation' dimension must be passed for the 'SuccessfulRequestLatency' metric.");
|
322 | }
|
323 | const dimensionsMap = {
|
324 | TableName: this.tableName,
|
325 | Operation: props.dimensionsMap?.Operation ?? props.dimensions?.Operation,
|
326 | };
|
327 | return new cloudwatch.Metric({
|
328 | ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.successfulRequestLatencyAverage(dimensionsMap),
|
329 | ...props,
|
330 | dimensionsMap,
|
331 | }).attachTo(this);
|
332 | }
|
333 | /**
|
334 | * Metric for the system errors this table.
|
335 | *
|
336 | * This will sum errors across all possible operations.
|
337 | * Note that by default, each individual metric will be calculated as a sum over a period of 5 minutes.
|
338 | * You can customize this by using the `statistic` and `period` properties.
|
339 | */
|
340 | metricSystemErrorsForOperations(props) {
|
341 | if (props?.dimensions?.Operation) {
|
342 | throw new Error("The Operation dimension is not supported. Use the 'operations' property.");
|
343 | }
|
344 | const operations = props?.operations ?? Object.values(Operation);
|
345 | const values = this.createMetricsForOperations('SystemErrors', operations, { statistic: 'sum', ...props });
|
346 | const sum = new cloudwatch.MathExpression({
|
347 | expression: `${Object.keys(values).join(' + ')}`,
|
348 | usingMetrics: { ...values },
|
349 | color: props?.color,
|
350 | label: 'Sum of errors across all operations',
|
351 | period: props?.period,
|
352 | });
|
353 | return sum;
|
354 | }
|
355 | /**
|
356 | * Create a map of metrics that can be used in a math expression.
|
357 | *
|
358 | * Using the return value of this function as the `usingMetrics` property in `cloudwatch.MathExpression` allows you to
|
359 | * use the keys of this map as metric names inside you expression.
|
360 | *
|
361 | * @param metricName The metric name.
|
362 | * @param operations The list of operations to create metrics for.
|
363 | * @param props Properties for the individual metrics.
|
364 | * @param metricNameMapper Mapper function to allow controlling the individual metric name per operation.
|
365 | */
|
366 | createMetricsForOperations(metricName, operations, props, metricNameMapper) {
|
367 | const metrics = {};
|
368 | const mapper = metricNameMapper ?? (op => op.toLowerCase());
|
369 | if (props?.dimensions?.Operation) {
|
370 | throw new Error('Invalid properties. Operation dimension is not supported when calculating operational metrics');
|
371 | }
|
372 | for (const operation of operations) {
|
373 | const metric = this.metric(metricName, {
|
374 | ...props,
|
375 | dimensionsMap: {
|
376 | TableName: this.tableName,
|
377 | Operation: operation,
|
378 | ...props?.dimensions,
|
379 | },
|
380 | });
|
381 | const operationMetricName = mapper(operation);
|
382 | const firstChar = operationMetricName.charAt(0);
|
383 | if (firstChar === firstChar.toUpperCase()) {
|
384 | // https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/using-metric-math.html#metric-math-syntax
|
385 | throw new Error(`Mapper generated an illegal operation metric name: ${operationMetricName}. Must start with a lowercase letter`);
|
386 | }
|
387 | metrics[operationMetricName] = metric;
|
388 | }
|
389 | return metrics;
|
390 | }
|
391 | /**
|
392 | * Adds an IAM policy statement associated with this table to an IAM
|
393 | * principal's policy.
|
394 | * @param grantee The principal (no-op if undefined)
|
395 | * @param opts Options for keyActions, tableActions and streamActions
|
396 | */
|
397 | combinedGrant(grantee, opts) {
|
398 | if (opts.tableActions) {
|
399 | const resources = [this.tableArn,
|
400 | core_1.Lazy.string({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : core_1.Aws.NO_VALUE }),
|
401 | ...this.regionalArns,
|
402 | ...this.regionalArns.map(arn => core_1.Lazy.string({
|
403 | produce: () => this.hasIndex ? `${arn}/index/*` : core_1.Aws.NO_VALUE,
|
404 | }))];
|
405 | const ret = iam.Grant.addToPrincipal({
|
406 | grantee,
|
407 | actions: opts.tableActions,
|
408 | resourceArns: resources,
|
409 | scope: this,
|
410 | });
|
411 | if (this.encryptionKey && opts.keyActions) {
|
412 | this.encryptionKey.grant(grantee, ...opts.keyActions);
|
413 | }
|
414 | return ret;
|
415 | }
|
416 | if (opts.streamActions) {
|
417 | if (!this.tableStreamArn) {
|
418 | throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
|
419 | }
|
420 | const resources = [this.tableStreamArn];
|
421 | const ret = iam.Grant.addToPrincipal({
|
422 | grantee,
|
423 | actions: opts.streamActions,
|
424 | resourceArns: resources,
|
425 | scope: this,
|
426 | });
|
427 | return ret;
|
428 | }
|
429 | throw new Error(`Unexpected 'action', ${opts.tableActions || opts.streamActions}`);
|
430 | }
|
431 | cannedMetric(fn, props) {
|
432 | return new cloudwatch.Metric({
|
433 | ...fn({ TableName: this.tableName }),
|
434 | ...props,
|
435 | }).attachTo(this);
|
436 | }
|
437 | }
|
438 | /**
|
439 | * Provides a DynamoDB table.
|
440 | */
|
441 | class Table extends TableBase {
|
442 | constructor(scope, id, props) {
|
443 | super(scope, id, {
|
444 | physicalName: props.tableName,
|
445 | });
|
446 | this.keySchema = new Array();
|
447 | this.attributeDefinitions = new Array();
|
448 | this.globalSecondaryIndexes = new Array();
|
449 | this.localSecondaryIndexes = new Array();
|
450 | this.secondaryIndexSchemas = new Map();
|
451 | this.nonKeyAttributes = new Set();
|
452 | this.tableScaling = {};
|
453 | this.indexScaling = new Map();
|
454 | this.globalReplicaCustomResources = new Array();
|
455 | try {
|
456 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_TableProps(props);
|
457 | }
|
458 | catch (error) {
|
459 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
460 | Error.captureStackTrace(error, Table);
|
461 | }
|
462 | throw error;
|
463 | }
|
464 | const { sseSpecification, encryptionKey } = this.parseEncryption(props);
|
465 | let streamSpecification;
|
466 | if (props.replicationRegions) {
|
467 | if (props.stream && props.stream !== StreamViewType.NEW_AND_OLD_IMAGES) {
|
468 | throw new Error('`stream` must be set to `NEW_AND_OLD_IMAGES` when specifying `replicationRegions`');
|
469 | }
|
470 | streamSpecification = { streamViewType: StreamViewType.NEW_AND_OLD_IMAGES };
|
471 | this.billingMode = props.billingMode ?? BillingMode.PAY_PER_REQUEST;
|
472 | }
|
473 | else {
|
474 | this.billingMode = props.billingMode ?? BillingMode.PROVISIONED;
|
475 | if (props.stream) {
|
476 | streamSpecification = { streamViewType: props.stream };
|
477 | }
|
478 | }
|
479 | this.validateProvisioning(props);
|
480 | this.table = new dynamodb_generated_1.CfnTable(this, 'Resource', {
|
481 | tableName: this.physicalName,
|
482 | keySchema: this.keySchema,
|
483 | attributeDefinitions: this.attributeDefinitions,
|
484 | globalSecondaryIndexes: core_1.Lazy.any({ produce: () => this.globalSecondaryIndexes }, { omitEmptyArray: true }),
|
485 | localSecondaryIndexes: core_1.Lazy.any({ produce: () => this.localSecondaryIndexes }, { omitEmptyArray: true }),
|
486 | pointInTimeRecoverySpecification: props.pointInTimeRecovery != null ? { pointInTimeRecoveryEnabled: props.pointInTimeRecovery } : undefined,
|
487 | billingMode: this.billingMode === BillingMode.PAY_PER_REQUEST ? this.billingMode : undefined,
|
488 | provisionedThroughput: this.billingMode === BillingMode.PAY_PER_REQUEST ? undefined : {
|
489 | readCapacityUnits: props.readCapacity || 5,
|
490 | writeCapacityUnits: props.writeCapacity || 5,
|
491 | },
|
492 | sseSpecification,
|
493 | streamSpecification,
|
494 | tableClass: props.tableClass,
|
495 | timeToLiveSpecification: props.timeToLiveAttribute ? { attributeName: props.timeToLiveAttribute, enabled: true } : undefined,
|
496 | contributorInsightsSpecification: props.contributorInsightsEnabled !== undefined ? { enabled: props.contributorInsightsEnabled } : undefined,
|
497 | kinesisStreamSpecification: props.kinesisStream ? { streamArn: props.kinesisStream.streamArn } : undefined,
|
498 | });
|
499 | this.table.applyRemovalPolicy(props.removalPolicy);
|
500 | this.encryptionKey = encryptionKey;
|
501 | this.tableArn = this.getResourceArnAttribute(this.table.attrArn, {
|
502 | service: 'dynamodb',
|
503 | resource: 'table',
|
504 | resourceName: this.physicalName,
|
505 | });
|
506 | this.tableName = this.getResourceNameAttribute(this.table.ref);
|
507 | if (props.tableName) {
|
508 | this.node.addMetadata('aws:cdk:hasPhysicalName', this.tableName);
|
509 | }
|
510 | this.tableStreamArn = streamSpecification ? this.table.attrStreamArn : undefined;
|
511 | this.scalingRole = this.makeScalingRole();
|
512 | this.addKey(props.partitionKey, HASH_KEY_TYPE);
|
513 | this.tablePartitionKey = props.partitionKey;
|
514 | if (props.sortKey) {
|
515 | this.addKey(props.sortKey, RANGE_KEY_TYPE);
|
516 | this.tableSortKey = props.sortKey;
|
517 | }
|
518 | if (props.replicationRegions && props.replicationRegions.length > 0) {
|
519 | this.createReplicaTables(props.replicationRegions, props.replicationTimeout, props.waitForReplicationToFinish);
|
520 | }
|
521 | }
|
522 | /**
|
523 | * Permits an IAM Principal to list all DynamoDB Streams.
|
524 | * @deprecated Use {@link #grantTableListStreams} for more granular permission
|
525 | * @param grantee The principal (no-op if undefined)
|
526 | */
|
527 | static grantListStreams(grantee) {
|
528 | try {
|
529 | jsiiDeprecationWarnings.print("@aws-cdk/aws-dynamodb.Table#grantListStreams", "Use {@link #grantTableListStreams} for more granular permission");
|
530 | }
|
531 | catch (error) {
|
532 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
533 | Error.captureStackTrace(error, this.grantListStreams);
|
534 | }
|
535 | throw error;
|
536 | }
|
537 | return iam.Grant.addToPrincipal({
|
538 | grantee,
|
539 | actions: ['dynamodb:ListStreams'],
|
540 | resourceArns: ['*'],
|
541 | });
|
542 | }
|
543 | /**
|
544 | * Creates a Table construct that represents an external table via table name.
|
545 | *
|
546 | * @param scope The parent creating construct (usually `this`).
|
547 | * @param id The construct's name.
|
548 | * @param tableName The table's name.
|
549 | */
|
550 | static fromTableName(scope, id, tableName) {
|
551 | return Table.fromTableAttributes(scope, id, { tableName });
|
552 | }
|
553 | /**
|
554 | * Creates a Table construct that represents an external table via table arn.
|
555 | *
|
556 | * @param scope The parent creating construct (usually `this`).
|
557 | * @param id The construct's name.
|
558 | * @param tableArn The table's ARN.
|
559 | */
|
560 | static fromTableArn(scope, id, tableArn) {
|
561 | return Table.fromTableAttributes(scope, id, { tableArn });
|
562 | }
|
563 | /**
|
564 | * Creates a Table construct that represents an external table.
|
565 | *
|
566 | * @param scope The parent creating construct (usually `this`).
|
567 | * @param id The construct's name.
|
568 | * @param attrs A `TableAttributes` object.
|
569 | */
|
570 | static fromTableAttributes(scope, id, attrs) {
|
571 | try {
|
572 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_TableAttributes(attrs);
|
573 | }
|
574 | catch (error) {
|
575 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
576 | Error.captureStackTrace(error, this.fromTableAttributes);
|
577 | }
|
578 | throw error;
|
579 | }
|
580 | class Import extends TableBase {
|
581 | constructor(_tableArn, tableName, tableStreamArn) {
|
582 | super(scope, id);
|
583 | this.hasIndex = (attrs.globalIndexes ?? []).length > 0 ||
|
584 | (attrs.localIndexes ?? []).length > 0;
|
585 | this.tableArn = _tableArn;
|
586 | this.tableName = tableName;
|
587 | this.tableStreamArn = tableStreamArn;
|
588 | this.encryptionKey = attrs.encryptionKey;
|
589 | }
|
590 | }
|
591 | let name;
|
592 | let arn;
|
593 | const stack = core_1.Stack.of(scope);
|
594 | if (!attrs.tableName) {
|
595 | if (!attrs.tableArn) {
|
596 | throw new Error('One of tableName or tableArn is required!');
|
597 | }
|
598 | arn = attrs.tableArn;
|
599 | const maybeTableName = stack.splitArn(attrs.tableArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
|
600 | if (!maybeTableName) {
|
601 | throw new Error('ARN for DynamoDB table must be in the form: ...');
|
602 | }
|
603 | name = maybeTableName;
|
604 | }
|
605 | else {
|
606 | if (attrs.tableArn) {
|
607 | throw new Error('Only one of tableArn or tableName can be provided');
|
608 | }
|
609 | name = attrs.tableName;
|
610 | arn = stack.formatArn({
|
611 | service: 'dynamodb',
|
612 | resource: 'table',
|
613 | resourceName: attrs.tableName,
|
614 | });
|
615 | }
|
616 | return new Import(arn, name, attrs.tableStreamArn);
|
617 | }
|
618 | /**
|
619 | * Add a global secondary index of table.
|
620 | *
|
621 | * @param props the property of global secondary index
|
622 | */
|
623 | addGlobalSecondaryIndex(props) {
|
624 | try {
|
625 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_GlobalSecondaryIndexProps(props);
|
626 | }
|
627 | catch (error) {
|
628 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
629 | Error.captureStackTrace(error, this.addGlobalSecondaryIndex);
|
630 | }
|
631 | throw error;
|
632 | }
|
633 | this.validateProvisioning(props);
|
634 | this.validateIndexName(props.indexName);
|
635 | // build key schema and projection for index
|
636 | const gsiKeySchema = this.buildIndexKeySchema(props.partitionKey, props.sortKey);
|
637 | const gsiProjection = this.buildIndexProjection(props);
|
638 | this.globalSecondaryIndexes.push({
|
639 | indexName: props.indexName,
|
640 | keySchema: gsiKeySchema,
|
641 | projection: gsiProjection,
|
642 | provisionedThroughput: this.billingMode === BillingMode.PAY_PER_REQUEST ? undefined : {
|
643 | readCapacityUnits: props.readCapacity || 5,
|
644 | writeCapacityUnits: props.writeCapacity || 5,
|
645 | },
|
646 | });
|
647 | this.secondaryIndexSchemas.set(props.indexName, {
|
648 | partitionKey: props.partitionKey,
|
649 | sortKey: props.sortKey,
|
650 | });
|
651 | this.indexScaling.set(props.indexName, {});
|
652 | }
|
653 | /**
|
654 | * Add a local secondary index of table.
|
655 | *
|
656 | * @param props the property of local secondary index
|
657 | */
|
658 | addLocalSecondaryIndex(props) {
|
659 | try {
|
660 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_LocalSecondaryIndexProps(props);
|
661 | }
|
662 | catch (error) {
|
663 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
664 | Error.captureStackTrace(error, this.addLocalSecondaryIndex);
|
665 | }
|
666 | throw error;
|
667 | }
|
668 | // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
|
669 | if (this.localSecondaryIndexes.length >= MAX_LOCAL_SECONDARY_INDEX_COUNT) {
|
670 | throw new RangeError(`a maximum number of local secondary index per table is ${MAX_LOCAL_SECONDARY_INDEX_COUNT}`);
|
671 | }
|
672 | this.validateIndexName(props.indexName);
|
673 | // build key schema and projection for index
|
674 | const lsiKeySchema = this.buildIndexKeySchema(this.tablePartitionKey, props.sortKey);
|
675 | const lsiProjection = this.buildIndexProjection(props);
|
676 | this.localSecondaryIndexes.push({
|
677 | indexName: props.indexName,
|
678 | keySchema: lsiKeySchema,
|
679 | projection: lsiProjection,
|
680 | });
|
681 | this.secondaryIndexSchemas.set(props.indexName, {
|
682 | partitionKey: this.tablePartitionKey,
|
683 | sortKey: props.sortKey,
|
684 | });
|
685 | }
|
686 | /**
|
687 | * Enable read capacity scaling for this table
|
688 | *
|
689 | * @returns An object to configure additional AutoScaling settings
|
690 | */
|
691 | autoScaleReadCapacity(props) {
|
692 | try {
|
693 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
|
694 | }
|
695 | catch (error) {
|
696 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
697 | Error.captureStackTrace(error, this.autoScaleReadCapacity);
|
698 | }
|
699 | throw error;
|
700 | }
|
701 | if (this.tableScaling.scalableReadAttribute) {
|
702 | throw new Error('Read AutoScaling already enabled for this table');
|
703 | }
|
704 | if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
|
705 | throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
|
706 | }
|
707 | return this.tableScaling.scalableReadAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, 'ReadScaling', {
|
708 | serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
|
709 | resourceId: `table/${this.tableName}`,
|
710 | dimension: 'dynamodb:table:ReadCapacityUnits',
|
711 | role: this.scalingRole,
|
712 | ...props,
|
713 | });
|
714 | }
|
715 | /**
|
716 | * Enable write capacity scaling for this table
|
717 | *
|
718 | * @returns An object to configure additional AutoScaling settings for this attribute
|
719 | */
|
720 | autoScaleWriteCapacity(props) {
|
721 | try {
|
722 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
|
723 | }
|
724 | catch (error) {
|
725 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
726 | Error.captureStackTrace(error, this.autoScaleWriteCapacity);
|
727 | }
|
728 | throw error;
|
729 | }
|
730 | if (this.tableScaling.scalableWriteAttribute) {
|
731 | throw new Error('Write AutoScaling already enabled for this table');
|
732 | }
|
733 | if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
|
734 | throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
|
735 | }
|
736 | this.tableScaling.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, 'WriteScaling', {
|
737 | serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
|
738 | resourceId: `table/${this.tableName}`,
|
739 | dimension: 'dynamodb:table:WriteCapacityUnits',
|
740 | role: this.scalingRole,
|
741 | ...props,
|
742 | });
|
743 | for (const globalReplicaCustomResource of this.globalReplicaCustomResources) {
|
744 | globalReplicaCustomResource.node.addDependency(this.tableScaling.scalableWriteAttribute);
|
745 | }
|
746 | return this.tableScaling.scalableWriteAttribute;
|
747 | }
|
748 | /**
|
749 | * Enable read capacity scaling for the given GSI
|
750 | *
|
751 | * @returns An object to configure additional AutoScaling settings for this attribute
|
752 | */
|
753 | autoScaleGlobalSecondaryIndexReadCapacity(indexName, props) {
|
754 | try {
|
755 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
|
756 | }
|
757 | catch (error) {
|
758 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
759 | Error.captureStackTrace(error, this.autoScaleGlobalSecondaryIndexReadCapacity);
|
760 | }
|
761 | throw error;
|
762 | }
|
763 | if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
|
764 | throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
|
765 | }
|
766 | const attributePair = this.indexScaling.get(indexName);
|
767 | if (!attributePair) {
|
768 | throw new Error(`No global secondary index with name ${indexName}`);
|
769 | }
|
770 | if (attributePair.scalableReadAttribute) {
|
771 | throw new Error('Read AutoScaling already enabled for this index');
|
772 | }
|
773 | return attributePair.scalableReadAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}ReadScaling`, {
|
774 | serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
|
775 | resourceId: `table/${this.tableName}/index/${indexName}`,
|
776 | dimension: 'dynamodb:index:ReadCapacityUnits',
|
777 | role: this.scalingRole,
|
778 | ...props,
|
779 | });
|
780 | }
|
781 | /**
|
782 | * Enable write capacity scaling for the given GSI
|
783 | *
|
784 | * @returns An object to configure additional AutoScaling settings for this attribute
|
785 | */
|
786 | autoScaleGlobalSecondaryIndexWriteCapacity(indexName, props) {
|
787 | try {
|
788 | jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
|
789 | }
|
790 | catch (error) {
|
791 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
792 | Error.captureStackTrace(error, this.autoScaleGlobalSecondaryIndexWriteCapacity);
|
793 | }
|
794 | throw error;
|
795 | }
|
796 | if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
|
797 | throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
|
798 | }
|
799 | const attributePair = this.indexScaling.get(indexName);
|
800 | if (!attributePair) {
|
801 | throw new Error(`No global secondary index with name ${indexName}`);
|
802 | }
|
803 | if (attributePair.scalableWriteAttribute) {
|
804 | throw new Error('Write AutoScaling already enabled for this index');
|
805 | }
|
806 | return attributePair.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}WriteScaling`, {
|
807 | serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
|
808 | resourceId: `table/${this.tableName}/index/${indexName}`,
|
809 | dimension: 'dynamodb:index:WriteCapacityUnits',
|
810 | role: this.scalingRole,
|
811 | ...props,
|
812 | });
|
813 | }
|
814 | /**
|
815 | * Get schema attributes of table or index.
|
816 | *
|
817 | * @returns Schema of table or index.
|
818 | */
|
819 | schema(indexName) {
|
820 | if (!indexName) {
|
821 | return {
|
822 | partitionKey: this.tablePartitionKey,
|
823 | sortKey: this.tableSortKey,
|
824 | };
|
825 | }
|
826 | let schema = this.secondaryIndexSchemas.get(indexName);
|
827 | if (!schema) {
|
828 | throw new Error(`Cannot find schema for index: ${indexName}. Use 'addGlobalSecondaryIndex' or 'addLocalSecondaryIndex' to add index`);
|
829 | }
|
830 | return schema;
|
831 | }
|
832 | /**
|
833 | * Validate the table construct.
|
834 | *
|
835 | * @returns an array of validation error message
|
836 | */
|
837 | validate() {
|
838 | const errors = new Array();
|
839 | if (!this.tablePartitionKey) {
|
840 | errors.push('a partition key must be specified');
|
841 | }
|
842 | if (this.localSecondaryIndexes.length > 0 && !this.tableSortKey) {
|
843 | errors.push('a sort key of the table must be specified to add local secondary indexes');
|
844 | }
|
845 | if (this.globalReplicaCustomResources.length > 0 && this.billingMode === BillingMode.PROVISIONED) {
|
846 | const writeAutoScaleAttribute = this.tableScaling.scalableWriteAttribute;
|
847 | if (!writeAutoScaleAttribute) {
|
848 | errors.push('A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity. ' +
|
849 | 'Use the autoScaleWriteCapacity() method to enable it.');
|
850 | }
|
851 | else if (!writeAutoScaleAttribute._scalingPolicyCreated) {
|
852 | errors.push('A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity with a policy. ' +
|
853 | 'Call one of the scaleOn*() methods of the object returned from autoScaleWriteCapacity()');
|
854 | }
|
855 | }
|
856 | return errors;
|
857 | }
|
858 | /**
|
859 | * Validate read and write capacity are not specified for on-demand tables (billing mode PAY_PER_REQUEST).
|
860 | *
|
861 | * @param props read and write capacity properties
|
862 | */
|
863 | validateProvisioning(props) {
|
864 | if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
|
865 | if (props.readCapacity !== undefined || props.writeCapacity !== undefined) {
|
866 | throw new Error('you cannot provision read and write capacity for a table with PAY_PER_REQUEST billing mode');
|
867 | }
|
868 | }
|
869 | }
|
870 | /**
|
871 | * Validate index name to check if a duplicate name already exists.
|
872 | *
|
873 | * @param indexName a name of global or local secondary index
|
874 | */
|
875 | validateIndexName(indexName) {
|
876 | if (this.secondaryIndexSchemas.has(indexName)) {
|
877 | // a duplicate index name causes validation exception, status code 400, while trying to create CFN stack
|
878 | throw new Error(`a duplicate index name, ${indexName}, is not allowed`);
|
879 | }
|
880 | }
|
881 | /**
|
882 | * Validate non-key attributes by checking limits within secondary index, which may vary in future.
|
883 | *
|
884 | * @param nonKeyAttributes a list of non-key attribute names
|
885 | */
|
886 | validateNonKeyAttributes(nonKeyAttributes) {
|
887 | if (this.nonKeyAttributes.size + nonKeyAttributes.length > 100) {
|
888 | // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
|
889 | throw new RangeError('a maximum number of nonKeyAttributes across all of secondary indexes is 100');
|
890 | }
|
891 | // store all non-key attributes
|
892 | nonKeyAttributes.forEach(att => this.nonKeyAttributes.add(att));
|
893 | }
|
894 | buildIndexKeySchema(partitionKey, sortKey) {
|
895 | this.registerAttribute(partitionKey);
|
896 | const indexKeySchema = [
|
897 | { attributeName: partitionKey.name, keyType: HASH_KEY_TYPE },
|
898 | ];
|
899 | if (sortKey) {
|
900 | this.registerAttribute(sortKey);
|
901 | indexKeySchema.push({ attributeName: sortKey.name, keyType: RANGE_KEY_TYPE });
|
902 | }
|
903 | return indexKeySchema;
|
904 | }
|
905 | buildIndexProjection(props) {
|
906 | if (props.projectionType === ProjectionType.INCLUDE && !props.nonKeyAttributes) {
|
907 | // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html
|
908 | throw new Error(`non-key attributes should be specified when using ${ProjectionType.INCLUDE} projection type`);
|
909 | }
|
910 | if (props.projectionType !== ProjectionType.INCLUDE && props.nonKeyAttributes) {
|
911 | // this combination causes validation exception, status code 400, while trying to create CFN stack
|
912 | throw new Error(`non-key attributes should not be specified when not using ${ProjectionType.INCLUDE} projection type`);
|
913 | }
|
914 | if (props.nonKeyAttributes) {
|
915 | this.validateNonKeyAttributes(props.nonKeyAttributes);
|
916 | }
|
917 | return {
|
918 | projectionType: props.projectionType ?? ProjectionType.ALL,
|
919 | nonKeyAttributes: props.nonKeyAttributes ?? undefined,
|
920 | };
|
921 | }
|
922 | findKey(keyType) {
|
923 | return this.keySchema.find(prop => prop.keyType === keyType);
|
924 | }
|
925 | addKey(attribute, keyType) {
|
926 | const existingProp = this.findKey(keyType);
|
927 | if (existingProp) {
|
928 | throw new Error(`Unable to set ${attribute.name} as a ${keyType} key, because ${existingProp.attributeName} is a ${keyType} key`);
|
929 | }
|
930 | this.registerAttribute(attribute);
|
931 | this.keySchema.push({
|
932 | attributeName: attribute.name,
|
933 | keyType,
|
934 | });
|
935 | return this;
|
936 | }
|
937 | /**
|
938 | * Register the key attribute of table or secondary index to assemble attribute definitions of TableResourceProps.
|
939 | *
|
940 | * @param attribute the key attribute of table or secondary index
|
941 | */
|
942 | registerAttribute(attribute) {
|
943 | const { name, type } = attribute;
|
944 | const existingDef = this.attributeDefinitions.find(def => def.attributeName === name);
|
945 | if (existingDef && existingDef.attributeType !== type) {
|
946 | throw new Error(`Unable to specify ${name} as ${type} because it was already defined as ${existingDef.attributeType}`);
|
947 | }
|
948 | if (!existingDef) {
|
949 | this.attributeDefinitions.push({
|
950 | attributeName: name,
|
951 | attributeType: type,
|
952 | });
|
953 | }
|
954 | }
|
955 | /**
|
956 | * Return the role that will be used for AutoScaling
|
957 | */
|
958 | makeScalingRole() {
|
959 | // Use a Service Linked Role.
|
960 | // https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html
|
961 | return iam.Role.fromRoleArn(this, 'ScalingRole', core_1.Stack.of(this).formatArn({
|
962 | service: 'iam',
|
963 | region: '',
|
964 | resource: 'role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com',
|
965 | resourceName: 'AWSServiceRoleForApplicationAutoScaling_DynamoDBTable',
|
966 | }));
|
967 | }
|
968 | /**
|
969 | * Creates replica tables
|
970 | *
|
971 | * @param regions regions where to create tables
|
972 | */
|
973 | createReplicaTables(regions, timeout, waitForReplicationToFinish) {
|
974 | const stack = core_1.Stack.of(this);
|
975 | if (!core_1.Token.isUnresolved(stack.region) && regions.includes(stack.region)) {
|
976 | throw new Error('`replicationRegions` cannot include the region where this stack is deployed.');
|
977 | }
|
978 | const provider = replica_provider_1.ReplicaProvider.getOrCreate(this, { timeout });
|
979 | // Documentation at https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2gt_IAM.html
|
980 | // is currently incorrect. AWS Support recommends `dynamodb:*` in both source and destination regions
|
981 | const onEventHandlerPolicy = new SourceTableAttachedPolicy(this, provider.onEventHandler.role);
|
982 | const isCompleteHandlerPolicy = new SourceTableAttachedPolicy(this, provider.isCompleteHandler.role);
|
983 | // Permissions in the source region
|
984 | this.grant(onEventHandlerPolicy, 'dynamodb:*');
|
985 | this.grant(isCompleteHandlerPolicy, 'dynamodb:DescribeTable');
|
986 | let previousRegion;
|
987 | let previousRegionCondition;
|
988 | for (const region of new Set(regions)) { // Remove duplicates
|
989 | // Use multiple custom resources because multiple create/delete
|
990 | // updates cannot be combined in a single API call.
|
991 | const currentRegion = new core_1.CustomResource(this, `Replica${region}`, {
|
992 | serviceToken: provider.provider.serviceToken,
|
993 | resourceType: 'Custom::DynamoDBReplica',
|
994 | properties: {
|
995 | TableName: this.tableName,
|
996 | Region: region,
|
997 | SkipReplicationCompletedWait: waitForReplicationToFinish == null
|
998 | ? undefined
|
999 | // CFN changes Custom Resource properties to strings anyways,
|
1000 | // so let's do that ourselves to make it clear in the handler this is a string, not a boolean
|
1001 | : (!waitForReplicationToFinish).toString(),
|
1002 | },
|
1003 | });
|
1004 | currentRegion.node.addDependency(onEventHandlerPolicy.policy, isCompleteHandlerPolicy.policy);
|
1005 | this.globalReplicaCustomResources.push(currentRegion);
|
1006 | // Deploy time check to prevent from creating a replica in the region
|
1007 | // where this stack is deployed. Only needed for environment agnostic
|
1008 | // stacks.
|
1009 | let createReplica;
|
1010 | if (core_1.Token.isUnresolved(stack.region)) {
|
1011 | createReplica = new core_1.CfnCondition(this, `StackRegionNotEquals${region}`, {
|
1012 | expression: core_1.Fn.conditionNot(core_1.Fn.conditionEquals(region, core_1.Aws.REGION)),
|
1013 | });
|
1014 | const cfnCustomResource = currentRegion.node.defaultChild;
|
1015 | cfnCustomResource.cfnOptions.condition = createReplica;
|
1016 | }
|
1017 | // Save regional arns for grantXxx() methods
|
1018 | this.regionalArns.push(stack.formatArn({
|
1019 | region,
|
1020 | service: 'dynamodb',
|
1021 | resource: 'table',
|
1022 | resourceName: this.tableName,
|
1023 | }));
|
1024 | // We need to create/delete regions sequentially because we cannot
|
1025 | // have multiple table updates at the same time. The `isCompleteHandler`
|
1026 | // of the provider waits until the replica is in an ACTIVE state.
|
1027 | if (previousRegion) {
|
1028 | if (previousRegionCondition) {
|
1029 | // we can't simply use a Dependency,
|
1030 | // because the previousRegion is protected by the "different region" Condition,
|
1031 | // and you can't have Fn::If in DependsOn.
|
1032 | // Instead, rely on Ref adding a dependency implicitly!
|
1033 | const previousRegionCfnResource = previousRegion.node.defaultChild;
|
1034 | const currentRegionCfnResource = currentRegion.node.defaultChild;
|
1035 | currentRegionCfnResource.addMetadata('DynamoDbReplicationDependency', core_1.Fn.conditionIf(previousRegionCondition.logicalId, previousRegionCfnResource.ref, core_1.Aws.NO_VALUE));
|
1036 | }
|
1037 | else {
|
1038 | currentRegion.node.addDependency(previousRegion);
|
1039 | }
|
1040 | }
|
1041 | previousRegion = currentRegion;
|
1042 | previousRegionCondition = createReplica;
|
1043 | }
|
1044 | // Permissions in the destination regions (outside of the loop to
|
1045 | // minimize statements in the policy)
|
1046 | onEventHandlerPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({
|
1047 | actions: ['dynamodb:*'],
|
1048 | resources: this.regionalArns,
|
1049 | }));
|
1050 | }
|
1051 | /**
|
1052 | * Whether this table has indexes
|
1053 | */
|
1054 | get hasIndex() {
|
1055 | return this.globalSecondaryIndexes.length + this.localSecondaryIndexes.length > 0;
|
1056 | }
|
1057 | /**
|
1058 | * Set up key properties and return the Table encryption property from the
|
1059 | * user's configuration.
|
1060 | */
|
1061 | parseEncryption(props) {
|
1062 | let encryptionType = props.encryption;
|
1063 | if (encryptionType != null && props.serverSideEncryption != null) {
|
1064 | throw new Error('Only one of encryption and serverSideEncryption can be specified, but both were provided');
|
1065 | }
|
1066 | if (props.serverSideEncryption && props.encryptionKey) {
|
1067 | throw new Error('encryptionKey cannot be specified when serverSideEncryption is specified. Use encryption instead');
|
1068 | }
|
1069 | if (encryptionType === undefined) {
|
1070 | encryptionType = props.encryptionKey != null
|
1071 | // If there is a configured encryptionKey, the encryption is implicitly CUSTOMER_MANAGED
|
1072 | ? TableEncryption.CUSTOMER_MANAGED
|
1073 | // Otherwise, if severSideEncryption is enabled, it's AWS_MANAGED; else undefined (do not set anything)
|
1074 | : props.serverSideEncryption ? TableEncryption.AWS_MANAGED : undefined;
|
1075 | }
|
1076 | if (encryptionType !== TableEncryption.CUSTOMER_MANAGED && props.encryptionKey) {
|
1077 | throw new Error('`encryptionKey cannot be specified unless encryption is set to TableEncryption.CUSTOMER_MANAGED (it was set to ${encryptionType})`');
|
1078 | }
|
1079 | if (encryptionType === TableEncryption.CUSTOMER_MANAGED && props.replicationRegions) {
|
1080 | throw new Error('TableEncryption.CUSTOMER_MANAGED is not supported by DynamoDB Global Tables (where replicationRegions was set)');
|
1081 | }
|
1082 | switch (encryptionType) {
|
1083 | case TableEncryption.CUSTOMER_MANAGED:
|
1084 | const encryptionKey = props.encryptionKey ?? new kms.Key(this, 'Key', {
|
1085 | description: `Customer-managed key auto-created for encrypting DynamoDB table at ${this.node.path}`,
|
1086 | enableKeyRotation: true,
|
1087 | });
|
1088 | return {
|
1089 | sseSpecification: { sseEnabled: true, kmsMasterKeyId: encryptionKey.keyArn, sseType: 'KMS' },
|
1090 | encryptionKey,
|
1091 | };
|
1092 | case TableEncryption.AWS_MANAGED:
|
1093 | // Not specifying "sseType: 'KMS'" here because it would cause phony changes to existing stacks.
|
1094 | return { sseSpecification: { sseEnabled: true } };
|
1095 | case TableEncryption.DEFAULT:
|
1096 | return { sseSpecification: { sseEnabled: false } };
|
1097 | case undefined:
|
1098 | // Not specifying "sseEnabled: false" here because it would cause phony changes to existing stacks.
|
1099 | return { sseSpecification: undefined };
|
1100 | default:
|
1101 | throw new Error(`Unexpected 'encryptionType': ${encryptionType}`);
|
1102 | }
|
1103 | }
|
1104 | }
|
1105 | exports.Table = Table;
|
1106 | _a = JSII_RTTI_SYMBOL_1;
|
1107 | Table[_a] = { fqn: "@aws-cdk/aws-dynamodb.Table", version: "1.191.0" };
|
1108 | /**
|
1109 | * Data types for attributes within a table
|
1110 | *
|
1111 | * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes
|
1112 | */
|
1113 | var AttributeType;
|
1114 | (function (AttributeType) {
|
1115 | /** Up to 400KiB of binary data (which must be encoded as base64 before sending to DynamoDB) */
|
1116 | AttributeType["BINARY"] = "B";
|
1117 | /** Numeric values made of up to 38 digits (positive, negative or zero) */
|
1118 | AttributeType["NUMBER"] = "N";
|
1119 | /** Up to 400KiB of UTF-8 encoded text */
|
1120 | AttributeType["STRING"] = "S";
|
1121 | })(AttributeType = exports.AttributeType || (exports.AttributeType = {}));
|
1122 | /**
|
1123 | * DynamoDB's Read/Write capacity modes.
|
1124 | */
|
1125 | var BillingMode;
|
1126 | (function (BillingMode) {
|
1127 | /**
|
1128 | * Pay only for what you use. You don't configure Read/Write capacity units.
|
1129 | */
|
1130 | BillingMode["PAY_PER_REQUEST"] = "PAY_PER_REQUEST";
|
1131 | /**
|
1132 | * Explicitly specified Read/Write capacity units.
|
1133 | */
|
1134 | BillingMode["PROVISIONED"] = "PROVISIONED";
|
1135 | })(BillingMode = exports.BillingMode || (exports.BillingMode = {}));
|
1136 | /**
|
1137 | * The set of attributes that are projected into the index
|
1138 | *
|
1139 | * @see https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Projection.html
|
1140 | */
|
1141 | var ProjectionType;
|
1142 | (function (ProjectionType) {
|
1143 | /** Only the index and primary keys are projected into the index. */
|
1144 | ProjectionType["KEYS_ONLY"] = "KEYS_ONLY";
|
1145 | /** Only the specified table attributes are projected into the index. The list of projected attributes is in `nonKeyAttributes`. */
|
1146 | ProjectionType["INCLUDE"] = "INCLUDE";
|
1147 | /** All of the table attributes are projected into the index. */
|
1148 | ProjectionType["ALL"] = "ALL";
|
1149 | })(ProjectionType = exports.ProjectionType || (exports.ProjectionType = {}));
|
1150 | /**
|
1151 | * When an item in the table is modified, StreamViewType determines what information
|
1152 | * is written to the stream for this table.
|
1153 | *
|
1154 | * @see https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_StreamSpecification.html
|
1155 | */
|
1156 | var StreamViewType;
|
1157 | (function (StreamViewType) {
|
1158 | /** The entire item, as it appears after it was modified, is written to the stream. */
|
1159 | StreamViewType["NEW_IMAGE"] = "NEW_IMAGE";
|
1160 | /** The entire item, as it appeared before it was modified, is written to the stream. */
|
1161 | StreamViewType["OLD_IMAGE"] = "OLD_IMAGE";
|
1162 | /** Both the new and the old item images of the item are written to the stream. */
|
1163 | StreamViewType["NEW_AND_OLD_IMAGES"] = "NEW_AND_OLD_IMAGES";
|
1164 | /** Only the key attributes of the modified item are written to the stream. */
|
1165 | StreamViewType["KEYS_ONLY"] = "KEYS_ONLY";
|
1166 | })(StreamViewType = exports.StreamViewType || (exports.StreamViewType = {}));
|
1167 | /**
|
1168 | * DynamoDB's table class.
|
1169 | *
|
1170 | * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.TableClasses.html
|
1171 | */
|
1172 | var TableClass;
|
1173 | (function (TableClass) {
|
1174 | /** Default table class for DynamoDB. */
|
1175 | TableClass["STANDARD"] = "STANDARD";
|
1176 | /** Table class for DynamoDB that reduces storage costs compared to existing DynamoDB Standard tables. */
|
1177 | TableClass["STANDARD_INFREQUENT_ACCESS"] = "STANDARD_INFREQUENT_ACCESS";
|
1178 | })(TableClass = exports.TableClass || (exports.TableClass = {}));
|
1179 | /**
|
1180 | * An inline policy that is logically bound to the source table of a DynamoDB Global Tables
|
1181 | * "cluster". This is here to ensure permissions are removed as part of (and not before) the
|
1182 | * CleanUp phase of a stack update, when a replica is removed (or the entire "cluster" gets
|
1183 | * replaced).
|
1184 | *
|
1185 | * If statements are added directly to the handler roles (as opposed to in a separate inline
|
1186 | * policy resource), new permissions are in effect before clean up happens, and so replicas that
|
1187 | * need to be dropped can no longer be due to lack of permissions.
|
1188 | */
|
1189 | class SourceTableAttachedPolicy extends core_2.Construct {
|
1190 | constructor(sourceTable, role) {
|
1191 | super(sourceTable, `SourceTableAttachedManagedPolicy-${core_1.Names.nodeUniqueId(role.node)}`);
|
1192 | const policy = new iam.ManagedPolicy(this, 'Resource', {
|
1193 | // A CF update of the description property of a managed policy requires
|
1194 | // a replacement. Use the table name in the description to force a managed
|
1195 | // policy replacement when the table name changes. This way we preserve permissions
|
1196 | // to delete old replicas in case of a table replacement.
|
1197 | description: `DynamoDB replication managed policy for table ${sourceTable.tableName}`,
|
1198 | roles: [role],
|
1199 | });
|
1200 | this.policy = policy;
|
1201 | this.grantPrincipal = new SourceTableAttachedPrincipal(role, policy);
|
1202 | }
|
1203 | }
|
1204 | /**
|
1205 | * An `IPrincipal` entity that can be used as the target of `grant` calls, used by the
|
1206 | * `SourceTableAttachedPolicy` class so it can act as an `IGrantable`.
|
1207 | */
|
1208 | class SourceTableAttachedPrincipal extends iam.PrincipalBase {
|
1209 | constructor(role, policy) {
|
1210 | super();
|
1211 | this.role = role;
|
1212 | this.policy = policy;
|
1213 | }
|
1214 | get policyFragment() {
|
1215 | return this.role.policyFragment;
|
1216 | }
|
1217 | addToPrincipalPolicy(statement) {
|
1218 | this.policy.addStatements(statement);
|
1219 | return {
|
1220 | policyDependable: this.policy,
|
1221 | statementAdded: true,
|
1222 | };
|
1223 | }
|
1224 | dedupeString() {
|
1225 | return undefined;
|
1226 | }
|
1227 | }
|
1228 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxrRUFBa0U7QUFDbEUsc0RBQXNEO0FBQ3RELHdDQUF3QztBQUV4Qyx3Q0FBd0M7QUFDeEMsd0NBSXVCO0FBRXZCLDJGQUFzRTtBQUN0RSw2REFBK0Q7QUFDL0QsaUNBQWlDO0FBQ2pDLHlEQUFxRDtBQUVyRCx5RUFBb0U7QUFFcEUsaUdBQWlHO0FBQ2pHLDhEQUE4RDtBQUM5RCx3Q0FBMkQ7QUFFM0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDO0FBQzdCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQztBQUUvQix3R0FBd0c7QUFDeEcsTUFBTSwrQkFBK0IsR0FBRyxDQUFDLENBQUM7QUFnQjFDOztHQUVHO0FBQ0gsSUFBWSxTQTRDWDtBQTVDRCxXQUFZLFNBQVM7SUFFbkIsY0FBYztJQUNkLGlDQUFvQixDQUFBO0lBRXBCLG1CQUFtQjtJQUNuQiw0Q0FBK0IsQ0FBQTtJQUUvQixXQUFXO0lBQ1gsMEJBQWEsQ0FBQTtJQUViLFlBQVk7SUFDWiw0QkFBZSxDQUFBO0lBRWYsaUJBQWlCO0lBQ2pCLHVDQUEwQixDQUFBO0lBRTFCLGNBQWM7SUFDZCxpQ0FBb0IsQ0FBQTtJQUVwQixpQkFBaUI7SUFDakIsdUNBQTBCLENBQUE7SUFFMUIsaUJBQWlCO0lBQ2pCLHVDQUEwQixDQUFBO0lBRTFCLHFCQUFxQjtJQUNyQixnREFBbUMsQ0FBQTtJQUVuQyx5QkFBeUI7SUFDekIsd0RBQTJDLENBQUE7SUFFM0MsdUJBQXVCO0lBQ3ZCLG9EQUF1QyxDQUFBO0lBRXZDLHlCQUF5QjtJQUN6Qix1REFBMEMsQ0FBQTtJQUUxQyw0QkFBNEI7SUFDNUIsOERBQWlELENBQUE7SUFFakQsdUJBQXVCO0lBQ3ZCLG1EQUFzQyxDQUFBO0FBRXhDLENBQUMsRUE1Q1csU0FBUyxHQUFULGlCQUFTLEtBQVQsaUJBQVMsUUE0Q3BCO0FBa0JEOztHQUVH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QUVEOzs7R0FHRztBQUNILE1BQU0sNEJBQTZCLFNBQVEsR0FBRyxDQUFDLGFBQWE7SUFDMUQsWUFBb0MsSUFBZSxFQUFtQixNQUF5QjtRQUM3RixLQUFLLEVBQUUsQ0FBQztRQUQwQixTQUFJLEdBQUosSUFBSSxDQUFXO1FBQW1CLFdBQU0sR0FBTixNQUFNLENBQW1CO0tBRTlGO0lBRUQsSUFBVyxjQUFjO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7S0FDakM7SUFFTSxvQkFBb0IsQ0FBQyxTQUE4QjtRQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDN0IsY0FBYyxFQUFFLElBQUk7U0FDckIsQ0FBQztLQUNIO0lBRU0sWUFBWTtRQUNqQixPQUFPLFNBQVMsQ0FBQztLQUNsQjtDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXBwc2NhbGluZyBmcm9tICdAYXdzLWNkay9hd3MtYXBwbGljYXRpb25hdXRvc2NhbGluZyc7XG5pbXBvcnQgKiBhcyBjbG91ZHdhdGNoIGZyb20gJ0Bhd3MtY2RrL2F3cy1jbG91ZHdhdGNoJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGtpbmVzaXMgZnJvbSAnQGF3cy1jZGsvYXdzLWtpbmVzaXMnO1xuaW1wb3J0ICogYXMga21zIGZyb20gJ0Bhd3MtY2RrL2F3cy1rbXMnO1xuaW1wb3J0IHtcbiAgQXJuRm9ybWF0LFxuICBBd3MsIENmbkNvbmRpdGlvbiwgQ2ZuQ3VzdG9tUmVzb3VyY2UsIENmblJlc291cmNlLCBDdXN0b21SZXNvdXJjZSwgRHVyYXRpb24sXG4gIEZuLCBJUmVzb3VyY2UsIExhenksIE5hbWVzLCBSZW1vdmFsUG9saWN5LCBSZXNvdXJjZSwgU3RhY2ssIFRva2VuLFxufSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgRHluYW1vREJNZXRyaWNzIH0gZnJvbSAnLi9keW5hbW9kYi1jYW5uZWQtbWV0cmljcy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgQ2ZuVGFibGUsIENmblRhYmxlUHJvcHMgfSBmcm9tICcuL2R5bmFtb2RiLmdlbmVyYXRlZCc7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tICcuL3Blcm1zJztcbmltcG9ydCB7IFJlcGxpY2FQcm92aWRlciB9IGZyb20gJy4vcmVwbGljYS1wcm92aWRlcic7XG5pbXBvcnQgeyBFbmFibGVTY2FsaW5nUHJvcHMsIElTY2FsYWJsZVRhYmxlQXR0cmlidXRlIH0gZnJvbSAnLi9zY2FsYWJsZS1hdHRyaWJ1dGUtYXBpJztcbmltcG9ydCB7IFNjYWxhYmxlVGFibGVBdHRyaWJ1dGUgfSBmcm9tICcuL3NjYWxhYmxlLXRhYmxlLWF0dHJpYnV0ZSc7XG5cbi8vIGtlZXAgdGhpcyBpbXBvcnQgc2VwYXJhdGUgZnJvbSBvdGhlciBpbXBvcnRzIHRvIHJlZHVjZSBjaGFuY2UgZm9yIG1lcmdlIGNvbmZsaWN0cyB3aXRoIHYyLW1haW5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1kdXBsaWNhdGUtaW1wb3J0cywgaW1wb3J0L29yZGVyXG5pbXBvcnQgeyBDb25zdHJ1Y3QgYXMgQ29yZUNvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG5jb25zdCBIQVNIX0tFWV9UWVBFID0gJ0hBU0gnO1xuY29uc3QgUkFOR0VfS0VZX1RZUEUgPSAnUkFOR0UnO1xuXG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL0xpbWl0cy5odG1sI2xpbWl0cy1zZWNvbmRhcnktaW5kZXhlc1xuY29uc3QgTUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVCA9IDU7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgYSBzeXN0ZW0gZXJyb3JzIG1ldHJpYyB0aGF0IGNvbnNpZGVycyBtdWx0aXBsZSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnNNZXRyaWNPcHRpb25zIGV4dGVuZHMgY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zIHtcblxuICAvKipcbiAgICogVGhlIG9wZXJhdGlvbnMgdG8gYXBwbHkgdGhlIG1ldHJpYyB0by5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgb3BlcmF0aW9ucyBhdmFpbGFibGUgYnkgRHluYW1vREIgdGFibGVzIHdpbGwgYmUgY29uc2lkZXJlZC5cbiAgICovXG4gIHJlYWRvbmx5IG9wZXJhdGlvbnM/OiBPcGVyYXRpb25bXTtcblxufVxuXG4vKipcbiAqIFN1cHBvcnRlZCBEeW5hbW9EQiB0YWJsZSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgZW51bSBPcGVyYXRpb24ge1xuXG4gIC8qKiBHZXRJdGVtICovXG4gIEdFVF9JVEVNID0gJ0dldEl0ZW0nLFxuXG4gIC8qKiBCYXRjaEdldEl0ZW0gKi9cbiAgQkFUQ0hfR0VUX0lURU0gPSAnQmF0Y2hHZXRJdGVtJyxcblxuICAvKiogU2NhbiAqL1xuICBTQ0FOID0gJ1NjYW4nLFxuXG4gIC8qKiBRdWVyeSAqL1xuICBRVUVSWSA9ICdRdWVyeScsXG5cbiAgLyoqIEdldFJlY29yZHMgKi9cbiAgR0VUX1JFQ09SRFMgPSAnR2V0UmVjb3JkcycsXG5cbiAgLyoqIFB1dEl0ZW0gKi9cbiAgUFVUX0lURU0gPSAnUHV0SXRlbScsXG5cbiAgLyoqIERlbGV0ZUl0ZW0gKi9cbiAgREVMRVRFX0lURU0gPSAnRGVsZXRlSXRlbScsXG5cbiAgLyoqIFVwZGF0ZUl0ZW0gKi9cbiAgVVBEQVRFX0lURU0gPSAnVXBkYXRlSXRlbScsXG5cbiAgLyoqIEJhdGNoV3JpdGVJdGVtICovXG4gIEJBVENIX1dSSVRFX0lURU0gPSAnQmF0Y2hXcml0ZUl0ZW0nLFxuXG4gIC8qKiBUcmFuc2FjdFdyaXRlSXRlbXMgKi9cbiAgVFJBTlNBQ1RfV1JJVEVfSVRFTVMgPSAnVHJhbnNhY3RXcml0ZUl0ZW1zJyxcblxuICAvKiogVHJhbnNhY3RHZXRJdGVtcyAqL1xuICBUUkFOU0FDVF9HRVRfSVRFTVMgPSAnVHJhbnNhY3RHZXRJdGVtcycsXG5cbiAgLyoqIEV4ZWN1dGVUcmFuc2FjdGlvbiAqL1xuICBFWEVDVVRFX1RSQU5TQUNUSU9OID0gJ0V4ZWN1dGVUcmFuc2FjdGlvbicsXG5cbiAgLyoqIEJhdGNoRXhlY3V0ZVN0YXRlbWVudCAqL1xuICBCQVRDSF9FWEVDVVRFX1NUQVRFTUVOVCA9ICdCYXRjaEV4ZWN1dGVTdGF0ZW1lbnQnLFxuXG4gIC8qKiBFeGVjdXRlU3RhdGVtZW50ICovXG4gIEVYRUNVVEVfU1RBVEVNRU5UID0gJ0V4ZWN1dGVTdGF0ZW1lbnQnLFxuXG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBhdHRyaWJ1dGUgZm9yIGRlc2NyaWJpbmcgdGhlIGtleSBzY2hlbWEgZm9yIHRoZSB0YWJsZVxuICogYW5kIGluZGV4ZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGFuIGF0dHJpYnV0ZS5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRhdGEgdHlwZSBvZiBhbiBhdHRyaWJ1dGUuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBBdHRyaWJ1dGVUeXBlO1xufVxuXG4vKipcbiAqIFdoYXQga2luZCBvZiBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHRvIGFwcGx5IHRvIHRoaXMgdGFibGUuXG4gKi9cbmV4cG9ydCBlbnVtIFRhYmxlRW5jcnlwdGlvbiB7XG4gIC8qKlxuICAgKiBTZXJ2ZXItc2lkZSBLTVMgZW5jcnlwdGlvbiB3aXRoIGEgbWFzdGVyIGtleSBvd25lZCBieSBBV1MuXG4gICAqL1xuICBERUZBVUxUID0gJ0FXU19PV05FRCcsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIEtNUyBlbmNyeXB0aW9uIHdpdGggYSBjdXN0b21lciBtYXN0ZXIga2V5IG1hbmFnZWQgYnkgY3VzdG9tZXIuXG4gICAqIElmIGBlbmNyeXB0aW9uS2V5YCBpcyBzcGVjaWZpZWQsIHRoaXMga2V5IHdpbGwgYmUgdXNlZCwgb3RoZXJ3aXNlLCBvbmUgd2lsbCBiZSBkZWZpbmVkLlxuICAgKlxuICAgKiA+ICoqTk9URSoqOiBpZiBgZW5jcnlwdGlvbktleWAgaXMgbm90IHNwZWNpZmllZCBhbmQgdGhlIGBUYWJsZWAgY29uc3RydWN0IGNyZWF0ZXNcbiAgICogPiBhIEtNUyBrZXkgZm9yIHlvdSwgdGhlIGtleSB3aWxsIGJlIGNyZWF0ZWQgd2l0aCBkZWZhdWx0IHBlcm1pc3Npb25zLiBJZiB5b3UgYXJlIHVzaW5nXG4gICAqID4gQ0RLdjIsIHRoZXNlIHBlcm1pc3Npb25zIHdpbGwgYmUgc3VmZmljaWVudCB0byBlbmFibGUgdGhlIGtleSBmb3IgdXNlIHdpdGggRHluYW1vREIgdGFibGVzLlxuICAgKiA+IElmIHlvdSBhcmUgdXNpbmcgQ0RLdjEsIG1ha2Ugc3VyZSB0aGUgZmVhdHVyZSBmbGFnIGBAYXdzLWNkay9hd3Mta21zOmRlZmF1bHRLZXlQb2xpY2llc2BcbiAgICogPiBpcyBzZXQgdG8gYHRydWVgIGluIHlvdXIgYGNkay5qc29uYC5cbiAgICovXG4gIENVU1RPTUVSX01BTkFHRUQgPSAnQ1VTVE9NRVJfTUFOQUdFRCcsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIEtNUyBlbmNyeXB0aW9uIHdpdGggYSBtYXN0ZXIga2V5IG1hbmFnZWQgYnkgQVdTLlxuICAgKi9cbiAgQVdTX01BTkFHRUQgPSAnQVdTX01BTkFHRUQnLFxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIHRhYmxlIHNjaGVtYSBhdHRyaWJ1dGVzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNjaGVtYU9wdGlvbnMge1xuICAvKipcbiAgICogUGFydGl0aW9uIGtleSBhdHRyaWJ1dGUgZGVmaW5pdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHBhcnRpdGlvbktleTogQXR0cmlidXRlO1xuXG4gIC8qKlxuICAgKiBTb3J0IGtleSBhdHRyaWJ1dGUgZGVmaW5pdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgbm8gc29ydCBrZXlcbiAgICovXG4gIHJlYWRvbmx5IHNvcnRLZXk/OiBBdHRyaWJ1dGU7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBvZiBhIER5bmFtb0RCIFRhYmxlXG4gKlxuICogVXNlIHtAbGluayBUYWJsZVByb3BzfSBmb3IgYWxsIHRhYmxlIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZU9wdGlvbnMgZXh0ZW5kcyBTY2hlbWFPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSByZWFkIGNhcGFjaXR5IGZvciB0aGUgdGFibGUuIENhcmVmdWwgaWYgeW91IGFkZCBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMsIGFzXG4gICAqIHRob3NlIHdpbGwgc2hhcmUgdGhlIHRhYmxlJ3MgcHJvdmlzaW9uZWQgdGhyb3VnaHB1dC5cbiAgICpcbiAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHJlYWRDYXBhY2l0eT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB3cml0ZSBjYXBhY2l0eSBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgKiB0aG9zZSB3aWxsIHNoYXJlIHRoZSB0YWJsZSdzIHByb3Zpc2lvbmVkIHRocm91Z2hwdXQuXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSB3cml0ZUNhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IGhvdyB5b3UgYXJlIGNoYXJnZWQgZm9yIHJlYWQgYW5kIHdyaXRlIHRocm91Z2hwdXQgYW5kIGhvdyB5b3UgbWFuYWdlIGNhcGFjaXR5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBQUk9WSVNJT05FRCBpZiBgcmVwbGljYXRpb25SZWdpb25zYCBpcyBub3Qgc3BlY2lmaWVkLCBQQVlfUEVSX1JFUVVFU1Qgb3RoZXJ3aXNlXG4gICAqL1xuICByZWFkb25seSBiaWxsaW5nTW9kZT86IEJpbGxpbmdNb2RlO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZW5hYmxlZC5cbiAgICogQGRlZmF1bHQgLSBwb2ludC1pbi10aW1lIHJlY292ZXJ5IGlzIGRpc2FibGVkXG4gICAqL1xuICByZWFkb25seSBwb2ludEluVGltZVJlY292ZXJ5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHdpdGggYW4gQVdTIG1hbmFnZWQgY3VzdG9tZXIgbWFzdGVyIGtleSBpcyBlbmFibGVkLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGNhbm5vdCBiZSBzZXQgaWYgYGVuY3J5cHRpb25gIGFuZC9vciBgZW5jcnlwdGlvbktleWAgaXMgc2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHNlcnZlci1zaWRlIGVuY3J5cHRpb24gaXMgZW5hYmxlZCB3aXRoIGFuIEFXUyBvd25lZCBjdXN0b21lciBtYXN0ZXIga2V5XG4gICAqXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgcHJvcGVydHkgaXMgZGVwcmVjYXRlZC4gSW4gb3JkZXIgdG8gb2J0YWluIHRoZSBzYW1lIGJlaGF2aW9yIGFzXG4gICAqIGVuYWJsaW5nIHRoaXMsIHNldCB0aGUgYGVuY3J5cHRpb25gIHByb3BlcnR5IHRvIGBUYWJsZUVuY3J5cHRpb24uQVdTX01BTkFHRURgIGluc3RlYWQuXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJTaWRlRW5jcnlwdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIHRhYmxlIGNsYXNzLlxuICAgKiBAZGVmYXVsdCBTVEFOREFSRFxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVDbGFzcz86IFRhYmxlQ2xhc3M7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiB3aXRoIGFuIEFXUyBtYW5hZ2VkIGN1c3RvbWVyIG1hc3RlciBrZXkgaXMgZW5hYmxlZC5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBjYW5ub3QgYmUgc2V0IGlmIGBzZXJ2ZXJTaWRlRW5jcnlwdGlvbmAgaXMgc2V0LlxuICAgKlxuICAgKiA+ICoqTk9URSoqOiBpZiB5b3Ugc2V0IHRoaXMgdG8gYENVU1RPTUVSX01BTkFHRURgIGFuZCBgZW5jcnlwdGlvbktleWAgaXMgbm90XG4gICAqID4gc3BlY2lmaWVkLCB0aGUga2V5IHRoYXQgdGhlIFRhYmxldCBnZW5lcmF0ZXMgZm9yIHlvdSB3aWxsIGJlIGNyZWF0ZWQgd2l0aFxuICAgKiA+IGRlZmF1bHQgcGVybWlzc2lvbnMuIElmIHlvdSBhcmUgdXNpbmcgQ0RLdjIsIHRoZXNlIHBlcm1pc3Npb25zIHdpbGwgYmVcbiAgICogPiBzdWZmaWNpZW50IHRvIGVuYWJsZSB0aGUga2V5IGZvciB1c2Ugd2l0aCBEeW5hbW9EQiB0YWJsZXMuICBJZiB5b3UgYXJlXG4gICAqID4gdXNpbmcgQ0RLdjEsIG1ha2Ugc3VyZSB0aGUgZmVhdHVyZSBmbGFnXG4gICAqID4gYEBhd3MtY2RrL2F3cy1rbXM6ZGVmYXVsdEtleVBvbGljaWVzYCBpcyBzZXQgdG8gYHRydWVgIGluIHlvdXIgYGNkay5qc29uYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgd2l0aCBhbiBBV1Mgb3duZWQgY3VzdG9tZXIgbWFzdGVyIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbj86IFRhYmxlRW5jcnlwdGlvbjtcblxuICAvKipcbiAgICogRXh0ZXJuYWwgS01TIGtleSB0byB1c2UgZm9yIHRhYmxlIGVuY3J5cHRpb24uXG4gICAqXG4gICAqIFRoaXMgcHJvcGVydHkgY2FuIG9ubHkgYmUgc2V0IGlmIGBlbmNyeXB0aW9uYCBpcyBzZXQgdG8gYFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJZiBgZW5jcnlwdGlvbmAgaXMgc2V0IHRvIGBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRGAgYW5kIHRoaXNcbiAgICogcHJvcGVydHkgaXMgdW5kZWZpbmVkLCBhIG5ldyBLTVMga2V5IHdpbGwgYmUgY3JlYXRlZCBhbmQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIFRUTCBhdHRyaWJ1dGUuXG4gICAqIEBkZWZhdWx0IC0gVFRMIGlzIGRpc2FibGVkXG4gICAqL1xuICByZWFkb25seSB0aW1lVG9MaXZlQXR0cmlidXRlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIGFuIGl0ZW0gaW4gdGhlIHRhYmxlIGlzIG1vZGlmaWVkLCBTdHJlYW1WaWV3VHlwZSBkZXRlcm1pbmVzIHdoYXQgaW5mb3JtYXRpb25cbiAgICogaXMgd3JpdHRlbiB0byB0aGUgc3RyZWFtIGZvciB0aGlzIHRhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHN0cmVhbXMgYXJlIGRpc2FibGVkIHVubGVzcyBgcmVwbGljYXRpb25SZWdpb25zYCBpcyBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHN0cmVhbT86IFN0cmVhbVZpZXdUeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVtb3ZhbCBwb2xpY3kgdG8gYXBwbHkgdG8gdGhlIER5bmFtb0RCIFRhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBSZW1vdmFsUG9saWN5LlJFVEFJTlxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG5cbiAgLyoqXG4gICAqIFJlZ2lvbnMgd2hlcmUgcmVwbGljYSB0YWJsZXMgd2lsbCBiZSBjcmVhdGVkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gcmVwbGljYSB0YWJsZXMgYXJlIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uUmVnaW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZW91dCBmb3IgYSB0YWJsZSByZXBsaWNhdGlvbiBvcGVyYXRpb24gaW4gYSBzaW5nbGUgcmVnaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgcmVwbGljYXRpb25UaW1lb3V0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIENsb3VkRm9ybWF0aW9uIHN0YWNrIHdhaXRzIGZvciByZXBsaWNhdGlvbiB0byBmaW5pc2guXG4gICAqIElmIHNldCB0byBmYWxzZSwgdGhlIENsb3VkRm9ybWF0aW9uIHJlc291cmNlIHdpbGwgbWFyayB0aGUgcmVzb3VyY2UgYXNcbiAgICogY3JlYXRlZCBhbmQgcmVwbGljYXRpb24gd2lsbCBiZSBjb21wbGV0ZWQgYXN5bmNocm9ub3VzbHkuIFRoaXMgcHJvcGVydHkgaXNcbiAgICogaWdub3JlZCBpZiByZXBsaWNhdGlvblJlZ2lvbnMgcHJvcGVydHkgaXMgbm90IHNldC5cbiAgICpcbiAgICogRE8gTk9UIFVOU0VUIHRoaXMgcHJvcGVydHkgaWYgYWRkaW5nL3JlbW92aW5nIG11bHRpcGxlIHJlcGxpY2F0aW9uUmVnaW9uc1xuICAgKiBpbiBvbmUgZGVwbG95bWVudCwgYXMgQ2xvdWRGb3JtYXRpb24gb25seSBzdXBwb3J0cyBvbmUgcmVnaW9uIHJlcGxpY2F0aW9uXG4gICAqIGF0IGEgdGltZS4gQ0RLIG92ZXJjb21lcyB0aGlzIGxpbWl0YXRpb24gYnkgd2FpdGluZyBmb3IgcmVwbGljYXRpb24gdG9cbiAgICogZmluaXNoIGJlZm9yZSBzdGFydGluZyBuZXcgcmVwbGljYXRpb25SZWdpb24uXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLWdsb2JhbHRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLWdsb2JhbHRhYmxlLXJlcGxpY2FzXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHdhaXRGb3JSZXBsaWNhdGlvblRvRmluaXNoPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciBDbG91ZFdhdGNoIGNvbnRyaWJ1dG9yIGluc2lnaHRzIGlzIGVuYWJsZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjb250cmlidXRvckluc2lnaHRzRW5hYmxlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBEeW5hbW9EQiBUYWJsZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhYmxlUHJvcHMgZXh0ZW5kcyBUYWJsZU9wdGlvbnMge1xuICAvKipcbiAgICogRW5mb3JjZXMgYSBwYXJ0aWN1bGFyIHBoeXNpY2FsIHRhYmxlIG5hbWUuXG4gICAqIEBkZWZhdWx0IDxnZW5lcmF0ZWQ+XG4gICAqL1xuICByZWFkb25seSB0YWJsZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEtpbmVzaXMgRGF0YSBTdHJlYW0gdG8gY2FwdHVyZSBpdGVtLWxldmVsIGNoYW5nZXMgZm9yIHRoZSB0YWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBLaW5lc2lzIERhdGEgU3RyZWFtXG4gICAqL1xuICByZWFkb25seSBraW5lc2lzU3RyZWFtPzoga2luZXNpcy5JU3RyZWFtO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgc2Vjb25kYXJ5IGluZGV4XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2Vjb25kYXJ5SW5kZXhQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgc2Vjb25kYXJ5IGluZGV4LlxuICAgKi9cbiAgcmVhZG9ubHkgaW5kZXhOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZXQgb2YgYXR0cmlidXRlcyB0aGF0IGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgc2Vjb25kYXJ5IGluZGV4LlxuICAgKiBAZGVmYXVsdCBBTExcbiAgICovXG4gIHJlYWRvbmx5IHByb2plY3Rpb25UeXBlPzogUHJvamVjdGlvblR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBub24ta2V5IGF0dHJpYnV0ZXMgdGhhdCBhcmUgcHJvamVjdGVkIGludG8gdGhlIHNlY29uZGFyeSBpbmRleC5cbiAgICogQGRlZmF1bHQgLSBObyBhZGRpdGlvbmFsIGF0dHJpYnV0ZXNcbiAgICovXG4gIHJlYWRvbmx5IG5vbktleUF0dHJpYnV0ZXM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXhcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BzIGV4dGVuZHMgU2Vjb25kYXJ5SW5kZXhQcm9wcywgU2NoZW1hT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcmVhZCBjYXBhY2l0eSBmb3IgdGhlIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXguXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIHRhYmxlIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkIG9yIHVuZGVmaW5lZC5cbiAgICpcbiAgICogQGRlZmF1bHQgNVxuICAgKi9cbiAgcmVhZG9ubHkgcmVhZENhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgd3JpdGUgY2FwYWNpdHkgZm9yIHRoZSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiB0YWJsZSBiaWxsaW5nTW9kZSBpcyBQcm92aXNpb25lZCBvciB1bmRlZmluZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHdyaXRlQ2FwYWNpdHk/OiBudW1iZXI7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBsb2NhbCBzZWNvbmRhcnkgaW5kZXhcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2NhbFNlY29uZGFyeUluZGV4UHJvcHMgZXh0ZW5kcyBTZWNvbmRhcnlJbmRleFByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBhdHRyaWJ1dGUgb2YgYSBzb3J0IGtleSBmb3IgdGhlIGxvY2FsIHNlY29uZGFyeSBpbmRleC5cbiAgICovXG4gIHJlYWRvbmx5IHNvcnRLZXk6IEF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBBbiBpbnRlcmZhY2UgdGhhdCByZXByZXNlbnRzIGEgRHluYW1vREIgVGFibGUgLSBlaXRoZXIgY3JlYXRlZCB3aXRoIHRoZSBDREssIG9yIGFuIGV4aXN0aW5nIG9uZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJVGFibGUgZXh0ZW5kcyBJUmVzb3VyY2Uge1xuICAvKipcbiAgICogQXJuIG9mIHRoZSBkeW5hbW9kYiB0YWJsZS5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGFibGUgbmFtZSBvZiB0aGUgZHluYW1vZGIgdGFibGUuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIHRhYmxlJ3Mgc3RyZWFtLCBpZiB0aGVyZSBpcyBvbmUuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlU3RyZWFtQXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKlxuICAgKiBPcHRpb25hbCBLTVMgZW5jcnlwdGlvbiBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgdG8gYW4gSUFNXG4gICAqIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpQdXRJdGVtXCIsIFwiZHluYW1vZGI6R2V0SXRlbVwiLCAuLi4pXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUncyBzdHJlYW0gdG8gYW5cbiAgICogSUFNIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpEZXNjcmliZVN0cmVhbVwiLCBcImR5bmFtb2RiOkdldFJlY29yZHNcIiwgLi4uKVxuICAgKi9cbiAgZ3JhbnRTdHJlYW0oZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgcmVhZCBvcGVyYXRpb25zIGZyb20gdGhpcyB0YWJsZTpcbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2Nhbi5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIGdyYW50UmVhZERhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYW4gSUFNIFByaW5jaXBhbCB0byBsaXN0IHN0cmVhbXMgYXR0YWNoZWQgdG8gY3VycmVudCBkeW5hbW9kYiB0YWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKi9cbiAgZ3JhbnRUYWJsZUxpc3RTdHJlYW1zKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIHN0cmVhbSBkYXRhIHJlYWQgb3BlcmF0aW9ucyBmb3IgdGhpc1xuICAgKiB0YWJsZSdzIHN0cmVhbTpcbiAgICogRGVzY3JpYmVTdHJlYW0sIEdldFJlY29yZHMsIEdldFNoYXJkSXRlcmF0b3IsIExpc3RTdHJlYW1zLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgZ3JhbnRTdHJlYW1SZWFkKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgd3JpdGUgb3BlcmF0aW9ucyB0byB0aGlzIHRhYmxlOlxuICAgKiBCYXRjaFdyaXRlSXRlbSwgUHV0SXRlbSwgVXBkYXRlSXRlbSwgRGVsZXRlSXRlbS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIGdyYW50V3JpdGVEYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgdG8gYWxsIGRhdGEgcmVhZC93cml0ZSBvcGVyYXRpb25zIHRvIHRoaXMgdGFibGUuXG4gICAqIEJhdGNoR2V0SXRlbSwgR2V0UmVjb3JkcywgR2V0U2hhcmRJdGVyYXRvciwgUXVlcnksIEdldEl0ZW0sIFNjYW4sXG4gICAqIEJhdGNoV3JpdGVJdGVtLCBQdXRJdGVtLCBVcGRhdGVJdGVtLCBEZWxldGVJdGVtXG4gICAqXG4gICAqIEFwcHJvcHJpYXRlIGdyYW50cyB3aWxsIGFsc28gYmUgYWRkZWQgdG8gdGhlIGN1c3RvbWVyLW1hbmFnZWQgS01TIGtleVxuICAgKiBpZiBvbmUgd2FzIGNvbmZpZ3VyZWQuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgdG8gZ3JhbnQgYWNjZXNzIHRvXG4gICAqL1xuICBncmFudFJlYWRXcml0ZURhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYWxsIER5bmFtb0RCIG9wZXJhdGlvbnMgKFwiZHluYW1vZGI6KlwiKSB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgZ3JhbnRGdWxsQWNjZXNzKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgRXJyb3JzIGV4ZWN1dGluZyBhbGwgTGFtYmRhc1xuICAgKi9cbiAgbWV0cmljKG1ldHJpY05hbWU6IHN0cmluZywgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgY29uc3VtZWQgcmVhZCBjYXBhY2l0eSB1bml0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0cyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBjb25zdW1lZCB3cml0ZSBjYXBhY2l0eSB1bml0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgc3lzdGVtIGVycm9yc1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYG1ldHJpY1N5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnNgXG4gICAqL1xuICBtZXRyaWNTeXN0ZW1FcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgc3lzdGVtIGVycm9ycyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqXG4gICAqL1xuICBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zKHByb3BzPzogU3lzdGVtRXJyb3JzRm9yT3BlcmF0aW9uc01ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLklNZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHVzZXIgZXJyb3JzXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqL1xuICBtZXRyaWNVc2VyRXJyb3JzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbmRpdGlvbmFsIGNoZWNrIGZhaWxlZCByZXF1ZXN0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uZGl0aW9uYWxDaGVja0ZhaWxlZFJlcXVlc3RzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhyb3R0bGVkIHJlcXVlc3RzXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqXG4gICAqL1xuICBtZXRyaWNUaHJvdHRsZWRSZXF1ZXN0cyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzdWNjZXNzZnVsIHJlcXVlc3QgbGF0ZW5jeVxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKlxuICAgKi9cbiAgbWV0cmljU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5KHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG59XG5cbi8qKlxuICogUmVmZXJlbmNlIHRvIGEgZHluYW1vZGIgdGFibGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVBdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGR5bmFtb2RiIHRhYmxlLlxuICAgKiBPbmUgb2YgdGhpcywgb3Ige0BsaW5rIHRhYmxlTmFtZX0sIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRhYmxlIGFyblxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0YWJsZSBuYW1lIG9mIHRoZSBkeW5hbW9kYiB0YWJsZS5cbiAgICogT25lIG9mIHRoaXMsIG9yIHtAbGluayB0YWJsZUFybn0sIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRhYmxlIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgdGFibGUncyBzdHJlYW0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gdGFibGUgc3RyZWFtXG4gICAqL1xuICByZWFkb25seSB0YWJsZVN0cmVhbUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogS01TIGVuY3J5cHRpb24ga2V5LCBpZiB0aGlzIHRhYmxlIHVzZXMgYSBjdXN0b21lci1tYW5hZ2VkIGVuY3J5cHRpb24ga2V5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZ2xvYmFsIGluZGV4ZXMgc2V0IGZvciB0aGlzIFRhYmxlLlxuICAgKiBOb3RlIHRoYXQgeW91IG5lZWQgdG8gc2V0IGVpdGhlciB0aGlzIHByb3BlcnR5LFxuICAgKiBvciB7QGxpbmsgbG9jYWxJbmRleGVzfSxcbiAgICogaWYgeW91IHdhbnQgbWV0aG9kcyBsaWtlIGdyYW50UmVhZERhdGEoKVxuICAgKiB0byBncmFudCBwZXJtaXNzaW9ucyBmb3IgaW5kZXhlcyBhcyB3ZWxsIGFzIHRoZSB0YWJsZSBpdHNlbGYuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gZ2xvYmFsIGluZGV4ZXNcbiAgICovXG4gIHJlYWRvbmx5IGdsb2JhbEluZGV4ZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGxvY2FsIGluZGV4ZXMgc2V0IGZvciB0aGlzIFRhYmxlLlxuICAgKiBOb3RlIHRoYXQgeW91IG5lZWQgdG8gc2V0IGVpdGhlciB0aGlzIHByb3BlcnR5LFxuICAgKiBvciB7QGxpbmsgZ2xvYmFsSW5kZXhlc30sXG4gICAqIGlmIHlvdSB3YW50IG1ldGhvZHMgbGlrZSBncmFudFJlYWREYXRhKClcbiAgICogdG8gZ3JhbnQgcGVybWlzc2lvbnMgZm9yIGluZGV4ZXMgYXMgd2VsbCBhcyB0aGUgdGFibGUgaXRzZWxmLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGxvY2FsIGluZGV4ZXNcbiAgICovXG4gIHJlYWRvbmx5IGxvY2FsSW5kZXhlcz86IHN0cmluZ1tdO1xufVxuXG5hYnN0cmFjdCBjbGFzcyBUYWJsZUJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElUYWJsZSB7XG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEtNUyBlbmNyeXB0aW9uIGtleSwgaWYgdGhpcyB0YWJsZSB1c2VzIGEgY3VzdG9tZXItbWFuYWdlZCBlbmNyeXB0aW9uIGtleS5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlZ2lvbmFsQXJucyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgdG8gYW4gSUFNXG4gICAqIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpQdXRJdGVtXCIsIFwiZHluYW1vZGI6R2V0SXRlbVwiLCAuLi4pXG4gICAqL1xuICBwdWJsaWMgZ3JhbnQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbXG4gICAgICAgIHRoaXMudGFibGVBcm4sXG4gICAgICAgIExhenkuc3RyaW5nKHsgcHJvZHVjZTogKCkgPT4gdGhpcy5oYXNJbmRleCA/IGAke3RoaXMudGFibGVBcm59L2luZGV4LypgIDogQXdzLk5PX1ZBTFVFIH0pLFxuICAgICAgICAuLi50aGlzLnJlZ2lvbmFsQXJucyxcbiAgICAgICAgLi4udGhpcy5yZWdpb25hbEFybnMubWFwKGFybiA9PiBMYXp5LnN0cmluZyh7XG4gICAgICAgICAgcHJvZHVjZTogKCkgPT4gdGhpcy5oYXNJbmRleCA/IGAke2Fybn0vaW5kZXgvKmAgOiBBd3MuTk9fVkFMVUUsXG4gICAgICAgIH0pKSxcbiAgICAgIF0sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIElBTSBwb2xpY3kgc3RhdGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhYmxlJ3Mgc3RyZWFtIHRvIGFuXG4gICAqIElBTSBwcmluY2lwYWwncyBwb2xpY3kuXG4gICAqXG4gICAqIElmIGBlbmNyeXB0aW9uS2V5YCBpcyBwcmVzZW50LCBhcHByb3ByaWF0ZSBncmFudHMgdG8gdGhlIGtleSBuZWVkcyB0byBiZSBhZGRlZFxuICAgKiBzZXBhcmF0ZWx5IHVzaW5nIHRoZSBgdGFibGUuZW5jcnlwdGlvbktleS5ncmFudCpgIG1ldGhvZHMuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICogQHBhcmFtIGFjdGlvbnMgVGhlIHNldCBvZiBhY3Rpb25zIHRvIGFsbG93IChpLmUuIFwiZHluYW1vZGI6RGVzY3JpYmVTdHJlYW1cIiwgXCJkeW5hbW9kYjpHZXRSZWNvcmRzXCIsIC4uLilcbiAgICovXG4gIHB1YmxpYyBncmFudFN0cmVhbShncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQge1xuICAgIGlmICghdGhpcy50YWJsZVN0cmVhbUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBEeW5hbW9EQiBTdHJlYW1zIG11c3QgYmUgZW5hYmxlZCBvbiB0aGUgdGFibGUgJHt0aGlzLm5vZGUucGF0aH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbdGhpcy50YWJsZVN0cmVhbUFybl0sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgcmVhZCBvcGVyYXRpb25zIGZyb20gdGhpcyB0YWJsZTpcbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2NhbiwgRGVzY3JpYmVUYWJsZS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFJlYWREYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCB0YWJsZUFjdGlvbnMgPSBwZXJtcy5SRUFEX0RBVEFfQUNUSU9OUy5jb25jYXQocGVybXMuREVTQ1JJQkVfVEFCTEUpO1xuICAgIHJldHVybiB0aGlzLmNvbWJpbmVkR3JhbnQoZ3JhbnRlZSwgeyBrZXlBY3Rpb25zOiBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLCB0YWJsZUFjdGlvbnMgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGVybWl0cyBhbiBJQU0gUHJpbmNpcGFsIHRvIGxpc3Qgc3RyZWFtcyBhdHRhY2hlZCB0byBjdXJyZW50IGR5bmFtb2RiIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIChuby1vcCBpZiB1bmRlZmluZWQpXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRUYWJsZUxpc3RTdHJlYW1zKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBpZiAoIXRoaXMudGFibGVTdHJlYW1Bcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRHluYW1vREIgU3RyZWFtcyBtdXN0IGJlIGVuYWJsZWQgb24gdGhlIHRhYmxlICR7dGhpcy5ub2RlLnBhdGh9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogWydkeW5hbW9kYjpMaXN0U3RyZWFtcyddLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbJyonXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIHN0cmVhbSBkYXRhIHJlYWQgb3BlcmF0aW9ucyBmb3IgdGhpc1xuICAgKiB0YWJsZSdzIHN0cmVhbTpcbiAgICogRGVzY3JpYmVTdHJlYW0sIEdldFJlY29yZHMsIEdldFNoYXJkSXRlcmF0b3IsIExpc3RTdHJlYW1zLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgcHVibGljIGdyYW50U3RyZWFtUmVhZChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgdGhpcy5ncmFudFRhYmxlTGlzdFN0cmVhbXMoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7IGtleUFjdGlvbnM6IHBlcm1zLktFWV9SRUFEX0FDVElPTlMsIHN0cmVhbUFjdGlvbnM6IHBlcm1zLlJFQURfU1RSRUFNX0RBVEFfQUNUSU9OUyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgd3JpdGUgb3BlcmF0aW9ucyB0byB0aGlzIHRhYmxlOlxuICAgKiBCYXRjaFdyaXRlSXRlbSwgUHV0SXRlbSwgVXBkYXRlSXRlbSwgRGVsZXRlSXRlbSwgRGVzY3JpYmVUYWJsZS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFdyaXRlRGF0YShncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgY29uc3QgdGFibGVBY3Rpb25zID0gcGVybXMuV1JJVEVfREFUQV9BQ1RJT05TLmNvbmNhdChwZXJtcy5ERVNDUklCRV9UQUJMRSk7XG4gICAgY29uc3Qga2V5QWN0aW9ucyA9IHBlcm1zLktFWV9SRUFEX0FDVElPTlMuY29uY2F0KHBlcm1zLktFWV9XUklURV9BQ1RJT05TKTtcbiAgICByZXR1cm4gdGhpcy5jb21iaW5lZEdyYW50KGdyYW50ZWUsIHsga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYW4gSUFNIHByaW5jaXBhbCB0byBhbGwgZGF0YSByZWFkL3dyaXRlIG9wZXJhdGlvbnMgdG8gdGhpcyB0YWJsZS5cbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2NhbixcbiAgICogQmF0Y2hXcml0ZUl0ZW0sIFB1dEl0ZW0sIFVwZGF0ZUl0ZW0sIERlbGV0ZUl0ZW0sIERlc2NyaWJlVGFibGVcbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFJlYWRXcml0ZURhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHRhYmxlQWN0aW9ucyA9IHBlcm1zLlJFQURfREFUQV9BQ1RJT05TLmNvbmNhdChwZXJtcy5XUklURV9EQVRBX0FDVElPTlMpLmNvbmNhdChwZXJtcy5ERVNDUklCRV9UQUJMRSk7XG4gICAgY29uc3Qga2V5QWN0aW9ucyA9IHBlcm1zLktFWV9SRUFEX0FDVElPTlMuY29uY2F0KHBlcm1zLktFWV9XUklURV9BQ1RJT05TKTtcbiAgICByZXR1cm4gdGhpcy5jb21iaW5lZEdyYW50KGdyYW50ZWUsIHsga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYWxsIER5bmFtb0RCIG9wZXJhdGlvbnMgKFwiZHluYW1vZGI6KlwiKSB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgcHVibGljIGdyYW50RnVsbEFjY2VzcyhncmFudGVlOiBpYW0uSUdyYW50YWJsZSkge1xuICAgIGNvbnN0IGtleUFjdGlvbnMgPSBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLmNvbmNhdChwZXJtcy5LRVlfV1JJVEVfQUNUSU9OUyk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7IGtleUFjdGlvbnMsIHRhYmxlQWN0aW9uczogWydkeW5hbW9kYjoqJ10gfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBnaXZlbiBuYW1lZCBtZXRyaWMgZm9yIHRoaXMgVGFibGVcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpYyhtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbmFtZXNwYWNlOiAnQVdTL0R5bmFtb0RCJyxcbiAgICAgIG1ldHJpY05hbWUsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSkuYXR0YWNoVG8odGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgY29uc3VtZWQgcmVhZCBjYXBhY2l0eSB1bml0cyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHRoZSBtZXRyaWMgd2lsbCBiZSBjYWxjdWxhdGVkIGFzIGEgc3VtIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDb25zdW1lZFJlYWRDYXBhY2l0eVVuaXRzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhEeW5hbW9EQk1ldHJpY3MuY29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0c1N1bSwgcHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbnN1bWVkIHdyaXRlIGNhcGFjaXR5IHVuaXRzIHRoaXMgdGFibGVcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY0NvbnN1bWVkV3JpdGVDYXBhY2l0eVVuaXRzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhEeW5hbW9EQk1ldHJpY3MuY29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHNTdW0sIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzeXN0ZW0gZXJyb3JzIHRoaXMgdGFibGVcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zYC5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNTeXN0ZW1FcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKCFwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uICYmICFwcm9wcz8uZGltZW5zaW9uc01hcD8uT3BlcmF0aW9uKSB7XG4gICAgICAvLyAnT3BlcmF0aW9uJyBtdXN0IGJlIHBhc3NlZCBiZWNhdXNlIGl0cyBhbiBvcGVyYXRpb25hbCBtZXRyaWMuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3lzdGVtRXJyb3JzJyBtZXRyaWMuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgLi4ucHJvcHM/LmRpbWVuc2lvbnMgPz8ge30sXG4gICAgICAuLi5wcm9wcz8uZGltZW5zaW9uc01hcCA/PyB7fSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdTeXN0ZW1FcnJvcnMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzLCBkaW1lbnNpb25zTWFwIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHVzZXIgZXJyb3JzLiBOb3RlIHRoYXQgdGhpcyBtZXRyaWMgcmVwb3J0cyB1c2VyIGVycm9ycyBhY3Jvc3MgYWxsXG4gICAqIHRoZSB0YWJsZXMgaW4gdGhlIGFjY291bnQgYW5kIHJlZ2lvbiB0aGUgdGFibGUgcmVzaWRlcyBpbi5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1VzZXJFcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKHByb3BzPy5kaW1lbnNpb25zKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInZGltZW5zaW9ucycgaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhlICdVc2VyRXJyb3JzJyBtZXRyaWNcIik7XG4gICAgfVxuXG4gICAgLy8gb3ZlcnJpZGluZyAnZGltZW5zaW9ucycgaGVyZSBiZWNhdXNlIHRoaXMgbWV0cmljIGlzIGFuIGFjY291bnQgbWV0cmljLlxuICAgIC8vIHNlZSAnVXNlckVycm9ycycgaW4gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9tZXRyaWNzLWRpbWVuc2lvbnMuaHRtbFxuICAgIHJldHVybiB0aGlzLm1ldHJpYygnVXNlckVycm9ycycsIHsgc3RhdGlzdGljOiAnc3VtJywgLi4ucHJvcHMsIGRpbWVuc2lvbnNNYXA6IHt9IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbmRpdGlvbmFsIGNoZWNrIGZhaWxlZCByZXF1ZXN0cyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHRoZSBtZXRyaWMgd2lsbCBiZSBjYWxjdWxhdGVkIGFzIGEgc3VtIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDb25kaXRpb25hbENoZWNrRmFpbGVkUmVxdWVzdHMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdDb25kaXRpb25hbENoZWNrRmFpbGVkUmVxdWVzdHMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IHJlcXVlc3RzIGFyZSB0aHJvdHRsZWQgb24gdGhpcyB0YWJsZVxuICAgKlxuICAgKiBEZWZhdWx0OiBzdW0gb3ZlciA1IG1pbnV0ZXNcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgRG8gbm90IHVzZSB0aGlzIGZ1bmN0aW9uLiBJdCByZXR1cm5zIGFuIGludmFsaWQgbWV0cmljLiBVc2UgYG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzRm9yT3BlcmF0aW9uYCBpbnN0ZWFkLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYygnVGhyb3R0bGVkUmVxdWVzdHMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IHJlcXVlc3RzIGFyZSB0aHJvdHRsZWQgb24gdGhpcyB0YWJsZSwgZm9yIHRoZSBnaXZlbiBvcGVyYXRpb25cbiAgICpcbiAgICogRGVmYXVsdDogc3VtIG92ZXIgNSBtaW51dGVzXG4gICAqL1xuICBwdWJsaWMgbWV0cmljVGhyb3R0bGVkUmVxdWVzdHNGb3JPcGVyYXRpb24ob3BlcmF0aW9uOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgLi4uRHluYW1vREJNZXRyaWNzLnRocm90dGxlZFJlcXVlc3RzU3VtKHsgT3BlcmF0aW9uOiBvcGVyYXRpb24sIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUgfSksXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzdWNjZXNzZnVsIHJlcXVlc3QgbGF0ZW5jeSB0aGlzIHRhYmxlLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgbWV0cmljIHdpbGwgYmUgY2FsY3VsYXRlZCBhcyBhbiBhdmVyYWdlIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3kocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKCFwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uICYmICFwcm9wcz8uZGltZW5zaW9uc01hcD8uT3BlcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5JyBtZXRyaWMuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgT3BlcmF0aW9uOiBwcm9wcy5kaW1lbnNpb25zTWFwPy5PcGVyYXRpb24gPz8gcHJvcHMuZGltZW5zaW9ucz8uT3BlcmF0aW9uLFxuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIC4uLkR5bmFtb0RCTWV0cmljcy5zdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lBdmVyYWdlKGRpbWVuc2lvbnNNYXApLFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBkaW1lbnNpb25zTWFwLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHN5c3RlbSBlcnJvcnMgdGhpcyB0YWJsZS5cbiAgICpcbiAgICogVGhpcyB3aWxsIHN1bSBlcnJvcnMgYWNyb3NzIGFsbCBwb3NzaWJsZSBvcGVyYXRpb25zLlxuICAgKiBOb3RlIHRoYXQgYnkgZGVmYXVsdCwgZWFjaCBpbmRpdmlkdWFsIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1N5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnMocHJvcHM/OiBTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guSU1ldHJpYyB7XG5cbiAgICBpZiAocHJvcHM/LmRpbWVuc2lvbnM/Lk9wZXJhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIE9wZXJhdGlvbiBkaW1lbnNpb24gaXMgbm90IHN1cHBvcnRlZC4gVXNlIHRoZSAnb3BlcmF0aW9ucycgcHJvcGVydHkuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBwcm9wcz8ub3BlcmF0aW9ucyA/PyBPYmplY3QudmFsdWVzKE9wZXJhdGlvbik7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSB0aGlzLmNyZWF0ZU1ldHJpY3NGb3JPcGVyYXRpb25zKCdTeXN0ZW1FcnJvcnMnLCBvcGVyYXRpb25zLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuXG4gICAgY29uc3Qgc3VtID0gbmV3IGNsb3Vkd2F0Y2guTWF0aEV4cHJlc3Npb24oe1xuICAgICAgZXhwcmVzc2lvbjogYCR7T2JqZWN0LmtleXModmFsdWVzKS5qb2luKCcgKyAnKX1gLFxuICAgICAgdXNpbmdNZXRyaWNzOiB7IC4uLnZhbHVlcyB9LFxuICAgICAgY29sb3I6IHByb3BzPy5jb2xvcixcbiAgICAgIGxhYmVsOiAnU3VtIG9mIGVycm9ycyBhY3Jvc3MgYWxsIG9wZXJhdGlvbnMnLFxuICAgICAgcGVyaW9kOiBwcm9wcz8ucGVyaW9kLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHN1bTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBtYXAgb2YgbWV0cmljcyB0aGF0IGNhbiBiZSB1c2VkIGluIGEgbWF0aCBleHByZXNzaW9uLlxuICAgKlxuICAgKiBVc2luZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoaXMgZnVuY3Rpb24gYXMgdGhlIGB1c2luZ01ldHJpY3NgIHByb3BlcnR5IGluIGBjbG91ZHdhdGNoLk1hdGhFeHByZXNzaW9uYCBhbGxvd3MgeW91IHRvXG4gICAqIHVzZSB0aGUga2V5cyBvZiB0aGlzIG1hcCBhcyBtZXRyaWMgbmFtZXMgaW5zaWRlIHlvdSBleHByZXNzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0cmljTmFtZSBUaGUgbWV0cmljIG5hbWUuXG4gICAqIEBwYXJhbSBvcGVyYXRpb25zIFRoZSBsaXN0IG9mIG9wZXJhdGlvbnMgdG8gY3JlYXRlIG1ldHJpY3MgZm9yLlxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgdGhlIGluZGl2aWR1YWwgbWV0cmljcy5cbiAgICogQHBhcmFtIG1ldHJpY05hbWVNYXBwZXIgTWFwcGVyIGZ1bmN0aW9uIHRvIGFsbG93IGNvbnRyb2xsaW5nIHRoZSBpbmRpdmlkdWFsIG1ldHJpYyBuYW1lIHBlciBvcGVyYXRpb24uXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZU1ldHJpY3NGb3JPcGVyYXRpb25zKG1ldHJpY05hbWU6IHN0cmluZywgb3BlcmF0aW9uczogT3BlcmF0aW9uW10sXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMsIG1ldHJpY05hbWVNYXBwZXI/OiAob3A6IE9wZXJhdGlvbikgPT4gc3RyaW5nKTogUmVjb3JkPHN0cmluZywgY2xvdWR3YXRjaC5JTWV0cmljPiB7XG5cbiAgICBjb25zdCBtZXRyaWNzOiBSZWNvcmQ8c3RyaW5nLCBjbG91ZHdhdGNoLklNZXRyaWM+ID0ge307XG5cbiAgICBjb25zdCBtYXBwZXIgPSBtZXRyaWNOYW1lTWFwcGVyID8/IChvcCA9PiBvcC50b0xvd2VyQ2FzZSgpKTtcblxuICAgIGlmIChwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcHJvcGVydGllcy4gT3BlcmF0aW9uIGRpbWVuc2lvbiBpcyBub3Qgc3VwcG9ydGVkIHdoZW4gY2FsY3VsYXRpbmcgb3BlcmF0aW9uYWwgbWV0cmljcycpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcblxuICAgICAgY29uc3QgbWV0cmljID0gdGhpcy5tZXRyaWMobWV0cmljTmFtZSwge1xuICAgICAgICAuLi5wcm9wcyxcbiAgICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICAgICAgT3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgICAgLi4ucHJvcHM/LmRpbWVuc2lvbnMsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgb3BlcmF0aW9uTWV0cmljTmFtZSA9IG1hcHBlcihvcGVyYXRpb24pO1xuICAgICAgY29uc3QgZmlyc3RDaGFyID0gb3BlcmF0aW9uTWV0cmljTmFtZS5jaGFyQXQoMCk7XG5cbiAgICAgIGlmIChmaXJzdENoYXIgPT09IGZpcnN0Q2hhci50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL3VzaW5nLW1ldHJpYy1tYXRoLmh0bWwjbWV0cmljLW1hdGgtc3ludGF4XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTWFwcGVyIGdlbmVyYXRlZCBhbiBpbGxlZ2FsIG9wZXJhdGlvbiBtZXRyaWMgbmFtZTogJHtvcGVyYXRpb25NZXRyaWNOYW1lfS4gTXVzdCBzdGFydCB3aXRoIGEgbG93ZXJjYXNlIGxldHRlcmApO1xuICAgICAgfVxuXG4gICAgICBtZXRyaWNzW29wZXJhdGlvbk1ldHJpY05hbWVdID0gbWV0cmljO1xuICAgIH1cblxuICAgIHJldHVybiBtZXRyaWNzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGdldCBoYXNJbmRleCgpOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBZGRzIGFuIElBTSBwb2xpY3kgc3RhdGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhYmxlIHRvIGFuIElBTVxuICAgKiBwcmluY2lwYWwncyBwb2xpY3kuXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICogQHBhcmFtIG9wdHMgT3B0aW9ucyBmb3Iga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIGFuZCBzdHJlYW1BY3Rpb25zXG4gICAqL1xuICBwcml2YXRlIGNvbWJpbmVkR3JhbnQoXG4gICAgZ3JhbnRlZTogaWFtLklHcmFudGFibGUsXG4gICAgb3B0czogeyBrZXlBY3Rpb25zPzogc3RyaW5nW10sIHRhYmxlQWN0aW9ucz86IHN0cmluZ1tdLCBzdHJlYW1BY3Rpb25zPzogc3RyaW5nW10gfSxcbiAgKTogaWFtLkdyYW50IHtcbiAgICBpZiAob3B0cy50YWJsZUFjdGlvbnMpIHtcbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFt0aGlzLnRhYmxlQXJuLFxuICAgICAgICBMYXp5LnN0cmluZyh7IHByb2R1Y2U6ICgpID0+IHRoaXMuaGFzSW5kZXggPyBgJHt0aGlzLnRhYmxlQXJufS9pbmRleC8qYCA6IEF3cy5OT19WQUxVRSB9KSxcbiAgICAgICAgLi4udGhpcy5yZWdpb25hbEFybnMsXG4gICAgICAgIC4uLnRoaXMucmVnaW9uYWxBcm5zLm1hcChhcm4gPT4gTGF6eS5zdHJpbmcoe1xuICAgICAgICAgIHByb2R1Y2U6ICgpID0+IHRoaXMuaGFzSW5kZXggPyBgJHthcm59L2luZGV4LypgIDogQXdzLk5PX1ZBTFVFLFxuICAgICAgICB9KSldO1xuICAgICAgY29uc3QgcmV0ID0gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgICAgZ3JhbnRlZSxcbiAgICAgICAgYWN0aW9uczogb3B0cy50YWJsZUFjdGlvbnMsXG4gICAgICAgIHJlc291cmNlQXJuczogcmVzb3VyY2VzLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgIH0pO1xuICAgICAgaWYgKHRoaXMuZW5jcnlwdGlvbktleSAmJiBvcHRzLmtleUFjdGlvbnMpIHtcbiAgICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50KGdyYW50ZWUsIC4uLm9wdHMua2V5QWN0aW9ucyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICBpZiAob3B0cy5zdHJlYW1BY3Rpb25zKSB7XG4gICAgICBpZiAoIXRoaXMudGFibGVTdHJlYW1Bcm4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEeW5hbW9EQiBTdHJlYW1zIG11c3QgYmUgZW5hYmxlZCBvbiB0aGUgdGFibGUgJHt0aGlzLm5vZGUucGF0aH1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFt0aGlzLnRhYmxlU3RyZWFtQXJuXTtcbiAgICAgIGNvbnN0IHJldCA9IGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICAgIGdyYW50ZWUsXG4gICAgICAgIGFjdGlvbnM6IG9wdHMuc3RyZWFtQWN0aW9ucyxcbiAgICAgICAgcmVzb3VyY2VBcm5zOiByZXNvdXJjZXMsXG4gICAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgJ2FjdGlvbicsICR7b3B0cy50YWJsZUFjdGlvbnMgfHwgb3B0cy5zdHJlYW1BY3Rpb25zfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5uZWRNZXRyaWMoXG4gICAgZm46IChkaW1zOiB7IFRhYmxlTmFtZTogc3RyaW5nIH0pID0+IGNsb3Vkd2F0Y2guTWV0cmljUHJvcHMsXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAuLi5mbih7IFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUgfSksXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3ZpZGVzIGEgRHluYW1vREIgdGFibGUuXG4gKi9cbmV4cG9ydCBjbGFzcyBUYWJsZSBleHRlbmRzIFRhYmxlQmFzZSB7XG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBQcmluY2lwYWwgdG8gbGlzdCBhbGwgRHluYW1vREIgU3RyZWFtcy5cbiAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZ3JhbnRUYWJsZUxpc3RTdHJlYW1zfSBmb3IgbW9yZSBncmFudWxhciBwZXJtaXNzaW9uXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ3JhbnRMaXN0U3RyZWFtcyhncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgcmV0dXJuIGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogWydkeW5hbW9kYjpMaXN0U3RyZWFtcyddLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbJyonXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgVGFibGUgY29uc3RydWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCB0YWJsZSB2aWEgdGFibGUgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBwYXJlbnQgY3JlYXRpbmcgY29uc3RydWN0ICh1c3VhbGx5IGB0aGlzYCkuXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0J3MgbmFtZS5cbiAgICogQHBhcmFtIHRhYmxlTmFtZSBUaGUgdGFibGUncyBuYW1lLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tVGFibGVOYW1lKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHRhYmxlTmFtZTogc3RyaW5nKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVOYW1lIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBUYWJsZSBjb25zdHJ1Y3QgdGhhdCByZXByZXNlbnRzIGFuIGV4dGVybmFsIHRhYmxlIHZpYSB0YWJsZSBhcm4uXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSB0YWJsZUFybiBUaGUgdGFibGUncyBBUk4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21UYWJsZUFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCB0YWJsZUFybjogc3RyaW5nKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVBcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIFRhYmxlIGNvbnN0cnVjdCB0aGF0IHJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgdGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSBhdHRycyBBIGBUYWJsZUF0dHJpYnV0ZXNgIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogVGFibGVBdHRyaWJ1dGVzKTogSVRhYmxlIHtcblxuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFRhYmxlQmFzZSB7XG5cbiAgICAgIHB1YmxpYyByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZztcbiAgICAgIHB1YmxpYyByZWFkb25seSB0YWJsZUFybjogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHRhYmxlU3RyZWFtQXJuPzogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcbiAgICAgIHByb3RlY3RlZCByZWFkb25seSBoYXNJbmRleCA9IChhdHRycy5nbG9iYWxJbmRleGVzID8/IFtdKS5sZW5ndGggPiAwIHx8XG4gICAgICAgIChhdHRycy5sb2NhbEluZGV4ZXMgPz8gW10pLmxlbmd0aCA+IDA7XG5cbiAgICAgIGNvbnN0cnVjdG9yKF90YWJsZUFybjogc3RyaW5nLCB0YWJsZU5hbWU6IHN0cmluZywgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICAgICAgdGhpcy50YWJsZUFybiA9IF90YWJsZUFybjtcbiAgICAgICAgdGhpcy50YWJsZU5hbWUgPSB0YWJsZU5hbWU7XG4gICAgICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSB0YWJsZVN0cmVhbUFybjtcbiAgICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gYXR0cnMuZW5jcnlwdGlvbktleTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbmFtZTogc3RyaW5nO1xuICAgIGxldCBhcm46IHN0cmluZztcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHNjb3BlKTtcbiAgICBpZiAoIWF0dHJzLnRhYmxlTmFtZSkge1xuICAgICAgaWYgKCFhdHRycy50YWJsZUFybikgeyB0aHJvdyBuZXcgRXJyb3IoJ09uZSBvZiB0YWJsZU5hbWUgb3IgdGFibGVBcm4gaXMgcmVxdWlyZWQhJyk7IH1cblxuICAgICAgYXJuID0gYXR0cnMudGFibGVBcm47XG4gICAgICBjb25zdCBtYXliZVRhYmxlTmFtZSA9IHN0YWNrLnNwbGl0QXJuKGF0dHJzLnRhYmxlQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lO1xuICAgICAgaWYgKCFtYXliZVRhYmxlTmFtZSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0FSTiBmb3IgRHluYW1vREIgdGFibGUgbXVzdCBiZSBpbiB0aGUgZm9ybTogLi4uJyk7IH1cbiAgICAgIG5hbWUgPSBtYXliZVRhYmxlTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGF0dHJzLnRhYmxlQXJuKSB7IHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgdGFibGVBcm4gb3IgdGFibGVOYW1lIGNhbiBiZSBwcm92aWRlZCcpOyB9XG4gICAgICBuYW1lID0gYXR0cnMudGFibGVOYW1lO1xuICAgICAgYXJuID0gc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgc2VydmljZTogJ2R5bmFtb2RiJyxcbiAgICAgICAgcmVzb3VyY2U6ICd0YWJsZScsXG4gICAgICAgIHJlc291cmNlTmFtZTogYXR0cnMudGFibGVOYW1lLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoYXJuLCBuYW1lLCBhdHRycy50YWJsZVN0cmVhbUFybik7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm46IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlOiBDZm5UYWJsZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGtleVNjaGVtYSA9IG5ldyBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhdHRyaWJ1dGVEZWZpbml0aW9ucyA9IG5ldyBBcnJheTxDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlcyA9IG5ldyBBcnJheTxDZm5UYWJsZS5HbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvY2FsU2Vjb25kYXJ5SW5kZXhlcyA9IG5ldyBBcnJheTxDZm5UYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHk+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZWNvbmRhcnlJbmRleFNjaGVtYXMgPSBuZXcgTWFwPHN0cmluZywgU2NoZW1hT3B0aW9ucz4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBub25LZXlBdHRyaWJ1dGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZVBhcnRpdGlvbktleTogQXR0cmlidXRlO1xuICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlU29ydEtleT86IEF0dHJpYnV0ZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZTtcbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZVNjYWxpbmc6IFNjYWxhYmxlQXR0cmlidXRlUGFpciA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IGluZGV4U2NhbGluZyA9IG5ldyBNYXA8c3RyaW5nLCBTY2FsYWJsZUF0dHJpYnV0ZVBhaXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2NhbGluZ1JvbGU6IGlhbS5JUm9sZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMgPSBuZXcgQXJyYXk8Q3VzdG9tUmVzb3VyY2U+KCk7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFRhYmxlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMudGFibGVOYW1lLFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyBzc2VTcGVjaWZpY2F0aW9uLCBlbmNyeXB0aW9uS2V5IH0gPSB0aGlzLnBhcnNlRW5jcnlwdGlvbihwcm9wcyk7XG5cbiAgICBsZXQgc3RyZWFtU3BlY2lmaWNhdGlvbjogQ2ZuVGFibGUuU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5IHwgdW5kZWZpbmVkO1xuICAgIGlmIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMpIHtcbiAgICAgIGlmIChwcm9wcy5zdHJlYW0gJiYgcHJvcHMuc3RyZWFtICE9PSBTdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdgc3RyZWFtYCBtdXN0IGJlIHNldCB0byBgTkVXX0FORF9PTERfSU1BR0VTYCB3aGVuIHNwZWNpZnlpbmcgYHJlcGxpY2F0aW9uUmVnaW9uc2AnKTtcbiAgICAgIH1cbiAgICAgIHN0cmVhbVNwZWNpZmljYXRpb24gPSB7IHN0cmVhbVZpZXdUeXBlOiBTdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMgfTtcblxuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9IHByb3BzLmJpbGxpbmdNb2RlID8/IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9IHByb3BzLmJpbGxpbmdNb2RlID8/IEJpbGxpbmdNb2RlLlBST1ZJU0lPTkVEO1xuICAgICAgaWYgKHByb3BzLnN0cmVhbSkge1xuICAgICAgICBzdHJlYW1TcGVjaWZpY2F0aW9uID0geyBzdHJlYW1WaWV3VHlwZTogcHJvcHMuc3RyZWFtIH07XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudmFsaWRhdGVQcm92aXNpb25pbmcocHJvcHMpO1xuXG4gICAgdGhpcy50YWJsZSA9IG5ldyBDZm5UYWJsZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICB0YWJsZU5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAga2V5U2NoZW1hOiB0aGlzLmtleVNjaGVtYSxcbiAgICAgIGF0dHJpYnV0ZURlZmluaXRpb25zOiB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zLFxuICAgICAgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMgfSwgeyBvbWl0RW1wdHlBcnJheTogdHJ1ZSB9KSxcbiAgICAgIGxvY2FsU2Vjb25kYXJ5SW5kZXhlczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmxvY2FsU2Vjb25kYXJ5SW5kZXhlcyB9LCB7IG9taXRFbXB0eUFycmF5OiB0cnVlIH0pLFxuICAgICAgcG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb246IHByb3BzLnBvaW50SW5UaW1lUmVjb3ZlcnkgIT0gbnVsbCA/IHsgcG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQ6IHByb3BzLnBvaW50SW5UaW1lUmVjb3ZlcnkgfSA6IHVuZGVmaW5lZCxcbiAgICAgIGJpbGxpbmdNb2RlOiB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QgPyB0aGlzLmJpbGxpbmdNb2RlIDogdW5kZWZpbmVkLFxuICAgICAgcHJvdmlzaW9uZWRUaHJvdWdocHV0OiB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QgPyB1bmRlZmluZWQgOiB7XG4gICAgICAgIHJlYWRDYXBhY2l0eVVuaXRzOiBwcm9wcy5yZWFkQ2FwYWNpdHkgfHwgNSxcbiAgICAgICAgd3JpdGVDYXBhY2l0eVVuaXRzOiBwcm9wcy53cml0ZUNhcGFjaXR5IHx8IDUsXG4gICAgICB9LFxuICAgICAgc3NlU3BlY2lmaWNhdGlvbixcbiAgICAgIHN0cmVhbVNwZWNpZmljYXRpb24sXG4gICAgICB0YWJsZUNsYXNzOiBwcm9wcy50YWJsZUNsYXNzLFxuICAgICAgdGltZVRvTGl2ZVNwZWNpZmljYXRpb246IHByb3BzLnRpbWVUb0xpdmVBdHRyaWJ1dGUgPyB7IGF0dHJpYnV0ZU5hbWU6IHByb3BzLnRpbWVUb0xpdmVBdHRyaWJ1dGUsIGVuYWJsZWQ6IHRydWUgfSA6IHVuZGVmaW5lZCxcbiAgICAgIGNvbnRyaWJ1dG9ySW5zaWdodHNTcGVjaWZpY2F0aW9uOiBwcm9wcy5jb250cmlidXRvckluc2lnaHRzRW5hYmxlZCAhPT0gdW5kZWZpbmVkID8geyBlbmFibGVkOiBwcm9wcy5jb250cmlidXRvckluc2lnaHRzRW5hYmxlZCB9IDogdW5kZWZpbmVkLFxuICAgICAga2luZXNpc1N0cmVhbVNwZWNpZmljYXRpb246IHByb3BzLmtpbmVzaXNTdHJlYW0gPyB7IHN0cmVhbUFybjogcHJvcHMua2luZXNpc1N0cmVhbS5zdHJlYW1Bcm4gfSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICB0aGlzLnRhYmxlLmFwcGx5UmVtb3ZhbFBvbGljeShwcm9wcy5yZW1vdmFsUG9saWN5KTtcblxuICAgIHRoaXMuZW5jcnlwdGlvbktleSA9IGVuY3J5cHRpb25LZXk7XG5cbiAgICB0aGlzLnRhYmxlQXJuID0gdGhpcy5nZXRSZXNvdXJjZUFybkF0dHJpYnV0ZSh0aGlzLnRhYmxlLmF0dHJBcm4sIHtcbiAgICAgIHNlcnZpY2U6ICdkeW5hbW9kYicsXG4gICAgICByZXNvdXJjZTogJ3RhYmxlJyxcbiAgICAgIHJlc291cmNlTmFtZTogdGhpcy5waHlzaWNhbE5hbWUsXG4gICAgfSk7XG4gICAgdGhpcy50YWJsZU5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZSh0aGlzLnRhYmxlLnJlZik7XG5cbiAgICBpZiAocHJvcHMudGFibGVOYW1lKSB7IHRoaXMubm9kZS5hZGRNZXRhZGF0YSgnYXdzOmNkazpoYXNQaHlzaWNhbE5hbWUnLCB0aGlzLnRhYmxlTmFtZSk7IH1cblxuICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSBzdHJlYW1TcGVjaWZpY2F0aW9uID8gdGhpcy50YWJsZS5hdHRyU3RyZWFtQXJuIDogdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5zY2FsaW5nUm9sZSA9IHRoaXMubWFrZVNjYWxpbmdSb2xlKCk7XG5cbiAgICB0aGlzLmFkZEtleShwcm9wcy5wYXJ0aXRpb25LZXksIEhBU0hfS0VZX1RZUEUpO1xuICAgIHRoaXMudGFibGVQYXJ0aXRpb25LZXkgPSBwcm9wcy5wYXJ0aXRpb25LZXk7XG5cbiAgICBpZiAocHJvcHMuc29ydEtleSkge1xuICAgICAgdGhpcy5hZGRLZXkocHJvcHMuc29ydEtleSwgUkFOR0VfS0VZX1RZUEUpO1xuICAgICAgdGhpcy50YWJsZVNvcnRLZXkgPSBwcm9wcy5zb3J0S2V5O1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMgJiYgcHJvcHMucmVwbGljYXRpb25SZWdpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuY3JlYXRlUmVwbGljYVRhYmxlcyhwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMsIHByb3BzLnJlcGxpY2F0aW9uVGltZW91dCwgcHJvcHMud2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4IG9mIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgdGhlIHByb3BlcnR5IG9mIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXhcbiAgICovXG4gIHB1YmxpYyBhZGRHbG9iYWxTZWNvbmRhcnlJbmRleChwcm9wczogR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wcykge1xuICAgIHRoaXMudmFsaWRhdGVQcm92aXNpb25pbmcocHJvcHMpO1xuICAgIHRoaXMudmFsaWRhdGVJbmRleE5hbWUocHJvcHMuaW5kZXhOYW1lKTtcblxuICAgIC8vIGJ1aWxkIGtleSBzY2hlbWEgYW5kIHByb2plY3Rpb24gZm9yIGluZGV4XG4gICAgY29uc3QgZ3NpS2V5U2NoZW1hID0gdGhpcy5idWlsZEluZGV4S2V5U2NoZW1hKHByb3BzLnBhcnRpdGlvbktleSwgcHJvcHMuc29ydEtleSk7XG4gICAgY29uc3QgZ3NpUHJvamVjdGlvbiA9IHRoaXMuYnVpbGRJbmRleFByb2plY3Rpb24ocHJvcHMpO1xuXG4gICAgdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzLnB1c2goe1xuICAgICAgaW5kZXhOYW1lOiBwcm9wcy5pbmRleE5hbWUsXG4gICAgICBrZXlTY2hlbWE6IGdzaUtleVNjaGVtYSxcbiAgICAgIHByb2plY3Rpb246IGdzaVByb2plY3Rpb24sXG4gICAgICBwcm92aXNpb25lZFRocm91Z2hwdXQ6IHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCA/IHVuZGVmaW5lZCA6IHtcbiAgICAgICAgcmVhZENhcGFjaXR5VW5pdHM6IHByb3BzLnJlYWRDYXBhY2l0eSB8fCA1LFxuICAgICAgICB3cml0ZUNhcGFjaXR5VW5pdHM6IHByb3BzLndyaXRlQ2FwYWNpdHkgfHwgNSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlY29uZGFyeUluZGV4U2NoZW1hcy5zZXQocHJvcHMuaW5kZXhOYW1lLCB7XG4gICAgICBwYXJ0aXRpb25LZXk6IHByb3BzLnBhcnRpdGlvbktleSxcbiAgICAgIHNvcnRLZXk6IHByb3BzLnNvcnRLZXksXG4gICAgfSk7XG5cbiAgICB0aGlzLmluZGV4U2NhbGluZy5zZXQocHJvcHMuaW5kZXhOYW1lLCB7fSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbG9jYWwgc2Vjb25kYXJ5IGluZGV4IG9mIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgdGhlIHByb3BlcnR5IG9mIGxvY2FsIHNlY29uZGFyeSBpbmRleFxuICAgKi9cbiAgcHVibGljIGFkZExvY2FsU2Vjb25kYXJ5SW5kZXgocHJvcHM6IExvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wcykge1xuICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hbWF6b25keW5hbW9kYi9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvTGltaXRzLmh0bWwjbGltaXRzLXNlY29uZGFyeS1pbmRleGVzXG4gICAgaWYgKHRoaXMubG9jYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCA+PSBNQVhfTE9DQUxfU0VDT05EQVJZX0lOREVYX0NPVU5UKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgYSBtYXhpbXVtIG51bWJlciBvZiBsb2NhbCBzZWNvbmRhcnkgaW5kZXggcGVyIHRhYmxlIGlzICR7TUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVH1gKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlSW5kZXhOYW1lKHByb3BzLmluZGV4TmFtZSk7XG5cbiAgICAvLyBidWlsZCBrZXkgc2NoZW1hIGFuZCBwcm9qZWN0aW9uIGZvciBpbmRleFxuICAgIGNvbnN0IGxzaUtleVNjaGVtYSA9IHRoaXMuYnVpbGRJbmRleEtleVNjaGVtYSh0aGlzLnRhYmxlUGFydGl0aW9uS2V5LCBwcm9wcy5zb3J0S2V5KTtcbiAgICBjb25zdCBsc2lQcm9qZWN0aW9uID0gdGhpcy5idWlsZEluZGV4UHJvamVjdGlvbihwcm9wcyk7XG5cbiAgICB0aGlzLmxvY2FsU2Vjb25kYXJ5SW5kZXhlcy5wdXNoKHtcbiAgICAgIGluZGV4TmFtZTogcHJvcHMuaW5kZXhOYW1lLFxuICAgICAga2V5U2NoZW1hOiBsc2lLZXlTY2hlbWEsXG4gICAgICBwcm9qZWN0aW9uOiBsc2lQcm9qZWN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZWNvbmRhcnlJbmRleFNjaGVtYXMuc2V0KHByb3BzLmluZGV4TmFtZSwge1xuICAgICAgcGFydGl0aW9uS2V5OiB0aGlzLnRhYmxlUGFydGl0aW9uS2V5LFxuICAgICAgc29ydEtleTogcHJvcHMuc29ydEtleSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgcmVhZCBjYXBhY2l0eSBzY2FsaW5nIGZvciB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEByZXR1cm5zIEFuIG9iamVjdCB0byBjb25maWd1cmUgYWRkaXRpb25hbCBBdXRvU2NhbGluZyBzZXR0aW5nc1xuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZVJlYWRDYXBhY2l0eShwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVhZCBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgdGFibGUnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRvU2NhbGluZyBpcyBub3QgYXZhaWxhYmxlIGZvciB0YWJsZXMgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudGFibGVTY2FsaW5nLnNjYWxhYmxlUmVhZEF0dHJpYnV0ZSA9IG5ldyBTY2FsYWJsZVRhYmxlQXR0cmlidXRlKHRoaXMsICdSZWFkU2NhbGluZycsIHtcbiAgICAgIHNlcnZpY2VOYW1lc3BhY2U6IGFwcHNjYWxpbmcuU2VydmljZU5hbWVzcGFjZS5EWU5BTU9EQixcbiAgICAgIHJlc291cmNlSWQ6IGB0YWJsZS8ke3RoaXMudGFibGVOYW1lfWAsXG4gICAgICBkaW1lbnNpb246ICdkeW5hbW9kYjp0YWJsZTpSZWFkQ2FwYWNpdHlVbml0cycsXG4gICAgICByb2xlOiB0aGlzLnNjYWxpbmdSb2xlLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlIHdyaXRlIGNhcGFjaXR5IHNjYWxpbmcgZm9yIHRoaXMgdGFibGVcbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHRvIGNvbmZpZ3VyZSBhZGRpdGlvbmFsIEF1dG9TY2FsaW5nIHNldHRpbmdzIGZvciB0aGlzIGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkocHJvcHM6IEVuYWJsZVNjYWxpbmdQcm9wcyk6IElTY2FsYWJsZVRhYmxlQXR0cmlidXRlIHtcbiAgICBpZiAodGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdXcml0ZSBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgdGFibGUnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRvU2NhbGluZyBpcyBub3QgYXZhaWxhYmxlIGZvciB0YWJsZXMgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlJyk7XG4gICAgfVxuXG4gICAgdGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSA9IG5ldyBTY2FsYWJsZVRhYmxlQXR0cmlidXRlKHRoaXMsICdXcml0ZVNjYWxpbmcnLCB7XG4gICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICByZXNvdXJjZUlkOiBgdGFibGUvJHt0aGlzLnRhYmxlTmFtZX1gLFxuICAgICAgZGltZW5zaW9uOiAnZHluYW1vZGI6dGFibGU6V3JpdGVDYXBhY2l0eVVuaXRzJyxcbiAgICAgIHJvbGU6IHRoaXMuc2NhbGluZ1JvbGUsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgICBmb3IgKGNvbnN0IGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZSBvZiB0aGlzLmdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMpIHtcbiAgICAgIGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kodGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVdyaXRlQXR0cmlidXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZSByZWFkIGNhcGFjaXR5IHNjYWxpbmcgZm9yIHRoZSBnaXZlbiBHU0lcbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHRvIGNvbmZpZ3VyZSBhZGRpdGlvbmFsIEF1dG9TY2FsaW5nIHNldHRpbmdzIGZvciB0aGlzIGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZUdsb2JhbFNlY29uZGFyeUluZGV4UmVhZENhcGFjaXR5KGluZGV4TmFtZTogc3RyaW5nLCBwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZScpO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVQYWlyID0gdGhpcy5pbmRleFNjYWxpbmcuZ2V0KGluZGV4TmFtZSk7XG4gICAgaWYgKCFhdHRyaWJ1dGVQYWlyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXggd2l0aCBuYW1lICR7aW5kZXhOYW1lfWApO1xuICAgIH1cbiAgICBpZiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVhZCBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgaW5kZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXR0cmlidXRlUGFpci5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSh0aGlzLCBgJHtpbmRleE5hbWV9UmVhZFNjYWxpbmdgLCB7XG4gICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICByZXNvdXJjZUlkOiBgdGFibGUvJHt0aGlzLnRhYmxlTmFtZX0vaW5kZXgvJHtpbmRleE5hbWV9YCxcbiAgICAgIGRpbWVuc2lvbjogJ2R5bmFtb2RiOmluZGV4OlJlYWRDYXBhY2l0eVVuaXRzJyxcbiAgICAgIHJvbGU6IHRoaXMuc2NhbGluZ1JvbGUsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgd3JpdGUgY2FwYWNpdHkgc2NhbGluZyBmb3IgdGhlIGdpdmVuIEdTSVxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBvYmplY3QgdG8gY29uZmlndXJlIGFkZGl0aW9uYWwgQXV0b1NjYWxpbmcgc2V0dGluZ3MgZm9yIHRoaXMgYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYXV0b1NjYWxlR2xvYmFsU2Vjb25kYXJ5SW5kZXhXcml0ZUNhcGFjaXR5KGluZGV4TmFtZTogc3RyaW5nLCBwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZScpO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVQYWlyID0gdGhpcy5pbmRleFNjYWxpbmcuZ2V0KGluZGV4TmFtZSk7XG4gICAgaWYgKCFhdHRyaWJ1dGVQYWlyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXggd2l0aCBuYW1lICR7aW5kZXhOYW1lfWApO1xuICAgIH1cbiAgICBpZiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVdyaXRlQXR0cmlidXRlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dyaXRlIEF1dG9TY2FsaW5nIGFscmVhZHkgZW5hYmxlZCBmb3IgdGhpcyBpbmRleCcpO1xuICAgIH1cblxuICAgIHJldHVybiBhdHRyaWJ1dGVQYWlyLnNjYWxhYmxlV3JpdGVBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSh0aGlzLCBgJHtpbmRleE5hbWV9V3JpdGVTY2FsaW5nYCwge1xuICAgICAgc2VydmljZU5hbWVzcGFjZTogYXBwc2NhbGluZy5TZXJ2aWNlTmFtZXNwYWNlLkRZTkFNT0RCLFxuICAgICAgcmVzb3VyY2VJZDogYHRhYmxlLyR7dGhpcy50YWJsZU5hbWV9L2luZGV4LyR7aW5kZXhOYW1lfWAsXG4gICAgICBkaW1lbnNpb246ICdkeW5hbW9kYjppbmRleDpXcml0ZUNhcGFjaXR5VW5pdHMnLFxuICAgICAgcm9sZTogdGhpcy5zY2FsaW5nUm9sZSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzY2hlbWEgYXR0cmlidXRlcyBvZiB0YWJsZSBvciBpbmRleC5cbiAgICpcbiAgICogQHJldHVybnMgU2NoZW1hIG9mIHRhYmxlIG9yIGluZGV4LlxuICAgKi9cbiAgcHVibGljIHNjaGVtYShpbmRleE5hbWU/OiBzdHJpbmcpOiBTY2hlbWFPcHRpb25zIHtcbiAgICBpZiAoIWluZGV4TmFtZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcGFydGl0aW9uS2V5OiB0aGlzLnRhYmxlUGFydGl0aW9uS2V5LFxuICAgICAgICBzb3J0S2V5OiB0aGlzLnRhYmxlU29ydEtleSxcbiAgICAgIH07XG4gICAgfVxuICAgIGxldCBzY2hlbWEgPSB0aGlzLnNlY29uZGFyeUluZGV4U2NoZW1hcy5nZXQoaW5kZXhOYW1lKTtcbiAgICBpZiAoIXNjaGVtYSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZmluZCBzY2hlbWEgZm9yIGluZGV4OiAke2luZGV4TmFtZX0uIFVzZSAnYWRkR2xvYmFsU2Vjb25kYXJ5SW5kZXgnIG9yICdhZGRMb2NhbFNlY29uZGFyeUluZGV4JyB0byBhZGQgaW5kZXhgKTtcbiAgICB9XG4gICAgcmV0dXJuIHNjaGVtYTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgdGFibGUgY29uc3RydWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VcbiAgICovXG4gIHByb3RlY3RlZCB2YWxpZGF0ZSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcblxuICAgIGlmICghdGhpcy50YWJsZVBhcnRpdGlvbktleSkge1xuICAgICAgZXJyb3JzLnB1c2goJ2EgcGFydGl0aW9uIGtleSBtdXN0IGJlIHNwZWNpZmllZCcpO1xuICAgIH1cbiAgICBpZiAodGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXMubGVuZ3RoID4gMCAmJiAhdGhpcy50YWJsZVNvcnRLZXkpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdhIHNvcnQga2V5IG9mIHRoZSB0YWJsZSBtdXN0IGJlIHNwZWNpZmllZCB0byBhZGQgbG9jYWwgc2Vjb25kYXJ5IGluZGV4ZXMnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5nbG9iYWxSZXBsaWNhQ3VzdG9tUmVzb3VyY2VzLmxlbmd0aCA+IDAgJiYgdGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUFJPVklTSU9ORUQpIHtcbiAgICAgIGNvbnN0IHdyaXRlQXV0b1NjYWxlQXR0cmlidXRlID0gdGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZTtcbiAgICAgIGlmICghd3JpdGVBdXRvU2NhbGVBdHRyaWJ1dGUpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goJ0EgZ2xvYmFsIFRhYmxlIHRoYXQgdXNlcyBQUk9WSVNJT05FRCBhcyB0aGUgYmlsbGluZyBtb2RlIG5lZWRzIGF1dG8tc2NhbGVkIHdyaXRlIGNhcGFjaXR5LiAnICtcbiAgICAgICAgICAnVXNlIHRoZSBhdXRvU2NhbGVXcml0ZUNhcGFjaXR5KCkgbWV0aG9kIHRvIGVuYWJsZSBpdC4nKTtcbiAgICAgIH0gZWxzZSBpZiAoIXdyaXRlQXV0b1NjYWxlQXR0cmlidXRlLl9zY2FsaW5nUG9saWN5Q3JlYXRlZCkge1xuICAgICAgICBlcnJvcnMucHVzaCgnQSBnbG9iYWwgVGFibGUgdGhhdCB1c2VzIFBST1ZJU0lPTkVEIGFzIHRoZSBiaWxsaW5nIG1vZGUgbmVlZHMgYXV0by1zY2FsZWQgd3JpdGUgY2FwYWNpdHkgd2l0aCBhIHBvbGljeS4gJyArXG4gICAgICAgICAgJ0NhbGwgb25lIG9mIHRoZSBzY2FsZU9uKigpIG1ldGhvZHMgb2YgdGhlIG9iamVjdCByZXR1cm5lZCBmcm9tIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkoKScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgcmVhZCBhbmQgd3JpdGUgY2FwYWNpdHkgYXJlIG5vdCBzcGVjaWZpZWQgZm9yIG9uLWRlbWFuZCB0YWJsZXMgKGJpbGxpbmcgbW9kZSBQQVlfUEVSX1JFUVVFU1QpLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcmVhZCBhbmQgd3JpdGUgY2FwYWNpdHkgcHJvcGVydGllc1xuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb3Zpc2lvbmluZyhwcm9wczogeyByZWFkQ2FwYWNpdHk/OiBudW1iZXIsIHdyaXRlQ2FwYWNpdHk/OiBudW1iZXIgfSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIGlmIChwcm9wcy5yZWFkQ2FwYWNpdHkgIT09IHVuZGVmaW5lZCB8fCBwcm9wcy53cml0ZUNhcGFjaXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5b3UgY2Fubm90IHByb3Zpc2lvbiByZWFkIGFuZCB3cml0ZSBjYXBhY2l0eSBmb3IgYSB0YWJsZSB3aXRoIFBBWV9QRVJfUkVRVUVTVCBiaWxsaW5nIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgaW5kZXggbmFtZSB0byBjaGVjayBpZiBhIGR1cGxpY2F0ZSBuYW1lIGFscmVhZHkgZXhpc3RzLlxuICAgKlxuICAgKiBAcGFyYW0gaW5kZXhOYW1lIGEgbmFtZSBvZiBnbG9iYWwgb3IgbG9jYWwgc2Vjb25kYXJ5IGluZGV4XG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlSW5kZXhOYW1lKGluZGV4TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc2Vjb25kYXJ5SW5kZXhTY2hlbWFzLmhhcyhpbmRleE5hbWUpKSB7XG4gICAgICAvLyBhIGR1cGxpY2F0ZSBpbmRleCBuYW1lIGNhdXNlcyB2YWxpZGF0aW9uIGV4Y2VwdGlvbiwgc3RhdHVzIGNvZGUgNDAwLCB3aGlsZSB0cnlpbmcgdG8gY3JlYXRlIENGTiBzdGFja1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBhIGR1cGxpY2F0ZSBpbmRleCBuYW1lLCAke2luZGV4TmFtZX0sIGlzIG5vdCBhbGxvd2VkYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIG5vbi1rZXkgYXR0cmlidXRlcyBieSBjaGVja2luZyBsaW1pdHMgd2l0aGluIHNlY29uZGFyeSBpbmRleCwgd2hpY2ggbWF5IHZhcnkgaW4gZnV0dXJlLlxuICAgKlxuICAgKiBAcGFyYW0gbm9uS2V5QXR0cmlidXRlcyBhIGxpc3Qgb2Ygbm9uLWtleSBhdHRyaWJ1dGUgbmFtZXNcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVOb25LZXlBdHRyaWJ1dGVzKG5vbktleUF0dHJpYnV0ZXM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKHRoaXMubm9uS2V5QXR0cmlidXRlcy5zaXplICsgbm9uS2V5QXR0cmlidXRlcy5sZW5ndGggPiAxMDApIHtcbiAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hbWF6b25keW5hbW9kYi9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvTGltaXRzLmh0bWwjbGltaXRzLXNlY29uZGFyeS1pbmRleGVzXG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignYSBtYXhpbXVtIG51bWJlciBvZiBub25LZXlBdHRyaWJ1dGVzIGFjcm9zcyBhbGwgb2Ygc2Vjb25kYXJ5IGluZGV4ZXMgaXMgMTAwJyk7XG4gICAgfVxuXG4gICAgLy8gc3RvcmUgYWxsIG5vbi1rZXkgYXR0cmlidXRlc1xuICAgIG5vbktleUF0dHJpYnV0ZXMuZm9yRWFjaChhdHQgPT4gdGhpcy5ub25LZXlBdHRyaWJ1dGVzLmFkZChhdHQpKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbmRleEtleVNjaGVtYShwYXJ0aXRpb25LZXk6IEF0dHJpYnV0ZSwgc29ydEtleT86IEF0dHJpYnV0ZSk6IENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5W10ge1xuICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUocGFydGl0aW9uS2V5KTtcbiAgICBjb25zdCBpbmRleEtleVNjaGVtYTogQ2ZuVGFibGUuS2V5U2NoZW1hUHJvcGVydHlbXSA9IFtcbiAgICAgIHsgYXR0cmlidXRlTmFtZTogcGFydGl0aW9uS2V5Lm5hbWUsIGtleVR5cGU6IEhBU0hfS0VZX1RZUEUgfSxcbiAgICBdO1xuXG4gICAgaWYgKHNvcnRLZXkpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUoc29ydEtleSk7XG4gICAgICBpbmRleEtleVNjaGVtYS5wdXNoKHsgYXR0cmlidXRlTmFtZTogc29ydEtleS5uYW1lLCBrZXlUeXBlOiBSQU5HRV9LRVlfVFlQRSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5kZXhLZXlTY2hlbWE7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkSW5kZXhQcm9qZWN0aW9uKHByb3BzOiBTZWNvbmRhcnlJbmRleFByb3BzKTogQ2ZuVGFibGUuUHJvamVjdGlvblByb3BlcnR5IHtcbiAgICBpZiAocHJvcHMucHJvamVjdGlvblR5cGUgPT09IFByb2plY3Rpb25UeXBlLklOQ0xVREUgJiYgIXByb3BzLm5vbktleUF0dHJpYnV0ZXMpIHtcbiAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbFxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBub24ta2V5IGF0dHJpYnV0ZXMgc2hvdWxkIGJlIHNwZWNpZmllZCB3aGVuIHVzaW5nICR7UHJvamVjdGlvblR5cGUuSU5DTFVERX0gcHJvamVjdGlvbiB0eXBlYCk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnByb2plY3Rpb25UeXBlICE9PSBQcm9qZWN0aW9uVHlwZS5JTkNMVURFICYmIHByb3BzLm5vbktleUF0dHJpYnV0ZXMpIHtcbiAgICAgIC8vIHRoaXMgY29tYmluYXRpb24gY2F1c2VzIHZhbGlkYXRpb24gZXhjZXB0aW9uLCBzdGF0dXMgY29kZSA0MDAsIHdoaWxlIHRyeWluZyB0byBjcmVhdGUgQ0ZOIHN0YWNrXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vbi1rZXkgYXR0cmlidXRlcyBzaG91bGQgbm90IGJlIHNwZWNpZmllZCB3aGVuIG5vdCB1c2luZyAke1Byb2plY3Rpb25UeXBlLklOQ0xVREV9IHByb2plY3Rpb24gdHlwZWApO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5ub25LZXlBdHRyaWJ1dGVzKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlTm9uS2V5QXR0cmlidXRlcyhwcm9wcy5ub25LZXlBdHRyaWJ1dGVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHJvamVjdGlvblR5cGU6IHByb3BzLnByb2plY3Rpb25UeXBlID8/IFByb2plY3Rpb25UeXBlLkFMTCxcbiAgICAgIG5vbktleUF0dHJpYnV0ZXM6IHByb3BzLm5vbktleUF0dHJpYnV0ZXMgPz8gdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGZpbmRLZXkoa2V5VHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMua2V5U2NoZW1hLmZpbmQocHJvcCA9PiBwcm9wLmtleVR5cGUgPT09IGtleVR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRLZXkoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIGtleVR5cGU6IHN0cmluZykge1xuICAgIGNvbnN0IGV4aXN0aW5nUHJvcCA9IHRoaXMuZmluZEtleShrZXlUeXBlKTtcbiAgICBpZiAoZXhpc3RpbmdQcm9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBzZXQgJHthdHRyaWJ1dGUubmFtZX0gYXMgYSAke2tleVR5cGV9IGtleSwgYmVjYXVzZSAke2V4aXN0aW5nUHJvcC5hdHRyaWJ1dGVOYW1lfSBpcyBhICR7a2V5VHlwZX0ga2V5YCk7XG4gICAgfVxuICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUoYXR0cmlidXRlKTtcbiAgICB0aGlzLmtleVNjaGVtYS5wdXNoKHtcbiAgICAgIGF0dHJpYnV0ZU5hbWU6IGF0dHJpYnV0ZS5uYW1lLFxuICAgICAga2V5VHlwZSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciB0aGUga2V5IGF0dHJpYnV0ZSBvZiB0YWJsZSBvciBzZWNvbmRhcnkgaW5kZXggdG8gYXNzZW1ibGUgYXR0cmlidXRlIGRlZmluaXRpb25zIG9mIFRhYmxlUmVzb3VyY2VQcm9wcy5cbiAgICpcbiAgICogQHBhcmFtIGF0dHJpYnV0ZSB0aGUga2V5IGF0dHJpYnV0ZSBvZiB0YWJsZSBvciBzZWNvbmRhcnkgaW5kZXhcbiAgICovXG4gIHByaXZhdGUgcmVnaXN0ZXJBdHRyaWJ1dGUoYXR0cmlidXRlOiBBdHRyaWJ1dGUpIHtcbiAgICBjb25zdCB7IG5hbWUsIHR5cGUgfSA9IGF0dHJpYnV0ZTtcbiAgICBjb25zdCBleGlzdGluZ0RlZiA9IHRoaXMuYXR0cmlidXRlRGVmaW5pdGlvbnMuZmluZChkZWYgPT4gZGVmLmF0dHJpYnV0ZU5hbWUgPT09IG5hbWUpO1xuICAgIGlmIChleGlzdGluZ0RlZiAmJiBleGlzdGluZ0RlZi5hdHRyaWJ1dGVUeXBlICE9PSB0eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBzcGVjaWZ5ICR7bmFtZX0gYXMgJHt0eXBlfSBiZWNhdXNlIGl0IHdhcyBhbHJlYWR5IGRlZmluZWQgYXMgJHtleGlzdGluZ0RlZi5hdHRyaWJ1dGVUeXBlfWApO1xuICAgIH1cbiAgICBpZiAoIWV4aXN0aW5nRGVmKSB7XG4gICAgICB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zLnB1c2goe1xuICAgICAgICBhdHRyaWJ1dGVOYW1lOiBuYW1lLFxuICAgICAgICBhdHRyaWJ1dGVUeXBlOiB0eXBlLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcm9sZSB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgQXV0b1NjYWxpbmdcbiAgICovXG4gIHByaXZhdGUgbWFrZVNjYWxpbmdSb2xlKCk6IGlhbS5JUm9sZSB7XG4gICAgLy8gVXNlIGEgU2VydmljZSBMaW5rZWQgUm9sZS5cbiAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXV0b3NjYWxpbmcvYXBwbGljYXRpb24vdXNlcmd1aWRlL2FwcGxpY2F0aW9uLWF1dG8tc2NhbGluZy1zZXJ2aWNlLWxpbmtlZC1yb2xlcy5odG1sXG4gICAgcmV0dXJuIGlhbS5Sb2xlLmZyb21Sb2xlQXJuKHRoaXMsICdTY2FsaW5nUm9sZScsIFN0YWNrLm9mKHRoaXMpLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnaWFtJyxcbiAgICAgIHJlZ2lvbjogJycsXG4gICAgICByZXNvdXJjZTogJ3JvbGUvYXdzLXNlcnZpY2Utcm9sZS9keW5hbW9kYi5hcHBsaWNhdGlvbi1hdXRvc2NhbGluZy5hbWF6b25hd3MuY29tJyxcbiAgICAgIHJlc291cmNlTmFtZTogJ0FXU1NlcnZpY2VSb2xlRm9yQXBwbGljYXRpb25BdXRvU2NhbGluZ19EeW5hbW9EQlRhYmxlJyxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyByZXBsaWNhIHRhYmxlc1xuICAgKlxuICAgKiBAcGFyYW0gcmVnaW9ucyByZWdpb25zIHdoZXJlIHRvIGNyZWF0ZSB0YWJsZXNcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlUmVwbGljYVRhYmxlcyhyZWdpb25zOiBzdHJpbmdbXSwgdGltZW91dD86IER1cmF0aW9uLCB3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaD86IGJvb2xlYW4pIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQoc3RhY2sucmVnaW9uKSAmJiByZWdpb25zLmluY2x1ZGVzKHN0YWNrLnJlZ2lvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYHJlcGxpY2F0aW9uUmVnaW9uc2AgY2Fubm90IGluY2x1ZGUgdGhlIHJlZ2lvbiB3aGVyZSB0aGlzIHN0YWNrIGlzIGRlcGxveWVkLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHByb3ZpZGVyID0gUmVwbGljYVByb3ZpZGVyLmdldE9yQ3JlYXRlKHRoaXMsIHsgdGltZW91dCB9KTtcblxuICAgIC8vIERvY3VtZW50YXRpb24gYXQgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9WMmd0X0lBTS5odG1sXG4gICAgLy8gaXMgY3VycmVudGx5IGluY29ycmVjdC4gQVdTIFN1cHBvcnQgcmVjb21tZW5kcyBgZHluYW1vZGI6KmAgaW4gYm90aCBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIHJlZ2lvbnNcblxuICAgIGNvbnN0IG9uRXZlbnRIYW5kbGVyUG9saWN5ID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQb2xpY3kodGhpcywgcHJvdmlkZXIub25FdmVudEhhbmRsZXIucm9sZSEpO1xuICAgIGNvbnN0IGlzQ29tcGxldGVIYW5kbGVyUG9saWN5ID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQb2xpY3kodGhpcywgcHJvdmlkZXIuaXNDb21wbGV0ZUhhbmRsZXIucm9sZSEpO1xuXG4gICAgLy8gUGVybWlzc2lvbnMgaW4gdGhlIHNvdXJjZSByZWdpb25cbiAgICB0aGlzLmdyYW50KG9uRXZlbnRIYW5kbGVyUG9saWN5LCAnZHluYW1vZGI6KicpO1xuICAgIHRoaXMuZ3JhbnQoaXNDb21wbGV0ZUhhbmRsZXJQb2xpY3ksICdkeW5hbW9kYjpEZXNjcmliZVRhYmxlJyk7XG5cbiAgICBsZXQgcHJldmlvdXNSZWdpb246IEN1c3RvbVJlc291cmNlIHwgdW5kZWZpbmVkO1xuICAgIGxldCBwcmV2aW91c1JlZ2lvbkNvbmRpdGlvbjogQ2ZuQ29uZGl0aW9uIHwgdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3QgcmVnaW9uIG9mIG5ldyBTZXQocmVnaW9ucykpIHsgLy8gUmVtb3ZlIGR1cGxpY2F0ZXNcbiAgICAgIC8vIFVzZSBtdWx0aXBsZSBjdXN0b20gcmVzb3VyY2VzIGJlY2F1c2UgbXVsdGlwbGUgY3JlYXRlL2RlbGV0ZVxuICAgICAgLy8gdXBkYXRlcyBjYW5ub3QgYmUgY29tYmluZWQgaW4gYSBzaW5nbGUgQVBJIGNhbGwuXG4gICAgICBjb25zdCBjdXJyZW50UmVnaW9uID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsIGBSZXBsaWNhJHtyZWdpb259YCwge1xuICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpEeW5hbW9EQlJlcGxpY2EnLFxuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICBSZWdpb246IHJlZ2lvbixcbiAgICAgICAgICBTa2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0OiB3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaCA9PSBudWxsXG4gICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgLy8gQ0ZOIGNoYW5nZXMgQ3VzdG9tIFJlc291cmNlIHByb3BlcnRpZXMgdG8gc3RyaW5ncyBhbnl3YXlzLFxuICAgICAgICAgICAgLy8gc28gbGV0J3MgZG8gdGhhdCBvdXJzZWx2ZXMgdG8gbWFrZSBpdCBjbGVhciBpbiB0aGUgaGFuZGxlciB0aGlzIGlzIGEgc3RyaW5nLCBub3QgYSBib29sZWFuXG4gICAgICAgICAgICA6ICghd2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gpLnRvU3RyaW5nKCksXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGN1cnJlbnRSZWdpb24ubm9kZS5hZGREZXBlbmRlbmN5KFxuICAgICAgICBvbkV2ZW50SGFuZGxlclBvbGljeS5wb2xpY3ksXG4gICAgICAgIGlzQ29tcGxldGVIYW5kbGVyUG9saWN5LnBvbGljeSxcbiAgICAgICk7XG4gICAgICB0aGlzLmdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMucHVzaChjdXJyZW50UmVnaW9uKTtcblxuICAgICAgLy8gRGVwbG95IHRpbWUgY2hlY2sgdG8gcHJldmVudCBmcm9tIGNyZWF0aW5nIGEgcmVwbGljYSBpbiB0aGUgcmVnaW9uXG4gICAgICAvLyB3aGVyZSB0aGlzIHN0YWNrIGlzIGRlcGxveWVkLiBPbmx5IG5lZWRlZCBmb3IgZW52aXJvbm1lbnQgYWdub3N0aWNcbiAgICAgIC8vIHN0YWNrcy5cbiAgICAgIGxldCBjcmVhdGVSZXBsaWNhOiBDZm5Db25kaXRpb24gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHN0YWNrLnJlZ2lvbikpIHtcbiAgICAgICAgY3JlYXRlUmVwbGljYSA9IG5ldyBDZm5Db25kaXRpb24odGhpcywgYFN0YWNrUmVnaW9uTm90RXF1YWxzJHtyZWdpb259YCwge1xuICAgICAgICAgIGV4cHJlc3Npb246IEZuLmNvbmRpdGlvbk5vdChGbi5jb25kaXRpb25FcXVhbHMocmVnaW9uLCBBd3MuUkVHSU9OKSksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjZm5DdXN0b21SZXNvdXJjZSA9IGN1cnJlbnRSZWdpb24ubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuQ3VzdG9tUmVzb3VyY2U7XG4gICAgICAgIGNmbkN1c3RvbVJlc291cmNlLmNmbk9wdGlvbnMuY29uZGl0aW9uID0gY3JlYXRlUmVwbGljYTtcbiAgICAgIH1cblxuICAgICAgLy8gU2F2ZSByZWdpb25hbCBhcm5zIGZvciBncmFudFh4eCgpIG1ldGhvZHNcbiAgICAgIHRoaXMucmVnaW9uYWxBcm5zLnB1c2goc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzZXJ2aWNlOiAnZHluYW1vZGInLFxuICAgICAgICByZXNvdXJjZTogJ3RhYmxlJyxcbiAgICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIH0pKTtcblxuICAgICAgLy8gV2UgbmVlZCB0byBjcmVhdGUvZGVsZXRlIHJlZ2lvbnMgc2VxdWVudGlhbGx5IGJlY2F1c2Ugd2UgY2Fubm90XG4gICAgICAvLyBoYXZlIG11bHRpcGxlIHRhYmxlIHVwZGF0ZXMgYXQgdGhlIHNhbWUgdGltZS4gVGhlIGBpc0NvbXBsZXRlSGFuZGxlcmBcbiAgICAgIC8vIG9mIHRoZSBwcm92aWRlciB3YWl0cyB1bnRpbCB0aGUgcmVwbGljYSBpcyBpbiBhbiBBQ1RJVkUgc3RhdGUuXG4gICAgICBpZiAocHJldmlvdXNSZWdpb24pIHtcbiAgICAgICAgaWYgKHByZXZpb3VzUmVnaW9uQ29uZGl0aW9uKSB7XG4gICAgICAgICAgLy8gd2UgY2FuJ3Qgc2ltcGx5IHVzZSBhIERlcGVuZGVuY3ksXG4gICAgICAgICAgLy8gYmVjYXVzZSB0aGUgcHJldmlvdXNSZWdpb24gaXMgcHJvdGVjdGVkIGJ5IHRoZSBcImRpZmZlcmVudCByZWdpb25cIiBDb25kaXRpb24sXG4gICAgICAgICAgLy8gYW5kIHlvdSBjYW4ndCBoYXZlIEZuOjpJZiBpbiBEZXBlbmRzT24uXG4gICAgICAgICAgLy8gSW5zdGVhZCwgcmVseSBvbiBSZWYgYWRkaW5nIGEgZGVwZW5kZW5jeSBpbXBsaWNpdGx5IVxuICAgICAgICAgIGNvbnN0IHByZXZpb3VzUmVnaW9uQ2ZuUmVzb3VyY2UgPSBwcmV2aW91c1JlZ2lvbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBDZm5SZXNvdXJjZTtcbiAgICAgICAgICBjb25zdCBjdXJyZW50UmVnaW9uQ2ZuUmVzb3VyY2UgPSBjdXJyZW50UmVnaW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblJlc291cmNlO1xuICAgICAgICAgIGN1cnJlbnRSZWdpb25DZm5SZXNvdXJjZS5hZGRNZXRhZGF0YSgnRHluYW1vRGJSZXBsaWNhdGlvbkRlcGVuZGVuY3knLFxuICAgICAgICAgICAgRm4uY29uZGl0aW9uSWYocHJldmlvdXNSZWdpb25Db25kaXRpb24ubG9naWNhbElkLCBwcmV2aW91c1JlZ2lvbkNmblJlc291cmNlLnJlZiwgQXdzLk5PX1ZBTFVFKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3VycmVudFJlZ2lvbi5ub2RlLmFkZERlcGVuZGVuY3kocHJldmlvdXNSZWdpb24pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHByZXZpb3VzUmVnaW9uID0gY3VycmVudFJlZ2lvbjtcbiAgICAgIHByZXZpb3VzUmVnaW9uQ29uZGl0aW9uID0gY3JlYXRlUmVwbGljYTtcbiAgICB9XG5cbiAgICAvLyBQZXJtaXNzaW9ucyBpbiB0aGUgZGVzdGluYXRpb24gcmVnaW9ucyAob3V0c2lkZSBvZiB0aGUgbG9vcCB0b1xuICAgIC8vIG1pbmltaXplIHN0YXRlbWVudHMgaW4gdGhlIHBvbGljeSlcbiAgICBvbkV2ZW50SGFuZGxlclBvbGljeS5ncmFudFByaW5jaXBhbC5hZGRUb1ByaW5jaXBhbFBvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBhY3Rpb25zOiBbJ2R5bmFtb2RiOionXSxcbiAgICAgIHJlc291cmNlczogdGhpcy5yZWdpb25hbEFybnMsXG4gICAgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyB0YWJsZSBoYXMgaW5kZXhlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBoYXNJbmRleCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCArIHRoaXMubG9jYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGtleSBwcm9wZXJ0aWVzIGFuZCByZXR1cm4gdGhlIFRhYmxlIGVuY3J5cHRpb24gcHJvcGVydHkgZnJvbSB0aGVcbiAgICogdXNlcidzIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwcml2YXRlIHBhcnNlRW5jcnlwdGlvbihwcm9wczogVGFibGVQcm9wcyk6IHsgc3NlU3BlY2lmaWNhdGlvbjogQ2ZuVGFibGVQcm9wc1snc3NlU3BlY2lmaWNhdGlvbiddLCBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXkgfSB7XG4gICAgbGV0IGVuY3J5cHRpb25UeXBlID0gcHJvcHMuZW5jcnlwdGlvbjtcblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSAhPSBudWxsICYmIHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uICE9IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgZW5jcnlwdGlvbiBhbmQgc2VydmVyU2lkZUVuY3J5cHRpb24gY2FuIGJlIHNwZWNpZmllZCwgYnV0IGJvdGggd2VyZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5zZXJ2ZXJTaWRlRW5jcnlwdGlvbiAmJiBwcm9wcy5lbmNyeXB0aW9uS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VuY3J5cHRpb25LZXkgY2Fubm90IGJlIHNwZWNpZmllZCB3aGVuIHNlcnZlclNpZGVFbmNyeXB0aW9uIGlzIHNwZWNpZmllZC4gVXNlIGVuY3J5cHRpb24gaW5zdGVhZCcpO1xuICAgIH1cblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBlbmNyeXB0aW9uVHlwZSA9IHByb3BzLmVuY3J5cHRpb25LZXkgIT0gbnVsbFxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIGNvbmZpZ3VyZWQgZW5jcnlwdGlvbktleSwgdGhlIGVuY3J5cHRpb24gaXMgaW1wbGljaXRseSBDVVNUT01FUl9NQU5BR0VEXG4gICAgICAgID8gVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRURcbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBpZiBzZXZlclNpZGVFbmNyeXB0aW9uIGlzIGVuYWJsZWQsIGl0J3MgQVdTX01BTkFHRUQ7IGVsc2UgdW5kZWZpbmVkIChkbyBub3Qgc2V0IGFueXRoaW5nKVxuICAgICAgICA6IHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uID8gVGFibGVFbmNyeXB0aW9uLkFXU19NQU5BR0VEIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSAhPT0gVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgJiYgcHJvcHMuZW5jcnlwdGlvbktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdgZW5jcnlwdGlvbktleSBjYW5ub3QgYmUgc3BlY2lmaWVkIHVubGVzcyBlbmNyeXB0aW9uIGlzIHNldCB0byBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRCAoaXQgd2FzIHNldCB0byAke2VuY3J5cHRpb25UeXBlfSlgJyk7XG4gICAgfVxuXG4gICAgaWYgKGVuY3J5cHRpb25UeXBlID09PSBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRCAmJiBwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgaXMgbm90IHN1cHBvcnRlZCBieSBEeW5hbW9EQiBHbG9iYWwgVGFibGVzICh3aGVyZSByZXBsaWNhdGlvblJlZ2lvbnMgd2FzIHNldCknKTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGVuY3J5cHRpb25UeXBlKSB7XG4gICAgICBjYXNlIFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEOlxuICAgICAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcHJvcHMuZW5jcnlwdGlvbktleSA/PyBuZXcga21zLktleSh0aGlzLCAnS2V5Jywge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgQ3VzdG9tZXItbWFuYWdlZCBrZXkgYXV0by1jcmVhdGVkIGZvciBlbmNyeXB0aW5nIER5bmFtb0RCIHRhYmxlIGF0ICR7dGhpcy5ub2RlLnBhdGh9YCxcbiAgICAgICAgICBlbmFibGVLZXlSb3RhdGlvbjogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzc2VTcGVjaWZpY2F0aW9uOiB7IHNzZUVuYWJsZWQ6IHRydWUsIGttc01hc3RlcktleUlkOiBlbmNyeXB0aW9uS2V5LmtleUFybiwgc3NlVHlwZTogJ0tNUycgfSxcbiAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICB9O1xuXG4gICAgICBjYXNlIFRhYmxlRW5jcnlwdGlvbi5BV1NfTUFOQUdFRDpcbiAgICAgICAgLy8gTm90IHNwZWNpZnlpbmcgXCJzc2VUeXBlOiAnS01TJ1wiIGhlcmUgYmVjYXVzZSBpdCB3b3VsZCBjYXVzZSBwaG9ueSBjaGFuZ2VzIHRvIGV4aXN0aW5nIHN0YWNrcy5cbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBzc2VFbmFibGVkOiB0cnVlIH0gfTtcblxuICAgICAgY2FzZSBUYWJsZUVuY3J5cHRpb24uREVGQVVMVDpcbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBzc2VFbmFibGVkOiBmYWxzZSB9IH07XG5cbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICAvLyBOb3Qgc3BlY2lmeWluZyBcInNzZUVuYWJsZWQ6IGZhbHNlXCIgaGVyZSBiZWNhdXNlIGl0IHdvdWxkIGNhdXNlIHBob255IGNoYW5nZXMgdG8gZXhpc3Rpbmcgc3RhY2tzLlxuICAgICAgICByZXR1cm4geyBzc2VTcGVjaWZpY2F0aW9uOiB1bmRlZmluZWQgfTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkICdlbmNyeXB0aW9uVHlwZSc6ICR7ZW5jcnlwdGlvblR5cGV9YCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogRGF0YSB0eXBlcyBmb3IgYXR0cmlidXRlcyB3aXRoaW4gYSB0YWJsZVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9Ib3dJdFdvcmtzLk5hbWluZ1J1bGVzRGF0YVR5cGVzLmh0bWwjSG93SXRXb3Jrcy5EYXRhVHlwZXNcbiAqL1xuZXhwb3J0IGVudW0gQXR0cmlidXRlVHlwZSB7XG4gIC8qKiBVcCB0byA0MDBLaUIgb2YgYmluYXJ5IGRhdGEgKHdoaWNoIG11c3QgYmUgZW5jb2RlZCBhcyBiYXNlNjQgYmVmb3JlIHNlbmRpbmcgdG8gRHluYW1vREIpICovXG4gIEJJTkFSWSA9ICdCJyxcbiAgLyoqIE51bWVyaWMgdmFsdWVzIG1hZGUgb2YgdXAgdG8gMzggZGlnaXRzIChwb3NpdGl2ZSwgbmVnYXRpdmUgb3IgemVybykgKi9cbiAgTlVNQkVSID0gJ04nLFxuICAvKiogVXAgdG8gNDAwS2lCIG9mIFVURi04IGVuY29kZWQgdGV4dCAqL1xuICBTVFJJTkcgPSAnUycsXG59XG5cbi8qKlxuICogRHluYW1vREIncyBSZWFkL1dyaXRlIGNhcGFjaXR5IG1vZGVzLlxuICovXG5leHBvcnQgZW51bSBCaWxsaW5nTW9kZSB7XG4gIC8qKlxuICAgKiBQYXkgb25seSBmb3Igd2hhdCB5b3UgdXNlLiBZb3UgZG9uJ3QgY29uZmlndXJlIFJlYWQvV3JpdGUgY2FwYWNpdHkgdW5pdHMuXG4gICAqL1xuICBQQVlfUEVSX1JFUVVFU1QgPSAnUEFZX1BFUl9SRVFVRVNUJyxcbiAgLyoqXG4gICAqIEV4cGxpY2l0bHkgc3BlY2lmaWVkIFJlYWQvV3JpdGUgY2FwYWNpdHkgdW5pdHMuXG4gICAqL1xuICBQUk9WSVNJT05FRCA9ICdQUk9WSVNJT05FRCcsXG59XG5cbi8qKlxuICogVGhlIHNldCBvZiBhdHRyaWJ1dGVzIHRoYXQgYXJlIHByb2plY3RlZCBpbnRvIHRoZSBpbmRleFxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX1Byb2plY3Rpb24uaHRtbFxuICovXG5leHBvcnQgZW51bSBQcm9qZWN0aW9uVHlwZSB7XG4gIC8qKiBPbmx5IHRoZSBpbmRleCBhbmQgcHJpbWFyeSBrZXlzIGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgaW5kZXguICovXG4gIEtFWVNfT05MWSA9ICdLRVlTX09OTFknLFxuICAvKiogT25seSB0aGUgc3BlY2lmaWVkIHRhYmxlIGF0dHJpYnV0ZXMgYXJlIHByb2plY3RlZCBpbnRvIHRoZSBpbmRleC4gVGhlIGxpc3Qgb2YgcHJvamVjdGVkIGF0dHJpYnV0ZXMgaXMgaW4gYG5vbktleUF0dHJpYnV0ZXNgLiAqL1xuICBJTkNMVURFID0gJ0lOQ0xVREUnLFxuICAvKiogQWxsIG9mIHRoZSB0YWJsZSBhdHRyaWJ1dGVzIGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgaW5kZXguICovXG4gIEFMTCA9ICdBTEwnXG59XG5cbi8qKlxuICogV2hlbiBhbiBpdGVtIGluIHRoZSB0YWJsZSBpcyBtb2RpZmllZCwgU3RyZWFtVmlld1R5cGUgZGV0ZXJtaW5lcyB3aGF0IGluZm9ybWF0aW9uXG4gKiBpcyB3cml0dGVuIHRvIHRoZSBzdHJlYW0gZm9yIHRoaXMgdGFibGUuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfU3RyZWFtU3BlY2lmaWNhdGlvbi5odG1sXG4gKi9cbmV4cG9ydCBlbnVtIFN0cmVhbVZpZXdUeXBlIHtcbiAgLyoqIFRoZSBlbnRpcmUgaXRlbSwgYXMgaXQgYXBwZWFycyBhZnRlciBpdCB3YXMgbW9kaWZpZWQsIGlzIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgTkVXX0lNQUdFID0gJ05FV19JTUFHRScsXG4gIC8qKiBUaGUgZW50aXJlIGl0ZW0sIGFzIGl0IGFwcGVhcmVkIGJlZm9yZSBpdCB3YXMgbW9kaWZpZWQsIGlzIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgT0xEX0lNQUdFID0gJ09MRF9JTUFHRScsXG4gIC8qKiBCb3RoIHRoZSBuZXcgYW5kIHRoZSBvbGQgaXRlbSBpbWFnZXMgb2YgdGhlIGl0ZW0gYXJlIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgTkVXX0FORF9PTERfSU1BR0VTID0gJ05FV19BTkRfT0xEX0lNQUdFUycsXG4gIC8qKiBPbmx5IHRoZSBrZXkgYXR0cmlidXRlcyBvZiB0aGUgbW9kaWZpZWQgaXRlbSBhcmUgd3JpdHRlbiB0byB0aGUgc3RyZWFtLiAqL1xuICBLRVlTX09OTFkgPSAnS0VZU19PTkxZJ1xufVxuXG4vKipcbiAqIER5bmFtb0RCJ3MgdGFibGUgY2xhc3MuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL0hvd0l0V29ya3MuVGFibGVDbGFzc2VzLmh0bWxcbiAqL1xuZXhwb3J0IGVudW0gVGFibGVDbGFzcyB7XG4gIC8qKiBEZWZhdWx0IHRhYmxlIGNsYXNzIGZvciBEeW5hbW9EQi4gKi9cbiAgU1RBTkRBUkQgPSAnU1RBTkRBUkQnLFxuXG4gIC8qKiBUYWJsZSBjbGFzcyBmb3IgRHluYW1vREIgdGhhdCByZWR1Y2VzIHN0b3JhZ2UgY29zdHMgY29tcGFyZWQgdG8gZXhpc3RpbmcgRHluYW1vREIgU3RhbmRhcmQgdGFibGVzLiAqL1xuICBTVEFOREFSRF9JTkZSRVFVRU5UX0FDQ0VTUyA9ICdTVEFOREFSRF9JTkZSRVFVRU5UX0FDQ0VTUycsXG59XG5cbi8qKlxuICogSnVzdCBhIGNvbnZlbmllbnQgd2F5IHRvIGtlZXAgdHJhY2sgb2YgYm90aCBhdHRyaWJ1dGVzXG4gKi9cbmludGVyZmFjZSBTY2FsYWJsZUF0dHJpYnV0ZVBhaXIge1xuICBzY2FsYWJsZVJlYWRBdHRyaWJ1dGU/OiBTY2FsYWJsZVRhYmxlQXR0cmlidXRlO1xuICBzY2FsYWJsZVdyaXRlQXR0cmlidXRlPzogU2NhbGFibGVUYWJsZUF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBBbiBpbmxpbmUgcG9saWN5IHRoYXQgaXMgbG9naWNhbGx5IGJvdW5kIHRvIHRoZSBzb3VyY2UgdGFibGUgb2YgYSBEeW5hbW9EQiBHbG9iYWwgVGFibGVzXG4gKiBcImNsdXN0ZXJcIi4gVGhpcyBpcyBoZXJlIHRvIGVuc3VyZSBwZXJtaXNzaW9ucyBhcmUgcmVtb3ZlZCBhcyBwYXJ0IG9mIChhbmQgbm90IGJlZm9yZSkgdGhlXG4gKiBDbGVhblVwIHBoYXNlIG9mIGEgc3RhY2sgdXBkYXRlLCB3aGVuIGEgcmVwbGljYSBpcyByZW1vdmVkIChvciB0aGUgZW50aXJlIFwiY2x1c3RlclwiIGdldHNcbiAqIHJlcGxhY2VkKS5cbiAqXG4gKiBJZiBzdGF0ZW1lbnRzIGFyZSBhZGRlZCBkaXJlY3RseSB0byB0aGUgaGFuZGxlciByb2xlcyAoYXMgb3Bwb3NlZCB0byBpbiBhIHNlcGFyYXRlIGlubGluZVxuICogcG9saWN5IHJlc291cmNlKSwgbmV3IHBlcm1pc3Npb25zIGFyZSBpbiBlZmZlY3QgYmVmb3JlIGNsZWFuIHVwIGhhcHBlbnMsIGFuZCBzbyByZXBsaWNhcyB0aGF0XG4gKiBuZWVkIHRvIGJlIGRyb3BwZWQgY2FuIG5vIGxvbmdlciBiZSBkdWUgdG8gbGFjayBvZiBwZXJtaXNzaW9ucy5cbiAqL1xuY2xhc3MgU291cmNlVGFibGVBdHRhY2hlZFBvbGljeSBleHRlbmRzIENvcmVDb25zdHJ1Y3QgaW1wbGVtZW50cyBpYW0uSUdyYW50YWJsZSB7XG4gIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbDogaWFtLklQcmluY2lwYWw7XG4gIHB1YmxpYyByZWFkb25seSBwb2xpY3k6IGlhbS5JTWFuYWdlZFBvbGljeTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc291cmNlVGFibGU6IFRhYmxlLCByb2xlOiBpYW0uSVJvbGUpIHtcbiAgICBzdXBlcihzb3VyY2VUYWJsZSwgYFNvdXJjZVRhYmxlQXR0YWNoZWRNYW5hZ2VkUG9saWN5LSR7TmFtZXMubm9kZVVuaXF1ZUlkKHJvbGUubm9kZSl9YCk7XG5cbiAgICBjb25zdCBwb2xpY3kgPSBuZXcgaWFtLk1hbmFnZWRQb2xpY3kodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgLy8gQSBDRiB1cGRhdGUgb2YgdGhlIGRlc2NyaXB0aW9uIHByb3BlcnR5IG9mIGEgbWFuYWdlZCBwb2xpY3kgcmVxdWlyZXNcbiAgICAgIC8vIGEgcmVwbGFjZW1lbnQuIFVzZSB0aGUgdGFibGUgbmFtZSBpbiB0aGUgZGVzY3JpcHRpb24gdG8gZm9yY2UgYSBtYW5hZ2VkXG4gICAgICAvLyBwb2xpY3kgcmVwbGFjZW1lbnQgd2hlbiB0aGUgdGFibGUgbmFtZSBjaGFuZ2VzLiBUaGlzIHdheSB3ZSBwcmVzZXJ2ZSBwZXJtaXNzaW9uc1xuICAgICAgLy8gdG8gZGVsZXRlIG9sZCByZXBsaWNhcyBpbiBjYXNlIG9mIGEgdGFibGUgcmVwbGFjZW1lbnQuXG4gICAgICBkZXNjcmlwdGlvbjogYER5bmFtb0RCIHJlcGxpY2F0aW9uIG1hbmFnZWQgcG9saWN5IGZvciB0YWJsZSAke3NvdXJjZVRhYmxlLnRhYmxlTmFtZX1gLFxuICAgICAgcm9sZXM6IFtyb2xlXSxcbiAgICB9KTtcbiAgICB0aGlzLnBvbGljeSA9IHBvbGljeTtcbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQcmluY2lwYWwocm9sZSwgcG9saWN5KTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIGBJUHJpbmNpcGFsYCBlbnRpdHkgdGhhdCBjYW4gYmUgdXNlZCBhcyB0aGUgdGFyZ2V0IG9mIGBncmFudGAgY2FsbHMsIHVzZWQgYnkgdGhlXG4gKiBgU291cmNlVGFibGVBdHRhY2hlZFBvbGljeWAgY2xhc3Mgc28gaXQgY2FuIGFjdCBhcyBhbiBgSUdyYW50YWJsZWAuXG4gKi9cbmNsYXNzIFNvdXJjZVRhYmxlQXR0YWNoZWRQcmluY2lwYWwgZXh0ZW5kcyBpYW0uUHJpbmNpcGFsQmFzZSB7XG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHJvbGU6IGlhbS5JUm9sZSwgcHJpdmF0ZSByZWFkb25seSBwb2xpY3k6IGlhbS5NYW5hZ2VkUG9saWN5KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcG9saWN5RnJhZ21lbnQoKTogaWFtLlByaW5jaXBhbFBvbGljeUZyYWdtZW50IHtcbiAgICByZXR1cm4gdGhpcy5yb2xlLnBvbGljeUZyYWdtZW50O1xuICB9XG5cbiAgcHVibGljIGFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCk6IGlhbS5BZGRUb1ByaW5jaXBhbFBvbGljeVJlc3VsdCB7XG4gICAgdGhpcy5wb2xpY3kuYWRkU3RhdGVtZW50cyhzdGF0ZW1lbnQpO1xuICAgIHJldHVybiB7XG4gICAgICBwb2xpY3lEZXBlbmRhYmxlOiB0aGlzLnBvbGljeSxcbiAgICAgIHN0YXRlbWVudEFkZGVkOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZGVkdXBlU3RyaW5nKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19 |
\ | No newline at end of file |