dcp-worker 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.gitlab-ci.yml CHANGED
@@ -149,11 +149,9 @@ publish_docs:
149
149
  AWS_REGION: 'us-east-1'
150
150
  TECHDOCS_S3_BUCKET_NAME: 'backstage.distributive.network'
151
151
  ENTITY_NAMESPACE: 'default'
152
- stage: deploy
153
- needs: []
154
152
  image: registry.gitlab.com/distributed-compute-protocol/backstage-ci-image:latest
155
153
  script:
156
- - bin/publish-docs.sh
154
+ - ./publish-docs.sh
157
155
  cache:
158
156
  - key:
159
157
  prefix: node-modules
@@ -41,8 +41,8 @@ var lastConnectionMs = 0;
41
41
  const defaultPrefix = '/usr';
42
42
  const daemonConfig = {
43
43
  net: new URL('tcpip://localhost:9000/'),
44
- proc: require.resolve('./dcp-evaluator-start'),
45
- argv: [ '-s', '--prefix', `${path.resolve(defaultPrefix)}/` ],
44
+ proc: process.argv[0],
45
+ argv: [ require.resolve('./dcp-evaluator-start'), '-s', '--prefix', `${path.resolve(defaultPrefix)}/` ],
46
46
  pidfile: pidfile.getDefaultPidFilename,
47
47
  limits: {
48
48
  loadavgType: 'short',
@@ -65,9 +65,10 @@ function usage()
65
65
  DCP Evaluator Monitor - Copyright (c) 2022-2024 Distributive Corp.
66
66
  Released under the terms of the MIT License.
67
67
 
68
- Usage: ${process.argv[0]} [-h | --help] [--prefix=<dir>] [--pts=<dir>] [-a]
68
+ Usage: ${process.argv[0]} [-h | --help] [--prefix=<dir>] [--pts=<dir>]
69
69
  [--disable-monitor=<session|screensaver|signal>] [-i <timeout>]
70
- [-p port] [-l | --max-load=<number>] [-r | --rate=<number>] [-L]
70
+ [-p port] [-H hostname]
71
+ [-a] [-l | --max-load=<number>] [-r | --rate=<number>] [-L]
71
72
  [-s | --signal=[name or number][,<toggle|quick>]]
72
73
  [-T | --loadavg-type=<short,medium,long,random>]
73
74
  [-f | --pidfile=</path/to/file.pid>]
@@ -75,6 +76,7 @@ Usage: ${process.argv[0]} [-h | --help] [--prefix=<dir>] [--pts=<dir>] [-a]
75
76
  Where:
76
77
  -i sets the idle timeout in seconds for tty sessions (${daemonConfig.session.idleTimeout}s)
77
78
  -p specifies the port to listen on for dcpsaw: worker connections (${daemonConfig.net.port})
79
+ -H specifies the address to listen on for dcpsaw: worker connections (${daemonConfig.net.port})
78
80
  --prefix specifies the directory where the DCP evaluator package was installed
79
81
  --pidfile specifies an alternate location for the pid file (currently ${daemonConfig.pidfile})
80
82
  --pts specifies the location of the system's pseudo terminal (${ptsDir})
@@ -110,7 +112,7 @@ async function listenForConnections(config)
110
112
  if (config.net.hostname === 'localhost')
111
113
  hostaddr = '::';
112
114
  else
113
- hostaddr = await dns.promises.lookup(config.net.hostname, { family: 4 });
115
+ hostaddr = (await dns.promises.lookup(config.net.hostname, { family: 4 })).address || config.net.hostname;
114
116
 
115
117
  server.on('error', (error) => {
116
118
  delete error.stack;
@@ -367,7 +369,7 @@ async function dbusScreenSaverMonitor()
367
369
  console.warn('Warning: could not open dbus session to any screensaver, tried', screensaverList);
368
370
  return;
369
371
  }
370
-
372
+
371
373
  try
372
374
  {
373
375
  // Note this is almost guranteed to fail if (GNOME is installed + you're accessing it not on GNOME,
@@ -524,7 +526,8 @@ function odRequire(moduleId)
524
526
  /* Main program entry point */
525
527
  async function main()
526
528
  {
527
- const parser = new getopt.BasicParser('h(help)P:(prefix)d:(disable-monitor)l:(max-load)r:(rate)Li:ap:s:(signal)T:(loadavg-type)f:(pidfile)', process.argv);
529
+ const parser = new getopt.BasicParser('h(help)P:(prefix)H:p:d:(disable-monitor)l:(max-load)r:(rate)'
530
+ + 'Li:as:(signal)T:(loadavg-type)f:(pidfile)', process.argv);
528
531
  var option;
529
532
 
530
533
  if (dcpConfig.evaluator.listen)
@@ -601,6 +604,12 @@ async function main()
601
604
  break;
602
605
  }
603
606
 
607
+ case 'H':
608
+ {
609
+ daemonConfig.net.hostname = option.optarg;
610
+ break;
611
+ }
612
+
604
613
  case 'l':
605
614
  {
606
615
  daemonConfig.limits.maxLoad = Number(option.optarg);
@@ -660,11 +669,20 @@ async function main()
660
669
  }
661
670
 
662
671
  /* Initialize dcp-client to use only local resources before launching the main function */
663
- require('dcp-client').init({
664
- programName: 'dcp-worker',
665
- parseArgv: false,
666
- dcpConfig: {
667
- scheduler: { configLocation: false },
668
- bundle: { location: false },
669
- }
670
- }).then(main);
672
+ try {
673
+ require('dcp-client').init({
674
+ programName: 'dcp-worker',
675
+ parseArgv: false,
676
+ dcpConfig: {
677
+ scheduler: { configLocation: false },
678
+ bundle: { location: false },
679
+ }
680
+ }).then(main);
681
+ }
682
+ catch(error)
683
+ {
684
+ if (error.name === 'SyntaxError')
685
+ console.error(`Unable to initialize dcp-client - Node.js version too old? (SyntaxError: ${error.message})`);
686
+ else
687
+ throw error;
688
+ }
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- /**
2
+ /**
3
3
  * @file dcp-evaluator-start
4
- * @author Eddie Roosenmaallen, eddie@kingsds.network
5
- * Levi Stringer, levi@kingsds.network
6
- * @date September 2020
4
+ * @author Wes Garland, wes@distributive.network
5
+ * Brandon Christie, brandon@distributive.network
6
+ * @date Feb 2021, June 2024
7
7
  *
8
8
  * This script starts a DCP Evaluator. It acts as a facade which takes a standardized command-line
9
9
  * interface and spawns the selected evaluator type with the correct corresponding options. Evaluator
10
10
  * support files (eg. those used to implement the host environment and sandboxes) are loaded from the
11
- * dcp-client module or it's dependencies, and which of those files to use are specified by the
12
- * sandbox-definitions.json which is generated during a dcp-client build.
11
+ * dcp-client module or its dependencies, and which of those files to use are specified by the
12
+ * sandbox-definitions.json, which is generated during a dcp-client build.
13
13
  */
14
14
  'use strict';
15
15
 
@@ -19,103 +19,144 @@ function panic(...argv)
19
19
  process.exit(1);
20
20
  }
21
21
 
22
- function main() {
22
+ function main()
23
+ {
23
24
  const { clearLine, cursorTo } = require('readline');
25
+ const { BasicParser } = require('posix-getopt');
26
+ const { expandPath } = require('dcp/utils');
24
27
  const path = require('path');
28
+ const pidfile = require('../lib/pidfile')
25
29
  const dcpConfig = require('dcp/dcp-config');
26
30
  const dcpClientDir = path.dirname(require.resolve('dcp-client'));
27
- const defaultPidFileName = require('../lib/pidfile').getDefaultPidFileName(dcpConfig.worker.pidfile);
28
- var evaluator;
31
+ const parser = new BasicParser(
32
+ 'h(help)P:(prefix)p:(port)s(stdio)e:(evaluator)r:(rEvaluator)\u1000:(sandbox-libexec-dir)' +
33
+ '\u1001:(sandbox-definitions)t:(sandbox-type)D(dump)T(dump-types)F(dump-files)J(json)v(verbose)' +
34
+ 'f:(pidfile)d:(logLevel)',
35
+ process.argv
36
+ );
29
37
 
30
- /* All evaluators must understand the following command-line options:
31
- * -p - port to listen on; unspecified => stdio
32
- */
33
- const options = require('dcp/cli')
34
- .base('Evaluator frontend')
35
- .option('prefix', {
36
- desc: 'Path under which native components are installed',
37
- default: path.resolve(path.dirname(process.argv[1]), '..'),
38
- })
39
- .option('port', {
40
- alias: ['p'],
41
- desc: 'Port to listen on',
42
- default: Number(dcpConfig.evaluator.listen.port),
43
- })
44
- .option('stdio', {
45
- alias: ['s'],
46
- desc: 'Use stdio pipeline (eg for inetd) instead of tcp port',
47
- type: 'boolean',
48
- default: false,
49
- })
50
- .option('evaluator', {
51
- alias: ['e'],
52
- desc: 'Path to evaluator (default: prefix/bin/dcp-evaluator)',
53
- })
54
- .option('rEvaluator', {
55
- alias: ['r'],
56
- desc: 'Path to evaluator as a module identitifer',
57
- })
58
- .option('sandbox-libexec-dir', {
59
- desc: 'Location of sandbox setup files',
60
- default: path.resolve(dcpClientDir, 'libexec', 'sandbox'),
61
- })
62
- .option('sandbox-definitions', {
63
- desc: 'Index of sandbox setup files for different evaluator/sandbox types',
64
- default: path.resolve(dcpClientDir, 'generated', 'sandbox-definitions.json'),
65
- })
66
- .option('sandbox-type', {
67
- alias: ['t'],
68
- desc: 'Type of evaluator/sandbox',
69
- default: 'native'
70
- })
71
- .option('dump', {
72
- alias: ['D'],
73
- desc: 'Dump configuration to stdout and exit',
74
- })
75
- .option('dump-types', {
76
- alias: ['T'],
77
- desc: 'Dump list of known sandbox types to stdout and exit',
78
- })
79
- .option('dump-files', {
80
- alias: ['F'],
81
- desc: 'Dump list of startup files which would be passed to the evaluator and exit',
82
- })
83
- .option('json', {
84
- alias: ['J'],
85
- desc: 'Dump in JSON format',
86
- })
87
- .option('verbose', {
88
- alias: ['v'],
89
- desc: 'Generate verbose output',
90
- })
91
- .option('pidFile', {
92
- alias: ['f'],
93
- describe: `create a .pid file; value overrides default location (${defaultPidFileName})`,
94
- })
95
- .options('debugLogLevel', {
96
- alias: ['d'],
97
- desc: 'Log level for evaluator output (emerg, alert, crit, error, warn, notice, info, debug)',
98
- })
99
- .epilogue("To pass arguments to the evaluator, make sure to separate your arguments with a '--'. For example: 'dcp-evaluator-start -p 9000 -- --options=--max-old-space-size=2048'")
100
- .wrap(process.stdout.columns || 80)
101
- .strict()
102
- .argv;
38
+ const options = {
39
+ prefix: path.resolve(path.dirname(process.argv[1]), '..'),
40
+ port: Number(dcpConfig.evaluator.listen.port),
41
+ sandboxLibexecDir: path.resolve(dcpClientDir, 'libexec', 'sandbox'),
42
+ sandboxDefinitions: path.resolve(dcpClientDir, 'generated', 'sandbox-definitions.json'),
43
+ sandboxType: 'native',
44
+ evaluator: path.join('bin', 'dcp-evaluator'), /* resolved against prefix later */
45
+ verbose: 0,
46
+ };
47
+
48
+ function help() {
49
+ const binName = path.basename(__filename);
50
+ console.log(`
51
+ ${binName} - Evaluator frontend
52
+ Copyright (c) 2021-2025, Distributive Corp. Released under the terms of the MIT License.
103
53
 
104
- if (!options.evaluator)
105
- options.evaluator = path.join(options.prefix, 'bin', 'dcp-evaluator');
54
+ Usage: ${binName} [options...]
55
+ Options:
56
+ -h, --help Display this help and exit
57
+ --prefix= Path under which native components are installed;
58
+ default is ${options.prefix}
59
+ -p, --port= Port to listen on; default is ${options.port}
60
+ -s, --stdio Use stdio pipeline (eg for inetd) instead of tcp
61
+ -t, --sandbox-type= Type of evaluator/sandbox; default is ${options.sandboxType}
62
+ -e, --evaluator= Path to evaluator; default is
63
+ ${options.prefix}/bin/dcp-evaluator
64
+ -m, --evaluator-module= Path to evaluator as a module identitifer
65
+ --sandbox-definitions= JSON file defining the sandbox setup files for the
66
+ different evaluator/sandbox types; default is
67
+ ${options.sandboxDefinitions}
68
+ --sandbox-libexec-dir= Location of sandbox setup files; default is
69
+ ${options.sandboxLibexecDir}
70
+ -D, --dump Dump configuration to stdout and exit
71
+ -T, --dump-types Dump list of known sandbox types to stdout and exit
72
+ -F, --dump-files Dump list of startup files which would be passed
73
+ to the evaluator and exit
74
+ -J, --json Dump in JSON format
75
+ -v, --verbose Generate verbose output
76
+ -f, --pidfile= create a .pid file; default is
77
+ ${pidfile.getDefaultPidFileName(dcpConfig.worker.pidfile)}
78
+ -d, --log-level= Select minimum log level for evaluator output
79
+ (debug, info, notice, warn, error, crit, alert, emerg)
80
+ `);
81
+ }
106
82
 
107
- if (options.stdio)
108
- delete options.port;
83
+ for (let opthnd; (opthnd = parser.getopt()) !== undefined; /* while loop */)
84
+ {
85
+ let option;
109
86
 
110
- const sandboxSetupDefs = require(options.sandboxDefinitions)[options.sandboxType]
87
+ /* To fake long-only-opts, we use short opts >= \u1000), and present only the long opt below */
88
+ if (opthnd.option < '\u1000')
89
+ option = opthnd.option;
90
+ else
91
+ option = (Object.entries(parser.gop_aliases).filter(longShort => longShort[1] === opthnd.option)[0] || ['?'])[0];
92
+
93
+ switch (option)
94
+ {
95
+ case '?':
96
+ process.exit(1);
97
+ break;
98
+ case 'h':
99
+ help();
100
+ process.exit(0);
101
+ break;
102
+ case 'P':
103
+ options.prefix = opthnd.optarg;
104
+ break;
105
+ case 'p':
106
+ options.port = opthnd.optarg;
107
+ break;
108
+ case 's':
109
+ options.stdio = true;
110
+ options.port = false;
111
+ break;
112
+ case 'e':
113
+ options.evaluator = expandPath(opthnd.optarg);
114
+ break;
115
+ case 'm':
116
+ options.evaluator = require.resolve(opthnd.optarg);
117
+ break;
118
+ case 't':
119
+ options.sandboxType = opthnd.optarg;
120
+ break;
121
+ case 'l':
122
+ options.sandboxLibexecDir = expandPath(opthnd.optarg);
123
+ break;
124
+ case 'J':
125
+ options.json = true;
126
+ break;
127
+ case 'f':
128
+ pidfile.write(expandPath(opthnd.optarg));
129
+ break;
130
+ case 'sandbox-definitions':
131
+ options.sandboxDefinitions = expandPath(opthnd.optarg);
132
+ break;
133
+ case 'T':
134
+ {
135
+ const dump = Object.keys(require(options.sandboxDefinitions));
136
+ console.log(options.json ? JSON.stringify(dump) : dump);
137
+ process.exit(0);
138
+ break;
139
+ }
140
+ case 'D':
141
+ options.dump = true;
142
+ break;
143
+ case 'F':
144
+ options.dumpFiles = true;
145
+ break;
146
+ case 'v':
147
+ options.verbose++;
148
+ break;
149
+ default:
150
+ throw new Error(`unhandled option '${option}'`);
151
+ }
152
+ }
153
+
154
+ options.evaluatorOptions = process.argv.slice(parser.optind()); /* after --, pass to evaluator as-is */
155
+
156
+ const sandboxSetupDefs = require(options.sandboxDefinitions)[options.sandboxType];
111
157
  if (!sandboxSetupDefs)
112
158
  panic(`Invalid sandbox type: ${options.sandboxType}`);
113
159
 
114
- if (options.rEvaluator)
115
- evaluator = require.resolve(options.rEvaluator);
116
- else
117
- evaluator = path.resolve(options.evaluator);
118
-
119
160
  let args = []; /* Command-line arguments to pass to evaluator */
120
161
  let files = []; /* Startup files passed to evaluator as supplementary arguments */
121
162
 
@@ -123,7 +164,7 @@ function main() {
123
164
  args = args.concat(['-p', options.port]);
124
165
 
125
166
  /* Decode log-level parameters and translate as appropriate for the type of evaluator in use */
126
- if (options.debugLogLevel || options.debugLogLevel === 0)
167
+ if (options.logLevel || options.logLevel === 0)
127
168
  {
128
169
  switch(options.sandboxType)
129
170
  {
@@ -143,22 +184,22 @@ function main() {
143
184
  'notice': 5,
144
185
  'info': 6,
145
186
  'debug': 7,
146
- }[options.debugLogLevel];
187
+ }[options.logLevel];
147
188
 
148
- if (typeof level === 'undefined' && (!isNaN(Number(options.debugLogLevel))))
189
+ if (typeof level === 'undefined' && (!isNaN(Number(options.logLevel))))
149
190
  {
150
191
  console.warn('Warning: numeric log levels are deprecated');
151
- level = Number(options.debugLogLevel);
192
+ level = Number(options.logLevel);
152
193
  }
153
194
 
154
195
  if (typeof level === 'undefined')
155
- panic(`unknown debug log level ${options.debugLogLevell}`);
196
+ panic(`unknown debug log level ${options.logLevell}`);
156
197
 
157
198
  args = args.concat('-d', level);
158
199
  break;
159
200
  }
160
201
  case 'node':
161
- process.env.DCP_DEBUG_EVALUATOR = options.debugLogLevel;
202
+ process.env.DCP_DEBUG_EVALUATOR = options.logLevel;
162
203
  break;
163
204
  default:
164
205
  panic(`debug log level not supported for ${options.sandboxType} evaluators`);
@@ -167,8 +208,8 @@ function main() {
167
208
  }
168
209
 
169
210
  /* Pass options after -- as evaluator-specific options */
170
- if (options._)
171
- args = args.concat(options._);
211
+ if (options.evaluatorOptions.length > 0)
212
+ args = args.concat(options.evaluatorOptions);
172
213
 
173
214
  /* Definitions in the JSON file are either in the sandboxLibexecDir, or pathed
174
215
  * via normal CommonJS (node_modules) rules. The syntax for detecting which must
@@ -183,15 +224,16 @@ function main() {
183
224
 
184
225
  if (options.dump) {
185
226
  if (options.json) {
186
- console.log(JSON.stringify({evaluator, files, args, options}));
227
+ console.log(JSON.stringify({ evaluator: options.evaluator, files, args, options }));
187
228
  } else {
188
- console.log('Evaluator command:', [evaluator].concat(files).concat(args).join(' '));
229
+ console.log('Evaluator command:', [path.resolve(options.prefix, options.evaluator)].concat(files).concat(args).join(' '));
189
230
  console.log('Options:', options);
190
231
  }
191
232
  process.exit(0);
192
233
  }
193
234
 
194
- if (options.dumpFiles) {
235
+ if (options.dumpFiles)
236
+ {
195
237
  let dump = files;
196
238
 
197
239
  if (options.json)
@@ -200,15 +242,6 @@ function main() {
200
242
  process.exit(0);
201
243
  }
202
244
 
203
- if (options.dumpTypes) {
204
- let dump = Object.keys(require(options.sandboxDefinitions));
205
-
206
- if (options.json)
207
- dump = JSON.stringify(dump);
208
- console.log(dump);
209
- process.exit(0);
210
- }
211
-
212
245
  if (!options.stdio && options.sandboxType === 'node') {
213
246
  if (process.env.I_WANT_AN_INSECURE_DCP_WORKER !== 'badly') {
214
247
  console.warn('***\x07 WARNING: Node evaluator is not suitable for production work - ^C to abort');
@@ -225,8 +258,8 @@ function main() {
225
258
 
226
259
  if (!options.stdio) {
227
260
  console.log('Starting DCP Evaluator -- ');
228
- console.log('. Evaluator program at:\t\t', evaluator);
229
- console.log('. Listening on: \t\t', options.port);
261
+ console.log('. Evaluator program at:\t\t', options.evaluator);
262
+ console.log('. Listening on: \t\t', options.port);
230
263
  console.log('. Worker environment type:\t', options.sandboxType);
231
264
  console.log('. Worker environment: \t');
232
265
  files.forEach(f => {
@@ -235,15 +268,12 @@ function main() {
235
268
  console.log('');
236
269
  }
237
270
 
238
- if (options.pidFile)
239
- require('../lib/pidfile').write(options.pidFile);
240
-
241
271
  if (options.verbose) {
242
272
  console.log('. cwd:', path.join(options.prefix));
243
- console.log('. run:', [evaluator].concat(files).concat(args).map(a => `"${a}"`).join(' '));
273
+ console.log('. run:', [options.evaluator].concat(files).concat(args).map(a => `"${a}"`).join(' '));
244
274
  }
245
275
 
246
- const child = require('child_process').spawn(evaluator, files.concat(args), {
276
+ const child = require('child_process').spawn(options.evaluator, files.concat(args), {
247
277
  cwd: path.join(options.prefix),
248
278
  windowsHide: true,
249
279
  stdio: ['inherit', 'inherit', 'inherit'],
@@ -102,7 +102,7 @@ Examples (bash syntax):
102
102
  - # dcp-task-probe --merge 'minimumWage={"CPU":1,"GPU":3}' -c
103
103
  Options:
104
104
  -h | --help show this help and exit
105
- -C | --dumpConfig dump worker configuration instead of requesting a task
105
+ -C | --showConfig [dot.path] show derived worker configuration instead of requesting a task
106
106
  -v | --version increase verbosity (show job info)
107
107
  -H | --hostname= set evaluator hostname (for capability probing)
108
108
  -p | --port= set evaluator port number (for capability probing)
@@ -272,13 +272,13 @@ function cpuCommaGpu(str)
272
272
  /**
273
273
  * Parse and process command-line options. Most options result in changes to the running dcpConfig;
274
274
  * other options are reflected in the returned object:
275
- * - dumpConfig
275
+ * - showConfig
276
276
  * - workerId
277
277
  */
278
278
  async function processOptions(workerConfig)
279
279
  {
280
280
  const opts = { verbose: 0 };
281
- const parser = new getopt.BasicParser('h(help)C(dumpConfig)S:(set)M:(merge)a:(allowedOrigins)'
281
+ const parser = new getopt.BasicParser('h(help)C(showConfig)S:(set)M:(merge)a:(allowedOrigins)'
282
282
  + 'c:(cores)u:(utilization)m:(maxSandboxes)w:(workerId)'
283
283
  + 'j:(job)g:(computeGroup)G(leaveGlobalGroup)'
284
284
  + 'H:(hostname)p:(port)r(replay)l(load)i(input)o(output)'
@@ -302,8 +302,18 @@ async function processOptions(workerConfig)
302
302
  break;
303
303
 
304
304
  case 'C':
305
- opts.dumpConfig = true;
305
+ {
306
+ /* no direct support for optional arguments in posix-getopt; dig into internals */
307
+ const nextArg = parser.gop_argv[parser.gop_optind];
308
+ if (nextArg?.[0] === '-')
309
+ opts.showConfig === ''; /* defined but empty - match yargs behaviour */
310
+ else
311
+ {
312
+ opts.showConfig = nextArg;
313
+ parser.gop_optind++;
314
+ }
306
315
  break;
316
+ }
307
317
 
308
318
  case 'v':
309
319
  opts.verbose += 1;
@@ -338,7 +348,7 @@ async function processOptions(workerConfig)
338
348
  break;
339
349
 
340
350
  case 'G':
341
- workerConfig.leavePublicGroup = true;
351
+ workerConfig.leaveGlobalGroup = true;
342
352
  break;
343
353
 
344
354
  case 'H':
@@ -462,7 +472,7 @@ function readWorkerSnapshot()
462
472
 
463
473
  if (!readWorkerSnapshot.cache)
464
474
  {
465
- const serializer = dcpConfig.worker.requestSnapshot.endsWith('kvin') ? require('kvin').KVIN : JSON;
475
+ const serializer = dcpConfig.worker.requestSnapshot.endsWith('kvin') ? require('dcp/internal/kvin').KVIN : JSON;
466
476
  debug('dcp-task-probe')('loading snapshot', detailedView(dcpConfig.worker.requestSnapshot));
467
477
  readWorkerSnapshot.cache = serializer.parse(fs.readFileSync(dcpConfig.worker.requestSnapshot));
468
478
  }
@@ -609,12 +619,11 @@ async function main()
609
619
  await probeEvaluator(initialWorkerConfig);
610
620
  const dummyWorker = new (require('dcp/worker').DistributiveWorker)(initialWorkerConfig, function FakeSandboxConstructor(){});
611
621
 
612
- if (opts.dumpConfig)
622
+ if (opts.hasOwnProperty('showConfig'))
613
623
  {
614
- /* work around the cores getter/setter */
615
- const dump = Object.assign({}, dummyWorker.config);
616
- console.log(dump);
617
- process.exit(0);
624
+ const val = opts.showConfig ? eval(`dummyWorker.config.${opts.showConfig}`) : dummyWorker.config;
625
+ console.log(JSON.stringify(val, null, 2));
626
+ process.exit();
618
627
  }
619
628
 
620
629
  const { workerId, response, workerConfig } = await requestTask(dummyWorker, opts);