UNPKG

cdk-efs-assets

Version:

Amazon EFS assets from Github repositories or S3 buckets

309 lines 43.1 kB
"use strict"; var _a, _b, _c, _d; Object.defineProperty(exports, "__esModule", { value: true }); exports.SyncedAccessPoint = exports.SyncEngine = exports.S3ArchiveSyncSource = exports.GithubSyncSource = exports.SyncSource = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const url_1 = require("url"); const cdk = require("aws-cdk-lib"); const ec2 = require("aws-cdk-lib/aws-ec2"); const ecs = require("aws-cdk-lib/aws-ecs"); const efs = require("aws-cdk-lib/aws-efs"); const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); const lambda = require("aws-cdk-lib/aws-lambda"); const secretsmanager = require("aws-cdk-lib/aws-secretsmanager"); const cr = require("aws-cdk-lib/custom-resources"); const cdk_fargate_run_task_1 = require("cdk-fargate-run-task"); const efs_fargate_task_1 = require("./efs-fargate-task"); class SyncSource { static github(props) { return new GithubSyncSource(props); } static s3Archive(props) { return new S3ArchiveSyncSource(props); } } exports.SyncSource = SyncSource; _a = JSII_RTTI_SYMBOL_1; SyncSource[_a] = { fqn: "cdk-efs-assets.SyncSource", version: "0.3.95" }; class GithubSyncSource extends SyncSource { constructor(props) { super(); this.props = props; } /** * @internal * @param accessPoint The EFS Access Point */ _createHandler(accessPoint) { const stack = cdk.Stack.of(accessPoint); const region = stack.region; const vpcSubnets = this.props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }; const timeout = this.props.timeout ?? cdk.Duration.minutes(3); let syncDirectoryPath; if (this.props.syncDirectoryPath === undefined) { // if property is unspecified, use repository name as output directory const parsed = new url_1.URL(this.props.repository); syncDirectoryPath = '/' + path.basename(parsed.pathname, '.git'); } else { syncDirectoryPath = this.props.syncDirectoryPath; } const lambdaEnv = { REPOSITORY_URI: this.props.repository, MOUNT_TARGET: '/mnt/efsmount', SYNC_PATH: syncDirectoryPath, }; if (this.props.secret) { lambdaEnv.GITHUB_SECRET_ID = this.props.secret.id; lambdaEnv.GITHUB_SECRET_KEY = this.props.secret.key; } const handler = new lambda.Function(accessPoint, 'GithubHandler', { runtime: lambda.Runtime.PYTHON_3_8, code: lambda.Code.fromAsset(path.join(__dirname, '../lambda-handler', 'github-sync')), handler: 'index.on_event', layers: [ lambda.LayerVersion.fromLayerVersionArn(accessPoint, 'GitLayer', `arn:aws:lambda:${region}:553035198032:layer:git-lambda2:7`), ], filesystem: lambda.FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/efsmount'), vpcSubnets: vpcSubnets, vpc: this.props.vpc, memorySize: 512, timeout: timeout, environment: lambdaEnv, currentVersionOptions: { provisionedConcurrentExecutions: 1, }, }); if (this.props.secret?.id) { // format the arn e.g. 'arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret'; const secretPartialArn = stack.formatArn({ service: 'secretsmanager', resource: 'secret', resourceName: this.props.secret?.id, arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, }); const secret = secretsmanager.Secret.fromSecretAttributes(stack, 'GithubSecret', { secretPartialArn, }); // allow lambda to read the secret secret.grantRead(handler); } return handler; } /** * @internal * @param id The task ID. * @param accessPoint The EFS access point. */ _createFargateTask(id, accessPoint) { const stack = cdk.Stack.of(accessPoint); const mountTarget = '/mnt/efsmount'; let syncDirectoryPath; if (this.props.syncDirectoryPath === undefined) { // if property is unspecified, use repository name as output directory const parsed = new url_1.URL(this.props.repository); syncDirectoryPath = '/' + path.basename(parsed.pathname, '.git'); } else { syncDirectoryPath = this.props.syncDirectoryPath; } const environment = { REPOSITORY_URI: this.props.repository, MOUNT_TARGET: mountTarget, SYNC_PATH: syncDirectoryPath, }; if (this.props.secret) { environment.GITHUB_SECRET_ID = this.props.secret.id; environment.GITHUB_SECRET_KEY = this.props.secret.key; } let secret; if (this.props.secret?.id) { // format the arn e.g. 'arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret'; const secretPartialArn = stack.formatArn({ service: 'secretsmanager', resource: 'secret', resourceName: this.props.secret?.id, arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, }); secret = secretsmanager.Secret.fromSecretAttributes(stack, 'GithubSecret', { secretPartialArn, }); } const fargateSyncTask = new efs_fargate_task_1.EfsFargateTask(stack, id, { vpc: this.props.vpc, accessPoint, efsMountTarget: mountTarget, syncContainer: { image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../docker.d')), command: ['/root/githubsync.sh'], environment, secrets: secret ? { OAUTH_TOKEN: ecs.Secret.fromSecretsManager(secret, 'oauth_token'), } : undefined, }, }); // allow task to read the secret secret?.grantRead(fargateSyncTask.task.taskRole); return { task: fargateSyncTask.task, securityGroup: fargateSyncTask.securityGroup, }; } ; } exports.GithubSyncSource = GithubSyncSource; _b = JSII_RTTI_SYMBOL_1; GithubSyncSource[_b] = { fqn: "cdk-efs-assets.GithubSyncSource", version: "0.3.95" }; class S3ArchiveSyncSource extends SyncSource { constructor(props) { super(); this.props = props; } /** * @internal * @param accessPoint The EFS access point. */ _createHandler(accessPoint) { const vpcSubnets = this.props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }; const syncOnUpdate = this.props.syncOnUpdate ?? true; const timeout = this.props.timeout ?? cdk.Duration.minutes(3); const filename = path.basename(this.props.zipFilePath, '.zip'); let syncDirectoryPath; if (this.props.syncDirectoryPath === undefined) { // if property is unspecified, use zip file name as output directory syncDirectoryPath = '/' + filename; } else { syncDirectoryPath = this.props.syncDirectoryPath; } const handler = new lambda.Function(accessPoint, 'SyncHandler', { runtime: lambda.Runtime.PYTHON_3_8, code: lambda.Code.fromAsset(path.join(__dirname, '../lambda-handler', 's3-archive-sync')), handler: 'index.on_event', filesystem: lambda.FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/efsmount'), vpcSubnets: vpcSubnets, vpc: this.props.vpc, memorySize: 512, timeout: timeout, environment: { MOUNT_TARGET: '/mnt/efsmount', BUCKET_NAME: this.props.bucket.bucketName, ZIPPED_KEY: this.props.zipFilePath, SYNC_PATH: syncDirectoryPath, }, currentVersionOptions: { provisionedConcurrentExecutions: 1, }, initialPolicy: [ new aws_iam_1.PolicyStatement({ actions: ['s3:GetObject*'], resources: ['arn:aws:s3:::' + this.props.bucket.bucketName + '/' + this.props.zipFilePath], }), ], }); if (syncOnUpdate) { // In order to support bucket notifications for imported IBucket objects, onCloudTrailWriteObject is used. // TODO: When https://github.com/aws/aws-cdk/issues/2004 is closed, can use handler.addEventSource instead. /* handler.addEventSource( new S3EventSource(props.bucket, { events: [s3.EventType.OBJECT_CREATED], filters: [{ prefix: props.zipFilePath }] }) ); */ this.props.bucket.onCloudTrailWriteObject('S3FileListener-' + filename, { paths: [this.props.zipFilePath], target: new aws_events_targets_1.LambdaFunction(handler), }); } return handler; } /** * @internal * @param id The Fargate task ID. * @param accessPoint The EFS access point. */ _createFargateTask(id, accessPoint) { const stack = cdk.Stack.of(accessPoint); const mountTarget = '/mnt/efsmount'; const filename = path.basename(this.props.zipFilePath, '.zip'); const syncDirectoryPath = this.props.syncDirectoryPath === undefined ? '/' + filename : this.props.syncDirectoryPath; const environment = { MOUNT_TARGET: '/mnt/efsmount', BUCKET_NAME: this.props.bucket.bucketName, ZIPPED_KEY: this.props.zipFilePath, SYNC_PATH: syncDirectoryPath, }; const fargateSyncTask = new efs_fargate_task_1.EfsFargateTask(stack, id, { vpc: this.props.vpc, accessPoint, efsMountTarget: mountTarget, syncContainer: { image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../docker.d')), command: ['/root/s3sync.sh'], environment, }, }); // allow ecs task to get the s3 object fargateSyncTask.task.addToTaskRolePolicy(new aws_iam_1.PolicyStatement({ actions: ['s3:GetObject*'], resources: [ stack.formatArn({ service: 's3', resource: this.props.bucket.bucketName, region: '', account: '', arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME, resourceName: this.props.zipFilePath, }), ], })); return { task: fargateSyncTask.task, securityGroup: fargateSyncTask.securityGroup, }; } ; } exports.S3ArchiveSyncSource = S3ArchiveSyncSource; _c = JSII_RTTI_SYMBOL_1; S3ArchiveSyncSource[_c] = { fqn: "cdk-efs-assets.S3ArchiveSyncSource", version: "0.3.95" }; var SyncEngine; (function (SyncEngine) { SyncEngine[SyncEngine["FARGATE"] = 0] = "FARGATE"; SyncEngine[SyncEngine["LAMBDA"] = 1] = "LAMBDA"; })(SyncEngine = exports.SyncEngine || (exports.SyncEngine = {})); class SyncedAccessPoint extends efs.AccessPoint { constructor(scope, id, props) { super(scope, id, props); if (props.engine === SyncEngine.LAMBDA) { const handler = props.syncSource._createHandler(this); // create a custom resource to trigger the sync const myProvider = new cr.Provider(this, 'Provider', { onEventHandler: handler, }); new cdk.CustomResource(this, 'SyncTrigger', { serviceToken: myProvider.serviceToken }); // ensure the mount targets are available as dependency for the sync function handler.node.addDependency(props.fileSystem.mountTargetsAvailable); } else { const taskConfig = props.syncSource._createFargateTask(`${id}FargateTask`, this); const cluster = new ecs.Cluster(this, 'Cluster', { vpc: props.vpc }); const runTask = new cdk_fargate_run_task_1.RunTask(this, 'SyncTrigger', { task: taskConfig.task, securityGroup: taskConfig.securityGroup, cluster, fargatePlatformVersion: cdk_fargate_run_task_1.PlatformVersion.V1_4_0, }); runTask.node.addDependency(props.fileSystem.mountTargetsAvailable); } } } exports.SyncedAccessPoint = SyncedAccessPoint; _d = JSII_RTTI_SYMBOL_1; SyncedAccessPoint[_d] = { fqn: "cdk-efs-assets.SyncedAccessPoint", version: "0.3.95" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luY2VkLWFjY2Vzcy1wb2ludC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zeW5jZWQtYWNjZXNzLXBvaW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkJBQTZCO0FBQzdCLDZCQUEwQjtBQUMxQixtQ0FBbUM7QUFDbkMsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsdUVBQWdFO0FBQ2hFLGlEQUFzRDtBQUN0RCxpREFBaUQ7QUFFakQsaUVBQWlFO0FBQ2pFLG1EQUFtRDtBQUNuRCwrREFBZ0U7QUFFaEUseURBQW9EO0FBNkVwRCxNQUFzQixVQUFVO0lBQ3ZCLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBd0I7UUFDM0MsT0FBTyxJQUFJLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQTJCO1FBQ2pELE9BQU8sSUFBSSxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4QyxDQUFDOztBQVBILGdDQWNDOzs7QUFFRCxNQUFhLGdCQUFpQixTQUFRLFVBQVU7SUFHOUMsWUFBWSxLQUF3QjtRQUNsQyxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsV0FBNEI7UUFDekMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUU1QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDNUYsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxP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YSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMscUJBQXFCLENBQUMsQ0FBQztTQUNwRTthQUFNO1lBQ0wsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRWpGLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBRXJFLE1BQU0sT0FBTyxHQUFHLElBQUksOEJBQU8sQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO2dCQUMvQyxJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUk7Z0JBQ3JCLGFBQWEsRUFBRSxVQUFVLENBQUMsYUFBYTtnQkFDdkMsT0FBTztnQkFDUCxzQkFBc0IsRUFBRSxzQ0FBZSxDQUFDLE1BQU07YUFDL0MsQ0FBQyxDQUFDO1lBRUgsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1NBQ3BFO0lBQ0gsQ0FBQzs7QUE5QkgsOENBK0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFVSTCB9IGZyb20gJ3VybCc7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3MnO1xuaW1wb3J0ICogYXMgZWZzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lZnMnO1xuaW1wb3J0IHsgTGFtYmRhRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzLXRhcmdldHMnO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgc2VjcmV0c21hbmFnZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNlY3JldHNtYW5hZ2VyJztcbmltcG9ydCAqIGFzIGNyIGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgUGxhdGZvcm1WZXJzaW9uLCBSdW5UYXNrIH0gZnJvbSAnY2RrLWZhcmdhdGUtcnVuLXRhc2snO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBFZnNGYXJnYXRlVGFzayB9IGZyb20gJy4vZWZzLWZhcmdhdGUtdGFzayc7XG5cblxuZXhwb3J0IGludGVyZmFjZSBTeW5jU291cmNlUHJvcHMge1xuICAvKipcbiAgICogVGhlIFZQQyBvZiB0aGUgQW1hem9uIEVGUyBGaWxlc3lzdGVtLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjOiBlYzIuSVZwYztcbiAgLyoqXG4gICAqIFdoZXJlIHRvIHBsYWNlIHRoZSBuZXR3b3JrIGludGVyZmFjZXMgd2l0aGluIHRoZSBWUEMuXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogZWMyLlN1Ym5ldFNlbGVjdGlvbjtcbiAgLyoqXG4gICAqIFRpbWVvdXQgZHVyYXRpb24gZm9yIHN5bmMgTGFtYmRhIGZ1bmN0aW9uLiAob3B0aW9uYWwsIGRlZmF1bHQ6IER1cmF0aW9uLm1pbnV0ZXMoMykpXG4gICAqL1xuICByZWFkb25seSB0aW1lb3V0PzogY2RrLkR1cmF0aW9uO1xuICAvKipcbiAgICogVGhlIChhYnNvbHV0ZSkgZGlyZWN0b3J5IHBhdGggaW5zaWRlIHRoZSBFRlMgQWNjZXNzUG9pbnQgdG8gc3luYyBmaWxlcyB0by4gU3BlY2lmeSAnLycgdG8gcmVzdG9yZSBzeW5jZWQgZmlsZXMgdG8gdGhlIHJvb3RcbiAgICogZGlyZWN0b3J5LiAob3B0aW9uYWwsIGRlZmF1bHQ6IGEgc291cmNlLXNwZWNpZmljIGRpcmVjdG9yeSBwYXRoLiBGb3IgZXhhbXBsZSwgZm9yIHRoZSBHaXRIdWIgc291cmNlLCB0aGUgZGVmYXVsdFxuICAgKiBiZWhhdmlvciBpcyB0byByZXN0b3JlIHRvIGEgZGlyZWN0b3J5IG1hdGNoaW5nIHRoZSBuYW1lIG9mIHRoZSByZXBvc2l0b3J5KVxuICAgKi9cbiAgcmVhZG9ubHkgc3luY0RpcmVjdG9yeVBhdGg/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0aHViU2VjcmV0IHtcbiAgLyoqXG4gICAqIFRoZSBzZWNyZXQgSUQgZnJvbSBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gICAqL1xuICByZWFkb25seSBpZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGtleSBvZiB0aGUgc2VjcmV0XG4gICAqL1xuICByZWFkb25seSBrZXk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHaXRodWJTb3VyY2VQcm9wcyBleHRlbmRzIFN5bmNTb3VyY2VQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgZ2l0aHViIHJlcG9zaXRvcnkgSFRUUCBVUkkuXG4gICAqL1xuICByZWFkb25seSByZXBvc2l0b3J5OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZ2l0aHViIHNlY3JldCBmb3IgdGhlIHByaXZhdGUgcmVwb3NpdG9yeVxuICAgKi9cbiAgcmVhZG9ubHkgc2VjcmV0PzogR2l0aHViU2VjcmV0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFMzQXJjaGl2ZVNvdXJjZVByb3BzIGV4dGVuZHMgU3luY1NvdXJjZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBTMyBidWNrZXQgY29udGFpbmluZyB0aGUgYXJjaGl2ZSBmaWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0OiBzMy5JQnVja2V0O1xuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCBvZiB0aGUgemlwIGZpbGUgdG8gZXh0cmFjdCBpbiB0aGUgUzMgYnVja2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgemlwRmlsZVBhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogSWYgdGhpcyBpcyBzZXQgdG8gdHJ1ZSwgdGhlbiB3aGVuZXZlciBhIG5ldyBvYmplY3QgaXMgdXBsb2FkZWQgdG8gdGhlIHNwZWNpZmllZCBwYXRoLFxuICAgKiBhbiBFRlMgc3luYyB3aWxsIGJlIHRyaWdnZXJlZC4gQ3VycmVudGx5LCB0aGlzIGZ1bmN0aW9uYWxpdHkgZGVwZW5kcyBvbiBhdCBsZWFzdCBvbmUgQ2xvdWRUcmFpbCBUcmFpbFxuICAgKiBleGlzdGluZyBpbiB5b3VyIGFjY291bnQgdGhhdCBjYXB0dXJlcyB0aGUgUzMgZXZlbnQuXG4gICAqXG4gICAqIFRoZSBvcHRpb24gaXMgb25seSBhdmFpbGFibGUgd2l0aCB0aGUgYExBTUJEQWAgc3luYyBlbmdpbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHN5bmNPblVwZGF0ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmFyZ2F0ZVRhc2tDb25maWcge1xuICByZWFkb25seSB0YXNrOiBlY3MuVGFza0RlZmluaXRpb247XG4gIC8qKlxuICAgKiBUaGUgc2VjdXJpdHkgZ3JvdXAgb2YgdGhlIGZhcmdhdGUgdGFza1xuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cDogZWMyLklTZWN1cml0eUdyb3VwO1xufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU3luY1NvdXJjZSB7XG4gIHB1YmxpYyBzdGF0aWMgZ2l0aHViKHByb3BzOiBHaXRodWJTb3VyY2VQcm9wcyk6IFN5bmNTb3VyY2Uge1xuICAgIHJldHVybiBuZXcgR2l0aHViU3luY1NvdXJjZShwcm9wcyk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHMzQXJjaGl2ZShwcm9wczogUzNBcmNoaXZlU291cmNlUHJvcHMpOiBTeW5jU291cmNlIHtcbiAgICByZXR1cm4gbmV3IFMzQXJjaGl2ZVN5bmNTb3VyY2UocHJvcHMpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBhYnN0cmFjdCBfY3JlYXRlSGFuZGxlcihhY2Nlc3NQb2ludDogZWZzLkFjY2Vzc1BvaW50KTogbGFtYmRhLkZ1bmN0aW9uO1xuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgYWJzdHJhY3QgX2NyZWF0ZUZhcmdhdGVUYXNrKGlkOiBzdHJpbmcsIGFjY2Vzc1BvaW50OiBlZnMuQWNjZXNzUG9pbnQpOiBGYXJnYXRlVGFza0NvbmZpZztcbn1cblxuZXhwb3J0IGNsYXNzIEdpdGh1YlN5bmNTb3VyY2UgZXh0ZW5kcyBTeW5jU291cmNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogR2l0aHViU291cmNlUHJvcHM7XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IEdpdGh1YlNvdXJjZVByb3BzKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnByb3BzID0gcHJvcHM7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqIEBwYXJhbSBhY2Nlc3NQb2ludCBUaGUgRUZTIEFjY2VzcyBQb2ludFxuICAgKi9cbiAgX2NyZWF0ZUhhbmRsZXIoYWNjZXNzUG9pbnQ6IGVmcy5BY2Nlc3NQb2ludCk6IGxhbWJkYS5GdW5jdGlvbiB7XG4gICAgY29uc3Qgc3RhY2sgPSBjZGsuU3RhY2sub2YoYWNjZXNzUG9pbnQpO1xuICAgIGNvbnN0IHJlZ2lvbiA9IHN0YWNrLnJlZ2lvbjtcblxuICAgIGNvbnN0IHZwY1N1Ym5ldHMgPSB0aGlzLnByb3BzLnZwY1N1Ym5ldHMgPz8geyBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QUklWQVRFX1dJVEhfTkFUIH07XG4gICAgY29uc3QgdGltZW91dCA9IHRoaXMucHJvcHMudGltZW91dCA/PyBjZGsuRHVyYXRpb24ubWludXRlcygzKTtcblxuICAgIGxldCBzeW5jRGlyZWN0b3J5UGF0aDtcbiAgICBpZiAodGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBpZiBwcm9wZXJ0eSBpcyB1bnNwZWNpZmllZCwgdXNlIHJlcG9zaXRvcnkgbmFtZSBhcyBvdXRwdXQgZGlyZWN0b3J5XG5cbiAgICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBVUkwodGhpcy5wcm9wcy5yZXBvc2l0b3J5KTtcbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gJy8nICsgcGF0aC5iYXNlbmFtZShwYXJzZWQucGF0aG5hbWUsICcuZ2l0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gdGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aDtcbiAgICB9XG5cbiAgICBjb25zdCBsYW1iZGFFbnY6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICBSRVBPU0lUT1JZX1VSSTogdGhpcy5wcm9wcy5yZXBvc2l0b3J5LFxuICAgICAgTU9VTlRfVEFSR0VUOiAnL21udC9lZnNtb3VudCcsXG4gICAgICBTWU5DX1BBVEg6IHN5bmNEaXJlY3RvcnlQYXRoLFxuICAgIH07XG5cbiAgICBpZiAodGhpcy5wcm9wcy5zZWNyZXQpIHtcbiAgICAgIGxhbWJkYUVudi5HSVRIVUJfU0VDUkVUX0lEID0gdGhpcy5wcm9wcy5zZWNyZXQuaWQ7XG4gICAgICBsYW1iZGFFbnYuR0lUSFVCX1NFQ1JFVF9LRVkgPSB0aGlzLnByb3BzLnNlY3JldC5rZXk7XG4gICAgfVxuXG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBsYW1iZGEuRnVuY3Rpb24oYWNjZXNzUG9pbnQsICdHaXRodWJIYW5kbGVyJywge1xuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOCxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbGFtYmRhLWhhbmRsZXInLCAnZ2l0aHViLXN5bmMnKSksXG4gICAgICBoYW5kbGVyOiAnaW5kZXgub25fZXZlbnQnLFxuICAgICAgbGF5ZXJzOiBbXG4gICAgICAgIGxhbWJkYS5MYXllclZlcnNpb24uZnJvbUxheWVyVmVyc2lvbkFybihcbiAgICAgICAgICBhY2Nlc3NQb2ludCxcbiAgICAgICAgICAnR2l0TGF5ZXInLFxuICAgICAgICAgIGBhcm46YXdzOmxhbWJkYToke3JlZ2lvbn06NTUzMDM1MTk4MDMyOmxheWVyOmdpdC1sYW1iZGEyOjdgLFxuICAgICAgICApLFxuICAgICAgXSxcbiAgICAgIGZpbGVzeXN0ZW06IGxhbWJkYS5GaWxlU3lzdGVtLmZyb21FZnNBY2Nlc3NQb2ludChhY2Nlc3NQb2ludCwgJy9tbnQvZWZzbW91bnQnKSxcbiAgICAgIHZwY1N1Ym5ldHM6IHZwY1N1Ym5ldHMsXG4gICAgICB2cGM6IHRoaXMucHJvcHMudnBjLFxuICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgdGltZW91dDogdGltZW91dCxcbiAgICAgIGVudmlyb25tZW50OiBsYW1iZGFFbnYsXG4gICAgICBjdXJyZW50VmVyc2lvbk9wdGlvbnM6IHtcbiAgICAgICAgcHJvdmlzaW9uZWRDb25jdXJyZW50RXhlY3V0aW9uczogMSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5wcm9wcy5zZWNyZXQ/LmlkKSB7XG4gICAgICAvLyBmb3JtYXQgdGhlIGFybiBlLmcuICdhcm46YXdzOnNlY3JldHNtYW5hZ2VyOmV1LXdlc3QtMToxMTExMTExMTExMTE6c2VjcmV0Ok15U2VjcmV0JztcbiAgICAgIGNvbnN0IHNlY3JldFBhcnRpYWxBcm4gPSBzdGFjay5mb3JtYXRBcm4oe1xuICAgICAgICBzZXJ2aWNlOiAnc2VjcmV0c21hbmFnZXInLFxuICAgICAgICByZXNvdXJjZTogJ3NlY3JldCcsXG4gICAgICAgIHJlc291cmNlTmFtZTogdGhpcy5wcm9wcy5zZWNyZXQ/LmlkLFxuICAgICAgICBhcm5Gb3JtYXQ6IGNkay5Bcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2VjcmV0ID0gc2VjcmV0c21hbmFnZXIuU2VjcmV0LmZyb21TZWNyZXRBdHRyaWJ1dGVzKHN0YWNrLCAnR2l0aHViU2VjcmV0Jywge1xuICAgICAgICBzZWNyZXRQYXJ0aWFsQXJuLFxuICAgICAgfSk7XG4gICAgICAvLyBhbGxvdyBsYW1iZGEgdG8gcmVhZCB0aGUgc2VjcmV0XG4gICAgICBzZWNyZXQuZ3JhbnRSZWFkKGhhbmRsZXIpO1xuICAgIH1cblxuICAgIHJldHVybiBoYW5kbGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKiBAcGFyYW0gaWQgVGhlIHRhc2sgSUQuXG4gICAqIEBwYXJhbSBhY2Nlc3NQb2ludCBUaGUgRUZTIGFjY2VzcyBwb2ludC5cbiAgICovXG4gIF9jcmVhdGVGYXJnYXRlVGFzayhpZDogc3RyaW5nLCBhY2Nlc3NQb2ludDogZWZzLkFjY2Vzc1BvaW50KTogRmFyZ2F0ZVRhc2tDb25maWcge1xuICAgIGNvbnN0IHN0YWNrID0gY2RrLlN0YWNrLm9mKGFjY2Vzc1BvaW50KTtcblxuICAgIGNvbnN0IG1vdW50VGFyZ2V0ID0gJy9tbnQvZWZzbW91bnQnO1xuXG4gICAgbGV0IHN5bmNEaXJlY3RvcnlQYXRoO1xuICAgIGlmICh0aGlzLnByb3BzLnN5bmNEaXJlY3RvcnlQYXRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIGlmIHByb3BlcnR5IGlzIHVuc3BlY2lmaWVkLCB1c2UgcmVwb3NpdG9yeSBuYW1lIGFzIG91dHB1dCBkaXJlY3RvcnlcbiAgICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBVUkwodGhpcy5wcm9wcy5yZXBvc2l0b3J5KTtcbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gJy8nICsgcGF0aC5iYXNlbmFtZShwYXJzZWQucGF0aG5hbWUsICcuZ2l0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gdGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aDtcbiAgICB9XG5cbiAgICBjb25zdCBlbnZpcm9ubWVudDogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgIFJFUE9TSVRPUllfVVJJOiB0aGlzLnByb3BzLnJlcG9zaXRvcnksXG4gICAgICBNT1VOVF9UQVJHRVQ6IG1vdW50VGFyZ2V0LFxuICAgICAgU1lOQ19QQVRIOiBzeW5jRGlyZWN0b3J5UGF0aCxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMucHJvcHMuc2VjcmV0KSB7XG4gICAgICBlbnZpcm9ubWVudC5HSVRIVUJfU0VDUkVUX0lEID0gdGhpcy5wcm9wcy5zZWNyZXQuaWQ7XG4gICAgICBlbnZpcm9ubWVudC5HSVRIVUJfU0VDUkVUX0tFWSA9IHRoaXMucHJvcHMuc2VjcmV0LmtleTtcbiAgICB9XG5cbiAgICBsZXQgc2VjcmV0OiBzZWNyZXRzbWFuYWdlci5JU2VjcmV0IHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKHRoaXMucHJvcHMuc2VjcmV0Py5pZCkge1xuICAgICAgLy8gZm9ybWF0IHRoZSBhcm4gZS5nLiAnYXJuOmF3czpzZWNyZXRzbWFuYWdlcjpldS13ZXN0LTE6MTExMTExMTExMTExOnNlY3JldDpNeVNlY3JldCc7XG4gICAgICBjb25zdCBzZWNyZXRQYXJ0aWFsQXJuID0gc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgc2VydmljZTogJ3NlY3JldHNtYW5hZ2VyJyxcbiAgICAgICAgcmVzb3VyY2U6ICdzZWNyZXQnLFxuICAgICAgICByZXNvdXJjZU5hbWU6IHRoaXMucHJvcHMuc2VjcmV0Py5pZCxcbiAgICAgICAgYXJuRm9ybWF0OiBjZGsuQXJuRm9ybWF0LkNPTE9OX1JFU09VUkNFX05BTUUsXG4gICAgICB9KTtcbiAgICAgIHNlY3JldCA9IHNlY3JldHNtYW5hZ2VyLlNlY3JldC5mcm9tU2VjcmV0QXR0cmlidXRlcyhzdGFjaywgJ0dpdGh1YlNlY3JldCcsIHtcbiAgICAgICAgc2VjcmV0UGFydGlhbEFybixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGZhcmdhdGVTeW5jVGFzayA9IG5ldyBFZnNGYXJnYXRlVGFzayhzdGFjaywgaWQsIHtcbiAgICAgIHZwYzogdGhpcy5wcm9wcy52cGMsXG4gICAgICBhY2Nlc3NQb2ludCxcbiAgICAgIGVmc01vdW50VGFyZ2V0OiBtb3VudFRhcmdldCxcbiAgICAgIHN5bmNDb250YWluZXI6IHtcbiAgICAgICAgaW1hZ2U6IGVjcy5Db250YWluZXJJbWFnZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2RvY2tlci5kJykpLFxuICAgICAgICBjb21tYW5kOiBbJy9yb290L2dpdGh1YnN5bmMuc2gnXSxcbiAgICAgICAgZW52aXJvbm1lbnQsXG4gICAgICAgIHNlY3JldHM6IHNlY3JldCA/IHtcbiAgICAgICAgICBPQVVUSF9UT0tFTjogZWNzLlNlY3JldC5mcm9tU2VjcmV0c01hbmFnZXIoc2VjcmV0LCAnb2F1dGhfdG9rZW4nKSxcbiAgICAgICAgfSA6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBhbGxvdyB0YXNrIHRvIHJlYWQgdGhlIHNlY3JldFxuICAgIHNlY3JldD8uZ3JhbnRSZWFkKGZhcmdhdGVTeW5jVGFzay50YXNrLnRhc2tSb2xlKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0YXNrOiBmYXJnYXRlU3luY1Rhc2sudGFzayxcbiAgICAgIHNlY3VyaXR5R3JvdXA6IGZhcmdhdGVTeW5jVGFzay5zZWN1cml0eUdyb3VwLFxuICAgIH07XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBTM0FyY2hpdmVTeW5jU291cmNlIGV4dGVuZHMgU3luY1NvdXJjZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IFMzQXJjaGl2ZVNvdXJjZVByb3BzO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBTM0FyY2hpdmVTb3VyY2VQcm9wcykge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKiBAcGFyYW0gYWNjZXNzUG9pbnQgVGhlIEVGUyBhY2Nlc3MgcG9pbnQuXG4gICAqL1xuICBfY3JlYXRlSGFuZGxlcihhY2Nlc3NQb2ludDogZWZzLkFjY2Vzc1BvaW50KTogbGFtYmRhLkZ1bmN0aW9uIHtcbiAgICBjb25zdCB2cGNTdWJuZXRzID0gdGhpcy5wcm9wcy52cGNTdWJuZXRzID8/IHsgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX05BVCB9O1xuICAgIGNvbnN0IHN5bmNPblVwZGF0ZSA9IHRoaXMucHJvcHMuc3luY09uVXBkYXRlID8/IHRydWU7XG4gICAgY29uc3QgdGltZW91dCA9IHRoaXMucHJvcHMudGltZW91dCA/PyBjZGsuRHVyYXRpb24ubWludXRlcygzKTtcblxuICAgIGNvbnN0IGZpbGVuYW1lID0gcGF0aC5iYXNlbmFtZSh0aGlzLnByb3BzLnppcEZpbGVQYXRoLCAnLnppcCcpO1xuXG4gICAgbGV0IHN5bmNEaXJlY3RvcnlQYXRoO1xuICAgIGlmICh0aGlzLnByb3BzLnN5bmNEaXJlY3RvcnlQYXRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIGlmIHByb3BlcnR5IGlzIHVuc3BlY2lmaWVkLCB1c2UgemlwIGZpbGUgbmFtZSBhcyBvdXRwdXQgZGlyZWN0b3J5XG5cbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gJy8nICsgZmlsZW5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN5bmNEaXJlY3RvcnlQYXRoID0gdGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aDtcbiAgICB9XG5cbiAgICBjb25zdCBoYW5kbGVyID0gbmV3IGxhbWJkYS5GdW5jdGlvbihhY2Nlc3NQb2ludCwgJ1N5bmNIYW5kbGVyJywge1xuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOCxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbGFtYmRhLWhhbmRsZXInLCAnczMtYXJjaGl2ZS1zeW5jJykpLFxuICAgICAgaGFuZGxlcjogJ2luZGV4Lm9uX2V2ZW50JyxcbiAgICAgIGZpbGVzeXN0ZW06IGxhbWJkYS5GaWxlU3lzdGVtLmZyb21FZnNBY2Nlc3NQb2ludChhY2Nlc3NQb2ludCwgJy9tbnQvZWZzbW91bnQnKSxcbiAgICAgIHZwY1N1Ym5ldHM6IHZwY1N1Ym5ldHMsXG4gICAgICB2cGM6IHRoaXMucHJvcHMudnBjLFxuICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgdGltZW91dDogdGltZW91dCxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE1PVU5UX1RBUkdFVDogJy9tbnQvZWZzbW91bnQnLFxuICAgICAgICBCVUNLRVRfTkFNRTogdGhpcy5wcm9wcy5idWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgWklQUEVEX0tFWTogdGhpcy5wcm9wcy56aXBGaWxlUGF0aCxcbiAgICAgICAgU1lOQ19QQVRIOiBzeW5jRGlyZWN0b3J5UGF0aCxcbiAgICAgIH0sXG4gICAgICBjdXJyZW50VmVyc2lvbk9wdGlvbnM6IHtcbiAgICAgICAgcHJvdmlzaW9uZWRDb25jdXJyZW50RXhlY3V0aW9uczogMSxcbiAgICAgIH0sXG4gICAgICBpbml0aWFsUG9saWN5OiBbXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnczM6R2V0T2JqZWN0KiddLFxuICAgICAgICAgIHJlc291cmNlczogWydhcm46YXdzOnMzOjo6JyArIHRoaXMucHJvcHMuYnVja2V0LmJ1Y2tldE5hbWUgKyAnLycgKyB0aGlzLnByb3BzLnppcEZpbGVQYXRoXSxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgaWYgKHN5bmNPblVwZGF0ZSkge1xuICAgICAgLy8gSW4gb3JkZXIgdG8gc3VwcG9ydCBidWNrZXQgbm90aWZpY2F0aW9ucyBmb3IgaW1wb3J0ZWQgSUJ1Y2tldCBvYmplY3RzLCBvbkNsb3VkVHJhaWxXcml0ZU9iamVjdCBpcyB1c2VkLlxuICAgICAgLy8gVE9ETzogV2hlbiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLzIwMDQgaXMgY2xvc2VkLCBjYW4gdXNlIGhhbmRsZXIuYWRkRXZlbnRTb3VyY2UgaW5zdGVhZC5cbiAgICAgIC8qXG4gICAgICBoYW5kbGVyLmFkZEV2ZW50U291cmNlKFxuICAgICAgICBuZXcgUzNFdmVudFNvdXJjZShwcm9wcy5idWNrZXQsIHtcbiAgICAgICAgICBldmVudHM6IFtzMy5FdmVudFR5cGUuT0JKRUNUX0NSRUFURURdLFxuICAgICAgICAgIGZpbHRlcnM6IFt7IHByZWZpeDogcHJvcHMuemlwRmlsZVBhdGggfV1cbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICAgKi9cblxuICAgICAgdGhpcy5wcm9wcy5idWNrZXQub25DbG91ZFRyYWlsV3JpdGVPYmplY3QoJ1MzRmlsZUxpc3RlbmVyLScgKyBmaWxlbmFtZSwge1xuICAgICAgICBwYXRoczogW3RoaXMucHJvcHMuemlwRmlsZVBhdGhdLFxuICAgICAgICB0YXJnZXQ6IG5ldyBMYW1iZGFGdW5jdGlvbihoYW5kbGVyKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBoYW5kbGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKiBAcGFyYW0gaWQgVGhlIEZhcmdhdGUgdGFzayBJRC5cbiAgICogQHBhcmFtIGFjY2Vzc1BvaW50IFRoZSBFRlMgYWNjZXNzIHBvaW50LlxuICAgKi9cbiAgX2NyZWF0ZUZhcmdhdGVUYXNrKGlkOiBzdHJpbmcsIGFjY2Vzc1BvaW50OiBlZnMuQWNjZXNzUG9pbnQpOiBGYXJnYXRlVGFza0NvbmZpZyB7XG4gICAgY29uc3Qgc3RhY2sgPSBjZGsuU3RhY2sub2YoYWNjZXNzUG9pbnQpO1xuXG4gICAgY29uc3QgbW91bnRUYXJnZXQgPSAnL21udC9lZnNtb3VudCc7XG5cbiAgICBjb25zdCBmaWxlbmFtZSA9IHBhdGguYmFzZW5hbWUodGhpcy5wcm9wcy56aXBGaWxlUGF0aCwgJy56aXAnKTtcblxuICAgIGNvbnN0IHN5bmNEaXJlY3RvcnlQYXRoID0gdGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aCA9PT0gdW5kZWZpbmVkID9cbiAgICAgICcvJyArIGZpbGVuYW1lIDogdGhpcy5wcm9wcy5zeW5jRGlyZWN0b3J5UGF0aDtcblxuICAgIGNvbnN0IGVudmlyb25tZW50OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgTU9VTlRfVEFSR0VUOiAnL21udC9lZnNtb3VudCcsXG4gICAgICBCVUNLRVRfTkFNRTogdGhpcy5wcm9wcy5idWNrZXQuYnVja2V0TmFtZSxcbiAgICAgIFpJUFBFRF9LRVk6IHRoaXMucHJvcHMuemlwRmlsZVBhdGgsXG4gICAgICBTWU5DX1BBVEg6IHN5bmNEaXJlY3RvcnlQYXRoLFxuICAgIH07XG5cbiAgICBjb25zdCBmYXJnYXRlU3luY1Rhc2sgPSBuZXcgRWZzRmFyZ2F0ZVRhc2soc3RhY2ssIGlkLCB7XG4gICAgICB2cGM6IHRoaXMucHJvcHMudnBjLFxuICAgICAgYWNjZXNzUG9pbnQsXG4gICAgICBlZnNNb3VudFRhcmdldDogbW91bnRUYXJnZXQsXG4gICAgICBzeW5jQ29udGFpbmVyOiB7XG4gICAgICAgIGltYWdlOiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9kb2NrZXIuZCcpKSxcbiAgICAgICAgY29tbWFuZDogWycvcm9vdC9zM3N5bmMuc2gnXSxcbiAgICAgICAgZW52aXJvbm1lbnQsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gYWxsb3cgZWNzIHRhc2sgdG8gZ2V0IHRoZSBzMyBvYmplY3RcbiAgICBmYXJnYXRlU3luY1Rhc2sudGFzay5hZGRUb1Rhc2tSb2xlUG9saWN5KG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgYWN0aW9uczogWydzMzpHZXRPYmplY3QqJ10sXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgICBzZXJ2aWNlOiAnczMnLFxuICAgICAgICAgIHJlc291cmNlOiB0aGlzLnByb3BzLmJ1Y2tldC5idWNrZXROYW1lLFxuICAgICAgICAgIHJlZ2lvbjogJycsXG4gICAgICAgICAgYWNjb3VudDogJycsXG4gICAgICAgICAgYXJuRm9ybWF0OiBjZGsuQXJuRm9ybWF0LlNMQVNIX1JFU09VUkNFX05BTUUsXG4gICAgICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnByb3BzLnppcEZpbGVQYXRoLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRhc2s6IGZhcmdhdGVTeW5jVGFzay50YXNrLFxuICAgICAgc2VjdXJpdHlHcm91cDogZmFyZ2F0ZVN5bmNUYXNrLnNlY3VyaXR5R3JvdXAsXG4gICAgfTtcbiAgfTtcbn1cblxuZXhwb3J0IGVudW0gU3luY0VuZ2luZSB7XG4gIEZBUkdBVEUsXG4gIExBTUJEQSxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTeW5jZWRBY2Nlc3NQb2ludFByb3BzIGV4dGVuZHMgZWZzLkFjY2Vzc1BvaW50UHJvcHMge1xuICByZWFkb25seSBzeW5jU291cmNlOiBTeW5jU291cmNlO1xuICAvKipcbiAgICogVGhlIFZQQyB0byBydW4gdGhlIHN5bmMgam9iXG4gICAqL1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjO1xuICAvKipcbiAgICogVHJpZ2dlciB0aGUgc3luYyB3aXRoIEFXUyBMYW1iZGEgb3IgQVdTIEZhcmdhdGUuXG4gICAqL1xuICByZWFkb25seSBlbmdpbmU/OiBTeW5jRW5naW5lO1xufVxuXG5leHBvcnQgY2xhc3MgU3luY2VkQWNjZXNzUG9pbnQgZXh0ZW5kcyBlZnMuQWNjZXNzUG9pbnQgaW1wbGVtZW50cyBlZnMuSUFjY2Vzc1BvaW50IHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFN5bmNlZEFjY2Vzc1BvaW50UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIGlmIChwcm9wcy5lbmdpbmUgPT09IFN5bmNFbmdpbmUuTEFNQkRBKSB7XG4gICAgICBjb25zdCBoYW5kbGVyID0gcHJvcHMuc3luY1NvdXJjZS5fY3JlYXRlSGFuZGxlcih0aGlzKTtcblxuICAgICAgLy8gY3JlYXRlIGEgY3VzdG9tIHJlc291cmNlIHRvIHRyaWdnZXIgdGhlIHN5bmNcbiAgICAgIGNvbnN0IG15UHJvdmlkZXIgPSBuZXcgY3IuUHJvdmlkZXIodGhpcywgJ1Byb3ZpZGVyJywge1xuICAgICAgICBvbkV2ZW50SGFuZGxlcjogaGFuZGxlcixcbiAgICAgIH0pO1xuXG4gICAgICBuZXcgY2RrLkN1c3RvbVJlc291cmNlKHRoaXMsICdTeW5jVHJpZ2dlcicsIHsgc2VydmljZVRva2VuOiBteVByb3ZpZGVyLnNlcnZpY2VUb2tlbiB9KTtcblxuICAgICAgLy8gZW5zdXJlIHRoZSBtb3VudCB0YXJnZXRzIGFyZSBhdmFpbGFibGUgYXMgZGVwZW5kZW5jeSBmb3IgdGhlIHN5bmMgZnVuY3Rpb25cbiAgICAgIGhhbmRsZXIubm9kZS5hZGREZXBlbmRlbmN5KHByb3BzLmZpbGVTeXN0ZW0ubW91bnRUYXJnZXRzQXZhaWxhYmxlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGFza0NvbmZpZyA9IHByb3BzLnN5bmNTb3VyY2UuX2NyZWF0ZUZhcmdhdGVUYXNrKGAke2lkfUZhcmdhdGVUYXNrYCwgdGhpcyk7XG5cbiAgICAgIGNvbnN0IGNsdXN0ZXIgPSBuZXcgZWNzLkNsdXN0ZXIodGhpcywgJ0NsdXN0ZXInLCB7IHZwYzogcHJvcHMudnBjIH0pO1xuXG4gICAgICBjb25zdCBydW5UYXNrID0gbmV3IFJ1blRhc2sodGhpcywgJ1N5bmNUcmlnZ2VyJywge1xuICAgICAgICB0YXNrOiB0YXNrQ29uZmlnLnRhc2ssXG4gICAgICAgIHNlY3VyaXR5R3JvdXA6IHRhc2tDb25maWcuc2VjdXJpdHlHcm91cCxcbiAgICAgICAgY2x1c3RlcixcbiAgICAgICAgZmFyZ2F0ZVBsYXRmb3JtVmVyc2lvbjogUGxhdGZvcm1WZXJzaW9uLlYxXzRfMCxcbiAgICAgIH0pO1xuXG4gICAgICBydW5UYXNrLm5vZGUuYWRkRGVwZW5kZW5jeShwcm9wcy5maWxlU3lzdGVtLm1vdW50VGFyZ2V0c0F2YWlsYWJsZSk7XG4gICAgfVxuICB9XG59XG4iXX0=