Merge pull request 'clan-cli: add test_create in clan_lib test folder' (#3501) from Qubasa/clan-core:api_vm_test into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3501
This commit is contained in:
Luis Hebendanz
2025-05-05 20:29:57 +00:00
11 changed files with 3788 additions and 63 deletions

View File

@@ -1,9 +1,3 @@
import pytest
from clan_cli.custom_logger import setup_logging
# collect_ignore = ["./nixpkgs"]
pytest_plugins = [
"clan_cli.tests.temporary_dir",
"clan_cli.tests.root",
@@ -19,13 +13,3 @@ pytest_plugins = [
"clan_cli.tests.stdout",
"clan_cli.tests.nix_config",
]
# Executed on pytest session start
def pytest_sessionstart(session: pytest.Session) -> None:
# This function will be called once at the beginning of the test session
print("Starting pytest session")
# You can access the session config, items, testsfailed, etc.
print(f"Session config: {session.config}")
setup_logging(level="INFO")

View File

@@ -2,6 +2,7 @@ import argparse
import json
import logging
import re
import time
from dataclasses import dataclass
from pathlib import Path
from typing import Literal
@@ -11,38 +12,38 @@ from clan_lib.api.disk import MachineDiskMatter
from clan_lib.api.modules import parse_frontmatter
from clan_lib.api.serde import dataclass_to_dict
from clan_cli.cmd import RunOpts, run_no_stdout
from clan_cli.cmd import RunOpts, run
from clan_cli.completions import add_dynamic_completer, complete_tags
from clan_cli.dirs import specific_machine_dir
from clan_cli.errors import ClanCmdError, ClanError
from clan_cli.errors import ClanError
from clan_cli.inventory import (
Machine,
load_inventory_eval,
patch_inventory_with,
)
from clan_cli.inventory.classes import Machine as InventoryMachine
from clan_cli.machines.hardware import HardwareConfig
from clan_cli.nix import nix_eval, nix_shell
from clan_cli.nix import nix_eval
from clan_cli.tags import list_nixos_machines_by_tags
log = logging.getLogger(__name__)
@API.register
def set_machine(flake_url: Path, machine_name: str, machine: Machine) -> None:
def set_machine(flake_url: Path, machine_name: str, machine: InventoryMachine) -> None:
patch_inventory_with(
flake_url, f"machines.{machine_name}", dataclass_to_dict(machine)
)
@API.register
def list_inventory_machines(flake_url: str | Path) -> dict[str, Machine]:
def list_inventory_machines(flake_url: str | Path) -> dict[str, InventoryMachine]:
inventory = load_inventory_eval(flake_url)
return inventory.get("machines", {})
@dataclass
class MachineDetails:
machine: Machine
machine: InventoryMachine
hw_config: HardwareConfig | None = None
disk_schema: MachineDiskMatter | None = None
@@ -92,7 +93,7 @@ def list_nixos_machines(flake_url: str | Path) -> list[str]:
]
)
proc = run_no_stdout(cmd)
proc = run(cmd)
try:
res = proc.stdout.strip()
@@ -106,53 +107,36 @@ def list_nixos_machines(flake_url: str | Path) -> list[str]:
@dataclass
class ConnectionOptions:
keyfile: str | None = None
timeout: int = 2
retries: int = 10
from clan_cli.machines.machines import Machine
@API.register
def check_machine_online(
flake_url: str | Path, machine_name: str, opts: ConnectionOptions | None
machine: Machine, opts: ConnectionOptions | None = None
) -> Literal["Online", "Offline"]:
machine = load_inventory_eval(flake_url).get("machines", {}).get(machine_name)
if not machine:
msg = f"Machine {machine_name} not found in inventory"
raise ClanError(msg)
hostname = machine.get("deploy", {}).get("targetHost")
hostname = machine.target_host_address
if not hostname:
msg = f"Machine {machine_name} does not specify a targetHost"
msg = f"Machine {machine.name} does not specify a targetHost"
raise ClanError(msg)
timeout = opts.timeout if opts and opts.timeout else 20
timeout = opts.timeout if opts and opts.timeout else 2
cmd = nix_shell(
["util-linux", *(["openssh"] if hostname else [])],
[
"ssh",
*(["-i", f"{opts.keyfile}"] if opts and opts.keyfile else []),
# Disable strict host key checking
"-o",
"StrictHostKeyChecking=accept-new",
# Disable known hosts file
"-o",
"UserKnownHostsFile=/dev/null",
"-o",
f"ConnectTimeout={timeout}",
f"{hostname}",
"true",
"&> /dev/null",
],
)
try:
proc = run_no_stdout(cmd, RunOpts(needs_user_terminal=True))
if proc.returncode != 0:
return "Offline"
except ClanCmdError:
return "Offline"
else:
return "Online"
for _ in range(opts.retries if opts and opts.retries else 10):
with machine.target_host() as target:
res = target.run(
["true"],
RunOpts(timeout=timeout, check=False, needs_user_terminal=True),
)
if res.returncode == 0:
return "Online"
time.sleep(timeout)
return "Offline"
def list_command(args: argparse.Namespace) -> None:

View File

@@ -27,6 +27,14 @@ def test_root() -> Path:
return TEST_ROOT
@pytest.fixture(scope="session")
def test_lib_root() -> Path:
"""
Root directory of the clan-lib tests
"""
return PROJECT_ROOT.parent / "clan_lib" / "tests"
@pytest.fixture(scope="session")
def clan_core() -> Path:
"""