mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 11:49:28 +00:00
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
159 lines
8.7 KiB
Python
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]
|