A hermetic remote rebuild is when Nixinate sends a specific Nix binary to the remote first, then uses it when activating a system closure, rather than using the Nix that is already on the remote. This is defaulted to false for the time being, as the bandwidth usage can be high. This allows users to avoid the need to bootstrap the remote first by enabling flakes on the remote Nix binary.
114 lines
4.3 KiB
Nix
114 lines
4.3 KiB
Nix
{ pkgs, makeTest, inputs }:
|
|
let
|
|
inherit (pkgs) lib;
|
|
# Return a store path with a closure containing everything including
|
|
# derivations and all build dependency outputs, all the way down.
|
|
allDrvOutputs = pkg:
|
|
let name = "allDrvOutputs-${pkg.pname or pkg.name or "unknown"}";
|
|
in
|
|
pkgs.runCommand name { refs = pkgs.writeReferencesToFile pkg.drvPath; } ''
|
|
touch $out
|
|
while read ref; do
|
|
case $ref in
|
|
*.drv)
|
|
cat $ref >>$out
|
|
;;
|
|
esac
|
|
done <$refs
|
|
'';
|
|
# Imports a flake with inputs passed in by hand, rather than
|
|
# builtins.getFlake, which cannot be used in this way.
|
|
callLocklessFlake = path: inputs: let
|
|
r = {outPath = path;} //
|
|
((import (path + "/flake.nix")).outputs (inputs // {self = r;}));
|
|
in
|
|
r;
|
|
mkNixinateTest = { buildOn, hermetic ? false, ... }:
|
|
let
|
|
exampleFlake = pkgs.writeTextFile {
|
|
name = "nixinate-example-flake";
|
|
destination = "/flake.nix";
|
|
text = ''
|
|
{
|
|
outputs = { self, nixpkgs }:
|
|
let
|
|
makeTest = (import (nixpkgs + "/nixos/lib/testing-python.nix") { system = "${pkgs.hostPlatform.system}"; }).makeTest;
|
|
baseConfig = ((makeTest { nodes.baseConfig = { ... }: {}; testScript = "";}).nodes).baseConfig.extendModules {
|
|
modules = [
|
|
${builtins.readFile ./nixinateeBase.nix}
|
|
${builtins.readFile ./nixinateeAdditional.nix}
|
|
{
|
|
_module.args.nixinate = {
|
|
host = "nixinatee";
|
|
sshUser = "nixinator";
|
|
buildOn = "${buildOn}"; # valid args are "local" or "remote"
|
|
hermetic = ${lib.boolToString hermetic}; # valid args are true or false
|
|
};
|
|
}
|
|
];
|
|
};
|
|
in
|
|
{
|
|
nixosConfigurations = {
|
|
nixinatee = baseConfig;
|
|
};
|
|
};
|
|
}
|
|
'';
|
|
};
|
|
deployScript = inputs.self.nixinate.${pkgs.hostPlatform.system} (callLocklessFlake "${exampleFlake}" { nixpkgs = inputs.nixpkgs; });
|
|
exampleSystem = (callLocklessFlake "${exampleFlake}" { nixpkgs = inputs.nixpkgs; }).nixosConfigurations.nixinatee.config.system.build.toplevel;
|
|
in
|
|
makeTest {
|
|
nodes = {
|
|
nixinatee = { ... }: {
|
|
imports = [
|
|
./nixinateeBase.nix
|
|
(import ./common.nix { inherit inputs; })
|
|
];
|
|
virtualisation = {
|
|
writableStore = true;
|
|
additionalPaths = []
|
|
++ lib.optional (buildOn == "remote") (allDrvOutputs exampleSystem)
|
|
++ lib.optional (hermetic == true) (pkgs.nixinate.nixos-rebuild);
|
|
};
|
|
};
|
|
nixinator = { ... }: {
|
|
imports = [
|
|
(import ./common.nix { inherit inputs; })
|
|
];
|
|
virtualisation = {
|
|
additionalPaths = [
|
|
(allDrvOutputs exampleSystem)
|
|
]
|
|
++ lib.optional (buildOn == "remote") exampleFlake;
|
|
};
|
|
};
|
|
};
|
|
testScript =
|
|
''
|
|
start_all()
|
|
nixinatee.wait_for_unit("sshd.service")
|
|
nixinator.wait_for_unit("multi-user.target")
|
|
nixinator.succeed("mkdir ~/.ssh/")
|
|
nixinator.succeed("ssh-keyscan -H nixinatee >> ~/.ssh/known_hosts")
|
|
nixinator.succeed("exec ${deployScript.nixinate.nixinatee.program} >&2")
|
|
nixinatee.wait_for_unit("nginx.service")
|
|
nixinatee.wait_for_open_port("80")
|
|
with subtest("Check that Nginx webserver can be reached by deployer after deployment"):
|
|
assert "<title>Welcome to nginx!</title>" in nixinator.succeed(
|
|
"curl -sSf http:/nixinatee/ | grep title"
|
|
)
|
|
with subtest("Check that Nginx webserver can be reached by deployee after deployment"):
|
|
assert "<title>Welcome to nginx!</title>" in nixinatee.succeed(
|
|
"curl -sSf http:/127.0.0.1/ | grep title"
|
|
)
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
local = (mkNixinateTest { buildOn = "local"; });
|
|
remote = (mkNixinateTest { buildOn = "remote"; });
|
|
localHermetic = (mkNixinateTest { buildOn = "local"; hermetic = true; });
|
|
remoteHermetic = (mkNixinateTest { buildOn = "remote"; hermetic = true; });
|
|
}
|