91 lines
2.6 KiB
Bash
91 lines
2.6 KiB
Bash
#!/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 in ('completed', 'completed_with_warnings') 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 in ('completed', 'completed_with_warnings') 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()
|
|
known_hosts = '/data/known_hosts'
|
|
if os.path.exists(known_hosts):
|
|
os.environ.setdefault(
|
|
'BORG_RSH',
|
|
f'ssh -o UserKnownHostsFile={known_hosts} -o StrictHostKeyChecking=yes',
|
|
)
|
|
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
|
|
}
|