Merge pull request 'Introduce flake parts module for clan nixos tests' (#4000) from speed-up-ci into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4000
This commit is contained in:
Mic92
2025-06-17 19:20:08 +00:00
44 changed files with 749 additions and 941 deletions

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
admin = lib.modules.importApply ./default.nix { }; admin = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.admin = {
admin = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/admin" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,62 +1,45 @@
{
pkgs,
nixosLib,
clan-core,
...
}:
let let
public-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII6zj7ubTg6z/aDwRNwvM/WlQdUocMprQ8E92NWxl6t+ test@test"; public-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII6zj7ubTg6z/aDwRNwvM/WlQdUocMprQ8E92NWxl6t+ test@test";
in in
nixosLib.runTest ( {
{ ... }: name = "admin";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
name = "admin"; machines.client = { };
machines.server = { };
clan = { instances = {
directory = ./.; ssh-test-one = {
modules."@clan/admin" = ../../default.nix; module.name = "@clan/admin";
inventory = { roles.default.machines."server".settings = {
allowedKeys.testkey = public-key;
machines.client = { };
machines.server = { };
instances = {
ssh-test-one = {
module.name = "@clan/admin";
roles.default.machines."server".settings = {
allowedKeys.testkey = public-key;
};
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
client.environment.etc.private-test-key.source = ./private-test-key; client.environment.etc.private-test-key.source = ./private-test-key;
server = { server = {
services.openssh.enable = true; services.openssh.enable = true;
};
}; };
};
testScript = '' testScript = ''
start_all() start_all()
machines = [client, server] machines = [client, server]
for m in machines: for m in machines:
m.systemctl("start network-online.target") m.systemctl("start network-online.target")
for m in machines: for m in machines:
m.wait_for_unit("network-online.target") m.wait_for_unit("network-online.target")
client.succeed(f"ssh -F /dev/null -i /etc/private-test-key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes root@server true &>/dev/null") client.succeed(f"ssh -F /dev/null -i /etc/private-test-key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes root@server true &>/dev/null")
''; '';
} }
)

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
borgbackup = lib.modules.importApply ./default.nix { }; borgbackup = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.borgbackup = {
borgbackup = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/borgbackup" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,118 +1,112 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "borgbackup";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
test.useContainers = true;
inventory = {
name = "borgbackup"; machines.clientone = { };
machines.serverone = { };
clan = { instances = {
directory = ./.; borgone = {
test.useContainers = true;
modules."@clan/borgbackup" = ../../default.nix;
inventory = {
machines.clientone = { }; module.name = "@clan/borgbackup";
machines.serverone = { };
instances = { roles.client.machines."clientone" = { };
borgone = { roles.server.machines."serverone".settings.directory = "/tmp/borg-test";
module.name = "@clan/borgbackup";
roles.client.machines."clientone" = { };
roles.server.machines."serverone".settings.directory = "/tmp/borg-test";
};
}; };
}; };
}; };
};
nodes = { nodes = {
serverone = {
services.openssh.enable = true;
# Needed so PAM doesn't see the user as locked
users.users.borg.password = "borg";
};
clientone =
{
config,
pkgs,
clan-core,
...
}:
let
dependencies = [
clan-core
pkgs.stdenv.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues clan-core.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
serverone = {
services.openssh.enable = true; services.openssh.enable = true;
# Needed so PAM doesn't see the user as locked
users.users.borg.password = "borg"; users.users.root.openssh.authorizedKeys.keyFiles = [ ../../../../checks/assets/ssh/pubkey ];
clan.core.networking.targetHost = config.networking.hostName;
environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ];
environment.etc.install-closure.source = "${closureInfo}/store-paths";
nix.settings = {
substituters = pkgs.lib.mkForce [ ];
hashed-mirrors = null;
connect-timeout = pkgs.lib.mkForce 3;
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
};
system.extraDependencies = dependencies;
clan.core.state.test-backups.folders = [ "/var/test-backups" ];
}; };
clientone = };
{ config, pkgs, ... }:
let
dependencies = [
clan-core
pkgs.stdenv.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues clan-core.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in testScript = ''
{ import json
start_all()
services.openssh.enable = true; machines = [clientone, serverone]
users.users.root.openssh.authorizedKeys.keyFiles = [ ../../../../checks/assets/ssh/pubkey ]; for m in machines:
m.systemctl("start network-online.target")
clan.core.networking.targetHost = config.networking.hostName; for m in machines:
m.wait_for_unit("network-online.target")
environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ]; # dummy data
clientone.succeed("mkdir -p /var/test-backups /var/test-service")
clientone.succeed("echo testing > /var/test-backups/somefile")
environment.etc.install-closure.source = "${closureInfo}/store-paths"; clientone.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../../../../checks/assets/ssh/privkey} /root/.ssh/id_ed25519")
nix.settings = { clientone.succeed("${pkgs.coreutils}/bin/touch /root/.ssh/known_hosts")
substituters = pkgs.lib.mkForce [ ]; clientone.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new localhost hostname")
hashed-mirrors = null; clientone.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new $(hostname) hostname")
connect-timeout = pkgs.lib.mkForce 3;
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
};
system.extraDependencies = dependencies;
clan.core.state.test-backups.folders = [ "/var/test-backups" ]; # create
}; clientone.succeed("borgbackup-create >&2")
clientone.wait_until_succeeds("! systemctl is-active borgbackup-job-serverone >&2")
}; # list
backup_id = json.loads(clientone.succeed("borg-job-serverone list --json"))["archives"][0]["archive"]
out = clientone.succeed("borgbackup-list").strip()
print(out)
assert backup_id in out, f"backup {backup_id} not found in {out}"
testScript = '' # borgbackup restore
import json clientone.succeed("rm -f /var/test-backups/somefile")
start_all() clientone.succeed(f"NAME='serverone::borg@serverone:.::{backup_id}' borgbackup-restore >&2")
assert clientone.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
machines = [clientone, serverone] '';
}
for m in machines:
m.systemctl("start network-online.target")
for m in machines:
m.wait_for_unit("network-online.target")
# dummy data
clientone.succeed("mkdir -p /var/test-backups /var/test-service")
clientone.succeed("echo testing > /var/test-backups/somefile")
clientone.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../../../../checks/assets/ssh/privkey} /root/.ssh/id_ed25519")
clientone.succeed("${pkgs.coreutils}/bin/touch /root/.ssh/known_hosts")
clientone.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new localhost hostname")
clientone.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new $(hostname) hostname")
# create
clientone.succeed("borgbackup-create >&2")
clientone.wait_until_succeeds("! systemctl is-active borgbackup-job-serverone >&2")
# list
backup_id = json.loads(clientone.succeed("borg-job-serverone list --json"))["archives"][0]["archive"]
out = clientone.succeed("borgbackup-list").strip()
print(out)
assert backup_id in out, f"backup {backup_id} not found in {out}"
# borgbackup restore
clientone.succeed("rm -f /var/test-backups/somefile")
clientone.succeed(f"NAME='serverone::borg@serverone:.::{backup_id}' borgbackup-restore >&2")
assert clientone.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
'';
}
)

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
deltachat = lib.modules.importApply ./default.nix { }; deltachat = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.deltachat = {
deltachat = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/deltachat" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,50 +1,39 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "deltachat";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
machines.server = { };
name = "deltachat"; instances = {
deltachat-test = {
clan = { module.name = "@clan/deltachat";
directory = ./.; roles.default.machines."server".settings = { };
modules."@clan/deltachat" = ../../default.nix;
inventory = {
machines.server = { };
instances = {
deltachat-test = {
module.name = "@clan/deltachat";
roles.default.machines."server".settings = { };
};
}; };
}; };
}; };
};
nodes = { nodes = {
server = { }; server = { };
}; };
testScript = '' testScript = ''
start_all() start_all()
server.wait_for_unit("maddy") server.wait_for_unit("maddy")
# imap # imap
server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 143") server.wait_until_succeeds("${pkgs.netcat}/bin/nc -z -v ::1 143")
# smtp submission # smtp submission
server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 587") server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 587")
# smtp # smtp
server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 25") server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 25")
''; '';
} }
)

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
ergochat = lib.modules.importApply ./default.nix { }; ergochat = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.ergochat = {
ergochat = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/ergochat" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,51 +1,41 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "ergochat";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
name = "ergochat"; directory = ./.;
inventory = {
machines.server = { };
clan = { instances = {
directory = ./.; ergochat-test = {
modules."@clan/ergochat" = ../../default.nix; module.name = "@clan/ergochat";
inventory = { roles.default.machines."server".settings = { };
machines.server = { };
instances = {
ergochat-test = {
module.name = "@clan/ergochat";
roles.default.machines."server".settings = { };
};
}; };
}; };
}; };
};
nodes = { nodes = {
server = { }; server = { };
}; };
testScript = '' testScript = ''
start_all() start_all()
server.wait_for_unit("ergochat") server.wait_for_unit("ergochat")
# Check that ergochat is running # Check that ergochat is running
server.succeed("systemctl status ergochat") server.succeed("systemctl status ergochat")
# Check that the data directory exists # Check that the data directory exists
server.succeed("test -d /var/lib/ergo") server.succeed("test -d /var/lib/ergo")
# Check that the server is listening on the correct ports # Check that the server is listening on the correct ports
server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 6667") server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 6667")
''; '';
} }
)

