UNPKG

deploy-time-build

Version:
209 lines 32.9 kB
"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('nodejs20.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); } const repositoryUri = repository.repositoryUri; const imageArtifactName = 'artifact'; 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 | 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', 'eval "$buildCommand"', `docker tag ${imageArtifactName}:latest ${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 -v -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=image', `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'); } /** * Get the instance of {@link DockerImageCode} for a Lambda function image. */ toLambdaDockerImageCode() { 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 }); } /** * 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.3.37" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGFpbmVyLWltYWdlLWJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnRhaW5lci1pbWFnZS1idWlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJCQUE4QztBQUM5QywrQkFBNEI7QUFDNUIsNkNBQW1GO0FBQ25GLDZEQUF3RztBQUV4RyxpREFBOEQ7QUFFOUQsaURBQXFEO0FBQ3JELGlEQUE2RjtBQUM3Rix1REFBMEc7QUFDMUcsNkRBQWtEO0FBQ2xELDJDQUF1QztBQUN2QywyREFBdUQ7QUFzQ3ZEOztHQUVHO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxzQkFBUztJQUtoRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFtQixLQUErQjtRQUN4RixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRHdDLFVBQUssR0FBTCxLQUFLLENBQTBCO1FBR3hGLE1BQU0sT0FBTyxHQUFHLElBQUksOEJBQWlCLENBQUMsSUFBSSxFQUFFLHVCQUF1QixFQUFFO1lBQ25FLGtFQUFrRTtZQUNsRSxPQUFPLEVBQUUsSUFBSSxvQkFBTyxDQUFDLFlBQVksRUFBRSwwQkFBYSxDQUFDLE1BQU0sQ0FBQztZQUN4RCxJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQUMsSUFBQSxXQUFJLEVBQUMsU0FBUyxFQUFFLGtDQUFrQyxDQUFDLENBQUM7WUFDekUsT0FBTyxFQUFFLGVBQWU7WUFDeEIsSUFBSSxFQUFFLHNDQUFzQyxFQUFFLCtCQUErQjtZQUM3RSxhQUFhLEVBQUUsc0NBQXNDO1lBQ3JELE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsNENBQTRDO1FBQzVDLE1BQU0sUUFBUSxHQUFHLGtDQUFrQixDQUFDLG9CQUFvQixDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDNUcsTUFBTSxRQUFRLEdBQUcsK0JBQWUsQ0FBQyxvQkFBb0IsQ0FB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LENBQUMsRUFBRSxDQUFDO1lBQ2hELG9CQUFvQjtZQUNwQixHQUFHO1NBQ0osQ0FBQztRQUNGLE9BQU8sa0JBQWtCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7O0FBOU1ILGtEQStNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gJ2ZzJztcbmltcG9ydCB7IGpvaW4gfSBmcm9tICdwYXRoJztcbmltcG9ydCB7IENmblJlc291cmNlLCBDdXN0b21SZXNvdXJjZSwgRHVyYXRpb24sIFJlbW92YWxQb2xpY3kgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBCdWlsZFNwZWMsIENvbXB1dGVUeXBlLCBMaW51eEFybUJ1aWxkSW1hZ2UsIExpbnV4QnVpbGRJbWFnZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jb2RlYnVpbGQnO1xuaW1wb3J0IHsgSVZwYyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnksIFJlcG9zaXRvcnkgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyJztcbmltcG9ydCB7IERvY2tlckltYWdlQXNzZXRQcm9wcyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3ItYXNzZXRzJztcbmltcG9ydCB7IENvbnRhaW5lckltYWdlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcyc7XG5pbXBvcnQgeyBJR3JhbnRhYmxlLCBJUHJpbmNpcGFsLCBNYW5hZ2VkUG9saWN5LCBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IENvZGUsIERvY2tlckltYWdlQ29kZSwgUnVudGltZSwgUnVudGltZUZhbWlseSwgU2luZ2xldG9uRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IEFzc2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWFzc2V0cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFNpbmdsZXRvblByb2plY3QgfSBmcm9tICcuL3NpbmdsZXRvbi1wcm9qZWN0JztcbmltcG9ydCB7IENvbnRhaW5lckltYWdlQnVpbGRSZXNvdXJjZVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGFpbmVySW1hZ2VCdWlsZFByb3BzIGV4dGVuZHMgRG9ja2VySW1hZ2VBc3NldFByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSB0YWcgd2hlbiB0byBwdXNoIHRoZSBpbWFnZVxuICAgKiBAZGVmYXVsdCB1c2UgYXNzZXRIYXNoIGFzIHRhZ1xuICAgKi9cbiAgcmVhZG9ubHkgdGFnPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBQcmVmaXggdG8gYWRkIHRvIHRoZSBpbWFnZSB0YWdcbiAgICogQGRlZmF1bHQgbm8gcHJlZml4XG4gICAqL1xuICByZWFkb25seSB0YWdQcmVmaXg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBFQ1IgcmVwb3NpdG9yeSB0byBwdXNoIHRoZSBpbWFnZS5cbiAgICogQGRlZmF1bHQgY3JlYXRlIGEgbmV3IEVDUiByZXBvc2l0b3J5XG4gICAqL1xuICByZWFkb25seSByZXBvc2l0b3J5PzogSVJlcG9zaXRvcnk7XG5cbiAgLyoqXG4gICAqIFVzZSB6c3RkIGZvciBjb21wcmVzc2luZyBhIGNvbnRhaW5lciBpbWFnZS5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHpzdGRDb21wcmVzc2lvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBWUEMgd2hlcmUgeW91ciBidWlsZCBqb2Igd2lsbCBiZSBkZXBsb3llZC5cbiAgICogVGhpcyBWUEMgbXVzdCBoYXZlIHByaXZhdGUgc3VibmV0cyB3aXRoIE5BVCBHYXRld2F5cy5cbiAgICpcbiAgICogVXNlIHRoaXMgcHJvcGVydHkgd2hlbiB5b3Ugd2FudCB0byBjb250cm9sIHRoZSBvdXRib3VuZCBJUCBhZGRyZXNzZXMgdGhhdCBiYXNlIGltYWdlcyBhcmUgcHVsbGVkIGZyb20uXG4gICAqIEBkZWZhdWx0IE5vIFZQQyB1c2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogSVZwYztcbn1cblxuLyoqXG4gKiBCdWlsZCBhIGNvbnRhaW5lciBpbWFnZSBhbmQgcHVzaCBpdCB0byBhbiBFQ1IgcmVwb3NpdG9yeSBvbiBkZXBsb3ktdGltZS5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRhaW5lckltYWdlQnVpbGQgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJR3JhbnRhYmxlIHtcbiAgcHVibGljIHJlYWRvbmx5IGdyYW50UHJpbmNpcGFsOiBJUHJpbmNpcGFsO1xuICBwdWJsaWMgcmVhZG9ubHkgcmVwb3NpdG9yeTogSVJlcG9zaXRvcnk7XG4gIHB1YmxpYyByZWFkb25seSBpbWFnZVRhZzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IENvbnRhaW5lckltYWdlQnVpbGRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBoYW5kbGVyID0gbmV3IFNpbmdsZXRvbkZ1bmN0aW9uKHRoaXMsICdDdXN0b21SZXNvdXJjZUhhbmRsZXInLCB7XG4gICAgICAvLyBVc2UgcmF3IHN0cmluZyB0byBhdm9pZCBmcm9tIHRpZ2h0ZW5pbmcgQ0RLIHZlcnNpb24gcmVxdWlyZW1lbnRcbiAgICAgIHJ1bnRpbWU6IG5ldyBSdW50aW1lKCdub2RlanMyMC54JywgUnVudGltZUZhbWlseS5OT0RFSlMpLFxuICAgICAgY29kZTogQ29kZS5mcm9tQXNzZXQoam9pbihfX2Rpcm5hbWUsICcuLi9sYW1iZGEvdHJpZ2dlci1jb2RlYnVpbGQvZGlzdCcpKSxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIHV1aWQ6ICdkYjc0MGZkNS01NDM2LTRhODQtOGEwOS1lNmRmY2QwMWY0ZjMnLCAvLyBnZW5lcmF0ZWQgZm9yIHRoaXMgY29uc3RydWN0XG4gICAgICBsYW1iZGFQdXJwb3NlOiAnRGVwbG95VGltZUJ1aWxkQ3VzdG9tUmVzb3VyY2VIYW5kbGVyJyxcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgYnVpbGR4IGZvciBjcm9zcy1wbGF0Zm9ybSBpbWFnZSBidWlsZFxuICAgIGNvbnN0IGFybUltYWdlID0gTGludXhBcm1CdWlsZEltYWdlLmZyb21Db2RlQnVpbGRJbWFnZUlkKCdhd3MvY29kZWJ1aWxkL2FtYXpvbmxpbnV4Mi1hYXJjaDY0LXN0YW5kYXJkOjMuMCcpO1xuICAgIGNvbnN0IHg2NEltYWdlID0gTGludXhCdWlsZEltYWdlLmZyb21Db2RlQnVpbGRJbWFnZUlkKCdhd3MvY29kZWJ1aWxkL3N0YW5kYXJkOjcuMCcpO1xuICAgIC8vIFNlbGVjdCB0aGUgYnVpbGQgaW1hZ2UgYmFzZWQgb24gdGhlIHRhcmdldCBwbGF0Zm9ybVxuICAgIGNvbnN0IGlzQXJtNjQgPSBwcm9wcy5wbGF0Zm9ybT8ucGxhdGZvcm0gPT09ICdsaW51eC9hcm02NCc7XG4gICAgY29uc3QgYnVpbGRJbWFnZSA9IGlzQXJtNjQgPyBhcm1JbWFnZSA6IHg2NEltYWdlO1xuXG4gICAgbGV0IHJlcG9zaXRvcnkgPSBwcm9wcy5yZXBvc2l0b3J5O1xuICAgIGlmIChyZXBvc2l0b3J5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlcG9zaXRvcnkgPSBuZXcgUmVwb3NpdG9yeSh0aGlzLCAnUmVwb3NpdG9yeScsIHsgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZIH0pO1xuICAgICAgKHJlcG9zaXRvcnkubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuUmVzb3VyY2UpLmFkZFByb3BlcnR5T3ZlcnJpZGUoJ0VtcHR5T25EZWxldGUnLCB0cnVlKTtcbiAgICB9XG4gICAgY29uc3QgcmVwb3NpdG9yeVVyaSA9IHJlcG9zaXRvcnkucmVwb3NpdG9yeVVyaTtcbiAgICBjb25zdCBpbWFnZUFydGlmYWN0TmFtZSA9ICdhcnRpZmFjdCc7XG5cbiAgICBjb25zdCBwcm9qZWN0ID0gbmV3IFNpbmdsZXRvblByb2plY3QodGhpcywgJ1Byb2plY3QnLCB7XG4gICAgICB1dWlkOiAnZTgzNzI5ZmUtYjE1Ni00ZTcwLTliZWMtNDUyYjE1ODQ3YTMwJyxcbiAgICAgIHByb2plY3RQdXJwb3NlOiBpc0FybTY0ID8gJ0NvbnRhaW5lckltYWdlQnVpbGRBcm02NCcgOiAnQ29udGFpbmVySW1hZ2VCdWlsZEFtZDY0JyxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIGNvbXB1dGVUeXBlOiBDb21wdXRlVHlwZS5TTUFMTCxcbiAgICAgICAgYnVpbGRJbWFnZTogYnVpbGRJbWFnZSxcbiAgICAgICAgcHJpdmlsZWdlZDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgIGJ1aWxkU3BlYzogQnVpbGRTcGVjLmZyb21PYmplY3Qoe1xuICAgICAgICB2ZXJzaW9uOiAnMC4yJyxcbiAgICAgICAgcGhhc2VzOiB7XG4gICAgICAgICAgYnVpbGQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmRzOiBbXG4gICAgICAgICAgICAgICdjdXJyZW50X2Rpcj0kKHB3ZCknLFxuICAgICAgICAgICAgICAnZWNobyBcIiRpbnB1dFwiJyxcbiAgICAgICAgICAgICAgJ21rZGlyIHdvcmtkaXInLFxuICAgICAgICAgICAgICAnY2Qgd29ya2RpcicsXG4gICAgICAgICAgICAgICdhd3MgczMgY3AgXCIkc291cmNlUzNVcmxcIiB0ZW1wLnppcCcsXG4gICAgICAgICAgICAgICd1bnppcCB0ZW1wLnppcCcsXG4gICAgICAgICAgICAgICdscyAtbGEnLFxuICAgICAgICAgICAgICAnYXdzIGVjciBnZXQtbG9naW4tcGFzc3dvcmQgfCBkb2NrZXIgbG9naW4gLS11c2VybmFtZSBBV1MgLS1wYXNzd29yZC1zdGRpbiAkcmVwb3NpdG9yeUF1dGhVcmknLFxuICAgICAgICAgICAgICAvLyBmb3IgYWNjZXNzaW5nIEVDUiBwdWJsaWNcbiAgICAgICAgICAgICAgJ2F3cyBlY3ItcHVibGljIGdldC1sb2dpbi1wYXNzd29yZCAtLXJlZ2lvbiB1cy1lYXN0LTEgfCBkb2NrZXIgbG9naW4gLS11c2VybmFtZSBBV1MgLS1wYXNzd29yZC1zdGRpbiBwdWJsaWMuZWNyLmF3cycsXG4gICAgICAgICAgICAgICdkb2NrZXIgYnVpbGR4IGxzJyxcbiAgICAgICAgICAgICAgJ2V2YWwgXCIkYnVpbGRDb21tYW5kXCInLFxuICAgICAgICAgICAgICBgZG9ja2VyIHRhZyAke2ltYWdlQXJ0aWZhY3ROYW1lfTpsYXRlc3QgJHtyZXBvc2l0b3J5VXJpfTokaW1hZ2VUYWdgLFxuICAgICAgICAgICAgICBgZG9ja2VyIHB1c2ggJHtyZXBvc2l0b3J5VXJpfTokaW1hZ2VUYWdgLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBvc3RfYnVpbGQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmRzOiBbXG4gICAgICAgICAgICAgICdlY2hvIEJ1aWxkIGNvbXBsZXRlZCBvbiBgZGF0ZWAnLFxuICAgICAgICAgICAgICBgXG5TVEFUVVM9J1NVQ0NFU1MnXG5pZiBbICRDT0RFQlVJTERfQlVJTERfU1VDQ0VFRElORyAtbmUgMSBdICMgVGVzdCBpZiB0aGUgYnVpbGQgaXMgZmFpbGluZ1xudGhlblxuU1RBVFVTPSdGQUlMRUQnXG5SRUFTT049XCJDb250YWluZXJJbWFnZUJ1aWxkIGZhaWxlZC4gU2VlIENsb3VkV2F0Y2ggTG9nIHN0cmVhbSBmb3IgdGhlIGRldGFpbGVkIHJlYXNvbjogXG5odHRwczovLyRBV1NfUkVHSU9OLmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0kQVdTX1JFR0lPTiNsb2dzVjI6bG9nLWdyb3Vwcy9sb2ctZ3JvdXAvXFxcXCQyNTJGYXdzXFxcXCQyNTJGY29kZWJ1aWxkXFxcXCQyNTJGJHByb2plY3ROYW1lL2xvZy1ldmVudHMvJENPREVCVUlMRF9MT0dfUEFUSFwiXG5maVxuY2F0IDw8RU9GID4gcGF5bG9hZC5qc29uXG57XG4gIFwiU3RhY2tJZFwiOiBcIiRzdGFja0lkXCIsXG4gIFwiUmVxdWVzdElkXCI6IFwiJHJlcXVlc3RJZFwiLFxuICBcIkxvZ2ljYWxSZXNvdXJjZUlkXCI6XCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJQaHlzaWNhbFJlc291cmNlSWRcIjogXCIkaW1hZ2VUYWdcIixcbiAgXCJTdGF0dXNcIjogXCIkU1RBVFVTXCIsXG4gIFwiUmVhc29uXCI6IFwiJFJFQVNPTlwiLFxuICBcIkRhdGFcIjoge1xuICAgIFwiSW1hZ2VUYWdcIjogXCIkaW1hZ2VUYWdcIlxuICB9XG59XG5FT0ZcbmN1cmwgLXYgLWkgLVggUFVUIC1IICdDb250ZW50LVR5cGU6JyAtZCBcIkBwYXlsb2FkLmpzb25cIiBcIiRyZXNwb25zZVVSTFwiXG4gICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICB9KS5wcm9qZWN0O1xuXG4gICAgcHJvamVjdC5yb2xlIS5hZGRNYW5hZ2VkUG9saWN5KE1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FbGFzdGljQ29udGFpbmVyUmVnaXN0cnlQdWJsaWNSZWFkT25seScpKTtcbiAgICByZXBvc2l0b3J5LmdyYW50UHVsbFB1c2gocHJvamVjdCk7XG4gICAgcmVwb3NpdG9yeS5ncmFudChwcm9qZWN0LCAnZWNyOkRlc2NyaWJlSW1hZ2VzJyk7XG5cbiAgICBoYW5kbGVyLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbJ2NvZGVidWlsZDpTdGFydEJ1aWxkJ10sXG4gICAgICAgIHJlc291cmNlczogW3Byb2plY3QucHJvamVjdEFybl0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgdGhpcy5ncmFudFByaW5jaXBhbCA9IHByb2plY3QuZ3JhbnRQcmluY2lwYWw7XG5cbiAgICBsZXQgYXNzZXRFeGNsdWRlID0gcHJvcHMuZXhjbHVkZTtcbiAgICAvLyBhdXRvbWF0aWNhbGx5IHJlYWQgLmRvY2tlcmlnbm9yZSBmb3IgY29udmVuaWVuY2VcbiAgICBpZiAoYXNzZXRFeGNsdWRlID09PSB1bmRlZmluZWQgJiYgZXhpc3RzU3luYyhqb2luKHByb3BzLmRpcmVjdG9yeSwgJy5kb2NrZXJpZ25vcmUnKSkpIHtcbiAgICAgIGFzc2V0RXhjbHVkZSA9IHJlYWRGaWxlU3luYyhqb2luKHByb3BzLmRpcmVjdG9yeSwgJy5kb2NrZXJpZ25vcmUnKSkudG9TdHJpbmcoKS5zcGxpdCgnXFxuJyk7XG4gICAgfVxuICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KHRoaXMsICdTb3VyY2UnLCB7XG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGV4Y2x1ZGU6IGFzc2V0RXhjbHVkZSxcbiAgICAgIHBhdGg6IHByb3BzLmRpcmVjdG9yeSxcbiAgICB9KTtcbiAgICBhc3NldC5ncmFudFJlYWQocHJvamVjdCk7XG5cbiAgICBjb25zdCBidWlsZENvbW1hbmRPcHRpb25zID0geyAuLi5wcm9wcywgcGxhdGZvcm06IHByb3BzLnBsYXRmb3JtPy5wbGF0Zm9ybSB9IGFzIGFueTtcbiAgICBidWlsZENvbW1hbmRPcHRpb25zLm91dHB1dHMgPz89IFtdO1xuICAgIC8vIHdlIGRvbid0IHVzZSBwdXNoPXRydWUgaGVyZSBiZWNhdXNlIENvZGVCdWlsZCBEb2NrZXIgc2VydmVyIGRvZXMgbm90IHNlZW0gdG8gd29yayBwcm9wZXJseSB3aXRoIHRoZSBjb25maWd1cmF0aW9uLlxuICAgIGJ1aWxkQ29tbWFuZE9wdGlvbnMub3V0cHV0cy5wdXNoKCd0eXBlPWltYWdlJywgYG5hbWU9JHtpbWFnZUFydGlmYWN0TmFtZX1gKTtcbiAgICBpZiAocHJvcHMuenN0ZENvbXByZXNzaW9uKSB7XG4gICAgICAvLyB0byBlbmFibGUgenN0ZCBjb21wcmVzc2lvbiwgYnVpbGR4IGRpcmVjdGx5IHB1c2hlcyB0aGUgYXJ0aWZhY3QgaW1hZ2UgdG8gYSByZWdpc3RyeVxuICAgICAgLy8gaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9ibG9ncy9jb250YWluZXJzL3JlZHVjaW5nLWF3cy1mYXJnYXRlLXN0YXJ0dXAtdGltZXMtd2l0aC16c3RkLWNvbXByZXNzZWQtY29udGFpbmVyLWltYWdlcy9cbiAgICAgIGJ1aWxkQ29tbWFuZE9wdGlvbnMub3V0cHV0cy5wdXNoKCdvY2ktbWVkaWF0eXBlcz10cnVlJywgJ2NvbXByZXNzaW9uPXpzdGQnLCAnZm9yY2UtY29tcHJlc3Npb249dHJ1ZScsICdjb21wcmVzc2lvbi1sZXZlbD0zJyk7XG4gICAgfVxuICAgIGNvbnN0IGJ1aWxkQ29tbWFuZCA9IHRoaXMuZ2V0RG9ja2VyQnVpbGRDb21tYW5kKGJ1aWxkQ29tbWFuZE9wdGlvbnMpO1xuXG4gICAgY29uc3QgcHJvcGVydGllczogQ29udGFpbmVySW1hZ2VCdWlsZFJlc291cmNlUHJvcHMgPSB7XG4gICAgICB0eXBlOiAnQ29udGFpbmVySW1hZ2VCdWlsZCcsXG4gICAgICBidWlsZENvbW1hbmQ6IGJ1aWxkQ29tbWFuZCxcbiAgICAgIHJlcG9zaXRvcnlVcmksXG4gICAgICBpbWFnZVRhZzogcHJvcHMudGFnLFxuICAgICAgdGFnUHJlZml4OiBwcm9wcy50YWdQcmVmaXgsXG4gICAgICBjb2RlQnVpbGRQcm9qZWN0TmFtZTogcHJvamVjdC5wcm9qZWN0TmFtZSxcbiAgICAgIHNvdXJjZVMzVXJsOiBhc3NldC5zM09iamVjdFVybCxcbiAgICB9O1xuXG4gICAgY29uc3QgY3VzdG9tID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogaGFuZGxlci5mdW5jdGlvbkFybixcbiAgICAgIHJlc291cmNlVHlwZTogJ0N1c3RvbTo6Q0RLQ29udGFpbmVySW1hZ2VCdWlsZCcsXG4gICAgICBwcm9wZXJ0aWVzLFxuICAgIH0pO1xuICAgIGN1c3RvbS5ub2RlLmFkZERlcGVuZGVuY3kocHJvamVjdCk7XG5cbiAgICB0aGlzLnJlcG9zaXRvcnkgPSByZXBvc2l0b3J5O1xuICAgIHRoaXMuaW1hZ2VUYWcgPSBjdXN0b20uZ2V0QXR0U3RyaW5nKCdJbWFnZVRhZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgaW5zdGFuY2Ugb2Yge0BsaW5rIERvY2tlckltYWdlQ29kZX0gZm9yIGEgTGFtYmRhIGZ1bmN0aW9uIGltYWdlLlxuICAgKi9cbiAgcHVibGljIHRvTGFtYmRhRG9ja2VySW1hZ2VDb2RlKCkge1xuICAgIGlmICh0aGlzLnByb3BzLnpzdGRDb21wcmVzc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgY2Fubm90IGVuYWJsZSB6c3RkQ29tcHJlc3Npb24gZm9yIGEgTGFtYmRhIGltYWdlLicpO1xuICAgIH1cbiAgICByZXR1cm4gRG9ja2VySW1hZ2VDb2RlLmZyb21FY3IodGhpcy5yZXBvc2l0b3J5LCB7IHRhZ09yRGlnZXN0OiB0aGlzLmltYWdlVGFnIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgaW5zdGFuY2Ugb2Yge0BsaW5rIENvbnRhaW5lckltYWdlfSBmb3IgYW4gRUNTIHRhc2sgZGVmaW5pdGlvbi5cbiAgICovXG4gIHB1YmxpYyB0b0Vjc0RvY2tlckltYWdlQ29kZSgpIHtcbiAgICByZXR1cm4gQ29udGFpbmVySW1hZ2UuZnJvbUVjclJlcG9zaXRvcnkodGhpcy5yZXBvc2l0b3J5LCB0aGlzLmltYWdlVGFnKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RG9ja2VyQnVpbGRDb21tYW5kKG9wdGlvbnM6IGFueSkge1xuICAgIC8vIHRoZSBtZW1iZXJzIG9mIHByb3BzIGRpZmZlcnMgd2l0aCBDREsgdmVyc2lvbi5cbiAgICAvLyBCeSByZWdhcmRpbmcgcHJvcHMgYXMgYW55LCB3ZSBjYW4gdXNlIHByb3BzIHRoYXQgYXJlIG5vdCBhdmFpbGFibGUgaW4gb2xkZXIgY2RrIHZlcnNpb25zLlxuXG4gICAgLy8gbG9naWMgaXMgY29waWVkIGZyb20gcGFja2FnZXMvY2RrLWFzc2V0cy9saWIvcHJpdmF0ZS9kb2NrZXIudHNcbiAgICBjb25zdCBjYWNoZU9wdGlvblRvRmxhZyA9IChvcHRpb246IGFueSk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgZmxhZyA9IGB0eXBlPSR7b3B0aW9uLnR5cGV9YDtcbiAgICAgIGlmIChvcHRpb24ucGFyYW1zKSB7XG4gICAgICAgIGZsYWcgKz1cbiAgICAgICAgICAnLCcgK1xuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKG9wdGlvbi5wYXJhbXMpXG4gICAgICAgICAgICAubWFwKChbaywgdl0pID0+IGAke2t9PSR7dn1gKVxuICAgICAgICAgICAgLmpvaW4oJywnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmbGFnO1xuICAgIH07XG4gICAgY29uc3QgZmxhdHRlbiA9ICh4OiBzdHJpbmdbXVtdKSA9PiB7XG4gICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmNvbmNhdChbXSwgLi4ueCk7XG4gICAgfTtcblxuICAgIGNvbnN0IGRvY2tlckJ1aWxkQ29tbWFuZCA9IFtcbiAgICAgICdkb2NrZXIgYnVpbGR4IGJ1aWxkJyxcbiAgICAgIC4uLmZsYXR0ZW4oT2JqZWN0LmVudHJpZXMob3B0aW9ucy5idWlsZEFyZ3MgfHwge30pLm1hcCgoW2ssIHZdKSA9PiBbJy0tYnVpbGQtYXJnJywgYCR7a309JHt2fWBdKSksXG4gICAgICAuLi5mbGF0dGVuKE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuYnVpbGRTZWNyZXRzIHx8IHt9KS5tYXAoKFtrLCB2XSkgPT4gWyctLXNlY3JldCcsIGBpZD0ke2t9LCR7dn1gXSkpLFxuICAgICAgLi4uKG9wdGlvbnMuYnVpbGRTc2ggPyBbJy0tc3NoJywgb3B0aW9ucy5idWlsZFNzaF0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy50YXJnZXQgPyBbJy0tdGFyZ2V0Jywgb3B0aW9ucy50YXJnZXRdIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMuZmlsZSA/IFsnLS1maWxlJywgb3B0aW9ucy5maWxlXSA6IFtdKSxcbiAgICAgIC4uLihvcHRpb25zLm5ldHdvcmtNb2RlID8gWyctLW5ldHdvcmsnLCBvcHRpb25zLm5ldHdvcmtNb2RlXSA6IFtdKSxcbiAgICAgIC4uLihvcHRpb25zLnBsYXRmb3JtID8gWyctLXBsYXRmb3JtJywgb3B0aW9ucy5wbGF0Zm9ybV0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy5vdXRwdXRzID8gWyctLW91dHB1dCcsIG9wdGlvbnMub3V0cHV0cy5qb2luKCcsJyldIDogW10pLFxuICAgICAgLi4uKG9wdGlvbnMuY2FjaGVGcm9tID8gWy4uLm9wdGlvbnMuY2FjaGVGcm9tLm1hcCgoY2FjaGVGcm9tOiBhbnkpID0+IFsnLS1jYWNoZS1mcm9tJywgY2FjaGVPcHRpb25Ub0ZsYWcoY2FjaGVGcm9tKV0pLmZsYXQoKV0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy5jYWNoZVRvID8gWyctLWNhY2hlLXRvJywgY2FjaGVPcHRpb25Ub0ZsYWcob3B0aW9ucy5jYWNoZVRvKV0gOiBbXSksXG4gICAgICAuLi4ob3B0aW9ucy5jYWNoZURpc2FibGVkID8gWyctLW5vLWNhY2hlJ10gOiBbXSksXG4gICAgICAnLS1wcm92ZW5hbmNlPWZhbHNlJyxcbiAgICAgICcuJyxcbiAgICBdO1xuICAgIHJldHVybiBkb2NrZXJCdWlsZENvbW1hbmQuam9pbignICcpO1xuICB9XG59XG4iXX0=