Add host-ready restore automation scripts
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
RESTORE_TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BORG_CONTAINER="${BORG_CONTAINER:-borg-ui}"
|
||||
BORG_RESTORE_HOST_ROOT="${BORG_RESTORE_HOST_ROOT:-/mnt/user/appdata/borg-ui/restore}"
|
||||
BORG_PASSPHRASE_FILE_DEFAULT="${BORG_PASSPHRASE_FILE_DEFAULT:-/mnt/user/appdata/secrets/borg_repo_passphrase.txt}"
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "Missing command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_path() {
|
||||
[ -e "$1" ] || {
|
||||
echo "Missing path: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
latest_archive_name() {
|
||||
docker exec "$BORG_CONTAINER" python3 - <<'PY'
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/data/borg.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("select archive_name from backup_jobs where status='completed' order by created_at desc limit 1")
|
||||
row = cur.fetchone()
|
||||
if not row:
|
||||
raise SystemExit("No completed borg archive found")
|
||||
print(row[0])
|
||||
PY
|
||||
}
|
||||
|
||||
borg_repo_url() {
|
||||
docker exec "$BORG_CONTAINER" python3 - <<'PY'
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/data/borg.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("select path from repositories where path is not null and path != '' order by id asc limit 1")
|
||||
row = cur.fetchone()
|
||||
if not row:
|
||||
raise SystemExit("No borg repository configured")
|
||||
print(row[0])
|
||||
PY
|
||||
}
|
||||
|
||||
borg_extract() {
|
||||
local extract_dir="$1"
|
||||
shift
|
||||
local paths=("$@")
|
||||
docker exec -i "$BORG_CONTAINER" python3 - "$extract_dir" "${paths[@]}" <<'PY'
|
||||
import os, sys, subprocess
|
||||
extract_dir = sys.argv[1]
|
||||
paths = sys.argv[2:]
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/data/borg.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("select path from repositories where path is not null and path != '' order by id asc limit 1")
|
||||
repo = cur.fetchone()[0]
|
||||
cur.execute("select archive_name from backup_jobs where status='completed' order by created_at desc limit 1")
|
||||
archive = cur.fetchone()[0]
|
||||
with open('/local/secrets/borg_repo_passphrase.txt', 'r', encoding='utf-8') as f:
|
||||
os.environ['BORG_PASSPHRASE'] = f.read().strip()
|
||||
os.makedirs(extract_dir, exist_ok=True)
|
||||
os.chdir(extract_dir)
|
||||
subprocess.run(['borg', 'extract', f'{repo}::{archive}', *paths], check=True)
|
||||
PY
|
||||
}
|
||||
|
||||
write_report() {
|
||||
local report_file="$1"
|
||||
shift
|
||||
mkdir -p "$(dirname "$report_file")"
|
||||
cat > "$report_file"
|
||||
}
|
||||
|
||||
cleanup_compose() {
|
||||
local compose_file="$1"
|
||||
if [ -f "$compose_file" ]; then
|
||||
docker compose -f "$compose_file" down >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user