cdk-databrew-cicd
Version:
A construct for AWS Glue DataBrew wtih CICD
251 lines • 38.1 kB
JavaScript
;
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodePipelineIamRole = exports.InfraIamRole = exports.DataBrewCodePipeline = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("aws-cdk-lib");
const codecommit = require("aws-cdk-lib/aws-codecommit");
const codepipeline = require("aws-cdk-lib/aws-codepipeline");
const codepipeline_actions = require("aws-cdk-lib/aws-codepipeline-actions");
const iam = require("aws-cdk-lib/aws-iam");
const logs = require("aws-cdk-lib/aws-logs");
const s3 = require("aws-cdk-lib/aws-s3");
const cr = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const cdk_databrew_lambda_1 = require("./cdk-databrew-lambda");
class DataBrewCodePipeline extends constructs_1.Construct {
constructor(scope, name, props) {
super(scope, name);
/**
* Creates a source action.
*
* @param codeCommitRepo the CodeCommit repository used in the DataBrew CICD pipeline.
* @param role the IAM role used by the CodePipeline pipeline.
* @returns the CodeCOmmit source action.
*/
this.createSourceAction = (codeCommitRepo, role) => {
const sourceOutput = new codepipeline.Artifact(this.firstStageArtifactName);
const sourceAction = new codepipeline_actions.CodeCommitSourceAction({
actionName: 'Source',
output: sourceOutput,
branch: this.branchName, // default: 'master'
trigger: codepipeline_actions.CodeCommitTrigger.EVENTS,
repository: codeCommitRepo,
runOrder: 1,
role: role,
});
return sourceAction;
};
this.firstStageArtifactName = props.firstStageArtifactName ?? 'SourceOutput';
this.repoName = props.repoName ?? 'DataBrew-Recipes-Repo';
this.branchName = props.branchName ?? 'main';
// create a bucket
const pipelineBucket = new s3.Bucket(this, 'CodePipelineBucket', {
bucketName: props.bucketName ?? 'databrew-cicd-codepipelineartifactstorebucket',
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
pipelineBucket.addToResourcePolicy(new iam.PolicyStatement({
sid: 'DenyUnEncryptedObjectUploads',
effect: iam.Effect.DENY,
principals: [new iam.AnyPrincipal()],
actions: ['s3:PutObject'],
resources: [`${pipelineBucket.bucketArn}/*`],
conditions: {
StringNotEquals: {
's3:x-amz-server-side-encryption': 'aws:kms',
},
},
}));
this.bucketArn = pipelineBucket.bucketArn;
const preproductionLambda = new cdk_databrew_lambda_1.PreProductionLambda(this, 'PreProductionLambda', {
bucketArn: pipelineBucket.bucketArn,
preproductionIamRoleArn: props.preproductionIamRoleArn,
});
const productionLambda = new cdk_databrew_lambda_1.ProductionLambda(this, 'ProductionLambda', {
bucketArn: pipelineBucket.bucketArn,
productionIamRoleArn: props.productionIamRoleArn,
});
this.preproductionFunctionArn = preproductionLambda.function.functionArn;
this.productionFunctionArn = productionLambda.function.functionArn;
// create a CodeCommit repo
const codeCommitRepo = new codecommit.Repository(this, 'DataBrewRepository', {
repositoryName: 'DataBrew-Recipes-Repo',
});
this.codeCommitRepoArn = codeCommitRepo.repositoryArn;
const firstCommitHelper = new cdk_databrew_lambda_1.FirstCommitHandler(this, 'FirstCommitLambda', {
codeCommitRepoArn: codeCommitRepo.repositoryArn,
repoName: codeCommitRepo.repositoryName,
branchName: this.branchName,
});
const onEvent = firstCommitHelper.function;
const lambdaInvoker = new cr.Provider(this, 'LambdaInvoker', {
onEventHandler: onEvent,
logRetention: logs.RetentionDays.FIVE_DAYS,
});
new cdk.CustomResource(this, 'CodeCommitCustomResource', {
serviceToken: lambdaInvoker.serviceToken,
resourceType: 'Custom::LambdaInvoker',
});
// create a CodePipeline pipeline
const pipelineRole = new CodePipelineIamRole(this, 'DataBrewCodePipelineRole', {
bucketArn: pipelineBucket.bucketArn,
preproductionLambdaArn: this.preproductionFunctionArn,
productionLambdaArn: this.productionFunctionArn,
});
pipelineRole.node.addDependency(preproductionLambda);
pipelineRole.node.addDependency(productionLambda);
const databrewCicdPipeline = new codepipeline.Pipeline(this, 'DataBrewCicdPipeline', {
artifactBucket: pipelineBucket,
role: pipelineRole.role.withoutPolicyUpdates(),
pipelineName: props.pipelineName ?? 'DataBrew-Recipe-Application',
});
databrewCicdPipeline.node.addDependency(pipelineRole.role);
const sourceAction = this.createSourceAction(codeCommitRepo, pipelineRole.role);
const preproductionLambdaAction = new codepipeline_actions.LambdaInvokeAction({
inputs: [new codepipeline.Artifact(this.firstStageArtifactName)],
actionName: 'PreProd-DeployRecipe',
lambda: preproductionLambda.function,
role: pipelineRole.role,
});
const productionLambdaAction = new codepipeline_actions.LambdaInvokeAction({
inputs: [new codepipeline.Artifact(this.firstStageArtifactName)],
actionName: 'Prod-DeployRecipe',
lambda: productionLambda.function,
role: pipelineRole.role,
});
databrewCicdPipeline.addStage({
stageName: 'Source',
actions: [sourceAction],
});
databrewCicdPipeline.addStage({
stageName: 'PreProd-DeployRecipe',
actions: [preproductionLambdaAction],
});
databrewCicdPipeline.addStage({
stageName: 'Prod-DeployRecipe',
actions: [productionLambdaAction],
});
this.codePipelineArn = databrewCicdPipeline.pipelineArn;
}
}
exports.DataBrewCodePipeline = DataBrewCodePipeline;
_a = JSII_RTTI_SYMBOL_1;
DataBrewCodePipeline[_a] = { fqn: "cdk-databrew-cicd.DataBrewCodePipeline", version: "2.0.636" };
class InfraIamRole extends constructs_1.Construct {
constructor(scope, name, props) {
super(scope, name);
const role = new iam.Role(this, 'InfraIamRole', {
assumedBy: new iam.AccountRootPrincipal(),
roleName: props.roleName ?? 'CrossAccountRepositoryContributorRole',
description: 'The IAM role for DataBrew CICD in the infrastructure account.',
});
role.addToPolicy(new iam.PolicyStatement({
sid: 'CodeCommitPermissions',
effect: iam.Effect.ALLOW,
actions: [
'codecommit:BatchGet*',
'codecommit:Create*',
'codecommit:DeleteBranch',
'codecommit:Get*',
'codecommit:List*',
'codecommit:Describe*',
'codecommit:Put*',
'codecommit:Post*',
'codecommit:Merge*',
'codecommit:Test*',
'codecommit:Update*',
'codecommit:GitPull',
'codecommit:GitPush',
],
resources: [
`arn:${cdk.Aws.PARTITION}:codecommit:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:DataBrew-Recipes-Repo`,
],
}));
role.addToPolicy(new iam.PolicyStatement({
sid: 'CodeCommitListReposPermission',
effect: iam.Effect.ALLOW,
actions: [
'codecommit:ListRepositories',
],
resources: ['*'],
}));
this.roleArn = role.roleArn;
}
}
exports.InfraIamRole = InfraIamRole;
_b = JSII_RTTI_SYMBOL_1;
InfraIamRole[_b] = { fqn: "cdk-databrew-cicd.InfraIamRole", version: "2.0.636" };
class CodePipelineIamRole extends constructs_1.Construct {
constructor(scope, name, props) {
super(scope, name);
const role = new iam.Role(this, 'CodePipelineIamRole', {
assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal('codepipeline.amazonaws.com'), new iam.ServicePrincipal('lambda.amazonaws.com')),
roleName: props.roleName ?? 'DataBrew-Recipe-Pipeline-Role',
description: 'The IAM role for the CodePipeline CICD pipeline in the infrastructure account.',
});
// CodeDeploy permissions
role.addToPolicy(new iam.PolicyStatement({
sid: 'CodeDeployPermissions',
effect: iam.Effect.ALLOW,
actions: [
'codedeploy:CreateDeployment',
'codedeploy:GetApplicationRevision',
'codedeploy:GetDeployment',
'codedeploy:GetDeploymentConfig',
'codedeploy:RegisterApplicationRevision',
],
resources: [
`arn:${cdk.Aws.PARTITION}:codedeploy:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:deploymentgroup:DataBrew-Recipe-Application*`,
`arn:${cdk.Aws.PARTITION}:codedeploy:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:application:DataBrew-Recipe-Application`,
],
}));
// CodeCommit permissions
role.addToPolicy(new iam.PolicyStatement({
sid: 'CodeCommitPermissions',
effect: iam.Effect.ALLOW,
actions: [
'codecommit:GetBranch',
'codecommit:GetCommit',
'codecommit:GetUploadArchiveStatus',
'codecommit:UploadArchive',
],
resources: [
`arn:${cdk.Aws.PARTITION}:codecommit:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:DataBrew-Recipes-Repo`,
],
}));
// S3 permissions
role.addToPolicy(new iam.PolicyStatement({
sid: 'S3Permissions',
effect: iam.Effect.ALLOW,
actions: [
's3:GetObject',
's3:PutObject',
],
resources: [props.bucketArn],
}));
// Lambda permissions
role.addToPolicy(new iam.PolicyStatement({
sid: 'LambdaPermissions',
effect: iam.Effect.ALLOW,
actions: [
'lambda:InvokeFunction',
],
resources: [props.preproductionLambdaArn, props.productionLambdaArn],
}));
role.addToPolicy(new iam.PolicyStatement({
sid: 'AssumRolePermissions',
effect: iam.Effect.ALLOW,
actions: [
'sts:AssumeRole',
],
resources: [role.roleArn],
}));
this.role = role;
this.roleArn = role.roleArn;
}
}
exports.CodePipelineIamRole = CodePipelineIamRole;
_c = JSII_RTTI_SYMBOL_1;
CodePipelineIamRole[_c] = { fqn: "cdk-databrew-cicd.CodePipelineIamRole", version: "2.0.636" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLWRhdGFicmV3LWNpY2QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2RrLWRhdGFicmV3LWNpY2QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxtQ0FBbUM7QUFDbkMseURBQXlEO0FBQ3pELDZEQUE2RDtBQUM3RCw2RUFBNkU7QUFDN0UsMkNBQTJDO0FBQzNDLDZDQUE2QztBQUM3Qyx5Q0FBeUM7QUFDekMsbURBQW1EO0FBQ25ELDJDQUF1QztBQUN2QywrREFBa0c7QUEwQ2xHLE1BQWEsb0JBQXFCLFNBQVEsc0JBQVM7SUFpQ2pELFlBQVksS0FBZ0IsRUFBRSxJQUFZLEVBQUUsS0FBZ0M7UUFDMUUsS0FBSyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQW9HckI7Ozs7OztlQU1PO1FBQ0MsdUJBQWtCLEdBQUcsQ0FDM0IsY0FBc0MsRUFDdEMsSUFBYyxFQUErQyxFQUFFO1lBQy9ELE1BQU0sWUFBWSxHQUFHLElBQUksWUFBWSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUM1RSxNQUFNLFlBQVksR0FBRyxJQUFJLG9CQUFvQixDQUFDLHNCQUFzQixDQUFDO2dCQUNuRSxVQUFVLEVBQUUsUUFBUTtnQkFDcEIsTUFBTSxFQUFFLFlBQVk7Z0JBQ3BCLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLG9CQUFvQjtnQkFDN0MsT0FBTyxFQUFFLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLE1BQU07Z0JBQ3RELFVBQVUsRUFBRSxjQUFjO2dCQUMxQixRQUFRLEVBQUUsQ0FBQztnQkFDWCxJQUFJLEVBQUUsSUFBSTthQUNYLENBQUMsQ0FBQztZQUNILE9BQU8sWUFBWSxDQUFDO1FBQ3RCLENBQUMsQ0FBQztRQXhIQSxJQUFJLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDLHNCQUFzQixJQUFJLGNBQWMsQ0FBQztRQUM3RSxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUss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Q0FBQyxDQUFDO1FBQ0osaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO1lBQ3ZDLEdBQUcsRUFBRSxlQUFlO1lBQ3BCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7WUFDeEIsT0FBTyxFQUFFO2dCQUNQLGNBQWM7Z0JBQ2QsY0FBYzthQUNmO1lBQ0QsU0FBUyxFQUFFLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztTQUM3QixDQUFDLENBQUMsQ0FBQztRQUNKLHFCQUFxQjtRQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztZQUN2QyxHQUFHLEVBQUUsbUJBQW1CO1lBQ3hCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7WUFDeEIsT0FBTyxFQUFFO2dCQUNQLHVCQUF1QjthQUN4QjtZQUNELFNBQVMsRUFBRSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLENBQUMsbUJBQW1CLENBQUM7U0FDckUsQ0FBQyxDQUFDLENBQUM7UUFDSixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztZQUN2QyxHQUFHLEVBQUUsc0JBQXNCO1lBQzNCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7WUFDeEIsT0FBTyxFQUFFO2dCQUNQLGdCQUFnQjthQUNqQjtZQUNELFNBQVMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDMUIsQ0FBQyxDQUFDLENBQUM7UUFDSixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDOUIsQ0FBQzs7QUE5RUgsa0RBK0VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGNvZGVjb21taXQgZnJvbSAnYXdzLWNkay1saWIvYXdzLWNvZGVjb21taXQnO1xuaW1wb3J0ICogYXMgY29kZXBpcGVsaW5lIGZyb20gJ2F3cy1jZGstbGliL2F3cy1jb2RlcGlwZWxpbmUnO1xuaW1wb3J0ICogYXMgY29kZXBpcGVsaW5lX2FjdGlvbnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWNvZGVwaXBlbGluZS1hY3Rpb25zJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIGNyIGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBGaXJzdENvbW1pdEhhbmRsZXIsIFByZVByb2R1Y3Rpb25MYW1iZGEsIFByb2R1Y3Rpb25MYW1iZGEgfSBmcm9tICcuL2Nkay1kYXRhYnJldy1sYW1iZGEnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFCcmV3Q29kZVBpcGVsaW5lUHJvcHMge1xuICAvKipcbiAgICAgKiBUaGUgQVJOIG9mIHRoZSBJQU0gcm9sZSBpbiB0aGUgcHJlLXByb2R1Y3Rpb24gYWNjb3VudC5cbiAgICAgKi9cbiAgcmVhZG9ubHkgcHJlcHJvZHVjdGlvbklhbVJvbGVBcm46IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIEFSTiBvZiB0aGUgSUFNIHJvbGUgaW4gdGhlIHByb2R1Y3Rpb24gYWNjb3VudC5cbiAgICAgKi9cbiAgcmVhZG9ubHkgcHJvZHVjdGlvbklhbVJvbGVBcm46IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIFMzIGJ1Y2tldCBmb3IgdGhlIENvZGVQaXBlbGluZSBEYXRhQnJldyBDSUNEIHBpcGVsaW5lLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgJ2RhdGFicmV3LWNpY2QtY29kZXBpcGVsaW5lYXJ0aWZhY3RzdG9yZWJ1Y2tldCdcbiAgICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0TmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIENvZGVDb21taXQgcmVwb3NpdHJveSBmb3IgdGhlIERhdGFCcmV3IENJQ0QgcGlwZWxpbmUuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCAnRGF0YUJyZXctUmVjaXBlcy1SZXBvJ1xuICAgICAqL1xuICByZWFkb25seSByZXBvTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyYW5jaCB0aGF0IHdpbGwgdHJpZ2dlciB0aGUgRGF0YUJyZXcgQ0lDRCBwaXBlbGluZS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0ICdtYWluJ1xuICAgICAqL1xuICByZWFkb25seSBicmFuY2hOYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgQ29kZVBpcGVsaW5lIERhdGFicmV3IENJQ0QgcGlwZWxpbmUuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCAnRGF0YUJyZXctUmVjaXBlLUFwcGxpY2F0aW9uJ1xuICAgICAqL1xuICByZWFkb25seSBwaXBlbGluZU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgICAqIHRoZSAocmVxdWlyZWQpIG5hbWUgb2YgdGhlIEFydGlmYWN0IGF0IHRoZSBmaXJzdCBzdGFnZS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0ICdTb3VyY2VPdXRwdXQnXG4gICAgICovXG4gIHJlYWRvbmx5IGZpcnN0U3RhZ2VBcnRpZmFjdE5hbWU/OiBzdHJpbmc7XG59XG5leHBvcnQgY2xhc3MgRGF0YUJyZXdDb2RlUGlwZWxpbmUgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICAgKiBUaGUgQVJOIG9mIHRoZSBTMyBidWNrZXQgZm9yIHRoZSBDb2RlUGlwZWxpbmUgRGF0YUJyZXcgQ0lDRCBwaXBlbGluZS5cbiAgICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0QXJuOiBzdHJpbmc7XG4gIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBDb2RlQ29tbWl0IHJlcG9zaXRyb3kgZm9yIHRoZSBEYXRhQnJldyBDSUNEIHBpcGVsaW5lLlxuICAgICAqL1xuICByZWFkb25seSByZXBvTmFtZTogc3RyaW5nO1xuICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJhbmNoIHRoYXQgd2lsbCB0cmlnZ2VyIHRoZSBEYXRhQnJldyBDSUNEIHBpcGVsaW5lLlxuICAgICAqL1xuICByZWFkb25seSBicmFuY2hOYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgICAqIHRoZSAocmVxdWlyZWQpIG5hbWUgb2YgdGhlIEFydGlmYWN0IGF0IHRoZSBmaXJzdCBzdGFnZS5cbiAgICAgKi9cbiAgcmVhZG9ubHkgZmlyc3RTdGFnZUFydGlmYWN0TmFtZTogc3RyaW5nO1xuICAvKipcbiAgICAgKiBUaGUgQVJOIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24gZm9yIHRoZSBwcmUtcHJvZHVjdGlvbiBhY2NvdW50LlxuICAgICAqL1xuICByZWFkb25seSBwcmVwcm9kdWN0aW9uRnVuY3Rpb25Bcm46IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIEFSTiBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGZvciB0aGUgcHJvZHVjdGlvbiBhY2NvdW50LlxuICAgICAqL1xuICByZWFkb25seSBwcm9kdWN0aW9uRnVuY3Rpb25Bcm46IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIEFSTiBvZiB0aGUgQ29kZUNvbW1pdCByZXBvc2l0b3J5XG4gICAgICovXG4gIHJlYWRvbmx5IGNvZGVDb21taXRSZXBvQXJuOiBzdHJpbmc7XG4gIC8qKlxuICAgICAqIFRoZSBBUk4gb2YgdGhlIERhdGFCcmV3IENJQ0QgcGlwZWxpbmUuXG4gICAgICovXG4gIHJlYWRvbmx5IGNvZGVQaXBlbGluZUFybjogc3RyaW5nO1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBuYW1lOiBzdHJpbmcsIHByb3BzOiBEYXRhQnJld0NvZGVQaXBlbGluZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIG5hbWUpO1xuICAgIHRoaXMuZmlyc3RTdGFnZUFydGlmYWN0TmFtZSA9IHByb3BzLmZpcnN0U3RhZ2VBcnRpZmFjdE5hbWUgPz8gJ1NvdXJjZU91dHB1dCc7XG4gICAgdGhpcy5yZXBvTmFtZSA9IHByb3BzLnJlcG9OYW1lID8/ICdEYXRhQnJldy1SZWNpcGVzLVJlcG8nO1xuICAgIHRoaXMuYnJhbmNoTmFtZSA9IHByb3BzLmJyYW5jaE5hbWUgPz8gJ21haW4nO1xuXG4gICAgLy8gY3JlYXRlIGEgYnVja2V0XG4gICAgY29uc3QgcGlwZWxpbmVCdWNrZXQgPSBuZXcgczMuQnVja2V0KHRoaXMsICdDb2RlUGlwZWxpbmVCdWNrZXQnLCB7XG4gICAgICBidWNrZXROYW1lOiBwcm9wcy5idWNrZXROYW1lID8/ICdkYXRhYnJldy1jaWNkLWNvZGVwaXBlbGluZWFydGlmYWN0c3RvcmVidWNrZXQnLFxuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGF1dG9EZWxldGVPYmplY3RzOiB0cnVlLFxuICAgIH0pO1xuICAgIHBpcGVsaW5lQnVja2V0LmFkZFRvUmVzb3VyY2VQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnRGVueVVuRW5jcnlwdGVkT2JqZWN0VXBsb2FkcycsXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuREVOWSxcbiAgICAgIHByaW5jaXBhbHM6IFtuZXcgaWFtLkFueVByaW5jaXBhbCgpXSxcbiAgICAgIGFjdGlvbnM6IFsnczM6UHV0T2JqZWN0J10sXG4gICAgICByZXNvdXJjZXM6IFtgJHtwaXBlbGluZUJ1Y2tldC5idWNrZXRBcm59LypgXSxcbiAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgU3RyaW5nTm90RXF1YWxzOiB7XG4gICAgICAgICAgJ3MzOngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24nOiAnYXdzOmttcycsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pKTtcbiAgICB0aGlzLmJ1Y2tldEFybiA9IHBpcGVsaW5lQnVja2V0LmJ1Y2tldEFybjtcblxuICAgIGNvbnN0IHByZXByb2R1Y3Rpb25MYW1iZGEgPSBuZXcgUHJlUHJvZHVjdGlvbkxhbWJkYSh0aGlzLCAnUHJlUHJvZHVjdGlvbkxhbWJkYScsIHtcbiAgICAgIGJ1Y2tldEFybjogcGlwZWxpbmVCdWNrZXQuYnVja2V0QXJuLFxuICAgICAgcHJlcHJvZHVjdGlvbklhbVJvbGVBcm46IHByb3BzLnByZXByb2R1Y3Rpb25JYW1Sb2xlQXJuLFxuICAgIH0pO1xuICAgIGNvbnN0IHByb2R1Y3Rpb25MYW1iZGEgPSBuZXcgUHJvZHVjdGlvbkxhbWJkYSh0aGlzLCAnUHJvZHVjdGlvbkxhbWJkYScsIHtcbiAgICAgIGJ1Y2tldEFybjogcGlwZWxpbmVCdWNrZXQuYnVja2V0QXJuLFxuICAgICAgcHJvZHVjdGlvbklhbVJvbGVBcm46IHByb3BzLnByb2R1Y3Rpb25JYW1Sb2xlQXJuLFxuICAgIH0pO1xuICAgIHRoaXMucHJlcHJvZHVjdGlvbkZ1bmN0aW9uQXJuID0gcHJlcHJvZHVjdGlvbkxhbWJkYS5mdW5jdGlvbi5mdW5jdGlvbkFybjtcbiAgICB0aGlzLnByb2R1Y3Rpb25GdW5jdGlvbkFybiA9IHByb2R1Y3Rpb25MYW1iZGEuZnVuY3Rpb24uZnVuY3Rpb25Bcm47XG5cbiAgICAvLyBjcmVhdGUgYSBDb2RlQ29tbWl0IHJlcG9cbiAgICBjb25zdCBjb2RlQ29tbWl0UmVwbyA9IG5ldyBjb2RlY29tbWl0LlJlcG9zaXRvcnkodGhpcywgJ0RhdGFCcmV3UmVwb3NpdG9yeScsIHtcbiAgICAgIHJlcG9zaXRvcnlOYW1lOiAnRGF0YUJyZXctUmVjaXBlcy1SZXBvJyxcbiAgICB9KTtcbiAgICB0aGlzLmNvZGVDb21taXRSZXBvQXJuID0gY29kZUNvbW1pdFJlcG8ucmVwb3NpdG9yeUFybjtcbiAgICBjb25zdCBmaXJzdENvbW1pdEhlbHBlciA9IG5ldyBGaXJzdENvbW1pdEhhbmRsZXIodGhpcywgJ0ZpcnN0Q29tbWl0TGFtYmRhJywge1xuICAgICAgY29kZUNvbW1pdFJlcG9Bcm46IGNvZGVDb21taXRSZXBvLnJlcG9zaXRvcnlBcm4sXG4gICAgICByZXBvTmFtZTogY29kZUNvbW1pdFJlcG8ucmVwb3NpdG9yeU5hbWUsXG4gICAgICBicmFuY2hOYW1lOiB0aGlzLmJyYW5jaE5hbWUsXG4gICAgfSk7XG4gICAgY29uc3Qgb25FdmVudCA9IGZpcnN0Q29tbWl0SGVscGVyLmZ1bmN0aW9uO1xuICAgIGNvbnN0IGxhbWJkYUludm9rZXIgPSBuZXcgY3IuUHJvdmlkZXIodGhpcywgJ0xhbWJkYUludm9rZXInLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogb25FdmVudCxcbiAgICAgIGxvZ1JldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLkZJVkVfREFZUyxcbiAgICB9KTtcbiAgICBuZXcgY2RrLkN1c3RvbVJlc291cmNlKHRoaXMsICdDb2RlQ29tbWl0Q3VzdG9tUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IGxhbWJkYUludm9rZXIuc2VydmljZVRva2VuLFxuICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpMYW1iZGFJbnZva2VyJyxcbiAgICB9KTtcblxuICAgIC8vIGNyZWF0ZSBhIENvZGVQaXBlbGluZSBwaXBlbGluZVxuICAgIGNvbnN0IHBpcGVsaW5lUm9sZSA9IG5ldyBDb2RlUGlwZWxpbmVJYW1Sb2xlKHRoaXMsICdEYXRhQnJld0NvZGVQaXBlbGluZVJvbGUnLCB7XG4gICAgICBidWNrZXRBcm46IHBpcGVsaW5lQnVja2V0LmJ1Y2tldEFybixcbiAgICAgIHByZXByb2R1Y3Rpb25MYW1iZGFBcm46IHRoaXMucHJlcHJvZHVjdGlvbkZ1bmN0aW9uQXJuLFxuICAgICAgcHJvZHVjdGlvbkxhbWJkYUFybjogdGhpcy5wcm9kdWN0aW9uRnVuY3Rpb25Bcm4sXG4gICAgfSk7XG4gICAgcGlwZWxpbmVSb2xlLm5vZGUuYWRkRGVwZW5kZW5jeShwcmVwcm9kdWN0aW9uTGFtYmRhKTtcbiAgICBwaXBlbGluZVJvbGUubm9kZS5hZGREZXBlbmRlbmN5KHByb2R1Y3Rpb25MYW1iZGEpO1xuXG4gICAgY29uc3QgZGF0YWJyZXdDaWNkUGlwZWxpbmUgPSBuZXcgY29kZXBpcGVsaW5lLlBpcGVsaW5lKHRoaXMsICdEYXRhQnJld0NpY2RQaXBlbGluZScsIHtcbiAgICAgIGFydGlmYWN0QnVja2V0OiBwaXBlbGluZUJ1Y2tldCxcbiAgICAgIHJvbGU6IHBpcGVsaW5lUm9sZS5yb2xlLndpdGhvdXRQb2xpY3lVcGRhdGVzKCksXG4gICAgICBwaXBlbGluZU5hbWU6IHByb3BzLnBpcGVsaW5lTmFtZSA/PyAnRGF0YUJyZXctUmVjaXBlLUFwcGxpY2F0aW9uJyxcbiAgICB9KTtcbiAgICBkYXRhYnJld0NpY2RQaXBlbGluZS5ub2RlLmFkZERlcGVuZGVuY3kocGlwZWxpbmVSb2xlLnJvbGUpO1xuXG4gICAgY29uc3Qgc291cmNlQWN0aW9uID0gdGhpcy5jcmVhdGVTb3VyY2VBY3Rpb24oY29kZUNvbW1pdFJlcG8sIHBpcGVsaW5lUm9sZS5yb2xlKTtcbiAgICBjb25zdCBwcmVwcm9kdWN0aW9uTGFtYmRhQWN0aW9uID0gbmV3IGNvZGVwaXBlbGluZV9hY3Rpb25zLkxhbWJkYUludm9rZUFjdGlvbih7XG4gICAgICBpbnB1dHM6IFtuZXcgY29kZXBpcGVsaW5lLkFydGlmYWN0KHRoaXMuZmlyc3RTdGFnZUFydGlmYWN0TmFtZSldLFxuICAgICAgYWN0aW9uTmFtZTogJ1ByZVByb2QtRGVwbG95UmVjaXBlJyxcbiAgICAgIGxhbWJkYTogcHJlcHJvZHVjdGlvbkxhbWJkYS5mdW5jdGlvbixcbiAgICAgIHJvbGU6IHBpcGVsaW5lUm9sZS5yb2xlLFxuICAgIH0pO1xuICAgIGNvbnN0IHByb2R1Y3Rpb25MYW1iZGFBY3Rpb24gPSBuZXcgY29kZXBpcGVsaW5lX2FjdGlvbnMuTGFtYmRhSW52b2tlQWN0aW9uKHtcbiAgICAgIGlucHV0czogW25ldyBjb2RlcGlwZWxpbmUuQXJ0aWZhY3QodGhpcy5maXJzdFN0YWdlQXJ0aWZhY3ROYW1lKV0sXG4gICAgICBhY3Rpb25OYW1lOiAnUHJvZC1EZXBsb3lSZWNpcGUnLFxuICAgICAgbGFtYmRhOiBwcm9kdWN0aW9uTGFtYmRhLmZ1bmN0aW9uLFxuICAgICAgcm9sZTogcGlwZWxpbmVSb2xlLnJvbGUsXG4gICAgfSk7XG4gICAgZGF0YWJyZXdDaWNkUGlwZWxpbmUuYWRkU3RhZ2Uoe1xuICAgICAgc3RhZ2VOYW1lOiAnU291cmNlJyxcbiAgICAgIGFjdGlvbnM6IFtzb3VyY2VBY3Rpb25dLFxuICAgIH0pO1xuICAgIGRhdGFicmV3Q2ljZFBpcGVsaW5lLmFkZFN0YWdlKHtcbiAgICAgIHN0YWdlTmFtZTogJ1ByZVByb2QtRGVwbG95UmVjaXBlJyxcbiAgICAgIGFjdGlvbnM6IFtwcmVwcm9kdWN0aW9uTGFtYmRhQWN0aW9uXSxcbiAgICB9KTtcbiAgICBkYXRhYnJld0NpY2RQaXBlbGluZS5hZGRTdGFnZSh7XG4gICAgICBzdGFnZU5hbWU6ICdQcm9kLURlcGxveVJlY2lwZScsXG4gICAgICBhY3Rpb25zOiBbcHJvZHVjdGlvbkxhbWJkYUFjdGlvbl0sXG4gICAgfSk7XG4gICAgdGhpcy5jb2RlUGlwZWxpbmVBcm4gPSBkYXRhYnJld0NpY2RQaXBlbGluZS5waXBlbGluZUFybjtcbiAgfVxuXG4gIC8qKlxuICAgICAgICogQ3JlYXRlcyBhIHNvdXJjZSBhY3Rpb24uXG4gICAgICAgKlxuICAgICAgICogQHBhcmFtIGNvZGVDb21taXRSZXBvIHRoZSBDb2RlQ29tbWl0IHJlcG9zaXRvcnkgdXNlZCBpbiB0aGUgRGF0YUJyZXcgQ0lDRCBwaXBlbGluZS5cbiAgICAgICAqIEBwYXJhbSByb2xlIHRoZSBJQU0gcm9sZSB1c2VkIGJ5IHRoZSBDb2RlUGlwZWxpbmUgcGlwZWxpbmUuXG4gICAgICAgKiBAcmV0dXJucyB0aGUgQ29kZUNPbW1pdCBzb3VyY2UgYWN0aW9uLlxuICAgICAgICovXG4gIHByaXZhdGUgY3JlYXRlU291cmNlQWN0aW9uID0gKFxuICAgIGNvZGVDb21taXRSZXBvOiBjb2RlY29tbWl0LklSZXBvc2l0b3J5LFxuICAgIHJvbGU6IGlhbS5Sb2xlKTogY29kZXBpcGVsaW5lX2FjdGlvbnMuQ29kZUNvbW1pdFNvdXJjZUFjdGlvbiA9PiB7XG4gICAgY29uc3Qgc291cmNlT3V0cHV0ID0gbmV3IGNvZGVwaXBlbGluZS5BcnRpZmFjdCh0aGlzLmZpcnN0U3RhZ2VBcnRpZmFjdE5hbWUpO1xuICAgIGNvbnN0IHNvdXJjZUFjdGlvbiA9IG5ldyBjb2RlcGlwZWxpbmVfYWN0aW9ucy5Db2RlQ29tbWl0U291cmNlQWN0aW9uKHtcbiAgICAgIGFjdGlvbk5hbWU6ICdTb3VyY2UnLFxuICAgICAgb3V0cHV0OiBzb3VyY2VPdXRwdXQsXG4gICAgICBicmFuY2g6IHRoaXMuYnJhbmNoTmFtZSwgLy8gZGVmYXVsdDogJ21hc3RlcidcbiAgICAgIHRyaWdnZXI6IGNvZGVwaXBlbGluZV9hY3Rpb25zLkNvZGVDb21taXRUcmlnZ2VyLkVWRU5UUyxcbiAgICAgIHJlcG9zaXRvcnk6IGNvZGVDb21taXRSZXBvLFxuICAgICAgcnVuT3JkZXI6IDEsXG4gICAgICByb2xlOiByb2xlLFxuICAgIH0pO1xuICAgIHJldHVybiBzb3VyY2VBY3Rpb247XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5mcmFJYW1Sb2xlUHJvcHMge1xuICAvKipcbiAgICAgKiBUaGUgcm9sZSBuYW1lIGZvciB0aGUgaW5mcmFzdHJ1Y3R1cmUgYWNjb3VudC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0ICdDcm9zc0FjY291bnRSZXBvc2l0b3J5Q29udHJpYnV0b3JSb2xlJ1xuICAgICAqL1xuICByZWFkb25seSByb2xlTmFtZT86IHN0cmluZztcbn1cbmV4cG9ydCBjbGFzcyBJbmZyYUlhbVJvbGUgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICAgKiBUaGUgQVJOIG9mIHRoZSBJQU0gcm9sZSBmb3IgdGhlIGluZnJhc3RydWN0dXJlIGFjY291bnQuXG4gICAgICovXG4gIHJlYWRvbmx5IHJvbGVBcm46IHN0cmluZztcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgbmFtZTogc3RyaW5nLCBwcm9wczogSW5mcmFJYW1Sb2xlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgbmFtZSk7XG5cbiAgICBjb25zdCByb2xlID0gbmV3IGlhbS5Sb2xlKHRoaXMsICdJbmZyYUlhbVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uQWNjb3VudFJvb3RQcmluY2lwYWwoKSxcbiAgICAgIHJvbGVOYW1lOiBwcm9wcy5yb2xlTmFtZSA/PyAnQ3Jvc3NBY2NvdW50UmVwb3NpdG9yeUNvbnRyaWJ1dG9yUm9sZScsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBJQU0gcm9sZSBmb3IgRGF0YUJyZXcgQ0lDRCBpbiB0aGUgaW5mcmFzdHJ1Y3R1cmUgYWNjb3VudC4nLFxuICAgIH0pO1xuICAgIHJvbGUuYWRkVG9Qb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnQ29kZUNvbW1pdFBlcm1pc3Npb25zJyxcbiAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgJ2NvZGVjb21taXQ6QmF0Y2hHZXQqJyxcbiAgICAgICAgJ2NvZGVjb21taXQ6Q3JlYXRlKicsXG4gICAgICAgICdjb2RlY29tbWl0OkRlbGV0ZUJyYW5jaCcsXG4gICAgICAgICdjb2RlY29tbWl0OkdldConLFxuICAgICAgICAnY29kZWNvbW1pdDpMaXN0KicsXG4gICAgICAgICdjb2RlY29tbWl0OkRlc2NyaWJlKicsXG4gICAgICAgICdjb2RlY29tbWl0OlB1dConLFxuICAgICAgICAnY29kZWNvbW1pdDpQb3N0KicsXG4gICAgICAgICdjb2RlY29tbWl0Ok1lcmdlKicsXG4gICAgICAgICdjb2RlY29tbWl0OlRlc3QqJyxcbiAgICAgICAgJ2NvZGVjb21taXQ6VXBkYXRlKicsXG4gICAgICAgICdjb2RlY29tbWl0OkdpdFB1bGwnLFxuICAgICAgICAnY29kZWNvbW1pdDpHaXRQdXNoJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgYGFybjoke2Nkay5Bd3MuUEFSVElUSU9OfTpjb2RlY29tbWl0OiR7Y2RrLkF3cy5SRUdJT059OiR7Y2RrLkF3cy5BQ0NPVU5UX0lEfTpEYXRhQnJldy1SZWNpcGVzLVJlcG9gLFxuICAgICAgXSxcbiAgICB9KSk7XG4gICAgcm9sZS5hZGRUb1BvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6ICdDb2RlQ29tbWl0TGlzdFJlcG9zUGVybWlzc2lvbicsXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgICdjb2RlY29tbWl0Okxpc3RSZXBvc2l0b3JpZXMnLFxuICAgICAgXSxcbiAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgfSkpO1xuICAgIHRoaXMucm9sZUFybiA9IHJvbGUucm9sZUFybjtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvZGVQaXBlbGluZUlhbVJvbGVQcm9wcyB7XG4gIC8qKlxuICAgICAqIFRoZSBBUk4gb2YgdGhlIFMzIGJ1Y2tldCB3aGVyZSB5b3Ugc3RvcmUgeW91ciBhcnRpZmFjdHMuXG4gICAgICovXG4gIHJlYWRvbmx5IGJ1Y2tldEFybjogc3RyaW5nO1xuICAvKipcbiAgICAgKiBUaGUgQVJOIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24gZm9yIHRoZSBwcmUtcHJvZHVjdGlvbiBhY2NvdW50LlxuICAgICAqL1xuICByZWFkb25seSBwcmVwcm9kdWN0aW9uTGFtYmRhQXJuOiBzdHJpbmc7XG4gIC8qKlxuICAgICAqIFRoZSBBUk4gb2YgdGhlIExhbWJkYSBmdW5jdGlvbiBmb3IgdGhlIHByb2R1Y3Rpb24gYWNjb3VudC5cbiAgICAgKi9cbiAgcmVhZG9ubHkgcHJvZHVjdGlvbkxhbWJkYUFybjogc3RyaW5nO1xuICAvKipcbiAgICAgKiBUaGUgcm9sZSBuYW1lIGZvciB0aGUgQ29kZVBpcGVsaW5lIENJQ0QgcGlwZWxpbmUuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCAnRGF0YUJyZXctUmVjaXBlLVBpcGVsaW5lLVJvbGUnXG4gICAgICovXG4gIHJlYWRvbmx5IHJvbGVOYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgQ29kZVBpcGVsaW5lSWFtUm9sZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgICAqIFRoZSBBUk4gb2YgdGhlIElBTSByb2xlIGZvciB0aGUgQ29kZVBpcGVsaW5lIENJQ0QgcGlwZWxpbmUuXG4gICAgICovXG4gIHJlYWRvbmx5IHJvbGVBcm46IHN0cmluZztcbiAgLyoqXG4gICAgICogVGhlIHJlcHJlc2VudGF0aXZlIG9mIHRoZSBJQU0gcm9sZSBmb3IgdGhlIENvZGVQaXBlbGluZSBDSUNEIHBpcGVsaW5lLlxuICAgICAqL1xuICByZWFkb25seSByb2xlOiBpYW0uUm9sZTtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgbmFtZTogc3RyaW5nLCBwcm9wczogQ29kZVBpcGVsaW5lSWFtUm9sZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIG5hbWUpO1xuICAgIGNvbnN0IHJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgJ0NvZGVQaXBlbGluZUlhbVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uQ29tcG9zaXRlUHJpbmNpcGFsKFxuICAgICAgICBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2NvZGVwaXBlbGluZS5hbWF6b25hd3MuY29tJyksXG4gICAgICAgIG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgICksXG4gICAgICByb2xlTmFtZTogcHJvcHMucm9sZU5hbWUgPz8gJ0RhdGFCcmV3LVJlY2lwZS1QaXBlbGluZS1Sb2xlJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIElBTSByb2xlIGZvciB0aGUgQ29kZVBpcGVsaW5lIENJQ0QgcGlwZWxpbmUgaW4gdGhlIGluZnJhc3RydWN0dXJlIGFjY291bnQuJyxcbiAgICB9KTtcbiAgICAvLyBDb2RlRGVwbG95IHBlcm1pc3Npb25zXG4gICAgcm9sZS5hZGRUb1BvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6ICdDb2RlRGVwbG95UGVybWlzc2lvbnMnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnY29kZWRlcGxveTpDcmVhdGVEZXBsb3ltZW50JyxcbiAgICAgICAgJ2NvZGVkZXBsb3k6R2V0QXBwbGljYXRpb25SZXZpc2lvbicsXG4gICAgICAgICdjb2RlZGVwbG95OkdldERlcGxveW1lbnQnLFxuICAgICAgICAnY29kZWRlcGxveTpHZXREZXBsb3ltZW50Q29uZmlnJyxcbiAgICAgICAgJ2NvZGVkZXBsb3k6UmVnaXN0ZXJBcHBsaWNhdGlvblJldmlzaW9uJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgYGFybjoke2Nkay5Bd3MuUEFSVElUSU9OfTpjb2RlZGVwbG95OiR7Y2RrLkF3cy5SRUdJT059OiR7Y2RrLkF3cy5BQ0NPVU5UX0lEfTpkZXBsb3ltZW50Z3JvdXA6RGF0YUJyZXctUmVjaXBlLUFwcGxpY2F0aW9uKmAsXG4gICAgICAgIGBhcm46JHtjZGsuQXdzLlBBUlRJVElPTn06Y29kZWRlcGxveToke2Nkay5Bd3MuUkVHSU9OfToke2Nkay5Bd3MuQUNDT1VOVF9JRH06YXBwbGljYXRpb246RGF0YUJyZXctUmVjaXBlLUFwcGxpY2F0aW9uYCxcbiAgICAgIF0sXG4gICAgfSkpO1xuICAgIC8vIENvZGVDb21taXQgcGVybWlzc2lvbnNcbiAgICByb2xlLmFkZFRvUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogJ0NvZGVDb21taXRQZXJtaXNzaW9ucycsXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgICdjb2RlY29tbWl0OkdldEJyYW5jaCcsXG4gICAgICAgICdjb2RlY29tbWl0OkdldENvbW1pdCcsXG4gICAgICAgICdjb2RlY29tbWl0OkdldFVwbG9hZEFyY2hpdmVTdGF0dXMnLFxuICAgICAgICAnY29kZWNvbW1pdDpVcGxvYWRBcmNoaXZlJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgYGFybjoke2Nkay5Bd3MuUEFSVElUSU9OfTpjb2RlY29tbWl0OiR7Y2RrLkF3cy5SRUdJT059OiR7Y2RrLkF3cy5BQ0NPVU5UX0lEfTpEYXRhQnJldy1SZWNpcGVzLVJlcG9gLFxuICAgICAgXSxcbiAgICB9KSk7XG4gICAgLy8gUzMgcGVybWlzc2lvbnNcbiAgICByb2xlLmFkZFRvUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogJ1MzUGVybWlzc2lvbnMnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnczM6R2V0T2JqZWN0JyxcbiAgICAgICAgJ3MzOlB1dE9iamVjdCcsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbcHJvcHMuYnVja2V0QXJuXSxcbiAgICB9KSk7XG4gICAgLy8gTGFtYmRhIHBlcm1pc3Npb25zXG4gICAgcm9sZS5hZGRUb1BvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6ICdMYW1iZGFQZXJtaXNzaW9ucycsXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgICdsYW1iZGE6SW52b2tlRnVuY3Rpb24nLFxuICAgICAgXSxcbiAgICAgIHJlc291cmNlczogW3Byb3BzLnByZXByb2R1Y3Rpb25MYW1iZGFBcm4sIHByb3BzLnByb2R1Y3Rpb25MYW1iZGFBcm5dLFxuICAgIH0pKTtcbiAgICByb2xlLmFkZFRvUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogJ0Fzc3VtUm9sZVBlcm1pc3Npb25zJyxcbiAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgJ3N0czpBc3N1bWVSb2xlJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFtyb2xlLnJvbGVBcm5dLFxuICAgIH0pKTtcbiAgICB0aGlzLnJvbGUgPSByb2xlO1xuICAgIHRoaXMucm9sZUFybiA9IHJvbGUucm9sZUFybjtcbiAgfVxufSJdfQ==