@neo-one/server-plugin-network
Version:
NEO•ONE Server network plugin.
411 lines (409 loc) • 48.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const node_core_1 = require("@neo-one/node-core");
const server_plugin_1 = require("@neo-one/server-plugin");
const cross_fetch_1 = tslib_1.__importDefault(require("cross-fetch"));
const execa_1 = tslib_1.__importDefault(require("execa"));
const fs = tslib_1.__importStar(require("fs-extra"));
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const path = tslib_1.__importStar(require("path"));
const operators_1 = require("rxjs/operators");
const NodeAdapter_1 = require("./NodeAdapter");
const DEFAULT_RPC_URLS = [
'http://node1.nyc3.bridgeprotocol.io:10332',
'http://node2.nyc3.bridgeprotocol.io:10332',
'https://seed1.switcheo.network:10331',
'https://seed2.switcheo.network:10331',
'https://seed3.switcheo.network:10331',
'http://seed1.aphelion-neo.com:10332',
'http://seed2.aphelion-neo.com:10332',
'http://seed3.aphelion-neo.com:10332',
'http://seed4.aphelion-neo.com:10332',
];
const DEFAULT_SEEDS = [
{ type: 'tcp', host: 'node1.nyc3.bridgeprotocol.io', port: 10333 },
{ type: 'tcp', host: 'node2.nyc3.bridgeprotocol.io', port: 10333 },
{ type: 'tcp', host: 'seed1.switcheo.com', port: 10333 },
{ type: 'tcp', host: 'seed2.switcheo.com', port: 10333 },
{ type: 'tcp', host: 'seed3.switcheo.com', port: 10333 },
{ type: 'tcp', host: 'seed1.aphelion-neo.com', port: 10333 },
{ type: 'tcp', host: 'seed2.aphelion-neo.com', port: 10333 },
{ type: 'tcp', host: 'seed3.aphelion-neo.com', port: 10333 },
{ type: 'tcp', host: 'seed4.aphelion-neo.com', port: 10333 },
];
const makeDefaultConfig = (dataPath) => ({
log: {
level: 'info',
maxSize: 10 * 1024 * 1024,
maxFiles: 5,
},
settings: {
test: false,
},
environment: {
dataPath: path.resolve(dataPath, 'node'),
rpc: {},
node: {},
network: {},
},
options: {
node: {
consensus: {
enabled: false,
options: { privateKey: 'default', privateNet: false },
},
rpcURLs: [...DEFAULT_RPC_URLS],
},
network: {
seeds: DEFAULT_SEEDS.map(node_core_1.createEndpoint),
},
rpc: {
server: {
keepAliveTimeout: 60000,
},
liveHealthCheck: {
rpcURLs: DEFAULT_RPC_URLS,
offset: 1,
timeoutMS: 5000,
},
readyHealthCheck: {
rpcURLs: DEFAULT_RPC_URLS,
offset: 1,
timeoutMS: 5000,
},
rateLimit: {
enabled: true,
duration: 60000,
rate: 6000000,
},
},
},
});
exports.createNodeConfig = ({ dataPath, defaultConfig = makeDefaultConfig(dataPath), }) => new server_plugin_1.Config({
name: 'node',
defaultConfig,
schema: {
type: 'object',
required: ['log'],
properties: {
log: {
type: 'object',
required: ['level', 'maxSize', 'maxFiles'],
properties: {
level: { type: 'string' },
maxSize: { type: 'number' },
maxFiles: { type: 'number' },
},
},
settings: {
type: 'object',
required: ['test'],
properties: {
test: { type: 'boolean' },
privateNet: { type: 'boolean' },
secondsPerBlock: { type: 'number' },
standbyValidators: { type: 'array', items: { type: 'string' } },
},
},
environment: {
type: 'object',
required: ['dataPath', 'rpc', 'node', 'network'],
properties: {
dataPath: { type: 'string' },
rpc: {
type: 'object',
required: [],
properties: {
http: {
type: 'object',
required: ['host', 'port'],
properties: {
host: { type: 'string' },
port: { type: 'number' },
},
},
https: {
type: 'object',
required: ['host', 'port', 'key', 'cert'],
properties: {
host: { type: 'string' },
port: { type: 'number' },
key: { type: 'string' },
cert: { type: 'string' },
},
},
},
},
node: {
type: 'object',
required: [],
properties: {
externalPort: { type: 'number' },
},
},
network: {
type: 'object',
required: [],
properties: {
listenTCP: {
type: 'object',
required: ['port'],
properties: {
host: { type: 'string' },
port: { type: 'number' },
},
},
externalEndpoints: {
type: 'array',
items: { type: 'string' },
},
connectPeersDelayMS: { type: 'number' },
socketTimeoutMS: { type: 'number' },
},
},
},
},
options: {
type: 'object',
required: ['node', 'network', 'rpc'],
properties: {
node: {
type: 'object',
required: ['consensus', 'rpcURLs'],
properties: {
consensus: {
type: 'object',
required: ['enabled', 'options'],
properties: {
enabled: { type: 'boolean' },
options: {
type: 'object',
required: ['privateKey', 'privateNet'],
properties: {
privateKey: { type: 'string' },
privateNet: { type: 'boolean' },
},
},
},
},
rpcURLs: { type: 'array', items: { type: 'string' } },
},
},
network: {
type: 'object',
required: ['seeds'],
properties: {
seeds: { type: 'array', items: { type: 'string' } },
maxConnectedPeers: { type: 'number' },
},
},
rpc: {
type: 'object',
required: ['server', 'liveHealthCheck', 'readyHealthCheck'],
properties: {
server: {
type: 'object',
required: ['keepAliveTimeout'],
properties: {
keepAliveTimeout: { type: 'number' },
},
},
liveHealthCheck: {
type: 'object',
required: ['rpcURLs', 'offset', 'timeoutMS'],
properties: {
rpcURLs: { type: 'array', items: { type: 'string' } },
offset: { type: 'number' },
timeoutMS: { type: 'number' },
},
},
readyHealthCheck: {
type: 'object',
required: ['rpcURLs', 'offset', 'timeoutMS'],
properties: {
rpcURLs: { type: 'array', items: { type: 'string' } },
offset: { type: 'number' },
timeoutMS: { type: 'number' },
},
},
},
},
},
},
},
},
configPath: dataPath,
});
class NEOONENodeAdapter extends NodeAdapter_1.NodeAdapter {
constructor({ monitor, name, binary, dataPath, settings, }) {
super({
monitor: monitor.at('neo_one_node_adapter'),
name,
binary,
dataPath,
settings,
});
}
getDebug() {
return super
.getDebug()
.concat([
['Process ID', this.mutableProcess === undefined ? 'null' : `${this.mutableProcess.pid}`],
['Config Path', this.mutableConfig === undefined ? 'null' : this.mutableConfig.configPath],
]);
}
getNodeStatus() {
return {
rpcAddress: this.getAddress('/rpc'),
tcpAddress: `localhost:${this.mutableSettings.listenTCPPort}`,
telemetryAddress: `http://localhost:${this.mutableSettings.telemetryPort}/metrics`,
};
}
async isLive() {
return this.checkRPC('/live_health_check');
}
async isReady() {
return this.checkRPC('/ready_health_check');
}
async createInternal() {
await this.writeSettings(this.mutableSettings);
}
async updateInternal(settings) {
const restart = await this.writeSettings(settings);
if (restart && this.mutableProcess !== undefined) {
await this.stop();
await this.start();
}
}
async startInternal() {
if (this.mutableProcess === undefined) {
const child = execa_1.default(this.binary.cmd, this.binary.firstArgs.concat(['start', 'node', this.dataPath]), {
windowsHide: true,
stdio: 'ignore',
});
this.mutableProcess = child;
child
.then(() => {
this.monitor.log({
name: 'neo_node_adapter_node_exit',
message: 'Child process exited',
});
this.mutableProcess = undefined;
})
.catch((error) => {
this.monitor.logError({
name: 'neo_node_adapter_node_error',
message: 'Child process exited with an error.',
error,
});
this.mutableProcess = undefined;
});
}
}
async stopInternal() {
const child = this.mutableProcess;
this.mutableProcess = undefined;
if (child !== undefined) {
await server_plugin_1.killProcess(child.pid);
}
}
async checkRPC(rpcPath) {
try {
const response = await cross_fetch_1.default(this.getAddress(rpcPath));
return response.ok;
}
catch (error) {
if (error.code !== 'ECONNREFUSED') {
this.monitor.withData({ [this.monitor.labels.HTTP_PATH]: rpcPath }).logError({
name: 'http_client_request',
message: 'Failed to check RPC.',
error,
});
}
return false;
}
}
getAddress(rpcPath) {
return `http://localhost:${this.mutableSettings.rpcPort}${rpcPath}`;
}
async writeSettings(settings) {
let config = this.mutableConfig;
if (config === undefined) {
config = exports.createNodeConfig({
dataPath: this.dataPath,
defaultConfig: this.createConfig(settings),
});
this.mutableConfig = config;
}
const nodeConfig = await config.config$.pipe(operators_1.take(1)).toPromise();
const newNodeConfig = this.createConfig(settings);
await fs.ensureDir(newNodeConfig.environment.dataPath);
await config.update({ config: newNodeConfig });
return !(lodash_1.default.isEqual(nodeConfig.settings, newNodeConfig.settings) &&
lodash_1.default.isEqual(nodeConfig.environment, newNodeConfig.environment));
}
createConfig(settings) {
return {
log: {
level: 'info',
maxSize: 10 * 1024 * 1024,
maxFiles: 5,
},
settings: {
test: settings.isTestNet,
privateNet: settings.privateNet,
secondsPerBlock: settings.secondsPerBlock,
standbyValidators: settings.standbyValidators,
address: settings.address,
},
environment: {
dataPath: path.resolve(this.dataPath, 'chain'),
rpc: {
http: {
port: settings.rpcPort,
host: '0.0.0.0',
},
},
node: {
externalPort: settings.listenTCPPort,
},
network: {
listenTCP: {
port: settings.listenTCPPort,
host: '0.0.0.0',
},
},
telemetry: {
port: settings.telemetryPort,
},
},
options: {
node: {
consensus: settings.consensus,
rpcURLs: settings.rpcEndpoints,
},
network: {
seeds: settings.seeds,
},
rpc: {
server: {
keepAliveTimeout: 60000,
},
liveHealthCheck: {
rpcURLs: settings.rpcEndpoints,
offset: 1,
timeoutMS: 5000,
},
readyHealthCheck: {
rpcURLs: settings.rpcEndpoints,
offset: 1,
timeoutMS: 5000,
},
},
},
};
}
}
exports.NEOONENodeAdapter = NEOONENodeAdapter;
//# sourceMappingURL=data:application/json;charset=utf8;base64,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SSxFQUFFO29CQUNKLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztvQkFDN0IsT0FBTyxFQUFFLFFBQVEsQ0FBQyxZQUFZO2lCQUMvQjtnQkFDRCxPQUFPLEVBQUU7b0JBQ1AsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO2lCQUN0QjtnQkFDRCxHQUFHLEVBQUU7b0JBQ0gsTUFBTSxFQUFFO3dCQUNOLGdCQUFnQixFQUFFLEtBQUs7cUJBQ3hCO29CQUNELGVBQWUsRUFBRTt3QkFDZixPQUFPLEVBQUUsUUFBUSxDQUFDLFlBQVk7d0JBQzlCLE1BQU0sRUFBRSxDQUFDO3dCQUNULFNBQVMsRUFBRSxJQUFJO3FCQUNoQjtvQkFDRCxnQkFBZ0IsRUFBRTt3QkFDaEIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxZQUFZO3dCQUM5QixNQUFNLEVBQUUsQ0FBQzt3QkFDVCxTQUFTLEVBQUUsSUFBSTtxQkFDaEI7aUJBQ0Y7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUEvTUQsOENBK01DIiwiZmlsZSI6Im5lby1vbmUtc2VydmVyLXBsdWdpbi1uZXR3b3JrL3NyYy9ub2RlL05FT09ORU5vZGVBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW9uaXRvciB9IGZyb20gJ0BuZW8tb25lL21vbml0b3InO1xuaW1wb3J0IHsgRnVsbE5vZGVFbnZpcm9ubWVudCwgRnVsbE5vZGVPcHRpb25zIH0gZnJvbSAnQG5lby1vbmUvbm9kZSc7XG5pbXBvcnQgeyBjcmVhdGVFbmRwb2ludCwgRW5kcG9pbnRDb25maWcgfSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUnO1xuaW1wb3J0IHsgQmluYXJ5LCBDb25maWcsIERlc2NyaWJlVGFibGUsIGtpbGxQcm9jZXNzIH0gZnJvbSAnQG5lby1vbmUvc2VydmVyLXBsdWdpbic7XG5pbXBvcnQgZmV0Y2ggZnJvbSAnY3Jvc3MtZmV0Y2gnO1xuaW1wb3J0IGV4ZWNhIGZyb20gJ2V4ZWNhJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE5vZGVTZXR0aW5ncyB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IE5vZGVBZGFwdGVyLCBOb2RlU3RhdHVzIH0gZnJvbSAnLi9Ob2RlQWRhcHRlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZUNvbmZpZyB7XG4gIHJlYWRvbmx5IGxvZzoge1xuICAgIHJlYWRvbmx5IGxldmVsOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgbWF4U2l6ZTogbnVtYmVyO1xuICAgIHJlYWRvbmx5IG1heEZpbGVzOiBudW1iZXI7XG4gIH07XG5cbiAgcmVhZG9ubHkgc2V0dGluZ3M6IHtcbiAgICByZWFkb25seSB0ZXN0PzogYm9vbGVhbjtcbiAgICByZWFkb25seSBwcml2YXRlTmV0PzogYm9vbGVhbjtcbiAgICByZWFkb25seSBzZWNvbmRzUGVyQmxvY2s/OiBudW1iZXI7XG4gICAgcmVhZG9ubHkgc3RhbmRieVZhbGlkYXRvcnM/OiByZWFkb25seSBzdHJpbmdbXTtcbiAgICByZWFkb25seSBhZGRyZXNzPzogc3RyaW5nO1xuICB9O1xuXG4gIHJlYWRvbmx5IGVudmlyb25tZW50OiBGdWxsTm9kZUVudmlyb25tZW50O1xuICByZWFkb25seSBvcHRpb25zOiBGdWxsTm9kZU9wdGlvbnM7XG59XG5cbmNvbnN0IERFRkFVTFRfUlBDX1VSTFM6IHJlYWRvbmx5IHN0cmluZ1tdID0gW1xuICAnaHR0cDovL25vZGUxLm55YzMuYnJpZGdlcHJvdG9jb2wuaW86MTAzMzInLFxuICAnaHR0cDovL25vZGUyLm55YzMuYnJpZGdlcHJvdG9jb2wuaW86MTAzMzInLFxuICAnaHR0cHM6Ly9zZWVkMS5zd2l0Y2hlby5uZXR3b3JrOjEwMzMxJyxcbiAgJ2h0dHBzOi8vc2VlZDIuc3dpdGNoZW8ubmV0d29yazoxMDMzMScsXG4gICdodHRwczovL3NlZWQzLnN3aXRjaGVvLm5ldHdvcms6MTAzMzEnLFxuICAnaHR0cDovL3NlZWQxLmFwaGVsaW9uLW5lby5jb206MTAzMzInLFxuICAnaHR0cDovL3NlZWQyLmFwaGVsaW9uLW5lby5jb206MTAzMzInLFxuICAnaHR0cDovL3NlZWQzLmFwaGVsaW9uLW5lby5jb206MTAzMzInLFxuICAnaHR0cDovL3NlZWQ0LmFwaGVsaW9uLW5lby5jb206MTAzMzInLFxuXTtcblxuY29uc3QgREVGQVVMVF9TRUVEUzogcmVhZG9ubHkgRW5kcG9pbnRDb25maWdbXSA9IFtcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ25vZGUxLm55YzMuYnJpZGdlcHJvdG9jb2wuaW8nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnbm9kZTIubnljMy5icmlkZ2Vwcm90b2NvbC5pbycsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkMS5zd2l0Y2hlby5jb20nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnc2VlZDIuc3dpdGNoZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ3NlZWQzLnN3aXRjaGVvLmNvbScsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkMS5hcGhlbGlvbi1uZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ3NlZWQyLmFwaGVsaW9uLW5lby5jb20nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnc2VlZDMuYXBoZWxpb24tbmVvLmNvbScsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkNC5hcGhlbGlvbi1uZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbl07XG5cbmNvbnN0IG1ha2VEZWZhdWx0Q29uZmlnID0gKGRhdGFQYXRoOiBzdHJpbmcpOiBOb2RlQ29uZmlnID0+ICh7XG4gIGxvZzoge1xuICAgIGxldmVsOiAnaW5mbycsXG4gICAgbWF4U2l6ZTogMTAgKiAxMDI0ICogMTAyNCxcbiAgICBtYXhGaWxlczogNSxcbiAgfSxcbiAgc2V0dGluZ3M6IHtcbiAgICB0ZXN0OiBmYWxzZSxcbiAgfSxcbiAgZW52aXJvbm1lbnQ6IHtcbiAgICBkYXRhUGF0aDogcGF0aC5yZXNvbHZlKGRhdGFQYXRoLCAnbm9kZScpLFxuICAgIHJwYzoge30sXG4gICAgbm9kZToge30sXG4gICAgbmV0d29yazoge30sXG4gIH0sXG4gIG9wdGlvbnM6IHtcbiAgICBub2RlOiB7XG4gICAgICBjb25zZW5zdXM6IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgIG9wdGlvbnM6IHsgcHJpdmF0ZUtleTogJ2RlZmF1bHQnLCBwcml2YXRlTmV0OiBmYWxzZSB9LFxuICAgICAgfSxcbiAgICAgIHJwY1VSTHM6IFsuLi5ERUZBVUxUX1JQQ19VUkxTXSxcbiAgICB9LFxuICAgIG5ldHdvcms6IHtcbiAgICAgIHNlZWRzOiBERUZBVUxUX1NFRURTLm1hcChjcmVhdGVFbmRwb2ludCksXG4gICAgfSxcbiAgICBycGM6IHtcbiAgICAgIHNlcnZlcjoge1xuICAgICAgICBrZWVwQWxpdmVUaW1lb3V0OiA2MDAwMCxcbiAgICAgIH0sXG4gICAgICBsaXZlSGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgcnBjVVJMczogREVGQVVMVF9SUENfVVJMUyxcbiAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICB0aW1lb3V0TVM6IDUwMDAsXG4gICAgICB9LFxuICAgICAgcmVhZHlIZWFsdGhDaGVjazoge1xuICAgICAgICBycGNVUkxzOiBERUZBVUxUX1JQQ19VUkxTLFxuICAgICAgICBvZmZzZXQ6IDEsXG4gICAgICAgIHRpbWVvdXRNUzogNTAwMCxcbiAgICAgIH0sXG4gICAgICByYXRlTGltaXQ6IHtcbiAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgZHVyYXRpb246IDYwMDAwLFxuICAgICAgICByYXRlOiA2MDAwMDAwLFxuICAgICAgfSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVOb2RlQ29uZmlnID0gKHtcbiAgZGF0YVBhdGgsXG4gIGRlZmF1bHRDb25maWcgPSBtYWtlRGVmYXVsdENvbmZpZyhkYXRhUGF0aCksXG59OiB7XG4gIHJlYWRvbmx5IGRhdGFQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlZmF1bHRDb25maWc/OiBOb2RlQ29uZmlnO1xufSk6IENvbmZpZzxOb2RlQ29uZmlnPiA9PlxuICBuZXcgQ29uZmlnKHtcbiAgICBuYW1lOiAnbm9kZScsXG4gICAgZGVmYXVsdENvbmZpZyxcbiAgICBzY2hlbWE6IHtcbiAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgcmVxdWlyZWQ6IFsnbG9nJ10sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGxvZzoge1xuICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgIHJlcXVpcmVkOiBbJ2xldmVsJywgJ21heFNpemUnLCAnbWF4RmlsZXMnXSxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBsZXZlbDogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgICAgICAgbWF4U2l6ZTogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgbWF4RmlsZXM6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBzZXR0aW5nczoge1xuICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgIHJlcXVpcmVkOiBbJ3Rlc3QnXSxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICB0ZXN0OiB7IHR5cGU6ICdib29sZWFuJyB9LFxuICAgICAgICAgICAgcHJpdmF0ZU5ldDogeyB0eXBlOiAnYm9vbGVhbicgfSxcbiAgICAgICAgICAgIHNlY29uZHNQZXJCbG9jazogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgc3RhbmRieVZhbGlkYXRvcnM6IHsgdHlwZTogJ2FycmF5JywgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgcmVxdWlyZWQ6IFsnZGF0YVBhdGgnLCAncnBjJywgJ25vZGUnLCAnbmV0d29yayddLFxuICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIGRhdGFQYXRoOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICBycGM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIGh0dHA6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnaG9zdCcsICdwb3J0J10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGhvc3Q6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgICAgcG9ydDogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAgICAgaHR0cHM6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnaG9zdCcsICdwb3J0JywgJ2tleScsICdjZXJ0J10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGhvc3Q6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgICAgcG9ydDogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgICAgY2VydDogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5vZGU6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIGV4dGVybmFsUG9ydDogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5ldHdvcms6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIGxpc3RlblRDUDoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydwb3J0J10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGhvc3Q6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgICAgcG9ydDogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAgICAgZXh0ZXJuYWxFbmRwb2ludHM6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdhcnJheScsXG4gICAgICAgICAgICAgICAgICBpdGVtczogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgICAgICBjb25uZWN0UGVlcnNEZWxheU1TOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgc29ja2V0VGltZW91dE1TOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICByZXF1aXJlZDogWydub2RlJywgJ25ldHdvcmsnLCAncnBjJ10sXG4gICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgbm9kZToge1xuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnY29uc2Vuc3VzJywgJ3JwY1VSTHMnXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIGNvbnNlbnN1czoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydlbmFibGVkJywgJ29wdGlvbnMnXSxcbiAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgZW5hYmxlZDogeyB0eXBlOiAnYm9vbGVhbicgfSxcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ3ByaXZhdGVLZXknLCAncHJpdmF0ZU5ldCddLFxuICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaXZhdGVLZXk6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaXZhdGVOZXQ6IHsgdHlwZTogJ2Jvb2xlYW4nIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBycGNVUkxzOiB7IHR5cGU6ICdhcnJheScsIGl0ZW1zOiB7IHR5cGU6ICdzdHJpbmcnIH0gfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXR3b3JrOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICByZXF1aXJlZDogWydzZWVkcyddLFxuICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgc2VlZHM6IHsgdHlwZTogJ2FycmF5JywgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSB9LFxuICAgICAgICAgICAgICAgIG1heENvbm5lY3RlZFBlZXJzOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnBjOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICByZXF1aXJlZDogWydzZXJ2ZXInLCAnbGl2ZUhlYWx0aENoZWNrJywgJ3JlYWR5SGVhbHRoQ2hlY2snXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHNlcnZlcjoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydrZWVwQWxpdmVUaW1lb3V0J10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGtlZXBBbGl2ZVRpbWVvdXQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsaXZlSGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsncnBjVVJMcycsICdvZmZzZXQnLCAndGltZW91dE1TJ10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHJwY1VSTHM6IHsgdHlwZTogJ2FycmF5JywgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSB9LFxuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgICAgdGltZW91dE1TOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVhZHlIZWFsdGhDaGVjazoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydycGNVUkxzJywgJ29mZnNldCcsICd0aW1lb3V0TVMnXSxcbiAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgcnBjVVJMczogeyB0eXBlOiAnYXJyYXknLCBpdGVtczogeyB0eXBlOiAnc3RyaW5nJyB9IH0sXG4gICAgICAgICAgICAgICAgICAgIG9mZnNldDogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgICAgICB0aW1lb3V0TVM6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBjb25maWdQYXRoOiBkYXRhUGF0aCxcbiAgfSk7XG5cbmV4cG9ydCBjbGFzcyBORU9PTkVOb2RlQWRhcHRlciBleHRlbmRzIE5vZGVBZGFwdGVyIHtcbiAgcHJpdmF0ZSBtdXRhYmxlQ29uZmlnOiBDb25maWc8Tm9kZUNvbmZpZz4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgbXV0YWJsZVByb2Nlc3M6IGV4ZWNhLkV4ZWNhQ2hpbGRQcm9jZXNzIHwgdW5kZWZpbmVkO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcih7XG4gICAgbW9uaXRvcixcbiAgICBuYW1lLFxuICAgIGJpbmFyeSxcbiAgICBkYXRhUGF0aCxcbiAgICBzZXR0aW5ncyxcbiAgfToge1xuICAgIHJlYWRvbmx5IG1vbml0b3I6IE1vbml0b3I7XG4gICAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGJpbmFyeTogQmluYXJ5O1xuICAgIHJlYWRvbmx5IGRhdGFQYXRoOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgc2V0dGluZ3M6IE5vZGVTZXR0aW5ncztcbiAgfSkge1xuICAgIHN1cGVyKHtcbiAgICAgIG1vbml0b3I6IG1vbml0b3IuYXQoJ25lb19vbmVfbm9kZV9hZGFwdGVyJyksXG4gICAgICBuYW1lLFxuICAgICAgYmluYXJ5LFxuICAgICAgZGF0YVBhdGgsXG4gICAgICBzZXR0aW5ncyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXREZWJ1ZygpOiBEZXNjcmliZVRhYmxlIHtcbiAgICByZXR1cm4gc3VwZXJcbiAgICAgIC5nZXREZWJ1ZygpXG4gICAgICAuY29uY2F0KFtcbiAgICAgICAgWydQcm9jZXNzIElEJywgdGhpcy5tdXRhYmxlUHJvY2VzcyA9PT0gdW5kZWZpbmVkID8gJ251bGwnIDogYCR7dGhpcy5tdXRhYmxlUHJvY2Vzcy5waWR9YF0gYXMgY29uc3QsXG4gICAgICAgIFsnQ29uZmlnIFBhdGgnLCB0aGlzLm11dGFibGVDb25maWcgPT09IHVuZGVmaW5lZCA/ICdudWxsJyA6IHRoaXMubXV0YWJsZUNvbmZpZy5jb25maWdQYXRoXSBhcyBjb25zdCxcbiAgICAgIF0pO1xuICB9XG5cbiAgcHVibGljIGdldE5vZGVTdGF0dXMoKTogTm9kZVN0YXR1cyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJwY0FkZHJlc3M6IHRoaXMuZ2V0QWRkcmVzcygnL3JwYycpLFxuICAgICAgdGNwQWRkcmVzczogYGxvY2FsaG9zdDoke3RoaXMubXV0YWJsZVNldHRpbmdzLmxpc3RlblRDUFBvcnR9YCxcbiAgICAgIHRlbGVtZXRyeUFkZHJlc3M6IGBodHRwOi8vbG9jYWxob3N0OiR7dGhpcy5tdXRhYmxlU2V0dGluZ3MudGVsZW1ldHJ5UG9ydH0vbWV0cmljc2AsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0xpdmUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tSUEMoJy9saXZlX2hlYWx0aF9jaGVjaycpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzUmVhZHkoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tSUEMoJy9yZWFkeV9oZWFsdGhfY2hlY2snKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVJbnRlcm5hbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLndyaXRlU2V0dGluZ3ModGhpcy5tdXRhYmxlU2V0dGluZ3MpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZUludGVybmFsKHNldHRpbmdzOiBOb2RlU2V0dGluZ3MpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN0YXJ0ID0gYXdhaXQgdGhpcy53cml0ZVNldHRpbmdzKHNldHRpbmdzKTtcbiAgICBpZiAocmVzdGFydCAmJiB0aGlzLm11dGFibGVQcm9jZXNzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RvcCgpO1xuICAgICAgYXdhaXQgdGhpcy5zdGFydCgpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBzdGFydEludGVybmFsKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm11dGFibGVQcm9jZXNzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGNoaWxkID0gZXhlY2EodGhpcy5iaW5hcnkuY21kLCB0aGlzLmJpbmFyeS5maXJzdEFyZ3MuY29uY2F0KFsnc3RhcnQnLCAnbm9kZScsIHRoaXMuZGF0YVBhdGhdKSwge1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIHdpbmRvd3NIaWRlOiB0cnVlLFxuICAgICAgICBzdGRpbzogJ2lnbm9yZScsXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5tdXRhYmxlUHJvY2VzcyA9IGNoaWxkO1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgICBjaGlsZFxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5tb25pdG9yLmxvZyh7XG4gICAgICAgICAgICBuYW1lOiAnbmVvX25vZGVfYWRhcHRlcl9ub2RlX2V4aXQnLFxuICAgICAgICAgICAgbWVzc2FnZTogJ0NoaWxkIHByb2Nlc3MgZXhpdGVkJyxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRoaXMubXV0YWJsZVByb2Nlc3MgPSB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5tb25pdG9yLmxvZ0Vycm9yKHtcbiAgICAgICAgICAgIG5hbWU6ICduZW9fbm9kZV9hZGFwdGVyX25vZGVfZXJyb3InLFxuICAgICAgICAgICAgbWVzc2FnZTogJ0NoaWxkIHByb2Nlc3MgZXhpdGVkIHdpdGggYW4gZXJyb3IuJyxcbiAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgdGhpcy5tdXRhYmxlUHJvY2VzcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHN0b3BJbnRlcm5hbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjaGlsZCA9IHRoaXMubXV0YWJsZVByb2Nlc3M7XG4gICAgdGhpcy5tdXRhYmxlUHJvY2VzcyA9IHVuZGVmaW5lZDtcbiAgICBpZiAoY2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYXdhaXQga2lsbFByb2Nlc3MoY2hpbGQucGlkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrUlBDKHJwY1BhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZ2V0QWRkcmVzcyhycGNQYXRoKSk7XG5cbiAgICAgIHJldHVybiByZXNwb25zZS5vaztcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yLmNvZGUgIT09ICdFQ09OTlJFRlVTRUQnKSB7XG4gICAgICAgIHRoaXMubW9uaXRvci53aXRoRGF0YSh7IFt0aGlzLm1vbml0b3IubGFiZWxzLkhUVFBfUEFUSF06IHJwY1BhdGggfSkubG9nRXJyb3Ioe1xuICAgICAgICAgIG5hbWU6ICdodHRwX2NsaWVudF9yZXF1ZXN0JyxcbiAgICAgICAgICBtZXNzYWdlOiAnRmFpbGVkIHRvIGNoZWNrIFJQQy4nLFxuICAgICAgICAgIGVycm9yLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWRkcmVzcyhycGNQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBgaHR0cDovL2xvY2FsaG9zdDoke3RoaXMubXV0YWJsZVNldHRpbmdzLnJwY1BvcnR9JHtycGNQYXRofWA7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHdyaXRlU2V0dGluZ3Moc2V0dGluZ3M6IE5vZGVTZXR0aW5ncyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGxldCBjb25maWcgPSB0aGlzLm11dGFibGVDb25maWc7XG4gICAgaWYgKGNvbmZpZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25maWcgPSBjcmVhdGVOb2RlQ29uZmlnKHtcbiAgICAgICAgZGF0YVBhdGg6IHRoaXMuZGF0YVBhdGgsXG4gICAgICAgIGRlZmF1bHRDb25maWc6IHRoaXMuY3JlYXRlQ29uZmlnKHNldHRpbmdzKSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLm11dGFibGVDb25maWcgPSBjb25maWc7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUNvbmZpZyA9IGF3YWl0IGNvbmZpZy5jb25maWckLnBpcGUodGFrZSgxKSkudG9Qcm9taXNlKCk7XG4gICAgY29uc3QgbmV3Tm9kZUNvbmZpZyA9IHRoaXMuY3JlYXRlQ29uZmlnKHNldHRpbmdzKTtcbiAgICBhd2FpdCBmcy5lbnN1cmVEaXIobmV3Tm9kZUNvbmZpZy5lbnZpcm9ubWVudC5kYXRhUGF0aCk7XG4gICAgYXdhaXQgY29uZmlnLnVwZGF0ZSh7IGNvbmZpZzogbmV3Tm9kZUNvbmZpZyB9KTtcblxuICAgIHJldHVybiAhKFxuICAgICAgXy5pc0VxdWFsKG5vZGVDb25maWcuc2V0dGluZ3MsIG5ld05vZGVDb25maWcuc2V0dGluZ3MpICYmXG4gICAgICBfLmlzRXF1YWwobm9kZUNvbmZpZy5lbnZpcm9ubWVudCwgbmV3Tm9kZUNvbmZpZy5lbnZpcm9ubWVudClcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVDb25maWcoc2V0dGluZ3M6IE5vZGVTZXR0aW5ncyk6IE5vZGVDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBsb2c6IHtcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgbWF4U2l6ZTogMTAgKiAxMDI0ICogMTAyNCxcbiAgICAgICAgbWF4RmlsZXM6IDUsXG4gICAgICB9LFxuICAgICAgc2V0dGluZ3M6IHtcbiAgICAgICAgdGVzdDogc2V0dGluZ3MuaXNUZXN0TmV0LFxuICAgICAgICBwcml2YXRlTmV0OiBzZXR0aW5ncy5wcml2YXRlTmV0LFxuICAgICAgICBzZWNvbmRzUGVyQmxvY2s6IHNldHRpbmdzLnNlY29uZHNQZXJCbG9jayxcbiAgICAgICAgc3RhbmRieVZhbGlkYXRvcnM6IHNldHRpbmdzLnN0YW5kYnlWYWxpZGF0b3JzLFxuICAgICAgICBhZGRyZXNzOiBzZXR0aW5ncy5hZGRyZXNzLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIGRhdGFQYXRoOiBwYXRoLnJlc29sdmUodGhpcy5kYXRhUGF0aCwgJ2NoYWluJyksXG4gICAgICAgIHJwYzoge1xuICAgICAgICAgIGh0dHA6IHtcbiAgICAgICAgICAgIHBvcnQ6IHNldHRpbmdzLnJwY1BvcnQsXG4gICAgICAgICAgICBob3N0OiAnMC4wLjAuMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgbm9kZToge1xuICAgICAgICAgIGV4dGVybmFsUG9ydDogc2V0dGluZ3MubGlzdGVuVENQUG9ydCxcbiAgICAgICAgfSxcbiAgICAgICAgbmV0d29yazoge1xuICAgICAgICAgIGxpc3RlblRDUDoge1xuICAgICAgICAgICAgcG9ydDogc2V0dGluZ3MubGlzdGVuVENQUG9ydCxcbiAgICAgICAgICAgIGhvc3Q6ICcwLjAuMC4wJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB0ZWxlbWV0cnk6IHtcbiAgICAgICAgICBwb3J0OiBzZXR0aW5ncy50ZWxlbWV0cnlQb3J0LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgbm9kZToge1xuICAgICAgICAgIGNvbnNlbnN1czogc2V0dGluZ3MuY29uc2Vuc3VzLFxuICAgICAgICAgIHJwY1VSTHM6IHNldHRpbmdzLnJwY0VuZHBvaW50cyxcbiAgICAgICAgfSxcbiAgICAgICAgbmV0d29yazoge1xuICAgICAgICAgIHNlZWRzOiBzZXR0aW5ncy5zZWVkcyxcbiAgICAgICAgfSxcbiAgICAgICAgcnBjOiB7XG4gICAgICAgICAgc2VydmVyOiB7XG4gICAgICAgICAgICBrZWVwQWxpdmVUaW1lb3V0OiA2MDAwMCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxpdmVIZWFsdGhDaGVjazoge1xuICAgICAgICAgICAgcnBjVVJMczogc2V0dGluZ3MucnBjRW5kcG9pbnRzLFxuICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgdGltZW91dE1TOiA1MDAwLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVhZHlIZWFsdGhDaGVjazoge1xuICAgICAgICAgICAgcnBjVVJMczogc2V0dGluZ3MucnBjRW5kcG9pbnRzLFxuICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgdGltZW91dE1TOiA1MDAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cbn1cbiJdfQ==