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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user