Watch
0
0
Fork
You've already forked hyperhive
0

refresh-consumer: key the restart on the file's mtime, not a pre-write compare

The restart decision was a shell variable set by comparing the fetched
value with the file just before overwriting it. A run that wrote the
file and then failed before the restart (the matrix unit's registration
render, or `systemctl --machine` finding no bus yet) left a retry that
saw an unchanged file and never restarted the consumer.

The file is now written only when the value differs, so its mtime marks
the last real change, and `refresh_consumer <machine> <unit> <path>`
compares that mtime with the consumer's ActiveEnterTimestamp on every
run, the shape the openbao client-CA refresh in swarm-bao.nix already
uses. A consumer that started after the last change is left alone; a
running one is try-restarted, a failed one reset and started, all with
--no-block, and nothing happens while the container is down.

The helper's comment block also exceeded the 30-line limit
(`comment-block lint` failed on d871467d); its per-function notes now
sit beside the functions.

module-eval-bao-grants asserts the gated write, the path the refresh is
keyed on, and the mtime-vs-start comparison for each consumer.

Refs #4662
This commit is contained in:
atlas 2026-09-30 00:27:33 +02:00 • committed by mara
commit b68fd7306e
6 changed files with 73 additions and 58 deletions

View file

@ -1565,8 +1565,10 @@ let
}
]
# A consumer that loads its credential at start never sees one a later
# attempt lands, so the fetch that lands it restarts that consumer — only
# on a changed value, so a routine re-fetch leaves it running.
# attempt lands, so the fetch restarts it when the file is newer than the
# consumer's last start. The file is written only when the value differs,
# so its mtime moves only on a real change, and the decision is re-read on
# every run instead of carried in a variable a failed run would lose.
++
map
(
@ -1576,13 +1578,26 @@ let
consumer,
}:
{
name = "${fetch} restarts ${consumer} in ${machine} when the value it fetched changed";
name = "${fetch} restarts ${consumer} in ${machine} when its file is newer than the consumer's start";
ok =
let
s = baoGrantWithConsumers.systemd.services.${fetch}.script;
# Text only: the script refers to store paths, and a string cut from it
# keeps that context, which `splitString` refuses as a separator.
s = builtins.unsafeDiscardStringContext baoGrantWithConsumers.systemd.services.${fetch}.script;
call = "refresh_consumer ${lib.escapeShellArg machine} ${consumer} ";
# The path the refresh is keyed on, as rendered.
path = lib.head (lib.splitString "\n" (lib.last (lib.splitString call s)));
# Everything from the gate on that path to the end of its `if`.
gated = lib.head (
lib.splitString "fi\n" (lib.last (lib.splitString "if secret_differs ${path} " s))
);
in
lib.hasInfix "secret_differs " s
&& lib.hasInfix "refresh_consumer ${lib.escapeShellArg machine} ${consumer}" s;
lib.hasInfix call s
&& lib.hasInfix "atomic_write_secret " gated
&& lib.hasInfix path gated
&& lib.hasInfix "ActiveEnterTimestamp" s
&& lib.hasInfix ''if [ "$written_us" -le "$started_us" ]; then'' s
&& !(lib.hasInfix "$changed" s);
}
)
[