@aws-cdk/aws-glue-alpha
Version:
The CDK Construct Library for AWS::Glue
336 lines • 38.9 kB
JavaScript
"use strict";
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.S3Table = exports.TableEncryption = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_glue_1 = require("aws-cdk-lib/aws-glue");
const kms = require("aws-cdk-lib/aws-kms");
const s3 = require("aws-cdk-lib/aws-s3");
const helpers_internal_1 = require("aws-cdk-lib/core/lib/helpers-internal");
const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource");
const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable");
const table_base_1 = require("./table-base");
/**
* Encryption options for a Table.
*
* @see https://docs.aws.amazon.com/athena/latest/ug/encryption.html
*/
var TableEncryption;
(function (TableEncryption) {
/**
* Server side encryption (SSE) with an Amazon S3-managed key.
*
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html
*/
TableEncryption["S3_MANAGED"] = "SSE-S3";
/**
* Server-side encryption (SSE) with an AWS KMS key managed by the account owner.
*
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
*/
TableEncryption["KMS"] = "SSE-KMS";
/**
* Server-side encryption (SSE) with an AWS KMS key managed by the KMS service.
*/
TableEncryption["KMS_MANAGED"] = "SSE-KMS-MANAGED";
/**
* Client-side encryption (CSE) with an AWS KMS key managed by the account owner.
*
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html
*/
TableEncryption["CLIENT_SIDE_KMS"] = "CSE-KMS";
})(TableEncryption || (exports.TableEncryption = TableEncryption = {}));
/**
* A Glue table that targets a S3 dataset.
* @resource AWS::Glue::Table
*/
let S3Table = (() => {
let _classDecorators = [prop_injectable_1.propertyInjectable];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = table_base_1.TableBase;
let _instanceExtraInitializers = [];
let _get_tableName_decorators;
let _get_tableArn_decorators;
let _grantRead_decorators;
let _grantWrite_decorators;
let _grantReadWrite_decorators;
var S3Table = class extends _classSuper {
static { _classThis = this; }
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_get_tableName_decorators = [helpers_internal_1.memoizedGetter];
_get_tableArn_decorators = [helpers_internal_1.memoizedGetter];
_grantRead_decorators = [(0, metadata_resource_1.MethodMetadata)()];
_grantWrite_decorators = [(0, metadata_resource_1.MethodMetadata)()];
_grantReadWrite_decorators = [(0, metadata_resource_1.MethodMetadata)()];
__esDecorate(this, null, _get_tableName_decorators, { kind: "getter", name: "tableName", static: false, private: false, access: { has: obj => "tableName" in obj, get: obj => obj.tableName }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _get_tableArn_decorators, { kind: "getter", name: "tableArn", static: false, private: false, access: { has: obj => "tableArn" in obj, get: obj => obj.tableArn }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _grantRead_decorators, { kind: "method", name: "grantRead", static: false, private: false, access: { has: obj => "grantRead" in obj, get: obj => obj.grantRead }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _grantWrite_decorators, { kind: "method", name: "grantWrite", static: false, private: false, access: { has: obj => "grantWrite" in obj, get: obj => obj.grantWrite }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _grantReadWrite_decorators, { kind: "method", name: "grantReadWrite", static: false, private: false, access: { has: obj => "grantReadWrite" in obj, get: obj => obj.grantReadWrite }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
S3Table = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-glue-alpha.S3Table", version: "2.257.0-alpha.0" };
/** Uniquely identifies this class. */
static PROPERTY_INJECTION_ID = '@aws-cdk.aws-glue-alpha.S3Table';
resource = __runInitializers(this, _instanceExtraInitializers);
/**
* S3 bucket in which the table's data resides.
*/
bucket;
/**
* S3 Key Prefix under which this table's files are stored in S3.
*/
s3Prefix;
/**
* The type of encryption enabled for the table.
*/
encryption;
/**
* The KMS key used to secure the data if `encryption` is set to `CSE-KMS` or `SSE-KMS`. Otherwise, `undefined`.
*/
encryptionKey;
/**
* This table's partition indexes.
*/
partitionIndexes;
tableResource;
constructor(scope, id, props) {
super(scope, id, props);
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_S3TableProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, S3Table);
}
throw error;
}
// Enhanced CDK Analytics Telemetry
(0, metadata_resource_1.addConstructMetadata)(this, props);
this.s3Prefix = props.s3Prefix ?? '';
const { bucket, encryption, encryptionKey } = createBucket(this, props);
this.bucket = bucket;
this.encryption = encryption;
this.encryptionKey = encryptionKey;
this.resource = new aws_glue_1.CfnTable(this, 'Table', {
catalogId: props.database.catalogId,
databaseName: props.database.databaseName,
tableInput: {
name: this.physicalName,
description: props.description || `${this.physicalName} generated by CDK`,
partitionKeys: renderColumns(props.partitionKeys),
parameters: {
'classification': props.dataFormat.classificationString?.value,
'has_encrypted_data': true,
'partition_filtering.enabled': props.enablePartitionFiltering,
...this.parameters,
},
storageDescriptor: {
location: `s3://${this.bucket.bucketName}/${this.s3Prefix}`,
compressed: this.compressed,
storedAsSubDirectories: props.storedAsSubDirectories ?? false,
columns: renderColumns(props.columns),
inputFormat: props.dataFormat.inputFormat.className,
outputFormat: props.dataFormat.outputFormat.className,
serdeInfo: {
serializationLibrary: props.dataFormat.serializationLibrary.className,
},
parameters: props.storageParameters ? props.storageParameters.reduce((acc, param) => {
if (param.key in acc) {
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `DuplicateStorageParameterKey`, `Duplicate storage parameter key: ${param.key}`, this);
}
const key = param.key;
acc[key] = param.value;
return acc;
}, {}) : undefined,
},
tableType: 'EXTERNAL_TABLE',
},
});
this.tableResource = this.resource;
this.node.defaultChild = this.resource;
// Partition index creation relies on created table.
if (props.partitionIndexes) {
this.partitionIndexes = props.partitionIndexes;
this.partitionIndexes.forEach((index) => this.addPartitionIndex(index));
}
}
/**
* Name of this table.
*/
get tableName() {
return this.getResourceNameAttribute(this.resource.ref);
}
/**
* ARN of this table.
*/
get tableArn() {
return this.stack.formatArn({
service: 'glue',
resource: 'table',
resourceName: `${this.database.databaseName}/${this.tableName}`,
});
}
/**
* Grant read permissions to the table and the underlying data stored in S3 to an IAM principal.
* [disable-awslint:no-grants]
*
* @param grantee the principal
*/
grantRead(grantee) {
const ret = this.grant(grantee, readPermissions);
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
this.encryptionKey.grantDecrypt(grantee);
}
this.bucket.grantRead(grantee, this.generateS3PrefixForGrant());
return ret;
}
/**
* Grant write permissions to the table and the underlying data stored in S3 to an IAM principal.
* [disable-awslint:no-grants]
*
* @param grantee the principal
*/
grantWrite(grantee) {
const ret = this.grant(grantee, writePermissions);
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
this.encryptionKey.grantEncrypt(grantee);
}
this.bucket.grantWrite(grantee, this.generateS3PrefixForGrant());
return ret;
}
/**
* Grant read and write permissions to the table and the underlying data stored in S3 to an IAM principal.
* [disable-awslint:no-grants]
*
* @param grantee the principal
*/
grantReadWrite(grantee) {
const ret = this.grant(grantee, [...readPermissions, ...writePermissions]);
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
this.encryptionKey.grantEncryptDecrypt(grantee);
}
this.bucket.grantReadWrite(grantee, this.generateS3PrefixForGrant());
return ret;
}
generateS3PrefixForGrant() {
return this.s3Prefix + '*';
}
static {
__runInitializers(_classThis, _classExtraInitializers);
}
};
return S3Table = _classThis;
})();
exports.S3Table = S3Table;
const readPermissions = [
'glue:BatchGetPartition',
'glue:GetPartition',
'glue:GetPartitions',
'glue:GetTable',
'glue:GetTables',
'glue:GetTableVersion',
'glue:GetTableVersions',
];
const writePermissions = [
'glue:BatchCreatePartition',
'glue:BatchDeletePartition',
'glue:CreatePartition',
'glue:DeletePartition',
'glue:UpdatePartition',
];
// map TableEncryption to bucket's SSE configuration (s3.BucketEncryption)
const encryptionMappings = {
[TableEncryption.S3_MANAGED]: s3.BucketEncryption.S3_MANAGED,
[TableEncryption.KMS_MANAGED]: s3.BucketEncryption.KMS_MANAGED,
[TableEncryption.KMS]: s3.BucketEncryption.KMS,
[TableEncryption.CLIENT_SIDE_KMS]: s3.BucketEncryption.S3_MANAGED,
};
// create the bucket to store a table's data depending on the `encryption` and `encryptionKey` properties.
function createBucket(table, props) {
let bucket = props.bucket;
if (bucket && (props.encryption !== undefined && props.encryption !== TableEncryption.CLIENT_SIDE_KMS)) {
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `EncryptionWithProvidedBucket`, 'you can not specify encryption settings if you also provide a bucket');
}
const encryption = props.encryption || TableEncryption.S3_MANAGED;
let encryptionKey;
if (encryption === TableEncryption.CLIENT_SIDE_KMS && props.encryptionKey === undefined) {
// CSE-KMS should behave the same as SSE-KMS - use the provided key or create one automatically
// Since Bucket only knows about SSE, we repeat the logic for CSE-KMS at the Table level.
encryptionKey = new kms.Key(table, 'Key');
}
else {
encryptionKey = props.encryptionKey;
}
// create the bucket if none was provided
if (!bucket) {
if (encryption === TableEncryption.CLIENT_SIDE_KMS) {
bucket = new s3.Bucket(table, 'Bucket');
}
else {
bucket = new s3.Bucket(table, 'Bucket', {
encryption: encryptionMappings[encryption],
encryptionKey,
});
encryptionKey = bucket.encryptionKey;
}
}
return {
bucket,
encryption,
encryptionKey,
};
}
function renderColumns(columns) {
if (columns === undefined) {
return undefined;
}
return columns.map(column => {
return {
name: column.name,
type: column.type.inputString,
comment: column.comment,
};
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMtdGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzMy10YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw2Q0FBdUU7QUFDdkUsbURBQWdEO0FBRWhELDJDQUEyQztBQUMzQyx5Q0FBeUM7QUFDekMsNEVBQTRFO0FBQzVFLDhFQUE4RjtBQUM5RiwwRUFBMEU7QUFJMUUsNkNBQXlDO0FBRXpDOzs7O0dBSUc7QUFDSCxJQUFZLGVBMEJYO0FBMUJELFdBQVksZUFBZTtJQUN6Qjs7OztPQUlHO0lBQ0gsd0NBQXFCLENBQUE7SUFFckI7Ozs7T0FJRztJQUNILGtDQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILGtEQUErQixDQUFBO0lBRS9COzs7O09BSUc7SUFDSCw4Q0FBMkIsQ0FBQTtBQUM3QixDQUFDLEVBMUJXLGVBQWUsK0JBQWYsZUFBZSxRQTBCMUI7QUF1Q0Q7OztHQUdHO0lBRVUsT0FBTzs0QkFEbkIsb0NBQWtCOzs7O3NCQUNVLHNCQUFTOzs7Ozs7O3VCQUFqQixTQUFRLFdBQVM7Ozs7eUNBaUduQyxpQ0FBYzt3Q0FRZCxpQ0FBYztxQ0FlZCxJQUFBLGtDQUFjLEdBQUU7c0NBY2hCLElBQUEsa0NBQWMsR0FBRTswQ0FjaEIsSUFBQSxrQ0FBYyxHQUFFO1lBbERqQixrTEFBVyxTQUFTLDZEQUVuQjtZQU1ELCtLQUFXLFFBQVEsNkRBTWxCO1lBU0QsOEtBQU8sU0FBUyw2REFLZjtZQVNELGlMQUFPLFVBQVUsNkRBS2hCO1lBU0QsNkxBQU8sY0FBYyw2REFLcEI7WUExSkgsNktBK0pDOzs7OztRQTlKQyxzQ0FBc0M7UUFDL0IsTUFBTSxDQUFVLHFCQUFxQixHQUFXLGlDQUFpQyxDQUFDO1FBRWpGLFFBQVEsR0FKTCxtREFBTyxDQUlTO1FBRTNCOztXQUVHO1FBQ2EsTUFBTSxDQUFhO1FBRW5DOztXQUVHO1FBQ2EsUUFBUSxDQUFTO1FBRWpDOztXQUVHO1FBQ2EsVUFBVSxDQUFrQjtRQUU1Qzs7V0FFRztRQUNhLGFBQWEsQ0FBWTtRQUV6Qzs7V0FFRztRQUNhLGdCQUFnQixDQUFvQjtRQUVqQyxhQUFhLENBQVc7UUFFM0MsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFtQjtZQUMzRCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQzs7Ozs7O21EQWxDZixPQUFPOzs7O1lBbUNoQixtQ0FBbUM7WUFDbkMsSUFBQSx3Q0FBb0IsRUFBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQztZQUNyQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsR0FBRyxZQUFZLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1lBQzdCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1lBRW5DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxtQkFBUSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUU7Z0JBQzFDLFNBQVMsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLFNBQVM7Z0JBRW5DLFlBQVksRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVk7Z0JBRXpDLFVBQVUsRUFBRTtvQkFDVixJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVk7b0JBQ3ZCLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksbUJBQW1CO29CQUV6RSxhQUFhLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUM7b0JBRWpELFVBQVUsRUFBRTt3QkFDVixnQkFBZ0IsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLG9CQUFvQixFQUFFLEtBQUs7d0JBQzlELG9CQUFvQixFQUFFLElBQUk7d0JBQzFCLDZCQUE2QixFQUFFLEtBQUssQ0FBQyx3QkFBd0I7d0JBQzdELEdBQUcsSUFBSSxDQUFDLFVBQVU7cUJBQ25CO29CQUNELGlCQUFpQixFQUFFO3dCQUNqQixRQUFRLEVBQUUsUUFBUSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO3dCQUMzRCxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7d0JBQzNCLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxzQkFBc0IsSUFBSSxLQUFLO3dCQUM3RCxPQUFPLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7d0JBQ3JDLFdBQVcsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxTQUFTO3dCQUNuRCxZQUFZLEVBQUUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsU0FBUzt3QkFDckQsU0FBUyxFQUFFOzRCQUNULG9CQUFvQixFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsU0FBUzt5QkFDdEU7d0JBQ0QsVUFBVSxFQUFFLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRTs0QkFDbEYsSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO2dDQUNyQixNQUFNLElBQUksNkJBQWUsQ0FBQyxJQUFBLHNCQUFHLEVBQUEsOEJBQThCLEVBQUUsb0NBQW9DLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQzs0QkFDdEgsQ0FBQzs0QkFDRCxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDOzRCQUN0QixHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQzs0QkFDdkIsT0FBTyxHQUFHLENBQUM7d0JBQ2IsQ0FBQyxFQUFFLEVBQStCLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztxQkFDaEQ7b0JBRUQsU0FBUyxFQUFFLGdCQUFnQjtpQkFDNUI7YUFDRixDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUV2QyxvREFBb0Q7WUFDcEQsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDL0MsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDMUUsQ0FBQztTQUNGO1FBRUQ7O1dBRUc7UUFFSCxJQUFXLFNBQVM7WUFDbEIsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUN6RDtRQUVEOztXQUVHO1FBRUgsSUFBVyxRQUFRO1lBQ2pCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7Z0JBQzFCLE9BQU8sRUFBRSxNQUFNO2dCQUNmLFFBQVEsRUFBRSxPQUFPO2dCQUNqQixZQUFZLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO2FBQ2hFLENBQUMsQ0FBQztTQUNKO1FBRUQ7Ozs7O1dBS0c7UUFFSSxTQUFTLENBQUMsT0FBdUI7WUFDdEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7WUFDakQsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssZUFBZSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQUMsQ0FBQztZQUM1SCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUMsQ0FBQztZQUNoRSxPQUFPLEdBQUcsQ0FBQztTQUNaO1FBRUQ7Ozs7O1dBS0c7UUFFSSxVQUFVLENBQUMsT0FBdUI7WUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUNsRCxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxlQUFlLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFBQyxDQUFDO1lBQzVILElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLE9BQU8sR0FBRyxDQUFDO1NBQ1o7UUFFRDs7Ozs7V0FLRztRQUVJLGNBQWMsQ0FBQyxPQUF1QjtZQUMzQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsZUFBZSxFQUFFLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1lBQzNFLElBQUksSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFBQyxJQUFJLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQUMsQ0FBQztZQUNuSSxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUMsQ0FBQztZQUNyRSxPQUFPLEdBQUcsQ0FBQztTQUNaO1FBRVMsd0JBQXdCO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUM7U0FDNUI7O1lBOUpVLHVEQUFPOzs7OztBQUFQLDBCQUFPO0FBaUtwQixNQUFNLGVBQWUsR0FBRztJQUN0Qix3QkFBd0I7SUFDeEIsbUJBQW1CO0lBQ25CLG9CQUFvQjtJQUNwQixlQUFlO0lBQ2YsZ0JBQWdCO0lBQ2hCLHNCQUFzQjtJQUN0Qix1QkFBdUI7Q0FDeEIsQ0FBQztBQUVGLE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkIsMkJBQTJCO0lBQzNCLDJCQUEyQjtJQUMzQixzQkFBc0I7SUFDdEIsc0JBQXNCO0lBQ3RCLHNCQUFzQjtDQUN2QixDQUFDO0FBRUYsMEVBQTBFO0FBQzFFLE1BQU0sa0JBQWtCLEdBQUc7SUFDekIsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFVBQVU7SUFDNUQsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFdBQVc7SUFDOUQsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLEdBQUc7SUFDOUMsQ0FBQyxlQUFlLENBQUMsZUFBZSxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFVBQVU7Q0FDbEUsQ0FBQztBQUVGLDBHQUEwRztBQUMxRyxTQUFTLFlBQVksQ0FBQyxLQUFjLEVBQUUsS0FBbUI7SUFDdkQsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUUxQixJQUFJLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxVQUFVLEtBQUssZUFBZSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDdkcsTUFBTSxJQUFJLHFDQUF1QixDQUFDLElBQUEsc0JBQUcsRUFBQSw4QkFBOEIsRUFBRSxzRUFBc0UsQ0FBQyxDQUFDO0lBQy9JLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLGVBQWUsQ0FBQyxVQUFVLENBQUM7SUFFbEUsSUFBSSxhQUFtQyxDQUFDO0lBQ3hDLElBQUksVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN4RiwrRkFBK0Y7UUFDL0YseUZBQXlGO1FBQ3pGLGFBQWEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzVDLENBQUM7U0FBTSxDQUFDO1FBQ04sYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7SUFDdEMsQ0FBQztJQUVELHlDQUF5QztJQUN6QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixJQUFJLFVBQVUsS0FBSyxlQUFlLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDbkQsTUFBTSxHQUFHLElBQUksRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDMUMsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLEdBQUcsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUU7Z0JBQ3RDLFVBQVUsRUFBRSxrQkFBa0IsQ0FBQyxVQUFVLENBQUM7Z0JBQzFDLGFBQWE7YUFDZCxDQUFDLENBQUM7WUFDSCxhQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUN2QyxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxNQUFNO1FBQ04sVUFBVTtRQUNWLGFBQWE7S0FDZCxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLE9BQWdDO0lBQ3JELElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzFCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDMUIsT0FBTztZQUNMLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtZQUNqQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXO1lBQzdCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztTQUN4QixDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IENmblRhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWdsdWUnO1xuaW1wb3J0IHR5cGUgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBrbXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWttcyc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0IHsgbWVtb2l6ZWRHZXR0ZXIsIGxpdCB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL2hlbHBlcnMtaW50ZXJuYWwnO1xuaW1wb3J0IHsgYWRkQ29uc3RydWN0TWV0YWRhdGEsIE1ldGhvZE1ldGFkYXRhIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvbWV0YWRhdGEtcmVzb3VyY2UnO1xuaW1wb3J0IHsgcHJvcGVydHlJbmplY3RhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvcHJvcC1pbmplY3RhYmxlJztcbmltcG9ydCB0eXBlIHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgdHlwZSB7IENvbHVtbiB9IGZyb20gJy4vc2NoZW1hJztcbmltcG9ydCB0eXBlIHsgUGFydGl0aW9uSW5kZXgsIFRhYmxlQmFzZVByb3BzIH0gZnJvbSAnLi90YWJsZS1iYXNlJztcbmltcG9ydCB7IFRhYmxlQmFzZSB9IGZyb20gJy4vdGFibGUtYmFzZSc7XG5cbi8qKlxuICogRW5jcnlwdGlvbiBvcHRpb25zIGZvciBhIFRhYmxlLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2F0aGVuYS9sYXRlc3QvdWcvZW5jcnlwdGlvbi5odG1sXG4gKi9cbmV4cG9ydCBlbnVtIFRhYmxlRW5jcnlwdGlvbiB7XG4gIC8qKlxuICAgKiBTZXJ2ZXIgc2lkZSBlbmNyeXB0aW9uIChTU0UpIHdpdGggYW4gQW1hem9uIFMzLW1hbmFnZWQga2V5LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25TMy9sYXRlc3QvZGV2L1VzaW5nU2VydmVyU2lkZUVuY3J5cHRpb24uaHRtbFxuICAgKi9cbiAgUzNfTUFOQUdFRCA9ICdTU0UtUzMnLFxuXG4gIC8qKlxuICAgKiBTZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIChTU0UpIHdpdGggYW4gQVdTIEtNUyBrZXkgbWFuYWdlZCBieSB0aGUgYWNjb3VudCBvd25lci5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L2Rldi9Vc2luZ0tNU0VuY3J5cHRpb24uaHRtbFxuICAgKi9cbiAgS01TID0gJ1NTRS1LTVMnLFxuXG4gIC8qKlxuICAgKiBTZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIChTU0UpIHdpdGggYW4gQVdTIEtNUyBrZXkgbWFuYWdlZCBieSB0aGUgS01TIHNlcnZpY2UuXG4gICAqL1xuICBLTVNfTUFOQUdFRCA9ICdTU0UtS01TLU1BTkFHRUQnLFxuXG4gIC8qKlxuICAgKiBDbGllbnQtc2lkZSBlbmNyeXB0aW9uIChDU0UpIHdpdGggYW4gQVdTIEtNUyBrZXkgbWFuYWdlZCBieSB0aGUgYWNjb3VudCBvd25lci5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L2Rldi9Vc2luZ0NsaWVudFNpZGVFbmNyeXB0aW9uLmh0bWxcbiAgICovXG4gIENMSUVOVF9TSURFX0tNUyA9ICdDU0UtS01TJyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTM1RhYmxlUHJvcHMgZXh0ZW5kcyBUYWJsZUJhc2VQcm9wcyB7XG4gIC8qKlxuICAgKiBTMyBidWNrZXQgaW4gd2hpY2ggdG8gc3RvcmUgZGF0YS5cbiAgICpcbiAgICogQGRlZmF1bHQgb25lIGlzIGNyZWF0ZWQgZm9yIHlvdVxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0PzogczMuSUJ1Y2tldDtcblxuICAvKipcbiAgICogUzMgcHJlZml4IHVuZGVyIHdoaWNoIHRhYmxlIG9iamVjdHMgYXJlIHN0b3JlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBwcmVmaXguIFRoZSBkYXRhIHdpbGwgYmUgc3RvcmVkIHVuZGVyIHRoZSByb290IG9mIHRoZSBidWNrZXQuXG4gICAqL1xuICByZWFkb25seSBzM1ByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGtpbmQgb2YgZW5jcnlwdGlvbiB0byBzZWN1cmUgdGhlIGRhdGEgd2l0aC5cbiAgICpcbiAgICogWW91IGNhbiBvbmx5IHByb3ZpZGUgdGhpcyBvcHRpb24gaWYgeW91IGFyZSBub3QgZXhwbGljaXRseSBwYXNzaW5nIGluIGEgYnVja2V0LlxuICAgKlxuICAgKiBJZiB5b3UgY2hvb3NlIGBTU0UtS01TYCwgeW91ICpjYW4qIHByb3ZpZGUgYW4gdW4tbWFuYWdlZCBLTVMga2V5IHdpdGggYGVuY3J5cHRpb25LZXlgLlxuICAgKiBJZiB5b3UgY2hvb3NlIGBDU0UtS01TYCwgeW91ICptdXN0KiBwcm92aWRlIGFuIHVuLW1hbmFnZWQgS01TIGtleSB3aXRoIGBlbmNyeXB0aW9uS2V5YC5cbiAgICpcbiAgICogQGRlZmF1bHQgQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VEXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uPzogVGFibGVFbmNyeXB0aW9uO1xuXG4gIC8qKlxuICAgKiBFeHRlcm5hbCBLTVMga2V5IHRvIHVzZSBmb3IgYnVja2V0IGVuY3J5cHRpb24uXG4gICAqXG4gICAqIFRoZSBgZW5jcnlwdGlvbmAgcHJvcGVydHkgbXVzdCBiZSBgU1NFLUtNU2Agb3IgYENTRS1LTVNgLlxuICAgKlxuICAgKiBAZGVmYXVsdCBrZXkgaXMgbWFuYWdlZCBieSBLTVMuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG59XG5cbi8qKlxuICogQSBHbHVlIHRhYmxlIHRoYXQgdGFyZ2V0cyBhIFMzIGRhdGFzZXQuXG4gKiBAcmVzb3VyY2UgQVdTOjpHbHVlOjpUYWJsZVxuICovXG5AcHJvcGVydHlJbmplY3RhYmxlXG5leHBvcnQgY2xhc3MgUzNUYWJsZSBleHRlbmRzIFRhYmxlQmFzZSB7XG4gIC8qKiBVbmlxdWVseSBpZGVudGlmaWVzIHRoaXMgY2xhc3MuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUFJPUEVSVFlfSU5KRUNUSU9OX0lEOiBzdHJpbmcgPSAnQGF3cy1jZGsuYXdzLWdsdWUtYWxwaGEuUzNUYWJsZSc7XG5cbiAgcHJpdmF0ZSByZXNvdXJjZTogQ2ZuVGFibGU7XG5cbiAgLyoqXG4gICAqIFMzIGJ1Y2tldCBpbiB3aGljaCB0aGUgdGFibGUncyBkYXRhIHJlc2lkZXMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYnVja2V0OiBzMy5JQnVja2V0O1xuXG4gIC8qKlxuICAgKiBTMyBLZXkgUHJlZml4IHVuZGVyIHdoaWNoIHRoaXMgdGFibGUncyBmaWxlcyBhcmUgc3RvcmVkIGluIFMzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHMzUHJlZml4OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIGVuY3J5cHRpb24gZW5hYmxlZCBmb3IgdGhlIHRhYmxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGVuY3J5cHRpb246IFRhYmxlRW5jcnlwdGlvbjtcblxuICAvKipcbiAgICogVGhlIEtNUyBrZXkgdXNlZCB0byBzZWN1cmUgdGhlIGRhdGEgaWYgYGVuY3J5cHRpb25gIGlzIHNldCB0byBgQ1NFLUtNU2Agb3IgYFNTRS1LTVNgLiBPdGhlcndpc2UsIGB1bmRlZmluZWRgLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcblxuICAvKipcbiAgICogVGhpcyB0YWJsZSdzIHBhcnRpdGlvbiBpbmRleGVzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBhcnRpdGlvbkluZGV4ZXM/OiBQYXJ0aXRpb25JbmRleFtdO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSB0YWJsZVJlc291cmNlOiBDZm5UYWJsZTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogUzNUYWJsZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG4gICAgLy8gRW5oYW5jZWQgQ0RLIEFuYWx5dGljcyBUZWxlbWV0cnlcbiAgICBhZGRDb25zdHJ1Y3RNZXRhZGF0YSh0aGlzLCBwcm9wcyk7XG4gICAgdGhpcy5zM1ByZWZpeCA9IHByb3BzLnMzUHJlZml4ID8/ICcnO1xuICAgIGNvbnN0IHsgYnVja2V0LCBlbmNyeXB0aW9uLCBlbmNyeXB0aW9uS2V5IH0gPSBjcmVhdGVCdWNrZXQodGhpcywgcHJvcHMpO1xuICAgIHRoaXMuYnVja2V0ID0gYnVja2V0O1xuICAgIHRoaXMuZW5jcnlwdGlvbiA9IGVuY3J5cHRpb247XG4gICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gZW5jcnlwdGlvbktleTtcblxuICAgIHRoaXMucmVzb3VyY2UgPSBuZXcgQ2ZuVGFibGUodGhpcywgJ1RhYmxlJywge1xuICAgICAgY2F0YWxvZ0lkOiBwcm9wcy5kYXRhYmFzZS5jYXRhbG9nSWQsXG5cbiAgICAgIGRhdGFiYXNlTmFtZTogcHJvcHMuZGF0YWJhc2UuZGF0YWJhc2VOYW1lLFxuXG4gICAgICB0YWJsZUlucHV0OiB7XG4gICAgICAgIG5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAgICBkZXNjcmlwdGlvbjogcHJvcHMuZGVzY3JpcHRpb24gfHwgYCR7dGhpcy5waHlzaWNhbE5hbWV9IGdlbmVyYXRlZCBieSBDREtgLFxuXG4gICAgICAgIHBhcnRpdGlvbktleXM6IHJlbmRlckNvbHVtbnMocHJvcHMucGFydGl0aW9uS2V5cyksXG5cbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICdjbGFzc2lmaWNhdGlvbic6IHByb3BzLmRhdGFGb3JtYXQuY2xhc3NpZmljYXRpb25TdHJpbmc/LnZhbHVlLFxuICAgICAgICAgICdoYXNfZW5jcnlwdGVkX2RhdGEnOiB0cnVlLFxuICAgICAgICAgICdwYXJ0aXRpb25fZmlsdGVyaW5nLmVuYWJsZWQnOiBwcm9wcy5lbmFibGVQYXJ0aXRpb25GaWx0ZXJpbmcsXG4gICAgICAgICAgLi4udGhpcy5wYXJhbWV0ZXJzLFxuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlRGVzY3JpcHRvcjoge1xuICAgICAgICAgIGxvY2F0aW9uOiBgczM6Ly8ke3RoaXMuYnVja2V0LmJ1Y2tldE5hbWV9LyR7dGhpcy5zM1ByZWZpeH1gLFxuICAgICAgICAgIGNvbXByZXNzZWQ6IHRoaXMuY29tcHJlc3NlZCxcbiAgICAgICAgICBzdG9yZWRBc1N1YkRpcmVjdG9yaWVzOiBwcm9wcy5zdG9yZWRBc1N1YkRpcmVjdG9yaWVzID8/IGZhbHNlLFxuICAgICAgICAgIGNvbHVtbnM6IHJlbmRlckNvbHVtbnMocHJvcHMuY29sdW1ucyksXG4gICAgICAgICAgaW5wdXRGb3JtYXQ6IHByb3BzLmRhdGFGb3JtYXQuaW5wdXRGb3JtYXQuY2xhc3NOYW1lLFxuICAgICAgICAgIG91dHB1dEZvcm1hdDogcHJvcHMuZGF0YUZvcm1hdC5vdXRwdXRGb3JtYXQuY2xhc3NOYW1lLFxuICAgICAgICAgIHNlcmRlSW5mbzoge1xuICAgICAgICAgICAgc2VyaWFsaXphdGlvbkxpYnJhcnk6IHByb3BzLmRhdGFGb3JtYXQuc2VyaWFsaXphdGlvbkxpYnJhcnkuY2xhc3NOYW1lLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcGFyYW1ldGVyczogcHJvcHMuc3RvcmFnZVBhcmFtZXRlcnMgPyBwcm9wcy5zdG9yYWdlUGFyYW1ldGVycy5yZWR1Y2UoKGFjYywgcGFyYW0pID0+IHtcbiAgICAgICAgICAgIGlmIChwYXJhbS5rZXkgaW4gYWNjKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IobGl0YER1cGxpY2F0ZVN0b3JhZ2VQYXJhbWV0ZXJLZXlgLCBgRHVwbGljYXRlIHN0b3JhZ2UgcGFyYW1ldGVyIGtleTogJHtwYXJhbS5rZXl9YCwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBwYXJhbS5rZXk7XG4gICAgICAgICAgICBhY2Nba2V5XSA9IHBhcmFtLnZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgfSxcblxuICAgICAgICB0YWJsZVR5cGU6ICdFWFRFUk5BTF9UQUJMRScsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy50YWJsZVJlc291cmNlID0gdGhpcy5yZXNvdXJjZTtcbiAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkID0gdGhpcy5yZXNvdXJjZTtcblxuICAgIC8vIFBhcnRpdGlvbiBpbmRleCBjcmVhdGlvbiByZWxpZXMgb24gY3JlYXRlZCB0YWJsZS5cbiAgICBpZiAocHJvcHMucGFydGl0aW9uSW5kZXhlcykge1xuICAgICAgdGhpcy5wYXJ0aXRpb25JbmRleGVzID0gcHJvcHMucGFydGl0aW9uSW5kZXhlcztcbiAgICAgIHRoaXMucGFydGl0aW9uSW5kZXhlcy5mb3JFYWNoKChpbmRleCkgPT4gdGhpcy5hZGRQYXJ0aXRpb25JbmRleChpbmRleCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoaXMgdGFibGUuXG4gICAqL1xuICBAbWVtb2l6ZWRHZXR0ZXJcbiAgcHVibGljIGdldCB0YWJsZU5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5nZXRSZXNvdXJjZU5hbWVBdHRyaWJ1dGUodGhpcy5yZXNvdXJjZS5yZWYpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFSTiBvZiB0aGlzIHRhYmxlLlxuICAgKi9cbiAgQG1lbW9pemVkR2V0dGVyXG4gIHB1YmxpYyBnZXQgdGFibGVBcm4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zdGFjay5mb3JtYXRBcm4oe1xuICAgICAgc2VydmljZTogJ2dsdWUnLFxuICAgICAgcmVzb3VyY2U6ICd0YWJsZScsXG4gICAgICByZXNvdXJjZU5hbWU6IGAke3RoaXMuZGF0YWJhc2UuZGF0YWJhc2VOYW1lfS8ke3RoaXMudGFibGVOYW1lfWAsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBwZXJtaXNzaW9ucyB0byB0aGUgdGFibGUgYW5kIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmVkIGluIFMzIHRvIGFuIElBTSBwcmluY2lwYWwuXG4gICAqIFtkaXNhYmxlLWF3c2xpbnQ6bm8tZ3JhbnRzXVxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSB0aGUgcHJpbmNpcGFsXG4gICAqL1xuICBATWV0aG9kTWV0YWRhdGEoKVxuICBwdWJsaWMgZ3JhbnRSZWFkKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCByZXQgPSB0aGlzLmdyYW50KGdyYW50ZWUsIHJlYWRQZXJtaXNzaW9ucyk7XG4gICAgaWYgKHRoaXMuZW5jcnlwdGlvbktleSAmJiB0aGlzLmVuY3J5cHRpb24gPT09IFRhYmxlRW5jcnlwdGlvbi5DTElFTlRfU0lERV9LTVMpIHsgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50RGVjcnlwdChncmFudGVlKTsgfVxuICAgIHRoaXMuYnVja2V0LmdyYW50UmVhZChncmFudGVlLCB0aGlzLmdlbmVyYXRlUzNQcmVmaXhGb3JHcmFudCgpKTtcbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IHdyaXRlIHBlcm1pc3Npb25zIHRvIHRoZSB0YWJsZSBhbmQgdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZWQgaW4gUzMgdG8gYW4gSUFNIHByaW5jaXBhbC5cbiAgICogW2Rpc2FibGUtYXdzbGludDpuby1ncmFudHNdXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIHRoZSBwcmluY2lwYWxcbiAgICovXG4gIEBNZXRob2RNZXRhZGF0YSgpXG4gIHB1YmxpYyBncmFudFdyaXRlKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCByZXQgPSB0aGlzLmdyYW50KGdyYW50ZWUsIHdyaXRlUGVybWlzc2lvbnMpO1xuICAgIGlmICh0aGlzLmVuY3J5cHRpb25LZXkgJiYgdGhpcy5lbmNyeXB0aW9uID09PSBUYWJsZUVuY3J5cHRpb24uQ0xJRU5UX1NJREVfS01TKSB7IHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHQoZ3JhbnRlZSk7IH1cbiAgICB0aGlzLmJ1Y2tldC5ncmFudFdyaXRlKGdyYW50ZWUsIHRoaXMuZ2VuZXJhdGVTM1ByZWZpeEZvckdyYW50KCkpO1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBhbmQgd3JpdGUgcGVybWlzc2lvbnMgdG8gdGhlIHRhYmxlIGFuZCB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlZCBpbiBTMyB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKiBbZGlzYWJsZS1hd3NsaW50Om5vLWdyYW50c11cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgdGhlIHByaW5jaXBhbFxuICAgKi9cbiAgQE1ldGhvZE1ldGFkYXRhKClcbiAgcHVibGljIGdyYW50UmVhZFdyaXRlKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCByZXQgPSB0aGlzLmdyYW50KGdyYW50ZWUsIFsuLi5yZWFkUGVybWlzc2lvbnMsIC4uLndyaXRlUGVybWlzc2lvbnNdKTtcbiAgICBpZiAodGhpcy5lbmNyeXB0aW9uS2V5ICYmIHRoaXMuZW5jcnlwdGlvbiA9PT0gVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNUykgeyB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChncmFudGVlKTsgfVxuICAgIHRoaXMuYnVja2V0LmdyYW50UmVhZFdyaXRlKGdyYW50ZWUsIHRoaXMuZ2VuZXJhdGVTM1ByZWZpeEZvckdyYW50KCkpO1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVTM1ByZWZpeEZvckdyYW50KCkge1xuICAgIHJldHVybiB0aGlzLnMzUHJlZml4ICsgJyonO1xuICB9XG59XG5cbmNvbnN0IHJlYWRQZXJtaXNzaW9ucyA9IFtcbiAgJ2dsdWU6QmF0Y2hHZXRQYXJ0aXRpb24nLFxuICAnZ2x1ZTpHZXRQYXJ0aXRpb24nLFxuICAnZ2x1ZTpHZXRQYXJ0aXRpb25zJyxcbiAgJ2dsdWU6R2V0VGFibGUnLFxuICAnZ2x1ZTpHZXRUYWJsZXMnLFxuICAnZ2x1ZTpHZXRUYWJsZVZlcnNpb24nLFxuICAnZ2x1ZTpHZXRUYWJsZVZlcnNpb25zJyxcbl07XG5cbmNvbnN0IHdyaXRlUGVybWlzc2lvbnMgPSBbXG4gICdnbHVlOkJhdGNoQ3JlYXRlUGFydGl0aW9uJyxcbiAgJ2dsdWU6QmF0Y2hEZWxldGVQYXJ0aXRpb24nLFxuICAnZ2x1ZTpDcmVhdGVQYXJ0aXRpb24nLFxuICAnZ2x1ZTpEZWxldGVQYXJ0aXRpb24nLFxuICAnZ2x1ZTpVcGRhdGVQYXJ0aXRpb24nLFxuXTtcblxuLy8gbWFwIFRhYmxlRW5jcnlwdGlvbiB0byBidWNrZXQncyBTU0UgY29uZmlndXJhdGlvbiAoczMuQnVja2V0RW5jcnlwdGlvbilcbmNvbnN0IGVuY3J5cHRpb25NYXBwaW5ncyA9IHtcbiAgW1RhYmxlRW5jcnlwdGlvbi5TM19NQU5BR0VEXTogczMuQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICBbVGFibGVFbmNyeXB0aW9uLktNU19NQU5BR0VEXTogczMuQnVja2V0RW5jcnlwdGlvbi5LTVNfTUFOQUdFRCxcbiAgW1RhYmxlRW5jcnlwdGlvbi5LTVNdOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNUyxcbiAgW1RhYmxlRW5jcnlwdGlvbi5DTElFTlRfU0lERV9LTVNdOiBzMy5CdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG59O1xuXG4vLyBjcmVhdGUgdGhlIGJ1Y2tldCB0byBzdG9yZSBhIHRhYmxlJ3MgZGF0YSBkZXBlbmRpbmcgb24gdGhlIGBlbmNyeXB0aW9uYCBhbmQgYGVuY3J5cHRpb25LZXlgIHByb3BlcnRpZXMuXG5mdW5jdGlvbiBjcmVhdGVCdWNrZXQodGFibGU6IFMzVGFibGUsIHByb3BzOiBTM1RhYmxlUHJvcHMpIHtcbiAgbGV0IGJ1Y2tldCA9IHByb3BzLmJ1Y2tldDtcblxuICBpZiAoYnVja2V0ICYmIChwcm9wcy5lbmNyeXB0aW9uICE9PSB1bmRlZmluZWQgJiYgcHJvcHMuZW5jcnlwdGlvbiAhPT0gVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNUykpIHtcbiAgICB0aHJvdyBuZXcgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IobGl0YEVuY3J5cHRpb25XaXRoUHJvdmlkZWRCdWNrZXRgLCAneW91IGNhbiBub3Qgc3BlY2lmeSBlbmNyeXB0aW9uIHNldHRpbmdzIGlmIHlvdSBhbHNvIHByb3ZpZGUgYSBidWNrZXQnKTtcbiAgfVxuXG4gIGNvbnN0IGVuY3J5cHRpb24gPSBwcm9wcy5lbmNyeXB0aW9uIHx8IFRhYmxlRW5jcnlwdGlvbi5TM19NQU5BR0VEO1xuXG4gIGxldCBlbmNyeXB0aW9uS2V5OiBrbXMuSUtleSB8IHVuZGVmaW5lZDtcbiAgaWYgKGVuY3J5cHRpb24gPT09IFRhYmxlRW5jcnlwdGlvbi5DTElFTlRfU0lERV9LTVMgJiYgcHJvcHMuZW5jcnlwdGlvbktleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gQ1NFLUtNUyBzaG91bGQgYmVoYXZlIHRoZSBzYW1lIGFzIFNTRS1LTVMgLSB1c2UgdGhlIHByb3ZpZGVkIGtleSBvciBjcmVhdGUgb25lIGF1dG9tYXRpY2FsbHlcbiAgICAvLyBTaW5jZSBCdWNrZXQgb25seSBrbm93cyBhYm91dCBTU0UsIHdlIHJlcGVhdCB0aGUgbG9naWMgZm9yIENTRS1LTVMgYXQgdGhlIFRhYmxlIGxldmVsLlxuICAgIGVuY3J5cHRpb25LZXkgPSBuZXcga21zLktleSh0YWJsZSwgJ0tleScpO1xuICB9IGVsc2Uge1xuICAgIGVuY3J5cHRpb25LZXkgPSBwcm9wcy5lbmNyeXB0aW9uS2V5O1xuICB9XG5cbiAgLy8gY3JlYXRlIHRoZSBidWNrZXQgaWYgbm9uZSB3YXMgcHJvdmlkZWRcbiAgaWYgKCFidWNrZXQpIHtcbiAgICBpZiAoZW5jcnlwdGlvbiA9PT0gVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNUykge1xuICAgICAgYnVja2V0ID0gbmV3IHMzLkJ1Y2tldCh0YWJsZSwgJ0J1Y2tldCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBidWNrZXQgPSBuZXcgczMuQnVja2V0KHRhYmxlLCAnQnVja2V0Jywge1xuICAgICAgICBlbmNyeXB0aW9uOiBlbmNyeXB0aW9uTWFwcGluZ3NbZW5jcnlwdGlvbl0sXG4gICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICB9KTtcbiAgICAgIGVuY3J5cHRpb25LZXkgPSBidWNrZXQuZW5jcnlwdGlvbktleTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJ1Y2tldCxcbiAgICBlbmNyeXB0aW9uLFxuICAgIGVuY3J5cHRpb25LZXksXG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlbmRlckNvbHVtbnMoY29sdW1ucz86IEFycmF5PENvbHVtbiB8IENvbHVtbj4pIHtcbiAgaWYgKGNvbHVtbnMgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIGNvbHVtbnMubWFwKGNvbHVtbiA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IGNvbHVtbi5uYW1lLFxuICAgICAgdHlwZTogY29sdW1uLnR5cGUuaW5wdXRTdHJpbmcsXG4gICAgICBjb21tZW50OiBjb2x1bW4uY29tbWVudCxcbiAgICB9O1xuICB9KTtcbn1cbiJdfQ==