From cc82badd56526da194dd7887dae415bd71268815 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 7 Sep 2026 20:33:53 +0200 Subject: [PATCH] swarm: move the controller's two packages to deploy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `package` (the daemon build) and `swarmctlPackage` (the operator CLI installed beside it) are host decisions, so they join the `deploy.swarm-controller` block that already holds `enable`, the socket path and the three local-disk credentials. ⚠️ The target namespace is spelled out in the shim comment because getting it wrong here does not fail. `deploy.hive-controller` also exists — it is hive-c0re's, carrying `tls.*` and `statusPublish.*`, and is referenced from four modules. A rename pointing at it would land on a live, unrelated option and evaluate cleanly. The module already warned about this above its own deploy block; the warning now sits next to the entries it governs too. `swarm-ui.nix`'s package description cited `swarm.controller.package` as the precedent for "wired from flake.nix rather than defaulted to pkgs". That was true when written and stops being true here, so it moves with it — it lives in a module this slice already finished, which is exactly where a per-module sweep stops looking. These were the last two `services.hyperhive.swarm.*` writers in flake.nix; that file now has none. Riding along, and not a defect fix: `controllerOldPath` spelled `enable` the NEW way while every other entry used the old one, so six of the seven controller shims were exercised and the seventh was not. It is named for testing old paths, so it now uses the old path throughout. Unlike the nats fixture there was no comment claiming otherwise — this is coverage the fixture was already shaped to provide. --- flake.nix | 4 +- nix/host-modules/deploy.nix | 11 +++++ nix/host-modules/swarm-controller.nix | 63 ++++++++++++++------------- nix/host-modules/swarm-ui.nix | 2 +- nix/module-eval.nix | 6 ++- 5 files changed, 51 insertions(+), 35 deletions(-) diff --git a/flake.nix b/flake.nix index 2d0b2f46..9e6d2ad4 100644 --- a/flake.nix +++ b/flake.nix @@ -142,10 +142,10 @@ agentBaseToplevel = lib.mkDefault self.packages.x86_64-linux.agent-base-toplevel; managerToplevel = lib.mkDefault self.packages.x86_64-linux.ruth-toplevel; }; - services.hyperhive.swarm.controller.package = + services.hyperhive.deploy.swarm-controller.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarm-controller; - services.hyperhive.swarm.controller.swarmctlPackage = + services.hyperhive.deploy.swarm-controller.swarmctlPackage = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarmctl; services.hyperhive.deploy.swarm-ui.package = diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index b1c36f90..45b1eade 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -381,6 +381,17 @@ in [ "services" "hyperhive" "swarm" "authelia" "bridgePackage" ] [ "services" "hyperhive" "deploy" "authelia" "bridgePackage" ] ) + # ⚠️ `swarm-controller`, not `hive-controller` — see the note in + # ./swarm-controller.nix. Both namespaces exist, so the wrong target here + # lands on a live option in hive-c0re's tree instead of failing. + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "controller" "package" ] + [ "services" "hyperhive" "deploy" "swarm-controller" "package" ] + ) + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "controller" "swarmctlPackage" ] + [ "services" "hyperhive" "deploy" "swarm-controller" "swarmctlPackage" ] + ) ]; # ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index c9a939e5..29d445ec 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -196,7 +196,7 @@ let # config back to it — and to get it wrong the day one of them changes. swarmctlConfigured = pkgs.symlinkJoin { name = "swarmctl-configured"; - paths = [ cfg.swarmctlPackage ]; + paths = [ deployCfg.swarm-controller.swarmctlPackage ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/swarmctl ${ @@ -243,30 +243,8 @@ in # asserts it, and that was never an exception to "not derived from # services.hyperhive.enable": that mode says "this box is the whole # deployment", which answers the topology question outright, where - # `enable` alone never can. What stays here is what the daemon IS. - - package = lib.mkOption { - type = lib.types.package; - defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-controller"; - description = '' - swarm-controller package. Wired by default from this flake's own - package set (see `flake.nix`); override to run a different build. - ''; - }; - - swarmctlPackage = lib.mkOption { - type = lib.types.package; - defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarmctl"; - description = '' - `swarmctl` package — the swarm operator's CLI, installed on this - host alongside the daemon and wrapped with the paths it needs. - - A separate option from `package` rather than a second binary in - the same derivation: the CLI runs as root and acts directly, - the daemon runs unprivileged and serves a socket, and pinning one - without the other is a thing an operator may legitimately want. - ''; - }; + # `enable` alone never can. Both packages moved to that same + # `deploy.swarm-controller` block. What stays here is what the daemon IS. staleAfterSeconds = lib.mkOption { type = lib.types.ints.positive; @@ -371,16 +349,39 @@ in }; # What stays above is what the controller IS to the swarm: the quick-links - # it publishes, the client id it is registered under, how stale a snapshot - # may read, and its packages. What the host running it decides is here — - # where its socket lives, and the three credentials it reads off local - # disk. `enable` already lives in ./deploy.nix, which also carries the - # renames. + # it publishes, the client id it is registered under, and how stale a + # snapshot may read. What the host running it decides is here — which two + # builds it runs, where its socket lives, and the three credentials it reads + # off local disk. `enable` already lives in ./deploy.nix, which also carries + # the renames. # # ⚠️ `deploy.swarm-controller`, NOT `deploy.hive-controller`. Both exist: # the latter is hive-c0re's namespace, where `tls.*` lives. A definition on # the wrong one lands on a live, unrelated option rather than failing. options.services.hyperhive.deploy.swarm-controller = { + package = lib.mkOption { + type = lib.types.package; + defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-controller"; + description = '' + swarm-controller package. Wired by default from this flake's own + package set (see `flake.nix`); override to run a different build. + ''; + }; + + swarmctlPackage = lib.mkOption { + type = lib.types.package; + defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarmctl"; + description = '' + `swarmctl` package — the swarm operator's CLI, installed on this + host alongside the daemon and wrapped with the paths it needs. + + A separate option from `package` rather than a second binary in + the same derivation: the CLI runs as root and acts directly, + the daemon runs unprivileged and serves a socket, and pinning one + without the other is a thing an operator may legitimately want. + ''; + }; + socketPath = lib.mkOption { type = lib.types.str; default = "/run/swarm-controller/controller.sock"; @@ -591,7 +592,7 @@ in after = [ "network.target" ]; serviceConfig = { - ExecStart = "${cfg.package}/bin/swarm-controller"; + ExecStart = "${deployCfg.swarm-controller.package}/bin/swarm-controller"; # The two differ on purpose. The queue credential is # unconditional — the assertions above make its path a value that diff --git a/nix/host-modules/swarm-ui.nix b/nix/host-modules/swarm-ui.nix index c7c7aac1..f50b3eff 100644 --- a/nix/host-modules/swarm-ui.nix +++ b/nix/host-modules/swarm-ui.nix @@ -90,7 +90,7 @@ in controller's own API. Wired by default from this flake's own package set (see - `flake.nix`), the same way `swarm.controller.package` is. There + `flake.nix`), the same way `deploy.swarm-controller.package` is. There is deliberately **no overlay** in this project, so a `pkgs.swarm-ui` default here would name an attribute that does not exist on any real deployment. diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 71598d6a..8e2e3ad7 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -153,8 +153,12 @@ let deploy.matrix.maxRequestSize = 99000000; }; + # `enable` is spelled the OLD way like everything else here, so all seven + # of the controller's shims are exercised rather than six. controllerOldPath = hive { - deploy.swarm-controller.enable = true; + swarm.controller.enable = true; + swarm.controller.package = pkgs.emptyDirectory; + swarm.controller.swarmctlPackage = pkgs.emptyDirectory; swarm.controller.socketPath = "/run/test-ctrl/ctrl.sock"; swarm.controller.forgeTokenFile = "/run/secrets/ctrl-forge.token"; swarm.controller.authBridgeUrl = "http://127.0.0.1:19097";