@andrian.yablonskyy/thub-coordinator 1.0.35 → 1.0.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrian.yablonskyy/thub-coordinator",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "TestHub Coordinator — job queue, resource registry, scheduler, heartbeat monitor, log/artifact store and web dashboard",
5
5
  "main": "src/server.js",
6
6
  "engines": {
@@ -19,7 +19,7 @@
19
19
  "lint:fix": "eslint . --fix"
20
20
  },
21
21
  "dependencies": {
22
- "@andrian.yablonskyy/thub-common": "^1.0.30",
22
+ "@andrian.yablonskyy/thub-common": "^1.0.31",
23
23
  "better-sqlite3": "^12.4.1",
24
24
  "express": "^5.1.0",
25
25
  "express-session": "^1.18.2",
@@ -81,6 +81,13 @@ function sanitizeCapabilities(caps){
81
81
  return typed
82
82
  ? {
83
83
  ...typed,
84
+ // Whether a job's command can use Docker on the host; unknown (null)
85
+ // for older Clients.
86
+ docker: caps.docker && typeof caps.docker === 'object'
87
+ ? caps.docker.available === true
88
+ ? { available: true, version: str(caps.docker.version, 64) }
89
+ : { available: false, reason: str(caps.docker.reason, 300) }
90
+ : null,
84
91
  // Whether the host has the root reboot helper (thub-client-reboot.path)
85
92
  // a scheduled reboot needs; unknown (null) for older Clients.
86
93
  rebootSupported: typeof caps.rebootSupported === 'boolean' ? caps.rebootSupported : null
@@ -725,6 +725,17 @@ test('HW capabilities: no power control — reported relays/power dropped, and r
725
725
  assert.throws(() => registry.setClientConfig(resourceId, { power: null }), /must NOT have additional properties/);
726
726
  });
727
727
 
728
+ test('Docker availability from registration is kept (and sanitized) for the resource card', () => {
729
+ const { registry } = buildTestServices(),
730
+ reg = (docker) => registry.get(registry.registerAuto({
731
+ clientId: `c-${Math.random()}`, name: `n${Math.random()}`.slice(0, 12), type: 'hw', labels: [],
732
+ capabilities: { hw: {}, ...(docker === undefined ? {} : { docker }) }
733
+ }).resourceId).capabilities.docker;
734
+ assert.deepEqual(reg({ available: true, version: '27.1.1', extra: 'x' }), { available: true, version: '27.1.1' });
735
+ assert.deepEqual(reg({ available: false, reason: 'docker isn\'t installed' }), { available: false, reason: 'docker isn\'t installed' });
736
+ assert.equal(reg(undefined), null); // an older Client
737
+ });
738
+
728
739
  test('rename from the dashboard: kept across re-registration, unique, and resettable to the Client\'s own name', () => {
729
740
  const { registry } = buildTestServices(),
730
741
  reg = (name) => registry.get(registry.registerAuto({ clientId: 'c-ren', name, type: 'sw', labels: [] }).resourceId),
@@ -150,6 +150,14 @@ mixin capabilitiesList(caps)
150
150
  ul.list-unstyled.mb-0.ms-2
151
151
  each d in caps.hw[pair[0]]
152
152
  +capDevice(d, pair[0] === 'uarts' && d.baudRate ? `${d.baudRate} baud` : null)
153
+ if caps && caps.docker
154
+ .small.text-body-secondary.mt-1 Docker
155
+ .ms-2
156
+ if caps.docker.available
157
+ span= caps.docker.version ? `available (${caps.docker.version})` : 'available'
158
+ else
159
+ span.badge.text-bg-warning(data-bs-toggle="tooltip" data-bs-title=caps.docker.reason || 'unknown reason') not available
160
+ span.small.text-body-secondary.ms-2 jobs can't run docker here
153
161
 
154
162
  //- Host uptime and the Client's current task/status with its duration,
155
163
  //- both from the last heartbeat. Measured up to now — or, for a Client