mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 03:29:25 +01:00
Replace redis:7-alpine with valkey/valkey:8-alpine across the management compose stack. Valkey is the Linux Foundation-backed BSD-3-Clause fork, maintaining full API compatibility with Redis 7.x. Changes: - Swap Docker image to valkey/valkey:8-alpine - Rename service and container (redis -> valkey, nomad_redis -> nomad_valkey) - Update health check to use valkey-cli - Update REDIS_HOST env var to point to new service name - Update sidecar-updater service list AdonisJS reads REDIS_HOST from env, so zero application code changes are needed. BullMQ job queues work identically on Valkey. Closes #276 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
151 lines
4.8 KiB
Bash
151 lines
4.8 KiB
Bash
#!/bin/bash
|
|
|
|
# Project N.O.M.A.D. Update Sidecar - Polls for update requests and executes them
|
|
|
|
SHARED_DIR="/shared"
|
|
REQUEST_FILE="${SHARED_DIR}/update-request"
|
|
STATUS_FILE="${SHARED_DIR}/update-status"
|
|
LOG_FILE="${SHARED_DIR}/update-log"
|
|
COMPOSE_FILE="/opt/project-nomad/compose.yml"
|
|
COMPOSE_PROJECT_NAME="project-nomad"
|
|
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
write_status() {
|
|
local stage="$1"
|
|
local progress="$2"
|
|
local message="$3"
|
|
|
|
cat > "$STATUS_FILE" <<EOF
|
|
{
|
|
"stage": "$stage",
|
|
"progress": $progress,
|
|
"message": "$message",
|
|
"timestamp": "$(date -Iseconds)"
|
|
}
|
|
EOF
|
|
}
|
|
|
|
perform_update() {
|
|
local target_tag="$1"
|
|
|
|
log "Update request received - starting system update (target tag: ${target_tag})"
|
|
|
|
# Clear old logs
|
|
> "$LOG_FILE"
|
|
|
|
# Stage 1: Starting
|
|
write_status "starting" 0 "System update initiated"
|
|
log "System update initiated"
|
|
sleep 1
|
|
|
|
# Apply target image tag to compose.yml before pulling
|
|
log "Applying image tag '${target_tag}' to compose.yml..."
|
|
if sed -i "s|\(image: ghcr\.io/crosstalk-solutions/project-nomad\):.*|\1:${target_tag}|" "$COMPOSE_FILE" 2>> "$LOG_FILE"; then
|
|
log "Successfully updated compose.yml admin image tag to '${target_tag}'"
|
|
else
|
|
log "ERROR: Failed to update compose.yml image tag"
|
|
write_status "error" 0 "Failed to update compose.yml image tag - check logs"
|
|
return 1
|
|
fi
|
|
|
|
# Stage 2: Pulling images
|
|
write_status "pulling" 20 "Pulling latest Docker images..."
|
|
log "Pulling latest Docker images..."
|
|
|
|
if docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" pull >> "$LOG_FILE" 2>&1; then
|
|
log "Successfully pulled latest images"
|
|
write_status "pulled" 60 "Images pulled successfully"
|
|
else
|
|
log "ERROR: Failed to pull images"
|
|
write_status "error" 0 "Failed to pull Docker images - check logs"
|
|
return 1
|
|
fi
|
|
|
|
sleep 2
|
|
|
|
# Stage 3: Recreating containers individually (excluding updater)
|
|
write_status "recreating" 65 "Recreating containers individually..."
|
|
log "Recreating containers individually (excluding updater)..."
|
|
|
|
# List of services to update (excluding updater)
|
|
SERVICES_TO_UPDATE="admin mysql valkey dozzle"
|
|
|
|
local current_progress=65
|
|
local progress_per_service=8 # (95 - 65) / 4 services ≈ 8% per service
|
|
|
|
for service in $SERVICES_TO_UPDATE; do
|
|
log "Updating service: $service"
|
|
write_status "recreating" $current_progress "Recreating $service..."
|
|
|
|
# Stop the service
|
|
log " Stopping $service..."
|
|
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" stop "$service" >> "$LOG_FILE" 2>&1 || log " WARNING: Failed to stop $service"
|
|
|
|
# Remove the container
|
|
log " Removing old $service container..."
|
|
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" rm -f "$service" >> "$LOG_FILE" 2>&1 || log " WARNING: Failed to remove $service"
|
|
|
|
# Recreate and start with new image
|
|
log " Starting new $service container..."
|
|
if docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" up -d --no-deps "$service" >> "$LOG_FILE" 2>&1; then
|
|
log " ✓ Successfully recreated $service"
|
|
else
|
|
log " ERROR: Failed to recreate $service"
|
|
write_status "error" $current_progress "Failed to recreate $service - check logs"
|
|
return 1
|
|
fi
|
|
|
|
current_progress=$((current_progress + progress_per_service))
|
|
done
|
|
|
|
log "Successfully recreated all containers"
|
|
write_status "complete" 100 "System update completed successfully"
|
|
log "System update completed successfully"
|
|
|
|
return 0
|
|
}
|
|
|
|
cleanup() {
|
|
log "Update sidecar shutting down"
|
|
exit 0
|
|
}
|
|
|
|
trap cleanup SIGTERM SIGINT
|
|
|
|
# Main watch loop
|
|
log "Update sidecar started - watching for update requests"
|
|
write_status "idle" 0 "Ready for update requests"
|
|
|
|
while true; do
|
|
# Check if an update request file exists
|
|
if [ -f "$REQUEST_FILE" ]; then
|
|
log "Found update request file"
|
|
|
|
# Read request details
|
|
REQUEST_DATA=$(cat "$REQUEST_FILE" 2>/dev/null || echo "{}")
|
|
log "Request data: $REQUEST_DATA"
|
|
|
|
# Extract target tag from request (defaults to "latest" if not provided)
|
|
TARGET_TAG=$(echo "$REQUEST_DATA" | jq -r '.target_tag // "latest"')
|
|
log "Target image tag: ${TARGET_TAG}"
|
|
|
|
# Remove the request file to prevent re-processing
|
|
rm -f "$REQUEST_FILE"
|
|
|
|
if perform_update "$TARGET_TAG"; then
|
|
log "Update completed successfully"
|
|
else
|
|
log "Update failed - see logs for details"
|
|
fi
|
|
|
|
sleep 5
|
|
write_status "idle" 0 "Ready for update requests"
|
|
fi
|
|
|
|
# Sleep before next check (1 second polling)
|
|
sleep 1
|
|
done
|