deploy-time-build
Version:
Build during CDK deployment.
221 lines (216 loc) • 29.7 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodejsBuild = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
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_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");
/**
* Build Node.js app and optionally publish the artifact to an S3 bucket.
*/
class NodejsBuild extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
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: '25648b21-2c40-4f09-aa65-b6bbb0c44659', // generated for this construct
lambdaPurpose: 'NodejsBuildCustomResourceHandler',
timeout: aws_cdk_lib_1.Duration.minutes(5),
});
const nodejsVersion = props.nodejsVersion ?? 18;
let buildImage = 'aws/codebuild/standard:7.0';
// See: https://docs.aws.amazon.com/codebuild/latest/userguide/available-runtimes.html#linux-runtimes
switch (nodejsVersion) {
case 12:
case 14:
buildImage = 'aws/codebuild/standard:5.0';
break;
case 16:
buildImage = 'aws/codebuild/standard:6.0';
break;
case 18:
case 20:
case 22:
buildImage = 'aws/codebuild/standard:7.0';
break;
default:
aws_cdk_lib_1.Annotations.of(this).addWarning(`Possibly unsupported Node.js version: ${nodejsVersion}. Currently 12, 14, 16, 18, 20, and 22 are supported.`);
}
const outputEnvFile = props.outputEnvFile ?? false;
const envFileKeyOutputKey = 'envFileKey';
const project = new aws_codebuild_1.Project(this, 'Project', {
environment: { buildImage: aws_codebuild_1.LinuxBuildImage.fromCodeBuildImageId(buildImage) },
buildSpec: aws_codebuild_1.BuildSpec.fromObject({
version: '0.2',
env: {
shell: 'bash',
},
phases: {
install: {
'runtime-versions': {
nodejs: nodejsVersion,
},
},
build: {
commands: [
'current_dir=$(pwd)',
// Iterate a json array using jq
// https://www.starkandwayne.com/blog/bash-for-loop-over-json-array-using-jq/index.html
`
echo "$input"
for obj in $(echo "$input" | jq -r '.[] | @base64'); do
decoded=$(echo "$obj" | base64 --decode)
assetUrl=$(echo "$decoded" | jq -r '.assetUrl')
extractPath=$(echo "$decoded" | jq -r '.extractPath')
commands=$(echo "$decoded" | jq -r '.commands')
# Download the zip file
aws s3 cp "$assetUrl" temp.zip
# Extract the zip file to the extractPath directory
mkdir -p "$extractPath"
unzip temp.zip -d "$extractPath"
# Remove the zip file
rm temp.zip
# Run the specified commands in the extractPath directory
cd "$extractPath"
ls -la
eval "$commands"
cd "$current_dir"
ls -la
done
`,
'ls -la',
'cd "$workingDirectory"',
'eval "$buildCommands"',
'ls -la',
'cd "$current_dir"',
'cd "$outputSourceDirectory"',
'aws s3 sync . "s3://$destinationBucketName/$destinationKeyPrefix" --delete',
// Invalidate CloudFront cache if distribution is specified
`
if [[ -n "$distributionId" ]]
then
INVALIDATION_OUTPUT=$(aws cloudfront create-invalidation --distribution-id "$distributionId" --paths "$distributionPath" --output json)
INVALIDATION_ID=$(echo "$INVALIDATION_OUTPUT" | jq -r '.Invalidation.Id')
aws cloudfront wait invalidation-completed --distribution-id "$distributionId" --id "$INVALIDATION_ID"
fi
`,
// Upload .env if required
`
if [[ $outputEnvFile == "true" ]]
then
# Split the comma-separated string into an array
for var_name in \${envNames//,/ }
do
echo "Element: $var_name"
var_value="\${!var_name}"
echo "$var_name=$var_value" >> tmp.env
done
aws s3 cp tmp.env "s3://$assetBucketName/$envFileKey"
fi
`,
],
},
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="NodejsBuild 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": "$logicalResourceId",
"Status": "$STATUS",
"Reason": "$REASON",
"Data": {
"${envFileKeyOutputKey}": "$envFileKey"
}
}
EOF
curl -i -X PUT -H 'Content-Type:' -d "@payload.json" "$responseURL"
`,
],
},
},
}),
});
handler.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['codebuild:StartBuild'],
resources: [project.projectArn],
}));
this.grantPrincipal = project.grantPrincipal;
props.destinationBucket.grantReadWrite(project);
if (props.distribution) {
project.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['cloudfront:GetInvalidation', 'cloudfront:CreateInvalidation'],
resources: [props.distribution.distributionArn],
}));
}
const commonExclude = ['.DS_Store', '.git', 'node_modules'];
const assets = props.assets.map((assetProps) => {
const asset = new aws_s3_assets_1.Asset(this, `Source-${assetProps.path.replace('/', '')}`, {
...assetProps,
...(props.excludeCommonFiles ?? true ? { exclude: [...commonExclude, ...(assetProps.exclude ?? [])] } : {}),
});
asset.grantRead(project);
return asset;
});
const bucket = assets[0].bucket;
if (outputEnvFile) {
// use the asset bucket that are created by CDK bootstrap to store .env file
bucket.grantWrite(project);
}
const sources = props.assets.map((s, i) => ({
sourceBucketName: assets[i].s3BucketName,
sourceObjectKey: assets[i].s3ObjectKey,
extractPath: s.extractPath ?? (0, path_1.basename)(s.path),
commands: s.commands,
}));
const workingDirectory = props.workingDirectory ?? sources[0].extractPath;
const properties = {
type: 'NodejsBuild',
sources,
destinationBucketName: props.destinationBucket.bucketName,
destinationKeyPrefix: props.destinationKeyPrefix ?? '/',
distributionId: props.distribution?.distributionId,
assetBucketName: bucket.bucketName,
workingDirectory,
// join paths for CodeBuild (Linux) platform
outputSourceDirectory: path_1.posix.join(workingDirectory, props.outputSourceDirectory),
environment: props.buildEnvironment,
buildCommands: props.buildCommands ?? ['npm run build'],
codeBuildProjectName: project.projectName,
outputEnvFile,
};
const custom = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
serviceToken: handler.functionArn,
resourceType: 'Custom::CDKNodejsBuild',
properties,
});
if (project.role) {
custom.node.addDependency(project.role);
}
if (props.outputEnvFile) {
new aws_cdk_lib_1.CfnOutput(this, 'DownloadEnvFile', { value: `aws s3 cp ${bucket.s3UrlForObject(custom.getAttString(envFileKeyOutputKey))} .env.local` });
}
}
}
exports.NodejsBuild = NodejsBuild;
_a = JSII_RTTI_SYMBOL_1;
NodejsBuild[_a] = { fqn: "deploy-time-build.NodejsBuild", version: "0.4.5" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25vZGVqcy1idWlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLCtCQUE2QztBQUM3Qyw2Q0FBK0U7QUFFL0UsNkRBQWdGO0FBQ2hGLGlEQUE4RTtBQUM5RSx1REFBeUY7QUFFekYsNkRBQThEO0FBQzlELDJDQUF1QztBQTRFdkM7O0dBRUc7QUFDSCxNQUFhLFdBQVksU0FBUSxzQkFBUztJQUd4QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXVCO1FBQy9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxPQUFPLEdBQUcsSUFBSSw4QkFBaUIsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7WUFDbkUsa0VBQWtFO1lBQ2xFLE9BQU8sRUFBRSxJQUFJLG9CQUFPLENBQUMsWUFBWSxFQUFFLDBCQUFhLENBQUMsTUFBTSxDQUFDO1lBQ3hELElBQUksRUFBRSxpQkFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsRixPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsc0NBQXNDLEVBQUUsK0JBQStCO1lBQzdFLGFBQWEsRUFBRSxrQ0FBa0M7WUFDakQsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztTQUM3QixDQUFDLENBQUM7UUFFSCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUNoRCxJQUFJLFVBQVUsR0FBRyw0QkFBNEIsQ0FBQztRQUM5QyxxR0FBcUc7UUFDckcsUUFBUSxhQUFhLEVBQUUsQ0FBQztZQUN0QixLQUFLLEVBQUUsQ0FBQztZQUNSLEtBQUssRUFBRTtnQkFDTCxVQUFVLEdBQUcsNEJBQTRCLENBQUM7Z0JBQzFDLE1BQU07WUFDUixLQUFLLEVBQUU7Z0JBQ0wsVUFBVSxHQUFHLDRCQUE0QixDQUFDO2dCQUMxQyxNQUFNO1lBQ1IsS0FBSyxFQUFFLENBQUM7WUFDUixLQUFLLEVBQUUsQ0FBQztZQUNSLEtBQUssRUFBRTtnQkFDTCxVQUFVLEdBQUcsNEJBQTRCLENBQUM7Z0JBQzFDLE1BQU07WUFDUjtnQkFDRSx5QkFBVyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMseUNBQXlDLGFBQWEsdURBQXVELENBQUMsQ0FBQztRQUNuSixDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUM7UUFDbkQsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLENBQUM7UUFFekMsTUFBTSxPQUFPLEdBQUcsSUFBSSx1QkFBTyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDM0MsV0FBVyxFQUFFLEVBQUUsVUFBVSxFQUFFLCtCQUFlLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDN0UsU0FBUyxFQUFFLHlCQUFTLENBQUMsVUFBVSxDQUFDO2dCQUM5QixPQUFPLEVBQUUsS0FBSztnQkFDZCxHQUFHLEVBQUU7b0JBQ0gsS0FBSyxFQUFFLE1BQU07aUJBQ2Q7Z0JBQ0QsTUFBTSxFQUFFO29CQUNOLE9BQU8sRUFBRTt3QkFDUCxrQkFBa0IsRUFBRTs0QkFDbEIsTUFBTSxFQUFFLGFBQWE7eUJBQ3RCO3FCQUNGO29CQUNELEtBQUssRUFBRTt3QkFDTCxRQUFRLEVBQUU7NEJBQ1Isb0JBQW9COzRCQUNwQixnQ0FBZ0M7NEJBQ2hDLHVGQUF1Rjs0QkFDdkY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUF5QkM7NEJBQ0QsUUFBUTs0QkFDUix3QkFBd0I7NEJBQ3hCLHVCQUF1Qjs0QkFDdkIsUUFBUTs0QkFDUixtQkFBbUI7NEJBQ25CLDZCQUE2Qjs0QkFDN0IsNEVBQTRFOzRCQUM1RSwyREFBMkQ7NEJBQzNEOzs7Ozs7O0NBT2I7NEJBQ2EsMEJBQTBCOzRCQUMxQjs7Ozs7Ozs7Ozs7OztlQWFDO3lCQUNGO3FCQUNGO29CQUNELFVBQVUsRUFBRTt3QkFDVixRQUFRLEVBQUU7NEJBQ1IsZ0NBQWdDOzRCQUNoQzs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FpQlAsbUJBQW1COzs7OztlQUtYO3lCQUNGO3FCQUNGO2lCQUNGO2FBQ0YsQ0FBQztTQUNILENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxlQUFlLENBQ3JCLElBQUkseUJBQWUsQ0FBQztZQUNsQixPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztZQUNqQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO1NBQ2hDLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO1FBRTdDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEQsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdkIsT0FBTyxDQUFDLGVBQWUsQ0FDckIsSUFBSSx5QkFBZSxDQUFDO2dCQUNsQixPQUFPLEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSwrQkFBK0IsQ0FBQztnQkFDeEUsU0FBUyxFQUFFLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUM7YUFDaEQsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQzVELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7WUFDN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxxQkFBSyxDQUFDLElBQUksRUFBRSxVQUFVLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMxRSxHQUFHLFVBQVU7Z0JBQ2IsR0FBRyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsR0FBRyxhQUFhLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDNUcsQ0FBQyxDQUFDO1lBQ0gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6QixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUNoQyxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLDRFQUE0RTtZQUM1RSxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBd0MsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9FLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZO1lBQ3hDLGVBQWUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVztZQUN0QyxXQUFXLEVBQUUsQ0FBQyxDQUFDLFdBQVcsSUFBSSxJQUFBLGVBQVEsRUFBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzlDLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtTQUNyQixDQUFDLENBQUMsQ0FBQztRQUVKLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7UUFDMUUsTUFBTSxVQUFVLEdBQTZCO1lBQzNDLElBQUksRUFBRSxhQUFhO1lBQ25CLE9BQU87WUFDUCxxQkFBcUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCLENBQUMsVUFBVTtZQUN6RCxvQkFBb0IsRUFBRSxLQUFLLENBQUMsb0JBQW9CLElBQUksR0FBRztZQUN2RCxjQUFjLEVBQUUsS0FBSyxDQUFDLFlBQVksRUFBRSxjQUFjO1lBQ2xELGVBQWUsRUFBRSxNQUFNLENBQUMsVUFBVTtZQUNsQyxnQkFBZ0I7WUFDaEIsNENBQTRDO1lBQzVDLHFCQUFxQixFQUFFLFlBQUssQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLHFCQUFxQixDQUFDO1lBQ2hGLFdBQVcsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO1lBQ25DLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQ3ZELG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ3pDLGFBQWE7U0FDZCxDQUFDO1FBRUYsTUFBTSxNQUFNLEdBQUcsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbEQsWUFBWSxFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ2pDLFlBQVksRUFBRSx3QkFBd0I7WUFDdEMsVUFBVTtTQUNYLENBQUMsQ0FBQztRQUNILElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDeEIsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEtBQUssRUFBRSxhQUFhLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7UUFDL0ksQ0FBQztJQUNILENBQUM7O0FBM05ILGtDQTROQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJhc2VuYW1lLCBqb2luLCBwb3NpeCB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQW5ub3RhdGlvbnMsIENmbk91dHB1dCwgQ3VzdG9tUmVzb3VyY2UsIER1cmF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSURpc3RyaWJ1dGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcbmltcG9ydCB7IEJ1aWxkU3BlYywgTGludXhCdWlsZEltYWdlLCBQcm9qZWN0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNvZGVidWlsZCc7XG5pbXBvcnQgeyBJR3JhbnRhYmxlLCBJUHJpbmNpcGFsLCBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IENvZGUsIFJ1bnRpbWUsIFJ1bnRpbWVGYW1pbHksIFNpbmdsZXRvbkZ1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBJQnVja2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IEFzc2V0LCBBc3NldFByb3BzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWFzc2V0cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE5vZGVqc0J1aWxkUmVzb3VyY2VQcm9wcyB9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFzc2V0Q29uZmlnIGV4dGVuZHMgQXNzZXRQcm9wcyB7XG4gIC8qKlxuICAgKiBTaGVsbCBjb21tYW5kcyBleGVjdXRlZCByaWdodCBhZnRlciB0aGUgYXNzZXQgemlwIGlzIGV4dHJhY3RlZCB0byB0aGUgYnVpbGQgZW52aXJvbm1lbnQuXG4gICAqIEBkZWZhdWx0IE5vIGNvbW1hbmQgaXMgZXhlY3V0ZWQuXG4gICAqL1xuICByZWFkb25seSBjb21tYW5kcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBSZWxhdGl2ZSBwYXRoIGZyb20gYSBidWlsZCBkaXJlY3RvcnkgdG8gdGhlIGRpcmVjdG9yeSB3aGVyZSB0aGUgYXNzZXQgaXMgZXh0cmFjdGVkLlxuICAgKiBAZGVmYXVsdCBiYXNlbmFtZSBvZiB0aGUgYXNzZXQgcGF0aC5cbiAgICovXG4gIHJlYWRvbmx5IGV4dHJhY3RQYXRoPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5vZGVqc0J1aWxkUHJvcHMge1xuICAvKipcbiAgICogVGhlIEFzc2V0UHJvcHMgZnJvbSB3aGljaCBzMy1hc3NldHMgYXJlIGNyZWF0ZWQgYW5kIGNvcGllZCB0byB0aGUgYnVpbGQgZW52aXJvbm1lbnQuXG4gICAqL1xuICByZWFkb25seSBhc3NldHM6IEFzc2V0Q29uZmlnW107XG4gIC8qKlxuICAgKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgaW5qZWN0ZWQgdG8gdGhlIGJ1aWxkIGVudmlyb25tZW50LlxuICAgKiBZb3UgY2FuIHVzZSBDREsgZGVwbG95LXRpbWUgdmFsdWVzIGFzIHdlbGwgYXMgbGl0ZXJhbHMuXG4gICAqIEBkZWZhdWx0IHt9XG4gICAqL1xuICByZWFkb25seSBidWlsZEVudmlyb25tZW50PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgLyoqXG4gICAqIFMzIEJ1Y2tldCB0byB3aGljaCB5b3VyIGJ1aWxkIGFydGlmYWN0cyBhcmUgZmluYWxseSBkZXBsb3llZC5cbiAgICovXG4gIHJlYWRvbmx5IGRlc3RpbmF0aW9uQnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogS2V5IHByZWZpeCB0byBkZXBsb3kgeW91ciBidWlsZCBhcnRpZmFjdC5cbiAgICogQGRlZmF1bHQgJy8nXG4gICAqL1xuICByZWFkb25seSBkZXN0aW5hdGlvbktleVByZWZpeD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBkaXN0cmlidXRpb24geW91IGFyZSB1c2luZyB0byBwdWJsaXNoIHlvdSBidWlsZCBhcnRpZmFjdC5cbiAgICogSWYgYW55IHNwZWNpZmllZCwgdGhlIGNhY2hlcyBhcmUgaW52YWxpZGF0ZWQgb24gbmV3IGFydGlmYWN0IGRlcGxveW1lbnRzLlxuICAgKiBAZGVmYXVsdCBObyBkaXN0cmlidXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbj86IElEaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBTaGVsbCBjb21tYW5kcyB0byBidWlsZCB5b3VyIHByb2plY3QuIFRoZXkgYXJlIGV4ZWN1dGVkIG9uIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB5b3Ugc3BlY2lmaWVkLlxuICAgKiBAZGVmYXVsdCBbJ25wbSBydW4gYnVpbGQnXVxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRDb21tYW5kcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogUmVsYXRpdmUgcGF0aCBmcm9tIHRoZSBidWlsZCBkaXJlY3RvcnkgdG8gdGhlIGRpcmVjdG9yeSB3aGVyZSBidWlsZCBjb21tYW5kcyBydW4uXG4gICAqIEBkZWZhdWx0IGFzc2V0UHJvcHNbMF0uZXh0cmFjdFBhdGhcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSZWxhdGl2ZSBwYXRoIGZyb20gdGhlIHdvcmtpbmcgZGlyZWN0b3J5IHRvIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIGJ1aWxkIGFydGlmYWN0cyBhcmUgb3V0cHV0LlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0U291cmNlRGlyZWN0b3J5OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdmVyc2lvbiBvZiBOb2RlLmpzIHRvIHVzZSBpbiBhIGJ1aWxkIGVudmlyb25tZW50LiBBdmFpbGFibGUgdmVyc2lvbnM6IDEyLCAxNCwgMTYsIDE4LCAyMCwgYW5kIDIyLlxuICAgKiBAZGVmYXVsdCAxOFxuICAgKi9cbiAgcmVhZG9ubHkgbm9kZWpzVmVyc2lvbj86IG51bWJlcjtcbiAgLyoqXG4gICAqIElmIHRydWUsIGEgLmVudiBmaWxlIGlzIHVwbG9hZGVkIHRvIGFuIFMzIGJ1Y2tldCB3aXRoIHZhbHVlcyBvZiBgYnVpbGRFbnZpcm9ubWVudGAgcHJvcGVydHkuXG4gICAqIFlvdSBjYW4gY29weSBpdCB0byB5b3VyIGxvY2FsIG1hY2hpbmUgYnkgcnVubmluZyB0aGUgY29tbWFuZCBpbiB0aGUgc3RhY2sgb3V0cHV0LlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0RW52RmlsZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZiB0cnVlLCBjb21tb24gdW5uZWNlc3NhcnkgZmlsZXMvZGlyZWN0b3JpZXMgc3VjaCBhcyAuRFNfU3RvcmUsIC5naXQsIG5vZGVfbW9kdWxlcywgZXRjIGFyZSBleGNsdWRlZFxuICAgKiBmcm9tIHRoZSBhc3NldHMgYnkgZGVmYXVsdC5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZUNvbW1vbkZpbGVzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBCdWlsZCBOb2RlLmpzIGFwcCBhbmQgb3B0aW9uYWxseSBwdWJsaXNoIHRoZSBhcnRpZmFjdCB0byBhbiBTMyBidWNrZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb2RlanNCdWlsZCBleHRlbmRzIENvbnN0cnVjdCBpbXBsZW1lbnRzIElHcmFudGFibGUge1xuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnRQcmluY2lwYWw6IElQcmluY2lwYWw7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5vZGVqc0J1aWxkUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBTaW5nbGV0b25GdW5jdGlvbih0aGlzLCAnQ3VzdG9tUmVzb3VyY2VIYW5kbGVyJywge1xuICAgICAgLy8gVXNlIHJhdyBzdHJpbmcgdG8gYXZvaWQgZnJvbSB0aWdodGVuaW5nIENESyB2ZXJzaW9uIHJlcXVpcmVtZW50XG4gICAgICBydW50aW1lOiBuZXcgUnVudGltZSgnbm9kZWpzMjIueCcsIFJ1bnRpbWVGYW1pbHkuTk9ERUpTKSxcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KGpvaW4oX19kaXJuYW1lLCAnLi4nLCAnbGFtYmRhJywgJ3RyaWdnZXItY29kZWJ1aWxkJywgJ2Rpc3QnKSksXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICB1dWlkOiAnMjU2NDhiMjEtMmM0MC00ZjA5LWFhNjUtYjZiYmIwYzQ0NjU5JywgLy8gZ2VuZXJhdGVkIGZvciB0aGlzIGNvbnN0cnVjdFxuICAgICAgbGFtYmRhUHVycG9zZTogJ05vZGVqc0J1aWxkQ3VzdG9tUmVzb3VyY2VIYW5kbGVyJyxcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBub2RlanNWZXJzaW9uID0gcHJvcHMubm9kZWpzVmVyc2lvbiA/PyAxODtcbiAgICBsZXQgYnVpbGRJbWFnZSA9ICdhd3MvY29kZWJ1aWxkL3N0YW5kYXJkOjcuMCc7XG4gICAgLy8gU2VlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY29kZWJ1aWxkL2xhdGVzdC91c2VyZ3VpZGUvYXZhaWxhYmxlLXJ1bnRpbWVzLmh0bWwjbGludXgtcnVudGltZXNcbiAgICBzd2l0Y2ggKG5vZGVqc1ZlcnNpb24pIHtcbiAgICAgIGNhc2UgMTI6XG4gICAgICBjYXNlIDE0OlxuICAgICAgICBidWlsZEltYWdlID0gJ2F3cy9jb2RlYnVpbGQvc3RhbmRhcmQ6NS4wJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE2OlxuICAgICAgICBidWlsZEltYWdlID0gJ2F3cy9jb2RlYnVpbGQvc3RhbmRhcmQ6Ni4wJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE4OlxuICAgICAgY2FzZSAyMDpcbiAgICAgIGNhc2UgMjI6XG4gICAgICAgIGJ1aWxkSW1hZ2UgPSAnYXdzL2NvZGVidWlsZC9zdGFuZGFyZDo3LjAnO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmcoYFBvc3NpYmx5IHVuc3VwcG9ydGVkIE5vZGUuanMgdmVyc2lvbjogJHtub2RlanNWZXJzaW9ufS4gQ3VycmVudGx5IDEyLCAxNCwgMTYsIDE4LCAyMCwgYW5kIDIyIGFyZSBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0RW52RmlsZSA9IHByb3BzLm91dHB1dEVudkZpbGUgPz8gZmFsc2U7XG4gICAgY29uc3QgZW52RmlsZUtleU91dHB1dEtleSA9ICdlbnZGaWxlS2V5JztcblxuICAgIGNvbnN0IHByb2plY3QgPSBuZXcgUHJvamVjdCh0aGlzLCAnUHJvamVjdCcsIHtcbiAgICAgIGVudmlyb25tZW50OiB7IGJ1aWxkSW1hZ2U6IExpbnV4QnVpbGRJbWFnZS5mcm9tQ29kZUJ1aWxkSW1hZ2VJZChidWlsZEltYWdlKSB9LFxuICAgICAgYnVpbGRTcGVjOiBCdWlsZFNwZWMuZnJvbU9iamVjdCh7XG4gICAgICAgIHZlcnNpb246ICcwLjInLFxuICAgICAgICBlbnY6IHtcbiAgICAgICAgICBzaGVsbDogJ2Jhc2gnLFxuICAgICAgICB9LFxuICAgICAgICBwaGFzZXM6IHtcbiAgICAgICAgICBpbnN0YWxsOiB7XG4gICAgICAgICAgICAncnVudGltZS12ZXJzaW9ucyc6IHtcbiAgICAgICAgICAgICAgbm9kZWpzOiBub2RlanNWZXJzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJ1aWxkOiB7XG4gICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAnY3VycmVudF9kaXI9JChwd2QpJyxcbiAgICAgICAgICAgICAgLy8gSXRlcmF0ZSBhIGpzb24gYXJyYXkgdXNpbmcganFcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cuc3RhcmthbmR3YXluZS5jb20vYmxvZy9iYXNoLWZvci1sb29wLW92ZXItanNvbi1hcnJheS11c2luZy1qcS9pbmRleC5odG1sXG4gICAgICAgICAgICAgIGBcbmVjaG8gXCIkaW5wdXRcIlxuZm9yIG9iaiBpbiAkKGVjaG8gXCIkaW5wdXRcIiB8IGpxIC1yICcuW10gfCBAYmFzZTY0Jyk7IGRvXG4gIGRlY29kZWQ9JChlY2hvIFwiJG9ialwiIHwgYmFzZTY0IC0tZGVjb2RlKVxuICBhc3NldFVybD0kKGVjaG8gXCIkZGVjb2RlZFwiIHwganEgLXIgJy5hc3NldFVybCcpXG4gIGV4dHJhY3RQYXRoPSQoZWNobyBcIiRkZWNvZGVkXCIgfCBqcSAtciAnLmV4dHJhY3RQYXRoJylcbiAgY29tbWFuZHM9JChlY2hvIFwiJGRlY29kZWRcIiB8IGpxIC1yICcuY29tbWFuZHMnKVxuXG4gICMgRG93bmxvYWQgdGhlIHppcCBmaWxlXG4gIGF3cyBzMyBjcCBcIiRhc3NldFVybFwiIHRlbXAuemlwXG5cbiAgIyBFeHRyYWN0IHRoZSB6aXAgZmlsZSB0byB0aGUgZXh0cmFjdFBhdGggZGlyZWN0b3J5XG4gIG1rZGlyIC1wIFwiJGV4dHJhY3RQYXRoXCJcbiAgdW56aXAgdGVtcC56aXAgLWQgXCIkZXh0cmFjdFBhdGhcIlxuXG4gICMgUmVtb3ZlIHRoZSB6aXAgZmlsZVxuICBybSB0ZW1wLnppcFxuXG4gICMgUnVuIHRoZSBzcGVjaWZpZWQgY29tbWFuZHMgaW4gdGhlIGV4dHJhY3RQYXRoIGRpcmVjdG9yeVxuICBjZCBcIiRleHRyYWN0UGF0aFwiXG4gIGxzIC1sYVxuICBldmFsIFwiJGNvbW1hbmRzXCJcbiAgY2QgXCIkY3VycmVudF9kaXJcIlxuICBscyAtbGFcbmRvbmVcbiAgICAgICAgICAgICAgYCxcbiAgICAgICAgICAgICAgJ2xzIC1sYScsXG4gICAgICAgICAgICAgICdjZCBcIiR3b3JraW5nRGlyZWN0b3J5XCInLFxuICAgICAgICAgICAgICAnZXZhbCBcIiRidWlsZENvbW1hbmRzXCInLFxuICAgICAgICAgICAgICAnbHMgLWxhJyxcbiAgICAgICAgICAgICAgJ2NkIFwiJGN1cnJlbnRfZGlyXCInLFxuICAgICAgICAgICAgICAnY2QgXCIkb3V0cHV0U291cmNlRGlyZWN0b3J5XCInLFxuICAgICAgICAgICAgICAnYXdzIHMzIHN5bmMgLiBcInMzOi8vJGRlc3RpbmF0aW9uQnVja2V0TmFtZS8kZGVzdGluYXRpb25LZXlQcmVmaXhcIiAtLWRlbGV0ZScsXG4gICAgICAgICAgICAgIC8vIEludmFsaWRhdGUgQ2xvdWRGcm9udCBjYWNoZSBpZiBkaXN0cmlidXRpb24gaXMgc3BlY2lmaWVkXG4gICAgICAgICAgICAgIGBcbmlmIFtbIC1uIFwiJGRpc3RyaWJ1dGlvbklkXCIgXV1cbnRoZW5cbklOVkFMSURBVElPTl9PVVRQVVQ9JChhd3MgY2xvdWRmcm9udCBjcmVhdGUtaW52YWxpZGF0aW9uIC0tZGlzdHJpYnV0aW9uLWlkIFwiJGRpc3RyaWJ1dGlvbklkXCIgLS1wYXRocyBcIiRkaXN0cmlidXRpb25QYXRoXCIgLS1vdXRwdXQganNvbilcbklOVkFMSURBVElPTl9JRD0kKGVjaG8gXCIkSU5WQUxJREFUSU9OX09VVFBVVFwiIHwganEgLXIgJy5JbnZhbGlkYXRpb24uSWQnKVxuYXdzIGNsb3VkZnJvbnQgd2FpdCBpbnZhbGlkYXRpb24tY29tcGxldGVkIC0tZGlzdHJpYnV0aW9uLWlkIFwiJGRpc3RyaWJ1dGlvbklkXCIgLS1pZCBcIiRJTlZBTElEQVRJT05fSURcIlxuZmlcbmAsXG4gICAgICAgICAgICAgIC8vIFVwbG9hZCAuZW52IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgIGBcbmlmIFtbICRvdXRwdXRFbnZGaWxlID09IFwidHJ1ZVwiIF1dXG50aGVuXG4gICMgU3BsaXQgdGhlIGNvbW1hLXNlcGFyYXRlZCBzdHJpbmcgaW50byBhbiBhcnJheVxuICBmb3IgdmFyX25hbWUgaW4gXFwke2Vudk5hbWVzLy8sLyB9XG4gIGRvXG4gICAgICBlY2hvIFwiRWxlbWVudDogJHZhcl9uYW1lXCJcbiAgICAgIHZhcl92YWx1ZT1cIlxcJHshdmFyX25hbWV9XCJcbiAgICAgIGVjaG8gXCIkdmFyX25hbWU9JHZhcl92YWx1ZVwiID4+IHRtcC5lbnZcbiAgZG9uZVxuXG4gIGF3cyBzMyBjcCB0bXAuZW52IFwiczM6Ly8kYXNzZXRCdWNrZXROYW1lLyRlbnZGaWxlS2V5XCJcbmZpXG4gICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcG9zdF9idWlsZDoge1xuICAgICAgICAgICAgY29tbWFuZHM6IFtcbiAgICAgICAgICAgICAgJ2VjaG8gQnVpbGQgY29tcGxldGVkIG9uIGBkYXRlYCcsXG4gICAgICAgICAgICAgIGBcblNUQVRVUz0nU1VDQ0VTUydcbmlmIFsgJENPREVCVUlMRF9CVUlMRF9TVUNDRUVESU5HIC1uZSAxIF0gIyBUZXN0IGlmIHRoZSBidWlsZCBpcyBmYWlsaW5nXG50aGVuXG5TVEFUVVM9J0ZBSUxFRCdcblJFQVNPTj1cIk5vZGVqc0J1aWxkIGZhaWxlZC4gU2VlIENsb3VkV2F0Y2ggTG9nIHN0cmVhbSBmb3IgdGhlIGRldGFpbGVkIHJlYXNvbjogXG5odHRwczovLyRBV1NfUkVHSU9OLmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0kQVdTX1JFR0lPTiNsb2dzVjI6bG9nLWdyb3Vwcy9sb2ctZ3JvdXAvXFxcXCQyNTJGYXdzXFxcXCQyNTJGY29kZWJ1aWxkXFxcXCQyNTJGJHByb2plY3ROYW1lL2xvZy1ldmVudHMvJENPREVCVUlMRF9MT0dfUEFUSFwiXG5maVxuY2F0IDw8RU9GID4gcGF5bG9hZC5qc29uXG57XG4gIFwiU3RhY2tJZFwiOiBcIiRzdGFja0lkXCIsXG4gIFwiUmVxdWVzdElkXCI6IFwiJHJlcXVlc3RJZFwiLFxuICBcIkxvZ2ljYWxSZXNvdXJjZUlkXCI6XCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJQaHlzaWNhbFJlc291cmNlSWRcIjogXCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJTdGF0dXNcIjogXCIkU1RBVFVTXCIsXG4gIFwiUmVhc29uXCI6IFwiJFJFQVNPTlwiLFxuICBcIkRhdGFcIjoge1xuICAgIFwiJHtlbnZGaWxlS2V5T3V0cHV0S2V5fVwiOiBcIiRlbnZGaWxlS2V5XCJcbiAgfVxufVxuRU9GXG5jdXJsIC1pIC1YIFBVVCAtSCAnQ29udGVudC1UeXBlOicgLWQgXCJAcGF5bG9hZC5qc29uXCIgXCIkcmVzcG9uc2VVUkxcIlxuICAgICAgICAgICAgICBgLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBoYW5kbGVyLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbJ2NvZGVidWlsZDpTdGFydEJ1aWxkJ10sXG4gICAgICAgIHJlc291cmNlczogW3Byb2plY3QucHJvamVjdEFybl0sXG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gcHJvamVjdC5ncmFudFByaW5jaXBhbDtcblxuICAgIHByb3BzLmRlc3RpbmF0aW9uQnVja2V0LmdyYW50UmVhZFdyaXRlKHByb2plY3QpO1xuICAgIGlmIChwcm9wcy5kaXN0cmlidXRpb24pIHtcbiAgICAgIHByb2plY3QuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbJ2Nsb3VkZnJvbnQ6R2V0SW52YWxpZGF0aW9uJywgJ2Nsb3VkZnJvbnQ6Q3JlYXRlSW52YWxpZGF0aW9uJ10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbcHJvcHMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbkFybl0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbW1vbkV4Y2x1ZGUgPSBbJy5EU19TdG9yZScsICcuZ2l0JywgJ25vZGVfbW9kdWxlcyddO1xuICAgIGNvbnN0IGFzc2V0cyA9IHByb3BzLmFzc2V0cy5tYXAoKGFzc2V0UHJvcHMpID0+IHtcbiAgICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KHRoaXMsIGBTb3VyY2UtJHthc3NldFByb3BzLnBhdGgucmVwbGFjZSgnLycsICcnKX1gLCB7XG4gICAgICAgIC4uLmFzc2V0UHJvcHMsXG4gICAgICAgIC4uLihwcm9wcy5leGNsdWRlQ29tbW9uRmlsZXMgPz8gdHJ1ZSA/IHsgZXhjbHVkZTogWy4uLmNvbW1vbkV4Y2x1ZGUsIC4uLihhc3NldFByb3BzLmV4Y2x1ZGUgPz8gW10pXSB9IDoge30pLFxuICAgICAgfSk7XG4gICAgICBhc3NldC5ncmFudFJlYWQocHJvamVjdCk7XG4gICAgICByZXR1cm4gYXNzZXQ7XG4gICAgfSk7XG5cbiAgICBjb25zdCBidWNrZXQgPSBhc3NldHNbMF0uYnVja2V0O1xuICAgIGlmIChvdXRwdXRFbnZGaWxlKSB7XG4gICAgICAvLyB1c2UgdGhlIGFzc2V0IGJ1Y2tldCB0aGF0IGFyZSBjcmVhdGVkIGJ5IENESyBib290c3RyYXAgdG8gc3RvcmUgLmVudiBmaWxlXG4gICAgICBidWNrZXQuZ3JhbnRXcml0ZShwcm9qZWN0KTtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2VzOiBOb2RlanNCdWlsZFJlc291cmNlUHJvcHNbJ3NvdXJjZXMnXSA9IHByb3BzLmFzc2V0cy5tYXAoKHMsIGkpID0+ICh7XG4gICAgICBzb3VyY2VCdWNrZXROYW1lOiBhc3NldHNbaV0uczNCdWNrZXROYW1lLFxuICAgICAgc291cmNlT2JqZWN0S2V5OiBhc3NldHNbaV0uczNPYmplY3RLZXksXG4gICAgICBleHRyYWN0UGF0aDogcy5leHRyYWN0UGF0aCA/PyBiYXNlbmFtZShzLnBhdGgpLFxuICAgICAgY29tbWFuZHM6IHMuY29tbWFuZHMsXG4gICAgfSkpO1xuXG4gICAgY29uc3Qgd29ya2luZ0RpcmVjdG9yeSA9IHByb3BzLndvcmtpbmdEaXJlY3RvcnkgPz8gc291cmNlc1swXS5leHRyYWN0UGF0aDtcbiAgICBjb25zdCBwcm9wZXJ0aWVzOiBOb2RlanNCdWlsZFJlc291cmNlUHJvcHMgPSB7XG4gICAgICB0eXBlOiAnTm9kZWpzQnVpbGQnLFxuICAgICAgc291cmNlcyxcbiAgICAgIGRlc3RpbmF0aW9uQnVja2V0TmFtZTogcHJvcHMuZGVzdGluYXRpb25CdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgIGRlc3RpbmF0aW9uS2V5UHJlZml4OiBwcm9wcy5kZXN0aW5hdGlvbktleVByZWZpeCA/PyAnLycsXG4gICAgICBkaXN0cmlidXRpb25JZDogcHJvcHMuZGlzdHJpYnV0aW9uPy5kaXN0cmlidXRpb25JZCxcbiAgICAgIGFzc2V0QnVja2V0TmFtZTogYnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICB3b3JraW5nRGlyZWN0b3J5LFxuICAgICAgLy8gam9pbiBwYXRocyBmb3IgQ29kZUJ1aWxkIChMaW51eCkgcGxhdGZvcm1cbiAgICAgIG91dHB1dFNvdXJjZURpcmVjdG9yeTogcG9zaXguam9pbih3b3JraW5nRGlyZWN0b3J5LCBwcm9wcy5vdXRwdXRTb3VyY2VEaXJlY3RvcnkpLFxuICAgICAgZW52aXJvbm1lbnQ6IHByb3BzLmJ1aWxkRW52aXJvbm1lbnQsXG4gICAgICBidWlsZENvbW1hbmRzOiBwcm9wcy5idWlsZENvbW1hbmRzID8/IFsnbnBtIHJ1biBidWlsZCddLFxuICAgICAgY29kZUJ1aWxkUHJvamVjdE5hbWU6IHByb2plY3QucHJvamVjdE5hbWUsXG4gICAgICBvdXRwdXRFbnZGaWxlLFxuICAgIH07XG5cbiAgICBjb25zdCBjdXN0b20gPSBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgc2VydmljZVRva2VuOiBoYW5kbGVyLmZ1bmN0aW9uQXJuLFxuICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpDREtOb2RlanNCdWlsZCcsXG4gICAgICBwcm9wZXJ0aWVzLFxuICAgIH0pO1xuICAgIGlmIChwcm9qZWN0LnJvbGUpIHtcbiAgICAgIGN1c3RvbS5ub2RlLmFkZERlcGVuZGVuY3kocHJvamVjdC5yb2xlKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMub3V0cHV0RW52RmlsZSkge1xuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCAnRG93bmxvYWRFbnZGaWxlJywgeyB2YWx1ZTogYGF3cyBzMyBjcCAke2J1Y2tldC5zM1VybEZvck9iamVjdChjdXN0b20uZ2V0QXR0U3RyaW5nKGVudkZpbGVLZXlPdXRwdXRLZXkpKX0gLmVudi5sb2NhbGAgfSk7XG4gICAgfVxuICB9XG59XG4iXX0=