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:
parent
7eb966fe2b
commit
b68fd7306e
6 changed files with 73 additions and 58 deletions
|
|
@ -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);
|
||||
}
|
||||
)
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in a new issue