fix(backup): run all required backup domains
This commit is contained in:
@@ -14,7 +14,7 @@ source "$(dirname "$0")/common.sh"
|
||||
main() {
|
||||
local start_time=$(date +%s)
|
||||
local failed=0
|
||||
local total=9
|
||||
local total=13
|
||||
|
||||
log_info "╔══════════════════════════════════════════════════════════════╗"
|
||||
log_info "║ WOOO AIOps - 全服務備份開始 (v3.0) ║"
|
||||
@@ -107,6 +107,42 @@ main() {
|
||||
failed=$((failed+1))
|
||||
fi
|
||||
|
||||
# Sentry data plane (Postgres, ClickHouse, Kafka, Redis, object state)
|
||||
log_info ">>> [10/${total}] 備份 Sentry..."
|
||||
if /backup/scripts/backup-sentry.sh; then
|
||||
log_success " Sentry 備份成功"
|
||||
else
|
||||
log_error " Sentry 備份失敗"
|
||||
failed=$((failed+1))
|
||||
fi
|
||||
|
||||
# AI model/tooling manifests from 188 (model blobs remain excluded by policy)
|
||||
log_info ">>> [11/${total}] 備份 AI artifacts (188)..."
|
||||
if /backup/scripts/backup-ai-artifacts.sh; then
|
||||
log_success " AI artifacts 備份成功"
|
||||
else
|
||||
log_error " AI artifacts 備份失敗"
|
||||
failed=$((failed+1))
|
||||
fi
|
||||
|
||||
# Host, K3s, service, and recovery configuration state
|
||||
log_info ">>> [12/${total}] 備份主機與服務設定..."
|
||||
if /backup/scripts/backup-configs.sh; then
|
||||
log_success " 主機與服務設定備份成功"
|
||||
else
|
||||
log_error " 主機與服務設定備份失敗"
|
||||
failed=$((failed+1))
|
||||
fi
|
||||
|
||||
# Public route, TLS, DNS-answer, and edge inventory evidence
|
||||
log_info ">>> [13/${total}] 備份 public routes..."
|
||||
if /backup/scripts/backup-public-routes.sh; then
|
||||
log_success " Public routes 備份成功"
|
||||
else
|
||||
log_error " Public routes 備份失敗"
|
||||
failed=$((failed+1))
|
||||
fi
|
||||
|
||||
local end_time=$(date +%s)
|
||||
local duration=$((end_time - start_time))
|
||||
|
||||
|
||||
50
scripts/backup/tests/test_backup_all_required_domains.py
Normal file
50
scripts/backup/tests/test_backup_all_required_domains.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
BACKUP_ALL = ROOT / "scripts" / "backup" / "backup-all.sh"
|
||||
PLAYBOOK = ROOT / "infra" / "ansible" / "playbooks" / "110-devops.yml"
|
||||
|
||||
REQUIRED_BACKUP_SCRIPTS = (
|
||||
"backup-gitea.sh",
|
||||
"backup-momo.sh",
|
||||
"backup-harbor.sh",
|
||||
"backup-awoooi.sh",
|
||||
"backup-langfuse.sh",
|
||||
"backup-monitoring.sh",
|
||||
"backup-signoz.sh",
|
||||
"backup-open-webui.sh",
|
||||
"backup-clawbot.sh",
|
||||
"backup-sentry.sh",
|
||||
"backup-ai-artifacts.sh",
|
||||
"backup-configs.sh",
|
||||
"backup-public-routes.sh",
|
||||
)
|
||||
|
||||
|
||||
def test_backup_all_runs_every_required_domain_once() -> None:
|
||||
source = BACKUP_ALL.read_text(encoding="utf-8")
|
||||
|
||||
assert "local total=13" in source
|
||||
assert [int(value) for value in re.findall(r">>> \[(\d+)/\$\{total\}\]", source)] == list(
|
||||
range(1, 14)
|
||||
)
|
||||
for script in REQUIRED_BACKUP_SCRIPTS:
|
||||
assert source.count(f"/backup/scripts/{script}") == 1
|
||||
|
||||
|
||||
def test_ansible_deploys_every_script_called_by_backup_all() -> None:
|
||||
playbook = PLAYBOOK.read_text(encoding="utf-8")
|
||||
|
||||
for script in REQUIRED_BACKUP_SCRIPTS:
|
||||
assert f"- {script}" in playbook
|
||||
|
||||
|
||||
def test_backup_all_does_not_publish_or_delete_offsite_data() -> None:
|
||||
source = BACKUP_ALL.read_text(encoding="utf-8")
|
||||
|
||||
for forbidden in ("rclone ", "sync-offsite-backups.sh", "rclone-last-success"):
|
||||
assert forbidden not in source
|
||||
Reference in New Issue
Block a user