Implements the two L1 rendering tests that were failing scaffolds: - egress-class-render (R-NET-05/06/07): renders vpn + internet fixtures, diffs each against a committed golden, asserts the vpn steering label is present on vpn and absent on internet (fail-closed), and that flipping the class changes ONLY the egress path (R-NET-07). This fixes the --requirements R-NET-05 merge gate. - default-deny-baseline-render (R-NET-01): asserts every render carries the namespaced default-deny baseline, shaped deny-all + both directions. Each test carries a pure-offline render-check.sh (renderer + golden diff, no cluster). run.sh runs L1 render checks offline and emits a REAL pass/fail JUnit (docs/14: L1 rendering assertions run in CI without a cluster) instead of skipping L1 with the cluster-gated layers; the chainsaw-test.yaml wrappers invoke the same render-check.sh so an in-cluster run executes the identical assertion. Co-Authored-By: Claude Opus 4.8 <[email protected]>
52 lines
2.4 KiB
Bash
Executable File
52 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# L1 render check (offline, no cluster) — default-deny-baseline-render
|
|
# Serves: R-NET-01 (every namespace renders a default-deny baseline). Run by
|
|
# conformance/run.sh --layer l1 and ci/l1.sh. Pure bash + catalog/render.py.
|
|
#
|
|
# GIVEN any onboarded service (this fixture declares NO dependencies),
|
|
# WHEN its resources are rendered,
|
|
# THEN (1) the render matches the committed golden byte-for-byte, and
|
|
# (2) it includes a NetworkPolicy labelled baseline=default-deny that denies
|
|
# all ingress (ingress: []) and covers BOTH Ingress and Egress — the
|
|
# render-time partner of the Kyverno L0 gate and the L2 behavioral test.
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT="$(cd "${DIR}/../../../.." && pwd)" # repo root
|
|
RENDER="${ROOT}/catalog/render.py"
|
|
PYTHON="${PYTHON:-python3}"
|
|
LBL="homelab.keithjackson.dev"
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "${tmp}"' EXIT
|
|
|
|
fail() { echo "RENDER-CHECK FAIL (default-deny-baseline-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) the baseline is present and shaped as deny-all + both directions.
|
|
grep -q "${LBL}/baseline: default-deny" "${tmp}/out.yaml" \
|
|
|| fail "render is missing the default-deny baseline NetworkPolicy (R-NET-01)"
|
|
|
|
# Structural assertion via the renderer's own parse (deterministic, no cluster):
|
|
# find the default-deny NetworkPolicy and assert its shape.
|
|
"${PYTHON}" - "${tmp}/out.yaml" <<'PY' || fail "default-deny baseline is malformed (R-NET-01)"
|
|
import sys, yaml
|
|
docs = [d for d in yaml.safe_load_all(open(sys.argv[1])) if d]
|
|
np = [d for d in docs
|
|
if d.get("kind") == "NetworkPolicy"
|
|
and d.get("metadata", {}).get("labels", {}).get(
|
|
"homelab.keithjackson.dev/baseline") == "default-deny"]
|
|
assert len(np) == 1, f"expected exactly one default-deny baseline, got {len(np)}"
|
|
spec = np[0]["spec"]
|
|
assert spec.get("ingress") == [], "baseline must deny ALL ingress (ingress: [])"
|
|
assert set(spec.get("policyTypes", [])) == {"Ingress", "Egress"}, \
|
|
"baseline must cover BOTH Ingress and Egress"
|
|
PY
|
|
|
|
echo "render-check OK: default-deny-baseline-render (R-NET-01)"
|