The renderer's PaaS path (kind: container) had no verifying conformance test — the R-PLAT-02 token appears only in renderer comments, so a change touching catalog/ surfaced it as an uncovered touched-requirement (blocking the merge gate). Adds the container render analog of vm-lifecycle (R-PLAT-03): asserts a kind: container ServiceDefinition renders a Deployment (running the declared image) + a Service, with the egress-class/auth-mode labels admission requires. Offline render-check.sh, wrapped by a chainsaw Test for in-cluster runs. Co-Authored-By: Claude Opus 4.8 <[email protected]>
53 lines
2.5 KiB
Bash
Executable File
53 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# L1 render check (offline, no cluster) — container-workload-render
|
|
# Serves: R-PLAT-02 (PaaS: a kind: container ServiceDefinition renders a container
|
|
# workload). The render analog of vm-lifecycle (R-PLAT-03) for the container path.
|
|
# Run by conformance/run.sh --layer l1 and ci/l1.sh. Pure bash + catalog/render.py.
|
|
#
|
|
# GIVEN a kind: container ServiceDefinition with an exposed port,
|
|
# WHEN the renderer produces resources,
|
|
# THEN (1) the render matches the committed golden byte-for-byte, and
|
|
# (2) it includes a Deployment running the SD's image plus a Service for the
|
|
# exposed port, and the pod carries the egress-class + auth-mode labels the
|
|
# platform's Kyverno policies require (a rendered container that admission
|
|
# would accept).
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT="$(cd "${DIR}/../../../.." && pwd)" # repo root
|
|
RENDER="${ROOT}/catalog/render.py"
|
|
PYTHON="${PYTHON:-python3}"
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "${tmp}"' EXIT
|
|
|
|
fail() { echo "RENDER-CHECK FAIL (container-workload-render): $*" >&2; exit 1; }
|
|
|
|
"${PYTHON}" "${RENDER}" "${DIR}/fixtures/svcdef.yaml" > "${tmp}/out.yaml"
|
|
|
|
# (1) golden match.
|
|
diff -u "${DIR}/golden/expected.yaml" "${tmp}/out.yaml" || fail "render drifted from golden"
|
|
|
|
# (2) structural: a Deployment (image) + Service (port) + the required pod labels.
|
|
"${PYTHON}" - "${tmp}/out.yaml" <<'PY' || fail "container render is missing the PaaS workload shape (R-PLAT-02)"
|
|
import sys, yaml
|
|
docs = [d for d in yaml.safe_load_all(open(sys.argv[1])) if d]
|
|
by = {}
|
|
for d in docs:
|
|
by.setdefault(d.get("kind"), []).append(d)
|
|
assert by.get("Deployment"), "expected a Deployment (the container workload)"
|
|
dep = by["Deployment"][0]
|
|
c = dep["spec"]["template"]["spec"]["containers"][0]
|
|
assert c["image"] == "nginx:1.27", f"unexpected image {c['image']!r}"
|
|
labels = dep["spec"]["template"]["metadata"]["labels"]
|
|
L = "homelab.keithjackson.dev"
|
|
assert labels.get(f"{L}/egress-class") in ("internet", "vpn"), "pod missing egress-class label"
|
|
assert labels.get(f"{L}/auth-mode"), "pod missing auth-mode label"
|
|
assert by.get("Service"), "expected a Service for the exposed port"
|
|
ports = [p["port"] for p in by["Service"][0]["spec"]["ports"]]
|
|
assert 8080 in ports, f"Service does not expose port 8080 ({ports})"
|
|
PY
|
|
|
|
echo "render-check OK: container-workload-render (R-PLAT-02)"
|