The five beds that read the catalogue read it through the harness
adopted-store-cross-node, two-node-db and the three whole-mesh beds each carried a private loader; they drifted. The ace loader never resolved a runtime artifact, so a module the mesh builds travelled unresolved; whole-mesh-full still asked for 'registry' and 'firewall', which the catalogue names distribution and nftables, and swallowed the miss as NOT ASSIGNED. One loader now (novox/hq 04-ISSUES/073).
This commit is contained in:
@@ -36,19 +36,17 @@
|
||||
|
||||
import { test, before, after } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { existsSync } from "node:fs";
|
||||
import { loadScenario } from "../../src/declaration/parse.ts";
|
||||
import { raise } from "../../src/lifecycle/raise.ts";
|
||||
import { destroy, exec } from "../../src/lifecycle/operate.ts";
|
||||
import { hostBinaryPath, HOST_PATH } from "../../src/lifecycle/place.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine } from "./harness.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine, catalogueIsPresent, catalogueModule, needsBrokerAccount } from "./harness.ts";
|
||||
import type { HeldImage } from "../../src/pinning.ts";
|
||||
|
||||
const capability = await labIsUsable();
|
||||
const binary = hostBinaryPath();
|
||||
const bundle = process.env["MESH_LAB_BUNDLE"] ?? "";
|
||||
const modulesEnv = process.env["MESH_LAB_MODULES"] ?? "";
|
||||
|
||||
const skip = !capability.usable
|
||||
? `lab not usable: ${capability.why}`
|
||||
@@ -56,15 +54,12 @@ const skip = !capability.usable
|
||||
? "MESH_LAB_HOST_BINARY is not set to a built mesh-host"
|
||||
: !bundle || !existsSync(bundle)
|
||||
? "MESH_LAB_BUNDLE is not set to a foundation bundle (mesh-host examples/)"
|
||||
: false;
|
||||
: catalogueIsPresent();
|
||||
|
||||
const SCENARIO = "whole-mesh-novox";
|
||||
const NODE = "novox";
|
||||
|
||||
/** Where the committed module.json files live: the mesh-catalog beside mesh-controller. */
|
||||
const catalogDir = process.env["MESH_LAB_CATALOG"]
|
||||
?? (modulesEnv ? resolve(dirname(dirname(dirname(modulesEnv))), "mesh-catalog", "modules") : "")
|
||||
?? resolve(process.cwd(), "..", "mesh-catalog", "modules");
|
||||
|
||||
|
||||
/**
|
||||
* The set, in dependency-reading order (the resolver accepts any order). Each row: the module, and
|
||||
@@ -229,38 +224,14 @@ function bundleFor(images: HeldImage[]): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a committed module.json, rewrite every container image to the scenario's pinned digest, and
|
||||
* apply the host-port remaps. Returns the manifest as a string and whether it needs a broker account
|
||||
* (a runtime that reads MESH_BROKER_FILE — providers and tooled apps do; plain/node modules do not).
|
||||
* The catalogue's manifest as the lab runs it (harness): images pinned, artifacts resolved to the
|
||||
* stocked images, the host-port remaps applied. Returns the manifest and whether it needs a broker
|
||||
* account (a runtime that reads MESH_BROKER_FILE — providers and tooled apps do; plain/node modules
|
||||
* do not).
|
||||
*/
|
||||
function loadManifest(name: string): { manifest: string; broker: boolean } {
|
||||
const path = resolve(catalogDir, name, "module.json");
|
||||
const m = JSON.parse(readFileSync(path, "utf8")) as {
|
||||
resources?: { type: string; image?: string; artifact?: string; ports?: string[] }[];
|
||||
build?: unknown;
|
||||
};
|
||||
const remap = REMAP[name] ?? {};
|
||||
for (const r of m.resources ?? []) {
|
||||
if (r.type !== "container") continue;
|
||||
if (typeof r.image === "string") {
|
||||
r.image = pinned(r.image);
|
||||
} else if (typeof r.artifact === "string") {
|
||||
// Since issue 060 a module's own runtime container names an artifact the mesh's builder
|
||||
// would fill, not a placeholder image. This bed stocks the image instead of building, so
|
||||
// map the artifact to the stocked `mesh-runtime-<module>` the machine holds — keyed on the
|
||||
// MODULE name, not the container's (mailu's runtime container is `mesh-mailu`, its image is
|
||||
// `mesh-runtime-mailu`). The placeholder digest is what `pinned` already resolves for a
|
||||
// mesh-built repo, exactly as it did for the old `image` field.
|
||||
r.image = pinned(`mesh-runtime-${name}@sha256:${"0".repeat(64)}`);
|
||||
delete r.artifact;
|
||||
}
|
||||
if (Array.isArray(r.ports)) r.ports = r.ports.map((p) => remap[p] ?? p);
|
||||
}
|
||||
// The build section the mesh's builder would consume: dropped, because this bed stocks the image
|
||||
// rather than building it. Harmless to leave (the push path never reads it), removed for clarity.
|
||||
delete m.build;
|
||||
const manifest = JSON.stringify(m);
|
||||
return { manifest, broker: manifest.includes("MESH_BROKER_FILE") };
|
||||
const manifest = catalogueModule(name, held, { ports: REMAP[name] });
|
||||
return { manifest, broker: needsBrokerAccount(manifest) };
|
||||
}
|
||||
|
||||
function tokenFrom(said: string): string {
|
||||
@@ -306,7 +277,6 @@ async function nodeState(node: string): Promise<NodeState> {
|
||||
|
||||
before(async () => {
|
||||
if (skip) return;
|
||||
assert.ok(existsSync(catalogDir), `mesh-catalog modules not found at ${catalogDir}`);
|
||||
|
||||
const raised = await raise(loadScenario(`scenarios/${SCENARIO}.yml`), {
|
||||
onProgress: (m) => console.log(`raise: ${m}`),
|
||||
|
||||
Reference in New Issue
Block a user