From e4e62be506fcfd5682078c2c8b42d35c4fdde430 Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 10 Oct 2026 01:22:32 +0200 Subject: [PATCH] module-eval/hive-otel: pin the fetch reviving a start-limited collector On a first boot the secret file does not exist until the first fetch succeeds, so the collector fails `LoadCredential` into its start limit, which leaves it `failed`. `refresh_unit` already handles that: it sees `is-failed`, runs `reset-failed` (which clears the start-limit counter) and starts it. This case pins that arm, the empty-ActiveEnterTimestamp fallback that makes the file count as newer, and that the collector only wants the fetch rather than requiring it. Refs #5015 --- nix/module-eval/hive-otel.nix | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/nix/module-eval/hive-otel.nix b/nix/module-eval/hive-otel.nix index 42941877..93554ef0 100644 --- a/nix/module-eval/hive-otel.nix +++ b/nix/module-eval/hive-otel.nix @@ -232,6 +232,29 @@ let && lib.hasInfix "ActiveEnterTimestamp" s && lib.hasInfix ''if [ "$written_us" -le "$started_us" ]; then'' s; } + { + # On a first boot the file does not exist until the fetch succeeds, so + # the collector fails `LoadCredential` into its start limit, i.e. the + # `failed` state. Only `reset-failed` clears that limit, so the fetch + # has to reset before it starts; `try-restart` acts on no failed unit. + # A never-active collector has an empty `ActiveEnterTimestamp`, read as + # 0, so the file always counts as newer. The collector only `wants` the + # fetch, so an unreachable store does not hold it back. + name = "the hive collector's fetch revives a collector that hit its start limit without the file"; + ok = + let + s = builtins.unsafeDiscardStringContext (hiveOtelFetch hiveOtelLeaf).script; + c = hiveOtelLeaf.systemd.services.opentelemetry-collector; + failedArm = lib.last (lib.splitString ''is-failed --quiet "$unit"; then'' s); + in + lib.hasInfix ''is-failed --quiet "$unit"; then'' s + && lib.hasInfix ''reset-failed "$unit"'' failedArm + && lib.hasInfix ''start --no-block "$unit"'' ( + lib.last (lib.splitString ''reset-failed "$unit"'' failedArm) + ) + && lib.hasInfix "started_us=0" s + && !(builtins.elem "swarm-bao-hive-otel-oidc.service" (c.requires or [ ])); + } { # The store is the one route, on the IdP's own host too: no default into # authelia's tree and no unit waiting for a file to appear there.