From a68f50fde396d5de818e7da9b9b2835c00de84a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 8 Apr 2025 17:45:44 +0200 Subject: [PATCH 1/3] bump disko to fix quoting issue --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 0c0f06174..ceca1d30f 100644 --- a/flake.lock +++ b/flake.lock @@ -36,11 +36,11 @@ ] }, "locked": { - "lastModified": 1744126564, - "narHash": "sha256-v1XPivS/Rvo9BBvF2Rh59HxUpucMsuOCGVrkIObF/bc=", + "lastModified": 1744135430, + "narHash": "sha256-1DGJ4w6Y2L1lV6V0UqecNNl0jK9eoIHqyZ2uLgrWxSw=", "owner": "nix-community", "repo": "disko", - "rev": "8f806681d781ca250ddaafd262d6b6c89d79d9ef", + "rev": "a8e75da08f462a2a4cc9a637643bda4eb1ea2d6c", "type": "github" }, "original": { From bbcc7f6e3b7d28b414d9ef76006a5411a87cc066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 8 Apr 2025 17:52:58 +0200 Subject: [PATCH 2/3] flash: test existing mount with spaces --- checks/flash/flake-module.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/checks/flash/flake-module.nix b/checks/flash/flake-module.nix index 47f528d80..ae5ebbfc4 100644 --- a/checks/flash/flake-module.nix +++ b/checks/flash/flake-module.nix @@ -36,7 +36,6 @@ perSystem = { - nodes, pkgs, lib, ... @@ -79,6 +78,8 @@ testScript = '' start_all() + # Some distros like to automount disks with spaces + machine.succeed('mkdir -p "/mnt/with spaces" && mkfs.ext4 /dev/vdb && mount /dev/vdb "/mnt/with spaces"') machine.succeed("clan flash write --debug --flake ${../..} --yes --disk main /dev/vdb test-flash-machine-${pkgs.hostPlatform.system}") ''; } { inherit pkgs self; }; From c61c1af18e5419e7b95f8c4c69bd9bd3ca9d934e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 8 Apr 2025 19:27:26 +0200 Subject: [PATCH 3/3] replace original installation test with installation-without-system --- checks/flake-module.nix | 1 - .../flake-module.nix | 243 ------------------ checks/installation/flake-module.nix | 90 ++++--- 3 files changed, 59 insertions(+), 275 deletions(-) delete mode 100644 checks/installation-without-system/flake-module.nix diff --git a/checks/flake-module.nix b/checks/flake-module.nix index 21e60ca2b..0ced0c78c 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -12,7 +12,6 @@ in ./flash/flake-module.nix ./impure/flake-module.nix ./installation/flake-module.nix - ./installation-without-system/flake-module.nix ./morph/flake-module.nix ./nixos-documentation/flake-module.nix ]; diff --git a/checks/installation-without-system/flake-module.nix b/checks/installation-without-system/flake-module.nix deleted file mode 100644 index d18a2a128..000000000 --- a/checks/installation-without-system/flake-module.nix +++ /dev/null @@ -1,243 +0,0 @@ -{ - self, - lib, - ... -}: -{ - # The purpose of this test is to ensure `clan machines install` works - # for machines that don't have a hardware config yet. - - # If this test starts failing it could be due to the `facter.json` being out of date - # you can get a new one by adding - # client.fail("cat test-flake/machines/test-install-machine/facter.json >&2") - # to the installation test. - clan.machines.test-install-machine-without-system = { - fileSystems."/".device = lib.mkDefault "/dev/vda"; - boot.loader.grub.device = lib.mkDefault "/dev/vda"; - - imports = [ self.nixosModules.test-install-machine-without-system ]; - }; - clan.machines.test-install-machine-with-system = - { pkgs, ... }: - { - # https://git.clan.lol/clan/test-fixtures - facter.reportPath = builtins.fetchurl { - url = "https://git.clan.lol/clan/test-fixtures/raw/commit/4a2bc56d886578124b05060d3fb7eddc38c019f8/nixos-vm-facter-json/${pkgs.hostPlatform.system}.json"; - sha256 = - { - aarch64-linux = "sha256:1rlfymk03rmfkm2qgrc8l5kj5i20srx79n1y1h4nzlpwaz0j7hh2"; - x86_64-linux = "sha256:16myh0ll2gdwsiwkjw5ba4dl23ppwbsanxx214863j7nvzx42pws"; - } - .${pkgs.hostPlatform.system}; - }; - - fileSystems."/".device = lib.mkDefault "/dev/vda"; - boot.loader.grub.device = lib.mkDefault "/dev/vda"; - - imports = [ self.nixosModules.test-install-machine-without-system ]; - }; - flake.nixosModules = { - test-install-machine-without-system = - { lib, modulesPath, ... }: - { - 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 - ]; - - networking.hostName = "test-install-machine"; - - environment.etc."install-successful".text = "ok"; - - boot.consoleLogLevel = lib.mkForce 100; - boot.kernelParams = [ "boot.shell_on_fail" ]; - - # disko config - boot.loader.grub.efiSupport = lib.mkDefault true; - boot.loader.grub.efiInstallAsRemovable = lib.mkDefault true; - clan.core.vars.settings.secretStore = "vm"; - clan.core.vars.generators.test = { - files.test.neededFor = "partitioning"; - script = '' - echo "notok" > $out/test - ''; - }; - disko.devices = { - disk = { - main = { - type = "disk"; - device = "/dev/vda"; - - preCreateHook = '' - test -e /run/partitioning-secrets/test/test - ''; - - content = { - type = "gpt"; - partitions = { - boot = { - size = "1M"; - type = "EF02"; # for grub MBR - priority = 1; - }; - ESP = { - size = "512M"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "umask=0077" ]; - }; - }; - root = { - size = "100%"; - content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; - }; - }; - }; - }; - }; - }; - }; - }; - }; - perSystem = - { - pkgs, - lib, - ... - }: - let - dependencies = [ - self - self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.toplevel - self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.diskoScript - self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.clan.deployment.file - pkgs.stdenv.drvPath - pkgs.bash.drvPath - pkgs.nixos-anywhere - pkgs.bubblewrap - ] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); - closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; - # with Nix 2.24 we get: - # vm-test-run-test-installation> client # error: sized: unexpected end-of-file - # vm-test-run-test-installation> client # error: unexpected end-of-file - # This seems to be fixed with Nix 2.26 - # Remove this line once `pkgs.nix` is 2.26+ - nixPackage = - assert - lib.versionOlder pkgs.nix.version "2.26" - && lib.versionAtLeast pkgs.nixVersions.latest.version "2.26"; - pkgs.nixVersions.latest; - in - { - # On aarch64-linux, hangs on reboot with after installation: - # vm-test-run-test-installation-without-system> installer # [ 288.002871] reboot: Restarting system - # vm-test-run-test-installation-without-system> client # [test-install-machine] ### Done! ### - # vm-test-run-test-installation-without-system> client # [test-install-machine] + step 'Done!' - # vm-test-run-test-installation-without-system> client # [test-install-machine] + echo '### Done! ###' - # vm-test-run-test-installation-without-system> client # [test-install-machine] + rm -rf /tmp/tmp.qb16EAq7hJ - # vm-test-run-test-installation-without-system> (finished: must succeed: clan machines install --debug --flake test-flake --yes test-install-machine-without-system --target-host root@installer --update-hardware-config nixos-facter >&2, in 154.62 seconds) - # vm-test-run-test-installation-without-system> target: starting vm - # vm-test-run-test-installation-without-system> target: QEMU running (pid 144) - # vm-test-run-test-installation-without-system> target: waiting for unit multi-user.target - # vm-test-run-test-installation-without-system> target: waiting for the VM to finish booting - # vm-test-run-test-installation-without-system> target: Guest root shell did not produce any data yet... - # vm-test-run-test-installation-without-system> target: To debug, enter the VM and run 'systemctl status backdoor.service'. - checks = pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) { - test-installation-without-system = (import ../lib/test-base.nix) { - name = "test-installation-without-system"; - nodes.target = { - services.openssh.enable = true; - virtualisation.diskImage = "./target.qcow2"; - virtualisation.useBootLoader = true; - nix.package = nixPackage; - }; - nodes.installer = - { modulesPath, ... }: - { - imports = [ - (modulesPath + "/../tests/common/auto-format-root-device.nix") - ]; - networking.useNetworkd = true; - services.openssh.enable = true; - system.nixos.variant_id = "installer"; - environment.systemPackages = [ pkgs.nixos-facter ]; - virtualisation.emptyDiskImages = [ 512 ]; - virtualisation.diskSize = 8 * 1024; - virtualisation.rootDevice = "/dev/vdb"; - # both installer and target need to use the same diskImage - virtualisation.diskImage = "./target.qcow2"; - nix.package = nixPackage; - nix.settings = { - substituters = lib.mkForce [ ]; - hashed-mirrors = null; - connect-timeout = lib.mkForce 3; - flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}''; - experimental-features = [ - "nix-command" - "flakes" - ]; - }; - users.users.nonrootuser = { - isNormalUser = true; - openssh.authorizedKeys.keyFiles = [ ../lib/ssh/pubkey ]; - extraGroups = [ "wheel" ]; - }; - security.sudo.wheelNeedsPassword = false; - system.extraDependencies = dependencies; - }; - nodes.client = { - networking.useNetworkd = true; - environment.systemPackages = [ - self.packages.${pkgs.system}.clan-cli - ] ++ self.packages.${pkgs.system}.clan-cli.runtimeDependencies; - environment.etc."install-closure".source = "${closureInfo}/store-paths"; - virtualisation.memorySize = 3048; - nix.package = nixPackage; - nix.settings = { - substituters = lib.mkForce [ ]; - hashed-mirrors = null; - connect-timeout = lib.mkForce 3; - flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}''; - experimental-features = [ - "nix-command" - "flakes" - ]; - }; - system.extraDependencies = dependencies; - }; - - testScript = '' - client.start() - installer.start() - - client.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../lib/ssh/privkey} /root/.ssh/id_ed25519") - client.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new -v nonrootuser@installer hostname") - client.succeed("cp -r ${../..} test-flake && chmod -R +w test-flake") - client.fail("test -f test-flake/machines/test-install-machine-without-system/hardware-configuration.nix") - client.fail("test -f test-flake/machines/test-install-machine-without-system/facter.json") - client.succeed("clan machines update-hardware-config --flake test-flake test-install-machine-without-system nonrootuser@installer >&2") - client.succeed("test -f test-flake/machines/test-install-machine-without-system/facter.json") - client.succeed("rm test-flake/machines/test-install-machine-without-system/facter.json") - client.succeed("clan machines install --debug --flake test-flake --yes test-install-machine-without-system --target-host nonrootuser@installer --update-hardware-config nixos-facter >&2") - try: - installer.shutdown() - except BrokenPipeError: - # qemu has already exited - pass - - target.state_dir = installer.state_dir - target.start() - target.wait_for_unit("multi-user.target") - assert(target.succeed("cat /etc/install-successful").strip() == "ok") - ''; - } { inherit pkgs self; }; - }; - }; -} diff --git a/checks/installation/flake-module.nix b/checks/installation/flake-module.nix index 167266876..5c81089ee 100644 --- a/checks/installation/flake-module.nix +++ b/checks/installation/flake-module.nix @@ -4,13 +4,38 @@ ... }: { + # The purpose of this test is to ensure `clan machines install` works + # for machines that don't have a hardware config yet. + + # If this test starts failing it could be due to the `facter.json` being out of date + # you can get a new one by adding + # client.fail("cat test-flake/machines/test-install-machine/facter.json >&2") + # to the installation test. clan.machines.test-install-machine = { - clan.core.networking.targetHost = "test-install-machine"; fileSystems."/".device = lib.mkDefault "/dev/vda"; boot.loader.grub.device = lib.mkDefault "/dev/vda"; imports = [ self.nixosModules.test-install-machine ]; }; + clan.machines.test-install-machine-with-system = + { pkgs, ... }: + { + # https://git.clan.lol/clan/test-fixtures + facter.reportPath = builtins.fetchurl { + url = "https://git.clan.lol/clan/test-fixtures/raw/commit/4a2bc56d886578124b05060d3fb7eddc38c019f8/nixos-vm-facter-json/${pkgs.hostPlatform.system}.json"; + sha256 = + { + aarch64-linux = "sha256:1rlfymk03rmfkm2qgrc8l5kj5i20srx79n1y1h4nzlpwaz0j7hh2"; + x86_64-linux = "sha256:16myh0ll2gdwsiwkjw5ba4dl23ppwbsanxx214863j7nvzx42pws"; + } + .${pkgs.hostPlatform.system}; + }; + + fileSystems."/".device = lib.mkDefault "/dev/vda"; + boot.loader.grub.device = lib.mkDefault "/dev/vda"; + + imports = [ self.nixosModules.test-install-machine ]; + }; flake.nixosModules = { test-install-machine = { lib, modulesPath, ... }: @@ -20,11 +45,11 @@ (modulesPath + "/profiles/qemu-guest.nix") ../lib/minify.nix ]; - networking.useNetworkd = true; + + networking.hostName = "test-install-machine"; environment.etc."install-successful".text = "ok"; - nixpkgs.hostPlatform = "x86_64-linux"; boot.consoleLogLevel = lib.mkForce 100; boot.kernelParams = [ "boot.shell_on_fail" ]; @@ -90,16 +115,15 @@ let dependencies = [ self - self.nixosConfigurations.test-install-machine.config.system.build.toplevel - self.nixosConfigurations.test-install-machine.config.system.build.diskoScript - self.nixosConfigurations.test-install-machine.config.system.clan.deployment.file - pkgs.bash.drvPath + self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.toplevel + self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.diskoScript + self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.clan.deployment.file pkgs.stdenv.drvPath + pkgs.bash.drvPath pkgs.nixos-anywhere pkgs.bubblewrap ] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; - # with Nix 2.24 we get: # vm-test-run-test-installation> client # error: sized: unexpected end-of-file # vm-test-run-test-installation> client # error: unexpected end-of-file @@ -113,14 +137,18 @@ in { # On aarch64-linux, hangs on reboot with after installation: - # vm-test-run-test-installation> (finished: waiting for the VM to power off, in 1.97 seconds) - # vm-test-run-test-installation> - # vm-test-run-test-installation> new_machine: must succeed: cat /etc/install-successful - # vm-test-run-test-installation> new_machine: waiting for the VM to finish booting - # vm-test-run-test-installation> new_machine: starting vm - # vm-test-run-test-installation> new_machine: QEMU running (pid 80) - # vm-test-run-test-installation> new_machine: Guest root shell did not produce any data yet... - # vm-test-run-test-installation> new_machine: To debug, enter the VM and run 'systemctl status backdoor.service'. + # vm-test-run-test-installation-> installer # [ 288.002871] reboot: Restarting system + # vm-test-run-test-installation-> client # [test-install-machine] ### Done! ### + # vm-test-run-test-installation-> client # [test-install-machine] + step 'Done!' + # vm-test-run-test-installation-> client # [test-install-machine] + echo '### Done! ###' + # vm-test-run-test-installation-> client # [test-install-machine] + rm -rf /tmp/tmp.qb16EAq7hJ + # vm-test-run-test-installation-> (finished: must succeed: clan machines install --debug --flake test-flake --yes test-install-machine --target-host root@installer --update-hardware-config nixos-facter >&2, in 154.62 seconds) + # vm-test-run-test-installation-> target: starting vm + # vm-test-run-test-installation-> target: QEMU running (pid 144) + # vm-test-run-test-installation-> target: waiting for unit multi-user.target + # vm-test-run-test-installation-> target: waiting for the VM to finish booting + # vm-test-run-test-installation-> target: Guest root shell did not produce any data yet... + # vm-test-run-test-installation-> target: To debug, enter the VM and run 'systemctl status backdoor.service'. checks = pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) { test-installation = (import ../lib/test-base.nix) { name = "test-installation"; @@ -129,11 +157,6 @@ virtualisation.diskImage = "./target.qcow2"; virtualisation.useBootLoader = true; nix.package = nixPackage; - - # virtualisation.fileSystems."/" = { - # device = "/dev/disk/by-label/this-is-not-real-and-will-never-be-used"; - # fsType = "ext4"; - # }; }; nodes.installer = { modulesPath, ... }: @@ -143,7 +166,6 @@ ]; networking.useNetworkd = true; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keyFiles = [ ../lib/ssh/pubkey ]; system.nixos.variant_id = "installer"; environment.systemPackages = [ pkgs.nixos-facter ]; virtualisation.emptyDiskImages = [ 512 ]; @@ -162,6 +184,12 @@ "flakes" ]; }; + users.users.nonrootuser = { + isNormalUser = true; + openssh.authorizedKeys.keyFiles = [ ../lib/ssh/pubkey ]; + extraGroups = [ "wheel" ]; + }; + security.sudo.wheelNeedsPassword = false; system.extraDependencies = dependencies; }; nodes.client = { @@ -190,21 +218,21 @@ installer.start() client.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../lib/ssh/privkey} /root/.ssh/id_ed25519") - client.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new -v root@installer hostname") + client.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new -v nonrootuser@installer hostname") client.succeed("cp -r ${../..} test-flake && chmod -R +w test-flake") - - # test that we can generate hardware configurations - client.fail("test -f test-flake/machines/test-install-machine/facter.json") client.fail("test -f test-flake/machines/test-install-machine/hardware-configuration.nix") - client.succeed("clan machines update-hardware-config --flake test-flake test-install-machine root@installer >&2") + client.fail("test -f test-flake/machines/test-install-machine/facter.json") + + client.succeed("clan machines update-hardware-config --flake test-flake test-install-machine nonrootuser@installer >&2") client.succeed("test -f test-flake/machines/test-install-machine/facter.json") - client.succeed("clan machines update-hardware-config --backend nixos-generate-config --flake test-flake test-install-machine root@installer>&2") + client.succeed("rm test-flake/machines/test-install-machine/facter.json") + + client.succeed("clan machines update-hardware-config --backend nixos-generate-config --flake test-flake test-install-machine nonrootuser@installer>&2") client.succeed("test -f test-flake/machines/test-install-machine/hardware-configuration.nix") + client.succeed("rm test-flake/machines/test-install-machine/hardware-configuration.nix") - # but we don't use them because they're not cached - client.succeed("rm test-flake/machines/test-install-machine/hardware-configuration.nix test-flake/machines/test-install-machine/facter.json") + client.succeed("clan machines install --debug --flake test-flake --yes test-install-machine --target-host nonrootuser@installer --update-hardware-config nixos-facter >&2") - client.succeed("clan machines install --debug --flake test-flake --yes test-install-machine --target-host root@installer >&2") try: installer.shutdown() except BrokenPipeError: