Merge pull request 'tests(clan): move test-inventory.nix to clanLib. And name it 'makeTestClan'' (#3330) from hsjobeki/clan-core:lib-cleanup into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3330
This commit is contained in:
hsjobeki
2025-04-15 16:27:09 +00:00
10 changed files with 236 additions and 211 deletions

View File

@@ -1,78 +1,86 @@
(import ../lib/test-inventory.nix) (
{ lib, ... }:
let
{
pkgs,
self,
clanLib,
...
}:
clanLib.test.makeTestClan {
inherit pkgs self;
nixosTest = (
{ lib, ... }:
let
machines = [
"admin"
"peer"
"signer"
];
in
{
name = "data-mesher";
machines = [
"admin"
"peer"
"signer"
];
in
{
name = "data-mesher";
clan = {
directory = ./.;
inventory = {
machines = lib.genAttrs machines (_: { });
services = {
data-mesher.default = {
roles.peer.machines = [ "peer" ];
roles.admin.machines = [ "admin" ];
roles.signer.machines = [ "signer" ];
clan = {
directory = ./.;
inventory = {
machines = lib.genAttrs machines (_: { });
services = {
data-mesher.default = {
roles.peer.machines = [ "peer" ];
roles.admin.machines = [ "admin" ];
roles.signer.machines = [ "signer" ];
};
};
};
};
};
defaults =
{ config, ... }:
{
environment.systemPackages = [
config.services.data-mesher.package
];
defaults =
{ config, ... }:
{
environment.systemPackages = [
config.services.data-mesher.package
];
clan.data-mesher.network.interface = "eth1";
clan.data-mesher.bootstrapNodes = [
"[2001:db8:1::1]:7946" # peer1
"[2001:db8:1::2]:7946" # peer2
];
clan.data-mesher.network.interface = "eth1";
clan.data-mesher.bootstrapNodes = [
"[2001:db8:1::1]:7946" # peer1
"[2001:db8:1::2]:7946" # peer2
];
# speed up for testing
services.data-mesher.settings = {
cluster.join_interval = lib.mkForce "2s";
cluster.push_pull_interval = lib.mkForce "5s";
# speed up for testing
services.data-mesher.settings = {
cluster.join_interval = lib.mkForce "2s";
cluster.push_pull_interval = lib.mkForce "5s";
};
};
nodes = {
admin.clan.data-mesher.network.tld = "foo";
};
nodes = {
admin.clan.data-mesher.network.tld = "foo";
};
# TODO Add better test script.
testScript = ''
# TODO Add better test script.
testScript = ''
def resolve(node, success = {}, fail = [], timeout = 60):
for hostname, ips in success.items():
for ip in ips:
node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout)
def resolve(node, success = {}, fail = [], timeout = 60):
for hostname, ips in success.items():
for ip in ips:
node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout)
for hostname in fail:
node.wait_until_fails(f"getent ahosts {hostname}")
for hostname in fail:
node.wait_until_fails(f"getent ahosts {hostname}")
start_all()
start_all()
admin.wait_for_unit("data-mesher")
signer.wait_for_unit("data-mesher")
peer.wait_for_unit("data-mesher")
admin.wait_for_unit("data-mesher")
signer.wait_for_unit("data-mesher")
peer.wait_for_unit("data-mesher")
# check dns resolution
for node in [admin, signer, peer]:
resolve(node, {
"admin.foo": ["2001:db8:1::1", "192.168.1.1"],
"peer.foo": ["2001:db8:1::2", "192.168.1.2"],
"signer.foo": ["2001:db8:1::3", "192.168.1.3"]
})
'';
}
)
# check dns resolution
for node in [admin, signer, peer]:
resolve(node, {
"admin.foo": ["2001:db8:1::1", "192.168.1.1"],
"peer.foo": ["2001:db8:1::2", "192.168.1.2"],
"signer.foo": ["2001:db8:1::3", "192.168.1.3"]
})
'';
}
);
}

View File

@@ -1,67 +1,76 @@
(import ../lib/test-inventory.nix) (
{ ... }:
{
# This tests the compatibility of the inventory
# With the test framework
# - legacy-modules
# - clan.service modules
name = "dummy-inventory-test";
{
pkgs,
self,
clanLib,
...
}:
clanLib.test.makeTestClan {
inherit pkgs self;
nixosTest = (
{ ... }:
{
# This tests the compatibility of the inventory
# With the test framework
# - legacy-modules
# - clan.service modules
name = "dummy-inventory-test";
clan = {
directory = ./.;
inventory = {
machines.peer1 = { };
machines.admin1 = { };
services = {
legacy-module.default = {
roles.peer.machines = [ "peer1" ];
roles.admin.machines = [ "admin1" ];
clan = {
directory = ./.;
inventory = {
machines.peer1 = { };
machines.admin1 = { };
services = {
legacy-module.default = {
roles.peer.machines = [ "peer1" ];
roles.admin.machines = [ "admin1" ];
};
};
instances."test" = {
module.name = "new-service";
roles.peer.machines.peer1 = { };
};
};
instances."test" = {
module.name = "new-service";
roles.peer.machines.peer1 = { };
};
modules = {
legacy-module = ./legacy-module;
new-service = {
_class = "clan.service";
manifest.name = "new-service";
roles.peer = { };
perMachine = {
nixosModule = {
# This should be generated by:
# ./pkgs/scripts/update-vars.py inventory-test-framework-compatibility-test
clan.core.vars.generators.new-service = {
files.hello = {
secret = false;
deploy = true;
modules = {
legacy-module = ./legacy-module;
new-service = {
_class = "clan.service";
manifest.name = "new-service";
roles.peer = { };
perMachine = {
nixosModule = {
# This should be generated by:
# ./pkgs/scripts/update-vars.py inventory-test-framework-compatibility-test
clan.core.vars.generators.new-service = {
files.hello = {
secret = false;
deploy = true;
};
script = ''
# This is a dummy script that does nothing
echo "This is a dummy script" > $out/hello
'';
};
script = ''
# This is a dummy script that does nothing
echo "This is a dummy script" > $out/hello
'';
};
};
};
};
};
};
};
testScript =
{ nodes, ... }:
''
start_all()
admin1.wait_for_unit("multi-user.target")
peer1.wait_for_unit("multi-user.target")
# Provided by the legacy module
print(admin1.succeed("systemctl status dummy-service"))
print(peer1.succeed("systemctl status dummy-service"))
testScript =
{ nodes, ... }:
''
start_all()
admin1.wait_for_unit("multi-user.target")
peer1.wait_for_unit("multi-user.target")
# Provided by the legacy module
print(admin1.succeed("systemctl status dummy-service"))
print(peer1.succeed("systemctl status dummy-service"))
# peer1 should have the 'hello' file
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.hello.path}")
'';
}
)
# peer1 should have the 'hello' file
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.hello.path}")
'';
}
);
}

View File

@@ -27,9 +27,10 @@ in
let
nixosTestArgs = {
# reference to nixpkgs for the current system
inherit pkgs;
inherit pkgs lib;
# this gives us a reference to our flake but also all flake inputs
inherit self;
inherit (self) clanLib;
};
nixosTests = lib.optionalAttrs (pkgs.stdenv.isLinux) {
# import our test

View File

@@ -99,7 +99,7 @@ in
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
self.clanLib.test.minifyModule
];
networking.hostName = "test-install-machine";

View File

@@ -13,7 +13,7 @@ in
{ config, options, ... }:
{
imports = [
./minify.nix
self.clanLib.test.minifyModule
];
config = lib.mkMerge [
(lib.optionalAttrs (options ? clan) {

View File

@@ -11,7 +11,7 @@ in
{ config, options, ... }:
{
imports = [
./minify.nix
self.clanLib.test.minifyModule
];
config = lib.mkMerge [
(lib.optionalAttrs (options ? clan) {

View File

@@ -1,89 +0,0 @@
test:
{ pkgs, self, ... }:
let
inherit (pkgs) lib;
inherit (lib)
mkOption
flip
mapAttrs
types
;
nixos-lib = import (pkgs.path + "/nixos/lib") { };
in
(nixos-lib.runTest (
{ config, ... }:
let
clanFlakeResult = config.clan;
in
{
imports = [ test ];
options = {
clanSettings = mkOption {
default = { };
type = types.submodule {
options = {
clan-core = mkOption { default = self; };
nixpkgs = mkOption { default = self.inputs.nixpkgs; };
nix-darwin = mkOption { default = self.inputs.nix-darwin; };
};
};
};
clan = mkOption {
default = { };
type = types.submoduleWith {
specialArgs = {
inherit (config.clanSettings)
clan-core
nixpkgs
nix-darwin
;
};
modules = [
self.clanLib.buildClanModule.flakePartsModule
];
};
};
};
config = {
nodes = flip mapAttrs clanFlakeResult.clanInternals.inventoryClass.machines (
machineName: attrs: {
imports = attrs.machineImports ++ [ self.nixosModules.clanCore ];
clan.core.settings.directory = "${config.clan.directory}";
clan.core.settings.machine.name = machineName;
}
);
hostPkgs = pkgs;
# speed-up evaluation
defaults = (
{ config, ... }:
{
imports = [
./minify.nix
];
documentation.enable = lib.mkDefault false;
nix.settings.min-free = 0;
system.stateVersion = config.system.nixos.release;
boot.initrd.systemd.enable = false;
# setup for sops
sops.age.keyFile = "/run/age-key.txt";
system.activationScripts =
{
setupSecrets.deps = [ "age-key" ];
age-key.text = ''
echo AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV > /run/age-key.txt
'';
}
// lib.optionalAttrs (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets != { }) {
setupSecretsForUsers.deps = [ "age-key" ];
};
}
);
_module.args = { inherit self; };
# to accept external dependencies such as disko
node.specialArgs.self = self;
};
}
)).config.result

View File

@@ -25,6 +25,7 @@ lib.fix (clanLib: {
buildClanModule = clanLib.callLib ./build-clan { };
inventory = clanLib.callLib ./inventory { };
modules = clanLib.callLib ./inventory/frontmatter { };
test = clanLib.callLib ./tests { };
# Plain imports.
values = import ./introspection { inherit lib; };

92
lib/tests/default.nix Normal file
View File

@@ -0,0 +1,92 @@
{ lib, clanLib }:
let
inherit (lib)
mkOption
types
;
in
{
minifyModule = ./minify.nix;
# A function that returns an extension to runTest
makeTestClan =
{
nixosTest,
pkgs,
self,
...
}:
let
nixos-lib = import (pkgs.path + "/nixos/lib") { };
in
(nixos-lib.runTest (
{ config, ... }:
let
clanFlakeResult = config.clan;
in
{
imports = [ nixosTest ];
options = {
clanSettings = mkOption {
default = { };
type = types.submodule {
options = {
clan-core = mkOption { default = self; };
nixpkgs = mkOption { default = self.inputs.nixpkgs; };
nix-darwin = mkOption { default = self.inputs.nix-darwin; };
};
};
};
clan = mkOption {
default = { };
type = types.submoduleWith {
specialArgs = {
inherit (config.clanSettings)
clan-core
nixpkgs
nix-darwin
;
};
modules = [
clanLib.buildClanModule.flakePartsModule
];
};
};
};
config = {
nodes = clanFlakeResult.clanInternals.nixosModules;
hostPkgs = pkgs;
# speed-up evaluation
defaults = (
{ config, ... }:
{
imports = [
clanLib.test.minifyModule
];
documentation.enable = lib.mkDefault false;
nix.settings.min-free = 0;
system.stateVersion = config.system.nixos.release;
boot.initrd.systemd.enable = false;
# setup for sops
sops.age.keyFile = "/run/age-key.txt";
system.activationScripts =
{
setupSecrets.deps = [ "age-key" ];
age-key.text = ''
echo AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV > /run/age-key.txt
'';
}
// lib.optionalAttrs (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets != { }) {
setupSecretsForUsers.deps = [ "age-key" ];
};
}
);
# to accept external dependencies such as disko
_module.args = { inherit self; };
node.specialArgs.self = self;
};
}
)).config.result;
}

View File

@@ -1,3 +1,6 @@
# This is a module to reduce the size of the NixOS configuration
# Used by the tests
# It unsets some unnecessary options
{ lib, ... }:
{
nixpkgs.flake.setFlakeRegistry = false;