Files
content-factory/tests/smoke/public-health.sh
T

132 lines
3.4 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/docker-compose.yml"
BACKEND_URL="${BACKEND_URL:-http://localhost:8000}"
RUNNER_URL="${RUNNER_URL:-http://localhost:8010}"
FRONTEND_URL="${FRONTEND_URL:-http://localhost:3000}"
WAIT_SECONDS="${WAIT_SECONDS:-60}"
PYTHON_BIN="${PYTHON_BIN:-python3}"
cleanup() {
docker compose -f "${COMPOSE_FILE}" down --remove-orphans >/dev/null 2>&1 || true
}
fetch_health() {
local name="$1"
local url="$2"
local deadline=$((SECONDS + WAIT_SECONDS))
local body
while (( SECONDS < deadline )); do
if body="$(curl -fsS "${url}" 2>/dev/null)"; then
printf '%s' "${body}"
return 0
fi
sleep 1
done
echo "Timed out waiting for ${name} at ${url}" >&2
return 1
}
assert_service_health() {
local name="$1"
local url="$2"
local expected_service="$3"
local body
body="$(fetch_health "${name}" "${url}")"
HEALTH_NAME="${name}" EXPECTED_SERVICE="${expected_service}" HEALTH_BODY="${body}" "${PYTHON_BIN}" - <<'PY'
import json
import os
import sys
name = os.environ["HEALTH_NAME"]
expected_service = os.environ["EXPECTED_SERVICE"]
body = os.environ["HEALTH_BODY"]
try:
payload = json.loads(body)
except json.JSONDecodeError as error:
print(f"{name}: expected JSON response, got: {body!r}", file=sys.stderr)
raise SystemExit(1) from error
if payload.get("service") != expected_service:
print(
f"{name}: expected service={expected_service!r}, got {payload.get('service')!r}",
file=sys.stderr,
)
raise SystemExit(1)
if payload.get("status") != "ok":
print(f"{name}: expected status='ok', got {payload.get('status')!r}", file=sys.stderr)
raise SystemExit(1)
PY
echo "${name} health ok"
}
assert_backend_dependencies() {
local body
body="$(fetch_health "backend dependencies" "${BACKEND_URL}/health/dependencies")"
HEALTH_BODY="${body}" "${PYTHON_BIN}" - <<'PY'
import json
import os
import sys
body = os.environ["HEALTH_BODY"]
required = ("postgres", "redis", "object_storage")
try:
payload = json.loads(body)
except json.JSONDecodeError as error:
print(f"backend dependencies: expected JSON response, got: {body!r}", file=sys.stderr)
raise SystemExit(1) from error
if payload.get("service") != "backend":
print(
f"backend dependencies: expected service='backend', got {payload.get('service')!r}",
file=sys.stderr,
)
raise SystemExit(1)
if payload.get("status") != "ok":
print(
f"backend dependencies: expected status='ok', got {payload.get('status')!r}",
file=sys.stderr,
)
raise SystemExit(1)
dependencies = payload.get("dependencies")
if not isinstance(dependencies, dict):
print("backend dependencies: expected dependencies object", file=sys.stderr)
raise SystemExit(1)
failed = [name for name in required if dependencies.get(name) != "ok"]
if failed:
print(
"backend dependencies: expected ok for " + ", ".join(failed),
file=sys.stderr,
)
raise SystemExit(1)
PY
echo "backend dependencies ok"
}
cd "${ROOT_DIR}"
trap cleanup EXIT
echo "Starting stack with docker compose..."
docker compose -f "${COMPOSE_FILE}" up --build -d
assert_service_health "backend" "${BACKEND_URL}/health" "backend"
assert_service_health "runner" "${RUNNER_URL}/health" "runner"
assert_service_health "frontend" "${FRONTEND_URL}/health" "frontend"
assert_backend_dependencies
echo "public health smoke ok"