From 0da2f77035665eb7096986f99cb877af4d0bc856 Mon Sep 17 00:00:00 2001 From: Max Mayfield Date: Sun, 1 Mar 2026 22:40:29 +0000 Subject: [PATCH] Fix smoke-test.sh: correct port parsing, webhook slug path, 404 as valid response, arithmetic safety --- products/smoke-test.sh | 264 ++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 136 deletions(-) diff --git a/products/smoke-test.sh b/products/smoke-test.sh index 0b9247a..377fe56 100755 --- a/products/smoke-test.sh +++ b/products/smoke-test.sh @@ -1,206 +1,198 @@ #!/bin/bash -# Smoke Test Script for Docker Compose Stack +# Smoke Test Script for dd0c Docker Compose Stack # Tests health endpoints, tenant creation, and key API endpoints for all services -set -e +set -euo pipefail # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' -NC='\033[0m' # No Color +NC='\033[0m' # Configuration BASE_URL="${BASE_URL:-localhost}" PROTOCOL="${PROTOCOL:-http}" -TEST_EMAIL="smoke@dd0c.dev" -TEST_PASSWORD="smoketest123!" -TEST_TENANT="smoke-test" +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_CHECKS=0 -PASSED_CHECKS=0 +TOTAL=0 +PASSED=0 -# Help function show_help() { cat << EOF -Smoke Test Script for Docker Compose Stack +dd0c Smoke Test Usage: $0 [OPTIONS] Options: - --help Show this help message + --help Show this help --base-url URL Set base URL (default: localhost) --protocol PROTO Set protocol (default: http) - -Environment Variables: - BASE_URL Override base URL (default: localhost) - PROTOCOL Override protocol (default: http) + --skip-rust Skip Rust service checks (P1 route) Examples: - $0 - $0 --base-url example.com --protocol https - BASE_URL=192.168.1.100 $0 - + $0 --base-url 192.168.86.11 + BASE_URL=192.168.86.11 $0 --skip-rust EOF } -# Parse arguments +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 - ;; - *) - echo "Unknown option: $1" - show_help - exit 1 - ;; + --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 -# Helper functions -log_check() { - local name=$1 - local status=$2 - ((TOTAL_CHECKS++)) - +check() { + local name=$1 status=$2 + ((TOTAL++)) || true if [ "$status" = "pass" ]; then - echo -e "${GREEN}✓${NC} $name" - ((PASSED_CHECKS++)) + echo -e " ${GREEN}✓${NC} $name" >&2 + ((PASSED++)) || true else - echo -e "${RED}✗${NC} $name" + echo -e " ${RED}✗${NC} $name" >&2 fi } -check_health() { - local service=$1 - local check_cmd=$2 - - if eval "$check_cmd" > /dev/null 2>&1; then - log_check "Health: $service" "pass" - else - log_check "Health: $service" "fail" - fi -} +url() { echo "${PROTOCOL}://${BASE_URL}:$1$2"; } -create_tenant() { - local port=$1 - local service=$2 - - local response=$(curl -s -X POST \ - "${PROTOCOL}://${BASE_URL}:${port}/api/v1/auth/signup" \ +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\": \"${TEST_EMAIL}\", - \"password\": \"${TEST_PASSWORD}\", - \"tenant_name\": \"${TEST_TENANT}\" - }" 2>/dev/null || echo "") - - local token=$(echo "$response" | grep -o '"token":"[^"]*' | cut -d'"' -f4 || echo "") - + -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 - log_check "Tenant Creation: $service (port $port)" "pass" + check "Signup: $name (:$port)" "pass" echo "$token" else - log_check "Tenant Creation: $service (port $port)" "fail" + check "Signup: $name (:$port) — $(echo "$resp" | head -c 80)" "fail" echo "" fi } -test_endpoint() { - local port=$1 - local service=$2 - local endpoint=$3 - local token=$4 - - if [ -z "$token" ]; then - log_check "Endpoint: $service - $endpoint" "fail" - return - fi - - local http_code=$(curl -s -o /dev/null -w "%{http_code}" \ - -H "Authorization: Bearer $token" \ - "${PROTOCOL}://${BASE_URL}:${port}${endpoint}" 2>/dev/null || echo "000") - - if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then - log_check "Endpoint: $service - $endpoint" "pass" +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 - log_check "Endpoint: $service - $endpoint (HTTP $http_code)" "fail" + check "Login: $name (:$port)" "fail" fi } -# Main execution -echo -e "${YELLOW}=== Smoke Test Starting ===${NC}\n" +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 +} -# 1. Health Checks -echo -e "${YELLOW}--- Health Checks ---${NC}" -check_health "PostgreSQL" "pg_isready -h ${BASE_URL} 2>/dev/null" -check_health "Redis" "redis-cli -h ${BASE_URL} ping > /dev/null 2>&1" +# ─── Run ─── -for port in 3001 3002 3003 3004 3005 3006; do - check_health "HTTP Service (port $port)" "curl -s -o /dev/null -w '%{http_code}' ${PROTOCOL}://${BASE_URL}:${port}/health 2>/dev/null | grep -q '200'" +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 -check_health "Route Proxy (port 8080)" "curl -s -o /dev/null -w '%{http_code}' ${PROTOCOL}://${BASE_URL}:8080/health 2>/dev/null | grep -q '200'" +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 -echo "" +# 2. Auth flow +echo -e "\n${YELLOW}Auth (signup → login → /me)${NC}" -# 2. Tenant Creation & API Tests -echo -e "${YELLOW}--- Tenant Creation & API Tests ---${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") -# P1 (port 3001) -echo -e "\n${YELLOW}P1 - route (port 3001):${NC}" -P1_TOKEN=$(create_tenant 3001 "P1") -test_endpoint 3001 "P1" "/api/v1/usage" "$P1_TOKEN" +login $PORT_ALERT "alert" -# P2 (port 3002) -echo -e "\n${YELLOW}P2 - drift (port 3002):${NC}" -P2_TOKEN=$(create_tenant 3002 "P2") -test_endpoint 3002 "P2" "/api/v1/reports" "$P2_TOKEN" +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 -# P3 (port 3003) -echo -e "\n${YELLOW}P3 - alert (port 3003):${NC}" -P3_TOKEN=$(create_tenant 3003 "P3") -test_endpoint 3003 "P3" "/api/v1/incidents" "$P3_TOKEN" -test_endpoint 3003 "P3" "/api/v1/summary" "$P3_TOKEN" +# 3. Product API endpoints +echo -e "\n${YELLOW}Product APIs${NC}" -# P4 (port 3004) -echo -e "\n${YELLOW}P4 (port 3004):${NC}" -P4_TOKEN=$(create_tenant 3004 "P4") -test_endpoint 3004 "P4" "/api/v1/services" "$P4_TOKEN" -test_endpoint 3004 "P4" "/api/v1/discovery/history" "$P4_TOKEN" +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" -# P5 (port 3005) -echo -e "\n${YELLOW}P5 (port 3005):${NC}" -P5_TOKEN=$(create_tenant 3005 "P5") -test_endpoint 3005 "P5" "/api/v1/anomalies" "$P5_TOKEN" -test_endpoint 3005 "P5" "/api/v1/baselines" "$P5_TOKEN" -test_endpoint 3005 "P5" "/api/v1/governance" "$P5_TOKEN" - -# P6 (port 3006) -echo -e "\n${YELLOW}P6 (port 3006):${NC}" -P6_TOKEN=$(create_tenant 3006 "P6") -test_endpoint 3006 "P6" "/api/v1/runbooks" "$P6_TOKEN" -test_endpoint 3006 "P6" "/api/v1/approvals" "$P6_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}=== Summary ===${NC}" -if [ $PASSED_CHECKS -eq $TOTAL_CHECKS ]; then - echo -e "${GREEN}$PASSED_CHECKS/$TOTAL_CHECKS passed${NC}" +echo -e "${YELLOW}═══════════════════════════${NC}" +if [ "$PASSED" -eq "$TOTAL" ]; then + echo -e "${GREEN}ALL PASSED: $PASSED/$TOTAL${NC}" exit 0 else - echo -e "${RED}$PASSED_CHECKS/$TOTAL_CHECKS passed${NC}" + echo -e "${RED}$PASSED/$TOTAL passed ($((TOTAL - PASSED)) failed)${NC}" exit 1 fi