INFINITO_SWARM_MESHES names a layout file of applications overrides. The
controller mesh, the transport mesh and the stale-link scan read it through
the CLI's own spec reader.
The prologue hands the chosen declarations to the mesh writer, and the
controller mesh and the transport switch follow the first declared mesh
instead of a hardcoded 'swarm'.
Locally the controller is the act container on the host's network, so its
interface outlives the round. A link left by other declarations still routes
the pool, and a development round after a three-mesh one died on
'RTNETLINK answers: File exists'. The controller now drops WireGuard links
that hold a pool address but name no declared mesh before it joins; nothing
outside the pool is touched.
The guarantees were asserted against the declared swarm and data pair,
so they proved two meshes work rather than that the planner works. A
deployment declares its own, and the review asks for any number of them with
the nodes arranged however the client wants.
The same invariants now run over generated topologies: one to eight meshes,
three arrangements each, hosts dealt out so some belong to several meshes and
some to none. 2247 subtests, four seconds, and the planner needed no change to
pass them.
Three runs of the transport benchmark, per module call:
become off become on
docker 247ms 246ms
ssh over mesh 215ms 1259ms
The connection is not the cost - ssh through the tunnel beats docker exec by
13% - and the tunnel is 4%. What the meshed arm pays is the sudo prompt: free
over the container connection, which runs as root, and 1046ms per escalated
call over ssh as the administrator. That is the 414ms per task the three-arm
comparison measured across a whole deploy.
A lab-only sudoers drop-in removes it. It is applied from the mesh prologue
while the inventory still reaches the nodes as root, so it is in place before
anything logs in as the administrator, and it touches no role: production
keeps 'administrator ALL=(ALL) ALL' and its password prompt.
The cost is that CI no longer exercises password sudo over the mesh. It never
exercised it on the direct arm either, which connects as root, and a wrong
password fails loudly rather than silently.
Run 37931817959 timed the four cells and two of them are real: a module
call costs 245ms over docker and 212ms over ssh through the tunnel, with or
without become on the docker side. The connection plugin is not the cost.
The escalated ssh cell is not real. The benchmark ran without the extras, so
ansible_become_password was absent and all 200 calls failed on 'Incorrect sudo
password' - 3.2s each, which prices a failing sudo rather than a working one.
It now passes the same two -e files the deploy passes.
Its exit code also reached the round, so a diagnostic turned three green
deploys red. transport_bench now discards its own rc: whether a deploy passes
is not a benchmark's business.
A second playbook-* file at the root makes 'playbook' a shared
delimiter-bounded prefix, and the structure lint reads that as a folder in
disguise: '2 files share the prefix playbook -> move them into ./playbook/'.
It failed test-lint, which gates the deploy chunks, so run 37929774651
produced no benchmark.
The alternative was renaming playbook-mesh.yml into a new playbook/ folder,
which is a structural change to the branch's own feature made for the sake of
a diagnostic. Renaming the diagnostic is the smaller move.
The local run missed it because the file was still untracked, and the rule
walks git ls-files.
The three-arm comparison on web-app-gitea#0 put the meshed arm at 414ms
per task over the direct arm, and the tunnel at 4% of that. What it could not
split is the rest: the arms differ both in connection plugin (docker against
ssh) and in escalation (root with no prompt against administrator with a
password sudo on every task).
A fixed set of module calls, timed either side of the transport switch with
become off and on, gives four numbers that separate the two. It costs about a
minute where a fourth deploy arm would have cost three hours, and it needs no
root login and no sudoers change.
INFINITO_SWARM_TRANSPORT_BENCH guards it, so a normal round times nothing.
The arm existed to answer one question: how much of the meshed arm's
cost is the connection plugin and how much is the tunnel. Runs 37592061960
(docker), 37753506661 (SSH on the underlay) and 37621556682 (SSH over
WireGuard) answered it on web-app-gitea#0, debian/ext4:
pass 1 5964s / 8511s / 8832s
pass 2 5319s / 7472s / 7705s
Leaving ansible_connection: docker costs +4700s, the tunnel +554s - 89.5%
against 10.5%. The answer is recorded; the scaffolding does not need to ship.
Reverts d792519725, 1b28f87b37, 89b8a8c8d1, 0470491e1a, 529c5ace43,
dd3d10a9a2, c20dd0e5f5, 458d8956e1, 63ade1e03b, d281555945 and 4adfb6e3d2.
95cfc8b7b7 is already superseded by bbfd82f89, which sets the profiling limit
upstream.
A meshed round deployed every role twice, once over the container
connection and once again over the tunnel, which left the most expensive
transport carrying nothing but idempotence checks. The first pass now brings
up the mesh and nothing else, so the pass after the seam is the only one
that deploys the applications.
The converge drops the backup inventory with it. That node is deployed after
the rotation now, so it renders the current mesh on its first run and has
nothing to converge from.
Only the first round deploys the backup host, so a later round meets a
container that has never been provisioned: the mesh role is the first thing
to reach it, and installing the tooling fails because nothing has populated
its package index. Every meshed variant above zero died there.
The converge now takes the sibling inventory only when the round brought
that node up, which is the only round whose data plane has a second spoke
to carry.
Reverts the apt refresh added for the same symptom. It reported the index
fresh on exactly the host that had none, so it never addressed this and the
rounds that do deploy the backup node were already converging without it.
The converge ran over devices.yml alone, so the backup host kept the
identity it was deployed with while the hub had already been told the new
one. Nothing caught it: the backup node is not a spoke of any play that runs
after the seam, so its half of the data plane went quiet without failing.
The play forces the axis on, so reaching it through the sibling inventory is
independent of the backup deploy's own mesh state.
write_mesh takes rotate, so the round mints a fresh keypair for every member
between the passes and the converge that follows carries them. The rotation is
asked for rather than inherited from a mirror that happened to wipe the keys,
which is what the requirement's two rotation criteria describe.
It holds a mesh address and routes the pool, but it is the machine running
the play. Pointed at itself over ssh, every task a role delegates to it dials
its own tunnel address instead of staying local -- which is where the second
pass died, on the controller-side NFS mount, after running 189 tasks on the
manager and 176 on each worker over the mesh without a failure.
The nodes are reached by container name over the docker connection, which
only the lab network resolves. The controller is not on it, so it is handed
the addresses default.env already pins for the five hosts.
The rotation gate mirrors one host's host_vars over every other, so the mesh
write that follows mints a fresh keypair for all but the mirror source. The
nodes kept running the keys of the first pass, so the hub turned the
controller away and its handshake gate failed the deploy.
Re-render every node before the controller joins, so the hub authorises the
set the inventory now holds.
Nodes resolve each other through the extra_hosts compose hands them; the
controller is not a container and got no such map, so wg setconf could not
resolve the hub and the swarm interface failed to come up. Pass the same
name-to-address pairs the compose file builds from the topology.