From e091add37a5d6b4b962ab520378016e50e9a1b1b Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 7 Sep 2026 18:53:43 +0200 Subject: [PATCH] swarm: move both metric stores' package to deploy, and cover their shims MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same rule as matrix and grafana: which build a service runs is a decision of the host that runs it. Both stores already had a `deploy.` option for retention, so the package joins something rather than opening a namespace. The prose in both modules claimed the package as part of "what the store IS from any hive's point of view" — a client hive needs the domain and the port to reach a store, never the build it runs. deploy.nix's own comment made the same claim about the pair and is corrected with them. Separately, and the reason this commit adds a fixture rather than a line: NEITHER STORE HAD AN OLD-PATH FIXTURE AT ALL. `swarm.victorialogs.` and `swarm.victoriametrics.` had zero hits in module-eval.nix, so the `enable` shims from the first slice and both `retentionPeriod` shims have been uncovered since they landed — the suite would have gone green with any of them deleted. That is precisely what the wireguard fixture's own comment warns about: a missing shim reads as a clean tree and breaks every existing operator config. `storesOldPath` therefore sets all six old paths, not just the two this commit moves. The case reads the package the CONTAINER renders rather than the option, so a shim that resolves but stops reaching the module fails too. Refs #3772. --- nix/host-modules/deploy.nix | 13 +++++++++-- nix/host-modules/swarm-victorialogs.nix | 23 ++++++++++--------- nix/host-modules/swarm-victoriametrics.nix | 23 ++++++++++--------- nix/module-eval.nix | 26 ++++++++++++++++++++++ 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index db784892..d8e818b8 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -259,8 +259,9 @@ in # Retention is read only where the container is defined, so it is a # decision of the host running the store rather than something the swarm - # agrees on. The two stores keep everything else — package, domain, port - # — in `swarm.*`, because a client hive needs those to reach them. + # agrees on. The two stores keep their domain and port in `swarm.*`, + # because a client hive needs those to reach them; `package` followed + # `enable` and `retentionPeriod` across in a later slice. (lib.mkRenamedOptionModule [ "services" "hyperhive" "swarm" "victoriametrics" "retentionPeriod" ] [ "services" "hyperhive" "deploy" "victoriametrics" "retentionPeriod" ] @@ -353,6 +354,14 @@ in [ "services" "hyperhive" "swarm" "grafana" "package" ] [ "services" "hyperhive" "deploy" "grafana" "package" ] ) + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "victorialogs" "package" ] + [ "services" "hyperhive" "deploy" "victorialogs" "package" ] + ) + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "victoriametrics" "package" ] + [ "services" "hyperhive" "deploy" "victoriametrics" "package" ] + ) ]; # ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the diff --git a/nix/host-modules/swarm-victorialogs.nix b/nix/host-modules/swarm-victorialogs.nix index 4709e3eb..ddead0d2 100644 --- a/nix/host-modules/swarm-victorialogs.nix +++ b/nix/host-modules/swarm-victorialogs.nix @@ -56,17 +56,11 @@ let ''; in { - # What stays here is what the store IS from any hive's point of view: its - # package, the name it answers on, the port. `enable` and `retentionPeriod` - # are decisions of the host that runs it and live under `deploy.*`. + # What stays here is what the store IS from any hive's point of view: the + # name it answers on and the port. `enable`, `package` and + # `retentionPeriod` are decisions of the host that runs it and live under + # `deploy.*`. options.services.hyperhive.swarm.victorialogs = { - package = lib.mkOption { - type = lib.types.package; - default = pkgs.victorialogs; - defaultText = lib.literalExpression "pkgs.victorialogs"; - description = "VictoriaLogs package to run."; - }; - machine = lib.mkOption { type = lib.types.str; readOnly = true; @@ -116,6 +110,13 @@ in # and a hive that is a *client* of the log store never consults it. That # makes it a `deploy.*` value by the same rule as the seal on the secret # store — options on the auto-deployed service itself. + options.services.hyperhive.deploy.victorialogs.package = lib.mkOption { + type = lib.types.package; + default = pkgs.victorialogs; + defaultText = lib.literalExpression "pkgs.victorialogs"; + description = "VictoriaLogs package to run."; + }; + options.services.hyperhive.deploy.victorialogs.retentionPeriod = lib.mkOption { type = lib.types.str; default = "30d"; @@ -259,7 +260,7 @@ in services.victorialogs = { enable = true; - package = cfg.package; + package = deployCfg.victorialogs.package; # ⚠️ PINNED TO LOOPBACK for the same reason the metrics store is, # and it matters more here: upstream's default listens on every diff --git a/nix/host-modules/swarm-victoriametrics.nix b/nix/host-modules/swarm-victoriametrics.nix index 7e080d97..604e9d3d 100644 --- a/nix/host-modules/swarm-victoriametrics.nix +++ b/nix/host-modules/swarm-victoriametrics.nix @@ -30,17 +30,11 @@ let domainBase = if swarmDomain == null then "invalid" else swarmDomain; in { - # What stays here is what the store IS from any hive's point of view: its - # package, the name it answers on, the port. `enable` and `retentionPeriod` - # are decisions of the host that runs it and live under `deploy.*`. + # What stays here is what the store IS from any hive's point of view: the + # name it answers on and the port. `enable`, `package` and + # `retentionPeriod` are decisions of the host that runs it and live under + # `deploy.*`. options.services.hyperhive.swarm.victoriametrics = { - package = lib.mkOption { - type = lib.types.package; - default = pkgs.victoriametrics; - defaultText = lib.literalExpression "pkgs.victoriametrics"; - description = "VictoriaMetrics package to run."; - }; - machine = lib.mkOption { type = lib.types.str; readOnly = true; @@ -79,6 +73,13 @@ in # Retention is a property of the store this host runs, not something the # swarm has to agree on: it is read only where the container is defined, # and a hive that is a *client* of the metrics store never consults it. + options.services.hyperhive.deploy.victoriametrics.package = lib.mkOption { + type = lib.types.package; + default = pkgs.victoriametrics; + defaultText = lib.literalExpression "pkgs.victoriametrics"; + description = "VictoriaMetrics package to run."; + }; + options.services.hyperhive.deploy.victoriametrics.retentionPeriod = lib.mkOption { type = lib.types.str; default = "5y"; @@ -213,7 +214,7 @@ in services.victoriametrics = { enable = true; - package = cfg.package; + package = deployCfg.victoriametrics.package; retentionPeriod = deployCfg.victoriametrics.retentionPeriod; # ⚠️ PINNED TO LOOPBACK, and this is a correction rather than a diff --git a/nix/module-eval.nix b/nix/module-eval.nix index f33e3dbf..5f098c53 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -154,6 +154,20 @@ let swarm.controller.queue.clientSecretFile = "/run/secrets/ctrl-queue.secret"; }; + # The two stores, which had NO old-path fixture at all until this slice — + # their `enable` and `retentionPeriod` shims have been uncovered since they + # landed, which is precisely the "a missing shim reads as a clean tree" + # failure ./module-eval.nix's wireguard fixture was written to catch. All six + # old paths are set, so dropping any single entry fails the eval. + storesOldPath = hive { + swarm.victoriametrics.enable = true; + swarm.victorialogs.enable = true; + swarm.victoriametrics.retentionPeriod = "3d"; + swarm.victorialogs.retentionPeriod = "5d"; + swarm.victoriametrics.package = pkgs.emptyDirectory; + swarm.victorialogs.package = pkgs.emptyDirectory; + }; + grafanaOldPath = hive { deploy.grafana.enable = true; swarm.grafana.socketDir = "/run/test-grafana-sock"; @@ -476,6 +490,18 @@ let # host-side half depends on: no store here, so no bind mount and no unit. # Without it a hive that merely names a token would drag the store's # container config into its evaluation. + # Reads the package the CONTAINER renders, not the option: a shim that + # resolves but stops reaching the module would leave the store running + # nixpkgs' default while the operator's override read back fine. + name = "a config written against the pre-rename store paths still picks the operator's package"; + ok = + storesOldPath.containers.swarm-victorialogs.config.services.victorialogs.package + == pkgs.emptyDirectory + && + storesOldPath.containers.swarm-victoriametrics.config.services.victoriametrics.package + == pkgs.emptyDirectory; + } + { name = "a bootstrap token on a host that runs no store grants nothing"; ok = !(baoGrantNoStore.systemd.services ? swarm-bao-bootstrap-dir); }