Introduce 'enroll validate' to check a harvest meets the schema spec and isn't lacking artifacts or contains orphaned ones
This commit is contained in:
parent
45e0d9bb16
commit
66d032d981
16 changed files with 1426 additions and 26 deletions
151
tests/test_validate.py
Normal file
151
tests/test_validate.py
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
import enroll.cli as cli
|
||||
from enroll.validate import validate_harvest
|
||||
|
||||
|
||||
def _base_state() -> dict:
|
||||
return {
|
||||
"enroll": {"version": "0.0.test", "harvest_time": 0},
|
||||
"host": {
|
||||
"hostname": "testhost",
|
||||
"os": "unknown",
|
||||
"pkg_backend": "dpkg",
|
||||
"os_release": {},
|
||||
},
|
||||
"inventory": {"packages": {}},
|
||||
"roles": {
|
||||
"users": {
|
||||
"role_name": "users",
|
||||
"users": [],
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"services": [],
|
||||
"packages": [],
|
||||
"apt_config": {
|
||||
"role_name": "apt_config",
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"dnf_config": {
|
||||
"role_name": "dnf_config",
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"etc_custom": {
|
||||
"role_name": "etc_custom",
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"usr_local_custom": {
|
||||
"role_name": "usr_local_custom",
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
"extra_paths": {
|
||||
"role_name": "extra_paths",
|
||||
"include_patterns": [],
|
||||
"exclude_patterns": [],
|
||||
"managed_dirs": [],
|
||||
"managed_files": [],
|
||||
"managed_links": [],
|
||||
"excluded": [],
|
||||
"notes": [],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _write_bundle(tmp_path: Path, state: dict) -> Path:
|
||||
bundle = tmp_path / "bundle"
|
||||
bundle.mkdir(parents=True)
|
||||
(bundle / "artifacts").mkdir()
|
||||
(bundle / "state.json").write_text(json.dumps(state, indent=2), encoding="utf-8")
|
||||
return bundle
|
||||
|
||||
|
||||
def test_validate_ok_bundle(tmp_path: Path):
|
||||
state = _base_state()
|
||||
state["roles"]["etc_custom"]["managed_files"].append(
|
||||
{
|
||||
"path": "/etc/hosts",
|
||||
"src_rel": "etc/hosts",
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"mode": "0644",
|
||||
"reason": "custom_specific_path",
|
||||
}
|
||||
)
|
||||
|
||||
bundle = _write_bundle(tmp_path, state)
|
||||
art = bundle / "artifacts" / "etc_custom" / "etc" / "hosts"
|
||||
art.parent.mkdir(parents=True, exist_ok=True)
|
||||
art.write_text("127.0.0.1 localhost\n", encoding="utf-8")
|
||||
|
||||
res = validate_harvest(str(bundle))
|
||||
assert res.ok
|
||||
assert res.errors == []
|
||||
|
||||
|
||||
def test_validate_missing_artifact_is_error(tmp_path: Path):
|
||||
state = _base_state()
|
||||
state["roles"]["etc_custom"]["managed_files"].append(
|
||||
{
|
||||
"path": "/etc/hosts",
|
||||
"src_rel": "etc/hosts",
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"mode": "0644",
|
||||
"reason": "custom_specific_path",
|
||||
}
|
||||
)
|
||||
bundle = _write_bundle(tmp_path, state)
|
||||
res = validate_harvest(str(bundle))
|
||||
assert not res.ok
|
||||
assert any("missing artifact" in e for e in res.errors)
|
||||
|
||||
|
||||
def test_validate_schema_error_is_reported(tmp_path: Path):
|
||||
state = _base_state()
|
||||
state["host"]["os"] = "not_a_real_os"
|
||||
bundle = _write_bundle(tmp_path, state)
|
||||
res = validate_harvest(str(bundle))
|
||||
assert not res.ok
|
||||
assert any(e.startswith("schema /host/os") for e in res.errors)
|
||||
|
||||
|
||||
def test_cli_validate_exits_2_on_validation_error(monkeypatch, tmp_path: Path):
|
||||
state = _base_state()
|
||||
state["roles"]["etc_custom"]["managed_files"].append(
|
||||
{
|
||||
"path": "/etc/hosts",
|
||||
"src_rel": "etc/hosts",
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"mode": "0644",
|
||||
"reason": "custom_specific_path",
|
||||
}
|
||||
)
|
||||
bundle = _write_bundle(tmp_path, state)
|
||||
|
||||
monkeypatch.setattr(sys, "argv", ["enroll", "validate", str(bundle)])
|
||||
with pytest.raises(SystemExit) as e:
|
||||
cli.main()
|
||||
assert e.value.code == 2
|
||||
Loading…
Add table
Add a link
Reference in a new issue