aboutsummaryrefslogtreecommitdiff
path: root/tests/nixos/remote-builds.nix
diff options
context:
space:
mode:
Diffstat (limited to 'tests/nixos/remote-builds.nix')
-rw-r--r--tests/nixos/remote-builds.nix106
1 files changed, 106 insertions, 0 deletions
diff --git a/tests/nixos/remote-builds.nix b/tests/nixos/remote-builds.nix
new file mode 100644
index 000000000..696cd2652
--- /dev/null
+++ b/tests/nixos/remote-builds.nix
@@ -0,0 +1,106 @@
+# Test Nix's remote build feature.
+
+{ config, lib, hostPkgs, ... }:
+
+let
+ pkgs = config.nodes.client.nixpkgs.pkgs;
+
+ # The configuration of the remote builders.
+ builder =
+ { config, pkgs, ... }:
+ { services.openssh.enable = true;
+ virtualisation.writableStore = true;
+ nix.settings.sandbox = true;
+ };
+
+ # Trivial Nix expression to build remotely.
+ expr = config: nr: pkgs.writeText "expr.nix"
+ ''
+ let utils = builtins.storePath ${config.system.build.extraUtils}; in
+ derivation {
+ name = "hello-${toString nr}";
+ system = "i686-linux";
+ PATH = "''${utils}/bin";
+ builder = "''${utils}/bin/sh";
+ args = [ "-c" "if [ ${toString nr} = 5 ]; then echo FAIL; exit 1; fi; echo Hello; mkdir $out $foo; cat /proc/sys/kernel/hostname > $out/host; ln -s $out $foo/bar; sleep 10" ];
+ outputs = [ "out" "foo" ];
+ }
+ '';
+
+in
+
+{
+ name = "remote-builds";
+
+ nodes =
+ { builder1 = builder;
+ builder2 = builder;
+
+ client =
+ { config, lib, pkgs, ... }:
+ { nix.settings.max-jobs = 0; # force remote building
+ nix.distributedBuilds = true;
+ nix.buildMachines =
+ [ { hostName = "builder1";
+ sshUser = "root";
+ sshKey = "/root/.ssh/id_ed25519";
+ system = "i686-linux";
+ maxJobs = 1;
+ }
+ { hostName = "builder2";
+ sshUser = "root";
+ sshKey = "/root/.ssh/id_ed25519";
+ system = "i686-linux";
+ maxJobs = 1;
+ }
+ ];
+ virtualisation.writableStore = true;
+ virtualisation.additionalPaths = [ config.system.build.extraUtils ];
+ nix.settings.substituters = lib.mkForce [ ];
+ programs.ssh.extraConfig = "ConnectTimeout 30";
+ };
+ };
+
+ testScript = { nodes }: ''
+ # fmt: off
+ import subprocess
+
+ start_all()
+
+ # Create an SSH key on the client.
+ subprocess.run([
+ "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", ""
+ ], capture_output=True, check=True)
+ client.succeed("mkdir -p -m 700 /root/.ssh")
+ client.copy_from_host("key", "/root/.ssh/id_ed25519")
+ client.succeed("chmod 600 /root/.ssh/id_ed25519")
+
+ # Install the SSH key on the builders.
+ client.wait_for_unit("network.target")
+ for builder in [builder1, builder2]:
+ builder.succeed("mkdir -p -m 700 /root/.ssh")
+ builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
+ builder.wait_for_unit("sshd")
+ client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'")
+
+ # Perform a build and check that it was performed on the builder.
+ out = client.succeed(
+ "nix-build ${expr nodes.client.config 1} 2> build-output",
+ "grep -q Hello build-output"
+ )
+ builder1.succeed(f"test -e {out}")
+
+ # And a parallel build.
+ paths = client.succeed(r'nix-store -r $(nix-instantiate ${expr nodes.client.config 2})\!out $(nix-instantiate ${expr nodes.client.config 3})\!out')
+ out1, out2 = paths.split()
+ builder1.succeed(f"test -e {out1} -o -e {out2}")
+ builder2.succeed(f"test -e {out1} -o -e {out2}")
+
+ # And a failing build.
+ client.fail("nix-build ${expr nodes.client.config 5}")
+
+ # Test whether the build hook automatically skips unavailable builders.
+ builder1.block()
+ client.succeed("nix-build ${expr nodes.client.config 4}")
+ '';
+}