diff --git a/checks/data-mesher/default.nix b/checks/data-mesher/default.nix index 029b2277d..653cc266a 100644 --- a/checks/data-mesher/default.nix +++ b/checks/data-mesher/default.nix @@ -1,78 +1,86 @@ -(import ../lib/test-inventory.nix) ( - { lib, ... }: - let +{ + pkgs, + self, + clanLib, + ... +}: +clanLib.test.makeTestClan { + inherit pkgs self; + nixosTest = ( + { lib, ... }: + let + machines = [ + "admin" + "peer" + "signer" + ]; + in + { + name = "data-mesher"; - machines = [ - "admin" - "peer" - "signer" - ]; - in - { - name = "data-mesher"; - - clan = { - directory = ./.; - inventory = { - machines = lib.genAttrs machines (_: { }); - services = { - data-mesher.default = { - roles.peer.machines = [ "peer" ]; - roles.admin.machines = [ "admin" ]; - roles.signer.machines = [ "signer" ]; + clan = { + directory = ./.; + inventory = { + machines = lib.genAttrs machines (_: { }); + services = { + data-mesher.default = { + roles.peer.machines = [ "peer" ]; + roles.admin.machines = [ "admin" ]; + roles.signer.machines = [ "signer" ]; + }; }; }; }; - }; - defaults = - { config, ... }: - { - environment.systemPackages = [ - config.services.data-mesher.package - ]; + defaults = + { config, ... }: + { + environment.systemPackages = [ + config.services.data-mesher.package + ]; - clan.data-mesher.network.interface = "eth1"; - clan.data-mesher.bootstrapNodes = [ - "[2001:db8:1::1]:7946" # peer1 - "[2001:db8:1::2]:7946" # peer2 - ]; + clan.data-mesher.network.interface = "eth1"; + clan.data-mesher.bootstrapNodes = [ + "[2001:db8:1::1]:7946" # peer1 + "[2001:db8:1::2]:7946" # peer2 + ]; - # speed up for testing - services.data-mesher.settings = { - cluster.join_interval = lib.mkForce "2s"; - cluster.push_pull_interval = lib.mkForce "5s"; + # speed up for testing + services.data-mesher.settings = { + cluster.join_interval = lib.mkForce "2s"; + cluster.push_pull_interval = lib.mkForce "5s"; + }; }; + + nodes = { + admin.clan.data-mesher.network.tld = "foo"; }; - nodes = { - admin.clan.data-mesher.network.tld = "foo"; - }; + # TODO Add better test script. + testScript = '' - # TODO Add better test script. - testScript = '' + def resolve(node, success = {}, fail = [], timeout = 60): + for hostname, ips in success.items(): + for ip in ips: + node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout) - def resolve(node, success = {}, fail = [], timeout = 60): - for hostname, ips in success.items(): - for ip in ips: - node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout) + for hostname in fail: + node.wait_until_fails(f"getent ahosts {hostname}") - for hostname in fail: - node.wait_until_fails(f"getent ahosts {hostname}") + start_all() - start_all() + admin.wait_for_unit("data-mesher") + signer.wait_for_unit("data-mesher") + peer.wait_for_unit("data-mesher") - admin.wait_for_unit("data-mesher") - signer.wait_for_unit("data-mesher") - peer.wait_for_unit("data-mesher") - - # check dns resolution - for node in [admin, signer, peer]: - resolve(node, { - "admin.foo": ["2001:db8:1::1", "192.168.1.1"], - "peer.foo": ["2001:db8:1::2", "192.168.1.2"], - "signer.foo": ["2001:db8:1::3", "192.168.1.3"] - }) - ''; - } -) + # check dns resolution + for node in [admin, signer, peer]: + resolve(node, { + "admin.foo": ["2001:db8:1::1", "192.168.1.1"], + "peer.foo": ["2001:db8:1::2", "192.168.1.2"], + "signer.foo": ["2001:db8:1::3", "192.168.1.3"] + }) + ''; + } + ); +} diff --git a/checks/dummy-inventory-test/default.nix b/checks/dummy-inventory-test/default.nix index bafac94e9..46e42ecec 100644 --- a/checks/dummy-inventory-test/default.nix +++ b/checks/dummy-inventory-test/default.nix @@ -1,67 +1,76 @@ -(import ../lib/test-inventory.nix) ( - { ... }: - { - # This tests the compatibility of the inventory - # With the test framework - # - legacy-modules - # - clan.service modules - name = "dummy-inventory-test"; +{ + pkgs, + self, + clanLib, + ... +}: +clanLib.test.makeTestClan { + inherit pkgs self; + nixosTest = ( + { ... }: + { + # This tests the compatibility of the inventory + # With the test framework + # - legacy-modules + # - clan.service modules + name = "dummy-inventory-test"; - clan = { - directory = ./.; - inventory = { - machines.peer1 = { }; - machines.admin1 = { }; - services = { - legacy-module.default = { - roles.peer.machines = [ "peer1" ]; - roles.admin.machines = [ "admin1" ]; + clan = { + directory = ./.; + inventory = { + machines.peer1 = { }; + machines.admin1 = { }; + services = { + legacy-module.default = { + roles.peer.machines = [ "peer1" ]; + roles.admin.machines = [ "admin1" ]; + }; + }; + instances."test" = { + module.name = "new-service"; + roles.peer.machines.peer1 = { }; }; - }; - instances."test" = { - module.name = "new-service"; - roles.peer.machines.peer1 = { }; - }; - modules = { - legacy-module = ./legacy-module; - new-service = { - _class = "clan.service"; - manifest.name = "new-service"; - roles.peer = { }; - perMachine = { - nixosModule = { - # This should be generated by: - # ./pkgs/scripts/update-vars.py inventory-test-framework-compatibility-test - clan.core.vars.generators.new-service = { - files.hello = { - secret = false; - deploy = true; + modules = { + legacy-module = ./legacy-module; + new-service = { + _class = "clan.service"; + manifest.name = "new-service"; + roles.peer = { }; + perMachine = { + nixosModule = { + # This should be generated by: + # ./pkgs/scripts/update-vars.py inventory-test-framework-compatibility-test + clan.core.vars.generators.new-service = { + files.hello = { + secret = false; + deploy = true; + }; + script = '' + # This is a dummy script that does nothing + echo "This is a dummy script" > $out/hello + ''; }; - script = '' - # This is a dummy script that does nothing - echo "This is a dummy script" > $out/hello - ''; }; }; }; }; }; }; - }; - testScript = - { nodes, ... }: - '' - start_all() - admin1.wait_for_unit("multi-user.target") - peer1.wait_for_unit("multi-user.target") - # Provided by the legacy module - print(admin1.succeed("systemctl status dummy-service")) - print(peer1.succeed("systemctl status dummy-service")) + testScript = + { nodes, ... }: + '' + start_all() + admin1.wait_for_unit("multi-user.target") + peer1.wait_for_unit("multi-user.target") + # Provided by the legacy module + print(admin1.succeed("systemctl status dummy-service")) + print(peer1.succeed("systemctl status dummy-service")) - # peer1 should have the 'hello' file - peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.hello.path}") - ''; - } -) + # peer1 should have the 'hello' file + peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.hello.path}") + ''; + } + ); +} diff --git a/checks/flake-module.nix b/checks/flake-module.nix index 0ced0c78c..2e7526864 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -27,9 +27,10 @@ in let nixosTestArgs = { # reference to nixpkgs for the current system - inherit pkgs; + inherit pkgs lib; # this gives us a reference to our flake but also all flake inputs inherit self; + inherit (self) clanLib; }; nixosTests = lib.optionalAttrs (pkgs.stdenv.isLinux) { # import our test diff --git a/checks/installation/flake-module.nix b/checks/installation/flake-module.nix index 35632bb02..30c909769 100644 --- a/checks/installation/flake-module.nix +++ b/checks/installation/flake-module.nix @@ -99,7 +99,7 @@ in imports = [ (modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests (modulesPath + "/profiles/qemu-guest.nix") - ../lib/minify.nix + self.clanLib.test.minifyModule ]; networking.hostName = "test-install-machine"; diff --git a/checks/lib/container-test.nix b/checks/lib/container-test.nix index 31ba285a5..b0d1935ba 100644 --- a/checks/lib/container-test.nix +++ b/checks/lib/container-test.nix @@ -13,7 +13,7 @@ in { config, options, ... }: { imports = [ - ./minify.nix + self.clanLib.test.minifyModule ]; config = lib.mkMerge [ (lib.optionalAttrs (options ? clan) { diff --git a/checks/lib/test-base.nix b/checks/lib/test-base.nix index 7c37ee51a..72fcc8826 100644 --- a/checks/lib/test-base.nix +++ b/checks/lib/test-base.nix @@ -11,7 +11,7 @@ in { config, options, ... }: { imports = [ - ./minify.nix + self.clanLib.test.minifyModule ]; config = lib.mkMerge [ (lib.optionalAttrs (options ? clan) { diff --git a/checks/lib/test-inventory.nix b/checks/lib/test-inventory.nix deleted file mode 100644 index 60939c13f..000000000 --- a/checks/lib/test-inventory.nix +++ /dev/null @@ -1,89 +0,0 @@ -test: -{ pkgs, self, ... }: -let - inherit (pkgs) lib; - inherit (lib) - mkOption - flip - mapAttrs - types - ; - nixos-lib = import (pkgs.path + "/nixos/lib") { }; -in -(nixos-lib.runTest ( - { config, ... }: - let - clanFlakeResult = config.clan; - in - { - imports = [ test ]; - options = { - clanSettings = mkOption { - default = { }; - type = types.submodule { - options = { - clan-core = mkOption { default = self; }; - nixpkgs = mkOption { default = self.inputs.nixpkgs; }; - nix-darwin = mkOption { default = self.inputs.nix-darwin; }; - }; - }; - }; - - clan = mkOption { - default = { }; - type = types.submoduleWith { - specialArgs = { - inherit (config.clanSettings) - clan-core - nixpkgs - nix-darwin - ; - }; - modules = [ - self.clanLib.buildClanModule.flakePartsModule - ]; - }; - }; - }; - config = { - nodes = flip mapAttrs clanFlakeResult.clanInternals.inventoryClass.machines ( - machineName: attrs: { - imports = attrs.machineImports ++ [ self.nixosModules.clanCore ]; - clan.core.settings.directory = "${config.clan.directory}"; - clan.core.settings.machine.name = machineName; - } - ); - hostPkgs = pkgs; - # speed-up evaluation - defaults = ( - { config, ... }: - { - imports = [ - ./minify.nix - ]; - documentation.enable = lib.mkDefault false; - nix.settings.min-free = 0; - system.stateVersion = config.system.nixos.release; - boot.initrd.systemd.enable = false; - - # setup for sops - sops.age.keyFile = "/run/age-key.txt"; - system.activationScripts = - { - setupSecrets.deps = [ "age-key" ]; - age-key.text = '' - echo AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV > /run/age-key.txt - ''; - } - // lib.optionalAttrs (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets != { }) { - setupSecretsForUsers.deps = [ "age-key" ]; - }; - } - ); - - _module.args = { inherit self; }; - # to accept external dependencies such as disko - node.specialArgs.self = self; - }; - } -)).config.result diff --git a/lib/default.nix b/lib/default.nix index f6b038528..9e852e89e 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -25,6 +25,7 @@ lib.fix (clanLib: { buildClanModule = clanLib.callLib ./build-clan { }; inventory = clanLib.callLib ./inventory { }; modules = clanLib.callLib ./inventory/frontmatter { }; + test = clanLib.callLib ./tests { }; # Plain imports. values = import ./introspection { inherit lib; }; diff --git a/lib/tests/default.nix b/lib/tests/default.nix new file mode 100644 index 000000000..d048c9ed1 --- /dev/null +++ b/lib/tests/default.nix @@ -0,0 +1,92 @@ +{ lib, clanLib }: +let + inherit (lib) + mkOption + types + ; +in +{ + minifyModule = ./minify.nix; + # A function that returns an extension to runTest + makeTestClan = + { + nixosTest, + pkgs, + self, + ... + }: + let + nixos-lib = import (pkgs.path + "/nixos/lib") { }; + in + (nixos-lib.runTest ( + { config, ... }: + let + clanFlakeResult = config.clan; + in + { + imports = [ nixosTest ]; + options = { + clanSettings = mkOption { + default = { }; + type = types.submodule { + options = { + clan-core = mkOption { default = self; }; + nixpkgs = mkOption { default = self.inputs.nixpkgs; }; + nix-darwin = mkOption { default = self.inputs.nix-darwin; }; + }; + }; + }; + + clan = mkOption { + default = { }; + type = types.submoduleWith { + specialArgs = { + inherit (config.clanSettings) + clan-core + nixpkgs + nix-darwin + ; + }; + modules = [ + clanLib.buildClanModule.flakePartsModule + ]; + }; + }; + }; + config = { + nodes = clanFlakeResult.clanInternals.nixosModules; + hostPkgs = pkgs; + # speed-up evaluation + defaults = ( + { config, ... }: + { + imports = [ + clanLib.test.minifyModule + ]; + documentation.enable = lib.mkDefault false; + nix.settings.min-free = 0; + system.stateVersion = config.system.nixos.release; + boot.initrd.systemd.enable = false; + + # setup for sops + sops.age.keyFile = "/run/age-key.txt"; + system.activationScripts = + { + setupSecrets.deps = [ "age-key" ]; + age-key.text = '' + echo AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV > /run/age-key.txt + ''; + } + // lib.optionalAttrs (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets != { }) { + setupSecretsForUsers.deps = [ "age-key" ]; + }; + } + ); + + # to accept external dependencies such as disko + _module.args = { inherit self; }; + node.specialArgs.self = self; + }; + } + )).config.result; +} diff --git a/checks/lib/minify.nix b/lib/tests/minify.nix similarity index 62% rename from checks/lib/minify.nix rename to lib/tests/minify.nix index 9b1c3e70e..411bf687d 100644 --- a/checks/lib/minify.nix +++ b/lib/tests/minify.nix @@ -1,3 +1,6 @@ +# This is a module to reduce the size of the NixOS configuration +# Used by the tests +# It unsets some unnecessary options { lib, ... }: { nixpkgs.flake.setFlakeRegistry = false;