#!/usr/bin/env bash # ----------------------------------------------------------------------------- # minio-switch.sh — swap MinIO target between local container and CAI cluster # # Usage: # ./minio-switch.sh cluster # → cluster (didi-prod bucket) # ./minio-switch.sh local # → staging-dataLayer-minio (multi-bucket) # ./minio-switch.sh status # show current # # Like redis-switch.sh, this rewrites the MINIO_* block in agent-v3 + framework # .env files and restarts both stacks. Cluster credentials live in # .cluster-credentials.env (gitignored) — same file used by redis-switch.sh. # ----------------------------------------------------------------------------- set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MONOREPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)" AGENT_DIR="${MONOREPO_ROOT}/backend/services/orchestration-layer/agent-v3" FW_DIR="${MONOREPO_ROOT}/backend/services/orchestration-layer/didiFramework" # Load shared cluster credentials (DIDI_MINIO_ACCESS_KEY etc) if present if [ -f "${SCRIPT_DIR}/.cluster-credentials.env" ]; then set -a; source "${SCRIPT_DIR}/.cluster-credentials.env"; set +a fi # ------------------------------------------------------------------------- # Cluster (external S3 cluster live since 2026-04-23) # ------------------------------------------------------------------------- # NOTE: Using VIP IP directly (minio-cluster.local) instead of DNS — # Docker containers don't resolve internal pfSense DNS (they use systemd-resolved # at 127.0.0.53 which doesn't see minio-host zone). VIP IP is stable. CLUSTER_ENDPOINT="minio-cluster.local" CLUSTER_PORT="9000" CLUSTER_USE_SSL="false" CLUSTER_BUCKET="didi-prod" # Credentials sourced from .cluster-credentials.env or shell env CLUSTER_ACCESS_KEY="${DIDI_MINIO_ACCESS_KEY:-didi-prod}" CLUSTER_SECRET_KEY="${DIDI_MINIO_SECRET_KEY:-}" # ------------------------------------------------------------------------- # Local (legacy multi-bucket) # ------------------------------------------------------------------------- LOCAL_ENDPOINT="staging-dataLayer-minio" LOCAL_PORT="9000" LOCAL_USE_SSL="false" LOCAL_BUCKET="" # empty = legacy multi-bucket mode LOCAL_ACCESS_KEY="minioadmin" LOCAL_SECRET_KEY="minio123" MODE="${1:-status}" write_minio_block() { local env_file="$1" endpoint="$2" port="$3" ssl="$4" bucket="$5" ak="$6" sk="$7" [ ! -f "$env_file" ] && touch "$env_file" local tmp="${env_file}.tmp" grep -vE '^(# MinIO|MINIO_ENDPOINT=|MINIO_PORT=|MINIO_USE_SSL=|MINIO_BUCKET=|MINIO_ACCESS_KEY=|MINIO_SECRET_KEY=|MINIO_PUBLIC_ENDPOINT=)' "$env_file" > "$tmp" || true { echo "" echo "# MinIO (set by minio-switch.sh $(date -Iseconds))" echo "MINIO_ENDPOINT=${endpoint}" echo "MINIO_PORT=${port}" echo "MINIO_USE_SSL=${ssl}" echo "MINIO_BUCKET=${bucket}" echo "MINIO_ACCESS_KEY=${ak}" echo "MINIO_SECRET_KEY=${sk}" } >> "$tmp" mv "$tmp" "$env_file" echo " ✓ MinIO env → ${env_file#${MONOREPO_ROOT}/}" } read_env() { local env="$1" key="$2" [ -f "$env" ] || { echo ""; return; } grep -E "^${key}=" "$env" 2>/dev/null | tail -1 | cut -d= -f2- || true } restart_services() { echo "→ Restarting didi-framework..." (cd "$FW_DIR" && docker compose up -d --force-recreate 2>&1 | tail -3) echo "→ Restarting agent-v3 stack..." (cd "$AGENT_DIR" && docker compose up -d --force-recreate 2>&1 | tail -3) echo "→ Waiting for services..." for i in $(seq 1 30); do if docker exec didi-framework wget -qO- http://127.0.0.1:3005/health > /dev/null 2>&1 \ && curl -sf http://localhost:24803/api/v3/health > /dev/null 2>&1; then echo " ✓ Both ready (${i}s)" return fi sleep 1 done echo " ⚠ Timeout — check logs" } case "$MODE" in status) env_file="${AGENT_DIR}/.env" ep=$(read_env "$env_file" MINIO_ENDPOINT) port=$(read_env "$env_file" MINIO_PORT) bk=$(read_env "$env_file" MINIO_BUCKET) ak=$(read_env "$env_file" MINIO_ACCESS_KEY) echo "Current MinIO target (from agent-v3 .env):" echo " endpoint: ${ep:-staging-dataLayer-minio}:${port:-9000}" echo " bucket: ${bk:-(legacy multi-bucket)}" echo " user: ${ak:-minioadmin}" echo "" echo "Local container:" docker ps -a --filter "name=staging-dataLayer-minio" --format " {{.Names}} | {{.Status}}" | head -1 ;; cluster) if [ -z "$CLUSTER_SECRET_KEY" ]; then echo "✘ ERROR: cluster secret key not set." >&2 echo " Set DIDI_MINIO_ACCESS_KEY + DIDI_MINIO_SECRET_KEY in" >&2 echo " ${SCRIPT_DIR}/.cluster-credentials.env or shell env" >&2 exit 1 fi echo "═══ Switching to CAI cluster ${CLUSTER_ENDPOINT} (bucket=${CLUSTER_BUCKET}) ═══" write_minio_block "${AGENT_DIR}/.env" "$CLUSTER_ENDPOINT" "$CLUSTER_PORT" "$CLUSTER_USE_SSL" "$CLUSTER_BUCKET" "$CLUSTER_ACCESS_KEY" "$CLUSTER_SECRET_KEY" write_minio_block "${FW_DIR}/.env" "$CLUSTER_ENDPOINT" "$CLUSTER_PORT" "$CLUSTER_USE_SSL" "$CLUSTER_BUCKET" "$CLUSTER_ACCESS_KEY" "$CLUSTER_SECRET_KEY" restart_services echo "✓ Cluster active. Single-bucket mode (MINIO_BUCKET=${CLUSTER_BUCKET})." ;; local) echo "═══ Switching to LOCAL staging-dataLayer-minio (legacy multi-bucket) ═══" if ! docker ps --filter "name=staging-dataLayer-minio" --filter "status=running" --format "{{.Names}}" | grep -q .; then echo "→ Starting local minio..." docker start staging-dataLayer-minio 2>&1 | tail -2 sleep 3 fi write_minio_block "${AGENT_DIR}/.env" "$LOCAL_ENDPOINT" "$LOCAL_PORT" "$LOCAL_USE_SSL" "$LOCAL_BUCKET" "$LOCAL_ACCESS_KEY" "$LOCAL_SECRET_KEY" write_minio_block "${FW_DIR}/.env" "$LOCAL_ENDPOINT" "$LOCAL_PORT" "$LOCAL_USE_SSL" "$LOCAL_BUCKET" "$LOCAL_ACCESS_KEY" "$LOCAL_SECRET_KEY" restart_services echo "✓ Local active (multi-bucket mode)." ;; *) echo "Usage: $0 {cluster|local|status}" exit 1 ;; esac