UNPKG

aws-delivlib

Version:

A fabulous library for defining continuous pipelines for building, testing and releasing code libraries.

171 lines • 29.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EcrMirrorAspect = exports.EcrMirror = void 0; const aws_cdk_lib_1 = require("aws-cdk-lib"); const constructs_1 = require("constructs"); const constants_1 = require("../constants"); /** * Synchronize images from DockerHub to an ECR registry in the AWS account. * This is particularly useful to workaround DockerHub's throttling on pulls and use ECR instead. */ class EcrMirror extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); this._repos = new Map(); this._repoTagsSeen = new Set(); if (!props.schedule && !props.autoStart) { throw new Error('Either schedule or autoStart must be provided'); } const ecrRegistry = `${aws_cdk_lib_1.Stack.of(scope).account}.dkr.ecr.${aws_cdk_lib_1.Stack.of(scope).region}.amazonaws.com`; const commands = []; const assets = new Array(); const codeBuildSecretValue = (key, auth) => { return `${props.dockerHubCredentials.secret.secretName}:${key}:${auth.versionStage ?? 'AWSCURRENT'}`; }; const username = codeBuildSecretValue(props.dockerHubCredentials.usernameKey, props.dockerHubCredentials); const password = codeBuildSecretValue(props.dockerHubCredentials.passwordKey, props.dockerHubCredentials); if (!props.buildImage) { aws_cdk_lib_1.Annotations.of(this).addWarningV2('aws-delivlib:EcrMirror.missingBuildImage', 'Prefer supplying an explicit build image to relying on the default superchain.'); } this.project = new aws_cdk_lib_1.aws_codebuild.Project(this, 'EcrPushImages', { description: aws_cdk_lib_1.Lazy.string({ produce: () => `Synchronize ${props.sources.length} images from DockerHub to local ECR` }), environment: { privileged: true, buildImage: props.buildImage ?? aws_cdk_lib_1.aws_codebuild.LinuxBuildImage.fromDockerRegistry(constants_1.DEFAULT_SUPERCHAIN_IMAGE), }, environmentVariables: { // DockerHub credentials to avoid throttling DOCKERHUB_USERNAME: { value: username, type: aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.SECRETS_MANAGER }, DOCKERHUB_PASSWORD: { value: password, type: aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.SECRETS_MANAGER }, }, buildSpec: aws_cdk_lib_1.aws_codebuild.BuildSpec.fromObject(aws_cdk_lib_1.Lazy.any({ produce: () => { return { version: '0.2', phases: { build: { commands: [ // start the docker daemon 'nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&', 'timeout 15 sh -c "until docker info; do echo .; sleep 1; done"', // login to dockerhub so we won't get throttled 'docker login -u ${DOCKERHUB_USERNAME} -p ${DOCKERHUB_PASSWORD}', // login to ecr so we can push to it `aws ecr get-login-password | docker login --username AWS --password-stdin ${ecrRegistry}`, // login to ecr-public so we can pull from it with improved rate limits 'aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws', ...commands, ], }, }, }; }, })), ssmSessionPermissions: true, }); // Ensure the runner has PULL access to ECR-Public. this.project.role.addManagedPolicy(aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly')); // Give the project access to the Docker Hub credentials // Required for access to private images and to avoid throttling of unauthorized requests props.dockerHubCredentials.secret.grantRead(this.project); for (const image of props.sources) { const result = image.bind({ scope: this, ecrRegistry, syncJob: this.project, }); commands.push(...result.commands); const repoTag = `${result.repositoryName}:${result.tag}`; if (this._repoTagsSeen.has(repoTag)) { throw new Error(`Mirror source with repository name [${result.repositoryName}] and tag [${result.tag}] already exists.`); } this._repoTagsSeen.add(repoTag); this.createMirrorRepo(result.repositoryName); const ecrImageUri = `${ecrRegistry}/${result.repositoryName}:${result.tag}`; commands.push(`docker push ${ecrImageUri}`); // clean after each push so that we don't fillup disk space // possibly failing the next pull. commands.push('docker image prune --all --force'); } // CodeBuild needs to read the secret to resolve environment variables props.dockerHubCredentials.secret.grantRead(this.project); aws_cdk_lib_1.aws_ecr.AuthorizationToken.grantRead(this.project); this._repos.forEach((r, _) => r.grantPullPush(this.project)); // this project needs to download the assets so it can build them assets.forEach(a => a.grantRead(this.project)); if (props.autoStart) { new aws_cdk_lib_1.custom_resources.AwsCustomResource(this, 'BuildExecution', { installLatestAwsSdk: false, policy: aws_cdk_lib_1.custom_resources.AwsCustomResourcePolicy.fromSdkCalls({ resources: [this.project.projectArn] }), onUpdate: { action: 'startBuild', service: 'CodeBuild', parameters: { projectName: this.project.projectName, // to tigger the build on every update idempotencyToken: `${Date.now()}`, }, physicalResourceId: aws_cdk_lib_1.custom_resources.PhysicalResourceId.of('EcrRegistryExecution'), // need since the default reponse if greater than the 4k limit for custom resources. outputPaths: ['build.id'], }, }); } if (props.schedule) { new aws_cdk_lib_1.aws_events.Rule(this, 'ScheduledTrigger', { description: 'Trigger ECR mirror job', schedule: props.schedule, targets: [new aws_cdk_lib_1.aws_events_targets.CodeBuildProject(this.project)], }); } } createMirrorRepo(ecrRepositoryName) { if (this._repos.get(ecrRepositoryName)) { return; } const repository = new aws_cdk_lib_1.aws_ecr.Repository(this, `Repo${ecrRepositoryName}`, { repositoryName: ecrRepositoryName, }); this._repos.set(ecrRepositoryName, repository); } /** * Get the target ECR repository for the given repository name and tag. * @param repositoryName The ECR repository with this name * @param tag the tag for the repository, defaults to 'latest' */ ecrRepository(repositoryName) { return this._repos.get(repositoryName); } } exports.EcrMirror = EcrMirror; ; /** * An aspect that walks through the construct tree and replaces CodeBuild jobs with Docker images * with ECR equivalents found in the EcrMirror. */ class EcrMirrorAspect { constructor(mirror) { this.mirror = mirror; } visit(construct) { if (construct instanceof aws_cdk_lib_1.aws_codebuild.Project) { const cfnproject = construct.node.defaultChild; if (!aws_cdk_lib_1.Token.isUnresolved(cfnproject.environment)) { const env = cfnproject.environment; const imageName = env.image.split(':')[0]; const tag = env.image.split(':')[1]; const replacement = this.mirror.ecrRepository(imageName); if (replacement) { cfnproject.environment = { ...env, image: aws_cdk_lib_1.aws_codebuild.LinuxBuildImage.fromEcrRepository(replacement, tag).imageId, }; replacement.grantPull(construct); aws_cdk_lib_1.aws_ecr.AuthorizationToken.grantRead(construct); } } } } } exports.EcrMirrorAspect = EcrMirrorAspect; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNyLW1pcnJvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImVjci1taXJyb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBV3FCO0FBQ3JCLDJDQUFtRDtBQUVuRCw0Q0FBd0Q7QUF1RXhEOzs7R0FHRztBQUNILE1BQWEsU0FBVSxTQUFRLHNCQUFTO0lBT3RDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBcUI7UUFDN0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQU5GLFdBQU0sR0FBZ0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNoRCxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFPakQsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFO1lBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQztTQUNsRTtRQUVELE1BQU0sV0FBVyxHQUFHLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxZQUFZLG1CQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sZ0JBQWdCLENBQUM7UUFDakcsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO1FBQzlCLE1BQU0sTUFBTSxHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1FBRTNDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFXLEVBQUUsSUFBMEIsRUFBRSxFQUFFO1lBQ3ZFLE9BQU8sR0FBRyxLQUFLLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLFlBQVksSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN2RyxDQUFDLENBQUM7UUFFRixNQUFNLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQzFHLE1BQU0sUUFBUSxHQUFHLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFFMUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUU7WUFDckIseUJBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsWUFBWSxDQUFDLDBDQUEwQyxFQUFFLGdGQUFnRixDQUFDLENBQUM7U0FDaks7UUFFRCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksMkJBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUMxRCxXQUFXLEVBQUUsa0JBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsZUFBZSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0scUNBQXFDLEVBQUUsQ0FBQztZQUNySCxXQUFXLEVBQUU7Z0JBQ1gsVUFBVSxFQUFFLElBQUk7Z0JBQ2hCLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxJQUFJLDJCQUFTLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDLG9DQUF3QixDQUFDO2FBQ3ZHO1lBQ0Qsb0JBQW9CLEVBQUU7Z0JBQ3BCLDRDQUE0QztnQkFDNUMsa0JBQWtCLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSwyQkFBUyxDQUFDLDRCQUE0QixDQUFDLGVBQWUsRUFBRTtnQkFDckcsa0JBQWtCLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSwyQkFBUyxDQUFDLDRCQUE0QixDQUFDLGVBQWUsRUFBRTthQUN0RztZQUNELFNBQVMsRUFBRSwyQkFBUyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsa0JBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQ2pELE9BQU8sRUFBRSxHQUFHLEVBQUU7b0JBQ1osT0FBTzt3QkFDTCxPQUFPLEVBQUUsS0FBSzt3QkFDZCxNQUFNLEVBQUU7NEJBQ04sS0FBSyxFQUFFO2dDQUNMLFFBQVEsRUFBRTtvQ0FFUiwwQkFBMEI7b0NBQzFCLGtIQUFrSDtvQ0FDbEgsZ0VBQWdFO29DQUVoRSwrQ0FBK0M7b0NBQy9DLGdFQUFnRTtvQ0FFaEUsb0NBQW9DO29DQUNwQyw2RUFBNkUsV0FBVyxFQUFFO29DQUUxRix1RUFBdUU7b0NBQ3ZFLG9IQUFvSDtvQ0FFcEgsR0FBRyxRQUFRO2lDQUNaOzZCQUNGO3lCQUNGO3FCQUNGLENBQUM7Z0JBQ0osQ0FBQzthQUNGLENBQUMsQ0FBQztZQUNILHFCQUFxQixFQUFFLElBQUk7U0FDNUIsQ0FBQyxDQUFDO1FBRUgsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSyxDQUFDLGdCQUFnQixDQUFDLHFCQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLDhDQUE4QyxDQUFDLENBQUMsQ0FBQztRQUVoSSx3REFBd0Q7UUFDeEQseUZBQXlGO1FBQ3pGLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUxRCxLQUFLLE1BQU0sS0FBSyxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDakMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztnQkFDeEIsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsV0FBVztnQkFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87YUFDdEIsQ0FBQyxDQUFDO1lBQ0gsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUVsQyxNQUFNLE9BQU8sR0FBRyxHQUFHLE1BQU0sQ0FBQyxjQUFjLElBQUksTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pELElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLE1BQU0sQ0FBQyxjQUFjLGNBQWMsTUFBTSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsQ0FBQzthQUMxSDtZQUNELElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRWhDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7WUFFN0MsTUFBTSxXQUFXLEdBQUcsR0FBRyxXQUFXLElBQUksTUFBTSxDQUFDLGNBQWMsSUFBSSxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDNUUsUUFBUSxDQUFDLElBQUksQ0FBQyxlQUFlLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFFNUMsMkRBQTJEO1lBQzNELGtDQUFrQztZQUNsQyxRQUFRLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxzRUFBc0U7UUFDdEUsS0FBSyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTFELHFCQUFHLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFFN0QsaUVBQWlFO1FBQ2pFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRS9DLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRTtZQUNuQixJQUFJLDhCQUFFLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFO2dCQUMvQyxtQkFBbUIsRUFBRSxLQUFLO2dCQUMxQixNQUFNLEVBQUUsOEJBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxZQUFZLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3pGLFFBQVEsRUFBRTtvQkFDUixNQUFNLEVBQUUsWUFBWTtvQkFDcEIsT0FBTyxFQUFFLFdBQVc7b0JBQ3BCLFVBQVUsRUFBRTt3QkFDVixXQUFXLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXO3dCQUNyQyxzQ0FBc0M7d0JBQ3RDLGdCQUFnQixFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFO3FCQUNsQztvQkFDRCxrQkFBa0IsRUFBRSw4QkFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztvQkFFcEUsb0ZBQW9GO29CQUNwRixXQUFXLEVBQUUsQ0FBQyxVQUFVLENBQUM7aUJBQzFCO2FBQ0YsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUU7WUFDbEIsSUFBSSx3QkFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7Z0JBQ3hDLFdBQVcsRUFBRSx3QkFBd0I7Z0JBQ3JDLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUTtnQkFDeEIsT0FBTyxFQUFFLENBQUMsSUFBSSxnQ0FBTyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUN0RCxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxpQkFBeUI7UUFDaEQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO1lBQ3RDLE9BQU87U0FDUjtRQUVELE1BQU0sVUFBVSxHQUFHLElBQUkscUJBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLE9BQU8saUJBQWlCLEVBQUUsRUFBRTtZQUN0RSxjQUFjLEVBQUUsaUJBQWlCO1NBQ2xDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksYUFBYSxDQUFDLGNBQXNCO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDekMsQ0FBQztDQUNGO0FBL0pELDhCQStKQztBQUFBLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFhLGVBQWU7SUFDMUIsWUFBNkIsTUFBaUI7UUFBakIsV0FBTSxHQUFOLE1BQU0sQ0FBVztJQUFHLENBQUM7SUFFM0MsS0FBSyxDQUFDLFNBQXFCO1FBQ2hDLElBQUksU0FBUyxZQUFZLDJCQUFTLENBQUMsT0FBTyxFQUFFO1lBQzFDLE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsWUFBb0MsQ0FBQztZQUN2RSxJQUFJLENBQUMsbUJBQUssQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxFQUFFO2dCQUMvQyxNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsV0FBdUQsQ0FBQztnQkFDL0UsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNwQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDekQsSUFBSSxXQUFXLEVBQUU7b0JBQ2YsVUFBVSxDQUFDLFdBQVcsR0FBRzt3QkFDdkIsR0FBRyxHQUFHO3dCQUNOLEtBQUssRUFBRSwyQkFBUyxDQUFDLGVBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTztxQkFDN0UsQ0FBQztvQkFDRixXQUFXLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUNqQyxxQkFBRyxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztpQkFDN0M7YUFDRjtTQUNGO0lBQ0gsQ0FBQztDQUNGO0FBdEJELDBDQXNCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElBc3BlY3QsIExhenksIFN0YWNrLCBUb2tlbixcbiAgYXdzX2VjciBhcyBlY3IsXG4gIGF3c19jb2RlYnVpbGQgYXMgY29kZWJ1aWxkLFxuICBhd3NfZXZlbnRzIGFzIGV2ZW50cyxcbiAgYXdzX2V2ZW50c190YXJnZXRzIGFzIHRhcmdldHMsXG4gIGF3c19pYW0gYXMgaWFtLFxuICBhd3NfczNfYXNzZXRzIGFzIHMzQXNzZXRzLFxuICBhd3Nfc2VjcmV0c21hbmFnZXIgYXMgc20sXG4gIGN1c3RvbV9yZXNvdXJjZXMgYXMgY3IsXG4gIEFubm90YXRpb25zLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE1pcnJvclNvdXJjZSB9IGZyb20gJy4vbWlycm9yLXNvdXJjZSc7XG5pbXBvcnQgeyBERUZBVUxUX1NVUEVSQ0hBSU5fSU1BR0UgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuXG4vKipcbiAqIEF1dGhlbnRpY2F0aW9uIGRldGFpbHMgZm9yIERvY2tlckh1Yi5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jb2RlYnVpbGQvbGF0ZXN0L3VzZXJndWlkZS9idWlsZC1zcGVjLXJlZi5odG1sI2J1aWxkLXNwZWMuZW52LnNlY3JldHMtbWFuYWdlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvY2tlckh1YkNyZWRlbnRpYWxzIHtcblxuICAvKipcbiAgICogVGhlIHNlY3JldCB0aGF0IGNvbnRhaW5zIHRoZSB1c2VybmFtZSBhbmQgcGFzc3dvcmQgZm9yIERvY2tlcmh1YlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjcmV0OiBzbS5JU2VjcmV0O1xuXG4gIC8qKlxuICAgKiBUaGUgc2VjcmV0IGtleSB0aGF0IGNvbnRhaW5zIHRoZSB1c2VybmFtZSBpbiB0aGUgc3BlY2lmaWVkIHNlY3JldC5cbiAgICovXG4gIHJlYWRvbmx5IHVzZXJuYW1lS2V5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZWNyZXQga2V5IHRoYXQgY29udGFpbnMgdGhlIHBhc3N3b3JkIGluIHRoZSBzcGVjaWZpZWQgc2VjcmV0LlxuICAgKi9cbiAgcmVhZG9ubHkgcGFzc3dvcmRLZXk6IHN0cmluZztcblxuICAvKipcbiAgICogVmVyc2lvbiBzdGFnZSBvZiB0aGUgc2VjcmV0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAnQVdTQ1VSUkVOVCdcbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb25TdGFnZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIHRvIGluaXRpYWxpemUgRWNyUmVnaXN0cnlTeW5jXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNyTWlycm9yUHJvcHMge1xuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgaW1hZ2VzIHRvIGtlZXAgc3luYydlZC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZXM6IE1pcnJvclNvdXJjZVtdO1xuXG4gIC8qKlxuICAgKiBDcmVkZW50aWFscyB0byBzaWduaW5nIGludG8gRG9ja2VyaHViLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VySHViQ3JlZGVudGlhbHM6IERvY2tlckh1YkNyZWRlbnRpYWxzO1xuXG4gIC8qKlxuICAgKiBUaGUgaW1hZ2UgdXNlZCB0byBydW4gdGhlIG1pcnJvciBzdGVwIGl0c2VsZi5cbiAgICpcbiAgICogUHJlZmVyIHRvIHN1cHBseSB0aGUgaW1hZ2UgeW91cnNlbGYgaGVyZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTb21lIHN1cGVyY2hhaW4gaW1hZ2UgdGhhdCBtYXkgZ3JvdyBvdXRkYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkSW1hZ2U/OiBjb2RlYnVpbGQuSUJ1aWxkSW1hZ2U7XG5cbiAgLyoqXG4gICAqIFN5bmMgam9iIHJ1bnMgb24gYSBzY2hlZHVsZS5cbiAgICogVGhyb3dzIGFuIGVycm9yIGlmIG5laXRoZXIgdGhpcyBub3IgYGF1dG9TdGFydGAgYXJlIHNwZWNpZmllZC5cbiAgICogQGRlZmF1bHQgLSBkb2VzIG5vdCBydW4gb24gc2NoZWR1bGVcbiAgICovXG4gIHJlYWRvbmx5IHNjaGVkdWxlPzogZXZlbnRzLlNjaGVkdWxlO1xuXG4gIC8qKlxuICAgKiBTdGFydCB0aGUgc3luYyBqb2IgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGRlcGxveW1lbnQuXG4gICAqIFRoaXMgaW5qZWN0cyBhIGN1c3RvbSByZXNvdXJjZSB0aGF0IGlzIGV4ZWN1dGVkIGFzIHBhcnQgb2YgdGhlIGRlcGxveW1lbnQuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiBuZWl0aGVyIHRoaXMgbm9yIGBzY2hlZHVsZWAgYXJlIHNwZWNpZmllZC5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGF1dG9TdGFydD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogU3luY2hyb25pemUgaW1hZ2VzIGZyb20gRG9ja2VySHViIHRvIGFuIEVDUiByZWdpc3RyeSBpbiB0aGUgQVdTIGFjY291bnQuXG4gKiBUaGlzIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgdG8gd29ya2Fyb3VuZCBEb2NrZXJIdWIncyB0aHJvdHRsaW5nIG9uIHB1bGxzIGFuZCB1c2UgRUNSIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBFY3JNaXJyb3IgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3JlcG9zOiBNYXA8c3RyaW5nLCBlY3IuUmVwb3NpdG9yeT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3JlcG9UYWdzU2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIHB1YmxpYyByZWFkb25seSBwcm9qZWN0OiBjb2RlYnVpbGQuUHJvamVjdDtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRWNyTWlycm9yUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKCFwcm9wcy5zY2hlZHVsZSAmJiAhcHJvcHMuYXV0b1N0YXJ0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VpdGhlciBzY2hlZHVsZSBvciBhdXRvU3RhcnQgbXVzdCBiZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGVjclJlZ2lzdHJ5ID0gYCR7U3RhY2sub2Yoc2NvcGUpLmFjY291bnR9LmRrci5lY3IuJHtTdGFjay5vZihzY29wZSkucmVnaW9ufS5hbWF6b25hd3MuY29tYDtcbiAgICBjb25zdCBjb21tYW5kczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBhc3NldHMgPSBuZXcgQXJyYXk8czNBc3NldHMuQXNzZXQ+KCk7XG5cbiAgICBjb25zdCBjb2RlQnVpbGRTZWNyZXRWYWx1ZSA9IChrZXk6IHN0cmluZywgYXV0aDogRG9ja2VySHViQ3JlZGVudGlhbHMpID0+IHtcbiAgICAgIHJldHVybiBgJHtwcm9wcy5kb2NrZXJIdWJDcmVkZW50aWFscy5zZWNyZXQuc2VjcmV0TmFtZX06JHtrZXl9OiR7YXV0aC52ZXJzaW9uU3RhZ2UgPz8gJ0FXU0NVUlJFTlQnfWA7XG4gICAgfTtcblxuICAgIGNvbnN0IHVzZXJuYW1lID0gY29kZUJ1aWxkU2VjcmV0VmFsdWUocHJvcHMuZG9ja2VySHViQ3JlZGVudGlhbHMudXNlcm5hbWVLZXksIHByb3BzLmRvY2tlckh1YkNyZWRlbnRpYWxzKTtcbiAgICBjb25zdCBwYXNzd29yZCA9IGNvZGVCdWlsZFNlY3JldFZhbHVlKHByb3BzLmRvY2tlckh1YkNyZWRlbnRpYWxzLnBhc3N3b3JkS2V5LCBwcm9wcy5kb2NrZXJIdWJDcmVkZW50aWFscyk7XG5cbiAgICBpZiAoIXByb3BzLmJ1aWxkSW1hZ2UpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmdWMignYXdzLWRlbGl2bGliOkVjck1pcnJvci5taXNzaW5nQnVpbGRJbWFnZScsICdQcmVmZXIgc3VwcGx5aW5nIGFuIGV4cGxpY2l0IGJ1aWxkIGltYWdlIHRvIHJlbHlpbmcgb24gdGhlIGRlZmF1bHQgc3VwZXJjaGFpbi4nKTtcbiAgICB9XG5cbiAgICB0aGlzLnByb2plY3QgPSBuZXcgY29kZWJ1aWxkLlByb2plY3QodGhpcywgJ0VjclB1c2hJbWFnZXMnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogTGF6eS5zdHJpbmcoeyBwcm9kdWNlOiAoKSA9PiBgU3luY2hyb25pemUgJHtwcm9wcy5zb3VyY2VzLmxlbmd0aH0gaW1hZ2VzIGZyb20gRG9ja2VySHViIHRvIGxvY2FsIEVDUmAgfSksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBwcml2aWxlZ2VkOiB0cnVlLFxuICAgICAgICBidWlsZEltYWdlOiBwcm9wcy5idWlsZEltYWdlID8/IGNvZGVidWlsZC5MaW51eEJ1aWxkSW1hZ2UuZnJvbURvY2tlclJlZ2lzdHJ5KERFRkFVTFRfU1VQRVJDSEFJTl9JTUFHRSksXG4gICAgICB9LFxuICAgICAgZW52aXJvbm1lbnRWYXJpYWJsZXM6IHtcbiAgICAgICAgLy8gRG9ja2VySHViIGNyZWRlbnRpYWxzIHRvIGF2b2lkIHRocm90dGxpbmdcbiAgICAgICAgRE9DS0VSSFVCX1VTRVJOQU1FOiB7IHZhbHVlOiB1c2VybmFtZSwgdHlwZTogY29kZWJ1aWxkLkJ1aWxkRW52aXJvbm1lbnRWYXJpYWJsZVR5cGUuU0VDUkVUU19NQU5BR0VSIH0sXG4gICAgICAgIERPQ0tFUkhVQl9QQVNTV09SRDogeyB2YWx1ZTogcGFzc3dvcmQsIHR5cGU6IGNvZGVidWlsZC5CdWlsZEVudmlyb25tZW50VmFyaWFibGVUeXBlLlNFQ1JFVFNfTUFOQUdFUiB9LFxuICAgICAgfSxcbiAgICAgIGJ1aWxkU3BlYzogY29kZWJ1aWxkLkJ1aWxkU3BlYy5mcm9tT2JqZWN0KExhenkuYW55KHtcbiAgICAgICAgcHJvZHVjZTogKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2ZXJzaW9uOiAnMC4yJyxcbiAgICAgICAgICAgIHBoYXNlczoge1xuICAgICAgICAgICAgICBidWlsZDoge1xuICAgICAgICAgICAgICAgIGNvbW1hbmRzOiBbXG5cbiAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0IHRoZSBkb2NrZXIgZGFlbW9uXG4gICAgICAgICAgICAgICAgICAnbm9odXAgL3Vzci9iaW4vZG9ja2VyZCAtLWhvc3Q9dW5peDovLy92YXIvcnVuL2RvY2tlci5zb2NrIC0taG9zdD10Y3A6Ly8xMjcuMC4wLjE6MjM3NSAtLXN0b3JhZ2UtZHJpdmVyPW92ZXJsYXkyJicsXG4gICAgICAgICAgICAgICAgICAndGltZW91dCAxNSBzaCAtYyBcInVudGlsIGRvY2tlciBpbmZvOyBkbyBlY2hvIC47IHNsZWVwIDE7IGRvbmVcIicsXG5cbiAgICAgICAgICAgICAgICAgIC8vIGxvZ2luIHRvIGRvY2tlcmh1YiBzbyB3ZSB3b24ndCBnZXQgdGhyb3R0bGVkXG4gICAgICAgICAgICAgICAgICAnZG9ja2VyIGxvZ2luIC11ICR7RE9DS0VSSFVCX1VTRVJOQU1FfSAtcCAke0RPQ0tFUkhVQl9QQVNTV09SRH0nLFxuXG4gICAgICAgICAgICAgICAgICAvLyBsb2dpbiB0byBlY3Igc28gd2UgY2FuIHB1c2ggdG8gaXRcbiAgICAgICAgICAgICAgICAgIGBhd3MgZWNyIGdldC1sb2dpbi1wYXNzd29yZCB8IGRvY2tlciBsb2dpbiAtLXVzZXJuYW1lIEFXUyAtLXBhc3N3b3JkLXN0ZGluICR7ZWNyUmVnaXN0cnl9YCxcblxuICAgICAgICAgICAgICAgICAgLy8gbG9naW4gdG8gZWNyLXB1YmxpYyBzbyB3ZSBjYW4gcHVsbCBmcm9tIGl0IHdpdGggaW1wcm92ZWQgcmF0ZSBsaW1pdHNcbiAgICAgICAgICAgICAgICAgICdhd3MgZWNyLXB1YmxpYyBnZXQtbG9naW4tcGFzc3dvcmQgLS1yZWdpb24gdXMtZWFzdC0xIHwgZG9ja2VyIGxvZ2luIC0tdXNlcm5hbWUgQVdTIC0tcGFzc3dvcmQtc3RkaW4gcHVibGljLmVjci5hd3MnLFxuXG4gICAgICAgICAgICAgICAgICAuLi5jb21tYW5kcyxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgfSkpLFxuICAgICAgc3NtU2Vzc2lvblBlcm1pc3Npb25zOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgLy8gRW5zdXJlIHRoZSBydW5uZXIgaGFzIFBVTEwgYWNjZXNzIHRvIEVDUi1QdWJsaWMuXG4gICAgdGhpcy5wcm9qZWN0LnJvbGUhLmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FbGFzdGljQ29udGFpbmVyUmVnaXN0cnlQdWJsaWNSZWFkT25seScpKTtcblxuICAgIC8vIEdpdmUgdGhlIHByb2plY3QgYWNjZXNzIHRvIHRoZSBEb2NrZXIgSHViIGNyZWRlbnRpYWxzXG4gICAgLy8gUmVxdWlyZWQgZm9yIGFjY2VzcyB0byBwcml2YXRlIGltYWdlcyBhbmQgdG8gYXZvaWQgdGhyb3R0bGluZyBvZiB1bmF1dGhvcml6ZWQgcmVxdWVzdHNcbiAgICBwcm9wcy5kb2NrZXJIdWJDcmVkZW50aWFscy5zZWNyZXQuZ3JhbnRSZWFkKHRoaXMucHJvamVjdCk7XG5cbiAgICBmb3IgKGNvbnN0IGltYWdlIG9mIHByb3BzLnNvdXJjZXMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGltYWdlLmJpbmQoe1xuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgICAgZWNyUmVnaXN0cnksXG4gICAgICAgIHN5bmNKb2I6IHRoaXMucHJvamVjdCxcbiAgICAgIH0pO1xuICAgICAgY29tbWFuZHMucHVzaCguLi5yZXN1bHQuY29tbWFuZHMpO1xuXG4gICAgICBjb25zdCByZXBvVGFnID0gYCR7cmVzdWx0LnJlcG9zaXRvcnlOYW1lfToke3Jlc3VsdC50YWd9YDtcbiAgICAgIGlmICh0aGlzLl9yZXBvVGFnc1NlZW4uaGFzKHJlcG9UYWcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTWlycm9yIHNvdXJjZSB3aXRoIHJlcG9zaXRvcnkgbmFtZSBbJHtyZXN1bHQucmVwb3NpdG9yeU5hbWV9XSBhbmQgdGFnIFske3Jlc3VsdC50YWd9XSBhbHJlYWR5IGV4aXN0cy5gKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3JlcG9UYWdzU2Vlbi5hZGQocmVwb1RhZyk7XG5cbiAgICAgIHRoaXMuY3JlYXRlTWlycm9yUmVwbyhyZXN1bHQucmVwb3NpdG9yeU5hbWUpO1xuXG4gICAgICBjb25zdCBlY3JJbWFnZVVyaSA9IGAke2VjclJlZ2lzdHJ5fS8ke3Jlc3VsdC5yZXBvc2l0b3J5TmFtZX06JHtyZXN1bHQudGFnfWA7XG4gICAgICBjb21tYW5kcy5wdXNoKGBkb2NrZXIgcHVzaCAke2VjckltYWdlVXJpfWApO1xuXG4gICAgICAvLyBjbGVhbiBhZnRlciBlYWNoIHB1c2ggc28gdGhhdCB3ZSBkb24ndCBmaWxsdXAgZGlzayBzcGFjZVxuICAgICAgLy8gcG9zc2libHkgZmFpbGluZyB0aGUgbmV4dCBwdWxsLlxuICAgICAgY29tbWFuZHMucHVzaCgnZG9ja2VyIGltYWdlIHBydW5lIC0tYWxsIC0tZm9yY2UnKTtcbiAgICB9XG5cbiAgICAvLyBDb2RlQnVpbGQgbmVlZHMgdG8gcmVhZCB0aGUgc2VjcmV0IHRvIHJlc29sdmUgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAgcHJvcHMuZG9ja2VySHViQ3JlZGVudGlhbHMuc2VjcmV0LmdyYW50UmVhZCh0aGlzLnByb2plY3QpO1xuXG4gICAgZWNyLkF1dGhvcml6YXRpb25Ub2tlbi5ncmFudFJlYWQodGhpcy5wcm9qZWN0KTtcbiAgICB0aGlzLl9yZXBvcy5mb3JFYWNoKChyLCBfKSA9PiByLmdyYW50UHVsbFB1c2godGhpcy5wcm9qZWN0KSk7XG5cbiAgICAvLyB0aGlzIHByb2plY3QgbmVlZHMgdG8gZG93bmxvYWQgdGhlIGFzc2V0cyBzbyBpdCBjYW4gYnVpbGQgdGhlbVxuICAgIGFzc2V0cy5mb3JFYWNoKGEgPT4gYS5ncmFudFJlYWQodGhpcy5wcm9qZWN0KSk7XG5cbiAgICBpZiAocHJvcHMuYXV0b1N0YXJ0KSB7XG4gICAgICBuZXcgY3IuQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgJ0J1aWxkRXhlY3V0aW9uJywge1xuICAgICAgICBpbnN0YWxsTGF0ZXN0QXdzU2RrOiBmYWxzZSxcbiAgICAgICAgcG9saWN5OiBjci5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU2RrQ2FsbHMoeyByZXNvdXJjZXM6IFt0aGlzLnByb2plY3QucHJvamVjdEFybl0gfSksXG4gICAgICAgIG9uVXBkYXRlOiB7XG4gICAgICAgICAgYWN0aW9uOiAnc3RhcnRCdWlsZCcsXG4gICAgICAgICAgc2VydmljZTogJ0NvZGVCdWlsZCcsXG4gICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgcHJvamVjdE5hbWU6IHRoaXMucHJvamVjdC5wcm9qZWN0TmFtZSxcbiAgICAgICAgICAgIC8vIHRvIHRpZ2dlciB0aGUgYnVpbGQgb24gZXZlcnkgdXBkYXRlXG4gICAgICAgICAgICBpZGVtcG90ZW5jeVRva2VuOiBgJHtEYXRlLm5vdygpfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6IGNyLlBoeXNpY2FsUmVzb3VyY2VJZC5vZignRWNyUmVnaXN0cnlFeGVjdXRpb24nKSxcblxuICAgICAgICAgIC8vIG5lZWQgc2luY2UgdGhlIGRlZmF1bHQgcmVwb25zZSBpZiBncmVhdGVyIHRoYW4gdGhlIDRrIGxpbWl0IGZvciBjdXN0b20gcmVzb3VyY2VzLlxuICAgICAgICAgIG91dHB1dFBhdGhzOiBbJ2J1aWxkLmlkJ10sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuc2NoZWR1bGUpIHtcbiAgICAgIG5ldyBldmVudHMuUnVsZSh0aGlzLCAnU2NoZWR1bGVkVHJpZ2dlcicsIHtcbiAgICAgICAgZGVzY3JpcHRpb246ICdUcmlnZ2VyIEVDUiBtaXJyb3Igam9iJyxcbiAgICAgICAgc2NoZWR1bGU6IHByb3BzLnNjaGVkdWxlLFxuICAgICAgICB0YXJnZXRzOiBbbmV3IHRhcmdldHMuQ29kZUJ1aWxkUHJvamVjdCh0aGlzLnByb2plY3QpXSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlTWlycm9yUmVwbyhlY3JSZXBvc2l0b3J5TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuX3JlcG9zLmdldChlY3JSZXBvc2l0b3J5TmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCByZXBvc2l0b3J5ID0gbmV3IGVjci5SZXBvc2l0b3J5KHRoaXMsIGBSZXBvJHtlY3JSZXBvc2l0b3J5TmFtZX1gLCB7XG4gICAgICByZXBvc2l0b3J5TmFtZTogZWNyUmVwb3NpdG9yeU5hbWUsXG4gICAgfSk7XG4gICAgdGhpcy5fcmVwb3Muc2V0KGVjclJlcG9zaXRvcnlOYW1lLCByZXBvc2l0b3J5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHRhcmdldCBFQ1IgcmVwb3NpdG9yeSBmb3IgdGhlIGdpdmVuIHJlcG9zaXRvcnkgbmFtZSBhbmQgdGFnLlxuICAgKiBAcGFyYW0gcmVwb3NpdG9yeU5hbWUgVGhlIEVDUiByZXBvc2l0b3J5IHdpdGggdGhpcyBuYW1lXG4gICAqIEBwYXJhbSB0YWcgdGhlIHRhZyBmb3IgdGhlIHJlcG9zaXRvcnksIGRlZmF1bHRzIHRvICdsYXRlc3QnXG4gICAqL1xuICBwdWJsaWMgZWNyUmVwb3NpdG9yeShyZXBvc2l0b3J5TmFtZTogc3RyaW5nKTogZWNyLklSZXBvc2l0b3J5IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fcmVwb3MuZ2V0KHJlcG9zaXRvcnlOYW1lKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBbiBhc3BlY3QgdGhhdCB3YWxrcyB0aHJvdWdoIHRoZSBjb25zdHJ1Y3QgdHJlZSBhbmQgcmVwbGFjZXMgQ29kZUJ1aWxkIGpvYnMgd2l0aCBEb2NrZXIgaW1hZ2VzXG4gKiB3aXRoIEVDUiBlcXVpdmFsZW50cyBmb3VuZCBpbiB0aGUgRWNyTWlycm9yLlxuICovXG5leHBvcnQgY2xhc3MgRWNyTWlycm9yQXNwZWN0IGltcGxlbWVudHMgSUFzcGVjdCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbWlycm9yOiBFY3JNaXJyb3IpIHt9XG5cbiAgcHVibGljIHZpc2l0KGNvbnN0cnVjdDogSUNvbnN0cnVjdCkge1xuICAgIGlmIChjb25zdHJ1Y3QgaW5zdGFuY2VvZiBjb2RlYnVpbGQuUHJvamVjdCkge1xuICAgICAgY29uc3QgY2ZucHJvamVjdCA9IGNvbnN0cnVjdC5ub2RlLmRlZmF1bHRDaGlsZCBhcyBjb2RlYnVpbGQuQ2ZuUHJvamVjdDtcbiAgICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGNmbnByb2plY3QuZW52aXJvbm1lbnQpKSB7XG4gICAgICAgIGNvbnN0IGVudiA9IGNmbnByb2plY3QuZW52aXJvbm1lbnQgYXMgY29kZWJ1aWxkLkNmblByb2plY3QuRW52aXJvbm1lbnRQcm9wZXJ0eTtcbiAgICAgICAgY29uc3QgaW1hZ2VOYW1lID0gZW52LmltYWdlLnNwbGl0KCc6JylbMF07XG4gICAgICAgIGNvbnN0IHRhZyA9IGVudi5pbWFnZS5zcGxpdCgnOicpWzFdO1xuICAgICAgICBjb25zdCByZXBsYWNlbWVudCA9IHRoaXMubWlycm9yLmVjclJlcG9zaXRvcnkoaW1hZ2VOYW1lKTtcbiAgICAgICAgaWYgKHJlcGxhY2VtZW50KSB7XG4gICAgICAgICAgY2ZucHJvamVjdC5lbnZpcm9ubWVudCA9IHtcbiAgICAgICAgICAgIC4uLmVudixcbiAgICAgICAgICAgIGltYWdlOiBjb2RlYnVpbGQuTGludXhCdWlsZEltYWdlLmZyb21FY3JSZXBvc2l0b3J5KHJlcGxhY2VtZW50LCB0YWcpLmltYWdlSWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXBsYWNlbWVudC5ncmFudFB1bGwoY29uc3RydWN0KTtcbiAgICAgICAgICBlY3IuQXV0aG9yaXphdGlvblRva2VuLmdyYW50UmVhZChjb25zdHJ1Y3QpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=