VMs: port vm_persistence test to python

This commit is contained in:
DavHau
2024-01-09 14:47:02 +07:00
parent b272eebc75
commit 17390fc392
3 changed files with 142 additions and 83 deletions

View File

@@ -1,4 +1,5 @@
import fileinput
import json
import logging
import os
import shutil
@@ -37,22 +38,88 @@ class FlakeForTest(NamedTuple):
path: Path
def generate_flake(
temporary_home: Path,
flake_template: Path,
substitutions: dict[str, str] = {},
# define the machines directly including their config
machine_configs: dict[str, dict] = {},
) -> FlakeForTest:
"""
Creates a clan flake with the given name.
Machines are fully generated from the machine_configs.
Example:
machine_configs = dict(
my_machine=dict(
clanCore=dict(
backups=dict(
...
)
)
)
)
"""
# copy the template to a new temporary location
flake = temporary_home / "flake"
shutil.copytree(flake_template, flake)
# substitute `substitutions` in all files of the template
for file in flake.rglob("*"):
if file.is_file():
print(f"Final Content of {file}:")
for line in fileinput.input(file, inplace=True):
for key, value in substitutions.items():
line = line.replace(key, value)
print(line, end="")
# generate machines from machineConfigs
for machine_name, machine_config in machine_configs.items():
settings_path = flake / "machines" / machine_name / "settings.json"
settings_path.parent.mkdir(parents=True, exist_ok=True)
settings_path.write_text(json.dumps(machine_config, indent=2))
if "/tmp" not in str(os.environ.get("HOME")):
log.warning(
f"!! $HOME does not point to a temp directory!! HOME={os.environ['HOME']}"
)
# 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,
)
sp.run(["git", "init"], cwd=flake, check=True)
sp.run(["git", "add", "."], cwd=flake, check=True)
sp.run(["git", "config", "user.name", "clan-tool"], cwd=flake, check=True)
sp.run(["git", "config", "user.email", "clan@example.com"], cwd=flake, check=True)
sp.run(["git", "commit", "-a", "-m", "Initial commit"], cwd=flake, check=True)
return FlakeForTest(flake)
def create_flake(
monkeypatch: pytest.MonkeyPatch,
temporary_home: Path,
flake_name: str,
flake_template_name: str,
clan_core_flake: Path | None = None,
# names referring to pre-defined machines from ../machines
machines: list[str] = [],
# alternatively specify the machines directly including their config
machine_configs: dict[str, dict] = {},
remote: bool = False,
) -> Iterator[FlakeForTest]:
"""
Creates a flake with the given name and machines.
The machine names map to the machines in ./test_machines
"""
template = Path(__file__).parent / flake_name
template = Path(__file__).parent / flake_template_name
# copy the template to a new temporary location
flake = temporary_home / flake_name
flake = temporary_home / flake_template_name
shutil.copytree(template, flake)
# lookup the requested machines in ./test_machines and include them
@@ -62,6 +129,13 @@ def create_flake(
machine_path = Path(__file__).parent / "machines" / machine_name
shutil.copytree(machine_path, flake / "machines" / machine_name)
substitute(flake / "machines" / machine_name / "default.nix", flake)
# generate machines from machineConfigs
for machine_name, machine_config in machine_configs.items():
settings_path = flake / "machines" / machine_name / "settings.json"
settings_path.parent.mkdir(parents=True, exist_ok=True)
settings_path.write_text(json.dumps(machine_config, indent=2))
# in the flake.nix file replace the string __CLAN_URL__ with the the clan flake
# provided by get_test_flake_toplevel
flake_nix = flake / "flake.nix"

View File

@@ -1,9 +1,11 @@
import os
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
from cli import Cli
from fixtures_flakes import FlakeForTest
from fixtures_flakes import FlakeForTest, generate_flake
from root import CLAN_CORE
if TYPE_CHECKING:
from age_keys import KeyPair
@@ -41,3 +43,63 @@ def test_run(
]
)
cli.run(["vms", "run", "vm1"])
@pytest.mark.skipif(no_kvm, reason="Requires KVM")
@pytest.mark.impure
def test_vm_persistence(
monkeypatch: pytest.MonkeyPatch,
temporary_home: Path,
) -> None:
flake = generate_flake(
temporary_home,
flake_template=CLAN_CORE / "templates" / "new-clan",
substitutions=dict(
__CHANGE_ME__="_test_vm_persistence",
),
machine_configs=dict(
my_machine=dict(
clanCore=dict(state=dict(my_state=dict(folders=["/var/my-state"]))),
systemd=dict(
services=dict(
poweroff=dict(
description="Poweroff the machine",
wantedBy=["multi-user.target"],
after=["my-state.service"],
script="""
echo "Powering off the machine"
poweroff
""",
),
my_state=dict(
description="Create a file in the state folder",
wantedBy=["multi-user.target"],
script="""
echo "Creating a file in the state folder"
echo "dream2nix" > /var/my-state/test
""",
serviceConfig=dict(Type="oneshot"),
),
)
),
clan=dict(virtualisation=dict(graphics=False)),
users=dict(users=dict(root=dict(password="root"))),
)
),
)
monkeypatch.chdir(flake.path)
Cli().run(["vms", "run", "my_machine"])
test_file = (
temporary_home
/ ".config"
/ "clan"
/ "vmstate"
/ "_test_vm_persistence"
/ "my_machine"
/ "var"
/ "my-state"
/ "test"
)
assert test_file.exists()
assert test_file.read_text() == "dream2nix\n"