Merge pull request 'tests: improve performance, keep flake.lock between tests' (#2428) from DavHau/clan-core:DavHau-nix-eval into main

This commit is contained in:
clan-bot
2024-11-18 10:08:43 +00:00
5 changed files with 224 additions and 320 deletions

View File

@@ -4,9 +4,10 @@ import os
import shutil import shutil
import subprocess as sp import subprocess as sp
import tempfile import tempfile
from collections.abc import Iterator from collections import defaultdict
from collections.abc import Callable, Iterator
from pathlib import Path from pathlib import Path
from typing import NamedTuple from typing import Any, NamedTuple
import pytest import pytest
from clan_cli.dirs import nixpkgs_source from clan_cli.dirs import nixpkgs_source
@@ -16,6 +17,14 @@ from root import CLAN_CORE
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# allows defining nested dictionary in a single line
def def_value() -> defaultdict:
return defaultdict(def_value)
nested_dict: Callable[[], dict[str, Any]] = lambda: defaultdict(def_value)
# Substitutes strings in a file. # Substitutes strings in a file.
# This can be used on the flake.nix or default.nix of a machine # This can be used on the flake.nix or default.nix of a machine
def substitute( def substitute(
@@ -59,118 +68,152 @@ def set_machine_settings(
config_path.write_text(json.dumps(machine_settings, indent=2)) config_path.write_text(json.dumps(machine_settings, indent=2))
def init_git(monkeypatch: pytest.MonkeyPatch, flake: Path) -> None: def set_git_credentials(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("GIT_AUTHOR_NAME", "clan-tool") monkeypatch.setenv("GIT_AUTHOR_NAME", "clan-tool")
monkeypatch.setenv("GIT_AUTHOR_EMAIL", "clan@example.com") monkeypatch.setenv("GIT_AUTHOR_EMAIL", "clan@example.com")
monkeypatch.setenv("GIT_COMMITTER_NAME", "clan-tool") monkeypatch.setenv("GIT_COMMITTER_NAME", "clan-tool")
monkeypatch.setenv("GIT_COMMITTER_EMAIL", "clan@example.com") monkeypatch.setenv("GIT_COMMITTER_EMAIL", "clan@example.com")
def init_git(monkeypatch: pytest.MonkeyPatch, flake: Path) -> None:
set_git_credentials(monkeypatch)
sp.run(["git", "init", "-b", "main"], cwd=flake, check=True)
# TODO: Find out why test_vms_api.py fails in nix build # TODO: Find out why test_vms_api.py fails in nix build
# but works in pytest when this bottom line is commented out # but works in pytest when this bottom line is commented out
sp.run(
["git", "config", "--global", "init.defaultBranch", "main"],
cwd=flake,
check=True,
)
sp.run(["git", "init"], cwd=flake, check=True)
sp.run(["git", "add", "."], cwd=flake, check=True) sp.run(["git", "add", "."], cwd=flake, check=True)
sp.run(["git", "commit", "-a", "-m", "Initial commit"], cwd=flake, check=True) sp.run(["git", "commit", "-a", "-m", "Initial commit"], cwd=flake, check=True)
def generate_flake( class ClanFlake:
temporary_home: Path,
flake_template: Path,
monkeypatch: pytest.MonkeyPatch,
substitutions: dict[str, str] | None = None,
# define the machines directly including their config
machine_configs: dict[str, dict] | None = None,
inventory: dict[str, dict] | None = None,
clan_modules: list[str] | None = None,
) -> FlakeForTest:
""" """
Creates a clan flake with the given name. This class holds all attributes for generating a clan flake.
Machines are fully generated from the machine_configs. For example, inventory and machine configs can be set via self.inventory and self.machines["my_machine"] = {...}.
Whenever a flake's configuration is changed, it needs to be re-generated by calling refresh().
Example: This class can also be used for managing templates.
machine_configs = dict( Once initialized, all its settings including all generated files, if any, can be copied using the copy() method.
my_machine=dict( This avoids expensive re-computation, like for example creating the flake.lock over and over again.
clan=dict( """
core=dict(
backups=dict( def __init__(
... self,
) temporary_home: Path,
) flake_template: Path,
suppress_tmp_home_warning: bool = False,
) -> None:
self._flake_template = flake_template
self.inventory = nested_dict()
self.machines = nested_dict()
self.substitutions: dict[str, str] = {
"git+https://git.clan.lol/clan/clan-core": "path://" + str(CLAN_CORE),
"https://git.clan.lol/clan/clan-core/archive/main.tar.gz": "path://"
+ str(CLAN_CORE),
}
self.clan_modules: list[str] = []
self.temporary_home = temporary_home
self.path = temporary_home / "flake"
if not suppress_tmp_home_warning:
if "/tmp" not in str(os.environ.get("HOME")):
log.warning(
f"!! $HOME does not point to a temp directory!! HOME={os.environ['HOME']}"
) )
def copy(
self,
temporary_home: Path,
monkeypatch: pytest.MonkeyPatch,
) -> "ClanFlake":
# copy the files to the new location
shutil.copytree(self.path, temporary_home / "flake")
set_git_credentials(monkeypatch)
return ClanFlake(
temporary_home=temporary_home,
flake_template=self._flake_template,
)
def substitute(self) -> None:
for file in self.path.rglob("*"):
if ".git" in file.parts:
continue
if file.is_file():
buf = ""
with file.open() as f:
for line in f:
for key, value in self.substitutions.items():
line = line.replace(key, value)
buf += line
file.write_text(buf)
def init_from_template(self) -> None:
shutil.copytree(self._flake_template, self.path)
sp.run(["chmod", "+w", "-R", str(self.path)], check=True)
self.substitute()
if not (self.path / ".git").exists():
sp.run(
["nix", "flake", "lock"],
cwd=self.path,
check=True,
) )
) with pytest.MonkeyPatch.context() as mp:
""" init_git(mp, self.path)
if machine_configs is None:
machine_configs = {}
if inventory is None:
inventory = {}
if clan_modules is None:
clan_modules = []
substitutions = {
"git+https://git.clan.lol/clan/clan-core": "path://" + str(CLAN_CORE),
"https://git.clan.lol/clan/clan-core/archive/main.tar.gz": "path://"
+ str(CLAN_CORE),
}
flake = temporary_home / "flake"
shutil.copytree(flake_template, flake)
sp.run(["chmod", "+w", "-R", str(flake)], check=True)
# initialize inventory def refresh(self) -> None:
if inventory: if not self.path.exists():
# check if inventory valid self.init_from_template()
inventory_path = flake / "inventory.json" self.substitute()
inventory_path.write_text(json.dumps(inventory, indent=2)) if self.inventory:
inventory_path = self.path / "inventory.json"
# substitute `substitutions` in all files of the template inventory_path.write_text(json.dumps(self.inventory, indent=2))
for file in flake.rglob("*"):
if file.is_file():
print(f"Final Content of {file}:")
buf = ""
with file.open() as f:
for line in f:
for key, value in substitutions.items():
line = line.replace(key, value)
buf += line
file.write_text(buf)
# generate machines from machineConfigs
for machine_name, machine_config in machine_configs.items():
configuration_nix = flake / "machines" / machine_name / "configuration.nix"
configuration_nix.parent.mkdir(parents=True, exist_ok=True)
imports = "\n".join( imports = "\n".join(
[f"clan-core.clanModules.{module}" for module in clan_modules] [f"clan-core.clanModules.{module}" for module in self.clan_modules]
) )
configuration_nix.write_text(f""" for machine_name, machine_config in self.machines.items():
{{clan-core, ...}}: configuration_nix = (
{{ self.path / "machines" / machine_name / "configuration.nix"
imports = [ )
(builtins.fromJSON (builtins.readFile ./configuration.json)) configuration_nix.parent.mkdir(parents=True, exist_ok=True)
{imports} configuration_nix.write_text(f"""
]; {{clan-core, ...}}:
}} {{
""") imports = [
set_machine_settings(flake, machine_name, machine_config) (builtins.fromJSON (builtins.readFile ./configuration.json))
{imports}
if "/tmp" not in str(os.environ.get("HOME")): ];
log.warning( }}
f"!! $HOME does not point to a temp directory!! HOME={os.environ['HOME']}" """)
set_machine_settings(self.path, machine_name, machine_config)
sp.run(["git", "add", "."], cwd=self.path, check=True)
sp.run(
["git", "commit", "-a", "-m", "Update by flake generator"],
cwd=self.path,
check=True,
) )
# TODO: Find out why test_vms_api.py fails in nix build
# but works in pytest when this bottom line is commented out
sp.run(
["git", "config", "--global", "init.defaultBranch", "main"],
cwd=flake,
check=True,
)
init_git(monkeypatch, flake)
return FlakeForTest(flake) @pytest.fixture(scope="session")
def minimal_flake_template() -> Iterator[ClanFlake]:
with (
tempfile.TemporaryDirectory(prefix="flake-") as home,
pytest.MonkeyPatch.context() as mp,
):
mp.setenv("HOME", home)
flake = ClanFlake(
temporary_home=Path(home),
flake_template=CLAN_CORE / "templates" / "minimal",
)
flake.init_from_template()
yield flake
@pytest.fixture
def flake(
temporary_home: Path,
minimal_flake_template: ClanFlake,
monkeypatch: pytest.MonkeyPatch,
) -> ClanFlake:
return minimal_flake_template.copy(temporary_home, monkeypatch)
def create_flake( def create_flake(
@@ -274,21 +317,3 @@ def test_flake_with_core(
clan_core_flake=CLAN_CORE, clan_core_flake=CLAN_CORE,
monkeypatch=monkeypatch, monkeypatch=monkeypatch,
) )
@pytest.fixture
def test_local_democlan(
monkeypatch: pytest.MonkeyPatch, temporary_home: Path
) -> FlakeForTest:
democlan = os.getenv(key="DEMOCLAN_ROOT")
if democlan is None:
msg = (
"DEMOCLAN_ROOT not set. This test requires the democlan flake to be present"
)
raise FixtureError(msg)
democlan_p = Path(democlan).resolve()
if not democlan_p.is_dir():
msg = f"DEMOCLAN_ROOT ({democlan_p}) is not a directory. This test requires the democlan directory to be present"
raise FixtureError(msg)
return FlakeForTest(democlan_p)

View File

@@ -8,22 +8,25 @@ from clan_cli.machines.facts import machine_get_fact
from clan_cli.machines.machines import Machine from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_shell from clan_cli.nix import nix_shell
from clan_cli.ssh import HostGroup from clan_cli.ssh import HostGroup
from fixtures_flakes import generate_flake from fixtures_flakes import ClanFlake
from helpers import cli from helpers import cli
from helpers.nixos_config import nested_dict
from helpers.validator import is_valid_ssh_key from helpers.validator import is_valid_ssh_key
from root import CLAN_CORE
@pytest.mark.impure @pytest.mark.impure
def test_upload_secret( def test_upload_secret(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
flake: ClanFlake,
temporary_home: Path, temporary_home: Path,
host_group: HostGroup, host_group: HostGroup,
) -> None: ) -> None:
config = nested_dict() flake.clan_modules = [
"root-password",
"user-password",
"sshd",
]
config = flake.machines["vm1"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
# clan.core.networking.zerotier.controller.enable = true;
config["clan"]["core"]["networking"]["zerotier"]["controller"]["enable"] = True config["clan"]["core"]["networking"]["zerotier"]["controller"]["enable"] = True
host = host_group.hosts[0] host = host_group.hosts[0]
addr = f"{host.user}@{host.host}:{host.port}?StrictHostKeyChecking=no&UserKnownHostsFile=/dev/null&IdentityFile={host.key}" addr = f"{host.user}@{host.host}:{host.port}?StrictHostKeyChecking=no&UserKnownHostsFile=/dev/null&IdentityFile={host.key}"
@@ -38,17 +41,7 @@ def test_upload_secret(
) )
facts["secretUploadDirectory"]["priority"] = 50 facts["secretUploadDirectory"]["priority"] = 50
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"vm1": config},
clan_modules=[
"root-password",
"user-password",
"sshd",
],
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
gnupghome = temporary_home / "gpg" gnupghome = temporary_home / "gpg"
gnupghome.mkdir(mode=0o700) gnupghome.mkdir(mode=0o700)

View File

@@ -16,10 +16,8 @@ from clan_cli.vars.list import stringify_all_vars
from clan_cli.vars.public_modules import in_repo from clan_cli.vars.public_modules import in_repo
from clan_cli.vars.secret_modules import password_store, sops from clan_cli.vars.secret_modules import password_store, sops
from clan_cli.vars.set import set_var from clan_cli.vars.set import set_var
from fixtures_flakes import generate_flake, set_machine_settings from fixtures_flakes import ClanFlake
from helpers import cli from helpers import cli
from helpers.nixos_config import nested_dict
from root import CLAN_CORE
from stdout import CaptureOutput from stdout import CaptureOutput
@@ -80,19 +78,14 @@ def test_required_generators() -> None:
@pytest.mark.impure @pytest.mark.impure
def test_generate_public_var( def test_generate_public_var(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["script"] = "echo hello > $out/my_value" my_generator["script"] = "echo hello > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
assert not check_vars(machine) assert not check_vars(machine)
@@ -120,20 +113,15 @@ def test_generate_public_var(
@pytest.mark.impure @pytest.mark.impure
def test_generate_secret_var_sops( def test_generate_secret_var_sops(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_secret"]["secret"] = True my_generator["files"]["my_secret"]["secret"] = True
my_generator["script"] = "echo hello > $out/my_secret" my_generator["script"] = "echo hello > $out/my_secret"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
@@ -163,21 +151,16 @@ def test_generate_secret_var_sops(
@pytest.mark.impure @pytest.mark.impure
def test_generate_secret_var_sops_with_default_group( def test_generate_secret_var_sops_with_default_group(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
config["clan"]["core"]["sops"]["defaultGroups"] = ["my_group"] config["clan"]["core"]["sops"]["defaultGroups"] = ["my_group"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_secret"]["secret"] = True my_generator["files"]["my_secret"]["secret"] = True
my_generator["script"] = "echo hello > $out/my_secret" my_generator["script"] = "echo hello > $out/my_secret"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run(["secrets", "groups", "add-user", "my_group", sops_setup.user]) cli.run(["secrets", "groups", "add-user", "my_group", sops_setup.user])
@@ -221,10 +204,10 @@ def test_generate_secret_var_sops_with_default_group(
@pytest.mark.impure @pytest.mark.impure
def test_generated_shared_secret_sops( def test_generated_shared_secret_sops(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
m1_config = nested_dict() m1_config = flake.machines["machine1"]
m1_config["nixpkgs"]["hostPlatform"] = "x86_64-linux" m1_config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
shared_generator = m1_config["clan"]["core"]["vars"]["generators"][ shared_generator = m1_config["clan"]["core"]["vars"]["generators"][
"my_shared_generator" "my_shared_generator"
@@ -232,17 +215,12 @@ def test_generated_shared_secret_sops(
shared_generator["share"] = True shared_generator["share"] = True
shared_generator["files"]["my_shared_secret"]["secret"] = True shared_generator["files"]["my_shared_secret"]["secret"] = True
shared_generator["script"] = "echo hello > $out/my_shared_secret" shared_generator["script"] = "echo hello > $out/my_shared_secret"
m2_config = nested_dict() m2_config = flake.machines["machine2"]
m2_config["nixpkgs"]["hostPlatform"] = "x86_64-linux" m2_config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
m2_config["clan"]["core"]["vars"]["generators"]["my_shared_generator"] = ( m2_config["clan"]["core"]["vars"]["generators"]["my_shared_generator"] = (
shared_generator.copy() shared_generator.copy()
) )
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"machine1": m1_config, "machine2": m2_config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
machine1 = Machine(name="machine1", flake=FlakeId(str(flake.path))) machine1 = Machine(name="machine1", flake=FlakeId(str(flake.path)))
@@ -267,10 +245,10 @@ def test_generated_shared_secret_sops(
@pytest.mark.impure @pytest.mark.impure
def test_generate_secret_var_password_store( def test_generate_secret_var_password_store(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
test_root: Path, test_root: Path,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
config["clan"]["core"]["vars"]["settings"]["secretStore"] = "password-store" config["clan"]["core"]["vars"]["settings"]["secretStore"] = "password-store"
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
@@ -282,20 +260,15 @@ def test_generate_secret_var_password_store(
my_shared_generator["share"] = True my_shared_generator["share"] = True
my_shared_generator["files"]["my_shared_secret"]["secret"] = True my_shared_generator["files"]["my_shared_secret"]["secret"] = True
my_shared_generator["script"] = "echo hello > $out/my_shared_secret" my_shared_generator["script"] = "echo hello > $out/my_shared_secret"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
gnupghome = temporary_home / "gpg" gnupghome = flake.path / "gpg"
shutil.copytree(test_root / "data" / "gnupg-home", gnupghome) shutil.copytree(test_root / "data" / "gnupg-home", gnupghome)
monkeypatch.setenv("GNUPGHOME", str(gnupghome)) monkeypatch.setenv("GNUPGHOME", str(gnupghome))
password_store_dir = temporary_home / "pass" password_store_dir = flake.path / "pass"
shutil.copytree(test_root / "data" / "password-store", password_store_dir) shutil.copytree(test_root / "data" / "password-store", password_store_dir)
monkeypatch.setenv("PASSWORD_STORE_DIR", str(temporary_home / "pass")) monkeypatch.setenv("PASSWORD_STORE_DIR", str(flake.path / "pass"))
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
assert not check_vars(machine) assert not check_vars(machine)
@@ -316,10 +289,10 @@ def test_generate_secret_var_password_store(
@pytest.mark.impure @pytest.mark.impure
def test_generate_secret_for_multiple_machines( def test_generate_secret_for_multiple_machines(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
machine1_config = nested_dict() machine1_config = flake.machines["machine1"]
machine1_generator = machine1_config["clan"]["core"]["vars"]["generators"][ machine1_generator = machine1_config["clan"]["core"]["vars"]["generators"][
"my_generator" "my_generator"
] ]
@@ -328,7 +301,7 @@ def test_generate_secret_for_multiple_machines(
machine1_generator["script"] = ( machine1_generator["script"] = (
"echo machine1 > $out/my_secret && echo machine1 > $out/my_value" "echo machine1 > $out/my_secret && echo machine1 > $out/my_value"
) )
machine2_config = nested_dict() machine2_config = flake.machines["machine2"]
machine2_generator = machine2_config["clan"]["core"]["vars"]["generators"][ machine2_generator = machine2_config["clan"]["core"]["vars"]["generators"][
"my_generator" "my_generator"
] ]
@@ -337,12 +310,7 @@ def test_generate_secret_for_multiple_machines(
machine2_generator["script"] = ( machine2_generator["script"] = (
"echo machine2 > $out/my_secret && echo machine2 > $out/my_value" "echo machine2 > $out/my_secret && echo machine2 > $out/my_value"
) )
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"machine1": machine1_config, "machine2": machine2_config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run(["vars", "generate", "--flake", str(flake.path)]) cli.run(["vars", "generate", "--flake", str(flake.path)])
@@ -373,9 +341,9 @@ def test_generate_secret_for_multiple_machines(
@pytest.mark.impure @pytest.mark.impure
def test_dependant_generators( def test_dependant_generators(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
parent_gen = config["clan"]["core"]["vars"]["generators"]["parent_generator"] parent_gen = config["clan"]["core"]["vars"]["generators"]["parent_generator"]
parent_gen["files"]["my_value"]["secret"] = False parent_gen["files"]["my_value"]["secret"] = False
parent_gen["script"] = "echo hello > $out/my_value" parent_gen["script"] = "echo hello > $out/my_value"
@@ -383,12 +351,7 @@ def test_dependant_generators(
child_gen["files"]["my_value"]["secret"] = False child_gen["files"]["my_value"]["secret"] = False
child_gen["dependencies"] = ["parent_generator"] child_gen["dependencies"] = ["parent_generator"]
child_gen["script"] = "cat $in/parent_generator/my_value > $out/my_value" child_gen["script"] = "cat $in/parent_generator/my_value > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
in_repo_store = in_repo.FactStore( in_repo_store = in_repo.FactStore(
@@ -412,23 +375,18 @@ def test_dependant_generators(
) )
def test_prompt( def test_prompt(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
prompt_type: str, prompt_type: str,
input_value: str, input_value: str,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["prompts"]["prompt1"]["description"] = "dream2nix" my_generator["prompts"]["prompt1"]["description"] = "dream2nix"
my_generator["prompts"]["prompt1"]["createFile"] = False my_generator["prompts"]["prompt1"]["createFile"] = False
my_generator["prompts"]["prompt1"]["type"] = prompt_type my_generator["prompts"]["prompt1"]["type"] = prompt_type
my_generator["script"] = "cat $prompts/prompt1 > $out/my_value" my_generator["script"] = "cat $prompts/prompt1 > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
monkeypatch.setattr("sys.stdin", StringIO(input_value)) monkeypatch.setattr("sys.stdin", StringIO(input_value))
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
@@ -442,10 +400,10 @@ def test_prompt(
@pytest.mark.impure @pytest.mark.impure
def test_share_flag( def test_share_flag(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
shared_generator = config["clan"]["core"]["vars"]["generators"]["shared_generator"] shared_generator = config["clan"]["core"]["vars"]["generators"]["shared_generator"]
shared_generator["share"] = True shared_generator["share"] = True
@@ -463,12 +421,7 @@ def test_share_flag(
unshared_generator["script"] = ( unshared_generator["script"] = (
"echo hello > $out/my_secret && echo hello > $out/my_value" "echo hello > $out/my_secret && echo hello > $out/my_value"
) )
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
@@ -504,10 +457,10 @@ def test_share_flag(
@pytest.mark.impure @pytest.mark.impure
def test_depending_on_shared_secret_succeeds( def test_depending_on_shared_secret_succeeds(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
shared_generator = config["clan"]["core"]["vars"]["generators"]["shared_generator"] shared_generator = config["clan"]["core"]["vars"]["generators"]["shared_generator"]
shared_generator["share"] = True shared_generator["share"] = True
shared_generator["files"]["my_secret"]["secret"] = True shared_generator["files"]["my_secret"]["secret"] = True
@@ -521,12 +474,7 @@ def test_depending_on_shared_secret_succeeds(
dependent_generator["script"] = ( dependent_generator["script"] = (
"cat $in/shared_generator/my_secret > $out/my_secret" "cat $in/shared_generator/my_secret > $out/my_secret"
) )
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
@@ -535,22 +483,17 @@ def test_depending_on_shared_secret_succeeds(
@pytest.mark.impure @pytest.mark.impure
def test_prompt_create_file( def test_prompt_create_file(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
""" """
Test that the createFile flag in the prompt configuration works as expected Test that the createFile flag in the prompt configuration works as expected
""" """
config = nested_dict() config = flake.machines["my_machine"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["prompts"]["prompt1"]["createFile"] = True my_generator["prompts"]["prompt1"]["createFile"] = True
my_generator["prompts"]["prompt2"]["createFile"] = False my_generator["prompts"]["prompt2"]["createFile"] = False
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
monkeypatch.setattr("sys.stdin", StringIO("input1\ninput2\n")) monkeypatch.setattr("sys.stdin", StringIO("input1\ninput2\n"))
@@ -566,20 +509,15 @@ def test_prompt_create_file(
@pytest.mark.impure @pytest.mark.impure
def test_api_get_prompts( def test_api_get_prompts(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
) -> None: ) -> None:
from clan_cli.vars.list import get_prompts from clan_cli.vars.list import get_prompts
config = nested_dict() config = flake.machines["my_machine"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["prompts"]["prompt1"]["type"] = "line" my_generator["prompts"]["prompt1"]["type"] = "line"
my_generator["files"]["prompt1"]["secret"] = False my_generator["files"]["prompt1"]["secret"] = False
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
monkeypatch.setattr("sys.stdin", StringIO("input1")) monkeypatch.setattr("sys.stdin", StringIO("input1"))
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
@@ -594,21 +532,16 @@ def test_api_get_prompts(
@pytest.mark.impure @pytest.mark.impure
def test_api_set_prompts( def test_api_set_prompts(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
) -> None: ) -> None:
from clan_cli.vars._types import GeneratorUpdate from clan_cli.vars._types import GeneratorUpdate
from clan_cli.vars.list import set_prompts from clan_cli.vars.list import set_prompts
config = nested_dict() config = flake.machines["my_machine"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["prompts"]["prompt1"]["type"] = "line" my_generator["prompts"]["prompt1"]["type"] = "line"
my_generator["files"]["prompt1"]["secret"] = False my_generator["files"]["prompt1"]["secret"] = False
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
set_prompts( set_prompts(
@@ -638,10 +571,10 @@ def test_api_set_prompts(
@pytest.mark.impure @pytest.mark.impure
def test_commit_message( def test_commit_message(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["script"] = "echo hello > $out/my_value" my_generator["script"] = "echo hello > $out/my_value"
@@ -650,12 +583,7 @@ def test_commit_message(
] ]
my_secret_generator["files"]["my_secret"]["secret"] = True my_secret_generator["files"]["my_secret"]["secret"] = True
my_secret_generator["script"] = "echo hello > $out/my_secret" my_secret_generator["script"] = "echo hello > $out/my_secret"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run( cli.run(
@@ -700,9 +628,9 @@ def test_commit_message(
@pytest.mark.impure @pytest.mark.impure
def test_default_value( def test_default_value(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
@@ -710,12 +638,7 @@ def test_default_value(
my_generator["files"]["my_value"]["value"]["priority"] = 1000 # mkDefault my_generator["files"]["my_value"]["value"]["priority"] = 1000 # mkDefault
my_generator["files"]["my_value"]["value"]["content"] = "foo" my_generator["files"]["my_value"]["value"]["content"] = "foo"
my_generator["script"] = "echo -n hello > $out/my_value" my_generator["script"] = "echo -n hello > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
# ensure evaluating the default value works without generating the value # ensure evaluating the default value works without generating the value
value_eval = run( value_eval = run(
@@ -742,11 +665,11 @@ def test_default_value(
@pytest.mark.impure @pytest.mark.impure
def test_stdout_of_generate( def test_stdout_of_generate(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
capture_output: CaptureOutput, capture_output: CaptureOutput,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
@@ -756,12 +679,7 @@ def test_stdout_of_generate(
] ]
my_secret_generator["files"]["my_secret"]["secret"] = True my_secret_generator["files"]["my_secret"]["secret"] = True
my_secret_generator["script"] = "echo -n hello > $out/my_secret" my_secret_generator["script"] = "echo -n hello > $out/my_secret"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
from clan_cli.vars.generate import generate_vars_for_machine from clan_cli.vars.generate import generate_vars_for_machine
@@ -828,10 +746,10 @@ def test_stdout_of_generate(
@pytest.mark.impure @pytest.mark.impure
def test_migration_skip( def test_migration_skip(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_service = config["clan"]["core"]["facts"]["services"]["my_service"] my_service = config["clan"]["core"]["facts"]["services"]["my_service"]
my_service["secret"]["my_value"] = {} my_service["secret"]["my_value"] = {}
@@ -841,12 +759,7 @@ def test_migration_skip(
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["migrateFact"] = "my_service" my_generator["migrateFact"] = "my_service"
my_generator["script"] = "echo -n world > $out/my_value" my_generator["script"] = "echo -n world > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run(["facts", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["facts", "generate", "--flake", str(flake.path), "my_machine"])
@@ -861,10 +774,10 @@ def test_migration_skip(
@pytest.mark.impure @pytest.mark.impure
def test_migration( def test_migration(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_service = config["clan"]["core"]["facts"]["services"]["my_service"] my_service = config["clan"]["core"]["facts"]["services"]["my_service"]
my_service["public"]["my_value"] = {} my_service["public"]["my_value"] = {}
@@ -873,12 +786,7 @@ def test_migration(
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["migrateFact"] = "my_service" my_generator["migrateFact"] = "my_service"
my_generator["script"] = "echo -n world > $out/my_value" my_generator["script"] = "echo -n world > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
cli.run(["facts", "generate", "--flake", str(flake.path), "my_machine"]) cli.run(["facts", "generate", "--flake", str(flake.path), "my_machine"])
@@ -893,10 +801,10 @@ def test_migration(
@pytest.mark.impure @pytest.mark.impure
def test_fails_when_files_are_left_from_other_backend( def test_fails_when_files_are_left_from_other_backend(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
temporary_home: Path, flake: ClanFlake,
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
config = nested_dict() config = flake.machines["my_machine"]
config["nixpkgs"]["hostPlatform"] = "x86_64-linux" config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
my_secret_generator = config["clan"]["core"]["vars"]["generators"][ my_secret_generator = config["clan"]["core"]["vars"]["generators"][
"my_secret_generator" "my_secret_generator"
@@ -908,12 +816,7 @@ def test_fails_when_files_are_left_from_other_backend(
] ]
my_value_generator["files"]["my_value"]["secret"] = False my_value_generator["files"]["my_value"]["secret"] = False
my_value_generator["script"] = "echo hello > $out/my_value" my_value_generator["script"] = "echo hello > $out/my_value"
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
sops_setup.init() sops_setup.init()
for generator in ["my_secret_generator", "my_value_generator"]: for generator in ["my_secret_generator", "my_value_generator"]:
@@ -925,7 +828,7 @@ def test_fails_when_files_are_left_from_other_backend(
) )
my_secret_generator["files"]["my_secret"]["secret"] = False my_secret_generator["files"]["my_secret"]["secret"] = False
my_value_generator["files"]["my_value"]["secret"] = True my_value_generator["files"]["my_value"]["secret"] = True
set_machine_settings(flake.path, "my_machine", config) flake.refresh()
monkeypatch.chdir(flake.path) monkeypatch.chdir(flake.path)
for generator in ["my_secret_generator", "my_value_generator"]: for generator in ["my_secret_generator", "my_value_generator"]:
with pytest.raises(ClanError): with pytest.raises(ClanError):

View File

@@ -1,6 +1,5 @@
import json import json
from contextlib import ExitStack from contextlib import ExitStack
from pathlib import Path
import pytest import pytest
from age_keys import SopsSetup from age_keys import SopsSetup
@@ -9,22 +8,19 @@ from clan_cli.clan_uri import FlakeId
from clan_cli.machines.machines import Machine from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_eval, run from clan_cli.nix import nix_eval, run
from clan_cli.vms.run import inspect_vm, spawn_vm from clan_cli.vms.run import inspect_vm, spawn_vm
from fixtures_flakes import generate_flake from fixtures_flakes import ClanFlake
from helpers import cli from helpers import cli
from helpers.nixos_config import nested_dict
from nix_config import ConfigItem from nix_config import ConfigItem
from root import CLAN_CORE
@pytest.mark.impure @pytest.mark.impure
def test_vm_deployment( def test_vm_deployment(
monkeypatch: pytest.MonkeyPatch, flake: ClanFlake,
temporary_home: Path,
nix_config: dict[str, ConfigItem], nix_config: dict[str, ConfigItem],
sops_setup: SopsSetup, sops_setup: SopsSetup,
) -> None: ) -> None:
# machine 1 # machine 1
machine1_config = nested_dict() machine1_config = flake.machines["m1_machine"]
machine1_config["nixpkgs"]["hostPlatform"] = nix_config["system"].value machine1_config["nixpkgs"]["hostPlatform"] = nix_config["system"].value
machine1_config["clan"]["virtualisation"]["graphics"] = False machine1_config["clan"]["virtualisation"]["graphics"] = False
machine1_config["services"]["getty"]["autologinUser"] = "root" machine1_config["services"]["getty"]["autologinUser"] = "root"
@@ -50,7 +46,7 @@ def test_vm_deployment(
echo hello > $out/no_deploy_secret echo hello > $out/no_deploy_secret
""" """
# machine 2 # machine 2
machine2_config = nested_dict() machine2_config = flake.machines["m2_machine"]
machine2_config["nixpkgs"]["hostPlatform"] = nix_config["system"].value machine2_config["nixpkgs"]["hostPlatform"] = nix_config["system"].value
machine2_config["clan"]["virtualisation"]["graphics"] = False machine2_config["clan"]["virtualisation"]["graphics"] = False
machine2_config["services"]["getty"]["autologinUser"] = "root" machine2_config["services"]["getty"]["autologinUser"] = "root"
@@ -63,12 +59,7 @@ def test_vm_deployment(
m1_shared_generator.copy() m1_shared_generator.copy()
) )
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs={"m1_machine": machine1_config, "m2_machine": machine2_config},
)
sops_setup.init(flake.path) sops_setup.init(flake.path)
cli.run(["vars", "generate", "--flake", str(flake.path)]) cli.run(["vars", "generate", "--flake", str(flake.path)])

View File

@@ -5,10 +5,8 @@ import pytest
from clan_cli.clan_uri import FlakeId from clan_cli.clan_uri import FlakeId
from clan_cli.machines.machines import Machine from clan_cli.machines.machines import Machine
from clan_cli.vms.run import inspect_vm, spawn_vm from clan_cli.vms.run import inspect_vm, spawn_vm
from fixtures_flakes import FlakeForTest, generate_flake from fixtures_flakes import ClanFlake, FlakeForTest
from helpers import cli from helpers import cli
from helpers.nixos_config import nested_dict
from root import CLAN_CORE
from stdout import CaptureOutput from stdout import CaptureOutput
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -59,33 +57,27 @@ def test_run(
@pytest.mark.skipif(no_kvm, reason="Requires KVM") @pytest.mark.skipif(no_kvm, reason="Requires KVM")
@pytest.mark.impure @pytest.mark.impure
def test_vm_persistence( def test_vm_persistence(
monkeypatch: pytest.MonkeyPatch, flake: ClanFlake,
temporary_home: Path,
) -> None: ) -> None:
# set up a clan flake with some systemd services to test persistence # set up a clan flake with some systemd services to test persistence
config = nested_dict() config = flake.machines["my_machine"]
# logrotate-checkconf doesn't work in VM because /nix/store is owned by nobody # logrotate-checkconf doesn't work in VM because /nix/store is owned by nobody
config["my_machine"]["systemd"]["services"]["logrotate-checkconf"]["enable"] = False config["systemd"]["services"]["logrotate-checkconf"]["enable"] = False
config["my_machine"]["services"]["getty"]["autologinUser"] = "root" config["services"]["getty"]["autologinUser"] = "root"
config["my_machine"]["clan"]["virtualisation"] = {"graphics": False} config["clan"]["virtualisation"] = {"graphics": False}
config["my_machine"]["clan"]["core"]["networking"] = {"targetHost": "client"} config["clan"]["core"]["networking"] = {"targetHost": "client"}
config["my_machine"]["clan"]["core"]["state"]["my_state"]["folders"] = [ config["clan"]["core"]["state"]["my_state"]["folders"] = [
# to be owned by root # to be owned by root
"/var/my-state", "/var/my-state",
# to be owned by user 'test' # to be owned by user 'test'
"/var/user-state", "/var/user-state",
] ]
config["my_machine"]["users"]["users"] = { config["users"]["users"] = {
"test": {"initialPassword": "test", "isSystemUser": True, "group": "users"}, "test": {"initialPassword": "test", "isSystemUser": True, "group": "users"},
"root": {"initialPassword": "root"}, "root": {"initialPassword": "root"},
} }
flake = generate_flake( flake.refresh()
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
monkeypatch=monkeypatch,
machine_configs=config,
)
vm_config = inspect_vm(machine=Machine("my_machine", FlakeId(str(flake.path)))) vm_config = inspect_vm(machine=Machine("my_machine", FlakeId(str(flake.path))))