forked from baron/baron-sso
151 lines
3.4 KiB
Bash
151 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
BACKUP_SUPPORTED_SERVICES="postgres ory-postgres clickhouse ory-clickhouse config"
|
|
BACKUP_SUPPORTED_DATASETS="full personnel"
|
|
|
|
backup_repo_root() {
|
|
if [[ -n "${BACKUP_REPO_ROOT:-}" ]]; then
|
|
printf '%s\n' "$BACKUP_REPO_ROOT"
|
|
return
|
|
fi
|
|
|
|
local script_dir
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
printf '%s\n' "$script_dir"
|
|
}
|
|
|
|
backup_log() {
|
|
printf '==> %s\n' "$*"
|
|
}
|
|
|
|
backup_die() {
|
|
printf 'ERROR: %s\n' "$*" >&2
|
|
return 1
|
|
}
|
|
|
|
backup_require_command() {
|
|
local command_name="$1"
|
|
command -v "$command_name" >/dev/null 2>&1 || backup_die "required command not found: $command_name"
|
|
}
|
|
|
|
backup_utc_now() {
|
|
date -u '+%Y-%m-%dT%H:%M:%SZ'
|
|
}
|
|
|
|
backup_timestamp() {
|
|
date -u '+%Y%m%d-%H%M%SZ'
|
|
}
|
|
|
|
backup_git_commit() {
|
|
local repo_root="$1"
|
|
git -c "safe.directory=$repo_root" -C "$repo_root" rev-parse --short=12 HEAD 2>/dev/null || printf 'unknown'
|
|
}
|
|
|
|
normalize_service_filter() {
|
|
local raw="${1:-all}"
|
|
local normalized=""
|
|
local candidate
|
|
|
|
if [[ "$raw" == "all" || -z "$raw" ]]; then
|
|
printf '%s\n' "$BACKUP_SUPPORTED_SERVICES"
|
|
return
|
|
fi
|
|
|
|
raw="${raw//,/ }"
|
|
for candidate in $raw; do
|
|
if ! grep -qw -- "$candidate" <<<"$BACKUP_SUPPORTED_SERVICES"; then
|
|
backup_die "unknown backup service: $candidate"
|
|
return 1
|
|
fi
|
|
if ! grep -qw -- "$candidate" <<<"$normalized"; then
|
|
normalized="${normalized:+$normalized }$candidate"
|
|
fi
|
|
done
|
|
|
|
[[ -n "$normalized" ]] || backup_die "service filter must not be empty"
|
|
printf '%s\n' "$normalized"
|
|
}
|
|
|
|
normalize_dataset_profile() {
|
|
local raw="${1:-full}"
|
|
|
|
[[ -n "$raw" ]] || raw="full"
|
|
if ! grep -qw -- "$raw" <<<"$BACKUP_SUPPORTED_DATASETS"; then
|
|
backup_die "unknown backup dataset: $raw"
|
|
return 1
|
|
fi
|
|
|
|
printf '%s\n' "$raw"
|
|
}
|
|
|
|
service_enabled() {
|
|
local service="$1"
|
|
local services="$2"
|
|
local candidate
|
|
|
|
for candidate in $services; do
|
|
[[ "$candidate" == "$service" ]] && return 0
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
backup_require_path() {
|
|
local path="$1"
|
|
[[ -e "$path" ]] || backup_die "required path not found: $path"
|
|
}
|
|
|
|
backup_container_running() {
|
|
local container="$1"
|
|
docker inspect -f '{{.State.Running}}' "$container" 2>/dev/null | grep -qx 'true'
|
|
}
|
|
|
|
backup_require_container() {
|
|
local container="$1"
|
|
backup_container_running "$container" || backup_die "container is not running: $container"
|
|
}
|
|
|
|
backup_redact_env() {
|
|
local source_file="$1"
|
|
local target_file="$2"
|
|
|
|
sed -E '/^[[:space:]]*#/! s/^([^=]*(SECRET|PASSWORD|TOKEN|KEY|PRIVATE|CLIENT_SECRET|COOKIE)[^=]*)=.*/\1=REDACTED/I' "$source_file" >"$target_file"
|
|
}
|
|
|
|
backup_checksum_file() {
|
|
local backup_dir="$1"
|
|
(
|
|
cd "$backup_dir"
|
|
find . -type f ! -name 'checksums.sha256' -print0 \
|
|
| sort -z \
|
|
| xargs -0 sha256sum
|
|
) >"$backup_dir/checksums.sha256"
|
|
}
|
|
|
|
backup_verify_checksums() {
|
|
local backup_dir="$1"
|
|
backup_require_path "$backup_dir/checksums.sha256"
|
|
(
|
|
cd "$backup_dir"
|
|
sha256sum -c checksums.sha256
|
|
)
|
|
}
|
|
|
|
backup_safe_tar() {
|
|
local source_path="$1"
|
|
local target_base="$2"
|
|
local source_parent
|
|
local source_name
|
|
|
|
[[ -e "$source_path" ]] || return 0
|
|
|
|
source_parent="$(dirname "$source_path")"
|
|
source_name="$(basename "$source_path")"
|
|
|
|
if command -v zstd >/dev/null 2>&1; then
|
|
tar --zstd -cf "${target_base}.tar.zst" -C "$source_parent" "$source_name"
|
|
else
|
|
tar -czf "${target_base}.tar.gz" -C "$source_parent" "$source_name"
|
|
fi
|
|
}
|