Files
Open_Ultra_SAST/tests/test_plane_profile.py
T
Marius CiepluchandClaude Fable 5.1 8099b29deb plane(1.4): up.sh by profile -- context, registry, pool and images file from kind.toml
ops/ax/up.sh reads kube_context, registry, pools.default and the images path
with `python -m openultrasast.plane.profile --print`, writes the runner digest to
ops/k8s/profiles/kind-images.json instead of ~/.cache/.../runner-image, renders
ops/ax/workerpool.yaml.tmpl from the profile's pool (POOL_NAME/REPLICAS/CPU/
MEMORY, WORKER_IMAGE), and keeps an existing pool and an ax CLI newer than its
checkout instead of rebuilding them (ko and go install would refill several GB
of Go cache on this disk). smoke-run.sh takes the runner from `--print
images.runner` and runs the checkout's code with OUSAST_PYTHON. repin_templates
reads the JSON images file (runner key; the one-line pin still reads). `--print
images` returns the file path (the first live rerun fell over this). Templates
and the generated validation-46 Tasks re-pinned to the rebuilt image (128
lines, one digest).

Live: up.sh reran idempotently on kind in 38 s (every step kept except the
runner build); smoke-run.sh done in 24 s on the new image, facts.json 451 B,
summary.json 238 B delivered (record: benchmarks/measurements/2026-10-02-k8s-01-profile/).

Gates: pytest 2010 passed, 42 skipped, exit 0; ruff check 0; ruff format 0;
mypy 0; mkdocs build --strict 0.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
2026-10-02 20:43:40 +02:00

159 lines
8.7 KiB
Python

