From 3f5b4adceca31d360c4a0c73f358c7544be31fdf Mon Sep 17 00:00:00 2001 From: Celes Renata Date: Sun, 12 Apr 2026 14:21:59 -0700 Subject: [PATCH] =?UTF-8?q?phase=2017:=20add=20backup/restore=20scripts=20?= =?UTF-8?q?=E2=80=94=20PostgreSQL=20+=20MinIO=20=E2=86=92=20NFS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/backup.sh | 115 +++++++++++++++++++++++++++++++++++++++++++ scripts/restore.sh | 119 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100755 scripts/backup.sh create mode 100755 scripts/restore.sh diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100755 index 0000000..b68a5b5 --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# Stonks Oracle Backup — PostgreSQL + MinIO → NFS +# Usage: bash scripts/backup.sh +set -euo pipefail + +NAMESPACE="stonks-oracle" +NFS_SERVER="192.168.42.8" +NFS_PATH="/volume1/Kubernetes/stonks" +BACKUP_NAME="stonks-backup-$(date +%Y%m%d-%H%M%S)" +JOB_NAME="stonks-backup" + +echo "=== Stonks Oracle Backup: ${BACKUP_NAME} ===" + +# Clean up any previous backup job +kubectl delete job ${JOB_NAME} -n ${NAMESPACE} --ignore-not-found=true 2>/dev/null || true + +cat </dev/null + + for bucket in stonks-raw-market stonks-raw-news stonks-raw-filings stonks-normalized stonks-llm-prompts stonks-llm-results stonks-lakehouse stonks-audit; do + if mc ls "backup/\${bucket}" >/dev/null 2>&1; then + echo " Mirroring \${bucket}..." + mc mirror --quiet "backup/\${bucket}" "\${DIR}/minio/\${bucket}/" 2>/dev/null || echo " (empty or error)" + else + echo " Bucket \${bucket} not found, skipping" + fi + done + + echo "[3/3] Writing manifest..." + cat > "\${DIR}/manifest.json" <&1 || { + echo "Backup job failed or timed out. Logs:" + kubectl logs job/${JOB_NAME} -n ${NAMESPACE} 2>&1 | tail -20 + exit 1 +} + +echo "" +kubectl logs job/${JOB_NAME} -n ${NAMESPACE} 2>&1 | tail -10 +echo "" +echo "=== Backup ${BACKUP_NAME} complete ===" diff --git a/scripts/restore.sh b/scripts/restore.sh new file mode 100755 index 0000000..dca88b1 --- /dev/null +++ b/scripts/restore.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# Stonks Oracle Restore — NFS → PostgreSQL + MinIO +# Usage: bash scripts/restore.sh [backup_name] +# If no backup_name given, restores from "latest" symlink. +set -euo pipefail + +NAMESPACE="stonks-oracle" +NFS_SERVER="192.168.42.8" +NFS_PATH="/volume1/Kubernetes/stonks" +BACKUP_NAME="${1:-latest}" +JOB_NAME="stonks-restore" + +echo "=== Stonks Oracle Restore: ${BACKUP_NAME} ===" +echo "WARNING: This will DROP and recreate the stonks database." +echo "Press Ctrl+C within 5 seconds to abort..." +sleep 5 + +# Clean up any previous restore job +kubectl delete job ${JOB_NAME} -n ${NAMESPACE} --ignore-not-found=true 2>/dev/null || true + +cat </dev/null || true + exit 1 + fi + + echo "Restoring from: \${DIR}" + cat "\${DIR}/manifest.json" 2>/dev/null || true + + echo "" + echo "[1/3] Restoring PostgreSQL..." + # Drop and recreate all tables by restoring with --clean + PGPASSWORD="\${POSTGRES_PASSWORD}" pg_restore \ + -h "\${POSTGRES_HOST}" -p "\${POSTGRES_PORT}" \ + -U "\${POSTGRES_USER}" -d "\${POSTGRES_DB}" \ + --clean --if-exists --no-owner --no-acl \ + "\${DIR}/stonks.pgdump" 2>&1 || echo " (some drop errors are expected on first restore)" + echo " PostgreSQL restored" + + echo "[2/3] Restoring MinIO buckets..." + curl -sL https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc + chmod +x /usr/local/bin/mc + mc alias set backup "http://\${MINIO_ENDPOINT}" "\${MINIO_ACCESS_KEY}" "\${MINIO_SECRET_KEY}" --api S3v4 2>/dev/null + + for bucket in stonks-raw-market stonks-raw-news stonks-raw-filings stonks-normalized stonks-llm-prompts stonks-llm-results stonks-lakehouse stonks-audit; do + if [ -d "\${DIR}/minio/\${bucket}" ]; then + echo " Restoring \${bucket}..." + mc mb --ignore-existing "backup/\${bucket}" 2>/dev/null || true + mc mirror --overwrite --quiet "\${DIR}/minio/\${bucket}/" "backup/\${bucket}" 2>/dev/null || echo " (empty or error)" + fi + done + + echo "[3/3] Verifying..." + PGPASSWORD="\${POSTGRES_PASSWORD}" psql \ + -h "\${POSTGRES_HOST}" -p "\${POSTGRES_PORT}" \ + -U "\${POSTGRES_USER}" -d "\${POSTGRES_DB}" \ + -c "SELECT 'companies=' || count(*) FROM companies UNION ALL SELECT 'documents=' || count(*) FROM documents UNION ALL SELECT 'intelligence=' || count(*) FROM document_intelligence;" + + echo "=== Restore complete ===" +EOJOB + +echo "Waiting for restore job to complete..." +kubectl wait --for=condition=complete job/${JOB_NAME} -n ${NAMESPACE} --timeout=600s 2>&1 || { + echo "Restore job failed or timed out. Logs:" + kubectl logs job/${JOB_NAME} -n ${NAMESPACE} 2>&1 | tail -20 + exit 1 +} + +echo "" +kubectl logs job/${JOB_NAME} -n ${NAMESPACE} 2>&1 | tail -15 +echo "" +echo "=== Restore from ${BACKUP_NAME} complete ===" +echo "You may want to restart services: kubectl rollout restart deployment -n ${NAMESPACE} --all"