Entrega read-only de apontamentos DNS (Cloudflare, OpenPanel BIND, público) no Desk e Console /admin/dominio, com spec, scripts de rollback e patches VM112 para painel lateral no passo DNS do onboarding (deploy wizard pendente). Co-authored-by: Cursor <cursoragent@cursor.com>
103 lines
2.7 KiB
Bash
Executable file
103 lines
2.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Spec 037-DNS-VIEWER — rollback automatizado VM122 (feature flag + restore último backup)
|
|
set -euo pipefail
|
|
|
|
HOST="root@10.10.10.122"
|
|
SCOPE="all" # all | api | frontend
|
|
|
|
ssh_cmd() {
|
|
if [[ -n "${SSHPASS:-}" ]] && command -v sshpass >/dev/null; then
|
|
sshpass -e ssh -o StrictHostKeyChecking=no "$@"
|
|
else
|
|
ssh -o StrictHostKeyChecking=no "$@"
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
echo "Usage: $0 [--host root@10.10.10.122] [--scope all|api|frontend] [--dry-run]"
|
|
exit 1
|
|
}
|
|
|
|
DRY=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--host) HOST="$2"; shift 2 ;;
|
|
--scope) SCOPE="$2"; shift 2 ;;
|
|
--dry-run) DRY=1; shift ;;
|
|
-h|--help) usage ;;
|
|
*) echo "Unknown: $1"; usage ;;
|
|
esac
|
|
done
|
|
|
|
run() {
|
|
if [[ "$DRY" -eq 1 ]]; then
|
|
echo "[dry-run] $*"
|
|
else
|
|
eval "$@"
|
|
fi
|
|
}
|
|
|
|
echo "=== DNS Viewer rollback — scope=$SCOPE host=$HOST ==="
|
|
|
|
ssh_cmd "$HOST" bash -s <<EOF
|
|
set -euo pipefail
|
|
BASE=/opt/ligbox-ops-platform
|
|
BK=\$(ls -td "\$BASE/.backups/dns-viewer-"* 2>/dev/null | head -1)
|
|
|
|
if [ -z "\$BK" ]; then
|
|
echo "ERRO: nenhum backup em \$BASE/.backups/dns-viewer-*"
|
|
echo "Correr preflight-dns-viewer.sh antes do próximo deploy."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Usando backup: \$BK"
|
|
|
|
# Feature flag off
|
|
if grep -q '^DNS_VIEWER_ENABLED=' "\$BASE/.env" 2>/dev/null; then
|
|
sed -i 's/^DNS_VIEWER_ENABLED=.*/DNS_VIEWER_ENABLED=0/' "\$BASE/.env"
|
|
else
|
|
echo 'DNS_VIEWER_ENABLED=0' >> "\$BASE/.env"
|
|
fi
|
|
echo "DNS_VIEWER_ENABLED=0"
|
|
|
|
SCOPE="${SCOPE}"
|
|
DRY=${DRY}
|
|
|
|
restore_api() {
|
|
[ -f "\$BK/api/cloudflare_dns.py" ] && cp -a "\$BK/api/cloudflare_dns.py" "\$BASE/api/app/"
|
|
[ -f "\$BK/api/main.py.bak" ] && cp -a "\$BK/api/main.py.bak" "\$BASE/api/app/main.py"
|
|
[ -f "\$BK/api/permissions.py" ] && cp -a "\$BK/api/permissions.py" "\$BASE/api/app/"
|
|
rm -f "\$BASE/api/app/dns_viewer.py" "\$BASE/api/app/openpanel_dns.py"
|
|
echo "API ficheiros restaurados"
|
|
}
|
|
|
|
restore_frontend() {
|
|
[ -f "\$BK/frontend/assets/app.js" ] && cp -a "\$BK/frontend/assets/app.js" "\$BASE/frontend/assets/"
|
|
rm -f "\$BASE/frontend/assets/dns-viewer.js"
|
|
[ -f "\$BK/frontend/index.html" ] && cp -a "\$BK/frontend/index.html" "\$BASE/frontend/"
|
|
echo "Frontend restaurado"
|
|
}
|
|
|
|
if [ "\$DRY" -eq 1 ]; then
|
|
echo "[dry-run] restore scope=\$SCOPE"
|
|
exit 0
|
|
fi
|
|
|
|
case "\$SCOPE" in
|
|
api) restore_api ;;
|
|
frontend) restore_frontend ;;
|
|
all) restore_api; restore_frontend ;;
|
|
*) echo "scope inválido"; exit 1 ;;
|
|
esac
|
|
|
|
cd "\$BASE"
|
|
docker compose -f docker-compose.mvp.yml build api frontend
|
|
docker compose -f docker-compose.mvp.yml up -d api frontend
|
|
sleep 3
|
|
curl -sS -o /dev/null -w 'health=%{http_code}\n' http://127.0.0.1:8080/health
|
|
curl -sS -o /dev/null -w 'frontend=%{http_code}\n' http://127.0.0.1:8091/
|
|
EOF
|
|
|
|
echo ""
|
|
echo "=== Rollback concluído — correr verify-dns-viewer.sh --legacy-only ==="
|