#!/usr/bin/env bash # Phase E operational checks for secs_gemd, run inside the builder image: # 1. serves the gRPC API over a UNIX DOMAIN SOCKET (no TCP exposure), # 2. exposes Prometheus metrics (link/control-state/spool gauges), # 3. shuts down GRACEFULLY on SIGTERM (exit 0, "stopped cleanly"). # Exit 0 = all three hold. set -u cd "$(dirname "${BASH_SOURCE[0]}")/.." SOCK=/tmp/gemd-ops.sock LOG=/tmp/gemd-ops.log rm -f "$SOCK" ./build/secs_gemd --port 5077 --grpc "unix://$SOCK" --metrics 9191 \ --config-dir data > "$LOG" 2>&1 & GEMD=$! sleep 2 fail() { echo "FAIL: $1"; cat "$LOG"; kill -9 $GEMD 2>/dev/null; exit 1; } [ -S "$SOCK" ] || fail "unix socket not created" # Metrics endpoint answers and carries our gauges. exec 3<>/dev/tcp/127.0.0.1/9191 || fail "metrics port closed" printf 'GET /metrics HTTP/1.0\r\n\r\n' >&3 METRICS=$(cat <&3) echo "$METRICS" | grep -q "secsgem_control_state" || fail "control-state gauge missing" echo "$METRICS" | grep -q "secsgem_spool_depth" || fail "spool gauge missing" echo "$METRICS" | grep -q "secsgem_link_selected" || fail "link gauge missing" # A gRPC call over the unix socket (python grpcio in the interop image; in # the builder image fall back to checking the socket accepts a connection). if python3 -c "import grpc" 2>/dev/null; then python3 - "$SOCK" <<'PY' || fail "gRPC over unix socket failed" import sys, grpc ch = grpc.insecure_channel(f"unix://{sys.argv[1]}") grpc.channel_ready_future(ch).result(timeout=5) PY fi # Graceful shutdown: SIGTERM -> exit 0 + the clean-stop line. kill -TERM $GEMD for _ in $(seq 1 50); do kill -0 $GEMD 2>/dev/null || break; sleep 0.1; done if kill -0 $GEMD 2>/dev/null; then fail "still running 5s after SIGTERM"; fi wait $GEMD; RC=$? [ "$RC" = "0" ] || fail "exit code $RC after SIGTERM (want 0)" grep -q "stopped cleanly" "$LOG" || fail "no clean-stop log line" grep -q "shutting down" "$LOG" || fail "no shutdown log line" echo "daemon ops: unix socket + metrics + graceful shutdown all OK"