aws-ddk-core
Version:
The AWS DataOps Development Kit is an open source development framework for customers that build data workflows and modern data architecture on AWS.
223 lines • 33.1 kB
JavaScript
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MWAAEnvironment = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("aws-cdk-lib");
const ec2 = require("aws-cdk-lib/aws-ec2");
const iam = require("aws-cdk-lib/aws-iam");
const mwaa = require("aws-cdk-lib/aws-mwaa");
const s3deploy = require("aws-cdk-lib/aws-s3-deployment");
const constructs_1 = require("constructs");
const s3_factory_1 = require("./s3-factory");
class MWAAEnvironment extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
this.dagProcessingLogs = props.dagProcessingLogs ?? "INFO";
this.schedulerLogsLevel = props.schedulerLogsLevel ?? "INFO";
this.taskLogsLevel = props.taskLogsLevel ?? "INFO";
this.workerLogsLevel = props.workerLogsLevel ?? "INFO";
this.webserverLogsLevel = props.webserverLogsLevel ?? "INFO";
this.dagS3Path = props.dagS3Path ?? "dags";
if (props.vpcId) {
this.vpc = ec2.Vpc.fromLookup(scope, `${props.name} VPC`, { vpcId: props.vpcId });
}
else if (props.vpcCidr) {
this.vpc = this.createVpc(scope, props.name, props.vpcCidr);
}
else {
throw new Error("One of 'vpcId' or 'vpcCidr' must be provided");
}
const securityGroup = new ec2.SecurityGroup(scope, `${props.name} Security Group`, {
securityGroupName: `${props.name} Security Group`,
description: "Security group with a self-referencing inbound rule.",
vpc: this.vpc,
});
securityGroup.addIngressRule(securityGroup, ec2.Port.allTraffic(), "Self referencing rule");
if (props.s3Bucket) {
this.s3Bucket = props.s3Bucket;
}
else {
this.s3Bucket = s3_factory_1.S3Factory.bucket(this, `${props.name} Environment Bucket`, {
versioned: true,
});
}
if (props.dagFiles) {
var sources = [];
props.dagFiles.forEach((location) => {
sources.push(s3deploy.Source.asset(location));
});
new s3deploy.BucketDeployment(this, `${props.name} Deploy Dag Files`, {
sources: sources,
destinationBucket: this.s3Bucket,
destinationKeyPrefix: this.dagS3Path,
});
}
if (props.pluginFile) {
if (props.pluginsS3Path) {
this.pluginFile = new s3deploy.BucketDeployment(this, `${props.name} Deploy Plugin File`, {
sources: [s3deploy.Source.asset(props.pluginFile)],
destinationBucket: this.s3Bucket,
destinationKeyPrefix: props.pluginsS3Path,
});
}
else {
throw new Error("'pluginsS3Path' must be specified if a 'pluginFile' is specified.");
}
}
if (props.requirementsFile) {
if (props.requirementsS3Path) {
this.pluginFile = new s3deploy.BucketDeployment(this, `${props.name} Deploy Requirements File`, {
sources: [
s3deploy.Source.asset(props.requirementsFile.split("/").slice(0, -1).join("/"), {
exclude: ["**", `!${props.requirementsFile.split("/")[-1]}`],
}),
],
destinationBucket: this.s3Bucket,
destinationKeyPrefix: props.requirementsS3Path,
});
}
else {
throw new Error("'requirementsS3Path' must be specified if a 'requirementsFile' is specified.");
}
}
const mwaaExecutionRole = new iam.Role(scope, `${props.name} MWAA Execution Role`, {
assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal("airflow.amazonaws.com"), new iam.ServicePrincipal("airflow-env.amazonaws.com")),
path: "/service-role/",
});
mwaaExecutionRole.addManagedPolicy(new iam.ManagedPolicy(this, `${props.name} MWAA Execution Policy`, {
statements: [
new iam.PolicyStatement({
actions: ["airflow:PublishMetrics"],
resources: [
`arn:aws:airflow:${cdk.Stack.of(scope).region}:${cdk.Stack.of(scope).account}:environment/${props.name}`,
],
}),
new iam.PolicyStatement({
effect: iam.Effect.DENY,
actions: ["s3:ListAllMyBuckets"],
resources: [this.s3Bucket.bucketArn, `${this.s3Bucket.bucketArn}/*`],
}),
new iam.PolicyStatement({
actions: ["s3:GetObject*", "s3:GetBucket*", "s3:List*"],
resources: [this.s3Bucket.bucketArn, `${this.s3Bucket.bucketArn}/*`],
}),
new iam.PolicyStatement({
actions: ["logs:DescribeLogGroups"],
resources: ["*"],
}),
new iam.PolicyStatement({
actions: [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:GetLogRecord",
"logs:GetLogGroupFields",
"logs:GetQueryResults",
"logs:DescribeLogGroups",
],
resources: [
`arn:aws:logs:${cdk.Stack.of(scope).region}:${cdk.Stack.of(scope).account}:log-group:airflow-${cdk.Stack.of(scope).stackName}*`,
],
}),
new iam.PolicyStatement({
actions: ["cloudwatch:PutMetricData"],
resources: ["*"],
}),
new iam.PolicyStatement({
actions: [
"sqs:ChangeMessageVisibility",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage",
"sqs:SendMessage",
],
resources: [`arn:aws:sqs:${cdk.Stack.of(scope).region}:*:airflow-celery-*`],
}),
new iam.PolicyStatement({
actions: ["kms:Decrypt", "kms:DescribeKey", "kms:GenerateDataKey*", "kms:Encrypt"],
notResources: [`arn:aws:kms:*:${cdk.Stack.of(scope).account}:key/*`],
conditions: {
StringLike: {
"kms:ViaService": [`sqs.${cdk.Stack.of(scope).region}.amazonaws.com`],
},
},
}),
],
}));
if (props.additionalPolicyStatements) {
props.additionalPolicyStatements.forEach((statement) => {
mwaaExecutionRole.addToPolicy(statement);
});
}
this.mwaaEnvironment = new mwaa.CfnEnvironment(this, `${props.name} MWAA Environment`, {
sourceBucketArn: this.s3Bucket.bucketArn,
executionRoleArn: mwaaExecutionRole.roleArn,
dagS3Path: this.dagS3Path,
networkConfiguration: {
securityGroupIds: [securityGroup.securityGroupId],
subnetIds: [
this.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds[0],
this.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds[1],
],
},
webserverAccessMode: "PUBLIC_ONLY",
loggingConfiguration: {
dagProcessingLogs: {
enabled: true,
logLevel: this.dagProcessingLogs,
},
schedulerLogs: {
enabled: true,
logLevel: this.schedulerLogsLevel,
},
taskLogs: {
enabled: true,
logLevel: this.taskLogsLevel,
},
webserverLogs: {
enabled: true,
logLevel: this.webserverLogsLevel,
},
workerLogs: {
enabled: false,
logLevel: this.workerLogsLevel,
},
},
...props,
});
}
createVpc(scope, environmentName, vpcCidr) {
const resourceName = `${environmentName}-MWAA`;
const vpcCIDRMask = +vpcCidr.split("/")[1];
if (vpcCIDRMask > 20 || vpcCIDRMask < 16) {
throw new Error("Vpc Cidr Range must of size >=16 and <=20");
}
const subnetCIDRMask = vpcCIDRMask + 4;
const vpc = new ec2.Vpc(scope, `${resourceName} Vpc`, {
ipAddresses: ec2.IpAddresses.cidr(vpcCidr),
enableDnsSupport: true,
enableDnsHostnames: true,
vpcName: resourceName,
subnetConfiguration: [
{
name: "Public",
subnetType: ec2.SubnetType.PUBLIC,
cidrMask: subnetCIDRMask,
},
{
name: "Private",
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
cidrMask: subnetCIDRMask,
},
],
});
return vpc;
}
}
exports.MWAAEnvironment = MWAAEnvironment;
_a = JSII_RTTI_SYMBOL_1;
MWAAEnvironment[_a] = { fqn: "aws-ddk-core.MWAAEnvironment", version: "1.4.1" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXdhYS1lbnZpcm9ubWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL213YWEtZW52aXJvbm1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxtQ0FBbUM7QUFDbkMsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQyw2Q0FBNkM7QUFFN0MsMERBQTBEO0FBQzFELDJDQUF1QztBQUV2Qyw2Q0FBeUM7QUFxRHpDLE1BQWEsZUFBZ0IsU0FBUSxzQkFBUztJQVk1QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTJCO1FBQ25FLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxNQUFNLENBQUM7UUFDM0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxNQUFNLENBQUM7UUFDN0QsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxJQUFJLE1BQU0sQ0FBQztRQUNuRCxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQyxlQUFlLElBQUksTUFBTSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUMsa0JBQWtCLElBQUksTUFBTSxDQUFDO1FBQzdELElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUM7UUFFM0MsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFO1lBQ2YsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxNQUFNLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7U0FDbkY7YUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDeEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM3RDthQUFNO1lBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1NBQ2pFO1FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLGlCQUFpQixFQUFFO1lBQ2pGLGlCQUFpQixFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksaUJBQWlCO1lBQ2pELFdBQVcsRUFBRSxzREFBc0Q7WUFDbkUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1NBQ2QsQ0FBQyxDQUFDO1FBQ0gsYUFBYSxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBRTVGLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRTtZQUNsQixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7U0FDaEM7YUFBTTtZQUNMLElBQUksQ0FBQyxRQUFRLEdBQUcsc0JBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUkscUJBQXFCLEVBQUU7Z0JBQ3pFLFNBQVMsRUFBRSxJQUFJO2FBQ2hCLENBQUMsQ0FBQztTQUNKO1FBRUQsSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFO1lBQ2xCLElBQUksT0FBTyxHQUF1QixFQUFFLENBQUM7WUFDckMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtnQkFDbEMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ2hELENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksbUJBQW1CLEVBQUU7Z0JBQ3BFLE9BQU8sRUFBRSxPQUFPO2dCQUNoQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUTtnQkFDaEMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLFNBQVM7YUFDckMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLEtBQUssQ0FBQyxVQUFVLEVBQUU7WUFDcEIsSUFBSSxLQUFLLENBQUMsYUFBYSxFQUFFO2dCQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLHFCQUFxQixFQUFFO29CQUN4RixPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ2xELGlCQUFpQixFQUFFLElBQUksQ0FBQyxRQUFRO29CQUNoQyxvQkFBb0IsRUFBRSxLQUFLLENBQUMsYUFBYTtpQkFDMUMsQ0FBQyxDQUFDO2FBQ0o7aUJBQU07Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO2FBQ3RGO1NBQ0Y7UUFFRCxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRTtZQUMxQixJQUFJLEtBQUssQ0FBQyxrQkFBa0IsRUFBRTtnQkFDNUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSwyQkFBMkIsRUFBRTtvQkFDOUYsT0FBTyxFQUFFO3dCQUNQLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTs0QkFDOUUsT0FBTyxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7eUJBQzdELENBQUM7cUJBQ0g7b0JBQ0QsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVE7b0JBQ2hDLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxrQkFBa0I7aUJBQy9DLENBQUMsQ0FBQzthQUNKO2lCQUFNO2dCQUNMLE1BQU0sSUFBSSxLQUFLLENBQUMsOEVBQThFLENBQUMsQ0FBQzthQUNqRztTQUNGO1FBRUQsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksc0JBQXNCLEVBQUU7WUFDakYsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGtCQUFrQixDQUNuQyxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyx1QkFBdUIsQ0FBQyxFQUNqRCxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQywyQkFBMkIsQ0FBQyxDQUN0RDtZQUNELElBQUksRUFBRSxnQkFBZ0I7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsaUJBQWlCLENBQUMsZ0JBQWdCLENBQ2hDLElBQUksR0FBRyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSx3QkFBd0IsRUFBRTtZQUNqRSxVQUFVLEVBQUU7Z0JBQ1YsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQztvQkFDbkMsU0FBUyxFQUFFO3dCQUNULG1CQUFtQixHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxnQkFBZ0IsS0FBSyxDQUFDLElBQUksRUFBRTtxQkFDekc7aUJBQ0YsQ0FBQztnQkFDRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUk7b0JBQ3ZCLE9BQU8sRUFBRSxDQUFDLHFCQUFxQixDQUFDO29CQUNoQyxTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxJQUFJLENBQUM7aUJBQ3JFLENBQUM7Z0JBQ0YsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQyxlQUFlLEVBQUUsZUFBZSxFQUFFLFVBQVUsQ0FBQztvQkFDdkQsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsSUFBSSxDQUFDO2lCQUNyRSxDQUFDO2dCQUNGLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztvQkFDdEIsT0FBTyxFQUFFLENBQUMsd0JBQXdCLENBQUM7b0JBQ25DLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztpQkFDakIsQ0FBQztnQkFDRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3RCLE9BQU8sRUFBRTt3QkFDUCxzQkFBc0I7d0JBQ3RCLHFCQUFxQjt3QkFDckIsbUJBQW1CO3dCQUNuQixtQkFBbUI7d0JBQ25CLG1CQUFtQjt3QkFDbkIsd0JBQXdCO3dCQUN4QixzQkFBc0I7d0JBQ3RCLHdCQUF3QjtxQkFDekI7b0JBQ0QsU0FBUyxFQUFFO3dCQUNULGdCQUFnQixHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxzQkFDdkUsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsU0FDdEIsR0FBRztxQkFDSjtpQkFDRixDQUFDO2dCQUNGLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztvQkFDdEIsT0FBTyxFQUFFLENBQUMsMEJBQTBCLENBQUM7b0JBQ3JDLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztpQkFDakIsQ0FBQztnQkFDRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3RCLE9BQU8sRUFBRTt3QkFDUCw2QkFBNkI7d0JBQzdCLG1CQUFtQjt3QkFDbkIsd0JBQXdCO3dCQUN4QixpQkFBaUI7d0JBQ2pCLG9CQUFvQjt3QkFDcEIsaUJBQWlCO3FCQUNsQjtvQkFDRCxTQUFTLEVBQUUsQ0FBQyxlQUFlLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0scUJBQXFCLENBQUM7aUJBQzVFLENBQUM7Z0JBQ0YsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsc0JBQXNCLEVBQUUsYUFBYSxDQUFDO29CQUNsRixZQUFZLEVBQUUsQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxRQUFRLENBQUM7b0JBQ3BFLFVBQVUsRUFBRTt3QkFDVixVQUFVLEVBQUU7NEJBQ1YsZ0JBQWdCLEVBQUUsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sZ0JBQWdCLENBQUM7eUJBQ3RFO3FCQUNGO2lCQUNGLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxLQUFLLENBQUMsMEJBQTBCLEVBQUU7WUFDcEMsS0FBSyxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO2dCQUNyRCxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDM0MsQ0FBQyxDQUFDLENBQUM7U0FDSjtRQUVELElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLG1CQUFtQixFQUFFO1lBQ3JGLGVBQWUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVM7WUFDeEMsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsT0FBTztZQUMzQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsb0JBQW9CLEVBQUU7Z0JBQ3BCLGdCQUFnQixFQUFFLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQztnQkFDakQsU0FBUyxFQUFFO29CQUNULElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQ3ZGLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7aUJBQ3hGO2FBQ0Y7WUFDRCxtQkFBbUIsRUFBRSxhQUFhO1lBQ2xDLG9CQUFvQixFQUFFO2dCQUNwQixpQkFBaUIsRUFBRTtvQkFDakIsT0FBTyxFQUFFLElBQUk7b0JBQ2IsUUFBUSxFQUFFLElBQUksQ0FBQyxpQkFBaUI7aUJBQ2pDO2dCQUNELGFBQWEsRUFBRTtvQkFDYixPQUFPLEVBQUUsSUFBSTtvQkFDYixRQUFRLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtpQkFDbEM7Z0JBQ0QsUUFBUSxFQUFFO29CQUNSLE9BQU8sRUFBRSxJQUFJO29CQUNiLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYTtpQkFDN0I7Z0JBQ0QsYUFBYSxFQUFFO29CQUNiLE9BQU8sRUFBRSxJQUFJO29CQUNiLFFBQVEsRUFBRSxJQUFJLENBQUMsa0JBQWtCO2lCQUNsQztnQkFDRCxVQUFVLEVBQUU7b0JBQ1YsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsUUFBUSxFQUFFLElBQUksQ0FBQyxlQUFlO2lCQUMvQjthQUNGO1lBQ0QsR0FBRyxLQUFLO1NBQ1QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELFNBQVMsQ0FBQyxLQUFnQixFQUFFLGVBQXVCLEVBQUUsT0FBZTtRQUNsRSxNQUFNLFlBQVksR0FBRyxHQUFHLGVBQWUsT0FBTyxDQUFDO1FBQy9DLE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQyxJQUFJLFdBQVcsR0FBRyxFQUFFLElBQUksV0FBVyxHQUFHLEVBQUUsRUFBRTtZQUN4QyxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7U0FDOUQ7UUFDRCxNQUFNLGNBQWMsR0FBRyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxZQUFZLE1BQU0sRUFBRTtZQUNwRCxXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQzFDLGdCQUFnQixFQUFFLElBQUk7WUFDdEIsa0JBQWtCLEVBQUUsSUFBSTtZQUN4QixPQUFPLEVBQUUsWUFBWTtZQUNyQixtQkFBbUIsRUFBRTtnQkFDbkI7b0JBQ0UsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTTtvQkFDakMsUUFBUSxFQUFFLGNBQWM7aUJBQ3pCO2dCQUNEO29CQUNFLElBQUksRUFBRSxTQUFTO29CQUNmLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLG1CQUFtQjtvQkFDOUMsUUFBUSxFQUFFLGNBQWM7aUJBQ3pCO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7O0FBck9ILDBDQXNPQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGVjMiBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgKiBhcyBtd2FhIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbXdhYVwiO1xuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0ICogYXMgczNkZXBsb3kgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zMy1kZXBsb3ltZW50XCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5pbXBvcnQgeyBTM0ZhY3RvcnkgfSBmcm9tIFwiLi9zMy1mYWN0b3J5XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTVdBQUVudmlyb25tZW50UHJvcHMgZXh0ZW5kcyBtd2FhLkNmbkVudmlyb25tZW50UHJvcHMge1xuICAvKipcbiAgICogTG9nIGxldmVsIGZvciBEYWdQcm9jZXNzaW5nXG4gICAqL1xuICByZWFkb25seSBkYWdQcm9jZXNzaW5nTG9ncz86IHN0cmluZztcbiAgLyoqXG4gICAqIExvZyBsZXZlbCBmb3IgU2NoZWR1bGVyTG9nc1xuICAgKi9cbiAgcmVhZG9ubHkgc2NoZWR1bGVyTG9nc0xldmVsPzogc3RyaW5nO1xuICAvKipcbiAgICogTG9nIGxldmVsIGZvciBUYXNrTG9nc1xuICAgKi9cbiAgcmVhZG9ubHkgdGFza0xvZ3NMZXZlbD86IHN0cmluZztcbiAgLyoqXG4gICAqIExvZyBsZXZlbCBmb3IgV29ya2VyTG9nc1xuICAgKi9cbiAgcmVhZG9ubHkgd29ya2VyTG9nc0xldmVsPzogc3RyaW5nO1xuICAvKipcbiAgICogTG9nIGxldmVsIGZvciBXZWJzZXJ2ZXJMb2dzXG4gICAqL1xuICByZWFkb25seSB3ZWJzZXJ2ZXJMb2dzTGV2ZWw/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFeGlzdGluZyB2cGMgaWRcbiAgICovXG4gIHJlYWRvbmx5IHZwY0lkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIElQIHJhbmdlIChDSURSIG5vdGF0aW9uKSBmb3IgdGhpcyBWUENcbiAgICovXG4gIHJlYWRvbmx5IHZwY0NpZHI/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBTMyBCdWNrZXRcbiAgICovXG4gIHJlYWRvbmx5IHMzQnVja2V0PzogczMuSUJ1Y2tldDtcbiAgLyoqXG4gICAqIEZpbGUocykgdG8gYmUgdXBsb2FkZWQgdG8gZGFncyBsb2NhdGlvbiBpbiBzMyBidWNrZXQuXG4gICAqL1xuICByZWFkb25seSBkYWdGaWxlcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogUmVxdWlyZW1lbnRzIGZpbGUgdG8gYmUgdXBsb2FkZWQgdG8gcGx1Z2luIHBhdGggaW4gUzMuICdyZXF1aXJlbWVudHNTM1BhdGgnIG11c3QgYmUgc3BlY2lmaWVkIGFzIHdlbGwuXG4gICAqL1xuICByZWFkb25seSByZXF1aXJlbWVudHNGaWxlPzogc3RyaW5nO1xuICAvKipcbiAgICogUGx1Z2luIGZpbGUgdG8gYmUgdXBsb2FkZWQgdG8gcGx1Z2luIHBhdGggaW4gUzMuICdwbHVnaW5zUzNQYXRoJyBtdXN0IGJlIHNwZWNpZmllZCBhcyB3ZWxsLlxuICAgKi9cbiAgcmVhZG9ubHkgcGx1Z2luRmlsZT86IHN0cmluZztcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgcG9saWN5IHN0YXRlbWVudHMgdG8gYWRkIHRvIHRoZSBhaXJmbG93IGV4ZWN1dGlvbiByb2xlXG4gICAqL1xuICByZWFkb25seSBhZGRpdGlvbmFsUG9saWN5U3RhdGVtZW50cz86IGlhbS5Qb2xpY3lTdGF0ZW1lbnRbXTtcbn1cblxuZXhwb3J0IGNsYXNzIE1XQUFFbnZpcm9ubWVudCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHJlYWRvbmx5IGRhZ1Byb2Nlc3NpbmdMb2dzOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNjaGVkdWxlckxvZ3NMZXZlbDogc3RyaW5nO1xuICByZWFkb25seSB0YXNrTG9nc0xldmVsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHdvcmtlckxvZ3NMZXZlbDogc3RyaW5nO1xuICByZWFkb25seSB3ZWJzZXJ2ZXJMb2dzTGV2ZWw6IHN0cmluZztcbiAgcmVhZG9ubHkgdnBjOiBlYzIuSVZwYztcbiAgcmVhZG9ubHkgczNCdWNrZXQ6IHMzLklCdWNrZXQ7XG4gIHJlYWRvbmx5IG13YWFFbnZpcm9ubWVudDogbXdhYS5DZm5FbnZpcm9ubWVudDtcbiAgcmVhZG9ubHkgZGFnUzNQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBsdWdpbkZpbGU/OiBzM2RlcGxveS5CdWNrZXREZXBsb3ltZW50O1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBNV0FBRW52aXJvbm1lbnRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLmRhZ1Byb2Nlc3NpbmdMb2dzID0gcHJvcHMuZGFnUHJvY2Vzc2luZ0xvZ3MgPz8gXCJJTkZPXCI7XG4gICAgdGhpcy5zY2hlZHVsZXJMb2dzTGV2ZWwgPSBwcm9wcy5zY2hlZHVsZXJMb2dzTGV2ZWwgPz8gXCJJTkZPXCI7XG4gICAgdGhpcy50YXNrTG9nc0xldmVsID0gcHJvcHMudGFza0xvZ3NMZXZlbCA/PyBcIklORk9cIjtcbiAgICB0aGlzLndvcmtlckxvZ3NMZXZlbCA9IHByb3BzLndvcmtlckxvZ3NMZXZlbCA/PyBcIklORk9cIjtcbiAgICB0aGlzLndlYnNlcnZlckxvZ3NMZXZlbCA9IHByb3BzLndlYnNlcnZlckxvZ3NMZXZlbCA/PyBcIklORk9cIjtcbiAgICB0aGlzLmRhZ1MzUGF0aCA9IHByb3BzLmRhZ1MzUGF0aCA/PyBcImRhZ3NcIjtcblxuICAgIGlmIChwcm9wcy52cGNJZCkge1xuICAgICAgdGhpcy52cGMgPSBlYzIuVnBjLmZyb21Mb29rdXAoc2NvcGUsIGAke3Byb3BzLm5hbWV9IFZQQ2AsIHsgdnBjSWQ6IHByb3BzLnZwY0lkIH0pO1xuICAgIH0gZWxzZSBpZiAocHJvcHMudnBjQ2lkcikge1xuICAgICAgdGhpcy52cGMgPSB0aGlzLmNyZWF0ZVZwYyhzY29wZSwgcHJvcHMubmFtZSwgcHJvcHMudnBjQ2lkcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk9uZSBvZiAndnBjSWQnIG9yICd2cGNDaWRyJyBtdXN0IGJlIHByb3ZpZGVkXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlY3VyaXR5R3JvdXAgPSBuZXcgZWMyLlNlY3VyaXR5R3JvdXAoc2NvcGUsIGAke3Byb3BzLm5hbWV9IFNlY3VyaXR5IEdyb3VwYCwge1xuICAgICAgc2VjdXJpdHlHcm91cE5hbWU6IGAke3Byb3BzLm5hbWV9IFNlY3VyaXR5IEdyb3VwYCxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlNlY3VyaXR5IGdyb3VwIHdpdGggYSBzZWxmLXJlZmVyZW5jaW5nIGluYm91bmQgcnVsZS5cIixcbiAgICAgIHZwYzogdGhpcy52cGMsXG4gICAgfSk7XG4gICAgc2VjdXJpdHlHcm91cC5hZGRJbmdyZXNzUnVsZShzZWN1cml0eUdyb3VwLCBlYzIuUG9ydC5hbGxUcmFmZmljKCksIFwiU2VsZiByZWZlcmVuY2luZyBydWxlXCIpO1xuXG4gICAgaWYgKHByb3BzLnMzQnVja2V0KSB7XG4gICAgICB0aGlzLnMzQnVja2V0ID0gcHJvcHMuczNCdWNrZXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuczNCdWNrZXQgPSBTM0ZhY3RvcnkuYnVja2V0KHRoaXMsIGAke3Byb3BzLm5hbWV9IEVudmlyb25tZW50IEJ1Y2tldGAsIHtcbiAgICAgICAgdmVyc2lvbmVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmRhZ0ZpbGVzKSB7XG4gICAgICB2YXIgc291cmNlczogczNkZXBsb3kuSVNvdXJjZVtdID0gW107XG4gICAgICBwcm9wcy5kYWdGaWxlcy5mb3JFYWNoKChsb2NhdGlvbikgPT4ge1xuICAgICAgICBzb3VyY2VzLnB1c2goczNkZXBsb3kuU291cmNlLmFzc2V0KGxvY2F0aW9uKSk7XG4gICAgICB9KTtcbiAgICAgIG5ldyBzM2RlcGxveS5CdWNrZXREZXBsb3ltZW50KHRoaXMsIGAke3Byb3BzLm5hbWV9IERlcGxveSBEYWcgRmlsZXNgLCB7XG4gICAgICAgIHNvdXJjZXM6IHNvdXJjZXMsXG4gICAgICAgIGRlc3RpbmF0aW9uQnVja2V0OiB0aGlzLnMzQnVja2V0LFxuICAgICAgICBkZXN0aW5hdGlvbktleVByZWZpeDogdGhpcy5kYWdTM1BhdGgsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMucGx1Z2luRmlsZSkge1xuICAgICAgaWYgKHByb3BzLnBsdWdpbnNTM1BhdGgpIHtcbiAgICAgICAgdGhpcy5wbHVnaW5GaWxlID0gbmV3IHMzZGVwbG95LkJ1Y2tldERlcGxveW1lbnQodGhpcywgYCR7cHJvcHMubmFtZX0gRGVwbG95IFBsdWdpbiBGaWxlYCwge1xuICAgICAgICAgIHNvdXJjZXM6IFtzM2RlcGxveS5Tb3VyY2UuYXNzZXQocHJvcHMucGx1Z2luRmlsZSldLFxuICAgICAgICAgIGRlc3RpbmF0aW9uQnVja2V0OiB0aGlzLnMzQnVja2V0LFxuICAgICAgICAgIGRlc3RpbmF0aW9uS2V5UHJlZml4OiBwcm9wcy5wbHVnaW5zUzNQYXRoLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIidwbHVnaW5zUzNQYXRoJyBtdXN0IGJlIHNwZWNpZmllZCBpZiBhICdwbHVnaW5GaWxlJyBpcyBzcGVjaWZpZWQuXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwcm9wcy5yZXF1aXJlbWVudHNGaWxlKSB7XG4gICAgICBpZiAocHJvcHMucmVxdWlyZW1lbnRzUzNQYXRoKSB7XG4gICAgICAgIHRoaXMucGx1Z2luRmlsZSA9IG5ldyBzM2RlcGxveS5CdWNrZXREZXBsb3ltZW50KHRoaXMsIGAke3Byb3BzLm5hbWV9IERlcGxveSBSZXF1aXJlbWVudHMgRmlsZWAsIHtcbiAgICAgICAgICBzb3VyY2VzOiBbXG4gICAgICAgICAgICBzM2RlcGxveS5Tb3VyY2UuYXNzZXQocHJvcHMucmVxdWlyZW1lbnRzRmlsZS5zcGxpdChcIi9cIikuc2xpY2UoMCwgLTEpLmpvaW4oXCIvXCIpLCB7XG4gICAgICAgICAgICAgIGV4Y2x1ZGU6IFtcIioqXCIsIGAhJHtwcm9wcy5yZXF1aXJlbWVudHNGaWxlLnNwbGl0KFwiL1wiKVstMV19YF0sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRlc3RpbmF0aW9uQnVja2V0OiB0aGlzLnMzQnVja2V0LFxuICAgICAgICAgIGRlc3RpbmF0aW9uS2V5UHJlZml4OiBwcm9wcy5yZXF1aXJlbWVudHNTM1BhdGgsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiJ3JlcXVpcmVtZW50c1MzUGF0aCcgbXVzdCBiZSBzcGVjaWZpZWQgaWYgYSAncmVxdWlyZW1lbnRzRmlsZScgaXMgc3BlY2lmaWVkLlwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtd2FhRXhlY3V0aW9uUm9sZSA9IG5ldyBpYW0uUm9sZShzY29wZSwgYCR7cHJvcHMubmFtZX0gTVdBQSBFeGVjdXRpb24gUm9sZWAsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5Db21wb3NpdGVQcmluY2lwYWwoXG4gICAgICAgIG5ldyBpYW0uU2VydmljZVByaW5jaXBhbChcImFpcmZsb3cuYW1hem9uYXdzLmNvbVwiKSxcbiAgICAgICAgbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKFwiYWlyZmxvdy1lbnYuYW1hem9uYXdzLmNvbVwiKSxcbiAgICAgICksXG4gICAgICBwYXRoOiBcIi9zZXJ2aWNlLXJvbGUvXCIsXG4gICAgfSk7XG4gICAgbXdhYUV4ZWN1dGlvblJvbGUuYWRkTWFuYWdlZFBvbGljeShcbiAgICAgIG5ldyBpYW0uTWFuYWdlZFBvbGljeSh0aGlzLCBgJHtwcm9wcy5uYW1lfSBNV0FBIEV4ZWN1dGlvbiBQb2xpY3lgLCB7XG4gICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXCJhaXJmbG93OlB1Ymxpc2hNZXRyaWNzXCJdLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICAgIGBhcm46YXdzOmFpcmZsb3c6JHtjZGsuU3RhY2sub2Yoc2NvcGUpLnJlZ2lvbn06JHtjZGsuU3RhY2sub2Yoc2NvcGUpLmFjY291bnR9OmVudmlyb25tZW50LyR7cHJvcHMubmFtZX1gLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuREVOWSxcbiAgICAgICAgICAgIGFjdGlvbnM6IFtcInMzOkxpc3RBbGxNeUJ1Y2tldHNcIl0sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLnMzQnVja2V0LmJ1Y2tldEFybiwgYCR7dGhpcy5zM0J1Y2tldC5idWNrZXRBcm59LypgXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXCJzMzpHZXRPYmplY3QqXCIsIFwiczM6R2V0QnVja2V0KlwiLCBcInMzOkxpc3QqXCJdLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbdGhpcy5zM0J1Y2tldC5idWNrZXRBcm4sIGAke3RoaXMuczNCdWNrZXQuYnVja2V0QXJufS8qYF0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogW1wibG9nczpEZXNjcmliZUxvZ0dyb3Vwc1wiXSxcbiAgICAgICAgICAgIHJlc291cmNlczogW1wiKlwiXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgIFwibG9nczpDcmVhdGVMb2dTdHJlYW1cIixcbiAgICAgICAgICAgICAgXCJsb2dzOkNyZWF0ZUxvZ0dyb3VwXCIsXG4gICAgICAgICAgICAgIFwibG9nczpQdXRMb2dFdmVudHNcIixcbiAgICAgICAgICAgICAgXCJsb2dzOkdldExvZ0V2ZW50c1wiLFxuICAgICAgICAgICAgICBcImxvZ3M6R2V0TG9nUmVjb3JkXCIsXG4gICAgICAgICAgICAgIFwibG9nczpHZXRMb2dHcm91cEZpZWxkc1wiLFxuICAgICAgICAgICAgICBcImxvZ3M6R2V0UXVlcnlSZXN1bHRzXCIsXG4gICAgICAgICAgICAgIFwibG9nczpEZXNjcmliZUxvZ0dyb3Vwc1wiLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgICBgYXJuOmF3czpsb2dzOiR7Y2RrLlN0YWNrLm9mKHNjb3BlKS5yZWdpb259OiR7Y2RrLlN0YWNrLm9mKHNjb3BlKS5hY2NvdW50fTpsb2ctZ3JvdXA6YWlyZmxvdy0ke1xuICAgICAgICAgICAgICAgIGNkay5TdGFjay5vZihzY29wZSkuc3RhY2tOYW1lXG4gICAgICAgICAgICAgIH0qYCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogW1wiY2xvdWR3YXRjaDpQdXRNZXRyaWNEYXRhXCJdLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbXCIqXCJdLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgXCJzcXM6Q2hhbmdlTWVzc2FnZVZpc2liaWxpdHlcIixcbiAgICAgICAgICAgICAgXCJzcXM6RGVsZXRlTWVzc2FnZVwiLFxuICAgICAgICAgICAgICBcInNxczpHZXRRdWV1ZUF0dHJpYnV0ZXNcIixcbiAgICAgICAgICAgICAgXCJzcXM6R2V0UXVldWVVcmxcIixcbiAgICAgICAgICAgICAgXCJzcXM6UmVjZWl2ZU1lc3NhZ2VcIixcbiAgICAgICAgICAgICAgXCJzcXM6U2VuZE1lc3NhZ2VcIixcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFtgYXJuOmF3czpzcXM6JHtjZGsuU3RhY2sub2Yoc2NvcGUpLnJlZ2lvbn06KjphaXJmbG93LWNlbGVyeS0qYF0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogW1wia21zOkRlY3J5cHRcIiwgXCJrbXM6RGVzY3JpYmVLZXlcIiwgXCJrbXM6R2VuZXJhdGVEYXRhS2V5KlwiLCBcImttczpFbmNyeXB0XCJdLFxuICAgICAgICAgICAgbm90UmVzb3VyY2VzOiBbYGFybjphd3M6a21zOio6JHtjZGsuU3RhY2sub2Yoc2NvcGUpLmFjY291bnR9OmtleS8qYF0sXG4gICAgICAgICAgICBjb25kaXRpb25zOiB7XG4gICAgICAgICAgICAgIFN0cmluZ0xpa2U6IHtcbiAgICAgICAgICAgICAgICBcImttczpWaWFTZXJ2aWNlXCI6IFtgc3FzLiR7Y2RrLlN0YWNrLm9mKHNjb3BlKS5yZWdpb259LmFtYXpvbmF3cy5jb21gXSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKHByb3BzLmFkZGl0aW9uYWxQb2xpY3lTdGF0ZW1lbnRzKSB7XG4gICAgICBwcm9wcy5hZGRpdGlvbmFsUG9saWN5U3RhdGVtZW50cy5mb3JFYWNoKChzdGF0ZW1lbnQpID0+IHtcbiAgICAgICAgbXdhYUV4ZWN1dGlvblJvbGUuYWRkVG9Qb2xpY3koc3RhdGVtZW50KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMubXdhYUVudmlyb25tZW50ID0gbmV3IG13YWEuQ2ZuRW52aXJvbm1lbnQodGhpcywgYCR7cHJvcHMubmFtZX0gTVdBQSBFbnZpcm9ubWVudGAsIHtcbiAgICAgIHNvdXJjZUJ1Y2tldEFybjogdGhpcy5zM0J1Y2tldC5idWNrZXRBcm4sXG4gICAgICBleGVjdXRpb25Sb2xlQXJuOiBtd2FhRXhlY3V0aW9uUm9sZS5yb2xlQXJuLFxuICAgICAgZGFnUzNQYXRoOiB0aGlzLmRhZ1MzUGF0aCxcbiAgICAgIG5ldHdvcmtDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IFtzZWN1cml0eUdyb3VwLnNlY3VyaXR5R3JvdXBJZF0sXG4gICAgICAgIHN1Ym5ldElkczogW1xuICAgICAgICAgIHRoaXMudnBjLnNlbGVjdFN1Ym5ldHMoeyBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QUklWQVRFX1dJVEhfRUdSRVNTIH0pLnN1Ym5ldElkc1swXSxcbiAgICAgICAgICB0aGlzLnZwYy5zZWxlY3RTdWJuZXRzKHsgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTUyB9KS5zdWJuZXRJZHNbMV0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAgd2Vic2VydmVyQWNjZXNzTW9kZTogXCJQVUJMSUNfT05MWVwiLFxuICAgICAgbG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgZGFnUHJvY2Vzc2luZ0xvZ3M6IHtcbiAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgIGxvZ0xldmVsOiB0aGlzLmRhZ1Byb2Nlc3NpbmdMb2dzLFxuICAgICAgICB9LFxuICAgICAgICBzY2hlZHVsZXJMb2dzOiB7XG4gICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICBsb2dMZXZlbDogdGhpcy5zY2hlZHVsZXJMb2dzTGV2ZWwsXG4gICAgICAgIH0sXG4gICAgICAgIHRhc2tMb2dzOiB7XG4gICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICBsb2dMZXZlbDogdGhpcy50YXNrTG9nc0xldmVsLFxuICAgICAgICB9LFxuICAgICAgICB3ZWJzZXJ2ZXJMb2dzOiB7XG4gICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICBsb2dMZXZlbDogdGhpcy53ZWJzZXJ2ZXJMb2dzTGV2ZWwsXG4gICAgICAgIH0sXG4gICAgICAgIHdvcmtlckxvZ3M6IHtcbiAgICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgICBsb2dMZXZlbDogdGhpcy53b3JrZXJMb2dzTGV2ZWwsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cbiAgY3JlYXRlVnBjKHNjb3BlOiBDb25zdHJ1Y3QsIGVudmlyb25tZW50TmFtZTogc3RyaW5nLCB2cGNDaWRyOiBzdHJpbmcpOiBlYzIuSVZwYyB7XG4gICAgY29uc3QgcmVzb3VyY2VOYW1lID0gYCR7ZW52aXJvbm1lbnROYW1lfS1NV0FBYDtcbiAgICBjb25zdCB2cGNDSURSTWFzayA9ICt2cGNDaWRyLnNwbGl0KFwiL1wiKVsxXTtcbiAgICBpZiAodnBjQ0lEUk1hc2sgPiAyMCB8fCB2cGNDSURSTWFzayA8IDE2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJWcGMgQ2lkciBSYW5nZSBtdXN0IG9mIHNpemUgPj0xNiBhbmQgPD0yMFwiKTtcbiAgICB9XG4gICAgY29uc3Qgc3VibmV0Q0lEUk1hc2sgPSB2cGNDSURSTWFzayArIDQ7XG4gICAgY29uc3QgdnBjID0gbmV3IGVjMi5WcGMoc2NvcGUsIGAke3Jlc291cmNlTmFtZX0gVnBjYCwge1xuICAgICAgaXBBZGRyZXNzZXM6IGVjMi5JcEFkZHJlc3Nlcy5jaWRyKHZwY0NpZHIpLFxuICAgICAgZW5hYmxlRG5zU3VwcG9ydDogdHJ1ZSxcbiAgICAgIGVuYWJsZURuc0hvc3RuYW1lczogdHJ1ZSxcbiAgICAgIHZwY05hbWU6IHJlc291cmNlTmFtZSxcbiAgICAgIHN1Ym5ldENvbmZpZ3VyYXRpb246IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwiUHVibGljXCIsXG4gICAgICAgICAgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFVCTElDLFxuICAgICAgICAgIGNpZHJNYXNrOiBzdWJuZXRDSURSTWFzayxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwiUHJpdmF0ZVwiLFxuICAgICAgICAgIHN1Ym5ldFR5cGU6IGVjMi5TdWJuZXRUeXBlLlBSSVZBVEVfV0lUSF9FR1JFU1MsXG4gICAgICAgICAgY2lkck1hc2s6IHN1Ym5ldENJRFJNYXNrLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIHJldHVybiB2cGM7XG4gIH1cbn1cbiJdfQ==
;