73 lines
2.4 KiB
Bash
Executable File
73 lines
2.4 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
if [ "$#" -ne 1 ]; then
|
|
echo "usage: $0 <backup-directory>" >&2
|
|
exit 2
|
|
fi
|
|
|
|
backup_dir="$1"
|
|
image="${ASSISTANT_RESTORE_IMAGE:-postgres:18.6-alpine}"
|
|
container="assistant-postgres-restore-check-$(date -u +%Y%m%dT%H%M%SZ)-$$"
|
|
password="$(od -An -N24 -tx1 /dev/urandom | tr -d ' \n')"
|
|
created=false
|
|
|
|
cleanup() {
|
|
if [ "$created" = true ]; then
|
|
docker rm -f "$container" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
for file in assistant.dump globals.sql database.name owner.name SHA256SUMS; do
|
|
if [ ! -f "$backup_dir/$file" ]; then
|
|
echo "Backup file is missing: $file" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
(
|
|
cd "$backup_dir"
|
|
sha256sum -c SHA256SUMS
|
|
)
|
|
|
|
database="$(sed -n '1p' "$backup_dir/database.name")"
|
|
owner="$(sed -n '1p' "$backup_dir/owner.name")"
|
|
[ -n "$database" ] && [ -n "$owner" ] || {
|
|
echo "Database metadata is empty" >&2
|
|
exit 1
|
|
}
|
|
case "$database:$owner" in
|
|
*[!A-Za-z0-9_:.-]*) echo "Unsafe database metadata" >&2; exit 1 ;;
|
|
esac
|
|
|
|
docker run -d --name "$container" \
|
|
--tmpfs /var/lib/postgresql:rw,noexec,nosuid,size=1g \
|
|
-e POSTGRES_PASSWORD="$password" \
|
|
"$image" >/dev/null
|
|
created=true
|
|
|
|
attempt=0
|
|
until docker exec "$container" pg_isready -U postgres -d postgres >/dev/null 2>&1; do
|
|
attempt=$((attempt + 1))
|
|
if [ "$attempt" -ge 60 ]; then
|
|
docker logs "$container" >&2
|
|
echo "Restore-check PostgreSQL did not become ready" >&2
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
docker exec -i "$container" psql -v ON_ERROR_STOP=1 -U postgres -d postgres <"$backup_dir/globals.sql" >/dev/null
|
|
docker exec "$container" psql -v ON_ERROR_STOP=1 -U postgres -d postgres \
|
|
-c "CREATE DATABASE \"$database\" OWNER \"$owner\"" >/dev/null
|
|
docker exec -i "$container" pg_restore --exit-on-error --no-password -U postgres -d "$database" <"$backup_dir/assistant.dump" >/dev/null
|
|
|
|
schema_count="$(docker exec "$container" psql -U postgres -d "$database" -Atqc "select count(*) from information_schema.schemata where schema_name not in ('pg_catalog','information_schema') and schema_name not like 'pg_toast%'")"
|
|
table_count="$(docker exec "$container" psql -U postgres -d "$database" -Atqc "select count(*) from information_schema.tables where table_schema not in ('pg_catalog','information_schema')")"
|
|
if [ "$schema_count" -lt 1 ] || [ "$table_count" -lt 1 ]; then
|
|
echo "Restored database lacks expected user objects" >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf 'restore verified: database=%s schemas=%s tables=%s\n' "$database" "$schema_count" "$table_count"
|