38b51f3e6d
regression/ policies (3): cap-013-adapter-dedup, cap-023-metrics-collector, cap-024-deck-structure — declarative mirrors of core/regression_verify.py over capability-inventory JSON. The imperative regression_verify.py is kept (drives CI gate); the policies are the declarative mirror (IDEATE I1 quality improvement). tests: test_regression_policies.py + clean/drifted fixtures. Skip-without-kj. docs: adapters/README.md (new kyverno-json row + PolicyEngine Protocol section with how-to-add-OpaEngine), adapters/kyverno-json/README.md (engine, install, policy directory layout, 4 categories, severity convention), schemas/README.md (D-116 engine enum reuse note), modules/STANDARDS.md §10 Policy Authoring Standard, docs/METRICS.md (swappable engine narrative). ---ci--- project: acdl phase: 4 milestone: v1.25 status: execute phase_role: execution requirements: covered: [REQ-304, REQ-305, REQ-306, REQ-307] partial: [] ---/ci---
88 lines
3.2 KiB
Python
88 lines
3.2 KiB
Python
"""Tests for regression-gate kyverno-json policies (REQ-304, REQ-305, v1.25).
|
|
|
|
Tests the 3 declarative mirrors of core/regression_verify.py:
|
|
cap-013-adapter-dedup, cap-023-metrics-collector, cap-024-deck-structure.
|
|
Uses clean + drifted capability-inventory fixtures. Skip-without-kj.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
import importlib.util
|
|
_ENGINE_PATH = Path(__file__).resolve().parent.parent / "adapters" / "kyverno-json" / "kyverno_json_engine.py"
|
|
_spec = importlib.util.spec_from_file_location("kyverno_json_engine", _ENGINE_PATH)
|
|
_mod = importlib.util.module_from_spec(_spec)
|
|
_spec.loader.exec_module(_mod)
|
|
KyvernoJsonEngine = _mod.KyvernoJsonEngine
|
|
|
|
POLICY_DIR = Path(__file__).resolve().parent.parent / "adapters" / "kyverno-json" / "policies" / "regression"
|
|
FIXTURES = Path(__file__).resolve().parent / "fixtures" / "capability_inventory"
|
|
|
|
|
|
def _kj_installed() -> bool:
|
|
return _mod._which_kj() is not None
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _require_kj():
|
|
if not _kj_installed():
|
|
pytest.skip("kj not installed (scripts/install-kyverno-json.sh)")
|
|
|
|
|
|
def _load(name):
|
|
with open(FIXTURES / name, "r", encoding="utf-8") as fh:
|
|
return json.load(fh)
|
|
|
|
|
|
class TestCleanInventory:
|
|
def test_clean_inventory_no_fails(self):
|
|
eng = KyvernoJsonEngine()
|
|
out = eng.evaluate(_load("clean.json"), POLICY_DIR, "cid-clean")
|
|
fails = [p for p in out if p["result"] == "fail"]
|
|
assert fails == [], f"expected no fails on clean inventory, got: {fails}"
|
|
|
|
|
|
class TestDriftedInventory:
|
|
def test_drifted_inventory_has_fails(self):
|
|
eng = KyvernoJsonEngine()
|
|
out = eng.evaluate(_load("drifted.json"), POLICY_DIR, "cid-drift")
|
|
fails = [p for p in out if p["result"] == "fail"]
|
|
assert len(fails) >= 1, "expected at least one fail on the drifted inventory"
|
|
|
|
|
|
class TestPolicyFilesExist:
|
|
def test_three_regression_policies_present(self):
|
|
files = sorted(os.listdir(POLICY_DIR))
|
|
assert "cap-013-adapter-dedup.json" in files
|
|
assert "cap-023-metrics-collector.json" in files
|
|
assert "cap-024-deck-structure.json" in files
|
|
|
|
def test_policies_are_valid_json(self):
|
|
for f in os.listdir(POLICY_DIR):
|
|
if f.endswith(".json"):
|
|
with open(POLICY_DIR / f, "r", encoding="utf-8") as fh:
|
|
data = json.load(fh)
|
|
assert data["apiVersion"] == "json.kyverno.io/v1alpha1"
|
|
assert data["kind"] == "ValidatingPolicy"
|
|
assert "nova.cloudinit.dev/severity" in data["metadata"]["annotations"]
|
|
|
|
|
|
class TestFixturesExist:
|
|
def test_clean_and_drifted_fixtures_present(self):
|
|
assert (FIXTURES / "clean.json").is_file()
|
|
assert (FIXTURES / "drifted.json").is_file()
|
|
|
|
def test_drifted_fixture_has_duplicate_adapter(self):
|
|
data = _load("drifted.json")
|
|
# The drifted fixture has 'terraform' twice (adapter dedup violation).
|
|
assert data["adapters"].count("terraform") == 2
|
|
|
|
def test_drifted_fixture_has_missing_roadmap_beat(self):
|
|
data = _load("drifted.json")
|
|
assert "Roadmap+Ask" not in data["deck"]["beats"] |