#!/bin/sh set -e # Integration test runner for API gateway. # Runs against a real canary pod in-cluster (has real secrets + upstreams). # GW env var must be set: e.g. http://10.244.1.5:8080 # # Required env: # GW — gateway base URL # RESULTS_DIR — directory to write result/summary files PASS=0; FAIL=0; TOTAL=0 assert() { NAME="$1"; EXPECT="$2" shift 2 TOTAL=$((TOTAL + 1)) CODE=$(curl -s -o /dev/null -w '%{http_code}' "$@" 2>/dev/null || echo "000") if [ "$CODE" = "$EXPECT" ]; then echo " ✓ ${NAME} (${CODE})" PASS=$((PASS + 1)) else echo " ✗ ${NAME} — expected ${EXPECT}, got ${CODE}" FAIL=$((FAIL + 1)) fi } # ── Wait for gateway ────────────────────────────────────────────────────────── echo "⏳ Waiting for gateway at ${GW}..." READY=false for i in $(seq 1 30); do CODE=$(curl -s -o /dev/null -w '%{http_code}' "${GW}/healthz" 2>/dev/null || echo "000") if [ "$CODE" = "200" ]; then READY=true echo "✓ Gateway ready" break fi sleep 2 done if [ "$READY" = "false" ]; then echo "✗ Gateway never became ready" echo "fail" > "${RESULTS_DIR}/result" echo "0/0 timeout" > "${RESULTS_DIR}/summary" exit 1 fi echo "" echo "═══ Integration Tests ═══" echo "" # ── Health ──────────────────────────────────────────────────────────────────── echo "▸ Health" assert "GET /healthz" 200 -X GET "${GW}/healthz" assert "GET /readyz" 200 -X GET "${GW}/readyz" # ── Header validation ───────────────────────────────────────────────────────── echo "▸ Header validation" assert "X-Service without X-Resource → 400" 400 \ -X GET -H "X-Service: memory" "${GW}/" assert "unknown service → 404" 404 \ -X GET -H "X-Service: nonexistent" -H "X-Resource: foo" "${GW}/" # ── S3 (no auth, MinIO rejects → 403) ──────────────────────────────────────── echo "▸ S3 service" assert "s3/list-objects → 403" 403 \ -X GET -H "X-Service: s3" -H "X-Resource: list-objects" "${GW}/" # ── SQS (auth required → 401) ───────────────────────────────────────────────── echo "▸ SQS service" assert "sqs/list-queues → 401" 401 \ -X GET -H "X-Service: sqs" -H "X-Resource: list-queues" "${GW}/" # ── Workflow ────────────────────────────────────────────────────────────────── echo "▸ Workflow service" # List with namespace — real Temporal call. # 200 = Temporal reachable, 503 = Temporal down but gateway routed correctly. echo " Testing workflow list (poimen-harness namespace)..." WF_LIST=$(curl -s \ -H "X-Service: workflow" \ -H "X-Resource: list" \ -H "Content-Type: application/json" \ -d '{"namespace": "poimen-harness"}' \ "${GW}/" 2>/dev/null || echo '{}') TOTAL=$((TOTAL + 1)) if echo "$WF_LIST" | grep -qE '"executions"|"TEMPORAL_UNAVAILABLE"'; then echo " ✓ workflow/list responded correctly" PASS=$((PASS + 1)) else echo " ✗ workflow/list unexpected: $WF_LIST" FAIL=$((FAIL + 1)) fi # Namespace is required — canary pod has real WorkflowAdapter → must return 400 assert "workflow/list without namespace → 400" 400 \ -X POST \ -H "X-Service: workflow" \ -H "X-Resource: list" \ -H "Content-Type: application/json" \ -d '{}' \ "${GW}/" # ── Forgejo webhook ─────────────────────────────────────────────────────────── echo "▸ Forgejo webhook" # Canary pod has real handler wired. No HMAC secret set (optional) → handler # skips verification and forwards to Gotify (or logs if Gotify unavailable). assert "POST /v1/webhooks/forgejo → 200" 200 \ -X POST \ -H "Content-Type: application/json" \ -H "X-Gitea-Event: push" \ -d '{"ref":"refs/heads/main","commits":[{"message":"test"}],"repository":{"full_name":"test/repo"},"sender":{"login":"ci"}}' \ "${GW}/v1/webhooks/forgejo" echo "" echo "═══ Results: ${PASS}/${TOTAL} passed, ${FAIL} failed ═══" if [ "$FAIL" -eq 0 ]; then echo "pass" > "${RESULTS_DIR}/result" else echo "fail" > "${RESULTS_DIR}/result" fi echo "${PASS}/${TOTAL} passed, ${FAIL} failed" > "${RESULTS_DIR}/summary" [ "$FAIL" -eq 0 ]