dcp-worker 4.1.1 → 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.
@@ -7,29 +7,53 @@
7
7
  */
8
8
  'use strict';
9
9
 
10
- // Copy the original global console object's properties onto a backup
11
- const _console = Object.assign({}, console);
10
+ const fs = require('fs');
11
+ var currentLogFileHnd;
12
12
 
13
13
  /**
14
14
  * Initialize the logfile worker logger
15
15
  *
16
- * @param {object} options Options for logger behaviour
17
- * @param {string} options.filepath Path to worker file; default: ./dcp-worker.log
18
- * @param {boolean} options.truncate If true, logfile will be cleared at worker startup
16
+ * @param {object} options Options for logger behaviour
17
+ * .filepath Path to worker file; default: ./dcp-worker.log
18
+ * .overwriteLogfile If true, logfile will be cleared at worker startup
19
19
  */
20
- exports.init = function init(options)
20
+ exports.open = function logFile$$open(options)
21
21
  {
22
- delete exports.init; // singleton
23
- options.verbose >= 3 && _console.debug('050: constructing LogfileConsole', options.logfile, options);
24
- getLogFile(options);
25
- require('../startWorkerLogger').inspectOptions.colors = Boolean(process.env.FORCE_COLOR);
26
-
22
+ console.log(` . creating log file ${options.logfile}`);
23
+ createLogFile(options);
24
+
27
25
  // on SIGHUP, close the output stream and open a new one
28
26
  process.on('SIGHUP', () => {
29
- getLogFile(options);
27
+ createLogFile(options, true);
30
28
  });
31
-
32
- exports.at = log;
29
+
30
+ exports.at = logToFile;
31
+ logToFile('info', 'begin');
32
+ }
33
+
34
+ /**
35
+ * Close the log file.
36
+ */
37
+ exports.close = function logFile$$close()
38
+ {
39
+ var p$resolve, p$reject;
40
+ if (!currentLogFileHnd)
41
+ return;
42
+ const p$finished = new Promise((resolve, reject) => { p$resolve = resolve; p$reject = reject });
43
+
44
+ try
45
+ {
46
+ currentLogFileHnd.on('error', error => p$reject(error));
47
+ currentLogFileHnd.on('finish', p$resolve);
48
+ currentLogFileHnd.write((new Date()).toISOString() + ` -------- end ${process.pid} --------\n`);
49
+ currentLogFileHnd.end();
50
+ }
51
+ catch (error)
52
+ {
53
+ exports.handleFatalError(error);
54
+ }
55
+ currentLogFileHnd = false;
56
+ return p$finished;
33
57
  }
34
58
 
35
59
  /**
@@ -38,62 +62,46 @@ exports.init = function init(options)
38
62
  *
39
63
  * @return {fs.WriteStream}
40
64
  */
41
- function getLogFile(options)
65
+ function createLogFile(options, overwrite)
42
66
  {
43
- {
44
- const fs = require('fs');
45
-
46
- if (getLogFile._file)
47
- {
48
- try
49
- {
50
- getLogFile._file.end();
51
- }
52
- catch (err)
53
- {
54
- console.error('061: failed to close old log file:', err);
55
- }
56
- getLogFile._file = false;
57
- }
58
-
59
- const fileOptions = {
60
- flags: options.truncate ? 'w' : 'a', // NYI: cli --truncate
61
- }
62
-
63
- const file = getLogFile._file = fs.createWriteStream(options.logfile, fileOptions);
64
-
65
- // On error, close & recreate the log file
66
- file.on('error', err => {
67
- _console.error('082: console-patch::LogFileConsole write error:', err);
68
-
69
- getLogFile(options);
70
- });
71
-
72
- return file;
73
- }
67
+ exports.close();
68
+
69
+ const logFileHnd = currentLogFileHnd = fs.createWriteStream(options.logfile, {
70
+ encoding: 'utf8',
71
+ flags: (overwrite || options.overwriteLogfile) ? 'w' : 'a',
72
+ autoClose: true,
73
+ emitClose: true,
74
+ flush: true,
75
+ highWaterMark: 1024 * 1024,
76
+ });
77
+ logFileHnd.on('error', exports.handleFatalError);
78
+ logFileHnd.write((new Date()).toISOString() + ` ------- begin ${process.pid} -------\n`);
79
+ return logFileHnd;
74
80
  }
