387 lines
12 KiB
Bash
Executable File
387 lines
12 KiB
Bash
Executable File
#!/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
|