Schema additions for issues #37-41: New models: - Domain (#37): Life domains (work, marriage, homelab, etc.) - Idea (#38): Brain dumps with pgvector embeddings - Relationship (#39): Generic entity linking (blocks, depends_on) - Agent (#40): ClawdBot agent tracking with metrics - AgentSession (#40): Conversation session tracking - WidgetDefinition (#41): HUD widget registry - UserLayout (#41): Per-user dashboard configuration Updated models: - Task, Event, Project: Added domainId foreign key - User, Workspace: Added new relations New enums: - IdeaStatus: CAPTURED, PROCESSING, ACTIONABLE, ARCHIVED, DISCARDED - RelationshipType: BLOCKS, BLOCKED_BY, DEPENDS_ON, etc. - AgentStatus: IDLE, WORKING, WAITING, ERROR, TERMINATED - EntityType: Added IDEA, DOMAIN Migration: 20260129182803_add_domains_ideas_agents_widgets
391 lines
11 KiB
Bash
Executable File
391 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
# Integration tests for Traefik deployment modes
|
|
# Tests bundled, upstream, and none modes
|
|
#
|
|
# Usage:
|
|
# ./traefik.test.sh [bundled|upstream|none|all]
|
|
#
|
|
# Requirements:
|
|
# - Docker and Docker Compose installed
|
|
# - jq for JSON parsing
|
|
# - curl for HTTP testing
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Test counters
|
|
TESTS_RUN=0
|
|
TESTS_PASSED=0
|
|
TESTS_FAILED=0
|
|
|
|
# Test result tracking
|
|
declare -a FAILED_TESTS=()
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_test() {
|
|
echo -e "\n${YELLOW}[TEST]${NC} $1"
|
|
((TESTS_RUN++))
|
|
}
|
|
|
|
log_pass() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
((TESTS_PASSED++))
|
|
}
|
|
|
|
log_fail() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
((TESTS_FAILED++))
|
|
FAILED_TESTS+=("$1")
|
|
}
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
log_info "Cleaning up test environment..."
|
|
docker compose -f docker-compose.test.yml down -v 2>/dev/null || true
|
|
docker network rm traefik-public-test 2>/dev/null || true
|
|
rm -f .env.test docker-compose.test.yml
|
|
}
|
|
|
|
# Trap cleanup on exit
|
|
trap cleanup EXIT
|
|
|
|
# Check prerequisites
|
|
check_prerequisites() {
|
|
log_info "Checking prerequisites..."
|
|
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker is not installed"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v docker compose &> /dev/null; then
|
|
log_error "Docker Compose is not installed"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v jq &> /dev/null; then
|
|
log_error "jq is not installed (required for JSON parsing)"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v curl &> /dev/null; then
|
|
log_error "curl is not installed"
|
|
exit 1
|
|
fi
|
|
|
|
log_pass "All prerequisites satisfied"
|
|
}
|
|
|
|
# Test bundled Traefik mode
|
|
test_bundled_mode() {
|
|
log_info "=========================================="
|
|
log_info "Testing Bundled Traefik Mode"
|
|
log_info "=========================================="
|
|
|
|
# Create test environment file
|
|
cat > .env.test <<EOF
|
|
TRAEFIK_MODE=bundled
|
|
MOSAIC_API_DOMAIN=api.mosaic.test
|
|
MOSAIC_WEB_DOMAIN=mosaic.test
|
|
MOSAIC_AUTH_DOMAIN=auth.mosaic.test
|
|
TRAEFIK_DASHBOARD_ENABLED=true
|
|
TRAEFIK_TLS_ENABLED=false
|
|
TRAEFIK_ACME_EMAIL=test@example.com
|
|
POSTGRES_PASSWORD=test_password
|
|
AUTHENTIK_SECRET_KEY=test_secret_key_minimum_50_characters_long_for_testing
|
|
AUTHENTIK_POSTGRES_PASSWORD=test_auth_password
|
|
AUTHENTIK_BOOTSTRAP_PASSWORD=test_admin
|
|
JWT_SECRET=test_jwt_secret_minimum_32_chars
|
|
EOF
|
|
|
|
# Copy docker-compose.yml to test version
|
|
cp docker-compose.yml docker-compose.test.yml
|
|
|
|
log_test "Starting services with bundled Traefik profile"
|
|
if docker compose -f docker-compose.test.yml --env-file .env.test --profile traefik-bundled up -d; then
|
|
log_pass "Services started successfully"
|
|
else
|
|
log_fail "Failed to start services"
|
|
return 1
|
|
fi
|
|
|
|
sleep 10 # Wait for services to initialize
|
|
|
|
log_test "Verifying Traefik container is running"
|
|
if docker ps --filter "name=mosaic-traefik" --format "{{.Names}}" | grep -q "mosaic-traefik"; then
|
|
log_pass "Traefik container is running"
|
|
else
|
|
log_fail "Traefik container not found"
|
|
fi
|
|
|
|
log_test "Verifying Traefik dashboard is accessible"
|
|
if curl -sf http://localhost:8080/dashboard/ > /dev/null; then
|
|
log_pass "Traefik dashboard is accessible"
|
|
else
|
|
log_fail "Traefik dashboard not accessible"
|
|
fi
|
|
|
|
log_test "Verifying Traefik API endpoint"
|
|
if curl -sf http://localhost:8080/api/overview | jq -e '.http.routers' > /dev/null; then
|
|
log_pass "Traefik API is responding"
|
|
else
|
|
log_fail "Traefik API not responding correctly"
|
|
fi
|
|
|
|
log_test "Verifying API service has Traefik labels"
|
|
LABELS=$(docker inspect mosaic-api --format='{{json .Config.Labels}}')
|
|
if echo "$LABELS" | jq -e '."traefik.enable"' > /dev/null; then
|
|
log_pass "API service has Traefik labels"
|
|
else
|
|
log_fail "API service missing Traefik labels"
|
|
fi
|
|
|
|
log_test "Verifying Web service has Traefik labels"
|
|
LABELS=$(docker inspect mosaic-web --format='{{json .Config.Labels}}')
|
|
if echo "$LABELS" | jq -e '."traefik.enable"' > /dev/null; then
|
|
log_pass "Web service has Traefik labels"
|
|
else
|
|
log_fail "Web service missing Traefik labels"
|
|
fi
|
|
|
|
log_test "Checking Traefik routes configuration"
|
|
ROUTES=$(curl -sf http://localhost:8080/api/http/routers | jq -r 'keys[]')
|
|
if echo "$ROUTES" | grep -q "mosaic-api"; then
|
|
log_pass "API route registered with Traefik"
|
|
else
|
|
log_fail "API route not found in Traefik"
|
|
fi
|
|
|
|
if echo "$ROUTES" | grep -q "mosaic-web"; then
|
|
log_pass "Web route registered with Traefik"
|
|
else
|
|
log_fail "Web route not found in Traefik"
|
|
fi
|
|
|
|
# Cleanup
|
|
docker compose -f docker-compose.test.yml --env-file .env.test down -v
|
|
}
|
|
|
|
# Test upstream Traefik mode
|
|
test_upstream_mode() {
|
|
log_info "=========================================="
|
|
log_info "Testing Upstream Traefik Mode"
|
|
log_info "=========================================="
|
|
|
|
# Create external network for upstream Traefik
|
|
log_test "Creating external Traefik network"
|
|
if docker network create traefik-public-test 2>/dev/null; then
|
|
log_pass "External network created"
|
|
else
|
|
log_warn "Network already exists or creation failed"
|
|
fi
|
|
|
|
# Create test environment file
|
|
cat > .env.test <<EOF
|
|
TRAEFIK_MODE=upstream
|
|
MOSAIC_API_DOMAIN=api.mosaic.test
|
|
MOSAIC_WEB_DOMAIN=mosaic.test
|
|
MOSAIC_AUTH_DOMAIN=auth.mosaic.test
|
|
TRAEFIK_NETWORK=traefik-public-test
|
|
POSTGRES_PASSWORD=test_password
|
|
AUTHENTIK_SECRET_KEY=test_secret_key_minimum_50_characters_long_for_testing
|
|
AUTHENTIK_POSTGRES_PASSWORD=test_auth_password
|
|
AUTHENTIK_BOOTSTRAP_PASSWORD=test_admin
|
|
JWT_SECRET=test_jwt_secret_minimum_32_chars
|
|
EOF
|
|
|
|
# Copy docker-compose.yml to test version
|
|
cp docker-compose.yml docker-compose.test.yml
|
|
|
|
log_test "Starting services in upstream mode (no bundled Traefik)"
|
|
if docker compose -f docker-compose.test.yml --env-file .env.test up -d; then
|
|
log_pass "Services started successfully"
|
|
else
|
|
log_fail "Failed to start services"
|
|
return 1
|
|
fi
|
|
|
|
sleep 10 # Wait for services to initialize
|
|
|
|
log_test "Verifying Traefik container is NOT running"
|
|
if ! docker ps --filter "name=mosaic-traefik" --format "{{.Names}}" | grep -q "mosaic-traefik"; then
|
|
log_pass "Bundled Traefik correctly not started"
|
|
else
|
|
log_fail "Bundled Traefik should not be running in upstream mode"
|
|
fi
|
|
|
|
log_test "Verifying API service is connected to external network"
|
|
NETWORKS=$(docker inspect mosaic-api --format='{{json .NetworkSettings.Networks}}' | jq -r 'keys[]')
|
|
if echo "$NETWORKS" | grep -q "traefik-public-test"; then
|
|
log_pass "API service connected to external Traefik network"
|
|
else
|
|
log_fail "API service not connected to external Traefik network"
|
|
fi
|
|
|
|
log_test "Verifying Web service is connected to external network"
|
|
NETWORKS=$(docker inspect mosaic-web --format='{{json .NetworkSettings.Networks}}' | jq -r 'keys[]')
|
|
if echo "$NETWORKS" | grep -q "traefik-public-test"; then
|
|
log_pass "Web service connected to external Traefik network"
|
|
else
|
|
log_fail "Web service not connected to external Traefik network"
|
|
fi
|
|
|
|
log_test "Verifying API service has correct Traefik labels for upstream"
|
|
LABELS=$(docker inspect mosaic-api --format='{{json .Config.Labels}}')
|
|
if echo "$LABELS" | jq -e '."traefik.enable" == "true"' > /dev/null && \
|
|
echo "$LABELS" | jq -e '."traefik.docker.network"' > /dev/null; then
|
|
log_pass "API service has correct upstream Traefik labels"
|
|
else
|
|
log_fail "API service missing or incorrect upstream Traefik labels"
|
|
fi
|
|
|
|
# Cleanup
|
|
docker compose -f docker-compose.test.yml --env-file .env.test down -v
|
|
docker network rm traefik-public-test 2>/dev/null || true
|
|
}
|
|
|
|
# Test none mode (direct port exposure)
|
|
test_none_mode() {
|
|
log_info "=========================================="
|
|
log_info "Testing None Mode (Direct Ports)"
|
|
log_info "=========================================="
|
|
|
|
# Create test environment file
|
|
cat > .env.test <<EOF
|
|
TRAEFIK_MODE=none
|
|
API_PORT=3001
|
|
WEB_PORT=3000
|
|
POSTGRES_PASSWORD=test_password
|
|
AUTHENTIK_SECRET_KEY=test_secret_key_minimum_50_characters_long_for_testing
|
|
AUTHENTIK_POSTGRES_PASSWORD=test_auth_password
|
|
AUTHENTIK_BOOTSTRAP_PASSWORD=test_admin
|
|
JWT_SECRET=test_jwt_secret_minimum_32_chars
|
|
EOF
|
|
|
|
# Copy docker-compose.yml to test version
|
|
cp docker-compose.yml docker-compose.test.yml
|
|
|
|
log_test "Starting services in none mode (no Traefik)"
|
|
if docker compose -f docker-compose.test.yml --env-file .env.test up -d; then
|
|
log_pass "Services started successfully"
|
|
else
|
|
log_fail "Failed to start services"
|
|
return 1
|
|
fi
|
|
|
|
sleep 10 # Wait for services to initialize
|
|
|
|
log_test "Verifying Traefik container is NOT running"
|
|
if ! docker ps --filter "name=mosaic-traefik" --format "{{.Names}}" | grep -q "mosaic-traefik"; then
|
|
log_pass "Traefik correctly not started in none mode"
|
|
else
|
|
log_fail "Traefik should not be running in none mode"
|
|
fi
|
|
|
|
log_test "Verifying API service Traefik labels are disabled"
|
|
LABELS=$(docker inspect mosaic-api --format='{{json .Config.Labels}}')
|
|
if echo "$LABELS" | jq -e '."traefik.enable" == "false"' > /dev/null; then
|
|
log_pass "API service Traefik labels correctly disabled"
|
|
else
|
|
log_fail "API service Traefik labels should be disabled"
|
|
fi
|
|
|
|
log_test "Verifying direct port access to API"
|
|
MAX_RETRIES=30
|
|
RETRY_COUNT=0
|
|
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
|
if curl -sf http://localhost:3001/health > /dev/null 2>&1; then
|
|
log_pass "API accessible via direct port 3001"
|
|
break
|
|
fi
|
|
((RETRY_COUNT++))
|
|
sleep 2
|
|
done
|
|
|
|
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
|
|
log_fail "API not accessible via direct port 3001"
|
|
fi
|
|
|
|
# Cleanup
|
|
docker compose -f docker-compose.test.yml --env-file .env.test down -v
|
|
}
|
|
|
|
# Print test summary
|
|
print_summary() {
|
|
echo ""
|
|
log_info "=========================================="
|
|
log_info "Test Summary"
|
|
log_info "=========================================="
|
|
echo "Total tests run: $TESTS_RUN"
|
|
echo -e "${GREEN}Passed: $TESTS_PASSED${NC}"
|
|
echo -e "${RED}Failed: $TESTS_FAILED${NC}"
|
|
|
|
if [ $TESTS_FAILED -gt 0 ]; then
|
|
echo ""
|
|
log_error "Failed tests:"
|
|
for test in "${FAILED_TESTS[@]}"; do
|
|
echo " - $test"
|
|
done
|
|
echo ""
|
|
exit 1
|
|
else
|
|
echo ""
|
|
log_pass "All tests passed!"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
TEST_MODE="${1:-all}"
|
|
|
|
log_info "Mosaic Stack - Traefik Integration Tests"
|
|
log_info "Test mode: $TEST_MODE"
|
|
echo ""
|
|
|
|
check_prerequisites
|
|
|
|
case "$TEST_MODE" in
|
|
bundled)
|
|
test_bundled_mode
|
|
;;
|
|
upstream)
|
|
test_upstream_mode
|
|
;;
|
|
none)
|
|
test_none_mode
|
|
;;
|
|
all)
|
|
test_bundled_mode
|
|
test_upstream_mode
|
|
test_none_mode
|
|
;;
|
|
*)
|
|
log_error "Invalid test mode: $TEST_MODE"
|
|
log_info "Usage: $0 [bundled|upstream|none|all]"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
print_summary
|
|
}
|
|
|
|
main "$@"
|