693e21b1a8
for now, had to get rid of vmVariant. we can figure out how to add it back when we understand how we should actually distinguish between real machines and VMs
150 lines
4.5 KiB
Nix
150 lines
4.5 KiB
Nix
pkgs: test:
|
|
let
|
|
inherit (pkgs.lib) mapAttrsToList concatStringsSep genAttrs mkIf;
|
|
inherit (builtins) attrNames;
|
|
|
|
interactiveConfig = ({ config, ... }: {
|
|
# so we can run `nix shell nixpkgs#foo` on the machines
|
|
nix.extraOptions = ''
|
|
extra-experimental-features = nix-command flakes
|
|
'';
|
|
|
|
# so we can ssh in and rebuild them
|
|
services.openssh = {
|
|
enable = true;
|
|
settings = {
|
|
PermitRootLogin = "yes";
|
|
PermitEmptyPasswords = "yes";
|
|
UsePAM = "no";
|
|
};
|
|
};
|
|
|
|
virtualisation = mkIf (config.networking.hostName == "jumphost") {
|
|
forwardPorts = [{
|
|
from = "host";
|
|
host.port = 2222;
|
|
guest.port = 22;
|
|
}];
|
|
};
|
|
});
|
|
|
|
sshConfig = pkgs.writeText "ssh-config" ''
|
|
Host *
|
|
User root
|
|
StrictHostKeyChecking no
|
|
BatchMode yes
|
|
ConnectTimeout 20
|
|
UserKnownHostsFile=/dev/null
|
|
LogLevel Error # no "added to known hosts"
|
|
Host jumphost
|
|
Port 2222
|
|
HostName localhost
|
|
Host * !jumphost
|
|
ProxyJump jumphost
|
|
'';
|
|
|
|
# one should first start up the interactive test driver, then start the
|
|
# machines, then update the config, and then redeploy with the `rebuildScript`
|
|
# associated with the new config.
|
|
rebuildScript = pkgs.writeShellScriptBin "rebuild" ''
|
|
# create an association array from machine names to the path to their
|
|
# configuration in the nix store
|
|
declare -A configPaths=(${
|
|
concatStringsSep " "
|
|
(mapAttrsToList
|
|
(n: v: ''["${n}"]="${v.system.build.toplevel}"'')
|
|
rebuildableTest.driverInteractive.nodes)
|
|
})
|
|
|
|
rebuild_one() {
|
|
machine="$1"
|
|
echo "pushing new config to $machine"
|
|
|
|
if [ -z ''${configPaths[$machine]+x} ]; then
|
|
echo 'No machine '"$machine"' in this test.'
|
|
exit 1
|
|
fi
|
|
|
|
if ! ssh -F ${sshConfig} $machine true; then
|
|
echo 'Couldn'"'"'t connect to '"$machine"'. Make sure you'"'"'ve started it with `'"$machine"'.start()` in the test interactive driver.'
|
|
exit 1
|
|
fi
|
|
|
|
# taken from nixos-rebuild (we only want to do the activate part)
|
|
cmd=(
|
|
"systemd-run"
|
|
"-E" "LOCALE_ARCHIVE"
|
|
"--collect"
|
|
"--no-ask-password"
|
|
"--pty"
|
|
"--quiet"
|
|
"--same-dir"
|
|
"--service-type=exec"
|
|
"--unit=nixos-rebuild-switch-to-configuration"
|
|
"--wait"
|
|
"''${configPaths[$machine]}/bin/switch-to-configuration"
|
|
"test"
|
|
)
|
|
|
|
|
|
if ! ssh -F ${sshConfig} $machine "''${cmd[@]}"; then
|
|
echo "warning: error(s) occurred while switching to the new configuration"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
if ! ssh -F ${sshConfig} jumphost true; then
|
|
echo 'Couldn'"'"'t connect to jump host. Make sure you are running driverInteractive, and that you'"'"'ve run `jumphost.start()` and `jumphost.forward_port(2222,22)`'
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$1" ]; then
|
|
rebuild_one "$1"
|
|
else
|
|
for machine in ${concatStringsSep " " (attrNames rebuildableTest.driverInteractive.nodes)}; do
|
|
rebuild_one $machine
|
|
done
|
|
fi
|
|
'';
|
|
|
|
# NOTE: This is awkward because NixOS does not expose the module interface
|
|
# that is used to build tests. When we upstream this, we can build it into the
|
|
# system more naturally (and expose more of the interface to end users while
|
|
# we're at it)
|
|
rebuildableTest =
|
|
let
|
|
preOverride = pkgs.nixosTest (test // {
|
|
interactive = (test.interactive or { }) // {
|
|
# no need to // with test.interactive.nodes here, since we are iterating
|
|
# over all of them, and adding back in the config via `imports`
|
|
nodes = genAttrs
|
|
(
|
|
attrNames test.nodes or { } ++
|
|
attrNames test.interactive.nodes or { } ++
|
|
[ "jumphost" ]
|
|
)
|
|
(n: {
|
|
imports = [
|
|
(test.interactive.${n} or { })
|
|
interactiveConfig
|
|
];
|
|
});
|
|
};
|
|
# override with test.passthru in case someone wants to overwrite us.
|
|
passthru = { inherit rebuildScript sshConfig; } // (test.passthru or { });
|
|
});
|
|
in
|
|
preOverride // {
|
|
driverInteractive = preOverride.driverInteractive.overrideAttrs (old: {
|
|
# this comes from runCommand, not mkDerivation, so this is the only
|
|
# hook we have to override
|
|
buildCommand = old.buildCommand + ''
|
|
ln -s ${sshConfig} $out/ssh-config
|
|
ln -s ${rebuildScript}/bin/rebuild $out/bin/rebuild
|
|
'';
|
|
});
|
|
};
|
|
in
|
|
rebuildableTest
|
|
|