inventory tests: add vars support

- Add support for leading vars
- Extend test to test for vars support
- Improve update-vars.py to take test name as argument
This commit is contained in:
DavHau
2025-04-08 20:23:57 +07:00
parent 39942ab3b4
commit 968fe4b64e
3 changed files with 88 additions and 12 deletions

View File

@@ -1,4 +1,4 @@
{ pkgs, ... }: { config, ... }:
{ {
systemd.services.dummy-service = { systemd.services.dummy-service = {
enable = true; enable = true;
@@ -6,8 +6,29 @@
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
ExecStart = "${pkgs.coreutils}/bin/true";
RemainAfterExit = true; RemainAfterExit = true;
}; };
script = ''
generated_password_path="${config.clan.core.vars.generators.dummy-generator.files.generated-password.path}"
if [ ! -f "$generated_password_path" ]; then
echo "Generated password file not found: $generated_password_path"
exit 1
fi
host_id_path="${config.clan.core.vars.generators.dummy-generator.files.host-id.path}"
if [ ! -e "$host_id_path" ]; then
echo "Host ID file not found: $host_id_path"
exit 1
fi
'';
};
# TODO: add and prompt and make it work in the test framework
clan.core.vars.generators.dummy-generator = {
files.host-id.secret = false;
files.generated-password.secret = true;
script = ''
echo $RANDOM > $out/host-id
echo $RANDOM > $out/generated-password
'';
}; };
} }

View File

@@ -47,6 +47,20 @@ in
documentation.enable = lib.mkDefault false; documentation.enable = lib.mkDefault false;
nix.settings.min-free = 0; nix.settings.min-free = 0;
system.stateVersion = config.system.nixos.release; 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" ];
};
} }
); );

View File

@@ -1,16 +1,17 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
import argparse
import json import json
import os import os
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Any from typing import Any
from clan_cli.flake import Flake from clan_cli.flake import Flake
from clan_cli.machines.machines import Machine from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_build, nix_config, nix_eval from clan_cli.nix import nix_build, nix_config, nix_eval
from clan_cli.vars.generate import generate_vars from clan_cli.vars.generate import generate_vars
from clan_cli.vars.keygen import keygen
if _project_root := os.environ.get("PRJ_ROOT"): if _project_root := os.environ.get("PRJ_ROOT"):
clan_core_dir = Path(_project_root) clan_core_dir = Path(_project_root)
@@ -18,7 +19,10 @@ else:
msg = "PRJ_ROOT not set. Enter the dev environment first" msg = "PRJ_ROOT not set. Enter the dev environment first"
raise Exception(msg) # noqa TRY002 raise Exception(msg) # noqa TRY002
test_name = "dummy-inventory-test" sops_priv_key = (
"AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV"
)
sops_pub_key = "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
def _test_dir(test_name: str) -> Path: def _test_dir(test_name: str) -> Path:
@@ -47,13 +51,17 @@ class TestMachine(Machine):
clan-core#checks.<system>.<test_name>.nodes.<machine_name>.<attr> clan-core#checks.<system>.<test_name>.nodes.<machine_name>.<attr>
""" """
def __init__(self, name: str, flake: Flake, test_name: str) -> None:
super().__init__(name, flake)
self.test_name = test_name
@property @property
def deployment(self) -> dict: def deployment(self) -> dict:
if getattr(self, "_deployment", None): if getattr(self, "_deployment", None):
return self._deployment return self._deployment
cmd = nix_build( cmd = nix_build(
[ [
f"{clan_core_dir}#checks.{nix_config()['system']}.{test_name}.nodes.{self.name}.system.clan.deployment.file" f"{clan_core_dir}#checks.{nix_config()['system']}.{self.test_name}.nodes.{self.name}.system.clan.deployment.file"
] ]
) )
out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE) out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE)
@@ -78,7 +86,7 @@ class TestMachine(Machine):
# return self.nix("eval", attr, nix_options) # return self.nix("eval", attr, nix_options)
cmd = nix_eval( cmd = nix_eval(
[ [
f"{clan_core_dir}#checks.{nix_config()['system']}.{test_name}.nodes.{self.name}.{attr}" f"{clan_core_dir}#checks.{nix_config()['system']}.{self.test_name}.nodes.{self.name}.{attr}"
] ]
) )
out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE) out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE)
@@ -100,7 +108,7 @@ class TestMachine(Machine):
cmd = nix_build( cmd = nix_build(
[ [
f"{clan_core_dir}#checks.{nix_config()['system']}.{test_name}.nodes.{self.name}.{attr}" f"{clan_core_dir}#checks.{nix_config()['system']}.{self.test_name}.nodes.{self.name}.{attr}"
] ]
) )
out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE) out = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE)
@@ -113,15 +121,48 @@ class TestMachine(Machine):
return return
def parse_args() -> argparse.Namespace:
import argparse
parser = argparse.ArgumentParser(
description="Update the vars of an inventory test",
)
parser.add_argument(
"test_name",
type=str,
help="The name of the test to update",
)
return parser.parse_args()
if __name__ == "__main__": if __name__ == "__main__":
os.environ["CLAN_NO_COMMIT"] = "1" os.environ["CLAN_NO_COMMIT"] = "1"
test_dir = _test_dir(test_name) args = parse_args()
test_dir = _test_dir(args.test_name)
subprocess.run(["rm", "-rf", f"{test_dir}/vars", f"{test_dir}/sops"]) subprocess.run(["rm", "-rf", f"{test_dir}/vars", f"{test_dir}/sops"])
flake = Flake(str(test_dir)) flake = Flake(str(test_dir))
flake._path = test_dir # noqa SLF001 flake._path = test_dir # noqa SLF001
flake._is_local = True # noqa SLF001 flake._is_local = True # noqa SLF001
machines = [TestMachine(name, flake) for name in machine_names(test_name)] machines = [
TestMachine(name, flake, args.test_name)
for name in machine_names(args.test_name)
]
user = "admin" user = "admin"
if not Path(flake.path / "sops" / "users" / user / "key.json").exists(): admin_key_path = Path(flake.path / "sops" / "users" / user / "key.json")
keygen(user, flake, False) admin_key_path.parent.mkdir(parents=True, exist_ok=True)
admin_key_path.write_text(
json.dumps(
{
"publickey": sops_pub_key,
"type": "age",
}
)
)
with NamedTemporaryFile("w") as f:
f.write("# created: 2023-07-17T10:51:45+02:00\n")
f.write(f"# public key: {sops_pub_key}\n")
f.write(sops_priv_key)
f.seek(0)
print(Path(f.name).read_text())
os.environ["SOPS_AGE_KEY_FILE"] = f.name
generate_vars(list(machines)) generate_vars(list(machines))