dcp-worker 3.2.24 → 3.2.25

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.
@@ -1,25 +1,33 @@
1
1
  #!/usr/bin/env node
2
- /** @file dcp-evaluator-start
3
- * @author Eddie Roosenmaallen, eddie@kingsds.network
4
- * Levi Stringer, levi@kingsds.network
5
- * @date September 2020
2
+ /**
3
+ * @file dcp-evaluator-start
4
+ * @author Eddie Roosenmaallen, eddie@kingsds.network
5
+ * Levi Stringer, levi@kingsds.network
6
+ * @date September 2020
6
7
  *
7
- * This script starts a DCP Evaluator, with the
8
- * appropriate list of worker startup files queued up
8
+ * This script starts a DCP Evaluator. It acts as a facade which takes a standardized command-line
9
+ * interface and spawns the selected evaluator type with the correct corresponding options. Evaluator
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.
9
13
  */
10
14
  'use strict';
11
15
 
16
+ function panic(...argv)
17
+ {
18
+ console.error(...argv);
19
+ process.exit(1);
20
+ }
21
+
12
22
  function main() {
13
23
  const { clearLine, cursorTo } = require('readline');
14
24
  const path = require('path');
15
- const fs = require('fs');
16
- const os = require('os');
17
25
  const dcpConfig = require('dcp/dcp-config');
18
26
  const dcpClientDir = path.dirname(require.resolve('dcp-client'));
27
+ const defaultPidFileName = require('../lib/pidfile').getDefaultPidFileName(dcpConfig.worker.pidfile);
19
28
  var evaluator;
20
29
 
21
30
  /* All evaluators must understand the following command-line options:
22
- * -l - location of libs
23
31
  * -p - port to listen on; unspecified => stdio
24
32
  */
25
33
  const options = require('dcp/cli')
@@ -31,7 +39,6 @@ function main() {
31
39
  .option('port', {
32
40
  alias: ['p'],
33
41
  desc: 'Port to listen on',
34
- deprecated: true,
35
42
  default: Number(dcpConfig.evaluator.listen.port),
36
43
  })
37
44
  .option('stdio', {
@@ -87,14 +94,13 @@ function main() {
87
94
  alias: ['v'],
88
95
  desc: 'Generate verbose output',
89
96
  })
90
- .option('pidFileLoc', {
97
+ .option('pidFile', {
91
98
  alias: ['f'],
92
- desc: 'Location for dcp-evaluator PID file',
99
+ describe: `create a .pid file; value overrides default location (${defaultPidFileName})`,
93
100
  })
94
101
  .options('debugLogLevel', {
95
102
  alias: ['d'],
96
- deprecated: true,
97
- desc: 'Log level for evaluator output (max 8)',
103
+ desc: 'Log level for evaluator output (emerg, alert, crit, error, warn, notice, info, debug)',
98
104
  })
99
105
  .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
106
  .wrap(process.stdout.columns || 80)
@@ -109,7 +115,7 @@ function main() {
109
115
 
110
116
  const sandboxSetupDefs = require(options.sandboxDefinitions)[options.sandboxType]
111
117
  if (!sandboxSetupDefs)
112
- throw new Error(`Invalid sandbox type: ${options.sandboxType}`);
118
+ panic(`Invalid sandbox type: ${options.sandboxType}`);
113
119
 
114
120
  if (options.rEvaluator)
115
121
  evaluator = require.resolve(options.rEvaluator);
@@ -119,19 +125,60 @@ function main() {
119
125
  let args = []; /* Command-line arguments to pass to evaluator */
120
126
  let files = []; /* Startup files passed to evaluator as supplementary arguments */
121
127
 
122
- if (!options.stdio && options.port) {
123
- console.warn(`Note: --port (-p) is deprecated. Please pass this argument to the evalutor 'dcp-evaluator-start ... -- -p ${options.port}'`);
128
+ if (!options.stdio && options.port)
124
129
  args = args.concat(['-p', options.port]);
125
- }
130
+
126
131
  if (options.evaluatorLibDir) {
127
132
  console.warn(`Note: --evaluator-lib-dir (-l) is deprecated. Please pass this argument to the evalutor 'dcp-evaluator-start ... -- -l ${options.evaluatorLibDir}'`);
128
133
  options.evaluatorLibDir = path.resolve(options.prefix, 'etc', options.evaluatorLibDir);
129
134
  args = args.concat(['-l', options.evaluatorLibDir]);
130
135
  }
131
- if (options.debugLogLevel){
132
- console.warn(`Note: --debugLogLevel (-d) is deprecated. Please pass this argument to the evalutor 'dcp-evaluator-start ... -- --debug ${options.debugLogLevel}'`);
133
- args = args.concat(['-d'], options.debugLogLevel)
136
+
137
+ /* Decode log-level parameters and translate as appropriate for the type of evaluator in use */
138
+ if (options.debugLogLevel || options.debugLogLevel === 0)
139
+ {
140
+ switch(options.sandboxType)
141
+ {
142
+ case 'native':
143
+ {
144
+ let level = {
145
+ 'emerg': 0,
146
+ 'emergency': 0,
147
+ 'alert': 1,
148
+ 'crit': 2,
149
+ 'critical': 2,
150
+ 'err': 3,
151
+ 'error': 3,
152
+ 'warn': 4,
153
+ 'warning': 4,
154
+ '': 5,
155
+ 'notice': 5,
156
+ 'info': 6,
157
+ 'debug': 7,
158
+ }[options.debugLogLevel];
159
+
160
+ if (typeof level === 'undefined' && (!isNaN(Number(options.debugLogLevel))))
161
+ {
162
+ console.warn('Warning: numeric log levels are deprecated');
163
+ level = Number(options.debugLogLevel);
164
+ }
165
+
166
+ if (typeof level === 'undefined')
167
+ panic(`unknown debug log level ${options.debugLogLevell}`);
168
+
169
+ args = args.concat('-d', level);
170
+ break;
171
+ }
172
+ case 'node':
173
+ process.env.DCP_DEBUG_EVALUATOR = options.debugLogLevel;
174
+ break;
175
+ default:
176
+ panic(`debug log level not supported for ${options.sandboxType} evaluators`);
177
+ break;
178
+ }
134
179
  }
180
+
181
+ /* Pass options after -- as evaluator-specific options */
135
182
  if (options._)
136
183
  args = args.concat(options._);
137
184
 
@@ -141,16 +188,16 @@ function main() {
141
188
  */
142
189
  for (let def of sandboxSetupDefs) {
143
190
  if (def.match(/\//))
144
- files.push(require.resolve(def));
191
+ files.push(require('dcp-client').__require.resolve(def));
145
192
  else
146
193
  files.push(require.resolve(options.sandboxLibexecDir + '/' + def));
147
194
  }
148
195
 
149
196
  if (options.dump) {
150
197
  if (options.json) {
151
- console.log(JSON.stringify({evaluator, args, files, options}));
198
+ console.log(JSON.stringify({evaluator, files, args, options}));
152
199
  } else {
153
- console.log('Evaluator command:', [evaluator].concat(args).concat(files).join(' '));
200
+ console.log('Evaluator command:', [evaluator].concat(files).concat(args).join(' '));
154
201
  console.log('Options:', options);
155
202
  }
156
203
  process.exit(0);
@@ -189,14 +236,9 @@ function main() {
189
236
  }
190
237
 
191
238
  if (!options.stdio) {
192
- // Log what we're about to do:
193
239
  console.log('Starting DCP Evaluator -- ');
194
240
  console.log('. Evaluator program at:\t\t', evaluator);
195
- console.log('. Library path at: \t\t', options.evaluatorLibDir);
196
- if (options.stdio)
197
- console.log('. Running in single-shot over stdio pipeline');
198
- else
199
- console.log('. Listening on: \t\t', options.port);
241
+ console.log('. Listening on: \t\t', options.port);
200
242
  console.log('. Worker environment type:\t', options.sandboxType);
201
243
  console.log('. Worker environment: \t');
202
244
  files.forEach(f => {
@@ -205,14 +247,14 @@ function main() {
205
247
  console.log('');
206
248
  }
207
249
 
208
- if (options.pidFileLoc)
209
- memoizePid(options.pidFileLoc)
250
+ if (options.pidFile)
251
+ require('../lib/pidfile').write(options.pidFile);
210
252
 
211
253
  if (options.verbose) {
212
254
  console.log('. cwd:', path.join(options.prefix));
213
- console.log('. run:', [evaluator].concat(args).concat(files).map(a => `"${a}"`).join(' '));
255
+ console.log('. run:', [evaluator].concat(files).concat(args).map(a => `"${a}"`).join(' '));
214
256
  }
215
- const ran = require('child_process').spawnSync(evaluator, args.concat(files), {
257
+ const ran = require('child_process').spawnSync(evaluator, files.concat(args), {
216
258
  cwd: path.join(options.prefix),
217
259
  windowsHide: true,
218
260
  stdio: ['inherit', 'inherit', 'inherit']
@@ -234,119 +276,12 @@ function main() {
234
276
  process.exit(1);
235
277
  }
236
278
 
237
- /* Half-initialize the dcp-client library so that we can use dcp/cli, but
238
- * without checking the scheduler for configuration updates.
239
- */
240
- require('dcp-client');
241
- const dcpConfig = require('dcp/dcp-config');
242
- const localConfig = require(process.env.DCP_CONFIG || '../etc/dcp-config');
243
- if (!localConfig.bundle)
244
- localConfig.bundle = {};
245
- if (!localConfig.scheduler)
246
- localConfig.scheduler = {};
247
- localConfig.bundle.location = false;
248
- localConfig.scheduler.configLocation = false;
249
- Object.assign(dcpConfig, require('dcp/utils').leafMerge(dcpConfig, localConfig));
250
-
251
- // Create the PID file for the worker
252
- function memoizePid(dir)
253
- {
254
- const path = require('path');
255
- const fs = require('fs');
256
- const program = path.basename(require.main.filename, '.js');
257
- let location;
258
- let filename;
259
- let fileType = '.pid';
260
-
261
- // Set default location for pid file
262
- let DEFAULT_PID_LOC;
263
- if (fs.existsSync('/var/dcp/run'))
264
- DEFAULT_PID_LOC = '/var/dcp/run/';
265
- else if (fs.existsSync('/var/run'))
266
- DEFAULT_PID_LOC = '/var/run/';
267
- else
268
- DEFAULT_PID_LOC = require('os').tmpdir();
269
-
270
- if (dir.length && dir.length > 0)
271
- {
272
- if (fs.existsSync(dir))
273
- {
274
- if (fs.statSync(dir).isDirectory())
275
- {
276
- location = dir;
277
- filename = program;
278
- }
279
- else
280
- {
281
- console.warn('Previous PID file was not cleaned up');
282
- location = path.dirname(dir);
283
- filename = path.basename(dir);
284
- fileType = '';
285
- }
286
- }
287
- else if (dir.endsWith(path.sep))
288
- {
289
- location = dir;
290
- filename = program;
291
- }
292
- else
293
- {
294
- location = path.dirname(dir)
295
- filename = path.basename(dir);
296
- fileType = '';
297
- }
298
- }
299
- else
300
- {
301
- location = DEFAULT_PID_LOC;
302
- filename = program;
303
- }
304
-
305
- const pidfile = path.join(
306
- location,
307
- filename + fileType
308
- )
309
- try
310
- {
311
- if (fs.existsSync(pidfile))
312
- {
313
- const oldPid = fs.readFileSync(pidfile, 'utf8')
314
- console.warn(`Warning: Previous invocation${oldPid.length ? ' pid#' + parseInt(String(oldPid)) : ''} did not remove ${pidfile}`);
315
- }
316
- else
317
- memoizePid.fd = fs.openSync(pidfile, 'wx');
318
-
319
- fs.writeSync(memoizePid.fd, Buffer.from(process.pid + '\n'), 0);
320
- }
321
- catch (error)
322
- {
323
- console.warn(`Warning: Could not create pidfile at ${pidfile} (${error.code || error.message})`);
324
-
325
- if (typeof memoizePid.fd === 'number')
326
- {
327
- fs.closeSync(memoizePid.fd);
328
- delete memoizePid.fd;
329
- }
330
- return;
279
+ /* Initialize dcp-client to use only local resources before launching the main function */
280
+ require('dcp-client').init({
281
+ progName: 'dcp-worker',
282
+ configName: process.env.DCP_CONFIG || '../etc/dcp-worker-config',
283
+ dcpConfig: {
284
+ scheduler: { configLocation: false },
285
+ bundle: { location: false },
331
286
  }
332
-
333
- function exitHandler()
334
- {
335
- try
336
- {
337
- fs.unlinkSync(pidfile);
338
- fs.closeSync(memoizePid.fd);
339
- delete memoizePid.fd;
340
- }
341
- catch (error)
342
- {
343
- console.warn(`Warning: Could not remove pidfile at ${pidfile} (${error.code})`);
344
- }
345
- }
346
-
347
- // Cleanup PID file
348
- require('dcp/signal-handler').init();
349
- process.on('dcpExit', exitHandler);
350
- }
351
- main();
352
-
287
+ }).then(main);