From fddf14e5f905e5fc1a4430bb8ddff6ec1f74b3e5 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 10 Sep 2026 11:00:32 +0200 Subject: [PATCH] feat(k8s): declare the six platform deviations so only new drift fails (refs #168) Six differences exist by design and are now recorded in DEVIATIONS with the reason each one was forced, so the check passes on today's tree and fails on tomorrow's accident: the four `*-init` Django services folded into their web pods (one migrator per database), and the two bootstrap Jobs compose runs from the host instead. Verified against both drift classes by hand: bumping OPENZAAK_TAG in compose alone reports openzaak + oz-celery, and adding a workload to values.yaml alone reports it by name. --- infra/helm/check-drift.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/infra/helm/check-drift.py b/infra/helm/check-drift.py index a69a474..e4df743 100755 --- a/infra/helm/check-drift.py +++ b/infra/helm/check-drift.py @@ -31,6 +31,26 @@ CHART = ROOT / "infra/helm/big-reference" # filterable without teaching the check what busybox is. BUSYBOX = "drift-check-ignored-init-image" +# Differences that Kubernetes forces, not drift (ADR-0033). A name listed here is +# expected to be on exactly one side; anything else fails. +DEVIATIONS = { + # The four Django services apply their own setup_configuration in the web pod + # (`args: [sh, -c, "/setup_configuration.sh && exec /start.sh"]`) rather than in a + # separate init Job. Both that script and /start.sh run `manage.py migrate`, and + # Kubernetes has no `depends_on: service_completed_successfully` to serialise them, + # so the Job and its web pod migrated the same database concurrently. + "oz-init": "folded into the openzaak pod", + "nrc-init": "folded into the nrc-web pod", + "objecttypen-init": "folded into the objecttypen pod", + "objecten-init": "folded into the objecten pod", + # Compose seeds these from the host — the verify scripts `docker cp` the two + # scripts into a running container, and docker-compose.local.yml carries + # `local-seed` + `nrc-subscribe` for `make local`. A cluster has no host to seed + # from, so both became Jobs in the chart. + "seed-zaaktype": "compose seeds the catalogus from the host (infra/openzaak/seed_catalogus.py)", + "nrc-subscribe": "compose registers the abonnement from the host (infra/local/register-abonnement.py)", +} + # Workloads the observability backplane adds. Off by default in both stacks' # defaults, so they are rendered on purpose here — otherwise their images drift # unwatched. @@ -70,9 +90,9 @@ def main() -> int: compose, chart = compose_services(), chart_workloads() problems = [] - for name in sorted(set(compose) - set(chart)): + for name in sorted(set(compose) - set(chart) - set(DEVIATIONS)): problems.append(f" {name}: in docker-compose.yml, not in the chart") - for name in sorted(set(chart) - set(compose)): + for name in sorted(set(chart) - set(compose) - set(DEVIATIONS)): problems.append(f" {name}: in the chart, not in docker-compose.yml") for name in sorted(set(compose) & set(chart)): if compose[name] != chart[name]: @@ -87,6 +107,8 @@ def main() -> int: return 1 print(f"no drift: {len(chart)} workloads, images identical on both stacks") + for name, why in sorted(DEVIATIONS.items()): + print(f" deviation (declared): {name} — {why}") return 0