The one-node bed places at the site it operates, and tolerates the CP recreating

Genesis places the anchor at the same site the test re-places it at, so that step
is a no-op rather than a change that recreates the control plane. And mesh() —
which runs commands inside the control-plane container — retries a transient
"container not running", because the control plane is a live mesh-managed
container the mesh recreates when its declaration changes (e.g. its first
.internal add-host). Also passes --sdk-source/--tools-ref for the SDK build.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
2026-09-16 14:10:26 +02:00
parent eff91742e8
commit f57e05e75e
2 changed files with 28 additions and 1 deletions
+21 -1
View File
@@ -217,7 +217,23 @@ async function must(machine: string, command: string, timeoutMs?: number): Promi
return out;
}
async function mesh(command: string, timeoutMs?: number): Promise<string> {
return must(CONTROL, `docker exec mesh-control /mesh-control ${command}`, timeoutMs);
// The control plane is a live, mesh-MANAGED container: the mesh recreates it whenever its
// declaration changes — most visibly when the machine first gets its `.internal` name on the
// private network, which becomes the container's `--add-host` (containers are immutable, so a new
// spec is a new container). A `docker exec mesh-control` that lands in that brief recreate window
// fails with "container ... is not running". That is not the mesh being wrong — it is a command
// racing a legitimate restart — so it is retried until the control plane answers again. A real
// command failure (anything else) still throws at once.
const deadline = Date.now() + (timeoutMs ?? 120_000);
for (;;) {
const { out, ok } = await on(CONTROL, `docker exec mesh-control /mesh-control ${command}`, timeoutMs);
if (ok) return out;
if (/is not running|No such container/i.test(out) && Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 2_000));
continue;
}
throw new Error(`${CONTROL}: docker exec mesh-control /mesh-control ${command}\n${out}`);
}
}
/**
@@ -468,10 +484,14 @@ before(async () => {
source,
sourceRef,
toolsSource: forgeUrl(BASE.repo),
toolsRef: refFor(BASE.repo),
catalogSource: forgeUrl(MODULE.repo),
catalogRef: refFor(MODULE.repo),
sdkSource: forgeUrl("mesh-sdk"),
sdkRef: refFor("mesh-sdk"),
// The same site N1 re-places the anchor at, so N1 is a no-op and the control plane is not
// recreated mid-test (its --add-host would otherwise change).
site: "hosting",
log: (m) => console.log(m),
});
} catch (err) {