pytest: clan_flake allow usage of plain dicts

This commit is contained in:
Johannes Kirschbauer
2025-07-23 11:33:36 +02:00
parent 1dbaff7b61
commit 29c764773f
3 changed files with 50 additions and 19 deletions

View File

@@ -1,3 +1,4 @@
import json
import shutil
from collections.abc import Callable, Iterator
from contextlib import contextmanager
@@ -7,6 +8,7 @@ from typing import Any
import pytest
from clan_lib.clan.create import CreateOptions, create_clan
from clan_lib.flake.flake import Flake
from clan_lib.nix_models.clan import Clan
@pytest.fixture(scope="session")
@@ -18,8 +20,12 @@ def offline_template(tmp_path_factory: Any, offline_session_flake_hook: Any) ->
shutil.copytree(template, dst_dir, dirs_exist_ok=True, symlinks=True)
# Emtpy clan.nix file for evaluation of the template
clan_file = dst_dir / "clan.nix"
with (clan_file).open("w") as f:
clan_nix_file = dst_dir / "clan.nix"
with (clan_nix_file).open("w") as f:
f.write(r"""{ }""")
clan_json_file = dst_dir / "clan.json"
with (clan_json_file).open("w") as f:
f.write(r"""{ }""")
# expensive call ~6 seconds
@@ -46,9 +52,15 @@ def patch_clan_template(monkeypatch: Any, offline_template: Path) -> None:
@pytest.fixture()
def clan_flake(tmp_path: Path, patch_clan_template: Any) -> Callable[[str], Flake]:
def factory(clan_expr: str) -> Flake:
def clan_flake(
tmp_path: Path, patch_clan_template: Any
) -> Callable[[Clan | None, str | None], Flake]:
def factory(clan: Clan | None = None, raw: str | None = None) -> Flake:
# TODO: Make more options configurable
if clan is None and raw is None:
msg = "Either 'clan' or 'raw' must be provided to create a Flake."
raise ValueError(msg)
dest = tmp_path / "my-clan"
opts = CreateOptions(
dest,
@@ -57,8 +69,13 @@ def clan_flake(tmp_path: Path, patch_clan_template: Any) -> Callable[[str], Flak
)
create_clan(opts)
if clan is not None:
with (dest / "clan.json").open("w") as f:
f.write(json.dumps(clan))
if raw is not None:
with (dest / "clan.nix").open("w") as f:
f.write(clan_expr)
f.write(raw)
return Flake(str(dest))

View File

@@ -10,6 +10,8 @@
imports = [
./clan.nix
(builtins.fromJSON (builtins.readFile ./clan.json))
(
{ lib, ... }:
{

View File

@@ -1,22 +1,23 @@
from collections.abc import Callable
from typing import cast
import pytest
from clan_lib.flake import Flake
from clan_lib.nix_models.clan import Clan, Unknown
from .actions import list_machines
@pytest.mark.with_core
def test_list_nixos_machines(clan_flake: Callable[..., Flake]) -> None:
flake = clan_flake(r"""
{
machines = {
jon = { };
sara = { };
};
clan_config: Clan = {
"machines": {
"jon": cast(Unknown, {}), # Nixos Modules are not type checkable
"sara": cast(Unknown, {}), # Nixos Modules are not type checkable
}
""")
}
flake = clan_flake(clan_config)
machines = list_machines(flake)
@@ -25,15 +26,26 @@ def test_list_nixos_machines(clan_flake: Callable[..., Flake]) -> None:
@pytest.mark.with_core
def test_list_inventory_machines(clan_flake: Callable[..., Flake]) -> None:
flake = clan_flake(r"""
flake = clan_flake(
{
inventory.machines = {
jon = { };
sara = { };
"inventory": {
"machines": {
"jon": {},
"sara": {},
},
}
},
# Attention: This is a raw Nix expression, which is not type-checked in python
# Use with care!
raw=r"""
{
machines = {
vanessa = { pkgs, ...}: { environment.systemPackages = [ pkgs.firefox ]; }; # Raw NixosModule
};
}
""")
""",
)
machines = list_machines(flake)
assert list(machines.keys()) == ["jon", "sara"]
assert list(machines.keys()) == ["jon", "sara", "vanessa"]