UNPKG

48.2 kBJavaScriptView Raw
1import { createEndpoint } from '@neo-one/node-core-esnext-esm';
2import { Config, killProcess } from '@neo-one/server-plugin-esnext-esm';
3import fetch from 'cross-fetch';
4import execa from 'execa';
5import * as fs from 'fs-extra';
6import _ from 'lodash';
7import * as path from 'path';
8import { take } from 'rxjs/operators';
9import { NodeAdapter } from './NodeAdapter';
10const DEFAULT_RPC_URLS = [
11 'http://node1.nyc3.bridgeprotocol.io:10332',
12 'http://node2.nyc3.bridgeprotocol.io:10332',
13 'https://seed1.switcheo.network:10331',
14 'https://seed2.switcheo.network:10331',
15 'https://seed3.switcheo.network:10331',
16 'http://seed1.aphelion-neo.com:10332',
17 'http://seed2.aphelion-neo.com:10332',
18 'http://seed3.aphelion-neo.com:10332',
19 'http://seed4.aphelion-neo.com:10332',
20];
21const DEFAULT_SEEDS = [
22 { type: 'tcp', host: 'node1.nyc3.bridgeprotocol.io', port: 10333 },
23 { type: 'tcp', host: 'node2.nyc3.bridgeprotocol.io', port: 10333 },
24 { type: 'tcp', host: 'seed1.switcheo.com', port: 10333 },
25 { type: 'tcp', host: 'seed2.switcheo.com', port: 10333 },
26 { type: 'tcp', host: 'seed3.switcheo.com', port: 10333 },
27 { type: 'tcp', host: 'seed1.aphelion-neo.com', port: 10333 },
28 { type: 'tcp', host: 'seed2.aphelion-neo.com', port: 10333 },
29 { type: 'tcp', host: 'seed3.aphelion-neo.com', port: 10333 },
30 { type: 'tcp', host: 'seed4.aphelion-neo.com', port: 10333 },
31];
32const makeDefaultConfig = (dataPath) => ({
33 log: {
34 level: 'info',
35 maxSize: 10 * 1024 * 1024,
36 maxFiles: 5,
37 },
38 settings: {
39 test: false,
40 },
41 environment: {
42 dataPath: path.resolve(dataPath, 'node'),
43 rpc: {},
44 node: {},
45 network: {},
46 },
47 options: {
48 node: {
49 consensus: {
50 enabled: false,
51 options: { privateKey: 'default', privateNet: false },
52 },
53 rpcURLs: [...DEFAULT_RPC_URLS],
54 },
55 network: {
56 seeds: DEFAULT_SEEDS.map(createEndpoint),
57 },
58 rpc: {
59 server: {
60 keepAliveTimeout: 60000,
61 },
62 liveHealthCheck: {
63 rpcURLs: DEFAULT_RPC_URLS,
64 offset: 1,
65 timeoutMS: 5000,
66 },
67 readyHealthCheck: {
68 rpcURLs: DEFAULT_RPC_URLS,
69 offset: 1,
70 timeoutMS: 5000,
71 },
72 },
73 },
74});
75export const createNodeConfig = ({ dataPath, defaultConfig = makeDefaultConfig(dataPath), }) => new Config({
76 name: 'node',
77 defaultConfig,
78 schema: {
79 type: 'object',
80 required: ['log'],
81 properties: {
82 log: {
83 type: 'object',
84 required: ['level', 'maxSize', 'maxFiles'],
85 properties: {
86 level: { type: 'string' },
87 maxSize: { type: 'number' },
88 maxFiles: { type: 'number' },
89 },
90 },
91 settings: {
92 type: 'object',
93 required: ['test'],
94 properties: {
95 test: { type: 'boolean' },
96 privateNet: { type: 'boolean' },
97 secondsPerBlock: { type: 'number' },
98 standbyValidators: { type: 'array', items: { type: 'string' } },
99 },
100 },
101 environment: {
102 type: 'object',
103 required: ['dataPath', 'rpc', 'node', 'network'],
104 properties: {
105 dataPath: { type: 'string' },
106 rpc: {
107 type: 'object',
108 required: [],
109 properties: {
110 http: {
111 type: 'object',
112 required: ['host', 'port'],
113 properties: {
114 host: { type: 'string' },
115 port: { type: 'number' },
116 },
117 },
118 https: {
119 type: 'object',
120 required: ['host', 'port', 'key', 'cert'],
121 properties: {
122 host: { type: 'string' },
123 port: { type: 'number' },
124 key: { type: 'string' },
125 cert: { type: 'string' },
126 },
127 },
128 },
129 },
130 node: {
131 type: 'object',
132 required: [],
133 properties: {
134 externalPort: { type: 'number' },
135 },
136 },
137 network: {
138 type: 'object',
139 required: [],
140 properties: {
141 listenTCP: {
142 type: 'object',
143 required: ['port'],
144 properties: {
145 host: { type: 'string' },
146 port: { type: 'number' },
147 },
148 },
149 externalEndpoints: {
150 type: 'array',
151 items: { type: 'string' },
152 },
153 connectPeersDelayMS: { type: 'number' },
154 socketTimeoutMS: { type: 'number' },
155 },
156 },
157 },
158 },
159 options: {
160 type: 'object',
161 required: ['node', 'network', 'rpc'],
162 properties: {
163 node: {
164 type: 'object',
165 required: ['consensus', 'rpcURLs'],
166 properties: {
167 consensus: {
168 type: 'object',
169 required: ['enabled', 'options'],
170 properties: {
171 enabled: { type: 'boolean' },
172 options: {
173 type: 'object',
174 required: ['privateKey', 'privateNet'],
175 properties: {
176 privateKey: { type: 'string' },
177 privateNet: { type: 'boolean' },
178 },
179 },
180 },
181 },
182 rpcURLs: { type: 'array', items: { type: 'string' } },
183 },
184 },
185 network: {
186 type: 'object',
187 required: ['seeds'],
188 properties: {
189 seeds: { type: 'array', items: { type: 'string' } },
190 maxConnectedPeers: { type: 'number' },
191 },
192 },
193 rpc: {
194 type: 'object',
195 required: ['server', 'liveHealthCheck', 'readyHealthCheck'],
196 properties: {
197 server: {
198 type: 'object',
199 required: ['keepAliveTimeout'],
200 properties: {
201 keepAliveTimeout: { type: 'number' },
202 },
203 },
204 liveHealthCheck: {
205 type: 'object',
206 required: ['rpcURLs', 'offset', 'timeoutMS'],
207 properties: {
208 rpcURLs: { type: 'array', items: { type: 'string' } },
209 offset: { type: 'number' },
210 timeoutMS: { type: 'number' },
211 },
212 },
213 readyHealthCheck: {
214 type: 'object',
215 required: ['rpcURLs', 'offset', 'timeoutMS'],
216 properties: {
217 rpcURLs: { type: 'array', items: { type: 'string' } },
218 offset: { type: 'number' },
219 timeoutMS: { type: 'number' },
220 },
221 },
222 },
223 },
224 },
225 },
226 },
227 },
228 configPath: dataPath,
229});
230export class NEOONENodeAdapter extends NodeAdapter {
231 constructor({ monitor, name, binary, dataPath, settings, }) {
232 super({
233 monitor: monitor.at('neo_one_node_adapter'),
234 name,
235 binary,
236 dataPath,
237 settings,
238 });
239 }
240 getDebug() {
241 return super
242 .getDebug()
243 .concat([
244 ['Process ID', this.mutableProcess === undefined ? 'null' : `${this.mutableProcess.pid}`],
245 ['Config Path', this.mutableConfig === undefined ? 'null' : this.mutableConfig.configPath],
246 ]);
247 }
248 getNodeStatus() {
249 return {
250 rpcAddress: this.getAddress('/rpc'),
251 tcpAddress: `localhost:${this.mutableSettings.listenTCPPort}`,
252 telemetryAddress: `http://localhost:${this.mutableSettings.telemetryPort}/metrics`,
253 };
254 }
255 async isLive() {
256 return this.checkRPC('/live_health_check');
257 }
258 async isReady() {
259 return this.checkRPC('/ready_health_check');
260 }
261 async createInternal() {
262 await this.writeSettings(this.mutableSettings);
263 }
264 async updateInternal(settings) {
265 const restart = await this.writeSettings(settings);
266 if (restart && this.mutableProcess !== undefined) {
267 await this.stop();
268 await this.start();
269 }
270 }
271 async startInternal() {
272 if (this.mutableProcess === undefined) {
273 const child = execa(this.binary.cmd, this.binary.firstArgs.concat(['start', 'node', this.dataPath]), {
274 // @ts-ignore
275 windowsHide: true,
276 stdio: 'ignore',
277 });
278 this.mutableProcess = child;
279 // tslint:disable-next-line no-floating-promises
280 child
281 .then(() => {
282 this.monitor.log({
283 name: 'neo_node_adapter_node_exit',
284 message: 'Child process exited',
285 });
286 this.mutableProcess = undefined;
287 })
288 .catch((error) => {
289 this.monitor.logError({
290 name: 'neo_node_adapter_node_error',
291 message: 'Child process exited with an error.',
292 error,
293 });
294 this.mutableProcess = undefined;
295 });
296 }
297 }
298 async stopInternal() {
299 const child = this.mutableProcess;
300 this.mutableProcess = undefined;
301 if (child !== undefined) {
302 await killProcess(child.pid);
303 }
304 }
305 async checkRPC(rpcPath) {
306 try {
307 const response = await fetch(this.getAddress(rpcPath));
308 return response.ok;
309 }
310 catch (error) {
311 if (error.code !== 'ECONNREFUSED') {
312 this.monitor.withData({ [this.monitor.labels.HTTP_PATH]: rpcPath }).logError({
313 name: 'http_client_request',
314 message: 'Failed to check RPC.',
315 error,
316 });
317 }
318 return false;
319 }
320 }
321 getAddress(rpcPath) {
322 return `http://localhost:${this.mutableSettings.rpcPort}${rpcPath}`;
323 }
324 async writeSettings(settings) {
325 let config = this.mutableConfig;
326 if (config === undefined) {
327 config = createNodeConfig({
328 dataPath: this.dataPath,
329 defaultConfig: this.createConfig(settings),
330 });
331 this.mutableConfig = config;
332 }
333 const nodeConfig = await config.config$.pipe(take(1)).toPromise();
334 const newNodeConfig = this.createConfig(settings);
335 await fs.ensureDir(newNodeConfig.environment.dataPath);
336 await config.update({ config: newNodeConfig });
337 return !(_.isEqual(nodeConfig.settings, newNodeConfig.settings) &&
338 _.isEqual(nodeConfig.environment, newNodeConfig.environment));
339 }
340 createConfig(settings) {
341 return {
342 log: {
343 level: 'info',
344 maxSize: 10 * 1024 * 1024,
345 maxFiles: 5,
346 },
347 settings: {
348 test: settings.isTestNet,
349 privateNet: settings.privateNet,
350 secondsPerBlock: settings.secondsPerBlock,
351 standbyValidators: settings.standbyValidators,
352 address: settings.address,
353 },
354 environment: {
355 dataPath: path.resolve(this.dataPath, 'chain'),
356 rpc: {
357 http: {
358 port: settings.rpcPort,
359 host: '0.0.0.0',
360 },
361 },
362 node: {
363 externalPort: settings.listenTCPPort,
364 },
365 network: {
366 listenTCP: {
367 port: settings.listenTCPPort,
368 host: '0.0.0.0',
369 },
370 },
371 telemetry: {
372 port: settings.telemetryPort,
373 },
374 },
375 options: {
376 node: {
377 consensus: settings.consensus,
378 rpcURLs: settings.rpcEndpoints,
379 },
380 network: {
381 seeds: settings.seeds,
382 },
383 rpc: {
384 server: {
385 keepAliveTimeout: 60000,
386 },
387 liveHealthCheck: {
388 rpcURLs: settings.rpcEndpoints,
389 offset: 1,
390 timeoutMS: 5000,
391 },
392 readyHealthCheck: {
393 rpcURLs: settings.rpcEndpoints,
394 offset: 1,
395 timeoutMS: 5000,
396 },
397 },
398 },
399 };
400 }
401}
402
403//# sourceMappingURL=data:application/json;charset=utf8;base64,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T0FBTyxFQUFFO29CQUNQLFNBQVMsRUFBRTt3QkFDVCxJQUFJLEVBQUUsUUFBUSxDQUFDLGFBQWE7d0JBQzVCLElBQUksRUFBRSxTQUFTO3FCQUNoQjtpQkFDRjtnQkFDRCxTQUFTLEVBQUU7b0JBQ1QsSUFBSSxFQUFFLFFBQVEsQ0FBQyxhQUFhO2lCQUM3QjthQUNGO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLElBQUksRUFBRTtvQkFDSixTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVM7b0JBQzdCLE9BQU8sRUFBRSxRQUFRLENBQUMsWUFBWTtpQkFDL0I7Z0JBQ0QsT0FBTyxFQUFFO29CQUNQLEtBQUssRUFBRSxRQUFRLENBQUMsS0FBSztpQkFDdEI7Z0JBQ0QsR0FBRyxFQUFFO29CQUNILE1BQU0sRUFBRTt3QkFDTixnQkFBZ0IsRUFBRSxLQUFLO3FCQUN4QjtvQkFDRCxlQUFlLEVBQUU7d0JBQ2YsT0FBTyxFQUFFLFFBQVEsQ0FBQyxZQUFZO3dCQUM5QixNQUFNLEVBQUUsQ0FBQzt3QkFDVCxTQUFTLEVBQUUsSUFBSTtxQkFDaEI7b0JBQ0QsZ0JBQWdCLEVBQUU7d0JBQ2hCLE9BQU8sRUFBRSxRQUFRLENBQUMsWUFBWTt3QkFDOUIsTUFBTSxFQUFFLENBQUM7d0JBQ1QsU0FBUyxFQUFFLElBQUk7cUJBQ2hCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQztDQUNGIiwiZmlsZSI6Im5lby1vbmUtc2VydmVyLXBsdWdpbi1uZXR3b3JrL3NyYy9ub2RlL05FT09ORU5vZGVBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW9uaXRvciB9IGZyb20gJ0BuZW8tb25lL21vbml0b3InO1xuaW1wb3J0IHsgRnVsbE5vZGVFbnZpcm9ubWVudCwgRnVsbE5vZGVPcHRpb25zIH0gZnJvbSAnQG5lby1vbmUvbm9kZSc7XG5pbXBvcnQgeyBjcmVhdGVFbmRwb2ludCwgRW5kcG9pbnRDb25maWcgfSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUnO1xuaW1wb3J0IHsgQmluYXJ5LCBDb25maWcsIERlc2NyaWJlVGFibGUsIGtpbGxQcm9jZXNzIH0gZnJvbSAnQG5lby1vbmUvc2VydmVyLXBsdWdpbic7XG5pbXBvcnQgZmV0Y2ggZnJvbSAnY3Jvc3MtZmV0Y2gnO1xuaW1wb3J0IGV4ZWNhIGZyb20gJ2V4ZWNhJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE5vZGVTZXR0aW5ncyB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IE5vZGVBZGFwdGVyLCBOb2RlU3RhdHVzIH0gZnJvbSAnLi9Ob2RlQWRhcHRlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZUNvbmZpZyB7XG4gIHJlYWRvbmx5IGxvZzoge1xuICAgIHJlYWRvbmx5IGxldmVsOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgbWF4U2l6ZTogbnVtYmVyO1xuICAgIHJlYWRvbmx5IG1heEZpbGVzOiBudW1iZXI7XG4gIH07XG5cbiAgcmVhZG9ubHkgc2V0dGluZ3M6IHtcbiAgICByZWFkb25seSB0ZXN0PzogYm9vbGVhbjtcbiAgICByZWFkb25seSBwcml2YXRlTmV0PzogYm9vbGVhbjtcbiAgICByZWFkb25seSBzZWNvbmRzUGVyQmxvY2s/OiBudW1iZXI7XG4gICAgcmVhZG9ubHkgc3RhbmRieVZhbGlkYXRvcnM/OiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gICAgcmVhZG9ubHkgYWRkcmVzcz86IHN0cmluZztcbiAgfTtcblxuICByZWFkb25seSBlbnZpcm9ubWVudDogRnVsbE5vZGVFbnZpcm9ubWVudDtcbiAgcmVhZG9ubHkgb3B0aW9uczogRnVsbE5vZGVPcHRpb25zO1xufVxuXG5jb25zdCBERUZBVUxUX1JQQ19VUkxTOiBSZWFkb25seUFycmF5PHN0cmluZz4gPSBbXG4gICdodHRwOi8vbm9kZTEubnljMy5icmlkZ2Vwcm90b2NvbC5pbzoxMDMzMicsXG4gICdodHRwOi8vbm9kZTIubnljMy5icmlkZ2Vwcm90b2NvbC5pbzoxMDMzMicsXG4gICdodHRwczovL3NlZWQxLnN3aXRjaGVvLm5ldHdvcms6MTAzMzEnLFxuICAnaHR0cHM6Ly9zZWVkMi5zd2l0Y2hlby5uZXR3b3JrOjEwMzMxJyxcbiAgJ2h0dHBzOi8vc2VlZDMuc3dpdGNoZW8ubmV0d29yazoxMDMzMScsXG4gICdodHRwOi8vc2VlZDEuYXBoZWxpb24tbmVvLmNvbToxMDMzMicsXG4gICdodHRwOi8vc2VlZDIuYXBoZWxpb24tbmVvLmNvbToxMDMzMicsXG4gICdodHRwOi8vc2VlZDMuYXBoZWxpb24tbmVvLmNvbToxMDMzMicsXG4gICdodHRwOi8vc2VlZDQuYXBoZWxpb24tbmVvLmNvbToxMDMzMicsXG5dO1xuXG5jb25zdCBERUZBVUxUX1NFRURTOiBSZWFkb25seUFycmF5PEVuZHBvaW50Q29uZmlnPiA9IFtcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ25vZGUxLm55YzMuYnJpZGdlcHJvdG9jb2wuaW8nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnbm9kZTIubnljMy5icmlkZ2Vwcm90b2NvbC5pbycsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkMS5zd2l0Y2hlby5jb20nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnc2VlZDIuc3dpdGNoZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ3NlZWQzLnN3aXRjaGVvLmNvbScsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkMS5hcGhlbGlvbi1uZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbiAgeyB0eXBlOiAndGNwJywgaG9zdDogJ3NlZWQyLmFwaGVsaW9uLW5lby5jb20nLCBwb3J0OiAxMDMzMyB9LFxuICB7IHR5cGU6ICd0Y3AnLCBob3N0OiAnc2VlZDMuYXBoZWxpb24tbmVvLmNvbScsIHBvcnQ6IDEwMzMzIH0sXG4gIHsgdHlwZTogJ3RjcCcsIGhvc3Q6ICdzZWVkNC5hcGhlbGlvbi1uZW8uY29tJywgcG9ydDogMTAzMzMgfSxcbl07XG5cbmNvbnN0IG1ha2VEZWZhdWx0Q29uZmlnID0gKGRhdGFQYXRoOiBzdHJpbmcpOiBOb2RlQ29uZmlnID0+ICh7XG4gIGxvZzoge1xuICAgIGxldmVsOiAnaW5mbycsXG4gICAgbWF4U2l6ZTogMTAgKiAxMDI0ICogMTAyNCxcbiAgICBtYXhGaWxlczogNSxcbiAgfSxcbiAgc2V0dGluZ3M6IHtcbiAgICB0ZXN0OiBmYWxzZSxcbiAgfSxcbiAgZW52aXJvbm1lbnQ6IHtcbiAgICBkYXRhUGF0aDogcGF0aC5yZXNvbHZlKGRhdGFQYXRoLCAnbm9kZScpLFxuICAgIHJwYzoge30sXG4gICAgbm9kZToge30sXG4gICAgbmV0d29yazoge30sXG4gIH0sXG4gIG9wdGlvbnM6IHtcbiAgICBub2RlOiB7XG4gICAgICBjb25zZW5zdXM6IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgIG9wdGlvbnM6IHsgcHJpdmF0ZUtleTogJ2RlZmF1bHQnLCBwcml2YXRlTmV0OiBmYWxzZSB9LFxuICAgICAgfSxcbiAgICAgIHJwY1VSTHM6IFsuLi5ERUZBVUxUX1JQQ19VUkxTXSxcbiAgICB9LFxuICAgIG5ldHdvcms6IHtcbiAgICAgIHNlZWRzOiBERUZBVUxUX1NFRURTLm1hcChjcmVhdGVFbmRwb2ludCksXG4gICAgfSxcbiAgICBycGM6IHtcbiAgICAgIHNlcnZlcjoge1xuICAgICAgICBrZWVwQWxpdmVUaW1lb3V0OiA2MDAwMCxcbiAgICAgIH0sXG4gICAgICBsaXZlSGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgcnBjVVJMczogREVGQVVMVF9SUENfVVJMUyxcbiAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICB0aW1lb3V0TVM6IDUwMDAsXG4gICAgICB9LFxuICAgICAgcmVhZHlIZWFsdGhDaGVjazoge1xuICAgICAgICBycGNVUkxzOiBERUZBVUxUX1JQQ19VUkxTLFxuICAgICAgICBvZmZzZXQ6IDEsXG4gICAgICAgIHRpbWVvdXRNUzogNTAwMCxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5leHBvcnQgY29uc3QgY3JlYXRlTm9kZUNvbmZpZyA9ICh7XG4gIGRhdGFQYXRoLFxuICBkZWZhdWx0Q29uZmlnID0gbWFrZURlZmF1bHRDb25maWcoZGF0YVBhdGgpLFxufToge1xuICByZWFkb25seSBkYXRhUGF0aDogc3RyaW5nO1xuICByZWFkb25seSBkZWZhdWx0Q29uZmlnPzogTm9kZUNvbmZpZztcbn0pOiBDb25maWc8Tm9kZUNvbmZpZz4gPT5cbiAgbmV3IENvbmZpZyh7XG4gICAgbmFtZTogJ25vZGUnLFxuICAgIGRlZmF1bHRDb25maWcsXG4gICAgc2NoZW1hOiB7XG4gICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgIHJlcXVpcmVkOiBbJ2xvZyddLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBsb2c6IHtcbiAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICByZXF1aXJlZDogWydsZXZlbCcsICdtYXhTaXplJywgJ21heEZpbGVzJ10sXG4gICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgbGV2ZWw6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgIG1heFNpemU6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgIG1heEZpbGVzOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgc2V0dGluZ3M6IHtcbiAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICByZXF1aXJlZDogWyd0ZXN0J10sXG4gICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgdGVzdDogeyB0eXBlOiAnYm9vbGVhbicgfSxcbiAgICAgICAgICAgIHByaXZhdGVOZXQ6IHsgdHlwZTogJ2Jvb2xlYW4nIH0sXG4gICAgICAgICAgICBzZWNvbmRzUGVyQmxvY2s6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgIHN0YW5kYnlWYWxpZGF0b3JzOiB7IHR5cGU6ICdhcnJheScsIGl0ZW1zOiB7IHR5cGU6ICdzdHJpbmcnIH0gfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgIHJlcXVpcmVkOiBbJ2RhdGFQYXRoJywgJ3JwYycsICdub2RlJywgJ25ldHdvcmsnXSxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBkYXRhUGF0aDogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgICAgICAgcnBjOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICByZXF1aXJlZDogW10sXG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBodHRwOiB7XG4gICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ2hvc3QnLCAncG9ydCddLFxuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBob3N0OiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgICAgIGh0dHBzOiB7XG4gICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ2hvc3QnLCAncG9ydCcsICdrZXknLCAnY2VydCddLFxuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBob3N0OiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgICAga2V5OiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICAgICAgICAgIGNlcnQ6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub2RlOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICByZXF1aXJlZDogW10sXG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBleHRlcm5hbFBvcnQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXR3b3JrOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICByZXF1aXJlZDogW10sXG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5UQ1A6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsncG9ydCddLFxuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBob3N0OiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgICAgIGV4dGVybmFsRW5kcG9pbnRzOiB7XG4gICAgICAgICAgICAgICAgICB0eXBlOiAnYXJyYXknLFxuICAgICAgICAgICAgICAgICAgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAgICAgY29ubmVjdFBlZXJzRGVsYXlNUzogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgIHNvY2tldFRpbWVvdXRNUzogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgcmVxdWlyZWQ6IFsnbm9kZScsICduZXR3b3JrJywgJ3JwYyddLFxuICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIG5vZGU6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ2NvbnNlbnN1cycsICdycGNVUkxzJ10sXG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBjb25zZW5zdXM6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnZW5hYmxlZCcsICdvcHRpb25zJ10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHsgdHlwZTogJ2Jvb2xlYW4nIH0sXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydwcml2YXRlS2V5JywgJ3ByaXZhdGVOZXQnXSxcbiAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcml2YXRlS2V5OiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwcml2YXRlTmV0OiB7IHR5cGU6ICdib29sZWFuJyB9LFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcnBjVVJMczogeyB0eXBlOiAnYXJyYXknLCBpdGVtczogeyB0eXBlOiAnc3RyaW5nJyB9IH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV0d29yazoge1xuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnc2VlZHMnXSxcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHNlZWRzOiB7IHR5cGU6ICdhcnJheScsIGl0ZW1zOiB7IHR5cGU6ICdzdHJpbmcnIH0gfSxcbiAgICAgICAgICAgICAgICBtYXhDb25uZWN0ZWRQZWVyczogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJwYzoge1xuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsnc2VydmVyJywgJ2xpdmVIZWFsdGhDaGVjaycsICdyZWFkeUhlYWx0aENoZWNrJ10sXG4gICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBzZXJ2ZXI6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsna2VlcEFsaXZlVGltZW91dCddLFxuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBrZWVwQWxpdmVUaW1lb3V0OiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbGl2ZUhlYWx0aENoZWNrOiB7XG4gICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ3JwY1VSTHMnLCAnb2Zmc2V0JywgJ3RpbWVvdXRNUyddLFxuICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICBycGNVUkxzOiB7IHR5cGU6ICdhcnJheScsIGl0ZW1zOiB7IHR5cGU6ICdzdHJpbmcnIH0gfSxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXRNUzogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlYWR5SGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IFsncnBjVVJMcycsICdvZmZzZXQnLCAndGltZW91dE1TJ10sXG4gICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHJwY1VSTHM6IHsgdHlwZTogJ2FycmF5JywgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSB9LFxuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IHsgdHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICAgICAgdGltZW91dE1TOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAgY29uZmlnUGF0aDogZGF0YVBhdGgsXG4gIH0pO1xuXG5leHBvcnQgY2xhc3MgTkVPT05FTm9kZUFkYXB0ZXIgZXh0ZW5kcyBOb2RlQWRhcHRlciB7XG4gIHByaXZhdGUgbXV0YWJsZUNvbmZpZzogQ29uZmlnPE5vZGVDb25maWc+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG11dGFibGVQcm9jZXNzOiBleGVjYS5FeGVjYUNoaWxkUHJvY2VzcyB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioe1xuICAgIG1vbml0b3IsXG4gICAgbmFtZSxcbiAgICBiaW5hcnksXG4gICAgZGF0YVBhdGgsXG4gICAgc2V0dGluZ3MsXG4gIH06IHtcbiAgICByZWFkb25seSBtb25pdG9yOiBNb25pdG9yO1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgICByZWFkb25seSBiaW5hcnk6IEJpbmFyeTtcbiAgICByZWFkb25seSBkYXRhUGF0aDogc3RyaW5nO1xuICAgIHJlYWRvbmx5IHNldHRpbmdzOiBOb2RlU2V0dGluZ3M7XG4gIH0pIHtcbiAgICBzdXBlcih7XG4gICAgICBtb25pdG9yOiBtb25pdG9yLmF0KCduZW9fb25lX25vZGVfYWRhcHRlcicpLFxuICAgICAgbmFtZSxcbiAgICAgIGJpbmFyeSxcbiAgICAgIGRhdGFQYXRoLFxuICAgICAgc2V0dGluZ3MsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0RGVidWcoKTogRGVzY3JpYmVUYWJsZSB7XG4gICAgcmV0dXJuIHN1cGVyXG4gICAgICAuZ2V0RGVidWcoKVxuICAgICAgLmNvbmNhdChbXG4gICAgICAgIFsnUHJvY2VzcyBJRCcsIHRoaXMubXV0YWJsZVByb2Nlc3MgPT09IHVuZGVmaW5lZCA/ICdudWxsJyA6IGAke3RoaXMubXV0YWJsZVByb2Nlc3MucGlkfWBdLFxuICAgICAgICBbJ0NvbmZpZyBQYXRoJywgdGhpcy5tdXRhYmxlQ29uZmlnID09PSB1bmRlZmluZWQgPyAnbnVsbCcgOiB0aGlzLm11dGFibGVDb25maWcuY29uZmlnUGF0aF0sXG4gICAgICBdKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXROb2RlU3RhdHVzKCk6IE5vZGVTdGF0dXMge1xuICAgIHJldHVybiB7XG4gICAgICBycGNBZGRyZXNzOiB0aGlzLmdldEFkZHJlc3MoJy9ycGMnKSxcbiAgICAgIHRjcEFkZHJlc3M6IGBsb2NhbGhvc3Q6JHt0aGlzLm11dGFibGVTZXR0aW5ncy5saXN0ZW5UQ1BQb3J0fWAsXG4gICAgICB0ZWxlbWV0cnlBZGRyZXNzOiBgaHR0cDovL2xvY2FsaG9zdDoke3RoaXMubXV0YWJsZVNldHRpbmdzLnRlbGVtZXRyeVBvcnR9L21ldHJpY3NgLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNMaXZlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmNoZWNrUlBDKCcvbGl2ZV9oZWFsdGhfY2hlY2snKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc1JlYWR5KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmNoZWNrUlBDKCcvcmVhZHlfaGVhbHRoX2NoZWNrJyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlSW50ZXJuYWwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy53cml0ZVNldHRpbmdzKHRoaXMubXV0YWJsZVNldHRpbmdzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyB1cGRhdGVJbnRlcm5hbChzZXR0aW5nczogTm9kZVNldHRpbmdzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdGFydCA9IGF3YWl0IHRoaXMud3JpdGVTZXR0aW5ncyhzZXR0aW5ncyk7XG4gICAgaWYgKHJlc3RhcnQgJiYgdGhpcy5tdXRhYmxlUHJvY2VzcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3AoKTtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnQoKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgc3RhcnRJbnRlcm5hbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5tdXRhYmxlUHJvY2VzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBjaGlsZCA9IGV4ZWNhKHRoaXMuYmluYXJ5LmNtZCwgdGhpcy5iaW5hcnkuZmlyc3RBcmdzLmNvbmNhdChbJ3N0YXJ0JywgJ25vZGUnLCB0aGlzLmRhdGFQYXRoXSksIHtcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICB3aW5kb3dzSGlkZTogdHJ1ZSxcbiAgICAgICAgc3RkaW86ICdpZ25vcmUnLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMubXV0YWJsZVByb2Nlc3MgPSBjaGlsZDtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1mbG9hdGluZy1wcm9taXNlc1xuICAgICAgY2hpbGRcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMubW9uaXRvci5sb2coe1xuICAgICAgICAgICAgbmFtZTogJ25lb19ub2RlX2FkYXB0ZXJfbm9kZV9leGl0JyxcbiAgICAgICAgICAgIG1lc3NhZ2U6ICdDaGlsZCBwcm9jZXNzIGV4aXRlZCcsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB0aGlzLm11dGFibGVQcm9jZXNzID0gdW5kZWZpbmVkO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMubW9uaXRvci5sb2dFcnJvcih7XG4gICAgICAgICAgICBuYW1lOiAnbmVvX25vZGVfYWRhcHRlcl9ub2RlX2Vycm9yJyxcbiAgICAgICAgICAgIG1lc3NhZ2U6ICdDaGlsZCBwcm9jZXNzIGV4aXRlZCB3aXRoIGFuIGVycm9yLicsXG4gICAgICAgICAgICBlcnJvcixcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRoaXMubXV0YWJsZVByb2Nlc3MgPSB1bmRlZmluZWQ7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBzdG9wSW50ZXJuYWwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2hpbGQgPSB0aGlzLm11dGFibGVQcm9jZXNzO1xuICAgIHRoaXMubXV0YWJsZVByb2Nlc3MgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGNoaWxkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGF3YWl0IGtpbGxQcm9jZXNzKGNoaWxkLnBpZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja1JQQyhycGNQYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmdldEFkZHJlc3MocnBjUGF0aCkpO1xuXG4gICAgICByZXR1cm4gcmVzcG9uc2Uub2s7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvci5jb2RlICE9PSAnRUNPTk5SRUZVU0VEJykge1xuICAgICAgICB0aGlzLm1vbml0b3Iud2l0aERhdGEoeyBbdGhpcy5tb25pdG9yLmxhYmVscy5IVFRQX1BBVEhdOiBycGNQYXRoIH0pLmxvZ0Vycm9yKHtcbiAgICAgICAgICBuYW1lOiAnaHR0cF9jbGllbnRfcmVxdWVzdCcsXG4gICAgICAgICAgbWVzc2FnZTogJ0ZhaWxlZCB0byBjaGVjayBSUEMuJyxcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldEFkZHJlc3MocnBjUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYGh0dHA6Ly9sb2NhbGhvc3Q6JHt0aGlzLm11dGFibGVTZXR0aW5ncy5ycGNQb3J0fSR7cnBjUGF0aH1gO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZVNldHRpbmdzKHNldHRpbmdzOiBOb2RlU2V0dGluZ3MpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBsZXQgY29uZmlnID0gdGhpcy5tdXRhYmxlQ29uZmlnO1xuICAgIGlmIChjb25maWcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uZmlnID0gY3JlYXRlTm9kZUNvbmZpZyh7XG4gICAgICAgIGRhdGFQYXRoOiB0aGlzLmRhdGFQYXRoLFxuICAgICAgICBkZWZhdWx0Q29uZmlnOiB0aGlzLmNyZWF0ZUNvbmZpZyhzZXR0aW5ncyksXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5tdXRhYmxlQ29uZmlnID0gY29uZmlnO1xuICAgIH1cblxuICAgIGNvbnN0IG5vZGVDb25maWcgPSBhd2FpdCBjb25maWcuY29uZmlnJC5waXBlKHRha2UoMSkpLnRvUHJvbWlzZSgpO1xuICAgIGNvbnN0IG5ld05vZGVDb25maWcgPSB0aGlzLmNyZWF0ZUNvbmZpZyhzZXR0aW5ncyk7XG4gICAgYXdhaXQgZnMuZW5zdXJlRGlyKG5ld05vZGVDb25maWcuZW52aXJvbm1lbnQuZGF0YVBhdGgpO1xuICAgIGF3YWl0IGNvbmZpZy51cGRhdGUoeyBjb25maWc6IG5ld05vZGVDb25maWcgfSk7XG5cbiAgICByZXR1cm4gIShcbiAgICAgIF8uaXNFcXVhbChub2RlQ29uZmlnLnNldHRpbmdzLCBuZXdOb2RlQ29uZmlnLnNldHRpbmdzKSAmJlxuICAgICAgXy5pc0VxdWFsKG5vZGVDb25maWcuZW52aXJvbm1lbnQsIG5ld05vZGVDb25maWcuZW52aXJvbm1lbnQpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQ29uZmlnKHNldHRpbmdzOiBOb2RlU2V0dGluZ3MpOiBOb2RlQ29uZmlnIHtcbiAgICByZXR1cm4ge1xuICAgICAgbG9nOiB7XG4gICAgICAgIGxldmVsOiAnaW5mbycsXG4gICAgICAgIG1heFNpemU6IDEwICogMTAyNCAqIDEwMjQsXG4gICAgICAgIG1heEZpbGVzOiA1LFxuICAgICAgfSxcbiAgICAgIHNldHRpbmdzOiB7XG4gICAgICAgIHRlc3Q6IHNldHRpbmdzLmlzVGVzdE5ldCxcbiAgICAgICAgcHJpdmF0ZU5ldDogc2V0dGluZ3MucHJpdmF0ZU5ldCxcbiAgICAgICAgc2Vjb25kc1BlckJsb2NrOiBzZXR0aW5ncy5zZWNvbmRzUGVyQmxvY2ssXG4gICAgICAgIHN0YW5kYnlWYWxpZGF0b3JzOiBzZXR0aW5ncy5zdGFuZGJ5VmFsaWRhdG9ycyxcbiAgICAgICAgYWRkcmVzczogc2V0dGluZ3MuYWRkcmVzcyxcbiAgICAgIH0sXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBkYXRhUGF0aDogcGF0aC5yZXNvbHZlKHRoaXMuZGF0YVBhdGgsICdjaGFpbicpLFxuICAgICAgICBycGM6IHtcbiAgICAgICAgICBodHRwOiB7XG4gICAgICAgICAgICBwb3J0OiBzZXR0aW5ncy5ycGNQb3J0LFxuICAgICAgICAgICAgaG9zdDogJzAuMC4wLjAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG5vZGU6IHtcbiAgICAgICAgICBleHRlcm5hbFBvcnQ6IHNldHRpbmdzLmxpc3RlblRDUFBvcnQsXG4gICAgICAgIH0sXG4gICAgICAgIG5ldHdvcms6IHtcbiAgICAgICAgICBsaXN0ZW5UQ1A6IHtcbiAgICAgICAgICAgIHBvcnQ6IHNldHRpbmdzLmxpc3RlblRDUFBvcnQsXG4gICAgICAgICAgICBob3N0OiAnMC4wLjAuMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgdGVsZW1ldHJ5OiB7XG4gICAgICAgICAgcG9ydDogc2V0dGluZ3MudGVsZW1ldHJ5UG9ydCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIG5vZGU6IHtcbiAgICAgICAgICBjb25zZW5zdXM6IHNldHRpbmdzLmNvbnNlbnN1cyxcbiAgICAgICAgICBycGNVUkxzOiBzZXR0aW5ncy5ycGNFbmRwb2ludHMsXG4gICAgICAgIH0sXG4gICAgICAgIG5ldHdvcms6IHtcbiAgICAgICAgICBzZWVkczogc2V0dGluZ3Muc2VlZHMsXG4gICAgICAgIH0sXG4gICAgICAgIHJwYzoge1xuICAgICAgICAgIHNlcnZlcjoge1xuICAgICAgICAgICAga2VlcEFsaXZlVGltZW91dDogNjAwMDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBsaXZlSGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgICAgIHJwY1VSTHM6IHNldHRpbmdzLnJwY0VuZHBvaW50cyxcbiAgICAgICAgICAgIG9mZnNldDogMSxcbiAgICAgICAgICAgIHRpbWVvdXRNUzogNTAwMCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlYWR5SGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgICAgIHJwY1VSTHM6IHNldHRpbmdzLnJwY0VuZHBvaW50cyxcbiAgICAgICAgICAgIG9mZnNldDogMSxcbiAgICAgICAgICAgIHRpbWVvdXRNUzogNTAwMCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG59XG4iXX0=