Unify trunk on main: initialization → main #3
@@ -131,6 +131,40 @@ Placing needs a built host binary — set `MESH_LAB_HOST_BINARY` to one. It is a
|
||||
rather than a search on purpose: the declaration design leaves *where `place:` gets its
|
||||
artifacts from* open, and guessing would harden into the answer by accident.
|
||||
|
||||
## Pointing a run at the repositories
|
||||
|
||||
**Every variable is an explicit path, and none of them has a default.** A test whose artifact was
|
||||
not pointed at *skips* — it does not fail — so an unset variable is a green run that proved
|
||||
nothing. That is `novox/hq` 04-ISSUES/005 exactly, and it has now been rediscovered twice, so it
|
||||
is written down here rather than reconstructed a third time.
|
||||
|
||||
```sh
|
||||
export MESH_LAB_HOST_BINARY=<mesh-host>/mesh-host
|
||||
export MESH_LAB_BUNDLE=<mesh-host>/examples/substrate-first-node.lock
|
||||
export MESH_LAB_MODULES=<mesh-control>/examples/modules
|
||||
export MESH_LAB_BUILDER=<mesh-control>/mesh-builder
|
||||
|
||||
# Built with `go build -o <path> ./examples/<name>` in mesh-control.
|
||||
export MESH_LAB_PROVISIONER=<somewhere>/postgres-provisioner
|
||||
export MESH_LAB_OBJECTSTORE_PROVISIONER=<somewhere>/objectstore-provisioner
|
||||
export MESH_LAB_ROUTE_PROXY=<somewhere>/route-proxy
|
||||
```
|
||||
|
||||
`MESH_LAB_HOST_BINARY` and `MESH_LAB_MODULES` do double duty: the repository each sits in is what
|
||||
`suite` rebuilds and what the receipt claims. Point the run at a repository and it is built and
|
||||
claimed; leave it out and it is neither.
|
||||
|
||||
Check before running a long suite — it says which of these are missing rather than skipping
|
||||
quietly:
|
||||
|
||||
```sh
|
||||
node --experimental-strip-types src/cli.ts check
|
||||
```
|
||||
|
||||
If it says the daemon is not reachable, the group grant postdates the shell. `newgrp` fixes it,
|
||||
but a heredoc into `newgrp` runs the suite as a child of a shell that then exits — start it with
|
||||
`setsid nohup … &` inside the heredoc, or the run dies with the shell that launched it.
|
||||
|
||||
## Measured on a workstation
|
||||
|
||||
| | one machine | two machines | two machines + a router |
|
||||
|
||||
@@ -1658,3 +1658,78 @@ test("a third-party workload is adopted, with the credential it already had", {
|
||||
assert.doesNotMatch(reached, /unreachable/,
|
||||
"a container could not reach the other by name, so the module's network did nothing");
|
||||
});
|
||||
|
||||
// The real modules, resolved together on one machine.
|
||||
//
|
||||
// **What this proves without pulling a gigabyte of images**: that five manifests written from the
|
||||
// running system resolve as a graph — keycloak's requirement met by postgres's provision,
|
||||
// capabilities checked, nothing claiming the same singular thing — and that the declaration the
|
||||
// control plane composes is one the host accepts. `plan --json` exists for exactly this: it is
|
||||
// the only way to know that what the control plane emits is what the host takes.
|
||||
//
|
||||
// Running them needs their images stocked and two provisioners built, which is a separate and
|
||||
// larger job. This is the half that can be known now, and it is the half where a design fault
|
||||
// would live.
|
||||
test("the real modules resolve together, and compose a declaration a host accepts", {
|
||||
skip, timeout: 300_000,
|
||||
}, async () => {
|
||||
const modules = ["postgres", "keycloak", "gitea", "minio", "mailu"];
|
||||
for (const name of modules) {
|
||||
const raw = readFileSync(
|
||||
`${process.env["MESH_LAB_MODULES"]}/${name}.json`, "utf8");
|
||||
await must("anchor", `printf %s ${quote(raw)} > /${name}.json`);
|
||||
await must("anchor", `docker cp /${name}.json mesh-control:/${name}.json`);
|
||||
await mesh(`module add /${name}.json`);
|
||||
}
|
||||
|
||||
// Assigned one at a time, because assignment resolves the whole set and says so immediately.
|
||||
// A refusal here is the graph rejecting something, which is the point of asking.
|
||||
for (const name of modules) {
|
||||
await mesh(`assign anchor ${name}`);
|
||||
}
|
||||
|
||||
const plan = await mesh("plan anchor --json", 120_000);
|
||||
const declaration = JSON.parse(plan.slice(plan.indexOf("{")));
|
||||
const byId = new Map<string, any>(
|
||||
(declaration.resources as any[]).map((r) => [r.id, r]));
|
||||
const ids = [...byId.keys()];
|
||||
|
||||
// Every module's own network, which only exists because more than one container needs to reach
|
||||
// another by name.
|
||||
for (const id of ["postgres.net", "keycloak.net", "minio.net", "mailu.net"]) {
|
||||
assert.ok(byId.has(id), `${id} is missing; ${ids.length} resources: ${ids.join(", ")}`);
|
||||
assert.equal(byId.get(id).type, "network");
|
||||
}
|
||||
|
||||
// The cross-module edge: keycloak asked for a database and was told where it is and given a
|
||||
// credential. Neither file is anything keycloak's manifest could have written.
|
||||
const bound = [...byId.values()].find((r) =>
|
||||
r.type === "file" && r.path === "/var/lib/keycloak/database.json");
|
||||
assert.ok(bound, `keycloak was never told where its database is: ${ids.join(", ")}`);
|
||||
assert.match(JSON.stringify(bound), /postgres/,
|
||||
"keycloak's binding does not name what answered its requirement");
|
||||
|
||||
const credential = [...byId.values()].find((r) =>
|
||||
r.type === "file" && r.path === "/var/lib/keycloak/database.env");
|
||||
assert.ok(credential, "keycloak was given no credential for its database");
|
||||
assert.ok(credential.sealed, "keycloak's credential is not sealed, so the mesh can read it");
|
||||
assert.ok(!credential.content, "a credential arrived as content rather than sealed");
|
||||
|
||||
// And the provider was told who asked, which is what its provisioner reconciles against.
|
||||
const grants = [...byId.values()].find((r) =>
|
||||
r.type === "file" && String(r.path).startsWith("/var/lib/postgres/grants"));
|
||||
assert.ok(grants, "postgres was never told which modules were granted a database");
|
||||
assert.match(JSON.stringify(grants), /keycloak|gitea/,
|
||||
"the grants file names neither module that asked for a database");
|
||||
|
||||
// Secrets reach containers as files, never as environment in the declaration.
|
||||
const containers = [...byId.values()].filter((r) => r.type === "container");
|
||||
assert.ok(containers.length >= 12,
|
||||
`only ${containers.length} containers; mailu alone is nine`);
|
||||
for (const c of containers) {
|
||||
for (const [key, value] of Object.entries(c.env ?? {})) {
|
||||
assert.doesNotMatch(String(value), /^[A-Za-z0-9+/]{24,}={0,2}$/,
|
||||
`${c.name} carries something secret-shaped in env.${key}, which the broker would see`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user