#!/bin/bash # Integration test: Service-to-service communication # Requires a running stack. Validates inter-service connectivity. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" ENV_FILE="$PROJECT_ROOT/demo.env" if [[ ! -f "$ENV_FILE" ]]; then echo "ERROR: $ENV_FILE not found. Copy demo.env.template to demo.env and configure." exit 1 fi set -a; source "$ENV_FILE"; set +a RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' PASS=0 FAIL=0 pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASS++)); } fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAIL++)); } check() { echo -e "${YELLOW}[CHECK]${NC} $1"; } require_stack_running() { if ! docker ps --filter "name=${COMPOSE_PROJECT_NAME}" --format "{{.Names}}" | grep -q .; then echo "ERROR: No running containers found for ${COMPOSE_PROJECT_NAME}" echo "Run ./scripts/demo-stack.sh deploy first" exit 1 fi } test_grafana_influxdb_integration() { check "Grafana can reach InfluxDB on internal network" if docker exec "${COMPOSE_PROJECT_NAME}-grafana" wget -q --spider http://influxdb:8086/ping 2>/dev/null; then pass "Grafana reaches InfluxDB via internal DNS" else fail "Grafana cannot reach InfluxDB" fi } test_dockhand_proxy_integration() { check "Dockhand can reach Docker via socket proxy" local dockhand_env dockhand_env=$(docker exec "${COMPOSE_PROJECT_NAME}-dockhand" env 2>/dev/null || echo "") if echo "$dockhand_env" | grep -q "DOCKER_HOST=tcp://docker-socket-proxy:2375"; then pass "Dockhand configured with DOCKER_HOST pointing to socket proxy" else fail "Dockhand DOCKER_HOST not configured for socket proxy" fi } test_homepage_discovery() { check "Homepage responds and contains service references" local http_code http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${HOMEPAGE_PORT}" 2>/dev/null || echo "000") if [[ "$http_code" -ge 200 && "$http_code" -lt 400 ]]; then pass "Homepage accessible (HTTP $http_code)" else fail "Homepage not accessible (HTTP $http_code)" fi } test_tubearchivist_redis() { check "Tube Archivist can reach Redis" if docker exec "${COMPOSE_PROJECT_NAME}-ta-redis" redis-cli ping 2>/dev/null | grep -q PONG; then pass "Redis responds to PING" else fail "Redis not responding" fi } test_tubearchivist_elasticsearch() { check "Elasticsearch cluster is healthy" local es_status es_status=$(docker exec "${COMPOSE_PROJECT_NAME}-ta-elasticsearch" curl -sf http://localhost:9200/_cluster/health 2>/dev/null || echo "") if echo "$es_status" | grep -q '"status"'; then pass "Elasticsearch cluster responding" else fail "Elasticsearch not responding" fi } test_network_isolation() { check "Services are on the correct network" local net_count net_count=$(docker network inspect "${COMPOSE_NETWORK_NAME}" --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | wc -w || echo "0") if [[ "$net_count" -ge 14 ]]; then pass "$net_count containers on ${COMPOSE_NETWORK_NAME}" else fail "Only $net_count containers on network (expected >= 14)" fi } require_stack_running echo "======================================" echo "Integration Tests: Service Communication" echo "======================================" echo "" test_grafana_influxdb_integration test_dockhand_proxy_integration test_homepage_discovery test_tubearchivist_redis test_tubearchivist_elasticsearch test_network_isolation echo "" echo "======================================" echo "RESULTS: $PASS passed, $FAIL failed" echo "======================================" [[ $FAIL -eq 0 ]]