test(infra): verify-objecten asserts Objecten API up + token auth + trusts Objecttypen (refs #140)

Fails against the current stack (no objecten service yet) with a clear
"no running objecten container" message. Green comes with the compose
service + seeded setup_configuration in the next commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
not
2026-07-27 10:57:05 +02:00
co-authored by Claude Opus 4.8
parent 23ea91de32
commit 32c3d31407
4 changed files with 88 additions and 1 deletions
+5
View File
@@ -204,6 +204,9 @@ jobs:
- name: Objecttypen API up + token authenticates
id: objecttypen
run: OBJECTTYPEN_TIMEOUT=120 make verify-objecttypen
- name: Objecten API up + token authenticates + trusts Objecttypen
id: objecten
run: OBJECTEN_TIMEOUT=120 make verify-objecten
- name: ACL ↔ OpenZaak integration tests
id: acl
run: make verify-acl
@@ -237,6 +240,7 @@ jobs:
UP: ${{ steps.up.outcome }}
OBS: ${{ steps.obs.outcome }}
OBJECTTYPEN: ${{ steps.objecttypen.outcome }}
OBJECTEN: ${{ steps.objecten.outcome }}
ACL: ${{ steps.acl.outcome }}
NRC: ${{ steps.nrc.outcome }}
PROJECTION: ${{ steps.projection.outcome }}
@@ -256,6 +260,7 @@ jobs:
echo "| Bring up + health | $(icon "$UP") |"
echo "| Observability backplane | $(icon "$OBS") |"
echo "| Objecttypen API + token | $(icon "$OBJECTTYPEN") |"
echo "| Objecten API + token | $(icon "$OBJECTEN") |"
echo "| ACL ↔ OpenZaak | $(icon "$ACL") |"
echo "| OpenZaak → NRC | $(icon "$NRC") |"
echo "| NRC → Event Subscriber → projection | $(icon "$PROJECTION") |"
+6 -1
View File
@@ -43,7 +43,7 @@ export DOCKER_HOST := unix://$(PODMAN_SOCK)
endif
endif
.PHONY: ci lint build unit mutation frontend integration verify verify-up verify-acl verify-nrc verify-projection verify-bff verify-domain verify-observability verify-tracing verify-metrics verify-objecttypen verify-notifications smoke up down local verify-local local-down changelog openzaak-up openzaak-smoke openzaak-seed openzaak-down stack-up stack-smoke stack-down keycloak-up keycloak-smoke keycloak-down flowable-up flowable-smoke flowable-down help
.PHONY: ci lint build unit mutation frontend integration verify verify-up verify-acl verify-nrc verify-projection verify-bff verify-domain verify-observability verify-tracing verify-metrics verify-objecttypen verify-objecten verify-notifications smoke up down local verify-local local-down changelog openzaak-up openzaak-smoke openzaak-seed openzaak-down stack-up stack-smoke stack-down keycloak-up keycloak-smoke keycloak-down flowable-up flowable-smoke flowable-down help
## ci: run the full pipeline — lint, build, unit, mutation, frontend, verify (mirrors Gitea Actions)
## `verify` is the live-stack stage (full stack up once → ACL + notification checks).
@@ -191,6 +191,11 @@ verify-metrics:
verify-objecttypen:
bash infra/run-objecttypen-check.sh
## verify-objecten: assert the Objecten API is up + its static token authenticates and it
## trusts the Objecttypen API (S-18b), against the already-running stack.
verify-objecten:
bash infra/run-objecten-check.sh
## verify: local mirror of the CI verify-stack job — full stack up once, all checks,
## tear down (always). For fast single-concern local iteration use `integration`
## (oz-only) or `verify-notifications` (oz+nrc) instead.
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""S-18b (#140): prove the Objecten API is up and its static token authenticates.
Assert an unauthenticated call to /api/v2/objects is 401 and an authenticated one (the seeded dev
token) is 200 — i.e. the service migrated, booted, and setup_configuration provisioned the token
and the Objecttypen service it trusts. Stdlib only so it runs in a bare python:3-slim container on
the compose network.
"""
import os
import sys
import time
import urllib.error
import urllib.request
BASE = os.environ["OBJECTEN"] # http://<ip>:8000
TOKEN = os.environ["OBJECTEN_TOKEN"]
TIMEOUT = int(os.environ.get("OBJECTEN_TIMEOUT", "60"))
def status(url, token=None):
req = urllib.request.Request(url)
if token:
req.add_header("Authorization", f"Token {token}")
try:
with urllib.request.urlopen(req, timeout=10) as r:
return r.status
except urllib.error.HTTPError as e:
return e.code
except Exception:
return 0
def main():
url = f"{BASE}/api/v2/objects"
deadline = time.time() + TIMEOUT
while time.time() < deadline:
unauth = status(url)
authed = status(url, TOKEN)
if unauth == 401 and authed == 200:
print(f"OK — {url}: no-auth {unauth}, token {authed}")
return 0
time.sleep(3)
print(f"FAIL — {url}: expected no-auth 401 + token 200, got {status(url)} / {status(url, TOKEN)}",
file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
#
# S-18b (#140): assert the Objecten API is healthy + its static token authenticates, against an
# ALREADY-RUNNING stack. Runs the check in a python:3-slim container on the stack network (the
# service is reached by container IP; the runner can't reach published ports — gitea-actions-gotchas.md
# §5/§6). Does NOT manage the stack lifecycle.
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# The dev token provisioned by infra/objecten/setup_configuration/data.yaml.
TOKEN="${OBJECTEN_TOKEN:-1234567890abcdef1234567890abcdef12345678}"
ot="$(docker ps -q --filter 'name=objecten' --filter 'health=healthy' | head -1)"
[ -n "$ot" ] || ot="$(docker ps -q --filter 'name=[-_]objecten[-_]' | head -1)"
[ -n "$ot" ] || { echo "ERROR: no running objecten container — bring the stack up first" >&2; exit 1; }
net="$(docker inspect -f '{{range $k,$_ := .NetworkSettings.Networks}}{{$k}}{{"\n"}}{{end}}' "$ot" | head -1)"
ip="$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$ot")"
echo ">> network=$net objecten=$ip"
cid="$(docker create --network "$net" \
-e "OBJECTEN=http://$ip:8000" -e "OBJECTEN_TOKEN=$TOKEN" \
-e "OBJECTEN_TIMEOUT=${OBJECTEN_TIMEOUT:-60}" \
python:3-slim python /objecten-check.py)"
docker cp "$here/objecten-check.py" "$cid:/objecten-check.py" >/dev/null
rc=0; docker start -a "$cid" || rc=$?
docker rm -f "$cid" >/dev/null
exit $rc