@norskvideo/ctl-test-harness 0.1.61 → 0.1.63
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/demo/harness.d.ts +2 -0
- package/demo/harness.js +2 -0
- package/demo/run.d.ts +32 -0
- package/demo/run.js +41 -2
- package/demo/spec.d.ts +2 -0
- package/demo/spec.js +1 -0
- package/package.json +1 -1
package/demo/harness.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface LaunchOverrides {
|
|
|
43
43
|
/** Merged over the spec's `launch.params`. */
|
|
44
44
|
params?: Record<string, string | number>;
|
|
45
45
|
hardware?: "nvidia" | "none";
|
|
46
|
+
/** Replaces the spec's `launch.st2110Nics`. */
|
|
47
|
+
st2110Nics?: string[];
|
|
46
48
|
workingDirectory?: string;
|
|
47
49
|
}
|
|
48
50
|
/** An instance `launch()` brought to running: its resolved ports and URLs,
|
package/demo/harness.js
CHANGED
|
@@ -139,6 +139,8 @@ export class ProductHarness {
|
|
|
139
139
|
const hardware = overrides.hardware ?? spec.launch?.hardware;
|
|
140
140
|
if (hardware)
|
|
141
141
|
launchArgv.push("--hardware", hardware);
|
|
142
|
+
for (const nic of overrides.st2110Nics ?? spec.launch?.st2110Nics ?? [])
|
|
143
|
+
launchArgv.push("--st2110-nics", nic);
|
|
142
144
|
const workingDirectory = overrides.workingDirectory ?? spec.launch?.workingDirectory;
|
|
143
145
|
if (this.action === "up" && workingDirectory) {
|
|
144
146
|
launchArgv.push("--working-directory", expandHome(workingDirectory));
|
package/demo/run.d.ts
CHANGED
|
@@ -242,6 +242,38 @@ export declare function demoUrlHost(opts: {
|
|
|
242
242
|
daemon: DemoDaemonPolicy;
|
|
243
243
|
env?: NodeJS.ProcessEnv;
|
|
244
244
|
}): string;
|
|
245
|
+
/** Where the daemon's nginx PROXY answers, which is not where the daemon does.
|
|
246
|
+
*
|
|
247
|
+
* The daemon is a process in this very process' container, so `localhost`
|
|
248
|
+
* reaches it. Its proxy is NOT: every `nginx proxy starting on port N` is
|
|
249
|
+
* followed by `docker: Container norsk-proxy Created/Started`, for a private
|
|
250
|
+
* daemon exactly as for a reused one. On a docker-outside-of-docker runner
|
|
251
|
+
* that container is created by the HOST's daemon and publishes there
|
|
252
|
+
* (`0.0.0.0:22263->22263/tcp`, HostIp "" — measured on test2, 2026-10-01), so
|
|
253
|
+
* from inside this container `localhost:<proxyPort>` reaches nothing at all.
|
|
254
|
+
*
|
|
255
|
+
* That is playout's `visualiser unreachable … (180s)`: composeAdvancingGate
|
|
256
|
+
* reads through `{ proxy: "/instance/{id}/visualiser" }`, got the daemon's
|
|
257
|
+
* host, and every poll failed to connect while the compositor was advancing.
|
|
258
|
+
* It is not the 2026-09-03 bug of the same shape — that one was the proxy
|
|
259
|
+
* being pointed AWAY from localhost; this is it being pinned TO localhost
|
|
260
|
+
* after the proxy became a container.
|
|
261
|
+
*
|
|
262
|
+
* `NORSK_TEST_HOST` is the explicit answer when a runner has one. Otherwise a
|
|
263
|
+
* containerised run takes the host-gateway alias, which these runners do
|
|
264
|
+
* resolve (`host.docker.internal -> 172.18.0.1` from test2-runner-one-1).
|
|
265
|
+
* Off a runner the test process is not in a container and the published port
|
|
266
|
+
* really is on localhost, so nothing changes for a dev box. */
|
|
267
|
+
export declare const HOST_GATEWAY_ALIAS = "host.docker.internal";
|
|
268
|
+
export declare function proxyUrlHost(opts: {
|
|
269
|
+
publicHost: string | undefined;
|
|
270
|
+
inContainer: boolean;
|
|
271
|
+
env?: NodeJS.ProcessEnv;
|
|
272
|
+
}): string;
|
|
273
|
+
/** Whether this process is itself in a container — the DooD case, where a
|
|
274
|
+
* sibling container's published port is on the host and not on our localhost.
|
|
275
|
+
* `/.dockerenv` is written by the daemon into every container it creates. */
|
|
276
|
+
export declare function runningInContainer(exists?: (p: string) => boolean): boolean;
|
|
245
277
|
/** The pieces of a run that `runDemo`, `runExportCheck` and the dev-loop
|
|
246
278
|
* share: the daemon (private on its band, or the developer's), the dev
|
|
247
279
|
* backend on the driver's port, the registration, and the template (built
|
package/demo/run.js
CHANGED
|
@@ -344,6 +344,43 @@ export function demoUrlHost(opts) {
|
|
|
344
344
|
return envHost;
|
|
345
345
|
return "localhost";
|
|
346
346
|
}
|
|
347
|
+
/** Where the daemon's nginx PROXY answers, which is not where the daemon does.
|
|
348
|
+
*
|
|
349
|
+
* The daemon is a process in this very process' container, so `localhost`
|
|
350
|
+
* reaches it. Its proxy is NOT: every `nginx proxy starting on port N` is
|
|
351
|
+
* followed by `docker: Container norsk-proxy Created/Started`, for a private
|
|
352
|
+
* daemon exactly as for a reused one. On a docker-outside-of-docker runner
|
|
353
|
+
* that container is created by the HOST's daemon and publishes there
|
|
354
|
+
* (`0.0.0.0:22263->22263/tcp`, HostIp "" — measured on test2, 2026-10-01), so
|
|
355
|
+
* from inside this container `localhost:<proxyPort>` reaches nothing at all.
|
|
356
|
+
*
|
|
357
|
+
* That is playout's `visualiser unreachable … (180s)`: composeAdvancingGate
|
|
358
|
+
* reads through `{ proxy: "/instance/{id}/visualiser" }`, got the daemon's
|
|
359
|
+
* host, and every poll failed to connect while the compositor was advancing.
|
|
360
|
+
* It is not the 2026-09-03 bug of the same shape — that one was the proxy
|
|
361
|
+
* being pointed AWAY from localhost; this is it being pinned TO localhost
|
|
362
|
+
* after the proxy became a container.
|
|
363
|
+
*
|
|
364
|
+
* `NORSK_TEST_HOST` is the explicit answer when a runner has one. Otherwise a
|
|
365
|
+
* containerised run takes the host-gateway alias, which these runners do
|
|
366
|
+
* resolve (`host.docker.internal -> 172.18.0.1` from test2-runner-one-1).
|
|
367
|
+
* Off a runner the test process is not in a container and the published port
|
|
368
|
+
* really is on localhost, so nothing changes for a dev box. */
|
|
369
|
+
export const HOST_GATEWAY_ALIAS = "host.docker.internal";
|
|
370
|
+
export function proxyUrlHost(opts) {
|
|
371
|
+
if (opts.publicHost !== undefined)
|
|
372
|
+
return opts.publicHost;
|
|
373
|
+
const envHost = (opts.env ?? process.env).NORSK_TEST_HOST;
|
|
374
|
+
if (envHost)
|
|
375
|
+
return envHost;
|
|
376
|
+
return opts.inContainer ? HOST_GATEWAY_ALIAS : "localhost";
|
|
377
|
+
}
|
|
378
|
+
/** Whether this process is itself in a container — the DooD case, where a
|
|
379
|
+
* sibling container's published port is on the host and not on our localhost.
|
|
380
|
+
* `/.dockerenv` is written by the daemon into every container it creates. */
|
|
381
|
+
export function runningInContainer(exists = existsSync) {
|
|
382
|
+
return exists("/.dockerenv");
|
|
383
|
+
}
|
|
347
384
|
/** The pieces of a run that `runDemo`, `runExportCheck` and the dev-loop
|
|
348
385
|
* share: the daemon (private on its band, or the developer's), the dev
|
|
349
386
|
* backend on the driver's port, the registration, and the template (built
|
|
@@ -381,19 +418,21 @@ export class DemoSession {
|
|
|
381
418
|
this.publicHost = opts.publicHost;
|
|
382
419
|
const host = demoUrlHost({ publicHost: opts.publicHost, daemon: opts.daemon });
|
|
383
420
|
this.host = host;
|
|
421
|
+
// The proxy is a container even when the daemon is ours; see proxyUrlHost.
|
|
422
|
+
const proxyHost = proxyUrlHost({ publicHost: opts.publicHost, inContainer: runningInContainer() });
|
|
384
423
|
if (opts.daemon === "reuse") {
|
|
385
424
|
const daemonPort = opts.daemonPort ?? (Number(process.env.NORSK_CTL_PORT) || DEFAULT_DAEMON_PORT);
|
|
386
425
|
this.storeDir = deps.realStoreDir();
|
|
387
426
|
const proxy = parseProxyConfig(deps.readFile(join(this.storeDir, "config.yaml")));
|
|
388
427
|
this.ports = demoPorts(slug, { daemonPort, proxyPort: proxy.port });
|
|
389
|
-
this.proxyBase = `${proxy.scheme}://${
|
|
428
|
+
this.proxyBase = `${proxy.scheme}://${proxyHost}:${proxy.port}`;
|
|
390
429
|
}
|
|
391
430
|
else {
|
|
392
431
|
this.ports = demoPorts(slug);
|
|
393
432
|
this.storeDir = opts.storeDir ?? deps.storeDir(slug);
|
|
394
433
|
// The private daemon is initialised without a cert source, so its proxy
|
|
395
434
|
// speaks plain http (seen live: https:// gave 000, http:// served the page).
|
|
396
|
-
this.proxyBase = `http://${
|
|
435
|
+
this.proxyBase = `http://${proxyHost}:${this.ports.proxyPort}`;
|
|
397
436
|
}
|
|
398
437
|
this.proxyAuth = opts.proxy;
|
|
399
438
|
this.daemonEnv = opts.daemonEnv ?? {};
|
package/demo/spec.d.ts
CHANGED
|
@@ -119,6 +119,8 @@ export interface DemoSpec {
|
|
|
119
119
|
launch?: {
|
|
120
120
|
hardware?: "nvidia" | "none";
|
|
121
121
|
params?: Record<string, string | number>;
|
|
122
|
+
/** Host NICs to claim for an ST 2110 template; one `--st2110-nics` each. */
|
|
123
|
+
st2110Nics?: string[];
|
|
122
124
|
/** `up` only; `check` launches without it (05-demo s5 playout). */
|
|
123
125
|
workingDirectory?: string;
|
|
124
126
|
};
|
package/demo/spec.js
CHANGED
|
@@ -67,6 +67,7 @@ export const DemoSpecSchema = z
|
|
|
67
67
|
.strictObject({
|
|
68
68
|
hardware: z.enum(["nvidia", "none"]).optional(),
|
|
69
69
|
params: Params.optional(),
|
|
70
|
+
st2110Nics: z.array(z.string().min(1)).min(1).optional(),
|
|
70
71
|
workingDirectory: z.string().min(1).optional(),
|
|
71
72
|
})
|
|
72
73
|
.optional(),
|