aws-delivlib
Version:
A fabulous library for defining continuous pipelines for building, testing and releasing code libraries.
288 lines • 52.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WindowsPlatform = exports.LinuxPlatform = exports.ShellPlatform = exports.PlatformType = exports.Shellable = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const build_spec_1 = require("./build-spec");
const util_1 = require("./util");
const S3_BUCKET_ENV = 'SCRIPT_S3_BUCKET';
const S3_KEY_ENV = 'SCRIPT_S3_KEY';
/**
* A CodeBuild project that runs arbitrary scripts.
*
* The scripts to be run are specified by supplying a directory.
* All files in the directory are uploaded, then the script designated
* as the entry point is started.
*
* The script is executed in the directory where the build project's
* input is stored. The directory where the script files are stored
* is in the $SCRIPT_DIR environment variable.
*
* Supports both Windows and Linux computes.
*/
class Shellable extends constructs_1.Construct {
constructor(parent, id, props) {
super(parent, id);
this.props = props;
this.platform = props.platform || ShellPlatform.LinuxUbuntu;
const entrypoint = path.join(props.scriptDirectory, props.entrypoint);
if (!fs.existsSync(entrypoint)) {
throw new Error(`Cannot find test entrypoint: ${entrypoint}`);
}
const asset = new aws_cdk_lib_1.aws_s3_assets.Asset(this, 'ScriptDirectory', {
path: props.scriptDirectory,
exclude: props.excludeFilePatterns,
ignoreMode: aws_cdk_lib_1.IgnoreMode.GLOB,
});
this.outputArtifactName = (props.producesArtifacts ?? true) ? `Artifact_${this.node.addr}` : undefined;
if (this.outputArtifactName && this.outputArtifactName.length > 100) {
throw new Error(`Whoops, too long: ${this.outputArtifactName}`);
}
this.buildSpec = build_spec_1.BuildSpec.simple({
install: this.platform.installCommands(),
preBuild: this.platform.prebuildCommands(props.assumeRole, props.useRegionalStsEndpoints),
build: this.platform.buildCommands(props.entrypoint, props.args),
}).merge(props.buildSpec || build_spec_1.BuildSpec.empty());
const environmentSecretsAsSecretNames = this.convertEnvironmentSecretArnsToSecretNames(props.environmentSecrets);
this.project = new aws_cdk_lib_1.aws_codebuild.Project(this, 'Resource', {
projectName: props.buildProjectName,
description: props.description,
source: props.source,
role: props.serviceRole,
environment: {
buildImage: this.platform.buildImage,
computeType: props.computeType || aws_cdk_lib_1.aws_codebuild.ComputeType.MEDIUM,
privileged: props.privileged,
},
environmentVariables: {
[S3_BUCKET_ENV]: { value: asset.s3BucketName },
[S3_KEY_ENV]: { value: asset.s3ObjectKey },
...(0, util_1.renderEnvironmentVariables)(props.environment),
...(0, util_1.renderEnvironmentVariables)(environmentSecretsAsSecretNames, aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.SECRETS_MANAGER),
...(0, util_1.renderEnvironmentVariables)(props.environmentParameters, aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.PARAMETER_STORE),
},
timeout: props.timeout,
buildSpec: aws_cdk_lib_1.aws_codebuild.BuildSpec.fromObject(this.buildSpec.render({ primaryArtifactName: this.outputArtifactName })),
ssmSessionPermissions: true,
});
this.role = this.project.role; // not undefined, as it's a new Project
this.role.addManagedPolicy(aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly'));
asset.grantRead(this.role);
// Grant read access to secrets
Object.entries(props.environmentSecrets ?? {}).forEach(([name, secretArn]) => {
const secret = aws_cdk_lib_1.aws_secretsmanager.Secret.fromSecretCompleteArn(this, `${name}Secret`, secretArn);
secret.grantRead(this.role);
});
// Grant read access to parameters
Object.entries(props.environmentParameters ?? {}).forEach(([name, parameterName]) => {
const parameter = aws_cdk_lib_1.aws_ssm.StringParameter.fromStringParameterName(this, `${name}Parameter`, parameterName);
parameter.grantRead(this.role);
});
if (props.assumeRole) {
this.role.addToPrincipalPolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
actions: ['sts:AssumeRole'],
resources: [props.assumeRole.roleArn],
}));
}
this.alarm = new aws_cdk_lib_1.aws_cloudwatch.Alarm(this, 'Alarm', {
metric: this.project.metricFailedBuilds({ period: props.alarmPeriod || aws_cdk_lib_1.Duration.seconds(300) }),
threshold: props.alarmThreshold || 1,
comparisonOperator: aws_cdk_lib_1.aws_cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
evaluationPeriods: props.alarmEvaluationPeriods || 1,
treatMissingData: aws_cdk_lib_1.aws_cloudwatch.TreatMissingData.IGNORE,
});
}
addToPipeline(stage, name, inputArtifact, runOrder) {
const codeBuildAction = new aws_cdk_lib_1.aws_codepipeline_actions.CodeBuildAction({
actionName: name,
project: this.project,
runOrder,
input: inputArtifact,
variablesNamespace: this.props.actionNamespace,
environmentVariables: this.props.pipelineEnvironmentVars
? Object.fromEntries(Object.entries(this.props.pipelineEnvironmentVars)
.map(([k, v]) => [k, { type: aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.PLAINTEXT, value: v }]))
: undefined,
outputs: this.outputArtifactName
? [this.outputArtifactName, ...this.buildSpec.additionalArtifactNames ?? []].map(n => new aws_cdk_lib_1.aws_codepipeline.Artifact(n))
: undefined,
});
stage.addAction(codeBuildAction);
return codeBuildAction;
}
/**
* The contract of `environmentSecrets` is that the values are complete Secret ARNs;
* however, the CodeBuild construct expects secret names as the inputs for environment variables.
* This method converts the environment secrets from ARNs to names.
*/
convertEnvironmentSecretArnsToSecretNames(environmentSecrets) {
if (!environmentSecrets) {
return undefined;
}
const out = {};
Object.entries(environmentSecrets ?? {}).forEach(([name, secretArn]) => {
const secret = aws_cdk_lib_1.aws_secretsmanager.Secret.fromSecretCompleteArn(this, `${name}SecretFromArn`, secretArn);
out[name] = secret.secretName;
});
return out;
}
}
exports.Shellable = Shellable;
/**
* Platform archetype
*/
var PlatformType;
(function (PlatformType) {
PlatformType["Linux"] = "Linux";
PlatformType["Windows"] = "Windows";
})(PlatformType = exports.PlatformType || (exports.PlatformType = {}));
/**
* The platform type to run the scripts on
*/
class ShellPlatform {
/**
* Return a default Ubuntu Linux platform
*/
static get LinuxUbuntu() {
// Cannot be static member because of initialization order
return new LinuxPlatform(aws_cdk_lib_1.aws_codebuild.LinuxBuildImage.STANDARD_7_0);
}
/**
* Return a default Windows platform
*/
static get Windows() {
// Cannot be static member because of initialization order
return new WindowsPlatform(aws_cdk_lib_1.aws_codebuild.WindowsBuildImage.WIN_SERVER_CORE_2019_BASE);
}
constructor(buildImage) {
this.buildImage = buildImage;
}
}
exports.ShellPlatform = ShellPlatform;
/**
* A Linux Platform
*/
class LinuxPlatform extends ShellPlatform {
constructor() {
super(...arguments);
this.platformType = PlatformType.Linux;
}
installCommands() {
return [
'command -v yarn > /dev/null || npm install --global yarn',
];
}
prebuildCommands(assumeRole, useRegionalStsEndpoints) {
const lines = new Array();
// Better echo the location here; if this fails, the error message only contains
// the unexpanded variables by default. It might fail if you're running an old
// definition of the CodeBuild project--the permissions will have been changed
// to only allow downloading the very latest version.
lines.push(`echo "Downloading scripts from s3://\${${S3_BUCKET_ENV}}/\${${S3_KEY_ENV}}"`);
lines.push(`aws s3 cp s3://\${${S3_BUCKET_ENV}}/\${${S3_KEY_ENV}} /tmp`);
lines.push('mkdir -p /tmp/scriptdir');
lines.push(`unzip /tmp/$(basename \$${S3_KEY_ENV}) -d /tmp/scriptdir`);
if (assumeRole) {
if (assumeRole.refresh) {
const awsHome = '~/.aws';
const profileName = assumeRole.profileName ?? 'long-running-profile';
lines.push(`mkdir -p ${awsHome}`);
lines.push(`touch ${awsHome}/credentials`);
lines.push(`config=${awsHome}/config`);
lines.push(`echo [profile ${profileName}]>> $\{config\}`);
lines.push('echo credential_source = EcsContainer >> $\{config\}');
lines.push(`echo role_session_name = ${assumeRole.sessionName} >> $\{config\}`);
lines.push(`echo role_arn = ${assumeRole.roleArn} >> $config`);
if (assumeRole.externalId) {
lines.push(`echo external_id = ${assumeRole.externalId} >> $config`);
}
// let the application code know which role is being used.
lines.push(`export AWS_PROFILE=${profileName}`);
// force the AWS SDK for JavaScript to actually load the config file (do automatically so users don't forget)
lines.push('export AWS_SDK_LOAD_CONFIG=1');
}
else {
const externalId = assumeRole.externalId ? `--external-id "${assumeRole.externalId}"` : '';
const StsEndpoints = useRegionalStsEndpoints ? 'regional' : 'legacy';
lines.push('creds=$(mktemp -d)/creds.json');
lines.push(`AWS_STS_REGIONAL_ENDPOINTS=${StsEndpoints} aws sts assume-role --role-arn "${assumeRole.roleArn}" --role-session-name "${assumeRole.sessionName}" ${externalId} > $creds`);
lines.push('export AWS_ACCESS_KEY_ID="$(cat ${creds} | grep "AccessKeyId" | cut -d\'"\' -f 4)"');
lines.push('export AWS_SECRET_ACCESS_KEY="$(cat ${creds} | grep "SecretAccessKey" | cut -d\'"\' -f 4)"');
lines.push('export AWS_SESSION_TOKEN="$(cat ${creds} | grep "SessionToken" | cut -d\'"\' -f 4)"');
}
}
return lines;
}
buildCommands(entrypoint, args) {
return [
'export SCRIPT_DIR=/tmp/scriptdir',
`echo "Running ${entrypoint}"`,
`/bin/bash /tmp/scriptdir/${entrypoint} ${(args ?? []).join(' ')}`.trimRight(),
];
}
}
exports.LinuxPlatform = LinuxPlatform;
/**
* A Windows Platform
*/
class WindowsPlatform extends ShellPlatform {
constructor() {
super(...arguments);
this.platformType = PlatformType.Windows;
}
installCommands() {
return [
// Update the image's nodejs to the latest LTS release.
'Import-Module "C:\\ProgramData\\chocolatey\\helpers\\chocolateyProfile.psm1"',
'C:\\ProgramData\\chocolatey\\bin\\choco.exe upgrade nodejs-lts -y',
];
}
prebuildCommands(assumeRole, _useRegionalStsEndpoints) {
if (assumeRole) {
throw new Error('assumeRole is not supported on Windows: https://github.com/cdklabs/aws-delivlib/issues/57');
}
return [
// Would love to do downloading here and executing in the next step,
// but I don't know how to propagate the value of $TEMPDIR.
//
// Punting for someone who knows PowerShell well enough.
];
}
buildCommands(entrypoint, args) {
return [
'Set-Variable -Name TEMPDIR -Value (New-TemporaryFile).DirectoryName',
`aws s3 cp s3://$env:${S3_BUCKET_ENV}/$env:${S3_KEY_ENV} $TEMPDIR\\scripts.zip`,
'New-Item -ItemType Directory -Path $TEMPDIR\\scriptdir',
'Expand-Archive -Path $TEMPDIR/scripts.zip -DestinationPath $TEMPDIR\\scriptdir',
'$env:SCRIPT_DIR = "$TEMPDIR\\scriptdir"',
`& $TEMPDIR\\scriptdir\\${entrypoint} ${(args ?? []).join(' ')}`.trimRight(),
];
}
}
exports.WindowsPlatform = WindowsPlatform;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hlbGxhYmxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2hlbGxhYmxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUM3Qiw2Q0FLcUI7QUFFckIsMkNBQXVDO0FBQ3ZDLDZDQUF5QztBQUN6QyxpQ0FBb0Q7QUFFcEQsTUFBTSxhQUFhLEdBQUcsa0JBQWtCLENBQUM7QUFDekMsTUFBTSxVQUFVLEdBQUcsZUFBZSxDQUFDO0FBNlBuQzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxzQkFBUztJQWN0QyxZQUFZLE1BQWlCLEVBQUUsRUFBVSxFQUFtQixLQUFxQjtRQUMvRSxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRHdDLFVBQUssR0FBTCxLQUFLLENBQWdCO1FBRy9FLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsSUFBSSxhQUFhLENBQUMsV0FBVyxDQUFDO1FBRTVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsVUFBVSxFQUFFLENBQUMsQ0FBQztTQUMvRDtRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksMkJBQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ3RELElBQUksRUFBRSxLQUFLLENBQUMsZUFBZTtZQUMzQixPQUFPLEVBQUUsS0FBSyxDQUFDLG1CQUFtQjtZQUNsQyxVQUFVLEVBQUUsd0JBQVUsQ0FBQyxJQUFJO1NBQzVCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEtB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QXlDO1lBQ3pDLDBCQUEwQixVQUFVLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFO1NBQzdFLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUFsQ0QsMENBa0NDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7XG4gIER1cmF0aW9uLFxuICBhd3NfY2xvdWR3YXRjaCBhcyBjbG91ZHdhdGNoLCBhd3NfY29kZWJ1aWxkIGFzIGNidWlsZCxcbiAgYXdzX2NvZGVwaXBlbGluZSBhcyBjcGlwZWxpbmUsIGF3c19jb2RlcGlwZWxpbmVfYWN0aW9ucyBhcyBjcGlwZWxpbmVfYWN0aW9ucyxcbiAgYXdzX2lhbSBhcyBpYW0sIGF3c19zM19hc3NldHMgYXMgYXNzZXRzLCBhd3Nfc2VjcmV0c21hbmFnZXIsIGF3c19zc20sIElnbm9yZU1vZGUsXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IElSb2xlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEJ1aWxkU3BlYyB9IGZyb20gJy4vYnVpbGQtc3BlYyc7XG5pbXBvcnQgeyByZW5kZXJFbnZpcm9ubWVudFZhcmlhYmxlcyB9IGZyb20gJy4vdXRpbCc7XG5cbmNvbnN0IFMzX0JVQ0tFVF9FTlYgPSAnU0NSSVBUX1MzX0JVQ0tFVCc7XG5jb25zdCBTM19LRVlfRU5WID0gJ1NDUklQVF9TM19LRVknO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNoZWxsYWJsZU9wdGlvbnMge1xuICAvKipcbiAgICogRGVzY3JpcHRpb24gZm9yIHRoZSBDb2RlQnVpbGQgUHJvamVjdFxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNvdXJjZSBmb3IgdGhlIENvZGVCdWlsZCBwcm9qZWN0XG4gICAqXG4gICAqIEBkZWZhdWx0IG5vIHNvdXJjZVxuICAgKi9cbiAgc291cmNlPzogY2J1aWxkLklTb3VyY2U7XG5cbiAgLyoqXG4gICAqIFdoYXQgcGxhdGZvcm0gdG8gdXMgdG8gcnVuIHRoZSBzY3JpcHRzIG9uXG4gICAqXG4gICAqIEBkZWZhdWx0IFNoZWxsUGxhdGZvcm0uTGludXhVYnVudHVcbiAgICovXG4gIHBsYXRmb3JtPzogU2hlbGxQbGF0Zm9ybTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gc2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBObyBhZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgKi9cbiAgZW52aXJvbm1lbnQ/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9O1xuXG4gIC8qKlxuICAgKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgd2l0aCBzZWNyZXRzIG1hbmFnZXIgdmFsdWVzLiBUaGUgdmFsdWVzIG11c3QgYmUgY29tcGxldGUgU2VjcmV0IE1hbmFnZXIgQVJOcy5cbiAgICpcbiAgICogQGRlZmF1bHQgbm8gYWRkaXRpb25hbCBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICovXG4gIGVudmlyb25tZW50U2VjcmV0cz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIEVudmlyb25tZW50IHZhcmlhYmxlcyB3aXRoIFNTTSBwYXJhbWV0ZXIgdmFsdWVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBubyBhZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgKi9cbiAgZW52aXJvbm1lbnRQYXJhbWV0ZXJzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogVGhlIGNvbXB1dGUgdHlwZSB0byB1c2UgZm9yIHRoZSBidWlsZCBjb250YWluZXIuXG4gICAqXG4gICAqIE5vdGUgdGhhdCBub3QgYWxsIGNvbWJpbmF0aW9ucyBhcmUgYXZhaWxhYmxlLiBGb3IgZXhhbXBsZSxcbiAgICogV2luZG93cyBpbWFnZXMgY2Fubm90IGJlIHJ1biBvbiBDb21wdXRlVHlwZS5TbWFsbC5cbiAgICpcbiAgICogQGRlZmF1bHQgQ29tcHV0ZVR5cGUuTWVkaXVtXG4gICAqL1xuICBjb21wdXRlVHlwZT86IGNidWlsZC5Db21wdXRlVHlwZTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIGhvdyB0aGUgcHJvamVjdCBidWlsZHMgRG9ja2VyIGltYWdlcy4gU3BlY2lmeSB0cnVlIHRvIGVuYWJsZVxuICAgKiBydW5uaW5nIHRoZSBEb2NrZXIgZGFlbW9uIGluc2lkZSBhIERvY2tlciBjb250YWluZXIuIFRoaXMgdmFsdWUgbXVzdCBiZVxuICAgKiBzZXQgdG8gdHJ1ZSBvbmx5IGlmIHRoaXMgYnVpbGQgcHJvamVjdCB3aWxsIGJlIHVzZWQgdG8gYnVpbGQgRG9ja2VyXG4gICAqIGltYWdlcywgYW5kIHRoZSBzcGVjaWZpZWQgYnVpbGQgZW52aXJvbm1lbnQgaW1hZ2UgaXMgbm90IG9uZSBwcm92aWRlZCBieVxuICAgKiBBV1MgQ29kZUJ1aWxkIHdpdGggRG9ja2VyIHN1cHBvcnQuIE90aGVyd2lzZSwgYWxsIGFzc29jaWF0ZWQgYnVpbGRzIHRoYXRcbiAgICogYXR0ZW1wdCB0byBpbnRlcmFjdCB3aXRoIHRoZSBEb2NrZXIgZGFlbW9uIHdpbGwgZmFpbC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHByaXZpbGVnZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBmb3IgdGhlIGJ1aWxkIHByb2plY3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IGEgbmFtZSBpcyBnZW5lcmF0ZWQgYnkgQ2xvdWRGb3JtYXRpb24uXG4gICAqL1xuICBidWlsZFByb2plY3ROYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgUmVnaW9uYWwgQVdTIFNUUyBlbmRwb2ludHMgc2hvdWxkIGJlIHVzZWQgaW5zdGVhZFxuICAgKiBvZiB0aGUgZ2xvYmFsIGVuZHBvaW50LiBTcGVjaWZ5IHRydWUgdG8gdXNlIFJlZ2lvbmFsIEFXUyBTVFMgZW5kcG9pbnRzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgdXNlUmVnaW9uYWxTdHNFbmRwb2ludHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDYW4gYmUgdXNlZCB0byBydW4gdGhpcyBidWlsZCB1c2luZyBhIHNwZWNpZmljIElBTSByb2xlLiBUaGlzIGNhbiBiZSB1c2VkLFxuICAgKiBmb3IgZXhhbXBsZSwgdG8gZXhlY3V0ZSBpbiB0aGUgY29udGV4dCBvZiBhbm90aGVyIGFjY291bnQgKGUuZy4gdG8gcnVuXG4gICAqIHRlc3RzIGluIGlzb2xhdGlvbikuXG4gICAqL1xuICBhc3N1bWVSb2xlPzogQXNzdW1lUm9sZTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBidWlsZHNwZWMgKGZvciBhcnRpZmFjdHMgZXRjLilcbiAgICpcbiAgICogQGRlZmF1bHQgTm8gYWRkaXRpb25hbCBidWlsZHNwZWNcbiAgICovXG4gIGJ1aWxkU3BlYz86IEJ1aWxkU3BlYztcblxuICAvKipcbiAgICogVGhlIHRpbWVvdXQgb2YgdGhlIGJ1aWxkLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0aGUgQ29kZUJ1aWxkIGRlZmF1bHQgKDEgaG91cilcbiAgICovXG4gIHRpbWVvdXQ/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogQWxhcm0gcGVyaW9kLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzMDAgc2Vjb25kcyAoNSBtaW51dGVzKVxuICAgKi9cbiAgYWxhcm1QZXJpb2Q/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogQWxhcm0gdGhyZXNob2xkLlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICBhbGFybVRocmVzaG9sZD86IG51bWJlcjtcblxuICAvKipcbiAgICogQWxhcm0gZXZhbHVhdGlvbiBwZXJpb2RzLlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICBhbGFybUV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyO1xuXG4gIHNlY29uZGFyeUFydGlmYWN0TmFtZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQ2xhcmlmeSB3aGV0aGVyIHRoaXMgU2hlbGxhYmxlIHByb2R1Y2VzIGFueSBhcnRpZmFjdHNcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZHVjZXNBcnRpZmFjdHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBOYW1lc3BhY2UgdG8gdXNlIHdoZW4gYWRkaW5nIGFzIGFuIGFjdGlvbiB0byB0aGUgcGlwZWxpbmVcbiAgICpcbiAgICogQGRlZmF1bHQgTm8gbmFtZXNwYWNlXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25OYW1lc3BhY2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHNldCBmcm9tIHRoZSBwaXBlbGluZSBhY3Rpb25cbiAgICpcbiAgICogQGRlZmF1bHQgTm8gZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAqL1xuICByZWFkb25seSBwaXBlbGluZUVudmlyb25tZW50VmFycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgLyoqXG4gICAqIFRoZSBzZXJ2aWNlIHJvbGUgdG8gYXNzdW1lIHdoaWxlIHJ1bm5pbmcgdGhlIGJ1aWxkXG4gICAqXG4gICAqIEBkZWZhdWx0IEEgcm9sZSB3aWxsIGJlIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VSb2xlPzogSVJvbGU7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyB1c2VkIHRvIGNyZWF0ZSBhIFNoZWxsYWJsZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoZWxsYWJsZVByb3BzIGV4dGVuZHMgU2hlbGxhYmxlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBEaXJlY3Rvcnkgd2l0aCB0aGUgc2NyaXB0cy5cbiAgICpcbiAgICogQnkgZGVmYXVsdCB0aGUgd2hvbGUgZGlyZWN0b3J5IHdpbGwgYmUgdXBsb2FkZWQuIFVzZSBgZXhjbHVkZUZpbGVQYXR0ZXJuc2AgdG8gaWdub3JlIGZpbGVzLlxuICAgKi9cbiAgc2NyaXB0RGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEZpbGUgcGF0aHMgbWF0Y2hpbmcgdGhlIGdsb2IgcGF0dGVybnMgd2lsbCBiZSBleGNsdWRlZCBmcm9tIHRoZSBzY3JpcHQgZGlyLlxuICAgKi9cbiAgZXhjbHVkZUZpbGVQYXR0ZXJucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBGaWxlbmFtZSBvZiB0aGUgaW5pdGlhbCBzY3JpcHQgdG8gc3RhcnQsIHJlbGF0aXZlIHRvIHNjcmlwdERpcmVjdG9yeS5cbiAgICovXG4gIGVudHJ5cG9pbnQ6IHN0cmluZztcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgZW50cnlwb2ludCBzY3JpcHQuXG4gICAqXG4gICAqIChOT1RFOiBub3QgbmFtZWQgJ2FyZ3VtZW50cycgYmVjYXVzZSB0aGF0J3MgYSByZXNlcnZlZCBpZGVudGlmaWVyIGluIEphdmFTY3JpcHQpXG4gICAqXG4gICAqIEBkZWZhdWx0IE5vIGFyZ3VtZW50c1xuICAgKi9cbiAgcmVhZG9ubHkgYXJncz86IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFzc3VtZVJvbGUge1xuICAvKipcbiAgICogVGhlIEFtYXpvbiBSZXNvdXJjZSBOYW1lIChBUk4pIG9mIHRoZSByb2xlIHRvIGFzc3VtZS5cbiAgICovXG4gIHJvbGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQW4gaWRlbnRpZmllciBmb3IgdGhlIGFzc3VtZWQgcm9sZSBzZXNzaW9uLlxuICAgKlxuICAgKiBVc2UgIHRoZSAgcm9sZSAgc2Vzc2lvbiBuYW1lIHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGEgc2Vzc2lvbiB3aGVuIHRoZSBzYW1lXG4gICAqIHJvbGUgaXMgYXNzdW1lZCBieSBkaWZmZXJlbnQgcHJpbmNpcGFscyBvciBmb3IgZGlmZmVyZW50IHJlYXNvbnMuIEluXG4gICAqIGNyb3NzLWFjY291bnQgc2NlbmFyaW9zLCB0aGUgcm9sZSBzZXNzaW9uIG5hbWUgaXMgdmlzaWJsZSB0bywgYW5kIGNhbiBiZVxuICAgKiBsb2dnZWQgYnkgdGhlIGFjY291bnQgdGhhdCBvd25zIHRoZSByb2xlLiAgVGhlIHJvbGUgc2Vzc2lvbiBuYW1lIGlzIGFsc29cbiAgICogdXNlZCBpbiB0aGUgQVJOIG9mIHRoZSBhc3N1bWVkIHJvbGUgcHJpbmNpcGFsLiBUaGlzIG1lYW5zIHRoYXQgc3Vic2VxdWVudFxuICAgKiBjcm9zcy1hY2NvdW50IEFQSSByZXF1ZXN0cyB1c2luZyB0aGUgdGVtLSBwb3Jhcnkgc2VjdXJpdHkgY3JlZGVudGlhbHMgd2lsbFxuICAgKiBleHBvc2UgdGhlIHJvbGUgc2Vzc2lvbiBuYW1lIHRvIHRoZSBleHRlcm5hbCBhY2NvdW50IGluIHRoZWlyIENsb3VkVHJhaWxcbiAgICogbG9ncy5cbiAgICpcbiAgICogVGhlIHJlZ2V4IHVzZWQgdG8gdmFsaWRhdGUgdGhpcyBwYXJhbWV0ZXIgaXMgYSBzdHJpbmcgb2YgY2hhcmFjdGVyc1xuICAgKiBjb25zaXN0aW5nICBvZiB1cHBlci0gYW5kIGxvd2VyLWNhc2UgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMgd2l0aCBub1xuICAgKiBzcGFjZXMuIFlvdSBjYW4gYWxzbyBpbmNsdWRlIHVuZGVyc2NvcmVzIG9yIGFueSBvZiB0aGUgZm9sbG93aW5nXG4gICAqIGNoYXJhY3RlcnM6ID0sLkAtXG4gICAqL1xuICBzZXNzaW9uTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBICB1bmlxdWUgIGlkZW50aWZpZXIgIHRoYXQgIGlzICB1c2VkIGJ5IHRoaXJkIHBhcnRpZXMgd2hlbiBhc3N1bWluZyByb2xlc1xuICAgKiBpbiB0aGVpciBjdXN0b21lcnMnIGFjY291bnRzLiBGb3IgZWFjaCAgcm9sZSAgdGhhdCAgdGhlICB0aGlyZCBwYXJ0eSBjYW5cbiAgICogYXNzdW1lLCB0aGV5IHNob3VsZCBpbnN0cnVjdCB0aGVpciBjdXN0b21lcnMgdG8gZW5zdXJlIHRoZSByb2xlJ3MgdHJ1c3RcbiAgICogcG9saWN5IGNoZWNrcyBmb3IgdGhlIGV4dGVybmFsIElEIHRoYXQgdGhlIHRoaXJkICBwYXJ0eSBnZW5lcmF0ZWQuICBFYWNoXG4gICAqIHRpbWUgdGhlIHRoaXJkIHBhcnR5IGFzc3VtZXMgdGhlIHJvbGUsIHRoZXkgc2hvdWxkIHBhc3MgdGhlIGN1c3RvbWVyJ3NcbiAgICogZXh0ZXJuYWwgSUQuIFRoZSBleHRlcm5hbCBJRCBpcyB1c2VmdWwgaW4gIG9yZGVyIHRvICBoZWxwICB0aGlyZCAgcGFydGllc1xuICAgKiBiaW5kIGEgcm9sZSB0byB0aGUgY3VzdG9tZXIgd2hvIGNyZWF0ZWQgaXQuIEZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZVxuICAgKiBleHRlcm5hbCBJRCwgc2VlIEhvdyB0byBVc2UgYW4gRXh0ZXItIG5hbCAgSUQgIFdoZW4gR3JhbnRpbmcgQWNjZXNzIHRvIFlvdXJcbiAgICogQVdTIFJlc291cmNlcyB0byBhIFRoaXJkIFBhcnR5IGluIHRoZSBJQU0gVXNlciBHdWlkZSAuXG4gICAqXG4gICAqIFRoaXMgcGFyYW1ldGVyIG11c3QgYmUgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyBjb25zaXN0aW5nICBvZiB1cHBlci0gYW5kXG4gICAqIGxvd2VyLWNhc2UgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMgd2l0aCBubyBzcGFjZXMuIFlvdSBjYW4gYWxzbyBpbmNsdWRlXG4gICAqIHVuZGVyc2NvcmVzIG9yICBhbnkgIG9mICB0aGUgIGZvbGxvd2luZyBjaGFyYWN0ZXJzOiA9LC5AOi8tXG4gICAqL1xuICBleHRlcm5hbElkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIGEgcHJvZmllIG5hbWUgaXMgY29uZmlndXJlZCwgYW4gYXNzdW1lZCByb2xlIGNvbmZpZ3VyYXRpb24gd2lsbCBiZSBjcmVhdGVkXG4gICAqIGluIHRoZSBzaGFyZWQgYXdzIGNvbmZpZ3VyYXRpb24gZmlsZSAofi8uYXdzL2NvbmZpZykuIFRoaXMgaXMgaW4gY29udHJhcnkgb2Ygc2ltcGx5IGludm9raW5nXG4gICAqIGFuIGBzdHMgYXNzdW1lLXJvbGVgIGNvbW1hbmQgdGhhdCBjcmVhdGVzIGEgc2Vzc2lvbiB3aXRoIGEgZml4ZWQgZXhwaXJ5IGRhdGUuXG4gICAqXG4gICAqIFVzaW5nIGEgcHJvZmlsZSB3aWxsIGRlbGVnYXRlIGNyZWRlbnRpYWwgcmVmcmVzaGluZyB0byB0aGUgU0RLL0NMSS5cbiAgICogVGhpcyBpcyBuZWVkZWQgdG8gc3VwcG9ydCBsb25nIHJ1bm5pbmcgc2Vzc2lvbnMgdGhhdCBuZWVkcyBzZXNzaW9ucyB0aGF0IGFyZSBsb25nZXIgdGhhblxuICAgKiB0aGUgc2Vzc2lvbiBkdXJhdGlvbiB0aGF0IGNhbiBiZSBjb25maWd1cmVkIHdpdGggYSBgc3RzIGFzc3VtZS1yb2xlYC5cbiAgICpcbiAgICogVGhlIGFwcGxpY2F0aW9uIGNvZGUgd2lsbCBhY2Nlc3MgdG8gdGhpcyBwcm9maWxlIGluIHRoZSBgQVdTX1BST0ZJTEVgIGVudiB2YXJpYWJsZS5cbiAgICpcbiAgICogT25seSByZWxldmFudCBpZiBgcmVmcmVzaGAgaXMgc3BlY2lmaWVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jbGkvbGF0ZXN0L3VzZXJndWlkZS9jbGktY29uZmlndXJlLWZpbGVzLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgJ2xvbmctcnVubmluZy1wcm9maWxlJ1xuICAgKi9cbiAgcHJvZmlsZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhpcyBpZiB5b3UgaGF2ZSBhIGxvbmcgcnVubmluZyBleGVjdXRpb24gdGhhdCBuZWVkcyBsb25nIHJ1bm5pbmcgc2Vzc2lvbnMuXG4gICAqIFRoaXMgd2lsbCBjcmVhdGUgYSBwcm9maWxlIGFuZCB1c2UgaXQgdG8gZGVsZWdhdGUgY3JlZGVudGlhbCByZWZyZXNoaW5nIHRvIHRoZSBTREsvQ0xJXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWZyZXNoPzogYm9vbGVhbjtcblxufVxuXG4vKipcbiAqIEEgQ29kZUJ1aWxkIHByb2plY3QgdGhhdCBydW5zIGFyYml0cmFyeSBzY3JpcHRzLlxuICpcbiAqIFRoZSBzY3JpcHRzIHRvIGJlIHJ1biBhcmUgc3BlY2lmaWVkIGJ5IHN1cHBseWluZyBhIGRpcmVjdG9yeS5cbiAqIEFsbCBmaWxlcyBpbiB0aGUgZGlyZWN0b3J5IGFyZSB1cGxvYWRlZCwgdGhlbiB0aGUgc2NyaXB0IGRlc2lnbmF0ZWRcbiAqIGFzIHRoZSBlbnRyeSBwb2ludCBpcyBzdGFydGVkLlxuICpcbiAqIFRoZSBzY3JpcHQgaXMgZXhlY3V0ZWQgaW4gdGhlIGRpcmVjdG9yeSB3aGVyZSB0aGUgYnVpbGQgcHJvamVjdCdzXG4gKiBpbnB1dCBpcyBzdG9yZWQuIFRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIHNjcmlwdCBmaWxlcyBhcmUgc3RvcmVkXG4gKiBpcyBpbiB0aGUgJFNDUklQVF9ESVIgZW52aXJvbm1lbnQgdmFyaWFibGUuXG4gKlxuICogU3VwcG9ydHMgYm90aCBXaW5kb3dzIGFuZCBMaW51eCBjb21wdXRlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNoZWxsYWJsZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBwcm9qZWN0OiBjYnVpbGQuUHJvamVjdDtcbiAgcHVibGljIHJlYWRvbmx5IHJvbGU6IGlhbS5JUm9sZTtcblxuICAvKipcbiAgICogQ2xvdWRXYXRjaCBhbGFybSB0aGF0IHdpbGwgYmUgdHJpZ2dlcmVkIGlmIHRoaXMgYWN0aW9uIGZhaWxzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFsYXJtOiBjbG91ZHdhdGNoLkFsYXJtO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcGxhdGZvcm06IFNoZWxsUGxhdGZvcm07XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVpbGRTcGVjOiBCdWlsZFNwZWM7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBvdXRwdXRBcnRpZmFjdE5hbWU/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocGFyZW50OiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IFNoZWxsYWJsZVByb3BzKSB7XG4gICAgc3VwZXIocGFyZW50LCBpZCk7XG5cbiAgICB0aGlzLnBsYXRmb3JtID0gcHJvcHMucGxhdGZvcm0gfHwgU2hlbGxQbGF0Zm9ybS5MaW51eFVidW50dTtcblxuICAgIGNvbnN0IGVudHJ5cG9pbnQgPSBwYXRoLmpvaW4ocHJvcHMuc2NyaXB0RGlyZWN0b3J5LCBwcm9wcy5lbnRyeXBvaW50KTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZW50cnlwb2ludCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGZpbmQgdGVzdCBlbnRyeXBvaW50OiAke2VudHJ5cG9pbnR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgYXNzZXQgPSBuZXcgYXNzZXRzLkFzc2V0KHRoaXMsICdTY3JpcHREaXJlY3RvcnknLCB7XG4gICAgICBwYXRoOiBwcm9wcy5zY3JpcHREaXJlY3RvcnksXG4gICAgICBleGNsdWRlOiBwcm9wcy5leGNsdWRlRmlsZVBhdHRlcm5zLFxuICAgICAgaWdub3JlTW9kZTogSWdub3JlTW9kZS5HTE9CLFxuICAgIH0pO1xuXG4gICAgdGhpcy5vdXRwdXRBcnRpZmFjdE5hbWUgPSAocHJvcHMucHJvZHVjZXNBcnRpZmFjdHMgPz8gdHJ1ZSkgPyBgQXJ0aWZhY3RfJHt0aGlzLm5vZGUuYWRkcn1gIDogdW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLm91dHB1dEFydGlmYWN0TmFtZSAmJiB0aGlzLm91dHB1dEFydGlmYWN0TmFtZS5sZW5ndGggPiAxMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgV2hvb3BzLCB0b28gbG9uZzogJHt0aGlzLm91dHB1dEFydGlmYWN0TmFtZX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmJ1aWxkU3BlYyA9IEJ1aWxkU3BlYy5zaW1wbGUoe1xuICAgICAgaW5zdGFsbDogdGhpcy5wbGF0Zm9ybS5pbnN0YWxsQ29tbWFuZHMoKSxcbiAgICAgIHByZUJ1aWxkOiB0aGlzLnBsYXRmb3JtLnByZWJ1aWxkQ29tbWFuZHMocHJvcHMuYXNzdW1lUm9sZSwgcHJvcHMudXNlUmVnaW9uYWxTdHNFbmRwb2ludHMpLFxuICAgICAgYnVpbGQ6IHRoaXMucGxhdGZvcm0uYnVpbGRDb21tYW5kcyhwcm9wcy5lbnRyeXBvaW50LCBwcm9wcy5hcmdzKSxcbiAgICB9KS5tZXJnZShwcm9wcy5idWlsZFNwZWMgfHwgQnVpbGRTcGVjLmVtcHR5KCkpO1xuXG4gICAgY29uc3QgZW52aXJvbm1lbnRTZWNyZXRzQXNTZWNyZXROYW1lcyA9IHRoaXMuY29udmVydEVudmlyb25tZW50U2VjcmV0QXJuc1RvU2VjcmV0TmFtZXMocHJvcHMuZW52aXJvbm1lbnRTZWNyZXRzKTtcblxuICAgIHRoaXMucHJvamVjdCA9IG5ldyBjYnVpbGQuUHJvamVjdCh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBwcm9qZWN0TmFtZTogcHJvcHMuYnVpbGRQcm9qZWN0TmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbixcbiAgICAgIHNvdXJjZTogcHJvcHMuc291cmNlLFxuICAgICAgcm9sZTogcHJvcHMuc2VydmljZVJvbGUsXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBidWlsZEltYWdlOiB0aGlzLnBsYXRmb3JtLmJ1aWxkSW1hZ2UsXG4gICAgICAgIGNvbXB1dGVUeXBlOiBwcm9wcy5jb21wdXRlVHlwZSB8fCBjYnVpbGQuQ29tcHV0ZVR5cGUuTUVESVVNLFxuICAgICAgICBwcml2aWxlZ2VkOiBwcm9wcy5wcml2aWxlZ2VkLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50VmFyaWFibGVzOiB7XG4gICAgICAgIFtTM19CVUNLRVRfRU5WXTogeyB2YWx1ZTogYXNzZXQuczNCdWNrZXROYW1lIH0sXG4gICAgICAgIFtTM19LRVlfRU5WXTogeyB2YWx1ZTogYXNzZXQuczNPYmplY3RLZXkgfSxcbiAgICAgICAgLi4ucmVuZGVyRW52aXJvbm1lbnRWYXJpYWJsZXMocHJvcHMuZW52aXJvbm1lbnQpLFxuICAgICAgICAuLi5yZW5kZXJFbnZpcm9ubWVudFZhcmlhYmxlcyhlbnZpcm9ubWVudFNlY3JldHNBc1NlY3JldE5hbWVzLCBjYnVpbGQuQnVpbGRFbnZpcm9ubWVudFZhcmlhYmxlVHlwZS5TRUNSRVRTX01BTkFHRVIpLFxuICAgICAgICAuLi5yZW5kZXJFbnZpcm9ubWVudFZhcmlhYmxlcyhwcm9wcy5lbnZpcm9ubWVudFBhcmFtZXRlcnMsIGNidWlsZC5CdWlsZEVudmlyb25tZW50VmFyaWFibGVUeXBlLlBBUkFNRVRFUl9TVE9SRSksXG4gICAgICB9LFxuICAgICAgdGltZW91dDogcHJvcHMudGltZW91dCxcbiAgICAgIGJ1aWxkU3BlYzogY2J1aWxkLkJ1aWxkU3BlYy5mcm9tT2JqZWN0KHRoaXMuYnVpbGRTcGVjLnJlbmRlcih7IHByaW1hcnlBcnRpZmFjdE5hbWU6IHRoaXMub3V0cHV0QXJ0aWZhY3ROYW1lIH0pKSxcbiAgICAgIHNzbVNlc3Npb25QZXJtaXNzaW9uczogdHJ1ZSxcbiAgICB9KTtcblxuICAgIHRoaXMucm9sZSA9IHRoaXMucHJvamVjdC5yb2xlITsgLy8gbm90IHVuZGVmaW5lZCwgYXMgaXQncyBhIG5ldyBQcm9qZWN0XG4gICAgdGhpcy5yb2xlLmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FbGFzdGljQ29udGFpbmVyUmVnaXN0cnlQdWJsaWNSZWFkT25seScpKTtcbiAgICBhc3NldC5ncmFudFJlYWQodGhpcy5yb2xlKTtcblxuICAgIC8vIEdyYW50IHJlYWQgYWNjZXNzIHRvIHNlY3JldHNcbiAgICBPYmplY3QuZW50cmllcyhwcm9wcy5lbnZpcm9ubWVudFNlY3JldHMgPz8ge30pLmZvckVhY2goKFtuYW1lLCBzZWNyZXRBcm5dKSA9PiB7XG4gICAgICBjb25zdCBzZWNyZXQgPSBhd3Nfc2VjcmV0c21hbmFnZXIuU2VjcmV0LmZyb21TZWNyZXRDb21wbGV0ZUFybih0aGlzLCBgJHtuYW1lfVNlY3JldGAsIHNlY3JldEFybik7XG4gICAgICBzZWNyZXQuZ3JhbnRSZWFkKHRoaXMucm9sZSk7XG4gICAgfSk7XG5cbiAgICAvLyBHcmFudCByZWFkIGFjY2VzcyB0byBwYXJhbWV0ZXJzXG4gICAgT2JqZWN0LmVudHJpZXMocHJvcHMuZW52aXJvbm1lbnRQYXJhbWV0ZXJzID8/IHt9KS5mb3JFYWNoKChbbmFtZSwgcGFyYW1ldGVyTmFtZV0pID0+IHtcbiAgICAgIGNvbnN0IHBhcmFtZXRlciA9IGF3c19zc20uU3RyaW5nUGFyYW1ldGVyLmZyb21TdHJpbmdQYXJhbWV0ZXJOYW1lKHRoaXMsIGAke25hbWV9UGFyYW1ldGVyYCwgcGFyYW1ldGVyTmFtZSk7XG4gICAgICBwYXJhbWV0ZXIuZ3JhbnRSZWFkKHRoaXMucm9sZSk7XG4gICAgfSk7XG5cbiAgICBpZiAocHJvcHMuYXNzdW1lUm9sZSkge1xuICAgICAgdGhpcy5yb2xlLmFkZFRvUHJpbmNpcGFsUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogWydzdHM6QXNzdW1lUm9sZSddLFxuICAgICAgICByZXNvdXJjZXM6IFtwcm9wcy5hc3N1bWVSb2xlLnJvbGVBcm5dLFxuICAgICAgfSkpO1xuICAgIH1cblxuICAgIHRoaXMuYWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5BbGFybSh0aGlzLCAnQWxhcm0nLCB7XG4gICAgICBtZXRyaWM6IHRoaXMucHJvamVjdC5tZXRyaWNGYWlsZWRCdWlsZHMoeyBwZXJpb2Q6IHByb3BzLmFsYXJtUGVyaW9kIHx8IER1cmF0aW9uLnNlY29uZHMoMzAwKSB9KSxcbiAgICAgIHRocmVzaG9sZDogcHJvcHMuYWxhcm1UaHJlc2hvbGQgfHwgMSxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBwcm9wcy5hbGFybUV2YWx1YXRpb25QZXJpb2RzIHx8IDEsXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZFRvUGlwZWxpbmUoc3RhZ2U6IGNwaXBlbGluZS5JU3RhZ2UsIG5hbWU6IHN0cmluZywgaW5wdXRBcnRpZmFjdDogY3BpcGVsaW5lLkFydGlmYWN0LCBydW5PcmRlcj86IG51bWJlcik6XG4gIGNwaXBlbGluZV9hY3Rpb25zLkNvZGVCdWlsZEFjdGlvbiB7XG4gICAgY29uc3QgY29kZUJ1aWxkQWN0aW9uID0gbmV3IGNwaXBlbGluZV9hY3Rpb25zLkNvZGVCdWlsZEFjdGlvbih7XG4gICAgICBhY3Rpb25OYW1lOiBuYW1lLFxuICAgICAgcHJvamVjdDogdGhpcy5wcm9qZWN0LFxuICAgICAgcnVuT3JkZXIsXG4gICAgICBpbnB1dDogaW5wdXRBcnRpZmFjdCxcbiAgICAgIHZhcmlhYmxlc05hbWVzcGFjZTogdGhpcy5wcm9wcy5hY3Rpb25OYW1lc3BhY2UsXG4gICAgICBlbnZpcm9ubWVudFZhcmlhYmxlczogdGhpcy5wcm9wcy5waXBlbGluZUVudmlyb25tZW50VmFyc1xuICAgICAgICA/IE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyh0aGlzLnByb3BzLnBpcGVsaW5lRW52aXJvbm1lbnRWYXJzKVxuICAgICAgICAgIC5tYXAoKFtrLCB2XSkgPT4gKFtrLCB7IHR5cGU6IGNidWlsZC5CdWlsZEVudmlyb25tZW50VmFyaWFibGVUeXBlLlBMQUlOVEVYVCwgdmFsdWU6IHYgfV0gYXMgY29uc3QpKSlcbiAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBvdXRwdXRzOiB0aGlzLm91dHB1dEFydGlmYWN0TmFtZVxuICAgICAgICA/IFt0aGlzLm91dHB1dEFydGlmYWN0TmFtZSwgLi4udGhpcy5idWlsZFNwZWMuYWRkaXRpb25hbEFydGlmYWN0TmFtZXMgPz8gW11dLm1hcChuID0+IG5ldyBjcGlwZWxpbmUuQXJ0aWZhY3QobikpXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuICAgIHN0YWdlLmFkZEFjdGlvbihjb2RlQnVpbGRBY3Rpb24pO1xuICAgIHJldHVybiBjb2RlQnVpbGRBY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNvbnRyYWN0IG9mIGBlbnZpcm9ubWVudFNlY3JldHNgIGlzIHRoYXQgdGhlIHZhbHVlcyBhcmUgY29tcGxldGUgU2VjcmV0IEFSTnM7XG4gICAqIGhvd2V2ZXIsIHRoZSBDb2RlQnVpbGQgY29uc3RydWN0IGV4cGVjdHMgc2VjcmV0IG5hbWVzIGFzIHRoZSBpbnB1dHMgZm9yIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogVGhpcyBtZXRob2QgY29udmVydHMgdGhlIGVudmlyb25tZW50IHNlY3JldHMgZnJvbSBBUk5zIHRvIG5hbWVzLlxuICAgKi9cbiAgcHJpdmF0ZSBjb252ZXJ0RW52aXJvbm1lbnRTZWNyZXRBcm5zVG9TZWNyZXROYW1lcyhlbnZpcm9ubWVudFNlY3JldHM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gICAgaWYgKCFlbnZpcm9ubWVudFNlY3JldHMpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0geyB9O1xuICAgIE9iamVjdC5lbnRyaWVzKGVudmlyb25tZW50U2VjcmV0cyA/PyB7fSkuZm9yRWFjaCgoW25hbWUsIHNlY3JldEFybl0pID0+IHtcbiAgICAgIGNvbnN0IHNlY3JldCA9IGF3c19zZWNyZXRzbWFuYWdlci5TZWNyZXQuZnJvbVNlY3JldENvbXBsZXRlQXJuKHRoaXMsIGAke25hbWV9U2VjcmV0RnJvbUFybmAsIHNlY3JldEFybik7XG4gICAgICBvdXRbbmFtZV0gPSBzZWNyZXQuc2VjcmV0TmFtZTtcbiAgICB9KTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG59XG5cbi8qKlxuICogUGxhdGZvcm0gYXJjaGV0eXBlXG4gKi9cbmV4cG9ydCBlbnVtIFBsYXRmb3JtVHlwZSB7XG4gIExpbnV4ID0gJ0xpbnV4JyxcbiAgV2luZG93cyA9ICdXaW5kb3dzJyxcbn1cblxuLyoqXG4gKiBUaGUgcGxhdGZvcm0gdHlwZSB0byBydW4gdGhlIHNjcmlwdHMgb25cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFNoZWxsUGxhdGZvcm0ge1xuICAvKipcbiAgICogUmV0dXJuIGEgZGVmYXVsdCBVYnVudHUgTGludXggcGxhdGZvcm1cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ2V0IExpbnV4VWJ1bnR1KCk6IFNoZWxsUGxhdGZvcm0ge1xuICAgIC8vIENhbm5vdCBiZSBzdGF0aWMgbWVtYmVyIGJlY2F1c2Ugb2YgaW5pdGlhbGl6YXRpb24gb3JkZXJcbiAgICByZXR1cm4gbmV3IExpbnV4UGxhdGZvcm0oY2J1aWxkLkxpbnV4QnVpbGRJbWFnZS5TVEFOREFSRF83XzApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIGRlZmF1bHQgV2luZG93cyBwbGF0Zm9ybVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXQgV2luZG93cygpOiBTaGVsbFBsYXRmb3JtIHtcbiAgICAvLyBDYW5ub3QgYmUgc3RhdGljIG1lbWJlciBiZWNhdXNlIG9mIGluaXRpYWxpemF0aW9uIG9yZGVyXG4gICAgcmV0dXJuIG5ldyBXaW5kb3dzUGxhdGZvcm0oY2J1aWxkLldpbmRvd3NCdWlsZEltYWdlLldJTl9TRVJWRVJfQ09SRV8yMDE5X0JBU0UpO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IGJ1aWxkSW1hZ2U6IGNidWlsZC5JQnVpbGRJbWFnZSkge1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJuIGNvbW1hbmRzIHRvIHByZXBhcmUgdGhlIGhvc3QgZm9yIHRoZSBzaGVsbGFibGUuXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgaW5zdGFsbENvbW1hbmRzKCk6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gY29tbWFuZHMgdG8gZG93bmxvYWQgdGhlIHNjcmlwdCBidW5kbGVcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCBwcmVidWlsZENvbW1hbmRzKGFzc3VtZVJvbGU/OiBBc3N1bWVSb2xlLCB1c2VSZWdpb25hbFN0c0VuZHBvaW50cz86IGJvb2xlYW4pOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogUmV0dXJuIGNvbW1hbmRzIHRvIHN0YXJ0IHRoZSBlbnRyeXBvaW50IHNjcmlwdFxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGJ1aWxkQ29tbWFuZHMoZW50cnlwb2ludDogc3RyaW5nLCBhcmdzPzogc3RyaW5nW10pOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVHlwZSBvZiBwbGF0Zm9ybVxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGdldCBwbGF0Zm9ybVR5cGUoKTogUGxhdGZvcm1UeXBlO1xufVxuXG4vKipcbiAqIEEgTGludXggUGxhdGZvcm1cbiAqL1xuZXhwb3J0IGNsYXNzIExpbnV4UGxhdGZvcm0gZXh0ZW5kcyBTaGVsbFBsYXRmb3JtIHtcbiAgcHVibGljIHJlYWRvbmx5IHBsYXRmb3JtVHlwZSA9IFBsYXRmb3JtVHlwZS5MaW51eDtcblxuICBwdWJsaWMgaW5zdGFsbENvbW1hbmRzKCk6IHN0cmluZ1tdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gW1xuICAgICAgJ2NvbW1hbmQgLXYgeWFybiA+IC9kZXYvbnVsbCB8fCBucG0gaW5zdGFsbCAtLWdsb2JhbCB5YXJuJyxcbiAgICBdO1xuICB9XG5cbiAgcHVibGljIHByZWJ1aWxkQ29tbWFuZHMoYXNzdW1lUm9sZT86IEFzc3VtZVJvbGUsIHVzZVJlZ2lvbmFsU3RzRW5kcG9pbnRzPzogYm9vbGVhbik6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBsaW5lcyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgLy8gQmV0dGVyIGVjaG8gdGhlIGxvY2F0aW9uIGhlcmU7IGlmIHRoaXMgZmFpbHMsIHRoZSBlcnJvciBtZXNzYWdlIG9ubHkgY29udGFpbnNcbiAgICAvLyB0aGUgdW5leHBhbmRlZCB2YXJpYWJsZXMgYnkgZGVmYXVsdC4gSXQgbWlnaHQgZmFpbCBpZiB5b3UncmUgcnVubmluZyBhbiBvbGRcbiAgICAvLyBkZWZpbml0aW9uIG9mIHRoZSBDb2RlQnVpbGQgcHJvamVjdC0tdGhlIHBlcm1pc3Npb25zIHdpbGwgaGF2ZSBiZWVuIGNoYW5nZWRcbiAgICAvLyB0byBvbmx5IGFsbG93IGRvd25sb2FkaW5nIHRoZSB2ZXJ5IGxhdGVzdCB2ZXJzaW9uLlxuICAgIGxpbmVzLnB1c2goYGVjaG8gXCJEb3dubG9hZGluZyBzY3JpcHRzIGZyb20gczM6Ly9cXCR7JHtTM19CVUNLRVRfRU5WfX0vXFwkeyR7UzNfS0VZX0VOVn19XCJgKTtcbiAgICBsaW5lcy5wdXNoKGBhd3MgczMgY3AgczM6Ly9cXCR7JHtTM19CVUNLRVRfRU5WfX0vXFwkeyR7UzNfS0VZX0VOVn19IC90bXBgKTtcbiAgICBsaW5lcy5wdXNoKCdta2RpciAtcCAvdG1wL3NjcmlwdGRpcicpO1xuICAgIGxpbmVzLnB1c2goYHVuemlwIC90bXAvJChiYXNlbmFtZSBcXCQke1MzX0tFWV9FTlZ9KSAtZCAvdG1wL3NjcmlwdGRpcmApO1xuXG4gICAgaWYgKGFzc3VtZVJvbGUpIHtcblxuICAgICAgaWYgKGFzc3VtZVJvbGUucmVmcmVzaCkge1xuXG4gICAgICAgIGNvbnN0IGF3c0hvbWUgPSAnfi8uYXdzJztcblxuICAgICAgICBjb25zdCBwcm9maWxlTmFtZSA9IGFzc3VtZVJvbGUucHJvZmlsZU5hbWUgPz8gJ2xvbmctcnVubmluZy1wcm9maWxlJztcblxuICAgICAgICBsaW5lcy5wdXNoKGBta2RpciAtcCAke2F3c0hvbWV9YCk7XG4gICAgICAgIGxpbmVzLnB1c2goYHRvdWNoICR7YXdzSG9tZX0vY3JlZGVudGlhbHNgKTtcbiAgICAgICAgbGluZXMucHVzaChgY29uZmlnPSR7YXdzSG9tZX0vY29uZmlnYCk7XG4gICAgICAgIGxpbmVzLnB1c2goYGVjaG8gW3Byb2ZpbGUgJHtwcm9maWxlTmFtZX1dPj4gJFxce2NvbmZpZ1xcfWApO1xuICAgICAgICBsaW5lcy5wdXNoKCdlY2hvIGNyZWRlbnRpYWxfc291cmNlID0gRWNzQ29udGFpbmVyID4+ICRcXHtjb25maWdcXH0nKTtcbiAgICAgICAgbGluZXMucHVzaChgZWNobyByb2xlX3Nlc3Npb25fbmFtZSA9ICR7YXNzdW1lUm9sZS5zZXNzaW9uTmFtZX0gPj4gJFxce2NvbmZpZ1xcfWApO1xuICAgICAgICBsaW5lcy5wdXNoKGBlY2hvIHJvbGVfYXJuID0gJHthc3N1bWVSb2xlLnJvbGVBcm59ID4+ICRjb25maWdgKTtcblxuICAgICAgICBpZiAoYXNzdW1lUm9sZS5leHRlcm5hbElkKSB7XG4gICAgICAgICAgbGluZXMucHVzaChgZWNobyBleHRlcm5hbF9pZCA9ICR7YXNzdW1lUm9sZS5leHRlcm5hbElkfSA+PiAkY29uZmlnYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBsZXQgdGhlIGFwcGxpY2F0aW9uIGNvZGUga25vdyB3aGljaCByb2xlIGlzIGJlaW5nIHVzZWQuXG4gICAgICAgIGxpbmVzLnB1c2goYGV4cG9ydCBBV1NfUFJPRklMRT0ke3Byb2ZpbGVOYW1lfWApO1xuXG4gICAgICAgIC8vIGZvcmNlIHRoZSBBV1MgU0RLIGZvciBKYXZhU2NyaXB0IHRvIGFjdHVhbGx5IGxvYWQgdGhlIGNvbmZpZyBmaWxlIChkbyBhdXRvbWF0aWNhbGx5IHNvIHVzZXJzIGRvbid0IGZvcmdldClcbiAgICAgICAgbGluZXMucHVzaCgnZXhwb3J0IEFXU19TREtfTE9BRF9DT05GSUc9MScpO1xuXG4gICAgICB9IGVsc2Uge1xuXG4gICAgICAgIGNvbnN0IGV4dGVybmFsSWQgPSBhc3N1bWVSb2xlLmV4dGVybmFsSWQgPyBgLS1leHRlcm5hbC1pZCBcIiR7YXNzdW1lUm9sZS5leHRlcm5hbElkfVwiYCA6ICcnO1xuICAgICAgICBjb25zdCBTdHNFbmRwb2ludHMgPSB1c2VSZWdpb25hbFN0c0VuZHBvaW50cyA/ICdyZWdpb25hbCcgOiAnbGVnYWN5JztcblxuICAgICAgICBsaW5lcy5wdXNoKCdjcmVkcz0kKG1rdGVtcCAtZCkvY3JlZHMuanNvbicpO1xuICAgICAgICBsaW5lcy5wdXNoKGBBV1NfU1RTX1JFR0lPTkFMX0VORFBPSU5UUz0ke1N0c0VuZHBvaW50c30gYXdzIHN0cyBhc3N1bWUtcm9sZSAtLXJvbGUtYXJuIFwiJHthc3N1bWVSb2xlLnJvbGVBcm59XCIgLS1yb2xlLXNlc3Npb24tbmFtZSBcIiR7YXNzdW1lUm9sZS5zZXNzaW9uTmFtZX1cIiAke2V4dGVybmFsSWR9ID4gJGNyZWRzYCk7XG4gICAgICAgIGxpbmVzLnB1c2goJ2V4cG9ydCBBV1NfQUNDRVNTX0tFWV9JRD1cIiQoY2F0ICR7Y3JlZHN9IHwgZ3JlcCBcIkFjY2Vzc0tleUlkXCIgfCBjdXQgLWRcXCdcIlxcJyAtZiA0KVwiJyk7XG4gICAgICAgIGxpbmVzLnB1c2goJ2V4cG9ydCBBV1NfU0VDUkVUX0FDQ0VTU19LRVk9XCIkKGNhdCAke2NyZWRzfSB8IGdyZXAgXCJTZWNyZXRBY2Nlc3NLZXlcIiB8IGN1dCAtZFxcJ1wiXFwnIC1mIDQpXCInKTtcbiAgICAgICAgbGluZXMucHVzaCgnZXhwb3J0IEFXU19TRVNTSU9OX1RPS0VOPVwiJChjYXQgJHtjcmVkc30gfCBncmVwIFwiU2Vzc2lvblRva2VuXCIgfCBjdXQgLWRcXCdcIlxcJyAtZiA0KVwiJyk7XG4gICAgICB9XG4gIC