raindancers-network
Version:
Extensions to the ec2.Vpc Constructs
209 lines • 31.4 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CoreNetwork = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = require("path");
const cdk = require("aws-cdk-lib");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs = require("constructs");
const cloudWanPolicyTable_1 = require("./cloudWanPolicyTable");
const coreNetworkSegment_1 = require("./coreNetworkSegment");
/**
* Create a CoreNework for a Cloudwan
*/
class CoreNetwork extends constructs.Construct {
constructor(scope, id, props) {
super(scope, id);
this.updateProviderToken = '';
this.updateDependson = [];
// create a core network.. do not intially give it a policy
const coreNetwork = new aws_cdk_lib_1.aws_networkmanager.CfnCoreNetwork(this, 'CoreNetwork', {
globalNetworkId: props.globalNetwork.attrId,
description: props.policyDescription,
tags: [{ key: 'CoreNetworkName', value: props.coreName }],
});
this.cfnCoreNetwork = coreNetwork;
this.coreName = props.coreName;
// Create a dynamodb table with a composite key to store the elements of a core network table.
// this is created for version "2021.12" of the wan policy
// and create the update lambda
const policyTable = new cloudWanPolicyTable_1.CloudWanCorePolicyTable(this, 'PolicyTable', {
coreName: props.coreName,
noTableBackup: props.nonProduction,
});
// create the coreNetworkConfiguration
const coreNetworkConfiguration = {};
coreNetworkConfiguration['asn-ranges'] = props.asnRanges;
coreNetworkConfiguration['edge-locations'] = props.edgeLocations;
if (props.vpnEcmpSupport !== undefined) {
coreNetworkConfiguration['vpn-ecmp-support'] = props.vpnEcmpSupport;
}
if (props.insideCidrBlocks !== undefined) {
coreNetworkConfiguration['inside-cidr-blocks'] = props.insideCidrBlocks;
}
// create a custom resource that will add the corenetwork configuration
const coreNetworkCfg = new cdk.CustomResource(this, 'UpdateCoreNetworkConfiguration', {
serviceToken: policyTable.serviceToken,
properties: {
policyTableName: policyTable.policyTable.tableName,
coreNetworkConfiguration: cdk.Fn.base64(cdk.Stack.of(this).toJsonString(coreNetworkConfiguration)),
coreName: props.coreName,
},
});
this.updateDependson.push(coreNetworkCfg);
this.policyTableName = policyTable.policyTable.tableName;
this.policyTableServiceToken = policyTable.serviceToken;
this.policyTable = policyTable.policyTable;
}
/**
* Add a segment to the core network
* @param props properties of the segment
* @returns
*/
addSegment(props) {
// verify only one of deny/allow filters are set.
if (props.denyFilter !== undefined && props.allowFilter !== undefined) {
throw new Error('Only one of denyFilter and allowFilter can be defined');
}
const segment = {};
segment.name = props.name;
if (props.description !== undefined) {
segment.description = props.description;
}
if (props.edgeLocations !== undefined) {
segment['edge-locations'] = props.edgeLocations;
}
if (props.isolateAttachments !== undefined) {
segment['isolate-attachments'] = props.isolateAttachments;
}
if (props.requireAttachmentAcceptance !== undefined) {
segment['require-attachment-acceptance'] = props.requireAttachmentAcceptance;
}
if (props.denyFilter !== undefined) {
segment['deny-filter'] = props.denyFilter;
}
if (props.allowFilter !== undefined) {
segment['allow-filter'] = props.allowFilter;
}
const addsegment = new cdk.CustomResource(this, `CloudwanSegment${props.name}`, {
serviceToken: this.policyTableServiceToken,
properties: {
segment: cdk.Fn.base64(cdk.Stack.of(this).toJsonString(segment)),
policyTableName: this.policyTableName,
},
});
this.updateDependson.push(addsegment);
return new coreNetworkSegment_1.CoreNetworkSegment(this, `CoreNetworkSegment${props.name}`, {
segmentName: props.name,
policyTableServiceToken: this.policyTableServiceToken,
updateDependsOn: this.updateDependson,
});
}
/**
* Create a CoreNetwork Sharing
* @param props Share properties
*/
share(props) {
new aws_cdk_lib_1.aws_ram.CfnResourceShare(this, 'ShareNetworktoOrg', {
name: this.node.tryGetContext('coreNetworkName'),
allowExternalPrincipals: props.allowExternalPrincipals,
principals: props.principals,
resourceArns: [this.cfnCoreNetwork.attrCoreNetworkArn],
tags: props.tags,
});
}
/**
* Update the corewan policy after actions, segments are added
*/
updatePolicy() {
// this updates the policy
const onEvent = new aws_cdk_lib_1.aws_lambda.Function(this, 'UpdateCoreNetworkLambda', {
environment: { coreNetworkName: this.coreName },
runtime: aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_9,
handler: 'updatepolicy.on_event',
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, '../../lambda/cloudwan')),
timeout: cdk.Duration.seconds(899),
});
onEvent.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
resources: ['*'],
actions: [
'networkmanager:putCoreNetworkPolicy',
'networkmanager:executeCoreNetworkChangeSet',
'*',
],
}));
// let the lambda have access to the dynamo table.
this.policyTable.grantFullAccess(onEvent);
const updateProvider = new aws_cdk_lib_1.custom_resources.Provider(this, 'UpdateProvider', {
onEventHandler: onEvent,
logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.SEVEN_YEARS,
providerFunctionName: cdk.PhysicalName.GENERATE_IF_NEEDED,
});
this.updateProviderToken = updateProvider.serviceToken;
const updatePolicy = new cdk.CustomResource(this, 'UpdatePolicy', {
serviceToken: updateProvider.serviceToken,
properties: {
TableName: this.policyTable.tableName,
coreNetworkId: this.cfnCoreNetwork.attrCoreNetworkId,
random: new Date().toISOString(),
},
});
// we need to force this to not happen till all the updates are done.
this.updateDependson.forEach((resource) => {
updatePolicy.node.addDependency(resource);
});
// this checks that the policy execution is finished
// the onEvent will return immediately..
// we have to do this as two functions as we need an attribute from the first function
// to check if the policy has executed
const waittofinishOnEvent = new aws_cdk_lib_1.aws_lambda.Function(this, 'WaittofinishOnEvent', {
environment: { coreNetworkName: this.coreName },
runtime: aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_9,
handler: 'checkpolicycomplete.on_event',
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, '../../lambda/cloudwan')),
timeout: cdk.Duration.seconds(899),
functionName: 'cloudwanPolicyExecutewaittofinishonevent',
});
const waittofinishIsComplete = new aws_cdk_lib_1.aws_lambda.Function(this, 'WaittofinishisComplete', {
environment: { coreNetworkName: this.coreName },
runtime: aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_9,
handler: 'checkpolicycomplete.is_complete',
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, '../../lambda/cloudwan')),
timeout: cdk.Duration.seconds(899),
functionName: 'cloudwanPolicyExecutewaitiscomplete',
});
waittofinishIsComplete.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
resources: ['*'],
actions: [
'networkmanager:getCoreNetworkChangeEvents',
],
}));
//const waittoFinishProvider =
new aws_cdk_lib_1.custom_resources.Provider(this, 'WaittoFinishProvider', {
onEventHandler: waittofinishOnEvent,
isCompleteHandler: waittofinishIsComplete,
totalTimeout: cdk.Duration.minutes(119),
queryInterval: cdk.Duration.seconds(20),
logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.SEVEN_YEARS,
providerFunctionName: cdk.PhysicalName.GENERATE_IF_NEEDED,
});
// TO DO.. Wait for finish does not work as expected.
// lambda versions.
// const waittofin = new cdk.CustomResource(this, 'WaittoFin', {
// serviceToken: waittoFinishProvider.serviceToken,
// properties: {
// policyVersionId: updatePolicy.getAtt('PolicyVersionId'),
// coreNetworkId: this.CoreNetwork.attrCoreNetworkId,
// random: uuid()
// }
// })
//waittofin.node.addDependency(updatePolicy)
}
}
exports.CoreNetwork = CoreNetwork;
_a = JSII_RTTI_SYMBOL_1;
CoreNetwork[_a] = { fqn: "raindancers-network.cloudwan.CoreNetwork", version: "1.29.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWRXYW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xvdWR3YW4vY2xvdWRXYW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsbUNBQW1DO0FBQ25DLDZDQVNxQjtBQUNyQix5Q0FBeUM7QUFJekMsK0RBQWdFO0FBQ2hFLDZEQUEwRDtBQUcxRDs7R0FFRztBQUNILE1BQWEsV0FBWSxTQUFRLFVBQVUsQ0FBQyxTQUFTO0lBMkJuRCxZQUFZLEtBQTJCLEVBQUUsRUFBVSxFQUFFLEtBQW9DO1FBQ3ZGLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFOWix3QkFBbUIsR0FBVyxFQUFFLENBQUM7UUFRdEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7UUFFMUIsMkRBQTJEO1FBQzNELE1BQU0sV0FBVyxHQUFHLElBQUksZ0NBQWMsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUN6RSxlQUFlLEVBQUUsS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFNO1lBQzNDLFdBQVcsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1lBQ3BDLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLGlCQUFpQixFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDMUQsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGNBQWMsR0FBRyxXQUFXLENBQUM7UUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBRy9CLDhGQUE4RjtRQUM5RiwwREFBMEQ7UUFDMUQsK0JBQStCO1FBRS9CLE1BQU0sV0FBVyxHQUFHLElBQUksNkNBQXVCLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUNuRSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDeEIsYUFBYSxFQUFFLEtBQUssQ0FBQyxhQUFhO1NBQ25DLENBQUMsQ0FBQztR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ZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgYXdzX25ldHdvcmttYW5hZ2VyIGFzIG5ldHdvcmttYW5hZ2VyLFxuICBhd3NfZHluYW1vZGIgYXMgZHluYW1vLFxuICBjdXN0b21fcmVzb3VyY2VzIGFzIGNyLFxuICBhd3NfbG9ncyBhcyBsb2dzLFxuICBhd3NfbGFtYmRhLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX3JhbSBhcyByYW0sXG59XG4gIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5cblxuaW1wb3J0ICogYXMgY2xvdWRXYW5FbnVtIGZyb20gJy4vY2xvdWRXYW5FbnVtJztcbmltcG9ydCB7IENsb3VkV2FuQ29yZVBvbGljeVRhYmxlIH0gZnJvbSAnLi9jbG91ZFdhblBvbGljeVRhYmxlJztcbmltcG9ydCB7IENvcmVOZXR3b3JrU2VnbWVudCB9IGZyb20gJy4vY29yZU5ldHdvcmtTZWdtZW50JztcblxuXG4vKipcbiAqIENyZWF0ZSBhIENvcmVOZXdvcmsgZm9yIGEgQ2xvdWR3YW5cbiAqL1xuZXhwb3J0IGNsYXNzIENvcmVOZXR3b3JrIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuXG4gIC8qKlxuXHQgKiBUaGUgcG9saWN5VGFibGUgTGFtYmEncyBTZXJ2aWNlIFRva2VuXG5cdCAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcG9saWN5VGFibGVTZXJ2aWNlVG9rZW46IHN0cmluZztcblxuICAvKipcblx0ICogTmFtZSBvZiB0aGUgRHluYW1vIFRhYmxlIGhvbGRpbmcgdGhlIHBvbGljeVxuXHQgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBvbGljeVRhYmxlTmFtZTogc3RyaW5nO1xuICAvKipcblx0ICogVEhlIGR5bmFtbyB0YWJsZSBob2xkaW5nIHRoZSBwb2xpY3lcblx0ICovXG4gIHB1YmxpYyByZWFkb25seSBwb2xpY3lUYWJsZTogZHluYW1vLlRhYmxlO1xuICAvKipcblx0ICogVGhlIGNvcmVuZXR3b3JrIG9iamVjdFxuXHQgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNmbkNvcmVOZXR3b3JrOiBuZXR3b3JrbWFuYWdlci5DZm5Db3JlTmV0d29yaztcblxuICAvLyB0aGUgY29yZW5ldHdvcmsgY29yZSBOYW1lXG4gIHB1YmxpYyByZWFkb25seSBjb3JlTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgdXBkYXRlUHJvdmlkZXJUb2tlbjogc3RyaW5nID0gJyc7XG5cbiAgcHJpdmF0ZSB1cGRhdGVEZXBlbmRzb246IGNkay5DdXN0b21SZXNvdXJjZVtdO1xuXG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogY2xvdWRXYW5FbnVtLkNvcmVOZXR3b3JrUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy51cGRhdGVEZXBlbmRzb24gPSBbXTtcblxuICAgIC8vIGNyZWF0ZSBhIGNvcmUgbmV0d29yay4uIGRvIG5vdCBpbnRpYWxseSBnaXZlIGl0IGEgcG9saWN5XG4gICAgY29uc3QgY29yZU5ldHdvcmsgPSBuZXcgbmV0d29ya21hbmFnZXIuQ2ZuQ29yZU5ldHdvcmsodGhpcywgJ0NvcmVOZXR3b3JrJywge1xuICAgICAgZ2xvYmFsTmV0d29ya0lkOiBwcm9wcy5nbG9iYWxOZXR3b3JrLmF0dHJJZCxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5wb2xpY3lEZXNjcmlwdGlvbixcbiAgICAgIHRhZ3M6IFt7IGtleTogJ0NvcmVOZXR3b3JrTmFtZScsIHZhbHVlOiBwcm9wcy5jb3JlTmFtZSB9XSxcblx0XHQgIH0pO1xuXG4gICAgdGhpcy5jZm5Db3JlTmV0d29yayA9IGNvcmVOZXR3b3JrO1xuICAgIHRoaXMuY29yZU5hbWUgPSBwcm9wcy5jb3JlTmFtZTtcblxuXG4gICAgLy8gQ3JlYXRlIGEgZHluYW1vZGIgdGFibGUgd2l0aCBhIGNvbXBvc2l0ZSBrZXkgdG8gc3RvcmUgdGhlIGVsZW1lbnRzIG9mIGEgY29yZSBuZXR3b3JrIHRhYmxlLlxuICAgIC8vIHRoaXMgaXMgY3JlYXRlZCBmb3IgdmVyc2lvbiBcIjIwMjEuMTJcIiBvZiB0aGUgd2FuIHBvbGljeVxuICAgIC8vIGFuZCBjcmVhdGUgdGhlIHVwZGF0ZSBsYW1iZGFcblxuICAgIGNvbnN0IHBvbGljeVRhYmxlID0gbmV3IENsb3VkV2FuQ29yZVBvbGljeVRhYmxlKHRoaXMsICdQb2xpY3lUYWJsZScsIHtcbiAgICAgIGNvcmVOYW1lOiBwcm9wcy5jb3JlTmFtZSxcbiAgICAgIG5vVGFibGVCYWNrdXA6IHByb3BzLm5vblByb2R1Y3Rpb24sXG4gICAgfSk7XG5cblxuICAgIC8vIGNyZWF0ZSB0aGUgY29yZU5ldHdvcmtDb25maWd1cmF0aW9uXG4gICAgY29uc3QgY29yZU5ldHdvcmtDb25maWd1cmF0aW9uOiB7W2s6IHN0cmluZ106IGFueX0gPSB7fTtcblxuICAgIGNvcmVOZXR3b3JrQ29uZmlndXJhdGlvblsnYXNuLXJhbmdlcyddID0gcHJvcHMuYXNuUmFuZ2VzO1xuICAgIGNvcmVOZXR3b3JrQ29uZmlndXJhdGlvblsnZWRnZS1sb2NhdGlvbnMnXSA9IHByb3BzLmVkZ2VMb2NhdGlvbnM7XG4gICAgaWYgKCBwcm9wcy52cG5FY21wU3VwcG9ydCAhPT11bmRlZmluZWQgKSB7XG4gICAgICBjb3JlTmV0d29ya0NvbmZpZ3VyYXRpb25bJ3Zwbi1lY21wLXN1cHBvcnQnXSA9IHByb3BzLnZwbkVjbXBTdXBwb3J0O1xuICAgIH1cbiAgICBpZiAoIHByb3BzLmluc2lkZUNpZHJCbG9ja3MgIT09dW5kZWZpbmVkICkge1xuICAgICAgY29yZU5ldHdvcmtDb25maWd1cmF0aW9uWydpbnNpZGUtY2lkci1ibG9ja3MnXSA9IHByb3BzLmluc2lkZUNpZHJCbG9ja3M7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGEgY3VzdG9tIHJlc291cmNlIHRoYXQgd2lsbCBhZGQgdGhlIGNvcmVuZXR3b3JrIGNvbmZpZ3VyYXRpb25cblxuICAgIGNvbnN0IGNvcmVOZXR3b3JrQ2ZnID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnVXBkYXRlQ29yZU5ldHdvcmtDb25maWd1cmF0aW9uJywge1xuICAgICAgc2VydmljZVRva2VuOiBwb2xpY3lUYWJsZS5zZXJ2aWNlVG9rZW4sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHBvbGljeVRhYmxlTmFtZTogcG9saWN5VGFibGUucG9saWN5VGFibGUudGFibGVOYW1lLFxuICAgICAgICBjb3JlTmV0d29ya0NvbmZpZ3VyYXRpb246IGNkay5Gbi5iYXNlNjQoY2RrLlN0YWNrLm9mKHRoaXMpLnRvSnNvblN0cmluZyhjb3JlTmV0d29ya0NvbmZpZ3VyYXRpb24pKSxcbiAgICAgICAgY29yZU5hbWU6IHByb3BzLmNvcmVOYW1lLFxuICAgICAgfSxcbiAgICB9KTtcblxuXG4gICAgdGhpcy51cGRhdGVEZXBlbmRzb24ucHVzaChjb3JlTmV0d29ya0NmZyk7XG5cbiAgICB0aGlzLnBvbGljeVRhYmxlTmFtZSA9IHBvbGljeVRhYmxlLnBvbGljeVRhYmxlLnRhYmxlTmFtZTtcbiAgICB0aGlzLnBvbGljeVRhYmxlU2VydmljZVRva2VuID0gcG9saWN5VGFibGUuc2VydmljZVRva2VuO1xuICAgIHRoaXMucG9saWN5VGFibGUgPSBwb2xpY3lUYWJsZS5wb2xpY3lUYWJsZTtcblxuICB9XG5cbiAgLyoqXG5cdCAqIEFkZCBhIHNlZ21lbnQgdG8gdGhlIGNvcmUgbmV0d29ya1xuXHQgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiB0aGUgc2VnbWVudFxuXHQgKiBAcmV0dXJuc1xuXHQgKi9cbiAgcHVibGljIGFkZFNlZ21lbnQoXG4gICAgcHJvcHM6IGNsb3VkV2FuRW51bS5TZWdtZW50LFxuICApOiBDb3JlTmV0d29ya1NlZ21lbnQge1xuXG4gICAgLy8gdmVyaWZ5IG9ubHkgb25lIG9mIGRlbnkvYWxsb3cgZmlsdGVycyBhcmUgc2V0LlxuICAgIGlmIChwcm9wcy5kZW55RmlsdGVyICE9PSB1bmRlZmluZWQgJiYgcHJvcHMuYWxsb3dGaWx0ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPbmx5IG9uZSBvZiBkZW55RmlsdGVyIGFuZCBhbGxvd0ZpbHRlciBjYW4gYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlZ21lbnQ6IHtbazogc3RyaW5nXTogYW55fSA9IHt9O1xuXG4gICAgc2VnbWVudC5uYW1lID0gcHJvcHMubmFtZTtcblxuICAgIGlmICggcHJvcHMuZGVzY3JpcHRpb24gIT09dW5kZWZpbmVkICkge1xuICAgICAgc2VnbWVudC5kZXNjcmlwdGlvbiA9IHByb3BzLmRlc2NyaXB0aW9uO1xuICAgIH1cbiAgICBpZiAoIHByb3BzLmVkZ2VMb2NhdGlvbnMgIT09dW5kZWZpbmVkICkge1xuICAgICAgc2VnbWVudFsnZWRnZS1sb2NhdGlvbnMnXSA9IHByb3BzLmVkZ2VMb2NhdGlvbnM7XG4gICAgfVxuICAgIGlmICggcHJvcHMuaXNvbGF0ZUF0dGFjaG1lbnRzICE9PXVuZGVmaW5lZCApIHtcbiAgICAgIHNlZ21lbnRbJ2lzb2xhdGUtYXR0YWNobWVudHMnXSA9IHByb3BzLmlzb2xhdGVBdHRhY2htZW50cztcbiAgICB9XG4gICAgaWYgKCBwcm9wcy5yZXF1aXJlQXR0YWNobWVudEFjY2VwdGFuY2UgIT09dW5kZWZpbmVkICkge1xuICAgICAgc2VnbWVudFsncmVxdWlyZS1hdHRhY2htZW50LWFjY2VwdGFuY2UnXSA9IHByb3BzLnJlcXVpcmVBdHRhY2htZW50QWNjZXB0YW5jZTtcbiAgICB9XG4gICAgaWYgKCBwcm9wcy5kZW55RmlsdGVyICE9PXVuZGVmaW5lZCApIHtcbiAgICAgIHNlZ21lbnRbJ2RlbnktZmlsdGVyJ10gPSBwcm9wcy5kZW55RmlsdGVyO1xuICAgIH1cbiAgICBpZiAoIHByb3BzLmFsbG93RmlsdGVyICE9PXVuZGVmaW5lZCApIHtcbiAgICAgIHNlZ21lbnRbJ2FsbG93LWZpbHRlciddID0gcHJvcHMuYWxsb3dGaWx0ZXI7XG4gICAgfVxuXG5cbiAgICBjb25zdCBhZGRzZWdtZW50ID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCBgQ2xvdWR3YW5TZWdtZW50JHtwcm9wcy5uYW1lfWAsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogdGhpcy5wb2xpY3lUYWJsZVNlcnZpY2VUb2tlbixcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgc2VnbWVudDogY2RrLkZuLmJhc2U2NChjZGsuU3RhY2sub2YodGhpcykudG9Kc29uU3RyaW5nKHNlZ21lbnQpKSxcbiAgICAgICAgcG9saWN5VGFibGVOYW1lOiB0aGlzLnBvbGljeVRhYmxlTmFtZSxcbiAgICAgIH0sXG4gICAgfSk7XG5cblxuICAgIHRoaXMudXBkYXRlRGVwZW5kc29uLnB1c2goYWRkc2VnbWVudCk7XG5cbiAgICByZXR1cm4gbmV3IENvcmVOZXR3b3JrU2VnbWVudCh0aGlzLCBgQ29yZU5ldHdvcmtTZWdtZW50JHtwcm9wcy5uYW1lfWAsIHtcbiAgICAgIHNlZ21lbnROYW1lOiBwcm9wcy5uYW1lLFxuICAgICAgcG9saWN5VGFibGVTZXJ2aWNlVG9rZW46IHRoaXMucG9saWN5VGFibGVTZXJ2aWNlVG9rZW4sXG4gICAgICB1cGRhdGVEZXBlbmRzT246IHRoaXMudXBkYXRlRGVwZW5kc29uLFxuICAgIH0pO1xuXG4gIH1cbiAgLyoqXG5cdCAqIENyZWF0ZSBhIENvcmVOZXR3b3JrIFNoYXJpbmdcblx0ICogQHBhcmFtIHByb3BzIFNoYXJlIHByb3BlcnRpZXNcblx0ICovXG4gIHB1YmxpYyBzaGFyZSAocHJvcHM6IGNsb3VkV2FuRW51bS5Db3JlTmV0d29ya1NoYXJlKSA6IHZvaWQge1xuXG4gICAgbmV3IHJhbS5DZm5SZXNvdXJjZVNoYXJlKHRoaXMsICdTaGFyZU5ldHdvcmt0b09yZycsIHtcbiAgICAgIG5hbWU6IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KCdjb3JlTmV0d29ya05hbWUnKSxcbiAgICAgIGFsbG93RXh0ZXJuYWxQcmluY2lwYWxzOiBwcm9wcy5hbGxvd0V4dGVybmFsUHJpbmNpcGFscyxcbiAgICAgIHByaW5jaXBhbHM6IHByb3BzLnByaW5jaXBhbHMsXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLmNmbkNvcmVOZXR3b3JrLmF0dHJDb3JlTmV0d29ya0Fybl0sXG4gICAgICB0YWdzOiBwcm9wcy50YWdzLFxuICAgIH0pO1xuXG4gIH1cblxuICAvKipcblx0ICogVXBkYXRlIHRoZSBjb3Jld2FuIHBvbGljeSBhZnRlciBhY3Rpb25zLCBzZWdtZW50cyBhcmUgYWRkZWRcblx0ICovXG4gIHB1YmxpYyB1cGRhdGVQb2xpY3kgKCk6IHZvaWQge1xuXG4gICAgLy8gdGhpcyB1cGRhdGVzIHRoZSBwb2xpY3lcbiAgICBjb25zdCBvbkV2ZW50ID0gbmV3IGF3c19sYW1iZGEuRnVuY3Rpb24odGhpcywgJ1VwZGF0ZUNvcmVOZXR3b3JrTGFtYmRhJywge1xuICAgICAgZW52aXJvbm1lbnQ6IHsgY29yZU5ldHdvcmtOYW1lOiB0aGlzLmNvcmVOYW1lIH0sXG4gICAgICBydW50aW1lOiBhd3NfbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOSxcbiAgICAgIGhhbmRsZXI6ICd1cGRhdGVwb2xpY3kub25fZXZlbnQnLFxuICAgICAgY29kZTogYXdzX2xhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vbGFtYmRhL2Nsb3Vkd2FuJykpLFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLnNlY29uZHMoODk5KSxcbiAgICAgIC8vZnVuY3Rpb25OYW1lOiAndXBkYXRlY29yZWxhbWJkYScvL2Nkay5QaHlzaWNhbE5hbWUuR0VORVJBVEVfSUZfTkVFREVEXG4gICAgfSk7XG5cbiAgICBvbkV2ZW50LmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ25ldHdvcmttYW5hZ2VyOnB1dENvcmVOZXR3b3JrUG9saWN5JyxcbiAgICAgICAgICAnbmV0d29ya21hbmFnZXI6ZXhlY3V0ZUNvcmVOZXR3b3JrQ2hhbmdlU2V0JyxcbiAgICAgICAgICAnKicsXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApO1xuICAgIC8vIGxldCB0aGUgbGFtYmRhIGhhdmUgYWNjZXNzIHRvIHRoZSBkeW5hbW8gdGFibGUuXG4gICAgdGhpcy5wb2xpY3lUYWJsZS5ncmFudEZ1bGxBY2Nlc3Mob25FdmVudCk7XG5cblxuICAgIGNvbnN0IHVwZGF0ZVByb3ZpZGVyID0gbmV3IGNyLlByb3ZpZGVyKHRoaXMsICdVcGRhdGVQcm92aWRlcicsIHtcbiAgICAgIG9uRXZlbnRIYW5kbGVyOiBvbkV2ZW50LFxuICAgICAgbG9nUmV0ZW50aW9uOiBsb2dzLlJldGVudGlvbkRheXMuU0VWRU5fWUVBUlMsXG4gICAgICBwcm92aWRlckZ1bmN0aW9uTmFtZTogY2RrLlBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERUQsXG4gICAgfSk7XG5cblxuICAgIHRoaXMudXBkYXRlUHJvdmlkZXJUb2tlbiA9IHVwZGF0ZVByb3ZpZGVyLnNlcnZpY2VUb2tlbjtcblxuXG4gICAgY29uc3QgdXBkYXRlUG9saWN5ID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnVXBkYXRlUG9saWN5Jywge1xuICAgICAgc2VydmljZVRva2VuOiB1cGRhdGVQcm92aWRlci5zZXJ2aWNlVG9rZW4sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy5wb2xpY3lUYWJsZS50YWJsZU5hbWUsXG4gICAgICAgIGNvcmVOZXR3b3JrSWQ6IHRoaXMuY2ZuQ29yZU5ldHdvcmsuYXR0ckNvcmVOZXR3b3JrSWQsXG4gICAgICAgIHJhbmRvbTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICAvLyB3ZSBuZWVkIHRvIGZvcmNlIHRoaXMgdG8gbm90IGhhcHBlbiB0aWxsIGFsbCB0aGUgdXBkYXRlcyBhcmUgZG9uZS5cbiAgICB0aGlzLnVwZGF0ZURlcGVuZHNvbi5mb3JFYWNoKChyZXNvdXJjZSkgPT4ge1xuICAgICAgdXBkYXRlUG9saWN5Lm5vZGUuYWRkRGVwZW5kZW5jeShyZXNvdXJjZSk7XG4gICAgfSk7XG5cblxuICAgIC8vIHRoaXMgY2hlY2tzIHRoYXQgdGhlIHBvbGljeSBleGVjdXRpb24gaXMgZmluaXNoZWRcbiAgICAvLyB0aGUgb25FdmVudCB3aWxsIHJldHVybiBpbW1lZGlhdGVseS4uXG4gICAgLy8gd2UgaGF2ZSB0byBkbyB0aGlzIGFzIHR3byBmdW5jdGlvbnMgYXMgd2UgbmVlZCBhbiBhdHRyaWJ1dGUgZnJvbSB0aGUgZmlyc3QgZnVuY3Rpb25cbiAgICAvLyB0byBjaGVjayBpZiB0aGUgcG9saWN5IGhhcyBleGVjdXRlZFxuXG4gICAgY29uc3Qgd2FpdHRvZmluaXNoT25FdmVudCA9IG5ldyBhd3NfbGFtYmRhLkZ1bmN0aW9uKHRoaXMsICdXYWl0dG9maW5pc2hPbkV2ZW50Jywge1xuICAgICAgZW52aXJvbm1lbnQ6IHsgY29yZU5ldHdvcmtOYW1lOiB0aGlzLmNvcmVOYW1lIH0sXG4gICAgICBydW50aW1lOiBhd3NfbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOSxcbiAgICAgIGhhbmRsZXI6ICdjaGVja3BvbGljeWNvbXBsZXRlLm9uX2V2ZW50JyxcbiAgICAgIGNvZGU6IGF3c19sYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uLy4uL2xhbWJkYS9jbG91ZHdhbicpKSxcbiAgICAgIHRpbWVvdXQ6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDg5OSksXG4gICAgICBmdW5jdGlvbk5hbWU6ICdjbG91ZHdhblBvbGljeUV4ZWN1dGV3YWl0dG9maW5pc2hvbmV2ZW50JywgLy9jZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRFxuICAgIH0pO1xuXG5cbiAgICBjb25zdCB3YWl0dG9maW5pc2hJc0NvbXBsZXRlID0gbmV3IGF3c19sYW1iZGEuRnVuY3Rpb24odGhpcywgJ1dhaXR0b2ZpbmlzaGlzQ29tcGxldGUnLCB7XG4gICAgICBlbnZpcm9ubWVudDogeyBjb3JlTmV0d29ya05hbWU6IHRoaXMuY29yZU5hbWUgfSxcbiAgICAgIHJ1bnRpbWU6IGF3c19sYW1iZGEuUnVudGltZS5QWVRIT05fM185LFxuICAgICAgaGFuZGxlcjogJ2NoZWNrcG9saWN5Y29tcGxldGUuaXNfY29tcGxldGUnLFxuICAgICAgY29kZTogYXdzX2xhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vbGFtYmRhL2Nsb3Vkd2FuJykpLFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLnNlY29uZHMoODk5KSxcbiAgICAgIGZ1bmN0aW9uTmFtZTogJ2Nsb3Vkd2FuUG9saWN5RXhlY3V0ZXdhaXRpc2NvbXBsZXRlJywgLy9jZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRFxuICAgIH0pO1xuXG5cbiAgICB3YWl0dG9maW5pc2hJc0NvbXBsZXRlLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ25ldHdvcmttYW5hZ2VyOmdldENvcmVOZXR3b3JrQ2hhbmdlRXZlbnRzJyxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICAvL2NvbnN0IHdhaXR0b0ZpbmlzaFByb3ZpZGVyID1cblxuICAgIG5ldyBjci5Qcm92aWRlcih0aGlzLCAnV2FpdHRvRmluaXNoUHJvdmlkZXInLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogd2FpdHRvZmluaXNoT25FdmVudCxcbiAgICAgIGlzQ29tcGxldGVIYW5kbGVyOiB3YWl0dG9maW5pc2hJc0NvbXBsZXRlLFxuICAgICAgdG90YWxUaW1lb3V0OiBjZGsuRHVyYXRpb24ubWludXRlcygxMTkpLFx0Ly8gbm90ZSB0aGlzIGNhbiBiZSBsb25nZXIgdGhhbiB0aGUgbGFtYmRhIHRpbWVvdXRcbiAgICAgIHF1ZXJ5SW50ZXJ2YWw6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDIwKSxcbiAgICAgIGxvZ1JldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLlNFVkVOX1lFQVJTLFxuICAgICAgcHJvdmlkZXJGdW5jdGlvbk5hbWU6IGNkay5QaHlzaWNhbE5hbWUuR0VORVJBVEVfSUZfTkVFREVELFxuICAgIH0pO1xuXG5cbiAgICAvLyBUTyBETy4uIFdhaXQgZm9yIGZpbmlzaCBkb2VzIG5vdCB3b3JrIGFzIGV4cGVjdGVkLlxuICAgIC8vIGxhbWJkYSB2ZXJzaW9ucy5cblxuXG4gICAgLy8gY29uc3Qgd2FpdHRvZmluID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnV2FpdHRvRmluJywge1xuICAgIC8vIFx0c2VydmljZVRva2VuOiB3YWl0dG9GaW5pc2hQcm92aWRlci5zZXJ2aWNlVG9rZW4sXG4gICAgLy8gXHRwcm9wZXJ0aWVzOiB7XG4gICAgLy8gXHRcdHBvbGljeVZlcnNpb25JZDogdXBkYXRlUG9saWN5LmdldEF0dCgnUG9saWN5VmVyc2lvbklkJyksXG4gICAgLy8gXHRcdGNvcmVOZXR3b3JrSWQ6IHRoaXMuQ29yZU5ldHdvcmsuYXR0ckNvcmVOZXR3b3JrSWQsXG4gICAgLy8gXHRcdHJhbmRvbTogdXVpZCgpXG4gICAgLy8gXHR9XG4gICAgLy8gfSlcblxuICAgIC8vd2FpdHRvZmluLm5vZGUuYWRkRGVwZW5kZW5jeSh1cGRhdGVQb2xpY3kpXG5cbiAgfVxuXG59XG4iXX0=