deploy-time-build
Version:
Build during CDK deployment.
221 lines • 36.4 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContainerImageBuild = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const fs_1 = require("fs");
const path_1 = require("path");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_codebuild_1 = require("aws-cdk-lib/aws-codebuild");
const aws_ecr_1 = require("aws-cdk-lib/aws-ecr");
const aws_ecs_1 = require("aws-cdk-lib/aws-ecs");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets");
const constructs_1 = require("constructs");
const singleton_project_1 = require("./singleton-project");
/**
* Build a container image and push it to an ECR repository on deploy-time.
*/
class ContainerImageBuild extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
this.props = props;
const handler = new aws_lambda_1.SingletonFunction(this, 'CustomResourceHandler', {
// Use raw string to avoid from tightening CDK version requirement
runtime: new aws_lambda_1.Runtime('nodejs22.x', aws_lambda_1.RuntimeFamily.NODEJS),
code: aws_lambda_1.Code.fromAsset((0, path_1.join)(__dirname, '..', 'lambda', 'trigger-codebuild', 'dist')),
handler: 'index.handler',
uuid: 'db740fd5-5436-4a84-8a09-e6dfcd01f4f3', // generated for this construct
lambdaPurpose: 'DeployTimeBuildCustomResourceHandler',
timeout: aws_cdk_lib_1.Duration.minutes(5),
});
// Use buildx for cross-platform image build
const armImage = aws_codebuild_1.LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:3.0');
const x64Image = aws_codebuild_1.LinuxBuildImage.fromCodeBuildImageId('aws/codebuild/standard:7.0');
// Select the build image based on the target platform
const isArm64 = props.platform?.platform === 'linux/arm64';
const buildImage = isArm64 ? armImage : x64Image;
let repository = props.repository;
if (repository === undefined) {
repository = new aws_ecr_1.Repository(this, 'Repository', { removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY });
repository.node.defaultChild.addPropertyOverride('EmptyOnDelete', true);
repository.node.defaultChild.addPropertyOverride('ImageScanningConfiguration.ScanOnPush', true);
}
const repositoryUri = repository.repositoryUri;
const imageArtifactName = 'artifact:$imageTag';
const project = new singleton_project_1.SingletonProject(this, 'Project', {
uuid: 'e83729fe-b156-4e70-9bec-452b15847a30',
projectPurpose: isArm64 ? 'ContainerImageBuildArm64' : 'ContainerImageBuildAmd64',
environment: {
computeType: aws_codebuild_1.ComputeType.SMALL,
buildImage: buildImage,
privileged: true,
},
vpc: props.vpc,
buildSpec: aws_codebuild_1.BuildSpec.fromObject({
version: '0.2',
phases: {
build: {
commands: [
'current_dir=$(pwd)',
'echo "$input"',
'mkdir workdir',
'cd workdir',
'aws s3 cp "$sourceS3Url" temp.zip',
'unzip temp.zip',
'ls -la',
'aws ecr get-login-password --region $repositoryRegion | docker login --username AWS --password-stdin $repositoryAuthUri',
// for accessing ECR public
'aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws',
'docker buildx ls',
'echo "$buildCommand"',
'eval "$buildCommand"',
'docker images',
`docker tag ${imageArtifactName} $repositoryUri:$imageTag`,
`docker push $repositoryUri:$imageTag`,
],
},
post_build: {
commands: [
'echo Build completed on `date`',
`
STATUS='SUCCESS'
if [ $CODEBUILD_BUILD_SUCCEEDING -ne 1 ] # Test if the build is failing
then
STATUS='FAILED'
REASON="ContainerImageBuild failed. See CloudWatch Log stream for the detailed reason:
https://$AWS_REGION.console.aws.amazon.com/cloudwatch/home?region=$AWS_REGION#logsV2:log-groups/log-group/\\$252Faws\\$252Fcodebuild\\$252F$projectName/log-events/$CODEBUILD_LOG_PATH"
fi
cat <<EOF > payload.json
{
"StackId": "$stackId",
"RequestId": "$requestId",
"LogicalResourceId":"$logicalResourceId",
"PhysicalResourceId": "$imageTag",
"Status": "$STATUS",
"Reason": "$REASON",
"Data": {
"ImageTag": "$imageTag"
}
}
EOF
curl -i -X PUT -H 'Content-Type:' -d "@payload.json" "$responseURL"
`,
],
},
},
}),
}).project;
project.role.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly'));
repository.grantPullPush(project);
repository.grant(project, 'ecr:DescribeImages');
handler.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['codebuild:StartBuild'],
resources: [project.projectArn],
}));
this.grantPrincipal = project.grantPrincipal;
let assetExclude = props.exclude;
// automatically read .dockerignore for convenience
if (assetExclude === undefined && (0, fs_1.existsSync)((0, path_1.join)(props.directory, '.dockerignore'))) {
assetExclude = (0, fs_1.readFileSync)((0, path_1.join)(props.directory, '.dockerignore')).toString().split('\n');
}
const asset = new aws_s3_assets_1.Asset(this, 'Source', {
...props,
exclude: assetExclude,
path: props.directory,
});
asset.grantRead(project);
const buildCommandOptions = { ...props, platform: props.platform?.platform };
buildCommandOptions.outputs ?? (buildCommandOptions.outputs = []);
// we don't use push=true here because CodeBuild Docker server does not seem to work properly with the configuration.
buildCommandOptions.outputs.push('type=docker', `name=${imageArtifactName}`);
if (props.zstdCompression) {
// to enable zstd compression, buildx directly pushes the artifact image to a registry
// https://aws.amazon.com/blogs/containers/reducing-aws-fargate-startup-times-with-zstd-compressed-container-images/
buildCommandOptions.outputs.push('oci-mediatypes=true', 'compression=zstd', 'force-compression=true', 'compression-level=3');
}
const buildCommand = this.getDockerBuildCommand(buildCommandOptions);
const properties = {
type: 'ContainerImageBuild',
buildCommand: buildCommand,
repositoryUri,
imageTag: props.tag,
tagPrefix: props.tagPrefix,
codeBuildProjectName: project.projectName,
sourceS3Url: asset.s3ObjectUrl,
};
const custom = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
serviceToken: handler.functionArn,
resourceType: 'Custom::CDKContainerImageBuild',
properties,
});
custom.node.addDependency(project);
this.repository = repository;
this.imageTag = custom.getAttString('ImageTag');
this.imageUri = `${repositoryUri}:${this.imageTag}`;
}
/**
* Get the instance of {@link DockerImageCode} for a Lambda function image.
* @param options Optional configuration for Docker image code.
*/
toLambdaDockerImageCode(options) {
if (this.props.zstdCompression) {
throw new Error('You cannot enable zstdCompression for a Lambda image.');
}
return aws_lambda_1.DockerImageCode.fromEcr(this.repository, {
tagOrDigest: this.imageTag,
...(options && {
cmd: options.cmd,
entrypoint: options.entrypoint,
workingDirectory: options.workingDirectory,
}),
});
}
/**
* Get the instance of {@link ContainerImage} for an ECS task definition.
*/
toEcsDockerImageCode() {
return aws_ecs_1.ContainerImage.fromEcrRepository(this.repository, this.imageTag);
}
getDockerBuildCommand(options) {
// the members of props differs with CDK version.
// By regarding props as any, we can use props that are not available in older cdk versions.
// logic is copied from packages/cdk-assets/lib/private/docker.ts
const cacheOptionToFlag = (option) => {
let flag = `type=${option.type}`;
if (option.params) {
flag +=
',' +
Object.entries(option.params)
.map(([k, v]) => `${k}=${v}`)
.join(',');
}
return flag;
};
const flatten = (x) => {
return Array.prototype.concat([], ...x);
};
const dockerBuildCommand = [
'docker buildx build',
...flatten(Object.entries(options.buildArgs || {}).map(([k, v]) => ['--build-arg', `${k}=${v}`])),
...flatten(Object.entries(options.buildSecrets || {}).map(([k, v]) => ['--secret', `id=${k},${v}`])),
...(options.buildSsh ? ['--ssh', options.buildSsh] : []),
...(options.target ? ['--target', options.target] : []),
...(options.file ? ['--file', options.file] : []),
...(options.networkMode ? ['--network', options.networkMode] : []),
...(options.platform ? ['--platform', options.platform] : []),
...(options.outputs ? ['--output', options.outputs.join(',')] : []),
...(options.cacheFrom ? [...options.cacheFrom.map((cacheFrom) => ['--cache-from', cacheOptionToFlag(cacheFrom)]).flat()] : []),
...(options.cacheTo ? ['--cache-to', cacheOptionToFlag(options.cacheTo)] : []),
...(options.cacheDisabled ? ['--no-cache'] : []),
'--provenance=false',
'.',
];
return dockerBuildCommand.join(' ');
}
}
exports.ContainerImageBuild = ContainerImageBuild;
_a = JSII_RTTI_SYMBOL_1;
ContainerImageBuild[_a] = { fqn: "deploy-time-build.ContainerImageBuild", version: "0.4.5" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGFpbmVyLWltYWdlLWJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnRhaW5lci1pbWFnZS1idWlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJCQUE4QztBQUM5QywrQkFBNEI7QUFDNUIsNkNBQW1GO0FBQ25GLDZEQUF3RztBQUV4RyxpREFBOEQ7QUFFOUQsaURBQXFEO0FBQ3JELGlEQUE2RjtBQUM3Rix1REFBMEc7QUFDMUcsNkRBQWtEO0FBQ2xELDJDQUF1QztBQUN2QywyREFBdUQ7QUFvRXZEOztHQUVHO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxzQkFBUztJQU1oRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFtQixLQUErQjtRQUN4RixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRHdDLFVBQUssR0FBTCxLQUFLLENBQTBCO1FBR3hGLE1BQU0sT0FBTyxHQUFHLElBQUksOEJBQWlCLENBQUMsSUFBSSxFQUFFLHVCQUF1QixFQUFFO1lBQ25FLGtFQUFrRTtZQUNsRSxPQUFPLEVBQUUsSUFBSSxvQkFBTyxDQUFDLFlBQVksRUFBRSwwQkFBYSxDQUFDLE1BQU0sQ0FBQztZQUN4RCxJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQUMsSUFBQSxXQUFJLEVBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbEYsT0FBTyxFQUFFLGVBQWU7WUFDeEIsSUFBSSxFQUFFLHNDQUFzQyxFQUFFLCtCQUErQjtZQUM3RSxhQUFhLEVBQUUsc0NBQXNDO1lBQ3JELE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsNENBQTRDO1FBQzVDLE1BQU0sUUFBUSxHQUFHLGtDQUFrQixDQUFDLG9CQUFvQixDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDNUcsTUFBTSxR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LFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsY0FBYyxFQUFFLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbkksR0FBRyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDOUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNoRCxvQkFBb0I7WUFDcEIsR0FBRztTQUNKLENBQUM7UUFDRixPQUFPLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QyxDQUFDOztBQTNOSCxrREE0TkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDZm5SZXNvdXJjZSwgQ3VzdG9tUmVzb3VyY2UsIER1cmF0aW9uLCBSZW1vdmFsUG9saWN5IH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQnVpbGRTcGVjLCBDb21wdXRlVHlwZSwgTGludXhBcm1CdWlsZEltYWdlLCBMaW51eEJ1aWxkSW1hZ2UgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY29kZWJ1aWxkJztcbmltcG9ydCB7IElWcGMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCB7IElSZXBvc2l0b3J5LCBSZXBvc2l0b3J5IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcic7XG5pbXBvcnQgeyBEb2NrZXJJbWFnZUFzc2V0UHJvcHMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyLWFzc2V0cyc7XG5pbXBvcnQgeyBDb250YWluZXJJbWFnZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3MnO1xuaW1wb3J0IHsgSUdyYW50YWJsZSwgSVByaW5jaXBhbCwgTWFuYWdlZFBvbGljeSwgUG9saWN5U3RhdGVtZW50IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgeyBDb2RlLCBEb2NrZXJJbWFnZUNvZGUsIFJ1bnRpbWUsIFJ1bnRpbWVGYW1pbHksIFNpbmdsZXRvbkZ1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBBc3NldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMy1hc3NldHMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBTaW5nbGV0b25Qcm9qZWN0IH0gZnJvbSAnLi9zaW5nbGV0b24tcHJvamVjdCc7XG5pbXBvcnQgeyBDb250YWluZXJJbWFnZUJ1aWxkUmVzb3VyY2VQcm9wcyB9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhaW5lckltYWdlQnVpbGRQcm9wcyBleHRlbmRzIERvY2tlckltYWdlQXNzZXRQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgdGFnIHdoZW4gdG8gcHVzaCB0aGUgaW1hZ2VcbiAgICogQGRlZmF1bHQgdXNlIGFzc2V0SGFzaCBhcyB0YWdcbiAgICovXG4gIHJlYWRvbmx5IHRhZz86IHN0cmluZztcblxuICAvKipcbiAgICogUHJlZml4IHRvIGFkZCB0byB0aGUgaW1hZ2UgdGFnXG4gICAqIEBkZWZhdWx0IG5vIHByZWZpeFxuICAgKi9cbiAgcmVhZG9ubHkgdGFnUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgRUNSIHJlcG9zaXRvcnkgdG8gcHVzaCB0aGUgaW1hZ2UuXG4gICAqIEBkZWZhdWx0IGNyZWF0ZSBhIG5ldyBFQ1IgcmVwb3NpdG9yeVxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb3NpdG9yeT86IElSZXBvc2l0b3J5O1xuXG4gIC8qKlxuICAgKiBVc2UgenN0ZCBmb3IgY29tcHJlc3NpbmcgYSBjb250YWluZXIgaW1hZ2UuXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSB6c3RkQ29tcHJlc3Npb24/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgVlBDIHdoZXJlIHlvdXIgYnVpbGQgam9iIHdpbGwgYmUgZGVwbG95ZWQuXG4gICAqIFRoaXMgVlBDIG11c3QgaGF2ZSBwcml2YXRlIHN1Ym5ldHMgd2l0aCBOQVQgR2F0ZXdheXMuXG4gICAqXG4gICAqIFVzZSB0aGlzIHByb3BlcnR5IHdoZW4geW91IHdhbnQgdG8gY29udHJvbCB0aGUgb3V0Ym91bmQgSVAgYWRkcmVzc2VzIHRoYXQgYmFzZSBpbWFnZXMgYXJlIHB1bGxlZCBmcm9tLlxuICAgKiBAZGVmYXVsdCBObyBWUEMgdXNlZC5cbiAgICovXG4gIHJlYWRvbmx5IHZwYz86IElWcGM7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgTGFtYmRhIERvY2tlciBpbWFnZSBjb2RlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYURvY2tlckltYWdlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IG9yIG92ZXJyaWRlIHRoZSBDTUQgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogVGhpcyBuZWVkcyB0byBiZSBpbiB0aGUgJ2V4ZWMgZm9ybScsIHZpei4sIGBbICdleGVjdXRhYmxlJywgJ3BhcmFtMScsICdwYXJhbTInIF1gLlxuICAgKiBAc2VlIDxodHRwczovL2RvY3MuZG9ja2VyLmNvbS9lbmdpbmUvcmVmZXJlbmNlL2J1aWxkZXIvI2NtZD5cbiAgICogQGRlZmF1bHQgLSB1c2UgdGhlIENNRCBzcGVjaWZpZWQgaW4gdGhlIGRvY2tlciBpbWFnZSBvciBEb2NrZXJmaWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgY21kPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgb3Igb3ZlcnJpZGUgdGhlIEVOVFJZUE9JTlQgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogQW4gRU5UUllQT0lOVCBhbGxvd3MgeW91IHRvIGNvbmZpZ3VyZSBhIGNvbnRhaW5lciB0aGF0IHdpbGwgcnVuIGFzIGFuIGV4ZWN1dGFibGUuXG4gICAqIFRoaXMgbmVlZHMgdG8gYmUgaW4gdGhlICdleGVjIGZvcm0nLCB2aXouLCBgWyAnZXhlY3V0YWJsZScsICdwYXJhbTEnLCAncGFyYW0yJyBdYC5cbiAgICogQHNlZSA8aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3JlZmVyZW5jZS9idWlsZGVyLyNlbnRyeXBvaW50PlxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgRU5UUllQT0lOVCBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSBlbnRyeXBvaW50Pzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgb3Igb3ZlcnJpZGUgdGhlIFdPUktESVIgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogQSBXT1JLRElSIGFsbG93cyB5b3UgdG8gY29uZmlndXJlIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0aGUgY29udGFpbmVyIHdpbGwgdXNlLlxuICAgKiBAc2VlIDxodHRwczovL2RvY3MuZG9ja2VyLmNvbS9lbmdpbmUvcmVmZXJlbmNlL2J1aWxkZXIvI3dvcmtkaXI+XG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBXT1JLRElSIGluIHRoZSBkb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICovXG4gIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQnVpbGQgYSBjb250YWluZXIgaW1hZ2UgYW5kIHB1c2ggaXQgdG8gYW4gRUNSIHJlcG9zaXRvcnkgb24gZGVwbG95LXRpbWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250YWluZXJJbWFnZUJ1aWxkIGV4dGVuZHMgQ29uc3RydWN0IGltcGxlbWVudHMgSUdyYW50YWJsZSB7XG4gIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbDogSVByaW5jaXBhbDtcbiAgcHVibGljIHJlYWRvbmx5IHJlcG9zaXRvcnk6IElSZXBvc2l0b3J5O1xuICBwdWJsaWMgcmVhZG9ubHkgaW1hZ2VUYWc6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGltYWdlVXJpOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSBwcm9wczogQ29udGFpbmVySW1hZ2VCdWlsZFByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IGhhbmRsZXIgPSBuZXcgU2luZ2xldG9uRnVuY3Rpb24odGhpcywgJ0N1c3RvbVJlc291cmNlSGFuZGxlcicsIHtcbiAgICAgIC8vIFVzZSByYXcgc3RyaW5nIHRvIGF2b2lkIGZyb20gdGlnaHRlbmluZyBDREsgdmVyc2lvbiByZXF1aXJlbWVudFxuICAgICAgcnVudGltZTogbmV3IFJ1bnRpbWUoJ25vZGVqczIyLngnLCBSdW50aW1lRmFtaWx5Lk5PREVKUyksXG4gICAgICBjb2RlOiBDb2RlLmZyb21Bc3NldChqb2luKF9fZGlybmFtZSwgJy4uJywgJ2xhbWJkYScsICd0cmlnZ2VyLWNvZGVidWlsZCcsICdkaXN0JykpLFxuICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgdXVpZDogJ2RiNzQwZmQ1LTU0MzYtNGE4NC04YTA5LWU2ZGZjZDAxZjRmMycsIC8vIGdlbmVyYXRlZCBmb3IgdGhpcyBjb25zdHJ1Y3RcbiAgICAgIGxhbWJkYVB1cnBvc2U6ICdEZXBsb3lUaW1lQnVpbGRDdXN0b21SZXNvdXJjZUhhbmRsZXInLFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICB9KTtcblxuICAgIC8vIFVzZSBidWlsZHggZm9yIGNyb3NzLXBsYXRmb3JtIGltYWdlIGJ1aWxkXG4gICAgY29uc3QgYXJtSW1hZ2UgPSBMaW51eEFybUJ1aWxkSW1hZ2UuZnJvbUNvZGVCdWlsZEltYWdlSWQoJ2F3cy9jb2RlYnVpbGQvYW1hem9ubGludXgyLWFhcmNoNjQtc3RhbmRhcmQ6My4wJyk7XG4gICAgY29uc3QgeDY0SW1hZ2UgPSBMaW51eEJ1aWxkSW1hZ2UuZnJvbUNvZGVCdWlsZEltYWdlSWQoJ2F3cy9jb2RlYnVpbGQvc3RhbmRhcmQ6Ny4wJyk7XG4gICAgLy8gU2VsZWN0IHRoZSBidWlsZCBpbWFnZSBiYXNlZCBvbiB0aGUgdGFyZ2V0IHBsYXRmb3JtXG4gICAgY29uc3QgaXNBcm02NCA9IHByb3BzLnBsYXRmb3JtPy5wbGF0Zm9ybSA9PT0gJ2xpbnV4L2FybTY0JztcbiAgICBjb25zdCBidWlsZEltYWdlID0gaXNBcm02NCA/IGFybUltYWdlIDogeDY0SW1hZ2U7XG5cbiAgICBsZXQgcmVwb3NpdG9yeSA9IHByb3BzLnJlcG9zaXRvcnk7XG4gICAgaWYgKHJlcG9zaXRvcnkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVwb3NpdG9yeSA9IG5ldyBSZXBvc2l0b3J5KHRoaXMsICdSZXBvc2l0b3J5JywgeyByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1kgfSk7XG4gICAgICAocmVwb3NpdG9yeS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBDZm5SZXNvdXJjZSkuYWRkUHJvcGVydHlPdmVycmlkZSgnRW1wdHlPbkRlbGV0ZScsIHRydWUpO1xuICAgICAgKHJlcG9zaXRvcnkubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuUmVzb3VyY2UpLmFkZFByb3BlcnR5T3ZlcnJpZGUoJ0ltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uLlNjYW5PblB1c2gnLCB0cnVlKTtcbiAgICB9XG4gICAgY29uc3QgcmVwb3NpdG9yeVVyaSA9IHJlcG9zaXRvcnkucmVwb3NpdG9yeVVyaTtcbiAgICBjb25zdCBpbWFnZUFydGlmYWN0TmFtZSA9ICdhcnRpZmFjdDokaW1hZ2VUYWcnO1xuXG4gICAgY29uc3QgcHJvamVjdCA9IG5ldyBTaW5nbGV0b25Qcm9qZWN0KHRoaXMsICdQcm9qZWN0Jywge1xuICAgICAgdXVpZDogJ2U4MzcyOWZlLWIxNTYtNGU3MC05YmVjLTQ1MmIxNTg0N2EzMCcsXG4gICAgICBwcm9qZWN0UHVycG9zZTogaXNBcm02NCA/ICdDb250YWluZXJJbWFnZUJ1aWxkQXJtNjQnIDogJ0NvbnRhaW5lckltYWdlQnVpbGRBbWQ2NCcsXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBjb21wdXRlVHlwZTogQ29tcHV0ZVR5cGUuU01BTEwsXG4gICAgICAgIGJ1aWxkSW1hZ2U6IGJ1aWxkSW1hZ2UsXG4gICAgICAgIHByaXZpbGVnZWQ6IHRydWUsXG4gICAgICB9LFxuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICBidWlsZFNwZWM6IEJ1aWxkU3BlYy5mcm9tT2JqZWN0KHtcbiAgICAgICAgdmVyc2lvbjogJzAuMicsXG4gICAgICAgIHBoYXNlczoge1xuICAgICAgICAgIGJ1aWxkOiB7XG4gICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAnY3VycmVudF9kaXI9JChwd2QpJyxcbiAgICAgICAgICAgICAgJ2VjaG8gXCIkaW5wdXRcIicsXG4gICAgICAgICAgICAgICdta2RpciB3b3JrZGlyJyxcbiAgICAgICAgICAgICAgJ2NkIHdvcmtkaXInLFxuICAgICAgICAgICAgICAnYXdzIHMzIGNwIFwiJHNvdXJjZVMzVXJsXCIgdGVtcC56aXAnLFxuICAgICAgICAgICAgICAndW56aXAgdGVtcC56aXAnLFxuICAgICAgICAgICAgICAnbHMgLWxhJyxcbiAgICAgICAgICAgICAgJ2F3cyBlY3IgZ2V0LWxvZ2luLXBhc3N3b3JkIC0tcmVnaW9uICRyZXBvc2l0b3J5UmVnaW9uIHwgZG9ja2VyIGxvZ2luIC0tdXNlcm5hbWUgQVdTIC0tcGFzc3dvcmQtc3RkaW4gJHJlcG9zaXRvcnlBdXRoVXJpJyxcbiAgICAgICAgICAgICAgLy8gZm9yIGFjY2Vzc2luZyBFQ1IgcHVibGljXG4gICAgICAgICAgICAgICdhd3MgZWNyLXB1YmxpYyBnZXQtbG9naW4tcGFzc3dvcmQgLS1yZWdpb24gdXMtZWFzdC0xIHwgZG9ja2VyIGxvZ2luIC0tdXNlcm5hbWUgQVdTIC0tcGFzc3dvcmQtc3RkaW4gcHVibGljLmVjci5hd3MnLFxuICAgICAgICAgICAgICAnZG9ja2VyIGJ1aWxkeCBscycsXG4gICAgICAgICAgICAgICdlY2hvIFwiJGJ1aWxkQ29tbWFuZFwiJyxcbiAgICAgICAgICAgICAgJ2V2YWwgXCIkYnVpbGRDb21tYW5kXCInLFxuICAgICAgICAgICAgICAnZG9ja2VyIGltYWdlcycsXG4gICAgICAgICAgICAgIGBkb2NrZXIgdGFnICR7aW1hZ2VBcnRpZmFjdE5hbWV9ICRyZXBvc2l0b3J5VXJpOiRpbWFnZVRhZ2AsXG4gICAgICAgICAgICAgIGBkb2NrZXIgcHVzaCAkcmVwb3NpdG9yeVVyaTokaW1hZ2VUYWdgLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBvc3RfYnVpbGQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmRzOiBbXG4gICAgICAgICAgICAgICdlY2hvIEJ1aWxkIGNvbXBsZXRlZCBvbiBgZGF0ZWAnLFxuICAgICAgICAgICAgICBgXG5TVEFUVVM9J1NVQ0NFU1MnXG5pZiBbICRDT0RFQlVJTERfQlVJTERfU1VDQ0VFRElORyAtbmUgMSBdICMgVGVzdCBpZiB0aGUgYnVpbGQgaXMgZmFpbGluZ1xudGhlblxuU1RBVFVTPSdGQUlMRUQnXG5SRUFTT049XCJDb250YWluZXJJbWFnZUJ1aWxkIGZhaWxlZC4gU2VlIENsb3VkV2F0Y2ggTG9nIHN0cmVhbSBmb3IgdGhlIGRldGFpbGVkIHJlYXNvbjogXG5odHRwczovLyRBV1NfUkVHSU9OLmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0kQVdTX1JFR0lPTiNsb2dzVjI6bG9nLWdyb3Vwcy9sb2ctZ3JvdXAvXFxcXCQyNTJGYXdzXFxcXCQyNTJGY29kZWJ1aWxkXFxcXCQyNTJGJHByb2plY3ROYW1lL2xvZy1ldmVudHMvJENPREVCVUlMRF9MT0dfUEFUSFwiXG5maVxuY2F0IDw8RU9GID4gcGF5bG9hZC5qc29uXG57XG4gIFwiU3RhY2tJZFwiOiBcIiRzdGFja0lkXCIsXG4gIFwiUmVxdWVzdElkXCI6IFwiJHJlcXVlc3RJZFwiLFxuICBcIkxvZ2ljYWxSZXNvdXJjZUlkXCI6XCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJQaHlzaWNhbFJlc291cmNlSWRcIjogXCIkaW1hZ2VUYWdcIixcbiAgXCJTdGF0dXNcIjogXCIkU1RBVFVTXCIsXG4gIFwiUmVhc29uXCI6IFwiJFJFQVNPTlwiLFxuICBcIkRhdGFcIjoge1xuICAgIFwiSW1hZ2VUYWdcIjogXCIkaW1hZ2VUYWdcIlxuICB9XG59XG5FT0ZcbmN1cmwgLWkgLVggUFVUIC1IICdDb250ZW50LVR5cGU6JyAtZCBcIkBwYXlsb2FkLmpzb25cIiBcIiRyZXNwb25zZVVSTFwiXG4gICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICB9KS5wcm9qZWN0O1xuXG4gICAgcHJvamVjdC5yb2xlIS5hZGRNYW5hZ2VkUG9saWN5KE1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FbGFzdGljQ29udGFpbmVyUmVnaXN0cnlQdWJsaWNSZWFkT25seScpKTtcbiAgICByZXBvc2l0b3J5LmdyYW50UHVsbFB1c2gocHJvamVjdCk7XG4gICAgcmVwb3NpdG9yeS5ncmFudChwcm9qZWN0LCAnZWNyOkRlc2NyaWJlSW1hZ2VzJyk7XG5cbiAgICBoYW5kbGVyLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbJ2NvZGVidWlsZDpTdGFydEJ1aWxkJ10sXG4gICAgICAgIHJlc291cmNlczogW3Byb2plY3QucHJvamVjdEFybl0sXG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gcHJvamVjdC5ncmFudFByaW5jaXBhbDtcblxuICAgIGxldCBhc3NldEV4Y2x1ZGUgPSBwcm9wcy5leGNsdWRlO1xuICAgIC8vIGF1dG9tYXRpY2FsbHkgcmVhZCAuZG9ja2VyaWdub3JlIGZvciBjb252ZW5pZW5jZVxuICAgIGlmIChhc3NldEV4Y2x1ZGUgPT09IHVuZGVmaW5lZCAmJiBleGlzdHNTeW5jKGpvaW4ocHJvcHMuZGlyZWN0b3J5LCAnLmRvY2tlcmlnbm9yZScpKSkge1xuICAgICAgYXNzZXRFeGNsdWRlID0gcmVhZEZpbGVTeW5jKGpvaW4ocHJvcHMuZGlyZWN0b3J5LCAnLmRvY2tlcmlnbm9yZScpKS50b1N0cmluZygpLnNwbGl0KCdcXG4nKTtcbiAgICB9XG4gICAgY29uc3QgYXNzZXQgPSBuZXcgQXNzZXQodGhpcywgJ1NvdXJjZScsIHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZXhjbHVkZTogYXNzZXRFeGNsdWRlLFxuICAgICAgcGF0aDogcHJvcHMuZGlyZWN0b3J5LFxuICAgIH0pO1xuICAgIGFzc2V0LmdyYW50UmVhZChwcm9qZWN0KTtcblxuICAgIGNvbnN0IGJ1aWxkQ29tbWFuZE9wdGlvbnMgPSB7IC4uLnByb3BzLCBwbGF0Zm9ybTogcHJvcHMucGxhdGZvcm0/LnBsYXRmb3JtIH0gYXMgYW55O1xuICAgIGJ1aWxkQ29tbWFuZE9wdGlvbnMub3V0cHV0cyA/Pz0gW107XG4gICAgLy8gd2UgZG9uJ3QgdXNlIHB1c2g9dHJ1ZSBoZXJlIGJlY2F1c2UgQ29kZUJ1aWxkIERvY2tlciBzZXJ2ZXIgZG9lcyBub3Qgc2VlbSB0byB3b3JrIHByb3Blcmx5IHdpdGggdGhlIGNvbmZpZ3VyYXRpb24uXG4gICAgYnVpbGRDb21tYW5kT3B0aW9ucy5vdXRwdXRzLnB1c2goJ3R5cGU9ZG9ja2VyJywgYG5hbWU9JHtpbWFnZUFydGlmYWN0TmFtZX1gKTtcbiAgICBpZiAocHJvcHMuenN0ZENvbXByZXNzaW9uKSB7XG4gICAgICAvLyB0byBlbmFibGUgenN0ZCBjb21wcmVzc2lvbiwgYnVpbGR4IGRpcmVjdGx5IHB1c2hlcyB0aGUgYXJ0aWZhY3QgaW1hZ2UgdG8gYSByZWdpc3RyeVxuICAgICAgLy8gaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9ibG9ncy9jb250YWluZXJzL3JlZHVjaW5nLWF3cy1mYXJnYXRlLXN0YXJ0dXAtdGltZXMtd2l0aC16c3RkLWNvbXByZXNzZWQtY29udGFpbmVyLWltYWdlcy9cbiAgICAgIGJ1aWxkQ29tbWFuZE9wdGlvbnMub3V0cHV0cy5wdXNoKCdvY2ktbWVkaWF0eXBlcz10cnVlJywgJ2NvbXByZXNzaW9uPXpzdGQnLCAnZm9yY2UtY29tcHJlc3Npb249dHJ1ZScsICdjb21wcmVzc2lvbi1sZXZlbD0zJyk7XG4gICAgfVxuICAgIGNvbnN0IGJ1aWxkQ29tbWFuZCA9IHRoaXMuZ2V0RG9ja2VyQnVpbGRDb21tYW5kKGJ1aWxkQ29tbWFuZE9wdGlvbnMpO1xuXG4gICAgY29uc3QgcHJvcGVydGllczogQ29udGFpbmVySW1hZ2VCdWlsZFJlc291cmNlUHJvcHMgPSB7XG4gICAgICB0eXBlOiAnQ29udGFpbmVySW1hZ2VCdWlsZCcsXG4gICAgICBidWlsZENvbW1hbmQ6IGJ1aWxkQ29tbWFuZCxcbiAgICAgIHJlcG9zaXRvcnlVcmksXG4gICAgICBpbWFnZVRhZzogcHJvcHMudGFnLFxuICAgICAgdGFnUHJlZml4OiBwcm9wcy50YWdQcmVmaXgsXG4gICAgICBjb2RlQnVpbGRQcm9qZWN0TmFtZTogcHJvamVjdC5wcm9qZWN0TmFtZSxcbiAgICAgIHNvdXJjZVMzVXJsOiBhc3NldC5zM09iamVjdFVybCxcbiAgICB9O1xuXG4gICAgY29uc3QgY3VzdG9tID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogaGFuZGxlci5mdW5jdGlvbkFybixcbiAgICAgIHJlc291cmNlVHlwZTogJ0N1c3RvbTo6Q0RLQ29udGFpbmVySW1hZ2VCdWlsZCcsXG4gICAgICBwcm9wZXJ0aWVzLFxuICAgIH0pO1xuICAgIGN1c3RvbS5ub2RlLmFkZERlcGVuZGVuY3kocHJvamVjdCk7XG5cbiAgICB0aGlzLnJlcG9zaXRvcnkgPSByZXBvc2l0b3J5O1xuICAgIHRoaXMuaW1hZ2VUYWcgPSBjdXN0b20uZ2V0QXR0U3RyaW5nKCdJbWFnZVRhZycpO1xuICAgIHRoaXMuaW1hZ2VVcmkgPSBgJHtyZXBvc2l0b3J5VXJpfToke3RoaXMuaW1hZ2VUYWd9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGluc3RhbmNlIG9mIHtAbGluayBEb2NrZXJJbWFnZUNvZGV9IGZvciBhIExhbWJkYSBmdW5jdGlvbiBpbWFnZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9uYWwgY29uZmlndXJhdGlvbiBmb3IgRG9ja2VyIGltYWdlIGNvZGUuXG4gICAqL1xuICBwdWJsaWMgdG9MYW1iZGFEb2NrZXJJbWFnZUNvZGUob3B0aW9ucz86IExhbWJkYURvY2tlckltYWdlT3B0aW9ucykge1xuICAgIGlmICh0aGlzLnByb3BzLnpzdGRDb21wcmVzc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgY2Fubm90IGVuYWJsZSB6c3RkQ29tcHJlc3Npb24gZm9yIGEgTGFtYmRhIGltYWdlLicpO1xuICAgIH1cbiAgICByZXR1cm4gRG9ja2VySW1hZ2VDb2RlLmZyb21FY3IodGhpcy5yZXBvc2l0b3J5LCB7XG4gICAgICB0YWdPckRpZ2VzdDogdGhpcy5pbWFnZVRhZyxcbiAgICAgIC4uLihvcHRpb25zICYmIHtcbiAgICAgICAgY21kOiBvcHRpb25zLmNtZCxcbiAgICAgICAgZW50cnlwb2ludDogb3B0aW9ucy5lbnRyeXBvaW50LFxuICAgICAgICB3b3JraW5nRGlyZWN0b3J5OiBvcHRpb25zLndvcmtpbmdEaXJlY3RvcnksXG4gICAgICB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGluc3RhbmNlIG9mIHtAbGluayBDb250YWluZXJJbWFnZX0gZm9yIGFuIEVDUyB0YXNrIGRlZmluaXRpb24uXG4gICAqL1xuICBwdWJsaWMgdG9FY3NEb2NrZXJJbWFnZUNvZGUoKSB7XG4gICAgcmV0dXJuIENvbnRhaW5lckltYWdlLmZyb21FY3JSZXBvc2l0b3J5KHRoaXMucmVwb3NpdG9yeSwgdGhpcy5pbWFnZVRhZyk7XG4gIH1cblxuICBwcml2YXRlIGdldERvY2tlckJ1aWxkQ29tbWFuZChvcHRpb25zOiBhbnkpIHtcbiAgICAvLyB0aGUgbWVtYmVycyBvZiBwcm9wcyBkaWZmZXJzIHdpdGggQ0RLIHZlcnNpb24uXG4gICAgLy8gQnkgcmVnYXJkaW5nIHByb3BzIGFzIGFueSwgd2UgY2FuIHVzZSBwcm9wcyB0aGF0IGFyZSBub3QgYXZhaWxhYmxlIGluIG9sZGVyIGNkayB2ZXJzaW9ucy5cblxuICAgIC8vIGxvZ2ljIGlzIGNvcGllZCBmcm9tIHBhY2thZ2VzL2Nkay1hc3NldHMvbGliL3ByaXZhdGUvZG9ja2VyLnRzXG4gICAgY29uc3QgY2FjaGVPcHRpb25Ub0ZsYWcgPSAob3B0aW9uOiBhbnkpOiBzdHJpbmcgPT4ge1xuICAgICAgbGV0IGZsYWcgPSBgdHlwZT0ke29wdGlvbi50eXBlfWA7XG4gICAgICBpZiAob3B0aW9uLnBhcmFtcykge1xuICAgICAgICBmbGFnICs9XG4gICAgICAgICAgJywnICtcbiAgICAgICAgICBPYmplY3QuZW50cmllcyhvcHRpb24ucGFyYW1zKVxuICAgICAgICAgICAgLm1hcCgoW2ssIHZdKSA9PiBgJHtrfT0ke3Z9YClcbiAgICAgICAgICAgIC5qb2luKCcsJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmxhZztcbiAgICB9O1xuICAgIGNvbnN0IGZsYXR0ZW4gPSAoeDogc3RyaW5nW11bXSkgPT4ge1xuICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQoW10sIC4uLngpO1xuICAgIH07XG5cbiAgICBjb25zdCBkb2NrZXJCdWlsZENvbW1hbmQgPSBbXG4gICAgICAnZG9ja2VyIGJ1aWxkeCBidWlsZCcsXG4gICAgICAuLi5mbGF0dGVuKE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuYnVpbGRBcmdzIHx8IHt9KS5tYXAoKFtrLCB2XSkgPT4gWyctLWJ1aWxkLWFyZycsIGAke2t9PSR7dn1gXSkpLFxuICAgICAgLi4uZmxhdHRlbihPYmplY3QuZW50cmllcyhvcHRpb25zLmJ1aWxkU2VjcmV0cyB8fCB7fSkubWFwKChbaywgdl0pID0+IFsnLS1zZWNyZXQnLCBgaWQ9JHtrfSwke3Z9YF0pKSxcbiAgICAgIC4uLihvcHRpb25zLmJ1aWxkU3NoID8gWyctLXNzaCcsIG9wdGlvbnMuYnVpbGRTc2hdIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMudGFyZ2V0ID8gWyctLXRhcmdldCcsIG9wdGlvbnMudGFyZ2V0XSA6IFtdKSxcbiAgICAgIC4uLihvcHRpb25zLmZpbGUgPyBbJy0tZmlsZScsIG9wdGlvbnMuZmlsZV0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy5uZXR3b3JrTW9kZSA/IFsnLS1uZXR3b3JrJywgb3B0aW9ucy5uZXR3b3JrTW9kZV0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy5wbGF0Zm9ybSA/IFsnLS1wbGF0Zm9ybScsIG9wdGlvbnMucGxhdGZvcm1dIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMub3V0cHV0cyA/IFsnLS1vdXRwdXQnLCBvcHRpb25zLm91dHB1dHMuam9pbignLCcpXSA6IFtdKSxcbiAgICAgIC4uLihvcHRpb25zLmNhY2hlRnJvbSA/IFsuLi5vcHRpb25zLmNhY2hlRnJvbS5tYXAoKGNhY2hlRnJvbTogYW55KSA9PiBbJy0tY2FjaGUtZnJvbScsIGNhY2hlT3B0aW9uVG9GbGFnKGNhY2hlRnJvbSldKS5mbGF0KCldIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMuY2FjaGVUbyA/IFsnLS1jYWNoZS10bycsIGNhY2hlT3B0aW9uVG9GbGFnKG9wdGlvbnMuY2FjaGVUbyldIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMuY2FjaGVEaXNhYmxlZCA/IFsnLS1uby1jYWNoZSddIDogW10pLFxuICAgICAgJy0tcHJvdmVuYW5jZT1mYWxzZScsXG4gICAgICAnLicsXG4gICAgXTtcbiAgICByZXR1cm4gZG9ja2VyQnVpbGRDb21tYW5kLmpvaW4oJyAnKTtcbiAgfVxufVxuIl19