Files
attune/scripts/test-timer-echo-docker.sh
2026-02-04 17:46:30 -06:00

387 lines
12 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Test Timer Echo Happy Path (Docker Environment)
# Verifies the complete event flow with unified runtime detection
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
API_URL="${ATTUNE_API_URL:-http://localhost:8080}"
API_USER="${ATTUNE_API_USER:-admin}"
API_PASSWORD="${ATTUNE_API_PASSWORD:-admin}"
WAIT_TIME=15 # Time to wait for executions
POLL_INTERVAL=2 # How often to check for executions
echo -e "${BLUE}=== Attune Timer Echo Happy Path Test (Docker) ===${NC}"
echo "API URL: $API_URL"
echo ""
# Function to print colored status
print_status() {
echo -e "${GREEN}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
print_info() {
echo -e "${YELLOW}${NC} $1"
}
# Function to check if a service is healthy
check_service() {
local service=$1
if docker ps --format '{{.Names}}' | grep -q "^${service}$"; then
if docker ps --filter "name=${service}" --filter "health=healthy" --format '{{.Names}}' | grep -q "^${service}$"; then
print_status "Service $service is healthy"
return 0
else
print_error "Service $service is not healthy yet"
return 1
fi
else
print_error "Service $service is not running"
return 1
fi
}
# Step 0: Check Docker services
echo -e "${BLUE}Step 0: Checking Docker services...${NC}"
SERVICES=("attune-api" "attune-executor" "attune-worker" "attune-sensor" "postgres" "rabbitmq")
ALL_HEALTHY=true
for service in "${SERVICES[@]}"; do
if ! check_service "$service" 2>/dev/null; then
ALL_HEALTHY=false
print_info "Service $service not ready yet"
fi
done
if [ "$ALL_HEALTHY" = false ]; then
print_info "Some services are not ready. Waiting 10 seconds..."
sleep 10
fi
echo ""
# Step 1: Login and get JWT token
echo -e "${BLUE}Step 1: Authenticating...${NC}"
LOGIN_RESPONSE=$(curl -s -X POST "$API_URL/auth/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$API_USER\",\"password\":\"$API_PASSWORD\"}")
ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | jq -r '.data.access_token // empty')
if [ -z "$ACCESS_TOKEN" ]; then
print_error "Failed to authenticate"
echo "Response: $LOGIN_RESPONSE"
exit 1
fi
print_status "Authentication successful"
echo ""
# Step 2: Verify runtime detection
echo -e "${BLUE}Step 2: Verifying runtime detection...${NC}"
RUNTIMES_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/runtimes" \
-H "Authorization: Bearer $ACCESS_TOKEN")
SHELL_RUNTIME=$(echo "$RUNTIMES_RESPONSE" | jq -r '.data[] | select(.name == "shell" or .name == "Shell") | .name')
if [ -n "$SHELL_RUNTIME" ]; then
print_status "Shell runtime detected: $SHELL_RUNTIME"
# Get runtime details
RUNTIME_DETAILS=$(echo "$RUNTIMES_RESPONSE" | jq -r ".data[] | select(.name == \"$SHELL_RUNTIME\")")
echo "$RUNTIME_DETAILS" | jq '{name, enabled, distributions}' || echo "$RUNTIME_DETAILS"
else
print_error "Shell runtime not found"
echo "Available runtimes:"
echo "$RUNTIMES_RESPONSE" | jq '.data[] | {name, enabled}'
exit 1
fi
echo ""
# Step 3: Check if core pack exists
echo -e "${BLUE}Step 3: Checking for core pack...${NC}"
PACK_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/packs/core" \
-H "Authorization: Bearer $ACCESS_TOKEN")
PACK_ID=$(echo "$PACK_RESPONSE" | jq -r '.data.id // empty')
if [ -z "$PACK_ID" ]; then
print_error "Core pack not found"
print_info "Attempting to load core pack..."
# Try to load core pack via docker exec
if docker ps --format '{{.Names}}' | grep -q "^attune-api$"; then
docker exec attune-api /opt/attune/scripts/load-core-pack.sh || true
sleep 2
# Retry
PACK_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/packs/core" \
-H "Authorization: Bearer $ACCESS_TOKEN")
PACK_ID=$(echo "$PACK_RESPONSE" | jq -r '.data.id // empty')
if [ -z "$PACK_ID" ]; then
print_error "Failed to load core pack"
exit 1
fi
else
print_error "Cannot load core pack - API container not accessible"
exit 1
fi
fi
print_status "Core pack found (ID: $PACK_ID)"
echo ""
# Step 4: Check interval timer trigger
echo -e "${BLUE}Step 4: Checking for interval timer trigger...${NC}"
TRIGGERS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/triggers" \
-H "Authorization: Bearer $ACCESS_TOKEN")
INTERVAL_TRIGGER=$(echo "$TRIGGERS_RESPONSE" | jq -r '.data[] | select(.ref == "core.intervaltimer") | .ref')
if [ -z "$INTERVAL_TRIGGER" ]; then
print_error "Interval timer trigger not found"
echo "Available triggers:"
echo "$TRIGGERS_RESPONSE" | jq '.data[] | {ref, name}'
exit 1
fi
print_status "Interval timer trigger found"
echo ""
# Step 5: Check echo action
echo -e "${BLUE}Step 5: Checking for echo action...${NC}"
ACTIONS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/actions" \
-H "Authorization: Bearer $ACCESS_TOKEN")
ECHO_ACTION=$(echo "$ACTIONS_RESPONSE" | jq -r '.data[] | select(.ref == "core.echo") | .ref')
if [ -z "$ECHO_ACTION" ]; then
print_error "Echo action not found"
echo "Available actions:"
echo "$ACTIONS_RESPONSE" | jq '.data[] | {ref, name, runtime}'
exit 1
fi
print_status "Echo action found"
ACTION_DETAILS=$(echo "$ACTIONS_RESPONSE" | jq -r '.data[] | select(.ref == "core.echo")')
echo "$ACTION_DETAILS" | jq '{ref, name, runtime, entry_point}'
echo ""
# Step 6: Create trigger instance for 1-second interval
echo -e "${BLUE}Step 6: Creating trigger instance...${NC}"
TRIGGER_INSTANCE_REF="test.timer_1s_$(date +%s)"
CREATE_TRIGGER_RESPONSE=$(curl -s -X POST "$API_URL/api/v1/trigger-instances" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"trigger_type_ref\": \"core.intervaltimer\",
\"ref\": \"$TRIGGER_INSTANCE_REF\",
\"description\": \"Test timer - 1 second interval\",
\"enabled\": true,
\"parameters\": {
\"unit\": \"seconds\",
\"interval\": 1
}
}")
TRIGGER_INSTANCE_ID=$(echo "$CREATE_TRIGGER_RESPONSE" | jq -r '.data.id // empty')
if [ -z "$TRIGGER_INSTANCE_ID" ]; then
print_error "Failed to create trigger instance"
echo "Response: $CREATE_TRIGGER_RESPONSE"
exit 1
fi
print_status "Trigger instance created (ID: $TRIGGER_INSTANCE_ID, Ref: $TRIGGER_INSTANCE_REF)"
echo ""
# Step 7: Create rule linking timer to echo
echo -e "${BLUE}Step 7: Creating rule...${NC}"
RULE_REF="test.timer_echo_1s_$(date +%s)"
CREATE_RULE_RESPONSE=$(curl -s -X POST "$API_URL/api/v1/rules" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"ref\": \"$RULE_REF\",
\"pack_ref\": \"core\",
\"name\": \"Test Timer Echo 1s\",
\"description\": \"Test rule - echoes Hello World every second\",
\"enabled\": true,
\"trigger_instance_ref\": \"$TRIGGER_INSTANCE_REF\",
\"action_ref\": \"core.echo\",
\"action_parameters\": {
\"message\": \"Hello, World! (from unified runtime detection test)\"
}
}")
RULE_ID=$(echo "$CREATE_RULE_RESPONSE" | jq -r '.data.id // empty')
if [ -z "$RULE_ID" ]; then
print_error "Failed to create rule"
echo "Response: $CREATE_RULE_RESPONSE"
exit 1
fi
print_status "Rule created (ID: $RULE_ID, Ref: $RULE_REF)"
echo ""
# Step 8: Wait for executions
echo -e "${BLUE}Step 8: Waiting for executions...${NC}"
print_info "Waiting $WAIT_TIME seconds for timer to fire and action to execute..."
EXECUTION_COUNT=0
START_TIME=$(date +%s)
MAX_WAIT=$((START_TIME + WAIT_TIME))
while [ $(date +%s) -lt $MAX_WAIT ]; do
sleep $POLL_INTERVAL
# Check for executions
EXECUTIONS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/executions?limit=50" \
-H "Authorization: Bearer $ACCESS_TOKEN")
CURRENT_COUNT=$(echo "$EXECUTIONS_RESPONSE" | jq '[.data[] | select(.action_ref == "core.echo")] | length')
if [ "$CURRENT_COUNT" -gt "$EXECUTION_COUNT" ]; then
EXECUTION_COUNT=$CURRENT_COUNT
ELAPSED=$(($(date +%s) - START_TIME))
print_status "Found $EXECUTION_COUNT execution(s) after ${ELAPSED}s"
fi
done
echo ""
# Step 9: Verify executions
echo -e "${BLUE}Step 9: Verifying executions...${NC}"
if [ "$EXECUTION_COUNT" -eq 0 ]; then
print_error "No executions found!"
print_info "Checking system status..."
# Check for events
EVENTS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/events?limit=10" \
-H "Authorization: Bearer $ACCESS_TOKEN")
EVENT_COUNT=$(echo "$EVENTS_RESPONSE" | jq '.data | length')
echo " Events created: $EVENT_COUNT"
# Check for enforcements
ENFORCEMENTS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/enforcements?limit=10" \
-H "Authorization: Bearer $ACCESS_TOKEN")
ENFORCEMENT_COUNT=$(echo "$ENFORCEMENTS_RESPONSE" | jq '.data | length')
echo " Enforcements created: $ENFORCEMENT_COUNT"
print_error "Happy path test FAILED - no executions"
exit 1
fi
print_status "Found $EXECUTION_COUNT execution(s)"
# Get execution details
EXECUTIONS_RESPONSE=$(curl -s -X GET "$API_URL/api/v1/executions?limit=5" \
-H "Authorization: Bearer $ACCESS_TOKEN")
echo ""
echo "Recent executions:"
echo "$EXECUTIONS_RESPONSE" | jq '.data[] | select(.action_ref == "core.echo") | {id, status, action_ref, result: .result.stdout // .result}' | head -20
# Check for successful executions
SUCCESS_COUNT=$(echo "$EXECUTIONS_RESPONSE" | jq '[.data[] | select(.action_ref == "core.echo" and .status == "succeeded")] | length')
if [ "$SUCCESS_COUNT" -gt 0 ]; then
print_status "$SUCCESS_COUNT execution(s) succeeded"
else
print_error "No successful executions found"
echo ""
echo "Execution statuses:"
echo "$EXECUTIONS_RESPONSE" | jq '.data[] | {id, status, action_ref}'
fi
echo ""
# Step 10: Check worker logs for runtime detection
echo -e "${BLUE}Step 10: Checking worker logs for runtime execution...${NC}"
if docker ps --format '{{.Names}}' | grep -q "^attune-worker$"; then
print_info "Recent worker logs:"
docker logs attune-worker --tail 30 | grep -i "runtime\|shell\|echo\|executing" || echo " (no matching log entries)"
else
print_info "Worker container not accessible for log inspection"
fi
echo ""
# Step 11: Cleanup
echo -e "${BLUE}Step 11: Cleanup...${NC}"
# Disable the rule
print_info "Disabling rule..."
curl -s -X PUT "$API_URL/api/v1/rules/$RULE_REF" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}' > /dev/null
print_status "Rule disabled"
# Optionally delete the rule and trigger instance
read -p "Delete test rule and trigger instance? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
curl -s -X DELETE "$API_URL/api/v1/rules/$RULE_REF" \
-H "Authorization: Bearer $ACCESS_TOKEN" > /dev/null
curl -s -X DELETE "$API_URL/api/v1/trigger-instances/$TRIGGER_INSTANCE_REF" \
-H "Authorization: Bearer $ACCESS_TOKEN" > /dev/null
print_status "Test resources deleted"
else
print_info "Test resources left in place (disabled)"
fi
echo ""
# Final summary
echo -e "${BLUE}=== Test Summary ===${NC}"
echo ""
echo "✓ Runtime detection working (Shell runtime detected)"
echo "✓ Core pack loaded with echo action"
echo "✓ Trigger instance created (1-second interval timer)"
echo "✓ Rule created and enabled"
echo "✓ Executions observed: $EXECUTION_COUNT"
echo "✓ Successful executions: $SUCCESS_COUNT"
echo ""
if [ "$SUCCESS_COUNT" -gt 0 ]; then
echo -e "${GREEN}=== HAPPY PATH TEST PASSED ===${NC}"
echo ""
echo "The complete event flow is working:"
echo " Timer Sensor → Event → Rule → Enforcement → Execution → Worker → Shell Action"
echo ""
exit 0
else
echo -e "${RED}=== HAPPY PATH TEST FAILED ===${NC}"
echo ""
echo "Executions were created but none succeeded."
echo "Check service logs for errors:"
echo " docker logs attune-sensor"
echo " docker logs attune-executor"
echo " docker logs attune-worker"
echo ""
exit 1
fi