integration-tests: Start migration to modular test framework
Still need to migrate most logic in tools.nix to modules.
This commit is contained in:
parent
92f0f155d4
commit
8b87f0de02
8 changed files with 280 additions and 190 deletions
|
@ -4,9 +4,10 @@ let
|
||||||
tools = pkgs.callPackage ../tools.nix {
|
tools = pkgs.callPackage ../tools.nix {
|
||||||
targets = [ "alpha" ];
|
targets = [ "alpha" ];
|
||||||
};
|
};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-allow-apply-all";
|
name = "colmena-allow-apply-all";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -16,4 +17,5 @@ in tools.makeTest {
|
||||||
|
|
||||||
deployer.succeed("cd /tmp/bundle && run-copy-stderr ${tools.colmenaExec} apply --on @target")
|
deployer.succeed("cd /tmp/bundle && run-copy-stderr ${tools.colmenaExec} apply --on @target")
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,10 @@ let
|
||||||
security.sudo.wheelNeedsPassword = false;
|
security.sudo.wheelNeedsPassword = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-apply-local";
|
name = "colmena-apply-local";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -22,4 +23,5 @@ in tools.makeTest {
|
||||||
deployer.succeed("grep SUCCESS /etc/deployment")
|
deployer.succeed("grep SUCCESS /etc/deployment")
|
||||||
deployer.succeed("grep SECRET /run/keys/key-text")
|
deployer.succeed("grep SECRET /run/keys/key-text")
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
tools = pkgs.callPackage ../tools.nix {};
|
tools = pkgs.callPackage ../tools.nix {};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-apply-${evaluator}";
|
name = "colmena-apply-${evaluator}";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
colmena = "${tools.colmenaExec}"
|
colmena = "${tools.colmenaExec}"
|
||||||
evaluator = "${evaluator}"
|
evaluator = "${evaluator}"
|
||||||
'' + builtins.readFile ./test-script.py;
|
'' + builtins.readFile ./test-script.py;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@ let
|
||||||
deployers = [ "deployer" "alpha" "beta" ];
|
deployers = [ "deployer" "alpha" "beta" ];
|
||||||
targets = [];
|
targets = [];
|
||||||
};
|
};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-build-on-target";
|
name = "colmena-build-on-target";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -32,4 +33,5 @@ in tools.makeTest {
|
||||||
profile = beta.succeed("readlink /run/current-system")
|
profile = beta.succeed("readlink /run/current-system")
|
||||||
deployer.fail(f"nix-store -qR {profile}")
|
deployer.fail(f"nix-store -qR {profile}")
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
tools = pkgs.callPackage ../tools.nix {};
|
tools = pkgs.callPackage ../tools.nix {};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-exec";
|
name = "colmena-exec";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -14,4 +15,5 @@ in tools.makeTest {
|
||||||
assert "output from beta" in logs
|
assert "output from beta" in logs
|
||||||
assert "output from gamma" in logs
|
assert "output from gamma" in logs
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,10 @@ let
|
||||||
tools = pkgs.callPackage ../tools.nix {
|
tools = pkgs.callPackage ../tools.nix {
|
||||||
targets = [ "alpha" ];
|
targets = [ "alpha" ];
|
||||||
};
|
};
|
||||||
in tools.makeTest {
|
in tools.runTest {
|
||||||
name = "colmena-flakes-${evaluator}";
|
name = "colmena-flakes-${evaluator}";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -45,4 +46,5 @@ in tools.makeTest {
|
||||||
deployer.succeed("cd /tmp/bundle && ${tools.colmenaExec} apply --on @target --evaluator ${evaluator} --impure")
|
deployer.succeed("cd /tmp/bundle && ${tools.colmenaExec} apply --on @target --evaluator ${evaluator} --impure")
|
||||||
alpha.succeed("grep deployer /etc/deployment")
|
alpha.succeed("grep deployer /etc/deployment")
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ let
|
||||||
in tools.makeTest {
|
in tools.makeTest {
|
||||||
name = "colmena-parallel";
|
name = "colmena-parallel";
|
||||||
|
|
||||||
|
colmena.test = {
|
||||||
bundle = ./.;
|
bundle = ./.;
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
@ -26,4 +27,5 @@ in tools.makeTest {
|
||||||
|
|
||||||
assert delay < 2000
|
assert delay < 2000
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
# By default, we have four nodes: deployer, alpha, beta, gamma.
|
# By default, we have four nodes: deployer, alpha, beta, gamma.
|
||||||
# deployer is where colmena will run.
|
# deployer is where colmena will run.
|
||||||
#
|
#
|
||||||
# `nixos/lib/build-vms.nix` will generate NixOS configurations
|
# TODO: Modularize most of this
|
||||||
# for each node, and we need to include those configurations
|
|
||||||
# in our Colmena setup as well.
|
|
||||||
|
|
||||||
{ insideVm ? false
|
{ insideVm ? false
|
||||||
, deployers ? [ "deployer" ] # Nodes configured as deployers (with Colmena and pre-built system closure)
|
, deployers ? [ "deployer" ] # Nodes configured as deployers (with Colmena and pre-built system closure)
|
||||||
|
@ -26,13 +24,101 @@ let
|
||||||
|
|
||||||
colmenaExec = "${colmena}/bin/colmena";
|
colmenaExec = "${colmena}/bin/colmena";
|
||||||
|
|
||||||
|
## Utilities
|
||||||
sshKeys = import (pkgs.path + "/nixos/tests/ssh-keys.nix") pkgs;
|
sshKeys = import (pkgs.path + "/nixos/tests/ssh-keys.nix") pkgs;
|
||||||
buildVms = import (pkgs.path + "/nixos/lib/build-vms.nix") {
|
nixosLib = import (pkgs.path + "/nixos/lib") { };
|
||||||
inherit (pkgs) system pkgs lib;
|
|
||||||
|
inputClosureOf = pkg: pkgs.runCommand "full-closure" {
|
||||||
|
refs = pkgs.writeReferencesToFile pkg.drvPath;
|
||||||
|
} ''
|
||||||
|
touch $out
|
||||||
|
|
||||||
|
while read ref; do
|
||||||
|
case $ref in
|
||||||
|
*.drv)
|
||||||
|
cat $ref >>$out
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done <$refs
|
||||||
|
'';
|
||||||
|
|
||||||
|
## The modular NixOS test framework with Colmena additions
|
||||||
|
colmenaTestModule = { lib, config, ... }: let
|
||||||
|
cfg = config.colmena.test;
|
||||||
|
|
||||||
|
targetList = "[${concatStringsSep ", " targets}]";
|
||||||
|
bundle = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${config.name}-bundle";
|
||||||
|
dontUnpack = true;
|
||||||
|
dontInstall = true;
|
||||||
|
buildPhase = ''
|
||||||
|
cp -r ${cfg.bundle} $out
|
||||||
|
chmod u+w $out
|
||||||
|
cp ${./tools.nix} $out/tools.nix
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
colmena.test = {
|
||||||
|
bundle = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Path to a directory to copy into the deployer as /tmp/bundle.
|
||||||
|
'';
|
||||||
|
type = lib.types.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Common setup
|
testScript = lib.mkOption {
|
||||||
nodes = let
|
description = ''
|
||||||
|
The test script.
|
||||||
|
|
||||||
|
The Colmena test framework will prepend initialization
|
||||||
|
statements to the actual test script.
|
||||||
|
'';
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
'' + lib.optionalString (prebuiltTarget != null) ''
|
||||||
|
deployer.succeed("nix-store -qR ${prebuiltSystem}")
|
||||||
|
'' + ''
|
||||||
|
deployer.succeed("nix-store -qR ${pkgs.path}")
|
||||||
|
deployer.succeed("ln -sf ${pkgs.path} /nixpkgs")
|
||||||
|
deployer.succeed("mkdir -p /root/.ssh && touch /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa && cat ${sshKeys.snakeOilPrivateKey} > /root/.ssh/id_rsa")
|
||||||
|
|
||||||
|
${lib.optionalString (length targets != 0) ''
|
||||||
|
for node in ${targetList}:
|
||||||
|
node.wait_for_unit("sshd.service")
|
||||||
|
deployer.succeed(f"ssh -o StrictHostKeyChecking=accept-new {node.name} true", timeout=30)
|
||||||
|
''}
|
||||||
|
|
||||||
|
deployer.succeed("cp --no-preserve=mode -r ${bundle} /tmp/bundle && chmod u+w /tmp/bundle")
|
||||||
|
|
||||||
|
orig_store_paths = set(deployer.succeed("ls /nix/store").strip().split("\n"))
|
||||||
|
def get_new_store_paths():
|
||||||
|
cur_store_paths = set(deployer.succeed("ls /nix/store").strip().split("\n"))
|
||||||
|
new_store_paths = cur_store_paths.difference(orig_store_paths)
|
||||||
|
deployer.log(f"{len(new_store_paths)} store paths were created")
|
||||||
|
|
||||||
|
l = list(map(lambda n: f"/nix/store/{n}", new_store_paths))
|
||||||
|
return l
|
||||||
|
|
||||||
|
${cfg.testScript}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
evalTest = module: nixosLib.evalTest {
|
||||||
|
imports = [
|
||||||
|
module
|
||||||
|
colmenaTestModule
|
||||||
|
{ hostPkgs = pkgs; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
## Common setup
|
||||||
|
|
||||||
# Setup for deployer nodes
|
# Setup for deployer nodes
|
||||||
#
|
#
|
||||||
# We include the input closure of a prebuilt system profile
|
# We include the input closure of a prebuilt system profile
|
||||||
|
@ -96,48 +182,34 @@ let
|
||||||
virtualisation.writableStore = true;
|
virtualisation.writableStore = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nodes = let
|
||||||
deployerNodes = map (name: lib.nameValuePair name deployerConfig) deployers;
|
deployerNodes = map (name: lib.nameValuePair name deployerConfig) deployers;
|
||||||
targetNodes = map (name: lib.nameValuePair name targetConfig) targets;
|
targetNodes = map (name: lib.nameValuePair name targetConfig) targets;
|
||||||
in listToAttrs (deployerNodes ++ targetNodes);
|
in listToAttrs (deployerNodes ++ targetNodes);
|
||||||
|
|
||||||
prebuiltSystem = let
|
# A "shallow" re-evaluation of the test for use from Colmena
|
||||||
all = buildVms.buildVirtualNetwork nodes;
|
standaloneTest = evalTest ({ ... }: {
|
||||||
in all.${prebuiltTarget}.config.system.build.toplevel;
|
inherit nodes;
|
||||||
|
});
|
||||||
|
|
||||||
# Utilities
|
prebuiltSystem = standaloneTest.config.nodes.${prebuiltTarget}.system.build.toplevel;
|
||||||
getStandaloneConfigFor = node: let
|
|
||||||
configsWithIp = buildVms.assignIPAddresses nodes;
|
getStandaloneConfigFor = node: { lib, config, ... }: {
|
||||||
in { modulesPath, lib, config, ... }: {
|
imports = [
|
||||||
imports = configsWithIp.${node} ++ [
|
(pkgs.path + "/nixos/lib/testing/nixos-test-base.nix")
|
||||||
(modulesPath + "/virtualisation/qemu-vm.nix")
|
(if elem node deployers then deployerConfig else targetConfig)
|
||||||
(modulesPath + "/testing/test-instrumentation.nix")
|
standaloneTest.config.nodes.${node}.system.build.networkConfig
|
||||||
];
|
];
|
||||||
|
|
||||||
documentation.nixos.enable = lib.mkOverride 55 false;
|
documentation.nixos.enable = lib.mkOverride 55 false;
|
||||||
boot.loader.grub.enable = false;
|
boot.loader.grub.enable = false;
|
||||||
system.nixos.revision = lib.mkForce "constant-nixos-revision";
|
system.nixos.revision = lib.mkForce "constant-nixos-revision";
|
||||||
|
|
||||||
# otherwise the evaluation is unnecessarily slow in VM
|
|
||||||
virtualisation.additionalPaths = lib.mkForce [];
|
|
||||||
nix.nixPath = lib.mkForce [ "nixpkgs=/nixpkgs" ];
|
nix.nixPath = lib.mkForce [ "nixpkgs=/nixpkgs" ];
|
||||||
|
|
||||||
deployment.tags = lib.optional (config.networking.hostName != "deployer") "target";
|
deployment.tags = lib.optional (config.networking.hostName != "deployer") "target";
|
||||||
};
|
};
|
||||||
|
|
||||||
inputClosureOf = pkg: pkgs.runCommand "full-closure" {
|
|
||||||
refs = pkgs.writeReferencesToFile pkg.drvPath;
|
|
||||||
} ''
|
|
||||||
touch $out
|
|
||||||
|
|
||||||
while read ref; do
|
|
||||||
case $ref in
|
|
||||||
*.drv)
|
|
||||||
cat $ref >>$out
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done <$refs
|
|
||||||
'';
|
|
||||||
|
|
||||||
makeTest = test: let
|
makeTest = test: let
|
||||||
customArgs = [ "bundle" ];
|
customArgs = [ "bundle" ];
|
||||||
|
|
||||||
|
@ -190,4 +262,9 @@ let
|
||||||
in {
|
in {
|
||||||
inherit pkgs nodes colmena colmenaExec
|
inherit pkgs nodes colmena colmenaExec
|
||||||
getStandaloneConfigFor inputClosureOf makeTest;
|
getStandaloneConfigFor inputClosureOf makeTest;
|
||||||
|
|
||||||
|
runTest = module: (evalTest ({ config, ... }: {
|
||||||
|
imports = [ module { inherit nodes; } ];
|
||||||
|
result = config.test;
|
||||||
|
})).config.result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue