203 lines
6.0 KiB
Bash
Executable File
203 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# End-to-end test runner for EVOLV Node-RED stack.
|
|
# Starts Node-RED + InfluxDB + Grafana via Docker Compose,
|
|
# verifies that EVOLV nodes are registered in the palette,
|
|
# and tears down the stack on exit.
|
|
#
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.e2e.yml"
|
|
|
|
NODERED_URL="http://localhost:1880"
|
|
MAX_WAIT=120 # seconds to wait for Node-RED to become healthy
|
|
GRAFANA_URL="http://localhost:3000/api/health"
|
|
MAX_GRAFANA_WAIT=60
|
|
|
|
# EVOLV node types that must appear in the palette (from package.json node-red.nodes)
|
|
EXPECTED_NODES=(
|
|
"dashboardapi"
|
|
"machineGroupControl"
|
|
"measurement"
|
|
"monster"
|
|
"pumpingstation"
|
|
"reactor"
|
|
"rotatingMachine"
|
|
"settler"
|
|
"valve"
|
|
"valveGroupControl"
|
|
)
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
|
|
|
# Determine docker compose command (handle permission via sg docker if needed)
|
|
USE_SG_DOCKER=false
|
|
if ! docker info >/dev/null 2>&1; then
|
|
if sg docker -c "docker info" >/dev/null 2>&1; then
|
|
USE_SG_DOCKER=true
|
|
log_info "Using sg docker for Docker access"
|
|
else
|
|
log_error "Docker is not accessible. Please ensure Docker is running and you have permissions."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
run_compose() {
|
|
if [ "$USE_SG_DOCKER" = true ]; then
|
|
local cmd="docker compose -f $(printf '%q' "$COMPOSE_FILE")"
|
|
local arg
|
|
for arg in "$@"; do
|
|
cmd+=" $(printf '%q' "$arg")"
|
|
done
|
|
sg docker -c "$cmd"
|
|
else
|
|
docker compose -f "$COMPOSE_FILE" "$@"
|
|
fi
|
|
}
|
|
|
|
cleanup() {
|
|
log_info "Tearing down E2E stack..."
|
|
run_compose down --volumes --remove-orphans 2>/dev/null || true
|
|
}
|
|
|
|
# Always clean up on exit
|
|
trap cleanup EXIT
|
|
|
|
# --- Step 1: Build and start the stack ---
|
|
log_info "Building and starting E2E stack..."
|
|
run_compose up -d --build
|
|
|
|
# --- Step 2: Wait for Node-RED to be healthy ---
|
|
log_info "Waiting for Node-RED to become healthy (max ${MAX_WAIT}s)..."
|
|
elapsed=0
|
|
while [ $elapsed -lt $MAX_WAIT ]; do
|
|
if curl -sf "$NODERED_URL/" >/dev/null 2>&1; then
|
|
log_info "Node-RED is up after ${elapsed}s"
|
|
break
|
|
fi
|
|
sleep 2
|
|
elapsed=$((elapsed + 2))
|
|
done
|
|
|
|
if [ $elapsed -ge $MAX_WAIT ]; then
|
|
log_error "Node-RED did not become healthy within ${MAX_WAIT}s"
|
|
log_error "Container logs:"
|
|
run_compose logs nodered
|
|
exit 1
|
|
fi
|
|
|
|
# Give Node-RED a few extra seconds to finish loading all nodes
|
|
sleep 5
|
|
|
|
# --- Step 3: Verify EVOLV nodes are registered in the palette ---
|
|
log_info "Querying Node-RED for registered nodes..."
|
|
NODES_RESPONSE=$(curl -sf "$NODERED_URL/nodes" 2>&1) || {
|
|
log_error "Failed to query Node-RED /nodes endpoint"
|
|
exit 1
|
|
}
|
|
|
|
FAILURES=0
|
|
for node_type in "${EXPECTED_NODES[@]}"; do
|
|
if echo "$NODES_RESPONSE" | grep -qi "$node_type"; then
|
|
log_info " [PASS] Node type '$node_type' found in palette"
|
|
else
|
|
log_error " [FAIL] Node type '$node_type' NOT found in palette"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
done
|
|
|
|
# --- Step 4: Verify flows are deployed ---
|
|
log_info "Checking deployed flows..."
|
|
FLOWS_RESPONSE=$(curl -sf "$NODERED_URL/flows" 2>&1) || {
|
|
log_error "Failed to query Node-RED /flows endpoint"
|
|
exit 1
|
|
}
|
|
|
|
if echo "$FLOWS_RESPONSE" | grep -q "e2e-flow-tab"; then
|
|
log_info " [PASS] E2E test flow is deployed"
|
|
else
|
|
log_warn " [WARN] E2E test flow not found in deployed flows (may need manual deploy)"
|
|
fi
|
|
|
|
# --- Step 5: Verify InfluxDB is reachable ---
|
|
log_info "Checking InfluxDB health..."
|
|
INFLUX_HEALTH=$(curl -sf "http://localhost:8086/health" 2>&1) || {
|
|
log_error "Failed to reach InfluxDB health endpoint"
|
|
FAILURES=$((FAILURES + 1))
|
|
}
|
|
|
|
if echo "$INFLUX_HEALTH" | grep -q '"status":"pass"'; then
|
|
log_info " [PASS] InfluxDB is healthy"
|
|
else
|
|
log_error " [FAIL] InfluxDB health check failed"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
|
|
# --- Step 5b: Verify Grafana is reachable ---
|
|
log_info "Checking Grafana health..."
|
|
GRAFANA_HEALTH=""
|
|
elapsed=0
|
|
while [ $elapsed -lt $MAX_GRAFANA_WAIT ]; do
|
|
GRAFANA_HEALTH=$(curl -sf "$GRAFANA_URL" 2>&1) && break
|
|
sleep 2
|
|
elapsed=$((elapsed + 2))
|
|
done
|
|
|
|
if echo "$GRAFANA_HEALTH" | grep -Eq '"database"[[:space:]]*:[[:space:]]*"ok"'; then
|
|
log_info " [PASS] Grafana is healthy"
|
|
else
|
|
log_error " [FAIL] Grafana health check failed"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
|
|
# --- Step 5c: Verify EVOLV measurement node produced output ---
|
|
log_info "Checking EVOLV measurement node output in container logs..."
|
|
NODERED_LOGS=$(run_compose logs nodered 2>&1)
|
|
|
|
if echo "$NODERED_LOGS" | grep -q "Database Output"; then
|
|
log_info " [PASS] EVOLV measurement node produced database output"
|
|
else
|
|
log_warn " [WARN] EVOLV measurement node output not detected in logs"
|
|
fi
|
|
|
|
if echo "$NODERED_LOGS" | grep -q "Process Output"; then
|
|
log_info " [PASS] EVOLV measurement node produced process output"
|
|
else
|
|
log_warn " [WARN] EVOLV measurement process output not detected in logs"
|
|
fi
|
|
|
|
if echo "$NODERED_LOGS" | grep -q "Monster Process Output"; then
|
|
log_info " [PASS] EVOLV monster node produced process output"
|
|
else
|
|
log_warn " [WARN] EVOLV monster process output not detected in logs"
|
|
fi
|
|
|
|
if echo "$NODERED_LOGS" | grep -q "Monster Database Output"; then
|
|
log_info " [PASS] EVOLV monster node produced database output"
|
|
else
|
|
log_warn " [WARN] EVOLV monster database output not detected in logs"
|
|
fi
|
|
|
|
# --- Step 6: Summary ---
|
|
echo ""
|
|
if [ $FAILURES -eq 0 ]; then
|
|
log_info "========================================="
|
|
log_info " E2E tests PASSED - all checks green"
|
|
log_info "========================================="
|
|
exit 0
|
|
else
|
|
log_error "========================================="
|
|
log_error " E2E tests FAILED - $FAILURES check(s) failed"
|
|
log_error "========================================="
|
|
exit 1
|
|
fi
|