View File

@@ -1,18 +1,19 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
garage = lib.modules.importApply ./default.nix { }; garage = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.garage = {
garage = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/garage" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,87 +1,76 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "garage";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
machines.server = { };
name = "garage"; instances = {
garage-test = {
module.name = "@clan/garage";
roles.default.machines."server".settings = { };
};
};
};
};
clan = { nodes = {
directory = ./.; server = {
modules."@clan/garage" = ../../default.nix; services.garage = {
inventory = { enable = true;
machines.server = { }; package = pkgs.garage;
settings = {
instances = { metadata_dir = "/var/lib/garage/meta";
garage-test = { data_dir = "/var/lib/garage/data";
module.name = "@clan/garage"; db_engine = "sqlite";
roles.default.machines."server".settings = { };
replication_factor = 1;
rpc_bind_addr = "127.0.0.1:3901";
s3_api = {
api_bind_addr = "127.0.0.1:3900";
s3_region = "garage";
root_domain = ".s3.garage";
};
s3_web = {
bind_addr = "127.0.0.1:3902";
root_domain = ".web.garage";
};
admin = {
api_bind_addr = "127.0.0.1:3903";
}; };
}; };
}; };
}; };
};
nodes = { testScript = ''
server = { start_all()
services.garage = {
enable = true;
package = pkgs.garage;
settings = {
metadata_dir = "/var/lib/garage/meta"; server.wait_for_unit("network-online.target")
data_dir = "/var/lib/garage/data"; server.wait_for_unit("garage")
db_engine = "sqlite";
replication_factor = 1; # Check that garage is running
server.succeed("systemctl status garage")
rpc_bind_addr = "127.0.0.1:3901"; # Check that the data directories exist
server.succeed("test -d /var/lib/garage/meta")
server.succeed("test -d /var/lib/garage/data")
s3_api = { # Check that the ports are open to confirm that garage is running
api_bind_addr = "127.0.0.1:3900"; server.wait_until_succeeds("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3901")
s3_region = "garage"; server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3900")
root_domain = ".s3.garage"; server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3902")
}; server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3903")
'';
s3_web = { }
bind_addr = "127.0.0.1:3902";
root_domain = ".web.garage";
};
admin = {
api_bind_addr = "127.0.0.1:3903";
};
};
};
};
};
testScript = ''
start_all()
server.wait_for_unit("network-online.target")
server.wait_for_unit("garage")
# Check that garage is running
server.succeed("systemctl status garage")
# Check that the data directories exist
server.succeed("test -d /var/lib/garage/meta")
server.succeed("test -d /var/lib/garage/data")
# Check that the ports are open to confirm that garage is running
server.wait_until_succeeds("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3901")
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3900")
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3902")
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 3903")
'';
}
)

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
heisenbridge = lib.modules.importApply ./default.nix { }; heisenbridge = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.heisenbridge = {
heisenbridge = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/heisenbridge" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,65 +1,53 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
{
name = "heisenbridge";
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; instances = {
heisenbridge-test = {
name = "heisenbridge"; module.name = "@clan/heisenbridge";
roles.default.machines."server".settings = {
clan = { homeserver = "http://127.0.0.1:8008";
directory = ./.;
modules."@clan/heisenbridge" = ../../default.nix;
inventory = {
machines.server = { };
instances = {
heisenbridge-test = {
module.name = "@clan/heisenbridge";
roles.default.machines."server".settings = {
homeserver = "http://127.0.0.1:8008";
};
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
server = { server = {
# Setup a minimal matrix-synapse to test with # Setup a minimal matrix-synapse to test with
services.matrix-synapse = { services.matrix-synapse = {
enable = true; enable = true;
settings.server_name = "example.com"; settings.server_name = "example.com";
settings.database = { settings.database = {
name = "sqlite3"; name = "sqlite3";
};
}; };
}; };
}; };
};
testScript = '' testScript = ''
start_all() start_all()
server.wait_for_unit("matrix-synapse") server.wait_for_unit("matrix-synapse")
server.wait_for_unit("heisenbridge") server.wait_for_unit("heisenbridge")
# Check that heisenbridge is running # Check that heisenbridge is running
server.succeed("systemctl status heisenbridge") server.succeed("systemctl status heisenbridge")
# Wait for the bridge to initialize # Wait for the bridge to initialize
server.wait_until_succeeds("journalctl -u heisenbridge | grep -q 'bridge is now running'") server.wait_until_succeeds("journalctl -u heisenbridge | grep -q 'bridge is now running'")
# Check that heisenbridge is listening on the default port # Check that heisenbridge is listening on the default port
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 9898") server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 9898")
''; '';
} }
)

View File

@@ -14,7 +14,7 @@ in
hello-world = module; hello-world = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
let let
# Module that contains the tests # Module that contains the tests
# This module adds: # This module adds:
@@ -41,15 +41,10 @@ in
2. To run the test 2. To run the test
nix build .#checks.x86_64-linux.hello-service nix build .#checks.x86_64-linux.hello-service
*/ */
checks = clan.nixosTests.hello-service = {
# Currently we don't support nixos-integration tests on darwin imports = [ ./tests/vm/default.nix ];
lib.optionalAttrs (pkgs.stdenv.isLinux) {
hello-service = import ./tests/vm/default.nix { clan.modules.hello-service = module;
inherit module; };
inherit self inputs pkgs;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
clan-core = self;
};
};
}; };
} }

