ops-warden/tests/test_scaffold.py

194 lines
6.7 KiB
Python
Raw Normal View History

from copy import deepcopy
import socket
import subprocess
import pytest
import yaml
from typer.testing import CliRunner
from warden.cli import app
from warden.routing.catalog import Catalog, load_catalog
from warden.routing.scaffold import ScaffoldError, render, scaffold
@pytest.fixture
def draft_request():
return {
"schema_version": 1,
"lane_id": "example-workload-kv",
"title": "Example workload read",
"need_keywords": ["example workload"],
"consumer_repo": "example-consumer",
"owner_repo": "railiance-platform",
"workload_ref": {
"applicability": "applicable",
"unknown_reason": "Synthetic fixture has no published deployment identity",
},
"risk": "standard",
"wiki_ref": "railiance-platform:docs/catalog-lane-scaffold.md",
"canon_ref": "railiance-platform:credential-change-requests/CCR-2026-9999.yaml",
"platform_request_ref": "railiance-platform:examples/catalog-lane-scaffold/platform-request.yaml",
"reviewed": "2026-10-04",
}
def empty_catalog(tmp_path):
return Catalog(path=tmp_path / "unused.yaml", entries=[])
def test_deterministic_draft_roundtrip_and_input_unchanged(draft_request, tmp_path):
before = deepcopy(draft_request)
contents = render(draft_request, empty_catalog(tmp_path))
assert contents == render(draft_request, empty_catalog(tmp_path))
assert draft_request == before
for name in ["one", "two"]:
source = tmp_path / f"{name}.yaml"
source.write_text(yaml.safe_dump(draft_request))
paths = scaffold(source, tmp_path / name, catalog=empty_catalog(tmp_path))
assert len(paths) == 3
assert (tmp_path / "one/catalog.yaml").read_bytes() == (
tmp_path / "two/catalog.yaml"
).read_bytes()
entry = load_catalog(tmp_path / "one/catalog.yaml").entries[0]
assert entry.status == "draft"
assert not entry.exec_capable and not entry.warden_executes
assert entry.fetch_command is None
assert entry.workload_ref.resolution == "unknown"
assert entry.workload_ref.name is None
assert entry.risk == "standard"
assert yaml.safe_load((tmp_path / "one/request.yaml").read_text()) == draft_request
@pytest.mark.parametrize("risk", ["high", "ungraded"])
def test_explicit_risk_is_preserved(draft_request, tmp_path, risk):
draft_request["risk"] = risk
raw = yaml.safe_load(render(draft_request, empty_catalog(tmp_path))["catalog.yaml"])
assert raw["entries"][0]["risk"] == risk
@pytest.mark.parametrize(
"mutation",
[
lambda r: r.update(exec_capable=True),
lambda r: r.pop("risk"),
lambda r: r.update(risk=""),
lambda r: r.update(schema_version=True),
lambda r: r.update(lane_id="../escape"),
lambda r: r.update(reviewed="yesterday"),
lambda r: r.update(need_keywords=[]),
lambda r: r.update(workload_ref={"applicability": "applicable"}),
lambda r: r.update(
workload_ref={
"applicability": "applicable",
"unknown_reason": "unknown",
"name": "inferred",
}
),
lambda r: r.update(
workload_ref={
"applicability": "applicable",
"unknown_reason": "unknown",
"role": "admin",
}
),
],
)
def test_invalid_request_publishes_nothing(draft_request, tmp_path, mutation):
mutation(draft_request)
source = tmp_path / "input.yaml"
source.write_text(yaml.safe_dump(draft_request))
with pytest.raises(ScaffoldError):
scaffold(source, tmp_path / "stage", catalog=empty_catalog(tmp_path))
assert not (tmp_path / "stage").exists()
@pytest.mark.parametrize(
"field", ["title", "platform_request_ref", "need_keywords", "workload_ref"]
)
def test_secret_rejection_does_not_echo_value(draft_request, tmp_path, field):
token = "ghp_" + "Ab12" * 12
draft_request[field] = (
[token]
if field == "need_keywords"
else {"applicability": "applicable", "unknown_reason": token}
if field == "workload_ref"
else token
)
with pytest.raises(ScaffoldError) as exc:
render(draft_request, empty_catalog(tmp_path))
assert token not in str(exc.value)
assert "Ab12" not in str(exc.value)
def test_existing_lane_collision_even_when_draft(draft_request, tmp_path):
raw = render(draft_request, empty_catalog(tmp_path))["catalog.yaml"]
path = tmp_path / "catalog.yaml"
path.write_text(raw)
with pytest.raises(ScaffoldError, match="already exists"):
render(draft_request, load_catalog(path))
@pytest.mark.parametrize("symlink", [False, True])
def test_preexisting_destination_is_preserved(draft_request, tmp_path, symlink):
source = tmp_path / "input.yaml"
source.write_text(yaml.safe_dump(draft_request))
stage = tmp_path / "stage"
if symlink:
stage.symlink_to(tmp_path / "missing")
else:
stage.mkdir()
(stage / "keep").write_text("original")
with pytest.raises(ScaffoldError, match="already exists"):
scaffold(source, stage, catalog=empty_catalog(tmp_path))
if not symlink:
assert (stage / "keep").read_text() == "original"
else:
assert stage.is_symlink()
def test_cli_offline_and_bad_yaml_diagnostic(draft_request, tmp_path, monkeypatch):
def forbidden(*args, **kwargs):
raise AssertionError("credential/network execution forbidden")
monkeypatch.setattr(socket, "create_connection", forbidden)
monkeypatch.setattr(subprocess, "run", forbidden)
monkeypatch.setenv("WARDEN_MEMORY", "0")
source = tmp_path / "input.yaml"
source.write_text(yaml.safe_dump(draft_request))
# Override live catalog with a different inert draft lane.
other = deepcopy(draft_request)
other["lane_id"] = "other-example"
catalog_path = tmp_path / "catalog.yaml"
catalog_path.write_text(render(other, empty_catalog(tmp_path))["catalog.yaml"])
monkeypatch.setenv("WARDEN_ROUTING_CATALOG", str(catalog_path))
result = CliRunner().invoke(
app,
[
"route",
"scaffold",
"--input",
str(source),
"--output-dir",
str(tmp_path / "stage"),
],
)
assert result.exit_code == 0, result.output
assert (
load_catalog(tmp_path / "stage/catalog.yaml").entries[0].id
== draft_request["lane_id"]
)
source.write_text("title: [ghp_private\n")
result = CliRunner().invoke(
app,
[
"route",
"scaffold",
"--input",
str(source),
"--output-dir",
str(tmp_path / "bad"),
],
)
assert result.exit_code == 1
assert "ghp_private" not in result.output