#!/usr/bin/env bash set -euo pipefail # switch-archicratie.sh — SAFE switch LIVE + STAGING (avec backups horodatés) # # Usage (NAS recommandé) : # sudo bash -c 'LIVE_PORT=8081 /volume2/docker/archicratie-web/current/scripts/switch-archicratie.sh' # sudo bash -c 'LIVE_PORT=8082 /volume2/docker/archicratie-web/current/scripts/switch-archicratie.sh' # # Usage (test local R&D, sans NAS) : # D=/tmp/dynamic-test LIVE_PORT=8081 bash scripts/switch-archicratie.sh --dry-run # D=/tmp/dynamic-test LIVE_PORT=8081 bash scripts/switch-archicratie.sh usage() { cat <<'EOF' SAFE switch LIVE + STAGING (avec backups horodatés). Variables / options : LIVE_PORT=8081|8082 (obligatoire) port LIVE cible D=/volume2/docker/edge/config/dynamic (optionnel) dossier des yml Traefik dynamiques --dry-run n'écrit rien, affiche seulement ce qui serait fait -h, --help aide Exemples : sudo bash -c 'LIVE_PORT=8082 /volume2/docker/archicratie-web/current/scripts/switch-archicratie.sh' D=/tmp/dynamic-test LIVE_PORT=8081 bash scripts/switch-archicratie.sh --dry-run EOF } DRY_RUN=0 for arg in "${@:-}"; do case "$arg" in --dry-run) DRY_RUN=1 ;; -h|--help) usage; exit 0 ;; *) ;; esac done D="${D:-/volume2/docker/edge/config/dynamic}" F_LIVE="$D/20-archicratie-backend.yml" F_STAG="$D/21-archicratie-staging.yml" LIVE_PORT="${LIVE_PORT:-}" if [[ "$LIVE_PORT" != "8081" && "$LIVE_PORT" != "8082" ]]; then echo "❌ LIVE_PORT doit valoir 8081 ou 8082." usage exit 1 fi if [[ ! -f "$F_LIVE" || ! -f "$F_STAG" ]]; then echo "❌ Fichiers manquants :" echo " $F_LIVE" echo " $F_STAG" echo " (Astuce R&D locale : mets D=/tmp/dynamic-test et crée 20/21 dedans.)" exit 1 fi OTHER_PORT="8081" [[ "$LIVE_PORT" == "8081" ]] && OTHER_PORT="8082" show_urls() { local f="$1" echo "— $f" grep -nE '^\s*-\s*url:\s*".*"' "$f" || true } # Garde-fou : on attend au moins un "url:" dans chaque fichier grep -qE '^\s*-\s*url:\s*"' "$F_LIVE" || { echo "❌ Format inattendu dans $F_LIVE (pas de - url: \")"; exit 1; } grep -qE '^\s*-\s*url:\s*"' "$F_STAG" || { echo "❌ Format inattendu dans $F_STAG (pas de - url: \")"; exit 1; } echo "Avant :" show_urls "$F_LIVE" show_urls "$F_STAG" echo echo "Plan : LIVE -> $LIVE_PORT ; STAGING -> $OTHER_PORT" echo if [[ "$DRY_RUN" == "1" ]]; then echo "DRY-RUN : aucune écriture." exit 0 fi TS="$(date +%F-%H%M%S)" cp -a "$F_LIVE" "$F_LIVE.bak.$TS" cp -a "$F_STAG" "$F_STAG.bak.$TS" # sed inplace portable (macOS vs Linux/DSM) sed_inplace() { local expr="$1" file="$2" if [[ "$(uname -s)" == "Darwin" ]]; then sed -i '' -e "$expr" "$file" else sed -i -e "$expr" "$file" fi } # Remplacement ciblé UNIQUEMENT sur la ligne - url: "http://127.0.0.1:808X" sed_inplace \ "s#^\([[:space:]]*-[[:space:]]*url:[[:space:]]*\"http://127\\.0\\.0\\.1:\\)808[12]\\(\"[[:space:]]*\)#\\1${LIVE_PORT}\\2#g" \ "$F_LIVE" sed_inplace \ "s#^\([[:space:]]*-[[:space:]]*url:[[:space:]]*\"http://127\\.0\\.0\\.1:\\)808[12]\\(\"[[:space:]]*\)#\\1${OTHER_PORT}\\2#g" \ "$F_STAG" # Post-check : on confirme que les fichiers contiennent bien les ports attendus grep -qE "http://127\.0\.0\.1:${LIVE_PORT}\"" "$F_LIVE" || { echo "❌ Post-check FAIL : $F_LIVE ne contient pas http://127.0.0.1:${LIVE_PORT}" echo "➡️ rollback backups : $F_LIVE.bak.$TS / $F_STAG.bak.$TS" exit 1 } grep -qE "http://127\.0\.0\.1:${OTHER_PORT}\"" "$F_STAG" || { echo "❌ Post-check FAIL : $F_STAG ne contient pas http://127.0.0.1:${OTHER_PORT}" echo "➡️ rollback backups : $F_LIVE.bak.$TS / $F_STAG.bak.$TS" exit 1 } echo "✅ OK. Backups :" echo " - $F_LIVE.bak.$TS" echo " - $F_STAG.bak.$TS" echo echo "Après :" show_urls "$F_LIVE" show_urls "$F_STAG" echo echo "Smoke tests :" echo " curl -sS -I http://127.0.0.1:${LIVE_PORT}/ | head -n 12" echo " curl -sS -I http://127.0.0.1:${OTHER_PORT}/ | head -n 12" echo " curl -sS -I -H 'Host: archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ | head -n 20" echo " curl -sS -I -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ | head -n 20"