@cdklabs/cdk-hyperledger-fabric-network
Version:
CDK construct to deploy a Hyperledger Fabric network running on Amazon Managed Blockchain
161 lines • 24.5 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HyperledgerFabricNode = exports.STARTER_INSTANCE_TYPES = exports.InstanceType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
const cdk = require("aws-cdk-lib");
const managedblockchain = require("aws-cdk-lib/aws-managedblockchain");
const customresources = require("aws-cdk-lib/custom-resources");
const constructs = require("constructs");
const network = require("./network");
const utilities = require("./utilities");
/**
* Supported instance types for Managed Blockchain nodes
*/
var InstanceType;
(function (InstanceType) {
InstanceType["BURSTABLE3_SMALL"] = "bc.t3.small";
InstanceType["BURSTABLE3_MEDIUM"] = "bc.t3.medium";
InstanceType["BURSTABLE3_LARGE"] = "bc.t3.large";
InstanceType["BURSTABLE3_XLARGE"] = "bc.t3.xlarge";
InstanceType["STANDARD5_LARGE"] = "bc.m5.large";
InstanceType["STANDARD5_XLARGE"] = "bc.m5.xlarge";
InstanceType["STANDARD5_XLARGE2"] = "bc.m5.2xlarge";
InstanceType["STANDARD5_XLARGE4"] = "bc.m5.4xlarge";
InstanceType["COMPUTE5_LARGE"] = "bc.c5.large";
InstanceType["COMPUTE5_XLARGE"] = "bc.c5.xlarge";
InstanceType["COMPUTE5_XLARGE2"] = "bc.c5.2xlarge";
InstanceType["COMPUTE5_XLARGE4"] = "bc.c5.4xlarge";
})(InstanceType || (exports.InstanceType = InstanceType = {}));
/**
* Valid instance types for starter networks
*/
exports.STARTER_INSTANCE_TYPES = [
InstanceType.BURSTABLE3_SMALL,
InstanceType.BURSTABLE3_MEDIUM,
];
/**
* Creates a Hyperledger Fabric node on an Amazon Managed Blockchain network
*/
class HyperledgerFabricNode extends constructs.Construct {
/**
* Build out a list of HyperledgerFabricNode constructs given a list of input property
* objects; additionally checks to ensure node count is supported given the network type
*/
static constructNodes(scope, nodeProps) {
// If no node configurations are provided, create one; the empty object
// will be populated with defaults when passed to the node constructor
if (typeof nodeProps === 'undefined')
nodeProps = [{}];
const starter = scope.networkEdition === network.NetworkEdition.STARTER;
if (starter && nodeProps.length > 2) {
throw new Error('A starter network can have at most 2 nodes per member.');
}
if (!starter && nodeProps.length > 3) {
throw new Error('A standard network can have at most 3 nodes per member.');
}
// Construct the node list, using an index value in the identifier
return Array.from(nodeProps.entries()).map(e => new HyperledgerFabricNode(scope, `Node${e[0]}`, e[1]));
}
constructor(scope, id, props) {
super(scope, id);
// These cannot be readonly since they have to be set after construction
// due the race condition documented in https://github.com/aws/aws-cdk/issues/18237.
this.endpoint = '';
this.eventEndpoint = '';
// Collect metadata on the stack
const region = cdk.Stack.of(this).region;
// Populate instance variables from input properties, using defaults if values not provided
if (typeof props === 'undefined')
props = {};
this.availabilityZone = props.availabilityZone ?? `${region}a`;
this.instanceType = props.instanceType ?? InstanceType.BURSTABLE3_SMALL;
this.enableChaincodeLogging = props.enableChaincodeLogging ?? true;
this.enableNodeLogging = props.enableNodeLogging ?? true;
this.networkId = scope.networkId;
this.memberId = scope.memberId;
// Ensure the parameters captured above are valid, so we don't
// need to wait until deployment time to discover an error
utilities.validateRegion(region);
utilities.validateAvailabilityZone(region, this.availabilityZone);
if (scope.networkEdition === network.NetworkEdition.STARTER && !exports.STARTER_INSTANCE_TYPES.includes(this.instanceType)) {
const starterInstanceTypeList = exports.STARTER_INSTANCE_TYPES.join(', ');
throw new Error(`Instance type in a starter network must be one of the following: ${starterInstanceTypeList}.`);
}
// Build out the Cloudformation construct for the network/member
const node = new managedblockchain.CfnNode(this, 'Node', {
networkId: this.networkId,
memberId: this.memberId,
nodeConfiguration: {
availabilityZone: this.availabilityZone,
instanceType: this.instanceType,
},
});
// Capture data included in the Cloudformation output in instance variables
this.nodeId = node.getAtt('NodeId').toString();
}
/**
* Configure logging for the node via SDK call; this function
* should be merged back into the constructor once the race condition is solved
*/
configureLogging(sdkCallPolicy) {
// This call doesn't really need all the permissions its using in the
// provided policy, but since the policy must be constructed all at once
// this is the only way to do it effectively
const logPublishingConfiguration = {
Fabric: {
ChaincodeLogs: {
Cloudwatch: { Enabled: this.enableChaincodeLogging },
},
PeerLogs: {
Cloudwatch: { Enabled: this.enableNodeLogging },
},
},
};
const configureNodeLogSdkCall = {
service: 'ManagedBlockchain',
action: 'updateNode',
parameters: {
NetworkId: this.networkId,
MemberId: this.memberId,
NodeId: this.nodeId,
LogPublishingConfiguration: logPublishingConfiguration,
},
physicalResourceId: customresources.PhysicalResourceId.of('Id'),
};
new customresources.AwsCustomResource(this, 'ConfigureNodeLogResource', {
policy: sdkCallPolicy,
onCreate: configureNodeLogSdkCall,
onUpdate: configureNodeLogSdkCall,
});
}
/**
* Populate the output properties that must be fetched via SDK call; this function
* should be merged back into the constructor once the race condition is solved
*/
fetchData(dataSdkCallPolicy) {
// This call doesn't really need all the permissions its using in the
// provided policy, but since the policy must be constructed all at once
// this is the only way to do it effectively
const nodeDataSdkCall = {
service: 'ManagedBlockchain',
action: 'getNode',
parameters: { NetworkId: this.networkId, MemberId: this.memberId, NodeId: this.nodeId },
physicalResourceId: customresources.PhysicalResourceId.of('Id'),
};
const nodeData = new customresources.AwsCustomResource(this, 'NodeDataResource', {
policy: dataSdkCallPolicy,
onCreate: nodeDataSdkCall,
onUpdate: nodeDataSdkCall,
});
// Grab items out of the above return values and stick them in output properties
this.endpoint = nodeData.getResponseField('Node.FrameworkAttributes.Fabric.PeerEndpoint');
this.eventEndpoint = nodeData.getResponseField('Node.FrameworkAttributes.Fabric.PeerEventEndpoint');
}
}
exports.HyperledgerFabricNode = HyperledgerFabricNode;
_a = JSII_RTTI_SYMBOL_1;
HyperledgerFabricNode[_a] = { fqn: "@cdklabs/cdk-hyperledger-fabric-network.HyperledgerFabricNode", version: "0.8.918" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ub2RlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLGlDQUFpQztBQUdqQyxtQ0FBbUM7QUFDbkMsdUVBQXVFO0FBQ3ZFLGdFQUFnRTtBQUNoRSx5Q0FBeUM7QUFFekMscUNBQXFDO0FBQ3JDLHlDQUF5QztBQUd6Qzs7R0FFRztBQUNILElBQVksWUFhWDtBQWJELFdBQVksWUFBWTtJQUN0QixnREFBZ0MsQ0FBQTtJQUNoQyxrREFBa0MsQ0FBQTtJQUNsQyxnREFBZ0MsQ0FBQTtJQUNoQyxrREFBa0MsQ0FBQTtJQUNsQywrQ0FBK0IsQ0FBQTtJQUMvQixpREFBaUMsQ0FBQTtJQUNqQyxtREFBbUMsQ0FBQTtJQUNuQyxtREFBbUMsQ0FBQTtJQUNuQyw4Q0FBOEIsQ0FBQTtJQUM5QixnREFBZ0MsQ0FBQTtJQUNoQyxrREFBa0MsQ0FBQTtJQUNsQyxrREFBa0MsQ0FBQTtBQUNwQyxDQUFDLEVBYlcsWUFBWSw0QkFBWixZQUFZLFFBYXZCO0FBR0Q7O0dBRUc7QUFDVSxRQUFBLHNCQUFzQixHQUFHO0lBQ3BDLFlBQVksQ0FBQyxnQkFBZ0I7SUFDN0IsWUFBWSxDQUFDLGlCQUFpQjtDQUMvQixDQUFDO0FBbUNGOztHQUVHO0FBQ0gsTUFBYSxxQkFBc0IsU0FBUSxVQUFVLENBQUMsU0FBUztJQUU3RDs7O09BR0c7SUFDSSxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQXVDLEVBQUUsU0FBNkM7UUFDakgsdUVBQXVFO1FBQ3ZFLHNFQUFzRTtRQUN0RSxJQUFJLE9BQU8sU0FBUyxLQUFLLFdBQVc7WUFBRSxTQUFTLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2RCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsY0FBYyxLQUFLLE9BQU8sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDO1FBQ3hFLElBQUksT0FBTyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQzVFLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFDRCxrRUFBa0U7UUFDbEUsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUkscUJBQXFCLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RyxDQUFDO0lBMENELFlBQVksS0FBdUMsRUFBRSxFQUFVLEVBQUUsS0FBa0M7UUFFakcsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQVBuQix3RUFBd0U7UUFDeEUsb0ZBQW9GO1FBQzdFLGFBQVEsR0FBVyxFQUFFLENBQUM7UUFDdEIsa0JBQWEsR0FBVyxFQUFFLENBQUM7UUFNaEMsZ0NBQWdDO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUV6QywyRkFBMkY7UUFDM0YsSUFBSSxPQUFPLEtBQUssS0FBSyxXQUFXO1lBQUUsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUM3QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixJQUFJLEdBQUcsTUFBTSxHQUFHLENBQUM7UUFDL0QsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUMsWUFBWSxJQUFJLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQztRQUN4RSxJQUFJLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDLHNCQUFzQixJQUFJLElBQUksQ0FBQztRQUNuRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLElBQUksQ0FBQztRQUN6RCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBRS9CLDhEQUE4RDtRQUM5RCwwREFBMEQ7UUFDMUQsU0FBUyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNqQyxTQUFTLENBQUMsd0JBQXdCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ2xFLElBQUksS0FBSyxDQUFDLGNBQWMsS0FBSyxPQUFPLENBQUMsY0FBYyxDQUFDLE9BQU8sSUFBSSxDQUFDLDhCQUFzQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUNuSCxNQUFNLHVCQUF1QixHQUFHLDhCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsRSxNQUFNLElBQUksS0FBSyxDQUFDLG9FQUFvRSx1QkFBdUIsR0FBRyxDQUFDLENBQUM7UUFDbEgsQ0FBQztRQUVELGdFQUFnRTtRQUNoRSxNQUFNLElBQUksR0FBRyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFO1lBQ3ZELFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsaUJBQWlCLEVBQUU7Z0JBQ2pCLGdCQUFnQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7Z0JBQ3ZDLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTthQUNoQztTQUNGLENBQUMsQ0FBQztRQUVILDJFQUEyRTtRQUMzRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7SUFFakQsQ0FBQztJQUVEOzs7T0FHRztJQUNJLGdCQUFnQixDQUFDLGFBQXNEO1FBRTVFLHFFQUFxRTtRQUNyRSx3RUFBd0U7UUFDeEUsNENBQTRDO1FBQzVDLE1BQU0sMEJBQTBCLEdBQUc7WUFDakMsTUFBTSxFQUFFO2dCQUNOLGFBQWEsRUFBRTtvQkFDYixVQUFVLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLHNCQUFzQixFQUFFO2lCQUNyRDtnQkFDRCxRQUFRLEVBQUU7b0JBQ1IsVUFBVSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtpQkFDaEQ7YUFDRjtTQUNGLENBQUM7UUFDRixNQUFNLHVCQUF1QixHQUFHO1lBQzlCLE9BQU8sRUFBRSxtQkFBbUI7WUFDNUIsTUFBTSxFQUFFLFlBQVk7WUFDcEIsVUFBVSxFQUFFO2dCQUNWLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztnQkFDekIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO2dCQUN2QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07Z0JBQ25CLDBCQUEwQixFQUFFLDBCQUEwQjthQUN2RDtZQUNELGtCQUFrQixFQUFFLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDO1NBQ2hFLENBQUM7UUFDRixJQUFJLGVBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsMEJBQTBCLEVBQUU7WUFDdEUsTUFBTSxFQUFFLGFBQWE7WUFDckIsUUFBUSxFQUFFLHVCQUF1QjtZQUNqQyxRQUFRLEVBQUUsdUJBQXVCO1NBQ2xDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSSxTQUFTLENBQUMsaUJBQTBEO1FBRXpFLHFFQUFxRTtRQUNyRSx3RUFBd0U7UUFDeEUsNENBQTRDO1FBQzVDLE1BQU0sZUFBZSxHQUFHO1lBQ3RCLE9BQU8sRUFBRSxtQkFBbUI7WUFDNUIsTUFBTSxFQUFFLFNBQVM7WUFDakIsVUFBVSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDdkYsa0JBQWtCLEVBQUUsZUFBZSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUM7U0FDaEUsQ0FBQztRQUNGLE1BQU0sUUFBUSxHQUFHLElBQUksZUFBZSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUMvRSxNQUFNLEVBQUUsaUJBQWlCO1lBQ3pCLFFBQVEsRUFBRSxlQUFlO1lBQ3pCLFFBQVEsRUFBRSxlQUFlO1NBQzFCLENBQUMsQ0FBQztRQUVILGdGQUFnRjtRQUNoRixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQzFGLElBQUksQ0FBQyxhQUFhLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixDQUFDLG1EQUFtRCxDQUFDLENBQUM7SUFFdEcsQ0FBQzs7QUFuS0gsc0RBcUtDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlULTBcblxuXG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgbWFuYWdlZGJsb2NrY2hhaW4gZnJvbSAnYXdzLWNkay1saWIvYXdzLW1hbmFnZWRibG9ja2NoYWluJztcbmltcG9ydCAqIGFzIGN1c3RvbXJlc291cmNlcyBmcm9tICdhd3MtY2RrLWxpYi9jdXN0b20tcmVzb3VyY2VzJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5cbmltcG9ydCAqIGFzIG5ldHdvcmsgZnJvbSAnLi9uZXR3b3JrJztcbmltcG9ydCAqIGFzIHV0aWxpdGllcyBmcm9tICcuL3V0aWxpdGllcyc7XG5cblxuLyoqXG4gKiBTdXBwb3J0ZWQgaW5zdGFuY2UgdHlwZXMgZm9yIE1hbmFnZWQgQmxvY2tjaGFpbiBub2Rlc1xuICovXG5leHBvcnQgZW51bSBJbnN0YW5jZVR5cGUge1xuICBCVVJTVEFCTEUzX1NNQUxMID0gJ2JjLnQzLnNtYWxsJyxcbiAgQlVSU1RBQkxFM19NRURJVU0gPSAnYmMudDMubWVkaXVtJyxcbiAgQlVSU1RBQkxFM19MQVJHRSA9ICdiYy50My5sYXJnZScsXG4gIEJVUlNUQUJMRTNfWExBUkdFID0gJ2JjLnQzLnhsYXJnZScsXG4gIFNUQU5EQVJENV9MQVJHRSA9ICdiYy5tNS5sYXJnZScsXG4gIFNUQU5EQVJENV9YTEFSR0UgPSAnYmMubTUueGxhcmdlJyxcbiAgU1RBTkRBUkQ1X1hMQVJHRTIgPSAnYmMubTUuMnhsYXJnZScsXG4gIFNUQU5EQVJENV9YTEFSR0U0ID0gJ2JjLm01LjR4bGFyZ2UnLFxuICBDT01QVVRFNV9MQVJHRSA9ICdiYy5jNS5sYXJnZScsXG4gIENPTVBVVEU1X1hMQVJHRSA9ICdiYy5jNS54bGFyZ2UnLFxuICBDT01QVVRFNV9YTEFSR0UyID0gJ2JjLmM1LjJ4bGFyZ2UnLFxuICBDT01QVVRFNV9YTEFSR0U0ID0gJ2JjLmM1LjR4bGFyZ2UnLFxufVxuXG5cbi8qKlxuICogVmFsaWQgaW5zdGFuY2UgdHlwZXMgZm9yIHN0YXJ0ZXIgbmV0d29ya3NcbiAqL1xuZXhwb3J0IGNvbnN0IFNUQVJURVJfSU5TVEFOQ0VfVFlQRVMgPSBbXG4gIEluc3RhbmNlVHlwZS5CVVJTVEFCTEUzX1NNQUxMLFxuICBJbnN0YW5jZVR5cGUuQlVSU1RBQkxFM19NRURJVU0sXG5dO1xuXG5cbi8qKlxuICogQ29uc3RydWN0IHByb3BlcnRpZXMgZm9yIGBIeXBlcmxlZGdlckZhYnJpY05vZGVgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHlwZXJsZWRnZXJGYWJyaWNOb2RlUHJvcHMge1xuXG4gIC8qKlxuICAgKiBUaGUgQXZhaWxhYmlsaXR5IFpvbmUgaW4gd2hpY2ggdGhlIG5vZGUgd2lsbCBiZSBjcmVhdGVkXG4gICAqIEBkZWZhdWx0IC0gVGhlIGZpcnN0IEFaIGluIHRoZSByZWdpb25cbiAgICovXG4gIHJlYWRvbmx5IGF2YWlsYWJpbGl0eVpvbmU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gTWFuYWdlZCBCbG9ja2NoYWluIGluc3RhbmNlIHR5cGUgZm9yIHRoZSBub2RlXG4gICAqIEBkZWZhdWx0IC0gQlVSU1RBQkxFM19TTUFMTFxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFuY2VUeXBlPzogSW5zdGFuY2VUeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgY29uZmlndXJhdGlvbiB0byBlbmFibGUgb3IgZGlzYWJsZSBjaGFpbmNvZGUgbG9nZ2luZ1xuICAgKiBAZGVmYXVsdCAtIHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUNoYWluY29kZUxvZ2dpbmc/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgY29uZmlndXJhdGlvbiB0byBlbmFibGUgb3IgZGlzYWJsZSBub2RlIGxvZ2dpbmdcbiAgICogQGRlZmF1bHQgLSB0cnVlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVOb2RlTG9nZ2luZz86IGJvb2xlYW47XG5cbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSBIeXBlcmxlZGdlciBGYWJyaWMgbm9kZSBvbiBhbiBBbWF6b24gTWFuYWdlZCBCbG9ja2NoYWluIG5ldHdvcmtcbiAqL1xuZXhwb3J0IGNsYXNzIEh5cGVybGVkZ2VyRmFicmljTm9kZSBleHRlbmRzIGNvbnN0cnVjdHMuQ29uc3RydWN0IHtcblxuICAvKipcbiAgICogQnVpbGQgb3V0IGEgbGlzdCBvZiBIeXBlcmxlZGdlckZhYnJpY05vZGUgY29uc3RydWN0cyBnaXZlbiBhIGxpc3Qgb2YgaW5wdXQgcHJvcGVydHlcbiAgICogb2JqZWN0czsgYWRkaXRpb25hbGx5IGNoZWNrcyB0byBlbnN1cmUgbm9kZSBjb3VudCBpcyBzdXBwb3J0ZWQgZ2l2ZW4gdGhlIG5ldHdvcmsgdHlwZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb25zdHJ1Y3ROb2RlcyhzY29wZTogbmV0d29yay5IeXBlcmxlZGdlckZhYnJpY05ldHdvcmssIG5vZGVQcm9wcz86IEFycmF5PEh5cGVybGVkZ2VyRmFicmljTm9kZVByb3BzPikge1xuICAgIC8vIElmIG5vIG5vZGUgY29uZmlndXJhdGlvbnMgYXJlIHByb3ZpZGVkLCBjcmVhdGUgb25lOyB0aGUgZW1wdHkgb2JqZWN0XG4gICAgLy8gd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCBkZWZhdWx0cyB3aGVuIHBhc3NlZCB0byB0aGUgbm9kZSBjb25zdHJ1Y3RvclxuICAgIGlmICh0eXBlb2Ygbm9kZVByb3BzID09PSAndW5kZWZpbmVkJykgbm9kZVByb3BzID0gW3t9XTtcbiAgICBjb25zdCBzdGFydGVyID0gc2NvcGUubmV0d29ya0VkaXRpb24gPT09IG5ldHdvcmsuTmV0d29ya0VkaXRpb24uU1RBUlRFUjtcbiAgICBpZiAoc3RhcnRlciAmJiBub2RlUHJvcHMubGVuZ3RoID4gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBIHN0YXJ0ZXIgbmV0d29yayBjYW4gaGF2ZSBhdCBtb3N0IDIgbm9kZXMgcGVyIG1lbWJlci4nKTtcbiAgICB9XG4gICAgaWYgKCFzdGFydGVyICYmIG5vZGVQcm9wcy5sZW5ndGggPiAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Egc3RhbmRhcmQgbmV0d29yayBjYW4gaGF2ZSBhdCBtb3N0IDMgbm9kZXMgcGVyIG1lbWJlci4nKTtcbiAgICB9XG4gICAgLy8gQ29uc3RydWN0IHRoZSBub2RlIGxpc3QsIHVzaW5nIGFuIGluZGV4IHZhbHVlIGluIHRoZSBpZGVudGlmaWVyXG4gICAgcmV0dXJuIEFycmF5LmZyb20obm9kZVByb3BzLmVudHJpZXMoKSkubWFwKGUgPT4gbmV3IEh5cGVybGVkZ2VyRmFicmljTm9kZShzY29wZSwgYE5vZGUke2VbMF19YCwgZVsxXSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hbmFnZWQgQmxvY2tjaGFpbiBuZXR3b3JrIGlkZW50aWZpZXJcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuZXR3b3JrSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogTWFuYWdlZCBCbG9ja2NoYWluIG1lbWJlciBpZGVudGlmaWVyXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbWVtYmVySWQ6IHN0cmluZztcblxuICAvKipcbiAgICogTWFuYWdlZCBCbG9ja2NoYWluIG5vZGUgaWRlbnRpZmllciBnZW5lcmF0ZWQgb24gY29uc3RydWN0aW9uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbm9kZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBdmFpbGFiaWxpdHkgWm9uZSBpbiB3aGljaCB0aGUgbm9kZSBleGlzdHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhdmFpbGFiaWxpdHlab25lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gTWFuYWdlZCBCbG9ja2NoYWluIGluc3RhbmNlIHR5cGUgZm9yIHRoZSBub2RlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaW5zdGFuY2VUeXBlOiBJbnN0YW5jZVR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBjb25maWd1cmF0aW9uIHRvIGVuYWJsZSBvciBkaXNhYmxlIGNoYWluY29kZSBsb2dnaW5nXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZW5hYmxlQ2hhaW5jb2RlTG9nZ2luZzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGNvbmZpZ3VyYXRpb24gdG8gZW5hYmxlIG9yIGRpc2FibGUgbm9kZSBsb2dnaW5nXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZW5hYmxlTm9kZUxvZ2dpbmc6IGJvb2xlYW47XG5cbiAgLy8gVGhlc2UgY2Fubm90IGJlIHJlYWRvbmx5IHNpbmNlIHRoZXkgaGF2ZSB0byBiZSBzZXQgYWZ0ZXIgY29uc3RydWN0aW9uXG4gIC8vIGR1ZSB0aGUgcmFjZSBjb25kaXRpb24gZG9jdW1lbnRlZCBpbiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLzE4MjM3LlxuICBwdWJsaWMgZW5kcG9pbnQ6IHN0cmluZyA9ICcnO1xuICBwdWJsaWMgZXZlbnRFbmRwb2ludDogc3RyaW5nID0gJyc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IG5ldHdvcmsuSHlwZXJsZWRnZXJGYWJyaWNOZXR3b3JrLCBpZDogc3RyaW5nLCBwcm9wcz86IEh5cGVybGVkZ2VyRmFicmljTm9kZVByb3BzKSB7XG5cbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gQ29sbGVjdCBtZXRhZGF0YSBvbiB0aGUgc3RhY2tcbiAgICBjb25zdCByZWdpb24gPSBjZGsuU3RhY2sub2YodGhpcykucmVnaW9uO1xuXG4gICAgLy8gUG9wdWxhdGUgaW5zdGFuY2UgdmFyaWFibGVzIGZyb20gaW5wdXQgcHJvcGVydGllcywgdXNpbmcgZGVmYXVsdHMgaWYgdmFsdWVzIG5vdCBwcm92aWRlZFxuICAgIGlmICh0eXBlb2YgcHJvcHMgPT09ICd1bmRlZmluZWQnKSBwcm9wcyA9IHt9O1xuICAgIHRoaXMuYXZhaWxhYmlsaXR5Wm9uZSA9IHByb3BzLmF2YWlsYWJpbGl0eVpvbmUgPz8gYCR7cmVnaW9ufWFgO1xuICAgIHRoaXMuaW5zdGFuY2VUeXBlID0gcHJvcHMuaW5zdGFuY2VUeXBlID8/IEluc3RhbmNlVHlwZS5CVVJTVEFCTEUzX1NNQUxMO1xuICAgIHRoaXMuZW5hYmxlQ2hhaW5jb2RlTG9nZ2luZyA9IHByb3BzLmVuYWJsZUNoYWluY29kZUxvZ2dpbmcgPz8gdHJ1ZTtcbiAgICB0aGlzLmVuYWJsZU5vZGVMb2dnaW5nID0gcHJvcHMuZW5hYmxlTm9kZUxvZ2dpbmcgPz8gdHJ1ZTtcbiAgICB0aGlzLm5ldHdvcmtJZCA9IHNjb3BlLm5ldHdvcmtJZDtcbiAgICB0aGlzLm1lbWJlcklkID0gc2NvcGUubWVtYmVySWQ7XG5cbiAgICAvLyBFbnN1cmUgdGhlIHBhcmFtZXRlcnMgY2FwdHVyZWQgYWJvdmUgYXJlIHZhbGlkLCBzbyB3ZSBkb24ndFxuICAgIC8vIG5lZWQgdG8gd2FpdCB1bnRpbCBkZXBsb3ltZW50IHRpbWUgdG8gZGlzY292ZXIgYW4gZXJyb3JcbiAgICB1dGlsaXRpZXMudmFsaWRhdGVSZWdpb24ocmVnaW9uKTtcbiAgICB1dGlsaXRpZXMudmFsaWRhdGVBdmFpbGFiaWxpdHlab25lKHJlZ2lvbiwgdGhpcy5hdmFpbGFiaWxpdHlab25lKTtcbiAgICBpZiAoc2NvcGUubmV0d29ya0VkaXRpb24gPT09IG5ldHdvcmsuTmV0d29ya0VkaXRpb24uU1RBUlRFUiAmJiAhU1RBUlRFUl9JTlNUQU5DRV9UWVBFUy5pbmNsdWRlcyh0aGlzLmluc3RhbmNlVHlwZSkpIHtcbiAgICAgIGNvbnN0IHN0YXJ0ZXJJbnN0YW5jZVR5cGVMaXN0ID0gU1RBUlRFUl9JTlNUQU5DRV9UWVBFUy5qb2luKCcsICcpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnN0YW5jZSB0eXBlIGluIGEgc3RhcnRlciBuZXR3b3JrIG11c3QgYmUgb25lIG9mIHRoZSBmb2xsb3dpbmc6ICR7c3RhcnRlckluc3RhbmNlVHlwZUxpc3R9LmApO1xuICAgIH1cblxuICAgIC8vIEJ1aWxkIG91dCB0aGUgQ2xvdWRmb3JtYXRpb24gY29uc3RydWN0IGZvciB0aGUgbmV0d29yay9tZW1iZXJcbiAgICBjb25zdCBub2RlID0gbmV3IG1hbmFnZWRibG9ja2NoYWluLkNmbk5vZGUodGhpcywgJ05vZGUnLCB7XG4gICAgICBuZXR3b3JrSWQ6IHRoaXMubmV0d29ya0lkLFxuICAgICAgbWVtYmVySWQ6IHRoaXMubWVtYmVySWQsXG4gICAgICBub2RlQ29uZmlndXJhdGlvbjoge1xuICAgICAgICBhdmFpbGFiaWxpdHlab25lOiB0aGlzLmF2YWlsYWJpbGl0eVpvbmUsXG4gICAgICAgIGluc3RhbmNlVHlwZTogdGhpcy5pbnN0YW5jZVR5cGUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gQ2FwdHVyZSBkYXRhIGluY2x1ZGVkIGluIHRoZSBDbG91ZGZvcm1hdGlvbiBvdXRwdXQgaW4gaW5zdGFuY2UgdmFyaWFibGVzXG4gICAgdGhpcy5ub2RlSWQgPSBub2RlLmdldEF0dCgnTm9kZUlkJykudG9TdHJpbmcoKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBsb2dnaW5nIGZvciB0aGUgbm9kZSB2aWEgU0RLIGNhbGw7IHRoaXMgZnVuY3Rpb25cbiAgICogc2hvdWxkIGJlIG1lcmdlZCBiYWNrIGludG8gdGhlIGNvbnN0cnVjdG9yIG9uY2UgdGhlIHJhY2UgY29uZGl0aW9uIGlzIHNvbHZlZFxuICAgKi9cbiAgcHVibGljIGNvbmZpZ3VyZUxvZ2dpbmcoc2RrQ2FsbFBvbGljeTogY3VzdG9tcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlUG9saWN5KSB7XG5cbiAgICAvLyBUaGlzIGNhbGwgZG9lc24ndCByZWFsbHkgbmVlZCBhbGwgdGhlIHBlcm1pc3Npb25zIGl0cyB1c2luZyBpbiB0aGVcbiAgICAvLyBwcm92aWRlZCBwb2xpY3ksIGJ1dCBzaW5jZSB0aGUgcG9saWN5IG11c3QgYmUgY29uc3RydWN0ZWQgYWxsIGF0IG9uY2VcbiAgICAvLyB0aGlzIGlzIHRoZSBvbmx5IHdheSB0byBkbyBpdCBlZmZlY3RpdmVseVxuICAgIGNvbnN0IGxvZ1B1Ymxpc2hpbmdDb25maWd1cmF0aW9uID0ge1xuICAgICAgRmFicmljOiB7XG4gICAgICAgIENoYWluY29kZUxvZ3M6IHtcbiAgICAgICAgICBDbG91ZHdhdGNoOiB7IEVuYWJsZWQ6IHRoaXMuZW5hYmxlQ2hhaW5jb2RlTG9nZ2luZyB9LFxuICAgICAgICB9LFxuICAgICAgICBQZWVyTG9nczoge1xuICAgICAgICAgIENsb3Vkd2F0Y2g6IHsgRW5hYmxlZDogdGhpcy5lbmFibGVOb2RlTG9nZ2luZyB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGNvbmZpZ3VyZU5vZGVMb2dTZGtDYWxsID0ge1xuICAgICAgc2VydmljZTogJ01hbmFnZWRCbG9ja2NoYWluJyxcbiAgICAgIGFjdGlvbjogJ3VwZGF0ZU5vZGUnLFxuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICBOZXR3b3JrSWQ6IHRoaXMubmV0d29ya0lkLFxuICAgICAgICBNZW1iZXJJZDogdGhpcy5tZW1iZXJJZCxcbiAgICAgICAgTm9kZUlkOiB0aGlzLm5vZGVJZCxcbiAgICAgICAgTG9nUHVibGlzaGluZ0NvbmZpZ3VyYXRpb246IGxvZ1B1Ymxpc2hpbmdDb25maWd1cmF0aW9uLFxuICAgICAgfSxcbiAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogY3VzdG9tcmVzb3VyY2VzLlBoeXNpY2FsUmVzb3VyY2VJZC5vZignSWQnKSxcbiAgICB9O1xuICAgIG5ldyBjdXN0b21yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgJ0NvbmZpZ3VyZU5vZGVMb2dSZXNvdXJjZScsIHtcbiAgICAgIHBvbGljeTogc2RrQ2FsbFBvbGljeSxcbiAgICAgIG9uQ3JlYXRlOiBjb25maWd1cmVOb2RlTG9nU2RrQ2FsbCxcbiAgICAgIG9uVXBkYXRlOiBjb25maWd1cmVOb2RlTG9nU2RrQ2FsbCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3B1bGF0ZSB0aGUgb3V0cHV0IHByb3BlcnRpZXMgdGhhdCBtdXN0IGJlIGZldGNoZWQgdmlhIFNESyBjYWxsOyB0aGlzIGZ1bmN0aW9uXG4gICAqIHNob3VsZCBiZSBtZXJnZWQgYmFjayBpbnRvIHRoZSBjb25zdHJ1Y3RvciBvbmNlIHRoZSByYWNlIGNvbmRpdGlvbiBpcyBzb2x2ZWRcbiAgICovXG4gIHB1YmxpYyBmZXRjaERhdGEoZGF0YVNka0NhbGxQb2xpY3k6IGN1c3RvbXJlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeSkge1xuXG4gICAgLy8gVGhpcyBjYWxsIGRvZXNuJ3QgcmVhbGx5IG5lZWQgYWxsIHRoZSBwZXJtaXNzaW9ucyBpdHMgdXNpbmcgaW4gdGhlXG4gICAgLy8gcHJvdmlkZWQgcG9saWN5LCBidXQgc2luY2UgdGhlIHBvbGljeSBtdXN0IGJlIGNvbnN0cnVjdGVkIGFsbCBhdCBvbmNlXG4gICAgLy8gdGhpcyBpcyB0aGUgb25seSB3YXkgdG8gZG8gaXQgZWZmZWN0aXZlbHlcbiAgICBjb25zdCBub2RlRGF0YVNka0NhbGwgPSB7XG4gICAgICBzZXJ2aWNlOiAnTWFuYWdlZEJsb2NrY2hhaW4nLFxuICAgICAgYWN0aW9uOiAnZ2V0Tm9kZScsXG4gICAgICBwYXJhbWV0ZXJzOiB7IE5ldHdvcmtJZDogdGhpcy5uZXR3b3JrSWQsIE1lbWJlcklkOiB0aGlzLm1lbWJlcklkLCBOb2RlSWQ6IHRoaXMubm9kZUlkIH0sXG4gICAgICBwaHlzaWNhbFJlc291cmNlSWQ6IGN1c3RvbXJlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQub2YoJ0lkJyksXG4gICAgfTtcbiAgICBjb25zdCBub2RlRGF0YSA9IG5ldyBjdXN0b21yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgJ05vZGVEYXRhUmVzb3VyY2UnLCB7XG4gICAgICBwb2xpY3k6IGRhdGFTZGtDYWxsUG9saWN5LFxuICAgICAgb25DcmVhdGU6IG5vZGVEYXRhU2RrQ2FsbCxcbiAgICAgIG9uVXBkYXRlOiBub2RlRGF0YVNka0NhbGwsXG4gICAgfSk7XG5cbiAgICAvLyBHcmFiIGl0ZW1zIG91dCBvZiB0aGUgYWJvdmUgcmV0dXJuIHZhbHVlcyBhbmQgc3RpY2sgdGhlbSBpbiBvdXRwdXQgcHJvcGVydGllc1xuICAgIHRoaXMuZW5kcG9pbnQgPSBub2RlRGF0YS5nZXRSZXNwb25zZUZpZWxkKCdOb2RlLkZyYW1ld29ya0F0dHJpYnV0ZXMuRmFicmljLlBlZXJFbmRwb2ludCcpO1xuICAgIHRoaXMuZXZlbnRFbmRwb2ludCA9IG5vZGVEYXRhLmdldFJlc3BvbnNlRmllbGQoJ05vZGUuRnJhbWV3b3JrQXR0cmlidXRlcy5GYWJyaWMuUGVlckV2ZW50RW5kcG9pbnQnKTtcblxuICB9XG5cbn1cbiJdfQ==