75
81
 
76
- /** Write a log line to the output file.
77
- *
78
- * current outputStream.
79
- * @param {string} level Log level.
80
- * @param {any} ...items Items to log.
82
+ /**
83
+ * Write a log line to the output file.
84
+ *
85
+ * @param {string} level Log level.
86
+ * @param {any} ...items Items to log.
81
87
  */
82
- function log(level, ...items)
88
+ function logToFile(level, ...items)
83
89
  {
84
- {
85
- const logPrefix = [
86
- (new Date()).toISOString(),
87
- level,
88
- ];
89
-
90
- const logElements = logPrefix.concat(items);
90
+ const logPrefix = `${(new Date()).toISOString()} ${level} `;
91
91
 
92
- try {
93
- getLogFile._file.write(logElements.join(' ') + '\n');
94
- }
95
- catch (error) {
96
- _console.error('131: Unexpected error writing to log file:', error);
97
- }
92
+ try
93
+ {
94
+ const message = items.join(' ');
95
+ if (!message)
96
+ return;
97
+ for (let line of message.split('\n'))
98
+ currentLogFileHnd.write(logPrefix + line + '\n');
99
+ }
100
+ catch (error)
101
+ {
102
+ exports.handleFatalError(error);
98
103
  }
99
104
  }
105
+
106
+ exports.inspectOptions = { colors: Boolean(process.env.FORCE_COLOR) };
107
+ exports.handleFatalError = undefined; /* supplied by ../loggers.js at runtime */
@@ -1,42 +1,123 @@
1
1
  /**
2
- * @file worker-loggers/syslog.js
3
- * @author Eddie Roosenmaallen <eddie@kingsds.network>
4
- * @date August 2022
2
+ * @file worker-loggers/syslog.js
3
+ * @author Eddie Roosenmaallen <eddie@kingsds.network>
4
+ * @date August 2022
5
5
  *
6
- * This logger module emits log lines to a remote syslogd, writing all
7
- * console logs to it.
6
+ * This logger module emits log lines to a remote syslogd, writing all
7
+ * console logs to it.
8
+ *
9
+ * @todo - Add options to support TLS syslog option tlsCA:
10
+ * - this option becomes options.ca in require('tls').connect(options, ....)
11
+ * - Add support to syslog-client-tls for options.secureProtocol; currently hard-coded to
12
+ * TLSv1_2_method
13
+ * - Investigate options besides handleFatalError when remote daemon yo-yoing
8
14
  */
9
15
  'use strict';
10
16
 
11
17
  const os = require('os');
12
- const syslog = require('syslog-client');
18
+ const syslog = require('syslog-client-tls');
13
19
  const process = require('process');
20
+ const debug = require('debug');
14
21
 
15
- // Copy the original global console object's properties onto a backup
16
- const _console = Object.assign({}, console);
17
22
  var syslogClient;
23
+ var syslogOptions;
18
24
  var processName;
25
+ var pending = 0; /* number of outstanding messages, not authoritative, good enough for cleanup timing */
19
26
 
27
+ exports.at = syslogAt;
28
+ exports.inspectOptions = { colors: false };
20
29
  /**
21
30
  * Initialize the syslog worker logger
22
31
  *
23
- * @param {object} cliArgs Options for logger behaviour (passed
32
+ * @param {object} options Options for logger behaviour (passed
24
33
  * through to consoleLogger)
25
34
  */
26
- exports.init = function syslog$$init(cliArgs)
35
+ exports.open = function syslog$$open(options)
27
36
  {
37
+ const facilityName = leadingCap(options.syslogUrl.pathname.slice(1) || 'local7');
38
+ const transportName = leadingCap(options.syslogUrl.protocol.slice(0, -1));
39
+ syslogOptions = {
40
+ syslogHostname: os.hostname(),
41
+ facility: syslog.Facility[facilityName],
42
+ transport: syslog.Transport[transportName],
43
+ port: options.syslogUrl.port,
44
+ tcpTimeout: (dcpConfig.worker.logging?.syslog?.tcpTimeout || '10') * 1e3,
45
+ };
46
+ const syslogTarget = options.syslogUrl.hostname;
47
+
48
+ if (!syslogOptions.transport)
49
+ throw new Error(`invalid syslog transport '${transportName}'`);
50
+ if (!syslogOptions.facility && syslogOptions.facility !== 0)
51
+ throw new Error(`invalid syslog facility '${facilityName}'`);
52
+
53
+ if (!syslogOptions.port)
28
54
  {
29
- const syslogOptions = {
30
- syslogHostname: os.hostname(),
31
- transport: cliArgs.syslogTransport, // tcp, udp, unix, tls
32
- port: cliArgs.syslogPort,
33
- facility: syslog.Facility[cliArgs.syslogFacility[0].toUpperCase() + cliArgs.syslogFacility.slice(1)],
34
- };
35
-
36
- syslogClient = syslog.createClient(cliArgs.syslogAddress, syslogOptions);
37
- processName = require('path').basename(process.mainModule.filename || process.argv0);
38
- exports.close = () => syslogClient.close();
55
+ switch(syslogOptions.transport)
56
+ {
57
+ case syslog.Transport.Tcp:
58
+ case syslog.Transport.Udp:
59
+ syslogOptions.port = 514;
60
+ break;
61
+ case syslog.Transport.Tls:
62
+ syslogOptions.port = 6514;
63
+ break;
64
+ }
39
65
  }
66
+
67
+ if (!syslogOptions.port)
68
+ throw new Error(`invalid syslog port '${syslogOptions.port}'`);
69
+ if (!syslogTarget)
70
+ throw new Error('missing syslog target');
71
+
72
+ debug('dcp-worker:logger')('connecting to syslogd at ' + options.syslogUrl);
73
+ syslogClient = syslog.createClient(options.syslogUrl.hostname, syslogOptions);
74
+ processName = require('path').basename(process.mainModule.filename) || 'dcp-worker';
75
+
76
+ syslogClient.on('error', (error) => {
77
+ pending = 0;
78
+ tryFinishClose();
79
+ if (!syslogClient)
80
+ return;
81
+
82
+ if (true /* lib does not have codes but messages are predictable */
83
+ && error.message !== 'connection timed out'
84
+ && error.message !== 'connection closed')
85
+ exports.handleFatalError(error);
86
+ else
87
+ {
88
+ if (pending !== 0)
89
+ console.warn(` ! syslog: ${error.message} (${pending} messages pending)`);
90
+ }
91
+ });
92
+
93
+ syslogClient.on('close', () => {
94
+ pending = 0;
95
+ tryFinishClose();
96
+ if (syslogClient)
97
+ exports.handleFatalError(new Error(`connection closed to syslog server at ${options.syslogUrl}`));
98
+ });
99
+ }
100
+
101
+ /**
102
+ * Close the connection to the syslog daemon; used by loggers::unhook(). Invoking this function makes
103
+ * it impossible to send any more messages to syslog, but we try to wait until all messages have been
104
+ * sent before resolving the close promise. This dramatically increases the probability that uncaught
105
+ * exceptions that crash the worker are actually logged some place other than the system console.
106
+ *
107
+ * The closePromise is resolved in tryFinishClose when the pending message counter reaches 0.
108
+ */
109
+ exports.close = function a$syslog$$Close()
110
+ {
111
+ const sc = syslogClient; /* symbol dance because sc.close() emits close event */
112
+ syslogClient = false;
113
+ const closePromise = new Promise(resolve => exports.close.resolve = resolve);
114
+ closePromise.then(() => {
115
+ clearTimeout(exports.close.timer);
116
+ sc && sc.close();
117
+ });
118
+ exports.close.timer = setTimeout(()=>1, syslogOptions.tcpTimeout + 867.5309); /* ref to keep process alive */
119
+ debug('dcp-worker:logger')('Closing syslog connection');
120
+ return sc ? closePromise : false;
40
121
  }
41
122
 
42
123
  /**
@@ -45,31 +126,52 @@ exports.init = function syslog$$init(cliArgs)
45
126
  * @param {string} level Event level (info, debug, log, warning, error)
46
127
  * @param {...any[]} argv Items to log
47
128
  */
48
- function log(level, ...argv)
129
+ function syslogAt(level, ...argv)
49
130
  {
131
+ const logPrefix = `${processName}[${process.pid}]: `;
132
+
133
+ // Use the string log-level to look up the severity number:
134
+ let severity = {
135
+ error: syslog.Severity.Error,
136
+ warn: syslog.Severity.Warning,
137
+ log: syslog.Severity.Notice,
138
+ info: syslog.Severity.Informational,
139
+ debug: syslog.Severity.Debug,
140
+ }[level];
141
+
142
+ const logMessages = argv.join(' ').split('\n');
143
+ if (!syslogClient)
144
+ return;
145
+
146
+ for (let logMessage of logMessages)
50
147
  {
51
- const logPrefix = `${processName}[${process.pid}]: `;
52
-
53
- // Use the string log-level to look up the severity number:
54
- let severity = {
55
- error: syslog.Severity.Error,
56
- warn: syslog.Severity.Warning,
57
- log: syslog.Severity.Notice,
58
- info: syslog.Severity.Informational,
59
- debug: syslog.Severity.Debug,
60
- }[level];
61
-
62
- const logMessages = argv.join(' ').split('\n');
63
-
64
- for (let logMessage of logMessages)
65
- {
66
- logMessage = logPrefix + logMessage;
67
- syslogClient.log(logMessage, { severity }, error => {
68
- if (error)
69
- _console.error('168: Unexpected error writing to syslog:', error);
70
- });
71
- }
148
+ if (!logMessage)
149
+ continue;
150
+ pending++;
151
+ debug('dcp-worker:syslog-verbose')(`Sending message '${logMessage.slice(0,20)}'; pending=${pending}`);
152
+ syslogClient.log(logPrefix + logMessage, { severity }, function doneMessage(error) {
153
+ pending--;
154
+ tryFinishClose();
155
+ if (error)
156
+ exports.handleFatalError(error)
157
+ });
72
158
  }
73
159
  }
74
160
 
75
- exports.at = log;
161
+ function tryFinishClose()
162
+ {
163
+ debug('dcp-worker:syslog-verbose')(`tryFinishCLose, pending=${pending}, have resolve=${!!exports.close.resolve}`);
164
+ if (pending === 0 && exports.close.resolve)
165
+ {
166
+ clearTimeout(exports.close.timer);
167
+ exports.close.resolve();
168
+ }
169
+ }
170
+
171
+ function leadingCap(str)
172
+ {
173
+ if (!str)
174
+ return str;
175
+ else
176
+ return str[0].toUpperCase() + str.toLowerCase().slice(1);
177
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcp-worker",
3
- "version": "4.1.1",
3
+ "version": "4.2.0",
4
4
  "description": "Node.js Worker for Distributive Compute Platform",
5
5
  "main": "bin/dcp-worker",
6
6
  "keywords": [
@@ -36,14 +36,16 @@
36
36
  "prepublishOnly": "npm-hooks/prepublish"
37
37
  },
38
38
  "dependencies": {
39
- "blessed": "^0.1.81",
39
+ "blessed": "0.1.81",
40
40
  "blessed-contrib": "4.11.0",
41
41
  "chalk": "^4.1.0",
42
- "dcp-client": "^5.0.1",
42
+ "dcp-client": "5.1.1",
43
43
  "kvin": "^1.2.7",
44
44
  "posix-getopt": "^1.2.1",
45
45
  "semver": "^7.3.8",
46
- "syslog-client": "1.1.1"
46
+ "syslog-client": "1.1.1",
47
+ "syslog-client-tls": "1.2.1",
48
+ "websocket": "1.0.34"
47
49
  },
48
50
  "optionalDependencies": {
49
51
  "dbus-next": "^0.10.2",
@@ -9,7 +9,7 @@
9
9
 
10
10
  set -euo pipefail
11
11
 
12
- cd "$(dirname "$0")/.."
12
+ cd "$(dirname "$0")"
13
13
 
14
14
  ROOT_DIR=$PWD
15
15
 
@@ -2,19 +2,21 @@
2
2
 
3
3
  /**
4
4
  * @file worker-with-no-options.simple
5
- *
5
+ *
6
6
  * @author Nazila Akhavan <nazila@distributive.network>
7
7
  * @date Aug 2024
8
- *
8
+ *
9
9
  * peter-timeout: 60
10
10
  */
11
11
  'use strict';
12
12
 
13
+ const assert = require('node:assert');
14
+
13
15
  const { tmpdir } =require('node:os');
14
16
  const { spawnSync } = require('node:child_process');
15
17
  const { mkdtempSync, rmSync, existsSync, writeFileSync } = require('node:fs');
16
18
  const { join, parse, basename } = require('node:path');
17
- const { strictEqual, deepEqual } = require('node:assert');
19
+ const { strictEqual, deepEqual } = assert;
18
20
 
19
21
  const filename = parse(basename(__filename)).name;
20
22
  const tempd = mkdtempSync(join(tmpdir(), `${filename}-`));
@@ -24,33 +26,53 @@ process.chdir(__dirname);
24
26
 
25
27
  async function main()
26
28
  {
29
+ const KVIN = require('dcp/internal/kvin')
27
30
  const { Keystore } = require('dcp/wallet');
28
31
  const ks = await new Keystore(null);
29
32
  const id = await new Keystore(null);
30
33
 
31
34
  writeFileSync(`${tempd}/default.keystore`, JSON.stringify(ks.toJSON()), { encoding: 'utf-8' });
32
35
  writeFileSync(`${tempd}/id.keystore`, JSON.stringify(id.toJSON()), { encoding: 'utf-8' });
33
- const res = spawnSync(
34
- '../bin/dcp-worker', ['--showConfig'],
36
+
37
+ const args = ['--show=worker-config', '--kvin'];
38
+ const env = { DCP_RESOURCE_DIR: tempd };
39
+ const envStr = Object.entries(env).map(kv => `${kv[0]}='${kv[1]}'`).join(' ');
40
+ const confOut = spawnSync(
41
+ '../bin/dcp-worker', ['--unmanaged', '--show=config', '--kvin', `--earnings-account=${tempd}/default.keystore`],
35
42
  {
36
43
  encoding: 'utf-8',
37
44
  env: {
38
45
  ...process.env,
39
- DCP_RESOURCE_DIR: tempd
46
+ ...env,
40
47
  }
41
48
  }
42
- );
43
-
44
- const confObj = JSON.parse(res.stdout);
45
- strictEqual(confObj.paymentAddress, ks.address.valueOf(), `${confObj.paymentAddress} payment address is not correct`);
46
- strictEqual(confObj.leavePublicGroup, undefined, `leaveComputeGroup is ${confObj.leavePublicGroup}`);
49
+ )
50
+
51
+ if (confOut.stderr)
52
+ console.error(confOut.stderr);
53
+ console.log(confOut.stdout);
54
+ const confObj = KVIN.parse(confOut.stdout);
55
+
56
+ strictEqual(confObj.paymentAddress.valueOf(), ks.address.valueOf(), `${confObj.paymentAddress} payment address is not correct`);
47
57
  deepEqual(confObj.allowOrigins.any, [], `allowOrigins should be empty. It includes ${confObj.allowOrigins.any}`);
48
58
  deepEqual(confObj.utilization, { cpu: 1, gpu: 0.75 }, `Mismatch in utilization! cpu: ${confObj.utilization.cpu}, gpu: ${confObj.utilization.gpu}`);
49
- deepEqual(confObj.jobIds, undefined, `jobIds should be false but it is ${confObj.jobIds}`);
59
+ deepEqual(confObj.jobIds, false, `jobIds should be false but it is ${confObj.jobIds}`);
60
+
61
+ const computeGroups = KVIN.parse(spawnSync(
62
+ '../bin/dcp-worker', ['--unmanaged', '--show=compute-groups', '--kvin'],
63
+ {
64
+ encoding: 'utf-8',
65
+ env: {
66
+ ...process.env,
67
+ DCP_RESOURCE_DIR: tempd
68
+ }
69
+ }
70
+ ).stdout);
71
+ assert(Object.values(computeGroups).find(cg => cg.joinKey === 'public'));
50
72
 
51
73
  console.log('Done.');
52
74
  }
53
75
 
54
76
  require('dcp-client')
55
77
  .init()
56
- .then(main);
78
+ .then(main);
@@ -10,11 +10,13 @@
10
10
  */
11
11
  'use strict';
12
12
 
13
+ const assert = require('node:assert');
14
+
13
15
  const { tmpdir } =require('node:os');
14
16
  const { spawnSync } = require('node:child_process');
15
17
  const { mkdtempSync, rmSync, existsSync, writeFileSync } = require('node:fs');
16
18
  const { join, parse, basename } = require('node:path');
17
- const { strictEqual, deepEqual } = require('node:assert');
19
+ const { strictEqual, deepEqual } = assert;
18
20
 
19
21
  const filename = parse(basename(__filename)).name;
20
22
  const tempd = mkdtempSync(join(tmpdir(), `${filename}-`));
@@ -24,23 +26,28 @@ process.chdir(__dirname);
24
26
 
25
27
  async function main()
26
28
  {
29
+ const KVIN = require('dcp/internal/kvin')
27
30
  const { Keystore } = require('dcp/wallet');
28
31
  const ks = await new Keystore(null);
29
32
  const id = await new Keystore(null);
33
+ const testUrl = 'http://example.com';
30
34
 
31
35
  writeFileSync(`${tempd}/default.keystore`, JSON.stringify(ks.toJSON()), { encoding: 'utf-8' });
32
36
  writeFileSync(`${tempd}/id.keystore`, JSON.stringify(id.toJSON()), { encoding: 'utf-8' });
37
+ const args = [
38
+ '--unmanaged',
39
+ '--earnings-account=0x9fd0909Bd93f7bad915726C3AB499391384b8b4b',
40
+ '--no-global',
41
+ '--cores=3,1',
42
+ '--utilization=0.1,0.5',
43
+ '--max-sandboxes=5',
44
+ '--job=09fd0909Bd93f7bad915726C3AB4',
45
+ '--join=joinKey1,joinHash1', '-g', 'joinKey2,joinHash2',
46
+ '--show=config', '--kvin' ];
47
+
48
+ console.log('worker args:', args.join(' '));
33
49
  const res = spawnSync(
34
- '../bin/dcp-worker', [
35
- '--paymentAddress', '0x9fd0909Bd93f7bad915726C3AB499391384b8b4b',
36
- '--leavePublicGroup',
37
- '--allowedOrigins', 'test-url',
38
- '--cores', '3,1',
39
- '--utilization', '0.1,0.5',
40
- '--maxSandboxes', '5',
41
- '--job-id', '09fd0909Bd93f7bad915726C3AB4',
42
- '--join', `joinKey1,joinHash1`, '-g', 'joinKey2,joinHash2',
43
- '--showConfig' ],
50
+ '../bin/dcp-worker', args,
44
51
  {
45
52
  encoding: 'utf-8',
46
53
  env: {
@@ -49,20 +56,60 @@ async function main()
49
56
  }
50
57
  }
51
58
  );
52
-
53
- const confObj = JSON.parse(res.stdout);
54
- strictEqual(confObj.paymentAddress, '0x9fd0909Bd93f7bad915726C3AB499391384b8b4b', `${confObj.paymentAddress} payment address is not corrrect`);
55
- strictEqual(confObj.leavePublicGroup, true, `leaveComputeGroup is ${confObj.leavePublicGroup}`);
56
- deepEqual(confObj.allowOrigins.any.includes('test-url'), true, `allowOrigins only includes ${confObj.allowOrigins.any}!`);
59
+
60
+ if (res.stderr)
61
+ res.stderr = res.stderr.replace(/^ *\*\*\* .*telnet daemon.*\n/,'').replace(/^ ! telnetd listening.*\n/,'');
62
+ if (res.stderr)
63
+ console.error('worker stderr:', res.stderr.replace(/\n$/,''));
64
+ console.log('worker stdout:', res.stdout.replace(/\n$/,''));
65
+ const confObj = KVIN.parse(res.stdout);
66
+ strictEqual(confObj.paymentAddress.valueOf(), '0x9fd0909Bd93f7bad915726C3AB499391384b8b4b', `${confObj.paymentAddress} payment address is not correct`);
67
+ strictEqual(confObj.leaveGlobalGroup, true, `leaveGlobalGroup is ${confObj.leaveGlobalGroup}`);
57
68
  deepEqual(confObj.cores, { cpu: 3, gpu: 1 }, `Mismatch in cores! cpu: ${confObj.cores.cpu}, gpu: ${confObj.cores.gpu}`);
58
69
  deepEqual(confObj.utilization, { cpu: 0.1, gpu: 0.5 }, `Mismatch in utilization! cpu: ${confObj.utilization.cpu}, gpu: ${confObj.utilization.gpu}`);
59
- deepEqual(confObj.computeGroups, [{ joinKey: 'joinKey1', joinSecret: 'joinHash1' }, { joinKey: 'joinKey2', joinSecret: 'joinHash2' }], 'Mismatch in computeGroups')
70
+ deepEqual(confObj.computeGroups, { joinKey1: { joinKey: 'joinKey1', joinSecret: 'joinHash1' }, joinKey2: { joinKey: 'joinKey2', joinSecret: 'joinHash2' } }, 'Mismatch in computeGroups')
60
71
  deepEqual(confObj.maxSandboxes, 5, `Mismatch! maxSandboxes:${confObj.maxSandboxes}`);
61
72
  deepEqual(confObj.jobIds, ['09fd0909Bd93f7bad915726C3AB4'], `Mismatch in job ids! jobIds:${confObj.jobIds}`);
62
73
 
74
+ const cgSpawn = spawnSync(
75
+ '../bin/dcp-worker', ['--unmanaged', '--show=compute-groups', '--kvin', '--no-global'],
76
+ {
77
+ encoding: 'utf-8',
78
+ env: {
79
+ ...process.env,
80
+ DCP_RESOURCE_DIR: tempd
81
+ }
82
+ }
83
+ );
84
+ if (cgSpawn.stderr)
85
+ cgSpawn.stderr = cgSpawn.stderr.replace(/^ *\*\*\* .*telnet daemon.*\n/,'').replace(/^ ! telnetd listening.*\n/,'');
86
+ if (cgSpawn.stderr)
87
+ console.error('worker stderr:', cgSpawn.stderr.replace(/\n$/,''));
88
+ console.log('worker stdout:', cgSpawn.stdout.replace(/\n$/,''));
89
+ const computeGroups = KVIN.parse(cgSpawn.stdout);
90
+ assert(!Object.values(computeGroups).find(cg => cg.joinKey === 'public'));
91
+
92
+ const allowedOriginsSpawn = spawnSync(
93
+ '../bin/dcp-worker', ['--unmanaged', '--show=allowed-origins', '--kvin', `--allow-origin=${testUrl}`],
94
+ {
95
+ encoding: 'utf-8',
96
+ env: {
97
+ ...process.env,
98
+ DCP_RESOURCE_DIR: tempd
99
+ }
100
+ }
101
+ );
102
+ if (allowedOriginsSpawn.stderr)
103
+ allowedOriginsSpawn.stderr = allowedOriginsSpawn.stderr.replace(/^ *\*\*\* .*telnet daemon.*\n/,'').replace(/^ ! telnetd listening.*\n/,'');
104
+ if (allowedOriginsSpawn.stderr)
105
+ console.error('worker stderr:', allowedOriginsSpawn.stderr.replace(/\n$/,''));
106
+ console.log('worker stdout:', allowedOriginsSpawn.stdout.replace(/\n$/,''));
107
+ const allowOrigins = KVIN.parse(allowedOriginsSpawn.stdout);
108
+ deepEqual(allowOrigins.every.any.includes(testUrl), true, `allowOrigins missing ${testUrl}; only includes [${allowOrigins.every.any}]!`);
109
+
63
110
  console.log('Done.');
64
111
  }
65
112
 
66
113
  require('dcp-client')
67
114
  .init()
68
- .then(main);
115
+ .then(main);