View File

@@ -1,44 +1,29 @@
{ {
pkgs,
nixosLib,
clan-core,
module, module,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "hello-service";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
machines.peer1 = { };
name = "hello-service"; instances."test" = {
module.name = "hello-service";
clan = { roles.peer.machines.peer1 = { };
directory = ./.;
modules = {
hello-service = module;
};
inventory = {
machines.peer1 = { };
instances."test" = {
module.name = "hello-service";
roles.peer.machines.peer1 = { };
};
}; };
}; };
};
testScript = testScript =
{ nodes, ... }: { nodes, ... }:
'' ''
start_all() start_all()
# peer1 should have the 'hello' file # peer1 should have the 'hello' file
value = peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.hello.files.hello.path}") value = peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.hello.files.hello.path}")
assert value.strip() == "Hello world from peer1", value assert value.strip() == "Hello world from peer1", value
''; '';
} }
)

View File

@@ -1,18 +1,19 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
localsend = lib.modules.importApply ./default.nix { }; localsend = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.localsend = {
localsend = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/localsend" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,51 +1,38 @@
{ {
pkgs, module,
nixosLib,
clan-core,
... ...
}: }:
{
name = "localsend";
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; instances = {
localsend-test = {
name = "localsend"; module.name = "@clan/localsend";
roles.default.machines."server".settings = {
clan = { displayName = "Test Instance";
directory = ./.; ipv4Addr = "192.168.56.2/24";
modules."@clan/localsend" = ../../default.nix;
inventory = {
machines.server = { };
instances = {
localsend-test = {
module.name = "@clan/localsend";
roles.default.machines."server".settings = {
displayName = "Test Instance";
ipv4Addr = "192.168.56.2/24";
};
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
server = { }; server = { };
}; };
testScript = '' testScript = ''
start_all() start_all()
# Check that the localsend wrapper script is available # Check that the localsend wrapper script is available
server.succeed("command -v localsend") server.succeed("command -v localsend")
# Verify the 09-zerotier network is configured with the specified IP address # Verify the 09-zerotier network is configured with the specified IP address
server.succeed("grep -q 'Address=192.168.56.2/24' /etc/systemd/network/09-zerotier.network") server.succeed("grep -q 'Address=192.168.56.2/24' /etc/systemd/network/09-zerotier.network")
''; '';
} }
)

View File

@@ -1,17 +1,18 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
mycelium = lib.modules.importApply ./default.nix { }; mycelium = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.mycelium = {
mycelium = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/mycelium" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,53 +1,42 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
nixosLib.runTest ( {
{ ... }: name = "mycelium";
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
name = "mycelium"; test.useContainers = false;
directory = ./.;
inventory = {
machines.server = { };
clan = { instances = {
mycelium-test = {
test.useContainers = false; module.name = "@clan/mycelium";
directory = ./.; roles.peer.machines."server".settings = {
modules."@clan/mycelium" = ../../default.nix; openFirewall = true;
inventory = { addHostedPublicNodes = true;
machines.server = { };
instances = {
mycelium-test = {
module.name = "@clan/mycelium";
roles.peer.machines."server".settings = {
openFirewall = true;
addHostedPublicNodes = true;
};
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
server = { }; server = { };
}; };
testScript = '' testScript = ''
start_all() start_all()
# Check that mycelium service is running # Check that mycelium service is running
server.wait_for_unit("mycelium") server.wait_for_unit("mycelium")
server.succeed("systemctl status mycelium") server.succeed("systemctl status mycelium")
# Check that mycelium is listening on its default port # Check that mycelium is listening on its default port
server.wait_until_succeeds("${pkgs.iproute2}/bin/ss -tulpn | grep -q 'mycelium'", 10) server.wait_until_succeeds("${pkgs.iproute2}/bin/ss -tulpn | grep -q 'mycelium'", 10)
''; '';
} }
)

View File

@@ -1,18 +1,19 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
packages = lib.modules.importApply ./default.nix { }; packages = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.packages = {
packages = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/packages" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };

View File

@@ -1,41 +1,28 @@
{ {
pkgs, module,
nixosLib,
clan-core,
... ...
}: }:
{
name = "packages";
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; instances.default = {
module.name = "@clan/packages";
name = "packages"; roles.default.machines."server".settings = {
packages = [ "cbonsai" ];
clan = {
directory = ./.;
modules."@clan/packages" = ../../default.nix;
inventory = {
machines.server = { };
instances.default = {
module.name = "@clan/packages";
roles.default.machines."server".settings = {
packages = [ "cbonsai" ];
};
}; };
}; };
}; };
};
nodes.server = { }; nodes.server = { };
testScript = '' testScript = ''
start_all() start_all()
server.succeed("cbonsai") server.succeed("cbonsai")
''; '';
} }
)

View File

@@ -1,18 +1,19 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules = {
sshd = lib.modules.importApply ./default.nix { }; sshd = module;
}; };
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.sshd = {
sshd = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/sshd" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };

View File

@@ -1,62 +1,50 @@
{ {
module,
pkgs, pkgs,
nixosLib,
clan-core,
... ...
}: }:
{
name = "sshd";
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest machines.client = { };
];
hostPkgs = pkgs; instances = {
sshd-test = {
name = "sshd"; module.name = "@clan/sshd";
roles.server.machines."server".settings = {
clan = { certificate.searchDomains = [ "example.com" ];
directory = ./.; hostKeys.rsa.enable = true;
modules."@clan/sshd" = ../../default.nix; };
inventory = { roles.client.machines."client".settings = {
machines.server = { }; certificate.searchDomains = [ "example.com" ];
machines.client = { };
instances = {
sshd-test = {
module.name = "@clan/sshd";
roles.server.machines."server".settings = {
certificate.searchDomains = [ "example.com" ];
hostKeys.rsa.enable = true;
};
roles.client.machines."client".settings = {
certificate.searchDomains = [ "example.com" ];
};
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
server = { }; server = { };
client = { }; client = { };
}; };
testScript = '' testScript = ''
start_all() start_all()
# Check that sshd port is open on the server # Check that sshd port is open on the server
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 22") server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 22")
# Check that /etc/ssh/ssh_known_hosts contains the required CA string on the server # Check that /etc/ssh/ssh_known_hosts contains the required CA string on the server
server.succeed("grep '^@cert-authority ssh-ca,\*.example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts") server.succeed("grep '^@cert-authority ssh-ca,\*.example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
# Check that server contains a line starting with 'localhost,server ssh-ed25519' # Check that server contains a line starting with 'localhost,server ssh-ed25519'
server.succeed("grep '^localhost,server ssh-ed25519 ' /etc/ssh/ssh_known_hosts") server.succeed("grep '^localhost,server ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
# Check that /etc/ssh/ssh_known_hosts contains the required CA string on the client # Check that /etc/ssh/ssh_known_hosts contains the required CA string on the client
client.succeed("grep '^.cert-authority ssh-ca.*example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts") client.succeed("grep '^.cert-authority ssh-ca.*example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
''; '';
} }
)

View File

@@ -1,19 +1,16 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules.state-version = module;
state-version = lib.modules.importApply ./default.nix { };
};
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.state-version = {
state-version = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/state-version" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,37 +1,20 @@
{ {
pkgs, name = "state-version";
nixosLib,
clan-core,
...
}:
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest instances.default = {
]; module.name = "@clan/state-version";
roles.default.machines."server" = { };
hostPkgs = pkgs;
name = "state-version";
clan = {
directory = ./.;
modules."@clan/state-version" = ../../default.nix;
inventory = {
machines.server = { };
instances.default = {
module.name = "@clan/state-version";
roles.default.machines."server" = { };
};
}; };
}; };
};
nodes.server = { }; nodes.server = { };
testScript = '' testScript = ''
start_all() start_all()
''; '';
} }
)

View File

@@ -1,17 +1,16 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules.trusted-nix-caches = module;
trusted-nix-caches = lib.modules.importApply ./default.nix { };
};
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.trusted-nix-caches = {
trusted-nix-caches = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/trusted-nix-caches" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,40 +1,24 @@
{ {
pkgs, name = "trusted-nix-caches";
nixosLib,
clan-core,
...
}:
nixosLib.runTest (
{ ... }:
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
machines.server = { };
name = "trusted-nix-caches"; instances = {
trusted-nix-caches = {
clan = { module.name = "@clan/trusted-nix-caches";
directory = ./.; roles.default.machines."server" = { };
modules."@clan/trusted-nix-caches" = ../../default.nix;
inventory = {
machines.server = { };
instances = {
trusted-nix-caches = {
module.name = "@clan/trusted-nix-caches";
roles.default.machines."server" = { };
};
}; };
}; };
}; };
};
nodes.server = { }; nodes.server = { };
testScript = '' testScript = ''
start_all() start_all()
server.succeed("grep -q 'cache.clan.lol' /etc/nix/nix.conf") server.succeed("grep -q 'cache.clan.lol' /etc/nix/nix.conf")
''; '';
} }
)

View File

@@ -1,18 +1,16 @@
{ lib, self, ... }: { lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{ {
clan.modules = { clan.modules.users = module;
users = lib.modules.importApply ./default.nix { };
};
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) { clan.nixosTests.users = {
users = import ./tests/vm/default.nix { imports = [ ./tests/vm/default.nix ];
inherit pkgs;
clan-core = self; clan.modules."@clan/users" = module;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
}; };
}; };
} }

View File

@@ -1,67 +1,50 @@
{ {
pkgs, name = "users";
nixosLib,
clan-core,
...
}:
nixosLib.runTest ( clan = {
{ ... }: directory = ./.;
{ inventory = {
imports = [ machines.server = { };
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; instances = {
root-password-test = {
name = "users"; module.name = "@clan/users";
roles.default.machines."server".settings = {
clan = { user = "root";
directory = ./.; prompt = false;
modules."@clan/users" = ../../default.nix;
inventory = {
machines.server = { };
instances = {
root-password-test = {
module.name = "@clan/users";
roles.default.machines."server".settings = {
user = "root";
prompt = false;
};
}; };
user-password-test = { };
module.name = "@clan/users"; user-password-test = {
roles.default.machines."server".settings = { module.name = "@clan/users";
user = "testuser"; roles.default.machines."server".settings = {
prompt = false; user = "testuser";
}; prompt = false;
}; };
}; };
}; };
}; };
};
nodes = { nodes = {
server = { server = {
users.users.testuser.group = "testuser"; users.users.testuser.group = "testuser";
users.groups.testuser = { }; users.groups.testuser = { };
users.users.testuser.isNormalUser = true; users.users.testuser.isNormalUser = true;
};
}; };
};
testScript = '' testScript = ''
start_all() start_all()
server.wait_for_unit("multi-user.target") server.wait_for_unit("multi-user.target")
# Check that the testuser account exists # Check that the testuser account exists
server.succeed("id testuser") server.succeed("id testuser")
# Try to log in as the user using the generated password # Try to log in as the user using the generated password
# TODO: fix # TODO: fix
# password = server.succeed("cat /run/clan/vars/user-password/user-password").strip() # password = server.succeed("cat /run/clan/vars/user-password/user-password").strip()
# server.succeed(f"echo '{password}' | su - testuser -c 'echo Login successful'") # server.succeed(f"echo '{password}' | su - testuser -c 'echo Login successful'")
''; '';
} }
)

View File

@@ -1,6 +1,5 @@
{ {
self, self,
inputs,
lib, lib,
... ...
}: }:
@@ -10,28 +9,14 @@ let
}; };
in in
{ {
clan.modules = { clan.modules.wifi = module;
wifi = module;
};
perSystem = perSystem =
{ pkgs, ... }: { ... }:
{ {
/** clan.nixosTests.wifi = {
1. Prepare the test vars imports = [ ./tests/vm/default.nix ];
nix run .#generate-test-vars -- clanServices/hello-world/tests/vm hello-service
2. To run the test clan.modules."@clan/wifi" = module;
nix build .#checks.x86_64-linux.hello-service };
*/
checks =
# Currently we don't support nixos-integration tests on darwin
lib.optionalAttrs (pkgs.stdenv.isLinux) {
wifi-service = import ./tests/vm/default.nix {
inherit module;
inherit inputs pkgs;
clan-core = self;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
};
}; };
} }

View File

@@ -1,46 +1,29 @@
{ {
pkgs, name = "wifi";
nixosLib,
clan-core,
module,
...
}:
nixosLib.runTest (
{ ... }:
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
test.useContainers = false;
inventory = {
name = "wifi-service"; machines.test = { };
clan = { instances = {
directory = ./.; wg-test-one = {
test.useContainers = false; module.name = "@clan/wifi";
modules."@clan/wifi" = module;
inventory = {
machines.test = { }; roles.default.machines = {
test.settings.networks.one = { };
instances = {
wg-test-one = {
module.name = "@clan/wifi";
roles.default.machines = {
test.settings.networks.one = { };
};
}; };
}; };
}; };
}; };
};
testScript = '' testScript = ''
start_all() start_all()
test.wait_for_unit("NetworkManager.service") test.wait_for_unit("NetworkManager.service")
psk = test.succeed("cat /run/NetworkManager/system-connections/one.nmconnection") psk = test.succeed("cat /run/NetworkManager/system-connections/one.nmconnection")
assert "password-eins" in psk, "Password is incorrect" assert "password-eins" in psk, "Password is incorrect"
''; '';
} }
)

