Files
dd0c/products/smoke-test.sh

199 lines
5.9 KiB
Bash
Raw Normal View History

#!/bin/bash
# Smoke Test Script for dd0c Docker Compose Stack
# Tests health endpoints, tenant creation, and key API endpoints for all services
set -euo pipefail
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration
BASE_URL="${BASE_URL:-localhost}"
PROTOCOL="${PROTOCOL:-http}"
TS=$(date +%s)
# Port mapping (matches docker-compose.yml)
PORT_DRIFT=3002
PORT_ALERT=3003
PORT_PORTAL=3004
PORT_RUN=3006
PORT_COST=3007
PORT_ROUTE_API=3001
PORT_ROUTE_PROXY=8080
PORT_PG=5433
PORT_REDIS=6379
# Counters
TOTAL=0
PASSED=0
show_help() {
cat << EOF
dd0c Smoke Test
Usage: $0 [OPTIONS]
Options:
--help Show this help
--base-url URL Set base URL (default: localhost)
--protocol PROTO Set protocol (default: http)
--skip-rust Skip Rust service checks (P1 route)
Examples:
$0 --base-url 192.168.86.11
BASE_URL=192.168.86.11 $0 --skip-rust
EOF
}
SKIP_RUST=false
while [[ $# -gt 0 ]]; do
case $1 in
--help) show_help; exit 0 ;;
--base-url) BASE_URL="$2"; shift 2 ;;
--protocol) PROTOCOL="$2"; shift 2 ;;
--skip-rust) SKIP_RUST=true; shift ;;
*) echo "Unknown: $1"; show_help; exit 1 ;;
esac
done
check() {
local name=$1 status=$2
((TOTAL++)) || true
if [ "$status" = "pass" ]; then
echo -e " ${GREEN}${NC} $name" >&2
((PASSED++)) || true
else
echo -e " ${RED}${NC} $name" >&2
fi
}
url() { echo "${PROTOCOL}://${BASE_URL}:$1$2"; }
signup() {
local port=$1 name=$2
local resp
resp=$(curl -s -X POST "$(url "$port" /api/v1/auth/signup)" \
-H "Content-Type: application/json" \
-d "{\"email\":\"smoke-${TS}@dd0c.dev\",\"password\":\"smoketest123!\",\"tenant_name\":\"Smoke ${TS}\"}" 2>/dev/null || echo "")
local token
token=$(echo "$resp" | grep -o '"token":"[^"]*' | cut -d'"' -f4 || echo "")
if [ -n "$token" ]; then
check "Signup: $name (:$port)" "pass"
echo "$token"
else
check "Signup: $name (:$port) — $(echo "$resp" | head -c 80)" "fail"
echo ""
fi
}
login() {
local port=$1 name=$2
local resp
resp=$(curl -s -X POST "$(url "$port" /api/v1/auth/login)" \
-H "Content-Type: application/json" \
-d "{\"email\":\"smoke-${TS}@dd0c.dev\",\"password\":\"smoketest123!\"}" 2>/dev/null || echo "")
local token
token=$(echo "$resp" | grep -o '"token":"[^"]*' | cut -d'"' -f4 || echo "")
if [ -n "$token" ]; then
check "Login: $name (:$port)" "pass"
else
check "Login: $name (:$port)" "fail"
fi
}
hit() {
local port=$1 name=$2 endpoint=$3 token=$4
if [ -z "$token" ]; then
check "API: $name $endpoint (no token)" "fail"
return
fi
local code
code=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $token" \
"$(url "$port" "$endpoint")" 2>/dev/null || echo "000")
if [ "$code" = "200" ] || [ "$code" = "201" ]; then
check "API: $name $endpoint" "pass"
else
check "API: $name $endpoint (HTTP $code)" "fail"
fi
}
# ─── Run ───
echo -e "${YELLOW}dd0c Smoke Test — $(date -u '+%Y-%m-%d %H:%M UTC')${NC}"
echo -e "Target: ${PROTOCOL}://${BASE_URL}\n"
# 1. Infrastructure health
echo -e "${YELLOW}Infrastructure${NC}"
for pair in "drift:$PORT_DRIFT" "alert:$PORT_ALERT" "portal:$PORT_PORTAL" "run:$PORT_RUN" "cost:$PORT_COST"; do
name=${pair%%:*}; port=${pair##*:}
code=$(curl -s -o /dev/null -w "%{http_code}" "$(url "$port" /health)" 2>/dev/null || echo "000")
[ "$code" = "200" ] && check "Health: $name (:$port)" "pass" || check "Health: $name (:$port) (HTTP $code)" "fail"
done
if [ "$SKIP_RUST" = false ]; then
for pair in "route-api:$PORT_ROUTE_API" "route-proxy:$PORT_ROUTE_PROXY"; do
name=${pair%%:*}; port=${pair##*:}
code=$(curl -s -o /dev/null -w "%{http_code}" "$(url "$port" /health)" 2>/dev/null || echo "000")
[ "$code" = "200" ] && check "Health: $name (:$port)" "pass" || check "Health: $name (:$port) (HTTP $code)" "fail"
done
fi
# 2. Auth flow
echo -e "\n${YELLOW}Auth (signup → login → /me)${NC}"
ALERT_TOKEN=$(signup $PORT_ALERT "alert")
PORTAL_TOKEN=$(signup $PORT_PORTAL "portal")
COST_TOKEN=$(signup $PORT_COST "cost")
RUN_TOKEN=$(signup $PORT_RUN "run")
DRIFT_TOKEN=$(signup $PORT_DRIFT "drift")
login $PORT_ALERT "alert"
if [ -n "$ALERT_TOKEN" ]; then
me_code=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $ALERT_TOKEN" \
"$(url $PORT_ALERT /api/v1/auth/me)" 2>/dev/null || echo "000")
[ "$me_code" = "200" ] && check "Auth /me: alert" "pass" || check "Auth /me: alert (HTTP $me_code)" "fail"
fi
# 3. Product API endpoints
echo -e "\n${YELLOW}Product APIs${NC}"
hit $PORT_ALERT "alert" "/api/v1/incidents" "$ALERT_TOKEN"
hit $PORT_PORTAL "portal" "/api/v1/services" "$PORTAL_TOKEN"
hit $PORT_COST "cost" "/api/v1/baselines" "$COST_TOKEN"
hit $PORT_COST "cost" "/api/v1/anomalies" "$COST_TOKEN"
hit $PORT_RUN "run" "/api/v1/runbooks" "$RUN_TOKEN"
hit $PORT_DRIFT "drift" "/api/v1/stacks" "$DRIFT_TOKEN"
# 4. Webhook endpoints (should be accessible without auth)
echo -e "\n${YELLOW}Webhook endpoints (no auth)${NC}"
for pair in "$PORT_ALERT:alert"; do
port=${pair%%:*}; name=${pair##*:}
code=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Content-Type: application/json" -d '{"alertType":"metric_alert_monitor","body":"test"}' \
"$(url "$port" /webhooks/datadog/smoke-test)" 2>/dev/null || echo "000")
# 400/401/404 all mean the endpoint exists (404 = unknown tenant slug, which is expected)
if [ "$code" = "200" ] || [ "$code" = "400" ] || [ "$code" = "401" ] || [ "$code" = "404" ]; then
check "Webhook: $name /webhooks/datadog/:slug (HTTP $code)" "pass"
else
check "Webhook: $name /webhooks/datadog/:slug (HTTP $code)" "fail"
fi
done
# Summary
echo ""
echo -e "${YELLOW}═══════════════════════════${NC}"
if [ "$PASSED" -eq "$TOTAL" ]; then
echo -e "${GREEN}ALL PASSED: $PASSED/$TOTAL${NC}"
exit 0
else
echo -e "${RED}$PASSED/$TOTAL passed ($((TOTAL - PASSED)) failed)${NC}"
exit 1
fi