"""plane-on-kubernetes task 1.1: the ``PlaneProfile`` (Req 1.1). Defaults, file-then-environment precedence, every
rejection naming its field, both committed profiles loading, and no committed value that looks like a credential."""
from __future__ import annotations
import json
import re
from pathlib import Path
import pytest
from openultrasast.plane import profile as profile_module
from openultrasast.plane.profile import PlaneProfile, Pool, ProfileError, load_images, load_profile, profiles_dir
ROOT = Path(__file__).resolve().parents[1]
DIGEST = "sha256:" + "ab" * 32
MINIMAL = 'exec = "local"\nkube_context = "kind-test"\nregistry = "registry.test:5000"\nimages = "images.json"\nmemory = "s3://m"\n'
def write_profile(tmp_path: Path, text: str = MINIMAL, name: str = "test") -> Path:
path = tmp_path / f"{name}.toml"
path.write_text(text, encoding="utf-8")
(tmp_path / "images.json").write_text(json.dumps({"runner": f"registry.test:5000/ousast-runner@{DIGEST}"}), encoding="utf-8")
return path
def test_defaults_and_the_images_path_resolve_against_the_profile_file(tmp_path: Path) -> None:
loaded = load_profile(str(write_profile(tmp_path)), environ={})
assert loaded.name == "test" and loaded.exec == "local" and loaded.kube_context == "kind-test"
assert loaded.images == tmp_path / "images.json" and loaded.load_images() == {"runner": f"registry.test:5000/ousast-runner@{DIGEST}"}
assert loaded.atespace == "default" and loaded.router_url == "" and loaded.pools == {}
assert "(tunnel through the kube context)" in loaded.addresses()["router_url"]
def test_the_environment_overrides_the_file_and_names_the_profile(tmp_path: Path) -> None:
path = write_profile(tmp_path, MINIMAL + '[pools.default]\nreplicas = 2\ncpu = "1"\nmemory = "1536Mi"\n')
env = {
"OUSAST_PLANE_PROFILE": str(path),
"OUSAST_KUBE_CONTEXT": "other-cluster",
"OUSAST_MEMORY": "s3://elsewhere/prefix",
"OUSAST_ROUTER_URL": "https://router.test",
"OUSAST_POOL_DEFAULT_REPLICAS": "5",
"OUSAST_POOL_DEFAULT_MEMORY": "2Gi",
"OUSAST_EXEC": "", # an empty variable is not an override
}
loaded = load_profile(environ=env)
assert (loaded.kube_context, loaded.memory, loaded.router_url, loaded.exec) == (
"other-cluster",
"s3://elsewhere/prefix",
"https://router.test",
"local",
)
assert loaded.pools == {"default": Pool(replicas=5, cpu="1", memory="2Gi")}
assert load_profile(str(path), environ={}).kube_context == "kind-test", "the file is unchanged"
@pytest.mark.parametrize(
("text", "field"),
[
(MINIMAL + 'colour = "blue"\n', "unknown keys: colour"),
(MINIMAL + 'aws_secret_key = "x"\n', "aws_secret_key looks like a credential"),
(MINIMAL + 'api_token = "x"\n', "api_token looks like a credential"),
(MINIMAL.replace('exec = "local"', 'exec = "cluster"'), "exec must be one of local, remote"),
(MINIMAL + '[pools.default]\nreplicas = "two"\ncpu = "1"\nmemory = "1Gi"\n', "pools.default.replicas must be an integer"),
(MINIMAL + '[pools.default]\nreplicas = 1\ncpu = "1"\n', "pools.default lacks memory"),
(MINIMAL + '[pools.default]\nreplicas = 1\ncpu = "1"\nmemory = "1Gi"\nnodes = 3\n', "pools.default has unknown keys: nodes"),
(MINIMAL.replace('kube_context = "kind-test"', "kube_context = 3"), "kube_context must be a string"),
],
)
def test_each_rejection_names_the_field(tmp_path: Path, text: str, field: str) -> None:
path = write_profile(tmp_path, text)
with pytest.raises(ProfileError, match=re.escape(field)) as exc:
load_profile(str(path), environ={})
assert str(path) in str(exc.value)
def test_a_credential_shaped_value_is_refused(tmp_path: Path) -> None:
path = write_profile(tmp_path, MINIMAL.replace("s3://m", "sk-" + "a1b2c3d4" * 3))
with pytest.raises(ProfileError, match="value of memory looks like a credential"):
load_profile(str(path), environ={})
def test_an_images_file_without_digest_pins_is_refused(tmp_path: Path) -> None:
path = write_profile(tmp_path)
(tmp_path / "images.json").write_text(json.dumps({"runner": "registry.test:5000/ousast-runner:dev"}), encoding="utf-8")
with pytest.raises(ProfileError, match="runner is not digest-pinned"):
load_profile(str(path), environ={})
(tmp_path / "images.json").write_text(f"registry.test:5000/ousast-runner@{DIGEST}\n", encoding="utf-8")
assert load_images(tmp_path / "images.json") == {"runner": f"registry.test:5000/ousast-runner@{DIGEST}"}, "the one-line form"
(tmp_path / "images.json").unlink()
loaded = load_profile(str(path), environ={}) # a file the release has not published yet: doctor's finding, not a load error
with pytest.raises(ProfileError, match="images file"):
loaded.load_images()
def test_an_environment_override_of_the_wrong_shape_is_refused(tmp_path: Path) -> None:
path = write_profile(tmp_path, MINIMAL + '[pools.default]\nreplicas = 1\ncpu = "1"\nmemory = "1Gi"\n')
with pytest.raises(ProfileError, match="OUSAST_POOL_DEFAULT_REPLICAS must be an integer"):
load_profile(str(path), environ={"OUSAST_POOL_DEFAULT_REPLICAS": "many"})
with pytest.raises(ProfileError, match="names a pool the profile does not declare"):
load_profile(str(path), environ={"OUSAST_POOL_ENGINE_REPLICAS": "1"})
with pytest.raises(ProfileError, match="exec must be one of"):
load_profile(str(path), environ={"OUSAST_EXEC": "both"})
def test_a_missing_profile_names_its_path(tmp_path: Path) -> None:
with pytest.raises(ProfileError, match="no-such.toml"):
load_profile(str(tmp_path / "no-such.toml"), environ={})
with pytest.raises(ProfileError, match="unknown"):
load_profile("unknown", environ={"OUSAST_PLANE_PROFILES": str(tmp_path)})
@pytest.mark.parametrize("name", ["kind", "k3s"])
def test_both_committed_profiles_load_with_the_designs_values(name: str) -> None:
loaded = load_profile(name, environ={})
assert loaded.path == profiles_dir() / f"{name}.toml" and profiles_dir() == ROOT / "ops/k8s/profiles"
assert loaded.exec == {"kind": "local", "k3s": "remote"}[name]
assert loaded.memory == "s3://sast-memory" and loaded.atespace == "default" and loaded.snapshots_bucket == "s3://ax-snapshots"
assert set(loaded.pools) == {"default", "engine"} and loaded.pools["engine"].memory == "4Gi"
assert loaded.router_url == "" and loaded.ax_server == "", "both profiles tunnel through the Kubernetes API"
if name == "kind":
assert loaded.image_pull_secret == "" and loaded.images.name == "kind-images.json" and loaded.images.is_file()
assert set(loaded.load_images()) == {"runner"} and loaded.load_images()["runner"].startswith(loaded.registry + "/")
else:
assert loaded.image_pull_secret == "ghcr-pull" and loaded.registry.startswith("ghcr.io/") and loaded.images.name == "images.json"
assert not loaded.images.is_file(), "the release asset is downloaded, never committed (design section 8)"
def test_no_committed_profile_value_matches_a_credential_pattern() -> None:
patterns = (
re.compile(r"(?i)(api_key|secret_key|access_key|token|password)\s*="), # image_pull_secret names a Secret, holds none
re.compile(r"sk-[A-Za-z0-9]{8,}"),
re.compile(r"AKIA[0-9A-Z]{12,}"),
)
for path in sorted(profiles_dir().glob("*.toml")):
for number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
code = line.split("#", 1)[0]
for pattern in patterns:
assert not pattern.search(code), f"{path}:{number}: {line.strip()}"
def test_print_for_shell_scripts(capsys: pytest.CaptureFixture[str], tmp_path: Path) -> None:
path = write_profile(tmp_path, MINIMAL + '[pools.default]\nreplicas = 3\ncpu = "1"\nmemory = "1Gi"\n')
fields = ["registry", "kube_context", "images.runner", "pools.default.replicas"]
assert profile_module.main(["--profile", str(path), "--print", *fields]) == 0
assert capsys.readouterr().out.splitlines() == ["registry.test:5000", "kind-test", f"registry.test:5000/ousast-runner@{DIGEST}", "3"]
assert profile_module.main(["--profile", str(path), "--print", "images"]) == 0, "the images file's path itself (up.sh writes it)"
assert capsys.readouterr().out.strip() == str(tmp_path / "images.json")
assert profile_module.main(["--profile", str(path), "--print", "images.engine"]) == 2
assert "no image named 'engine'" in capsys.readouterr().err
assert profile_module.main(["--profile", str(path), "--print", "nothing"]) == 2
def test_profile_is_frozen_and_typed() -> None:
loaded = load_profile("kind", environ={})
assert isinstance(loaded, PlaneProfile)
with pytest.raises(AttributeError):
loaded.exec = "remote" # type: ignore[misc]