Merge pull request 'test(clan/inventory): test deserialization of different inventories' (#3258) from hsjobeki/clan-core:inventory-serde into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3258
This commit is contained in:
@@ -39,6 +39,7 @@ def substitute(
|
|||||||
file: Path,
|
file: Path,
|
||||||
clan_core_flake: Path | None = None,
|
clan_core_flake: Path | None = None,
|
||||||
flake: Path = Path(__file__).parent,
|
flake: Path = Path(__file__).parent,
|
||||||
|
inventory_expr: str = r"{}",
|
||||||
) -> None:
|
) -> None:
|
||||||
sops_key = str(flake.joinpath("sops.key"))
|
sops_key = str(flake.joinpath("sops.key"))
|
||||||
buf = ""
|
buf = ""
|
||||||
@@ -54,6 +55,7 @@ def substitute(
|
|||||||
"https://git.clan.lol/clan/clan-core/archive/main.tar.gz",
|
"https://git.clan.lol/clan/clan-core/archive/main.tar.gz",
|
||||||
f"path:{clan_core_flake}",
|
f"path:{clan_core_flake}",
|
||||||
)
|
)
|
||||||
|
line = line.replace("__INVENTORY_EXPR__", str(inventory_expr))
|
||||||
line = line.replace("__CLAN_SOPS_KEY_PATH__", sops_key)
|
line = line.replace("__CLAN_SOPS_KEY_PATH__", sops_key)
|
||||||
line = line.replace("__CLAN_SOPS_KEY_DIR__", str(flake / "facts"))
|
line = line.replace("__CLAN_SOPS_KEY_DIR__", str(flake / "facts"))
|
||||||
buf += line
|
buf += line
|
||||||
@@ -252,6 +254,7 @@ def create_flake(
|
|||||||
machines: list[str] | None = None,
|
machines: list[str] | None = None,
|
||||||
# alternatively specify the machines directly including their config
|
# alternatively specify the machines directly including their config
|
||||||
machine_configs: dict[str, dict] | None = None,
|
machine_configs: dict[str, dict] | None = None,
|
||||||
|
inventory_expr: str = r"{}",
|
||||||
) -> Iterator[FlakeForTest]:
|
) -> Iterator[FlakeForTest]:
|
||||||
"""
|
"""
|
||||||
Creates a flake with the given name and machines.
|
Creates a flake with the given name and machines.
|
||||||
@@ -279,7 +282,11 @@ def create_flake(
|
|||||||
for machine_name in machines:
|
for machine_name in machines:
|
||||||
machine_path = Path(__file__).parent / "machines" / machine_name
|
machine_path = Path(__file__).parent / "machines" / machine_name
|
||||||
shutil.copytree(machine_path, flake / "machines" / machine_name)
|
shutil.copytree(machine_path, flake / "machines" / machine_name)
|
||||||
substitute(flake / "machines" / machine_name / "default.nix", flake)
|
substitute(
|
||||||
|
flake / "machines" / machine_name / "default.nix",
|
||||||
|
flake,
|
||||||
|
inventory_expr=inventory_expr,
|
||||||
|
)
|
||||||
|
|
||||||
# generate machines from machineConfigs
|
# generate machines from machineConfigs
|
||||||
for machine_name, machine_config in machine_configs.items():
|
for machine_name, machine_config in machine_configs.items():
|
||||||
@@ -291,7 +298,7 @@ def create_flake(
|
|||||||
# provided by get_test_flake_toplevel
|
# provided by get_test_flake_toplevel
|
||||||
flake_nix = flake / "flake.nix"
|
flake_nix = flake / "flake.nix"
|
||||||
# this is where we would install the sops key to, when updating
|
# this is where we would install the sops key to, when updating
|
||||||
substitute(flake_nix, clan_core_flake, flake)
|
substitute(flake_nix, clan_core_flake, flake, inventory_expr=inventory_expr)
|
||||||
nix_options = []
|
nix_options = []
|
||||||
if tmp_store := nix_test_store():
|
if tmp_store := nix_test_store():
|
||||||
nix_options += ["--store", str(tmp_store)]
|
nix_options += ["--store", str(tmp_store)]
|
||||||
@@ -345,8 +352,12 @@ def test_flake(
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def test_flake_with_core(
|
def test_flake_with_core(
|
||||||
monkeypatch: pytest.MonkeyPatch, temporary_home: Path
|
request: pytest.FixtureRequest,
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
temporary_home: Path,
|
||||||
) -> Iterator[FlakeForTest]:
|
) -> Iterator[FlakeForTest]:
|
||||||
|
test_params = getattr(request, "param", {}) # Default if not parametrized
|
||||||
|
inventory_expr = test_params.get("inventory_expr", r"{}") # Default empty inventory
|
||||||
if not (CLAN_CORE / "flake.nix").exists():
|
if not (CLAN_CORE / "flake.nix").exists():
|
||||||
msg = "clan-core flake not found. This test requires the clan-core flake to be present"
|
msg = "clan-core flake not found. This test requires the clan-core flake to be present"
|
||||||
raise FixtureError(msg)
|
raise FixtureError(msg)
|
||||||
@@ -355,4 +366,5 @@ def test_flake_with_core(
|
|||||||
flake_template="test_flake_with_core",
|
flake_template="test_flake_with_core",
|
||||||
clan_core_flake=CLAN_CORE,
|
clan_core_flake=CLAN_CORE,
|
||||||
monkeypatch=monkeypatch,
|
monkeypatch=monkeypatch,
|
||||||
|
inventory_expr=inventory_expr,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
clan = clan-core.clanLib.buildClan {
|
clan = clan-core.clanLib.buildClan {
|
||||||
inherit self;
|
inherit self;
|
||||||
meta.name = "test_flake_with_core";
|
meta.name = "test_flake_with_core";
|
||||||
|
# Don't quote this will be replaced by the inventory expression
|
||||||
|
# Not a string!
|
||||||
|
inventory = __INVENTORY_EXPR__;
|
||||||
machines = {
|
machines = {
|
||||||
vm1 =
|
vm1 =
|
||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
|
|||||||
56
pkgs/clan-cli/clan_cli/tests/test_inventory_serde.py
Normal file
56
pkgs/clan-cli/clan_cli/tests/test_inventory_serde.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# Functions to test
|
||||||
|
from clan_cli.inventory import load_inventory_eval
|
||||||
|
from clan_cli.tests.fixtures_flakes import FlakeForTest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"test_flake_with_core",
|
||||||
|
[
|
||||||
|
# Emtpy inventory
|
||||||
|
{"inventory_expr": r"{ }"},
|
||||||
|
# Empty machines
|
||||||
|
{
|
||||||
|
"inventory_expr": r"""{
|
||||||
|
machines.jon = {};
|
||||||
|
machines.sara = {};
|
||||||
|
}"""
|
||||||
|
},
|
||||||
|
# TODO: Test
|
||||||
|
# - Function modules
|
||||||
|
# - Instances with non-deserializable settings ?
|
||||||
|
# - Tags function modules
|
||||||
|
# -
|
||||||
|
# {
|
||||||
|
# "inventory_expr": r"""{
|
||||||
|
# modules.messager = { ... }: { };
|
||||||
|
# }"""
|
||||||
|
# },
|
||||||
|
],
|
||||||
|
# Important!
|
||||||
|
# tells pytest to pass these values to the fixture
|
||||||
|
# So we can write it to the flake fixtures
|
||||||
|
indirect=True,
|
||||||
|
)
|
||||||
|
@pytest.mark.with_core
|
||||||
|
def test_inventory_deserialize_variants(
|
||||||
|
test_flake_with_core: FlakeForTest,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Testing different inventory deserializations
|
||||||
|
Inventory should always be deserializable to a dict
|
||||||
|
"""
|
||||||
|
inventory: dict[str, Any] = load_inventory_eval(test_flake_with_core.path) # type: ignore
|
||||||
|
# Check that the inventory is a dict
|
||||||
|
assert isinstance(inventory, dict)
|
||||||
|
|
||||||
|
# Check that all keys are present
|
||||||
|
assert "meta" in inventory
|
||||||
|
assert "machines" in inventory
|
||||||
|
assert "services" in inventory
|
||||||
|
assert "tags" in inventory
|
||||||
|
assert "modules" in inventory
|
||||||
|
assert "instances" in inventory
|
||||||
Reference in New Issue
Block a user