86 lines
3.0 KiB
Bash
Executable File
86 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
DIR="/opt/hx-ki/com2-stack"
|
|
F="$DIR/docker-compose.yml"
|
|
C="hxki-postgres"
|
|
TS="$(date +%Y%m%d-%H%M%S)"
|
|
BK="/opt/hx-ki/backups/com2-pg-semicolon-$TS"
|
|
mkdir -p "$BK"
|
|
|
|
echo "=== COM2 · FIX POSTGRES ; + VERIFY (one-shot) ==="
|
|
echo "Compose: $F"
|
|
echo "Backup: $BK"
|
|
echo
|
|
|
|
[ -f "$F" ] || { echo "FAIL: missing $F"; exit 1; }
|
|
|
|
cp -a "$F" "$BK/docker-compose.yml.pre"
|
|
|
|
echo "[1] Show offending lines (with trailing ';')"
|
|
grep -nE 'POSTGRES_(USER|PASSWORD|DB)=.*;$' "$F" || echo "OK: no trailing ';' in compose"
|
|
|
|
echo
|
|
echo "[2] Patch ONLY trailing ';' for POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB (compose is authority)"
|
|
# supports both list-form " - POSTGRES_USER=..." and mapping-form "POSTGRES_USER: ..."
|
|
sed -i -E \
|
|
-e 's/^(\s*-\s*POSTGRES_USER=[^;]*);$/\1/' \
|
|
-e 's/^(\s*-\s*POSTGRES_PASSWORD=[^;]*);$/\1/' \
|
|
-e 's/^(\s*-\s*POSTGRES_DB=[^;]*);$/\1/' \
|
|
-e 's/^(\s*POSTGRES_USER:\s*[^;]*);$/\1/' \
|
|
-e 's/^(\s*POSTGRES_PASSWORD:\s*[^;]*);$/\1/' \
|
|
-e 's/^(\s*POSTGRES_DB:\s*[^;]*);$/\1/' \
|
|
"$F"
|
|
|
|
echo
|
|
echo "[3] Validate compose"
|
|
docker compose -f "$F" config >/dev/null
|
|
echo "OK: compose valid"
|
|
|
|
echo
|
|
echo "[4] Recreate postgres container to re-inject ENV"
|
|
cd "$DIR"
|
|
docker compose up -d --force-recreate --no-deps "$C" >/dev/null
|
|
|
|
echo
|
|
echo "[5] Read ENV actually inside container (ground truth)"
|
|
docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^POSTGRES_(USER|PASSWORD|DB)=' || true
|
|
|
|
PG_USER="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_USER=/{print $2}' | tail -n1)"
|
|
PG_DB="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_DB=/{print $2}' | tail -n1)"
|
|
PG_PW="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_PASSWORD=/{print $2}' | tail -n1)"
|
|
|
|
echo
|
|
echo "[6] Wait until Postgres accepts connections (max 30s)"
|
|
for i in $(seq 1 30); do
|
|
if docker exec -e PGPASSWORD="$PG_PW" "$C" psql -U "$PG_USER" -d "$PG_DB" -c "SELECT 1;" >/dev/null 2>&1; then
|
|
echo "OK: login works with CURRENT ENV"
|
|
OK_MODE="CURRENT_ENV"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [ "${OK_MODE:-}" != "CURRENT_ENV" ]; then
|
|
echo "WARN: login failed with CURRENT ENV. Testing legacy ';' variants deterministically."
|
|
|
|
# Variant B: user+db with ';' and password with ';'
|
|
if docker exec -e PGPASSWORD="${PG_PW};" "$C" psql -U "${PG_USER};" -d "${PG_DB};" -c "SELECT 1;" >/dev/null 2>&1; then
|
|
echo "OK: legacy semicolon credentials work (user/db/pw had ';' at init time)"
|
|
OK_MODE="LEGACY_SEMICOLON"
|
|
else
|
|
echo "FAIL: Neither CURRENT_ENV nor LEGACY_SEMICOLON credentials can authenticate."
|
|
echo "=> Then the only deterministic path is an auth-reset inside the data dir (no guessing), because plaintext can't be recovered."
|
|
exit 2
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
echo "=== RESULT ==="
|
|
echo "MODE=$OK_MODE"
|
|
echo "POSTGRES_USER=$PG_USER"
|
|
echo "POSTGRES_DB=$PG_DB"
|
|
echo "POSTGRES_PASSWORD=$PG_PW"
|
|
echo "Backup: $BK"
|
|
echo "=== DONE ==="
|