dcp-worker 4.1.1 → 4.2.1
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 +1 -3
- package/bin/dcp-evaluator-manager +33 -15
- package/bin/dcp-evaluator-start +149 -119
- package/bin/dcp-task-probe +20 -11
- package/bin/dcp-worker +698 -578
- package/lib/blessed-components/log.js +10 -0
- package/lib/check-scheduler-version.js +3 -2
- package/lib/consts.js +25 -0
- package/lib/loggers.js +256 -0
- package/lib/node-version-check.js +4 -2
- package/lib/pidfile.js +88 -4
- package/lib/reports.js +95 -0
- package/lib/show.js +54 -0
- package/lib/{remote-console.js → telnetd.js} +32 -19
- package/lib/utils.js +112 -9
- package/lib/web-console.js +178 -0
- package/lib/web-iface.js +128 -0
- package/lib/{dashboard-tui.js → worker-consoles/dashboard-console.js} +167 -57
- package/lib/worker-consoles/index.js +44 -0
- package/lib/worker-consoles/none-console.js +23 -0
- package/lib/worker-consoles/stdio-console.js +70 -0
- package/lib/worker-info.js +29 -20
- package/lib/worker-loggers/event-log.js +24 -26
- package/lib/worker-loggers/logfile.js +73 -65
- package/lib/worker-loggers/syslog.js +145 -43
- package/package.json +6 -4
- package/{bin/publish-docs.sh → publish-docs.sh} +1 -1
- package/tests/worker-with-no-options.simple +35 -13
- package/tests/worker-with-options.simple +65 -18
- package/lib/startWorkerLogger.js +0 -138
- package/lib/worker-loggers/console.js +0 -74
- package/lib/worker-loggers/dashboard.js +0 -76
|
@@ -7,29 +7,53 @@
|
|
|
7
7
|
*/
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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.
|
|
20
|
+
exports.open = function logFile$$open(options)
|
|
21
21
|
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
27
|
+
createLogFile(options, true);
|
|
30
28
|
});
|
|
31
|
-
|
|
32
|
-
exports.at =
|
|
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
|
|
65
|
+
function createLogFile(options, overwrite)
|
|
42
66
|
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
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
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @file worker-loggers/syslog.js
|
|
3
|
+
* @author Eddie Roosenmaallen <eddie@kingsds.network>
|
|
4
|
+
* @date August 2022
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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}
|
|
32
|
+
* @param {object} options Options for logger behaviour (passed
|
|
24
33
|
* through to consoleLogger)
|
|
25
34
|
*/
|
|
26
|
-
exports.
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "4.2.1",
|
|
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": "
|
|
39
|
+
"blessed": "0.1.81",
|
|
40
40
|
"blessed-contrib": "4.11.0",
|
|
41
41
|
"chalk": "^4.1.0",
|
|
42
|
-
"dcp-client": "^5.
|
|
42
|
+
"dcp-client": "^5.1.2",
|
|
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",
|
|
@@ -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 } =
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
46
|
+
...env,
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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,
|
|
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 } =
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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,
|
|
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);
|