Follow rail-knative 76cb9c7 (RAIL-KNATIVE-WP-0003): overlays set 10m CPU requests for the six substrate containers and add hpa-caps.patch.yaml (maxReplicas activator 3, webhook 2, 3scale-kourier-gateway 3); verify.sh checks both; tests/test_knative_render.py checks overlays, verify.sh, the rail-knative declaration and the render. Not applied. Adds the receiving task for wave-2 railiance-cluster allocation (CUST-WP-0071, RESOURCE-WP-0008). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 8340@bnt-lap001 Assistant-Session: 2e192b3d-b3e8-4403-94d4-d55a2c8b476c
155 lines
6.7 KiB
Python
155 lines
6.7 KiB
Python
"""Offline proof that install/knative renders the declared CPU requests and HPA caps.
|
|
|
|
Runs install/knative/render.sh (download + SHA-256 verification + kustomize;
|
|
no cluster contact) and compares the result with the upstream assets: the six
|
|
declared CPU requests and HPA maxReplicas change, the Kourier Service is ClusterIP, the gateway
|
|
image is the pinned Envoy digest, and nothing else differs. Skips when the
|
|
upstream assets cannot be fetched or kubectl is missing.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
try:
|
|
import yaml
|
|
except ImportError: # pragma: no cover
|
|
yaml = None
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
KNATIVE = ROOT / "install" / "knative"
|
|
RAIL_KNATIVE = Path(os.environ.get("RAIL_KNATIVE_DIR", ROOT.parent / "rail-knative"))
|
|
DECLARED = { # (namespace, deployment, container) -> cpu request
|
|
("knative-serving", "activator", "activator"): "10m",
|
|
("knative-serving", "autoscaler", "autoscaler"): "10m",
|
|
("knative-serving", "controller", "controller"): "10m",
|
|
("knative-serving", "webhook", "webhook"): "10m",
|
|
("knative-serving", "net-kourier-controller", "controller"): "10m",
|
|
("kourier-system", "3scale-kourier-gateway", "kourier-gateway"): "10m",
|
|
}
|
|
DECLARED_HPA = { # (namespace, hpa) -> maxReplicas
|
|
("knative-serving", "activator"): 3,
|
|
("knative-serving", "webhook"): 2,
|
|
("kourier-system", "3scale-kourier-gateway"): 3,
|
|
}
|
|
|
|
|
|
def lock() -> dict[str, str]:
|
|
lines = (KNATIVE / "release-lock.env").read_text().splitlines()
|
|
return dict(line.split("=", 1) for line in lines if "=" in line)
|
|
|
|
|
|
def load(path: Path) -> list[dict]:
|
|
return [d for d in yaml.safe_load_all(path.read_text()) if d]
|
|
|
|
|
|
def key(doc: dict) -> tuple:
|
|
meta = doc["metadata"]
|
|
return (doc["apiVersion"], doc["kind"], meta.get("namespace"), meta["name"])
|
|
|
|
|
|
def patch_requests(path: Path) -> dict[tuple, str]:
|
|
out = {}
|
|
for doc in load(path):
|
|
for c in doc["spec"]["template"]["spec"]["containers"]:
|
|
out[(doc["metadata"]["namespace"], doc["metadata"]["name"], c["name"])] = c["resources"]["requests"]["cpu"]
|
|
return out
|
|
|
|
|
|
def patch_hpa_caps(path: Path) -> dict[tuple, int]:
|
|
return {(d["metadata"]["namespace"], d["metadata"]["name"]): d["spec"]["maxReplicas"] for d in load(path)}
|
|
|
|
|
|
@unittest.skipIf(yaml is None, "PyYAML not installed")
|
|
class DeclarationTests(unittest.TestCase):
|
|
def test_overlays_carry_the_declared_requests(self) -> None:
|
|
got = {}
|
|
for overlay in ("serving-core", "kourier"):
|
|
got.update(patch_requests(KNATIVE / "overlays" / overlay / "cpu-requests.patch.yaml"))
|
|
self.assertEqual(DECLARED, got)
|
|
|
|
def test_overlays_carry_the_declared_hpa_caps(self) -> None:
|
|
got = {}
|
|
for overlay in ("serving-core", "kourier"):
|
|
got.update(patch_hpa_caps(KNATIVE / "overlays" / overlay / "hpa-caps.patch.yaml"))
|
|
self.assertEqual(DECLARED_HPA, got)
|
|
|
|
def test_verify_checks_the_declared_requests(self) -> None:
|
|
rows = re.search(r"<<'LIST'\n(.*?)\nLIST", (KNATIVE / "verify.sh").read_text(), re.S).group(1)
|
|
got = {tuple(r.split()[:3]): r.split()[3] for r in rows.splitlines()}
|
|
self.assertEqual(DECLARED, got)
|
|
|
|
def test_verify_checks_the_declared_hpa_caps(self) -> None:
|
|
rows = re.search(r"<<'HPAS'\n(.*?)\nHPAS", (KNATIVE / "verify.sh").read_text(), re.S).group(1)
|
|
got = {tuple(r.split()[:2]): int(r.split()[2]) for r in rows.splitlines()}
|
|
self.assertEqual(DECLARED_HPA, got)
|
|
|
|
def test_matches_rail_knative_declaration(self) -> None:
|
|
source = RAIL_KNATIVE / "substrate" / "v1.22.0" / "cpu-requests.patch.yaml"
|
|
if not source.exists():
|
|
self.skipTest(f"rail-knative not checked out at {RAIL_KNATIVE}")
|
|
self.assertEqual(DECLARED, patch_requests(source))
|
|
self.assertEqual(DECLARED_HPA, patch_hpa_caps(source.with_name("hpa-caps.patch.yaml")))
|
|
|
|
|
|
@unittest.skipIf(yaml is None or shutil.which("kubectl") is None, "needs PyYAML and kubectl")
|
|
class RenderTests(unittest.TestCase):
|
|
stage: Path
|
|
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls.stage = Path(os.environ.get("KNATIVE_STAGE_DIR") or tempfile.mkdtemp(prefix="knative-render-"))
|
|
result = subprocess.run([str(KNATIVE / "render.sh"), str(cls.stage)], capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
if "checksum mismatch" in result.stderr:
|
|
raise AssertionError(result.stderr)
|
|
raise unittest.SkipTest(f"render.sh failed (offline?): {result.stderr.strip()[:200]}")
|
|
|
|
def compare(self, upstream_file: str, rendered_file: str) -> dict[tuple, dict]:
|
|
upstream = {key(d): d for d in load(self.stage / upstream_file)}
|
|
rendered = {key(d): d for d in load(self.stage / rendered_file)}
|
|
self.assertEqual(set(upstream), set(rendered))
|
|
return {k: (upstream[k], rendered[k]) for k in upstream}
|
|
|
|
def check(self, upstream_file: str, rendered_file: str) -> set:
|
|
seen = set()
|
|
envoy = lock()["ENVOY_IMAGE"]
|
|
for k, (up, out) in self.compare(upstream_file, rendered_file).items():
|
|
expected = copy.deepcopy(up)
|
|
if k[1] == "Deployment":
|
|
for c in expected["spec"]["template"]["spec"]["containers"]:
|
|
ident = (k[2], k[3], c["name"])
|
|
if ident in DECLARED:
|
|
c["resources"]["requests"]["cpu"] = DECLARED[ident]
|
|
seen.add(ident)
|
|
if c["image"].startswith("docker.io/envoyproxy/envoy:"):
|
|
c["image"] = envoy
|
|
if k[1] == "HorizontalPodAutoscaler" and k[2:] in DECLARED_HPA:
|
|
expected["spec"]["maxReplicas"] = DECLARED_HPA[k[2:]]
|
|
seen.add(k[2:])
|
|
if k[1:] == ("Service", "kourier-system", "kourier"):
|
|
expected["spec"]["type"] = "ClusterIP"
|
|
self.assertEqual(expected, out, f"{k} differs beyond the declared changes")
|
|
return seen
|
|
|
|
def test_crds_are_the_pinned_upstream_file(self) -> None:
|
|
digest = hashlib.sha256((self.stage / "crds.yaml").read_bytes()).hexdigest()
|
|
self.assertEqual(lock()["SERVING_CRDS_SHA256"], digest)
|
|
for doc in load(self.stage / "crds.yaml"):
|
|
self.assertEqual("CustomResourceDefinition", doc["kind"])
|
|
|
|
def test_rendered_carries_declared_requests_and_nothing_else_changes(self) -> None:
|
|
seen = self.check("core.yaml", "serving-core.rendered.yaml")
|
|
seen |= self.check("kourier.yaml", "kourier.rendered.yaml")
|
|
self.assertEqual(set(DECLARED) | set(DECLARED_HPA), seen)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|