Files
VoxVera/scripts/docker-runtime-smoke.sh
T

110 lines
3.6 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
if ! command -v docker >/dev/null 2>&1; then
echo "docker is not installed; skipping Docker runtime smoke"
exit 0
fi
IMAGE_TAG="${VOXVERA_DOCKER_SMOKE_TAG:-voxvera:smoke}"
CONTAINER_NAME="${VOXVERA_DOCKER_SMOKE_CONTAINER:-voxvera-smoke}"
TMP_DIR="${VOXVERA_DOCKER_SMOKE_TMPDIR:-$(mktemp -d /tmp/voxvera-docker-smoke-XXXXXX)}"
FLYERS_DIR="$TMP_DIR/flyers"
mkdir -p "$FLYERS_DIR"
cleanup() {
docker logs "$CONTAINER_NAME" >/dev/null 2>&1 || true
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
if [[ -z "${VOXVERA_DOCKER_SMOKE_TMPDIR:-}" ]]; then
chmod -R u+w "$TMP_DIR" 2>/dev/null || true
docker run --rm -v "$TMP_DIR:/cleanup" python:3.11-slim sh -lc 'rm -rf /cleanup/* /cleanup/.[!.]* /cleanup/..?* 2>/dev/null || true' >/dev/null 2>&1 || true
rm -rf "$TMP_DIR" 2>/dev/null || true
fi
}
trap cleanup EXIT
echo "==> building Docker image"
docker build -t "$IMAGE_TAG" .
echo "==> starting Docker container"
docker run -d \
--name "$CONTAINER_NAME" \
--restart no \
-e VOXVERA_START_INTERVAL=15 \
-v "$FLYERS_DIR:/flyers" \
"$IMAGE_TAG" >/dev/null
echo "==> waiting for healthy container"
deadline=$((SECONDS + 240))
while true; do
status="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}no-healthcheck{{end}}' "$CONTAINER_NAME")"
case "$status" in
healthy)
break
;;
unhealthy)
echo "Container became unhealthy" >&2
docker logs "$CONTAINER_NAME" >&2 || true
exit 1
;;
esac
if (( SECONDS >= deadline )); then
echo "Timed out waiting for healthy Docker container" >&2
docker logs "$CONTAINER_NAME" >&2 || true
exit 1
fi
sleep 5
done
PLATFORM_JSON="$TMP_DIR/platform-status.json"
DOCTOR_JSON="$TMP_DIR/doctor.json"
docker exec "$CONTAINER_NAME" voxvera platform-status --json >"$PLATFORM_JSON"
docker exec "$CONTAINER_NAME" voxvera doctor --json >"$DOCTOR_JSON"
PLATFORM_JSON="$PLATFORM_JSON" \
DOCTOR_JSON="$DOCTOR_JSON" \
FLYERS_DIR="$FLYERS_DIR" \
python3 - <<'PY'
import json
import os
import sys
from pathlib import Path
platform_status = json.loads(Path(os.environ["PLATFORM_JSON"]).read_text(encoding="utf-8"))
doctor = json.loads(Path(os.environ["DOCTOR_JSON"]).read_text(encoding="utf-8"))
flyers_dir = Path(os.environ["FLYERS_DIR"])
errors = []
if platform_status.get("platform_id") != "docker_cli":
errors.append(f"platform_id mismatch: {platform_status.get('platform_id')}")
if platform_status.get("tier") != "experimental":
errors.append(f"tier mismatch: {platform_status.get('tier')}")
checks = {check["name"]: check for check in doctor.get("checks", [])}
for required in ("container_marker", "docker_entrypoint", "docker_healthcheck", "tor_socks_reachable", "host_root"):
check = checks.get(required)
if not check:
errors.append(f"missing doctor check: {required}")
elif not check.get("ok"):
errors.append(f"doctor check failed: {required} ({check.get('detail')})")
site_dir = flyers_dir / "host" / "voxvera"
for path in (flyers_dir / "config.json", site_dir / "config.json", site_dir / "index.html", site_dir / ".onionshare-session", site_dir / "server.pid"):
if not path.exists():
errors.append(f"missing expected Docker runtime artifact: {path}")
if errors:
print("Docker runtime smoke failed:", file=sys.stderr)
for error in errors:
print(f"- {error}", file=sys.stderr)
sys.exit(1)
print("Docker runtime smoke OK")
print(f"Platform: {platform_status['label']} [{platform_status['tier']}]")
print(f"Hosting model: {platform_status.get('hosting_model', '')}")
PY