feat(tests): load live VM host/key from .env, keep inventory non-sensitive

This commit is contained in:
dw-0
2026-07-04 14:11:01 +02:00
parent 1d1bac1524
commit e20b85e00c
6 changed files with 104 additions and 17 deletions
+17 -10
View File
@@ -24,17 +24,24 @@ the VM in the inventory.
## Inventory ## Inventory
Edit `kiauh/live/inventory.yaml` or point to a custom file: `kiauh/live/inventory.yaml` defines non-sensitive VM settings. The host and SSH
key path are read from environment variables or a `.env` file so they are not
committed.
```yaml Create `.env` in the project root:
vms:
- name: debian12-kiauh ```bash
host: 192.168.122.10 KIAUH_LIVE_DEBIAN12_KIAUH_HOST=192.168.122.10
user: kiauh KIAUH_LIVE_DEBIAN12_KIAUH_KEY_FILE=/home/you/.ssh/kiauh_vm
key_file: ~/.ssh/kiauh_vm ```
os: debian-12
domain: debian12-kiauh Variable naming: `KIAUH_LIVE_<VM_NAME>_HOST` and `KIAUH_LIVE_<VM_NAME>_KEY_FILE`,
snapshot: clean with the VM name uppercased and hyphens replaced by underscores.
You can also point to a custom inventory file:
```bash
export KIAUH_LIVE_INVENTORY=/path/to/inventory.yaml
``` ```
## Run Live Tests ## Run Live Tests
+26 -4
View File
@@ -15,6 +15,13 @@ from typing import List
import yaml import yaml
try:
from dotenv import load_dotenv
load_dotenv(Path(__file__).parents[2].joinpath(".env"))
except ImportError:
load_dotenv = None
DEFAULT_INVENTORY_PATH = Path(__file__).parent.joinpath("inventory.yaml") DEFAULT_INVENTORY_PATH = Path(__file__).parent.joinpath("inventory.yaml")
@@ -33,6 +40,11 @@ class InventoryError(Exception):
pass pass
def _env_var_name(vm_name: str, suffix: str) -> str:
safe_name = vm_name.replace("-", "_").upper()
return f"KIAUH_LIVE_{safe_name}_{suffix.upper()}"
def load_inventory(path: Path | None = None) -> List[VM]: def load_inventory(path: Path | None = None) -> List[VM]:
inventory_path = Path(path or os.environ.get("KIAUH_LIVE_INVENTORY", DEFAULT_INVENTORY_PATH)) inventory_path = Path(path or os.environ.get("KIAUH_LIVE_INVENTORY", DEFAULT_INVENTORY_PATH))
if not inventory_path.exists(): if not inventory_path.exists():
@@ -44,15 +56,25 @@ def load_inventory(path: Path | None = None) -> List[VM]:
vms = [] vms = []
for item in data["vms"]: for item in data["vms"]:
for required in ("name", "host", "user", "key_file", "os"): for required in ("name", "user", "os"):
if required not in item: if required not in item:
raise InventoryError(f"VM '{item.get('name', '?')}' missing '{required}'") raise InventoryError(f"VM '{item.get('name', '?')}' missing '{required}'")
name = item["name"]
host = os.environ.get(_env_var_name(name, "host"), item.get("host"))
key_file = os.environ.get(_env_var_name(name, "key_file"), item.get("key_file"))
if not host:
raise InventoryError(f"VM '{name}' missing 'host' (inventory or env)")
if not key_file:
raise InventoryError(f"VM '{name}' missing 'key_file' (inventory or env)")
vms.append( vms.append(
VM( VM(
name=item["name"], name=name,
host=item["host"], host=host,
user=item["user"], user=item["user"],
key_file=item["key_file"], key_file=key_file,
os=item["os"], os=item["os"],
domain=item.get("domain"), domain=item.get("domain"),
snapshot=item.get("snapshot"), snapshot=item.get("snapshot"),
+5 -2
View File
@@ -1,8 +1,11 @@
vms: vms:
- name: debian12-kiauh - name: debian12-kiauh
host: 192.168.122.10 # Override host/key_file via environment variables or a .env file.
# KIAUH_LIVE_DEBIAN12_KIAUH_HOST
# KIAUH_LIVE_DEBIAN12_KIAUH_KEY_FILE
host: null
user: kiauh user: kiauh
key_file: ~/.ssh/kiauh_vm key_file: null
os: debian-12 os: debian-12
domain: debian12-kiauh domain: debian12-kiauh
snapshot: clean snapshot: clean
+54
View File
@@ -0,0 +1,54 @@
from __future__ import annotations
from pathlib import Path
import pytest
from live.inventory import InventoryError, VM, load_inventory
class TestLoadInventory:
def test_loads_vm_from_inventory(self, tmp_path: Path) -> None:
inv = tmp_path / "inv.yaml"
inv.write_text(
"vms:\n"
" - name: debian12\n"
" host: 10.0.0.5\n"
" user: kiauh\n"
" key_file: /key\n"
" os: debian-12\n"
)
vms = load_inventory(inv)
assert len(vms) == 1
assert vms[0].host == "10.0.0.5"
assert vms[0].key_file == "/key"
def test_env_overrides_host_and_key_file(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("KIAUH_LIVE_DEBIAN12_HOST", "192.168.1.50")
monkeypatch.setenv("KIAUH_LIVE_DEBIAN12_KEY_FILE", "/secret/key")
inv = tmp_path / "inv.yaml"
inv.write_text(
"vms:\n"
" - name: debian12\n"
" host: 10.0.0.5\n"
" user: kiauh\n"
" key_file: /key\n"
" os: debian-12\n"
)
vms = load_inventory(inv)
assert vms[0].host == "192.168.1.50"
assert vms[0].key_file == "/secret/key"
def test_missing_host_raises(self, tmp_path: Path) -> None:
inv = tmp_path / "inv.yaml"
inv.write_text(
"vms:\n"
" - name: debian12\n"
" user: kiauh\n"
" key_file: /key\n"
" os: debian-12\n"
)
with pytest.raises(InventoryError, match="missing 'host'"):
load_inventory(inv)
+1 -1
View File
@@ -2,7 +2,7 @@
requires-python = ">=3.8" requires-python = ">=3.8"
[project.optional-dependencies] [project.optional-dependencies]
dev=["ruff", "mypy", "pytest", "paramiko", "pytest-testinfra", "pyyaml"] dev=["ruff", "mypy", "pytest", "paramiko", "pytest-testinfra", "pyyaml", "python-dotenv"]
[tool.ruff] [tool.ruff]
required-version = ">=0.9.10" required-version = ">=0.9.10"
+1
View File
@@ -4,3 +4,4 @@ pytest
paramiko paramiko
pytest-testinfra pytest-testinfra
pyyaml pyyaml
python-dotenv