diff --git a/nix/vm-tests/agent-toplevels.nix b/nix/vm-tests/agent-toplevels.nix new file mode 100644 index 000000000..9177ad2f5 --- /dev/null +++ b/nix/vm-tests/agent-toplevels.nix @@ -0,0 +1,70 @@ +# The agents' toplevels as the controller's meta flake builds them, for the VM +# tests that deploy agents without network or a substituter (./full-setup.nix, +# ./semi-spread.nix). `hive-meta-flake/testdata/meta-flake-swarm.nix.in`, filled +# in with the controller's settings, is that flake: the toplevels are built from +# it here, so the builder finds them in its store. The builder's nix daemon runs +# with `max-jobs = 0`, so a missing toplevel fails the build instead of +# compiling. +{ + pkgs, + self, + agents, +}: +let + inherit (pkgs) lib; + + inherit (import ./hyperhive-fixture-repo.nix { inherit pkgs self; }) hyperhiveRepo; + + metaTemplate = ../../hive-meta-flake/testdata/meta-flake-swarm.nix.in; + + # The values the fixture has a placeholder for. A swarm whose controller sends + # another set renders another flake, so evaluation stops there. + forwardedVars = [ + "HIVE_AGENT_BAO_ADDR" + "HIVE_AGENT_BAO_SERVICES_PKI_MOUNT" + "HIVE_AGENT_LOGS_QUERY_URL" + "HIVE_AGENT_METRICS_URL" + "HIVE_FORGE_URL" + "HIVE_MATRIX_URL" + ]; + + # The meta flake the controller renders for `agents`, from its settings JSON + # (`SWARM_CONTROLLER_META_FLAKE`). `hyperhive` is `self`: the agents' toplevels + # do not depend on how the input is pinned. + filled = + settingsJson: pin: + let + settings = builtins.fromJSON settingsJson; + names = [ "HYPERHIVE_URL" ] ++ forwardedVars; + values = [ pin ] ++ map (name: settings.vars.${name}) forwardedVars; + in + assert lib.assertMsg + (builtins.attrNames settings.vars == forwardedVars && !settings.github_disabled) + "the controller's meta flake settings changed: update hive-meta-flake/testdata/meta-flake-swarm.nix.in"; + builtins.replaceStrings (map (name: "@${name}@") names) values (builtins.readFile metaTemplate); + + toplevels = + settingsJson: + let + flake = import (builtins.toFile "meta-flake.nix" (filled settingsJson "unused")); + evaluated = flake.outputs { + self = null; + hyperhive = self; + }; + in + map (agent: evaluated.nixosConfigurations.${agent}.config.system.build.toplevel) agents; +in +{ + inherit hyperhiveRepo metaTemplate toplevels; + + # What the builder's store needs besides the toplevels: every source tree the + # meta flake's lock names, keyed by narHash (nix takes a locked input from the + # store when its path is valid), and the repo the test pushes to the forge. + sourcePaths = [ + self + self.inputs.nixpkgs + self.inputs.crane + self.inputs.treefmt-nix + hyperhiveRepo + ]; +} diff --git a/nix/vm-tests/full-setup.nix b/nix/vm-tests/full-setup.nix index 76b941a1c..9b9f0c1dd 100644 --- a/nix/vm-tests/full-setup.nix +++ b/nix/vm-tests/full-setup.nix @@ -39,46 +39,12 @@ let "spawn" ]; - inherit (import ./hyperhive-fixture-repo.nix { inherit pkgs self; }) hyperhiveRepo; - - metaTemplate = ../../hive-meta-flake/testdata/meta-flake-swarm.nix.in; - - # The values the fixture has a placeholder for. A swarm whose controller sends - # another set renders another flake, so evaluation stops there. - forwardedVars = [ - "HIVE_AGENT_BAO_ADDR" - "HIVE_AGENT_BAO_SERVICES_PKI_MOUNT" - "HIVE_AGENT_LOGS_QUERY_URL" - "HIVE_AGENT_METRICS_URL" - "HIVE_FORGE_URL" - "HIVE_MATRIX_URL" - ]; - - # The meta flake the controller renders for `agents`, from its settings JSON - # (`SWARM_CONTROLLER_META_FLAKE`). `hyperhive` is `self`: the agents' toplevels - # do not depend on how the input is pinned. - filled = - settingsJson: pin: - let - settings = builtins.fromJSON settingsJson; - names = [ "HYPERHIVE_URL" ] ++ forwardedVars; - values = [ pin ] ++ map (name: settings.vars.${name}) forwardedVars; - in - assert lib.assertMsg - (builtins.attrNames settings.vars == forwardedVars && !settings.github_disabled) - "the controller's meta flake settings changed: update hive-meta-flake/testdata/meta-flake-swarm.nix.in"; - builtins.replaceStrings (map (name: "@${name}@") names) values (builtins.readFile metaTemplate); - - toplevels = - settingsJson: - let - flake = import (builtins.toFile "meta-flake.nix" (filled settingsJson "unused")); - evaluated = flake.outputs { - self = null; - hyperhive = self; - }; - in - map (agent: evaluated.nixosConfigurations.${agent}.config.system.build.toplevel) agents; + inherit (import ./agent-toplevels.nix { inherit pkgs self agents; }) + hyperhiveRepo + metaTemplate + sourcePaths + toplevels + ; in pkgs.testers.runNixOSTest ( { config, ... }: @@ -132,17 +98,10 @@ pkgs.testers.runNixOSTest ( virtualisation.diskSize = 40960; virtualisation.writableStoreUseTmpfs = false; - # The toplevels, and every source tree the meta flake's lock names, keyed - # by narHash: nix takes a locked input from the store when its path is - # valid. - virtualisation.additionalPaths = [ - self - self.inputs.nixpkgs - self.inputs.crane - self.inputs.treefmt-nix - hyperhiveRepo - ] - ++ toplevels config.systemd.services.swarm-controller.environment.SWARM_CONTROLLER_META_FLAKE; + # The toplevels, and every source tree the meta flake's lock names. + virtualisation.additionalPaths = + sourcePaths + ++ toplevels config.systemd.services.swarm-controller.environment.SWARM_CONTROLLER_META_FLAKE; # No substituter, and no build. nix.settings = {