Files
mesh-lab/test/catalogue-module.test.ts
T
jschoubben 2530ca762e The lab stands in for the builder on an upstream artifact too: the reference the manifest pins
hello-web's server is somebody else's image the mesh would copy in (ADR 0096); the
loader refused it as an artifact nobody stocked.
2026-09-21 22:33:44 +02:00

102 lines
4.7 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { catalogueModule } from "./integration/harness.ts";
import type { HeldImage } from "../src/pinning.ts";
/**
* The shared loader thirteen beds install through (novox/hq 04-ISSUES/073, ADR 0089): it reads
* the catalogue's manifest and rewrites only what the lab must. Checked here against a catalogue
* written by the test, so the rules hold without a lab run.
*/
const digest = (c: string) => "sha256:" + c.repeat(64);
const held: HeldImage[] = [
{ requested: "mesh-runtime-thing:development", repository: "mesh-runtime-thing", reference: digest("a") },
{ requested: "mesh-helper:development", repository: "mesh-helper", reference: digest("b") },
];
function aCatalogueWith(manifest: object): () => void {
const root = mkdtempSync(join(tmpdir(), "mesh-lab-catalogue-"));
mkdirSync(join(root, "modules", "distribution"), { recursive: true });
writeFileSync(join(root, "modules", "distribution", "module.json"), "{}");
mkdirSync(join(root, "modules", "thing"));
writeFileSync(join(root, "modules", "thing", "module.json"), JSON.stringify(manifest));
const before = process.env["MESH_LAB_CATALOG"];
process.env["MESH_LAB_CATALOG"] = root;
return () => {
if (before === undefined) delete process.env["MESH_LAB_CATALOG"]; else process.env["MESH_LAB_CATALOG"] = before;
rmSync(root, { recursive: true, force: true });
};
}
const thing = {
module: "thing", version: "1",
resources: [
{ id: "server", type: "container", name: "thing", image: "postgres@" + digest("c"), ports: ["8080", "9090:9090"], env: { A: "1" } },
{ id: "runtime", type: "container", name: "mesh-thing", artifact: "runtime" },
],
build: { artifacts: [{ name: "runtime", kind: "image", from: "Dockerfile" }] },
};
test("the runtime artifact becomes the image the machine holds, and the build section goes", () => {
const restore = aCatalogueWith(thing);
try {
const m = JSON.parse(catalogueModule("thing", held)) as { build?: unknown; resources: Record<string, unknown>[] };
assert.equal(m.build, undefined);
const runtime = m.resources.find((r) => r["id"] === "runtime")!;
assert.equal(runtime["image"], digest("a"));
assert.equal(runtime["artifact"], undefined);
// An image already pinned to a digest passes through as written.
assert.equal(m.resources.find((r) => r["id"] === "server")!["image"], "postgres@" + digest("c"));
} finally { restore(); }
});
test("an artifact the bed did not name is refused, and a named one resolves to the stocked image", () => {
const helper = { ...thing, resources: [{ id: "helper", type: "container", name: "h", artifact: "helper" }] };
const restore = aCatalogueWith(helper);
try {
assert.throws(() => catalogueModule("thing", held), /names the "helper" artifact/);
const m = JSON.parse(catalogueModule("thing", held, { artifacts: { helper: "mesh-helper" } })) as { resources: Record<string, unknown>[] };
assert.equal(m.resources[0]!["image"], digest("b"));
assert.throws(() => catalogueModule("thing", held, { artifacts: { helper: "mesh-nothing" } }), /stocked no such image/);
} finally { restore(); }
});
test("a host-port remap and a lab address are the only other things that change", () => {
const restore = aCatalogueWith(thing);
try {
const m = JSON.parse(catalogueModule("thing", held, {
ports: { "8080": "8090:8080" },
env: { server: { B: "2" } },
})) as { resources: Record<string, unknown>[] };
const server = m.resources.find((r) => r["id"] === "server")!;
assert.deepEqual(server["ports"], ["8090:8080", "9090:9090"]);
assert.deepEqual(server["env"], { A: "1", B: "2" });
} finally { restore(); }
});
test("a manifest the catalogue does not have is refused by name", () => {
const restore = aCatalogueWith(thing);
try {
assert.throws(() => catalogueModule("nothing", held), /no manifest for nothing/);
} finally { restore(); }
});
test("an upstream artifact resolves to the reference the manifest pins, as the machine pulls it", () => {
const web = {
module: "thing", version: "1",
resources: [{ id: "server", type: "container", name: "web", artifact: "server" }],
build: { artifacts: [{ name: "server", kind: "upstream", from: "alpine@" + digest("e") }] },
};
const restore = aCatalogueWith(web);
try {
const m = JSON.parse(catalogueModule("thing", held)) as { resources: Record<string, unknown>[] };
assert.equal(m.resources[0]!["image"], "alpine@" + digest("e"));
assert.equal(m.resources[0]!["artifact"], undefined);
} finally { restore(); }
});