View File

@@ -8,9 +8,7 @@ let
module = lib.modules.importApply ./default.nix { }; module = lib.modules.importApply ./default.nix { };
in in
{ {
clan.modules = { clan.modules.zerotier = module;
zerotier = module;
};
perSystem = perSystem =
{ ... }: { ... }:
let let
@@ -28,11 +26,11 @@ in
imports = [ imports = [
unit-test-module unit-test-module
]; ];
# zerotier = import ./tests/vm/default.nix {
# inherit module; clan.nixosTests.zerotier = {
# inherit inputs pkgs; imports = [ ./tests/vm/default.nix ];
# clan-core = self;
# nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { }; clan.modules.zerotier = module;
# }; };
}; };
} }

View File

@@ -1,43 +1,27 @@
{ {
pkgs, name = "zerotier";
nixosLib,
clan-core,
module,
...
}:
nixosLib.runTest (
{ ... }:
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs; clan = {
directory = ./.;
inventory = {
name = "zerotier"; machines.jon = { };
machines.sara = { };
machines.bam = { };
clan = { instances = {
directory = ./.; "zerotier" = {
modules."zerotier" = module; module.name = "zerotier";
inventory = {
machines.jon = { }; roles.peer.tags.all = { };
machines.sara = { }; roles.controller.machines.bam = { };
machines.bam = { }; roles.moon.machines = { };
instances = {
"zerotier" = {
module.name = "zerotier";
roles.peer.tags.all = { };
roles.controller.machines.bam = { };
};
}; };
}; };
}; };
};
# This is not an actual vm test, this is a workaround to # This is not an actual vm test, this is a workaround to
# generate the needed vars for the eval test. # generate the needed vars for the eval test.
testScript = ''''; testScript = "";
} }
)

View File

@@ -1,6 +0,0 @@
[
{
"publickey": "age13ahclyps97532zt2sfta5zrfx976d3r2jmctj8d36vj9x5v5ffqq304fqf",
"type": "age"
}
]

View File

@@ -1,15 +0,0 @@
{
"data": "ENC[AES256_GCM,data:AGYme1x1pE7SVk6HowmIYMN3EHNaZglW97geihpDCkKqArq/zD2IHxbgo8OtXmaNws16i0R6LehWJTL21fVmnAEA9GNZQOE/Y4Q=,iv:Kc3bDcOwJmxHnnlBweUbqDE77VVFZFelEGpmpfBSct8=,tag:m4kzx3nOtexD91kisQafFw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTc2Q5NTY1ejl5ODhSOXhv\nVUFrb0xvblErWEY1R0k3UXNBQk5Ja1MwaERVCmdISk1RSGFUL2FRMWlPSFdERjB6\nalltcHZLd21XOVFuaExSRUNQc1VmdjAKLS0tIGg0ZGdvbm9wbC9Jd255cHNmVWxP\nWStOQS9EQW9WQUtLZVp5SDBmM1ByaEEKzviyWc0yLbDMwk/CHhTwntrjA5LX44Wu\nNdlsQG/yfRaqRL1TKZztT9RnX0293gOEZFvoYZasEJJAIeBoZvN6VQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-29T13:14:51Z",
"mac": "ENC[AES256_GCM,data:uCk2e5aFHZhttLkIdvDU3KARN7PiHKLtXsqxmuLkZP903XhDTCuj1GH6S0C9UN5LftlaVjCEaqlgx68cCNwTc9bTUnhSdVVjMWy0gjxKZ1Y25YzOMlEmOAk/TZqUvnMn/cUL8KOeBnymPbAeqLm8yATjwsyx5+GrFrIVxwGQzUA=,iv:UMX2Ik0xlcljMZyBhjOpvYcsJCC5Wb6d/rgbTFb+6oM=,tag:HH05tFDzOcRrQ8TTXxrDyw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -1 +0,0 @@
../../../users/admin

View File

@@ -1 +0,0 @@
../../../../../sops/machines/test

View File

@@ -1,19 +0,0 @@
{
"data": "ENC[AES256_GCM,data:iNOb,iv:24+bKY5u61JYsvLHV8TIUBVmJPV1aX/BJr//c7le68o=,tag:ANCOrzvnukvqyKGf+L8gFQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age13ahclyps97532zt2sfta5zrfx976d3r2jmctj8d36vj9x5v5ffqq304fqf",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxN2EwVHN3SENVTjdjZGRi\nQmJOWlNGYmpmM1BnZnpYWGhaSlRaUVJIODFRCkhhMUhyZzVWWk53SDBwSVBVZGVY\nVUpMTm9qWTIzc3VwdGJHcUVWVzFlV0UKLS0tIDBBVXdlS1FFbzNPSnlZWWtEaDJi\nK215OWQvMVRCRUZyQjFZckJFbHBZeDQK2cqgDnGM5uIm834dbQ3bi3nQA5nPq6Bf\n0+sezXuY55GdFS6OxIgI5/KcitHzDE0WHOvklIGDCSysoXIQ3QXanA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0NDB5SVcrU0V6akYwbDlv\na1BuSm5XbjYwN2ZkZWtIcnhBVHBTWGFxd24wCnZTVGlPRm5uZEd3QXYwdFRMS09K\nWWw5N2RJZ3d4N0VDMWZmM2lkYVM4VncKLS0tIGplTDVka1VoUVdXMU9VS3hYSlZ1\nRjZGL25hQWxHWEx3OXdQamJiNG9KaDgKk94uXPuCE/M4Hz/7hVKJPHuzQfbOQi/9\nVfR2i17Hjcq08l68Xzn+DllQEAFdts2fS96Pu4FFKfiLK7INl/fUOg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-29T13:15:02Z",
"mac": "ENC[AES256_GCM,data:4beXC5ONY5RLChluoVkklpDnaf/KCjlUzpQkFVSp7vauQmMKeTK40xqfvY5d+64u/OKRTIdc38KQTwhZ0pYzOv1LcJOWbHrGu7XadlALKgyUqKOZy03G2O8y0IF6t/LUK8TaNFnNvNteFsfD36/+wkRaxPJe7MKXGqPhWf6RC78=,iv:FR/PQUZqL3HnyVbW+H1QlZMmgFxA5juSb88wuatIlHM=,tag:parvZw3y9ZHieZ8pmUjCZQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -1 +0,0 @@
../../../../../sops/users/admin

View File

@@ -1 +0,0 @@
../../../../../sops/machines/test

View File

@@ -1,19 +0,0 @@
{
"data": "ENC[AES256_GCM,data:HHWyM9d6StpKc6uTxg==,iv:blDyfL/xSThCt+dhxeR5eOLa11OsIkbe+w4ReLBv754=,tag:qGHcDXS4DWdUIXUvtLc5XQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age13ahclyps97532zt2sfta5zrfx976d3r2jmctj8d36vj9x5v5ffqq304fqf",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPdkQyYnQ1UzlCWEFtdnJh\nMWlBK0RGcENTMmRITWM5SSs2Mkt2N0ZKdm5VClNTS0NuR05OVHY3QkFLZWt6bTUx\nMzJLc2Vib1ZUbW1VM0lhYXFFeEhOaEEKLS0tIHVoODVOK3BUU2JDZkJkN2I2Wm1L\nMWM0TUNQazljZS9uWXRKRFlxWmd0clUKg1YhJoRea05c24hCuZKYvqyvjuu965KD\nr4GLtyqQ6wt9sn50Rzx5cAY/Ac684DNFJVZ1RwG1NTB2kmXcVP8SJA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoZTA5QXpsOXR3L2FKcnJD\neUxzNVp3M2VQMFFaUUxwNXQ4UTlXa01rR0IwCjkyU2hmdlVYbWY4WUpVK0J1ZC9Q\nRjVkYWlGTlh1MFY3R3FxMEZHODZXMmcKLS0tIFV3bGdvUEtnT21wRWJveEQwdTBV\nbGFUUExBZWR1enQ0c0l0dUY3TnErM3cKutl5cv8dSlpQA7SXUYWJq1M0yLmko/Bx\nUvxxGGLQaK0Mp81Z5mOsjNhcVQrY160AyVnWJ0z39cqOJq9PpXRP+A==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-29T13:15:02Z",
"mac": "ENC[AES256_GCM,data:Y2FFQevNHSJrEtCmGHQXcpfyof0v2IF8ey79g7EfGj13An4ylhvogsVjRtfMkQvKD5GZykswZgmh+PmKUIzRoc+cvnMLu0iBzleYv+KzpYqtvUpdK0+NQn/4cKOoafajwNV7EuCQh+SkJgSGjNSbMs8xtIb4q9DmJyTcTbG0JQ4=,iv:xmA/cEhl/J0Z+8QR2GFiGWRw4aH/C4HmO+Qd4e25utw=,tag:/hG5S/EmRt8CjAy8DfBoqg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -1 +0,0 @@
../../../../../sops/users/admin

View File

@@ -71,6 +71,7 @@
./flakeModules/demo_iso.nix ./flakeModules/demo_iso.nix
./lib/filter-clan-core/flake-module.nix ./lib/filter-clan-core/flake-module.nix
./lib/flake-module.nix ./lib/flake-module.nix
./lib/flake-parts/clan-nixos-test.nix
./nixosModules/clanCore/vars/flake-module.nix ./nixosModules/clanCore/vars/flake-module.nix
./nixosModules/flake-module.nix ./nixosModules/flake-module.nix
./pkgs/flake-module.nix ./pkgs/flake-module.nix

View File

@@ -99,10 +99,18 @@ in
machine: machine:
flip mapAttrsToList machine.clan.core.vars.generators (_name: generator: generator.runtimeInputs); flip mapAttrsToList machine.clan.core.vars.generators (_name: generator: generator.runtimeInputs);
generatorScripts =
machine:
flip mapAttrsToList machine.clan.core.vars.generators (_name: generator: generator.finalScript);
generatorRuntimeInputs = unique ( generatorRuntimeInputs = unique (
flatten (flip mapAttrsToList config.nodes (_machineName: machine: inputsForMachine machine)) flatten (flip mapAttrsToList config.nodes (_machineName: machine: inputsForMachine machine))
); );
allGeneratorScripts = unique (
flatten (flip mapAttrsToList config.nodes (_machineName: machine: generatorScripts machine))
);
vars-check = vars-check =
hostPkgs.runCommand "update-vars-check-${testName}" hostPkgs.runCommand "update-vars-check-${testName}"
{ {
@@ -114,16 +122,19 @@ in
hostPkgs.bubblewrap hostPkgs.bubblewrap
]; ];
closureInfo = hostPkgs.closureInfo { closureInfo = hostPkgs.closureInfo {
rootPaths = generatorRuntimeInputs ++ [ rootPaths =
hostPkgs.bash generatorRuntimeInputs
hostPkgs.coreutils ++ allGeneratorScripts
hostPkgs.jq.dev ++ [
hostPkgs.stdenv hostPkgs.bash
hostPkgs.stdenvNoCC hostPkgs.coreutils
hostPkgs.shellcheck-minimal hostPkgs.jq.dev
hostPkgs.age hostPkgs.stdenv
hostPkgs.sops hostPkgs.stdenvNoCC
]; hostPkgs.shellcheck-minimal
hostPkgs.age
hostPkgs.sops
];
}; };
} }
'' ''
@@ -277,8 +288,6 @@ in
# Harder to handle advanced setups (like TPM, LUKS, or LVM-on-LUKS) but not needed since we are in a test # Harder to handle advanced setups (like TPM, LUKS, or LVM-on-LUKS) but not needed since we are in a test
# No systemd journal logs from initrd. # No systemd journal logs from initrd.
boot.initrd.systemd.enable = false; boot.initrd.systemd.enable = false;
# make the test depend on its vars-check derivation
environment.variables.CLAN_VARS_CHECK = "${vars-check}";
} }
); );

View File

@@ -0,0 +1,94 @@
{
lib,
flake-parts-lib,
self,
inputs,
...
}:
let
inherit (lib)
mkOption
types
;
inherit (flake-parts-lib)
mkPerSystemOption
;
nixosLib = import (inputs.nixpkgs + "/nixos/lib") { };
in
{
options = {
perSystem = mkPerSystemOption (
{ config, pkgs, ... }:
let
cfg = config.clan.nixosTests;
in
{
options.clan.nixosTests = mkOption {
description = "Clan NixOS tests configuration";
type = types.attrsOf types.unspecified;
default = { };
};
config.checks = lib.optionalAttrs (pkgs.stdenv.isLinux) (
let
# Build all individual vars-check derivations
varsChecks = lib.mapAttrs' (
name: testModule:
lib.nameValuePair "vars-check-${name}" (
let
test = nixosLib.runTest (
{ ... }:
{
imports = [
self.modules.nixosVmTest.clanTest
testModule
];
hostPkgs = pkgs;
defaults = {
imports = [
{
_module.args.clan-core = self;
}
];
};
}
);
in
test.config.result.vars-check
)
) cfg;
in
lib.mkMerge [
# Add the VM tests as checks
(lib.mapAttrs (
_name: testModule:
nixosLib.runTest (
{ ... }:
{
imports = [
self.modules.nixosVmTest.clanTest
testModule
];
hostPkgs = pkgs;
defaults = {
imports = [
{
_module.args.clan-core = self;
}
];
};
}
)
) cfg)
varsChecks
]
);
}
);
};
}