RAILIANCE-WP-0012/0013/0014: Core Hub S5 release, CNPG observability, and follow-up workplans
Deliver the inbox-suggestion implementation from WP-0012: Core Hub Helm chart and Makefile targets, CNPG backup status tooling, and updated backup handoff docs. Archive the finished WP-0012 workplan and register ready follow-ups WP-0013 (CNPG backup wiring + restore drill) and WP-0014 (Core Hub Helm cutover and vergabe-teilnahme image refresh).
This commit is contained in:
parent
85f81714f1
commit
df7225dd3e
19 changed files with 1025 additions and 2 deletions
110
tools/core-hub-smoke.sh
Executable file
110
tools/core-hub-smoke.sh
Executable file
|
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
base_url="${CORE_HUB_BASE_URL:-https://hub.coulomb.social}"
|
||||
base_url="${base_url%/}"
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
request() {
|
||||
local name="$1"
|
||||
local url="$2"
|
||||
local expected_status="$3"
|
||||
local body="$tmpdir/${name}.json"
|
||||
local status
|
||||
|
||||
status="$(curl -sS -o "$body" -w "%{http_code}" "$url")"
|
||||
if [[ "$status" != "$expected_status" ]]; then
|
||||
echo "ERROR: expected $url to return $expected_status, got $status" >&2
|
||||
cat "$body" >&2
|
||||
echo >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
health_body="$(request healthz "${base_url}/healthz" 200)"
|
||||
ready_body="$(request readyz "${base_url}/readyz" 200)"
|
||||
|
||||
python3 - "$health_body" "$ready_body" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
for path, filename in (("/healthz", sys.argv[1]), ("/readyz", sys.argv[2])):
|
||||
with open(filename, encoding="utf-8") as fh:
|
||||
payload = json.load(fh)
|
||||
if not isinstance(payload, dict) or payload.get("status") not in {"ok", "ready"}:
|
||||
raise SystemExit(f"{path} did not return an ok/ready health payload")
|
||||
print(f"ok: {path} returned healthy JSON")
|
||||
PY
|
||||
|
||||
openapi_body="$(request openapi "${base_url}/api/v2/openapi.json" 200)"
|
||||
python3 - "$openapi_body" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
required_paths = {
|
||||
"/hubs",
|
||||
"/hub-capability-manifests",
|
||||
"/api-consumers",
|
||||
"/policy-scopes",
|
||||
"/widgets",
|
||||
"/hub-registry",
|
||||
"/widget-types",
|
||||
}
|
||||
|
||||
with open(sys.argv[1], encoding="utf-8") as fh:
|
||||
payload = json.load(fh)
|
||||
|
||||
paths = payload.get("paths")
|
||||
if not isinstance(paths, dict):
|
||||
raise SystemExit("/api/v2/openapi.json did not include an OpenAPI paths object")
|
||||
|
||||
missing = sorted(required_paths - set(paths))
|
||||
if missing:
|
||||
raise SystemExit("OpenAPI missing paths: " + ", ".join(missing))
|
||||
|
||||
print("ok: /api/v2/openapi.json lists expected v2 resources")
|
||||
PY
|
||||
|
||||
widget_types_body="$(request widget-types "${base_url}/api/v2/widget-types" 200)"
|
||||
python3 - "$widget_types_body" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
with open(sys.argv[1], encoding="utf-8") as fh:
|
||||
payload = json.load(fh)
|
||||
|
||||
if not isinstance(payload, list) or not payload:
|
||||
raise SystemExit("/api/v2/widget-types did not return a non-empty JSON list")
|
||||
|
||||
print("ok: /api/v2/widget-types returned public discovery JSON")
|
||||
PY
|
||||
|
||||
for endpoint in hubs hub-registry widgets; do
|
||||
body="$(request "${endpoint}-protected" "${base_url}/api/v2/${endpoint}" 401)"
|
||||
python3 - "$body" "/api/v2/${endpoint}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
with open(sys.argv[1], encoding="utf-8") as fh:
|
||||
payload = json.load(fh)
|
||||
|
||||
path = sys.argv[2]
|
||||
if not isinstance(payload, dict):
|
||||
raise SystemExit(f"{path} returned 401 but not JSON")
|
||||
|
||||
code = payload.get("code")
|
||||
detail = payload.get("detail")
|
||||
if code == "invalid_api_key":
|
||||
print(f"ok: {path} requires an API key")
|
||||
elif isinstance(detail, dict) and detail.get("code") == "unauthorized":
|
||||
print(f"ok: {path} requires bearer authentication")
|
||||
else:
|
||||
raise SystemExit(f"{path} returned 401 but not a recognized auth error payload")
|
||||
PY
|
||||
done
|
||||
|
||||
echo "ok: Core Hub public smoke checks passed for ${base_url}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue