176 lines
4.1 KiB
Bash
Executable File
176 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
|
|
cd "$ROOT"
|
|
|
|
if [ "$#" -ne 1 ]; then
|
|
echo "Usage: $0 PATH_TO_CUSTOM_FORMAT_DUMP" >&2
|
|
exit 1
|
|
fi
|
|
|
|
dump=$1
|
|
checksum="$dump.sha256"
|
|
|
|
if [ ! -f "$dump" ] || [ ! -s "$dump" ]; then
|
|
echo "Dump does not exist or is empty: $dump" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$checksum" ]; then
|
|
echo "Checksum manifest is required: $checksum" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$ROOT/.env" ]; then
|
|
echo "Missing $ROOT/.env." >&2
|
|
exit 1
|
|
fi
|
|
|
|
set -a
|
|
# shellcheck source=/dev/null
|
|
. "$ROOT/.env"
|
|
set +a
|
|
|
|
if [ "${DATABASE_MODE:-container}" != container ]; then
|
|
echo "restore-drill-compose.sh only operates on DATABASE_MODE=container." >&2
|
|
exit 1
|
|
fi
|
|
|
|
: "${POSTGRES_DB:?Set POSTGRES_DB in .env}"
|
|
: "${POSTGRES_USER:?Set POSTGRES_USER in .env}"
|
|
: "${DATABASE_URL:?Set DATABASE_URL in .env}"
|
|
|
|
dump_dir=$(CDPATH='' cd -- "$(dirname -- "$dump")" && pwd)
|
|
dump_name=$(basename -- "$dump")
|
|
|
|
(
|
|
cd "$dump_dir"
|
|
sha256sum --check --status "$(basename -- "$checksum")"
|
|
)
|
|
|
|
docker compose exec -T db pg_restore --list <"$dump" >/dev/null
|
|
|
|
drill_db="who_need_help_restore_drill_$(date -u +%Y%m%d%H%M%S)_$$"
|
|
created=false
|
|
|
|
cleanup() {
|
|
if [ "$created" = true ]; then
|
|
docker compose exec -T db \
|
|
dropdb --username "$POSTGRES_USER" --if-exists "$drill_db" >/dev/null
|
|
fi
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
docker compose exec -T db \
|
|
createdb \
|
|
--username "$POSTGRES_USER" \
|
|
--template template0 \
|
|
"$drill_db"
|
|
created=true
|
|
|
|
docker compose exec -T db \
|
|
pg_restore \
|
|
--username "$POSTGRES_USER" \
|
|
--dbname "$drill_db" \
|
|
--exit-on-error \
|
|
--no-owner \
|
|
--no-privileges <"$dump"
|
|
|
|
tables=$(
|
|
docker compose exec -T db \
|
|
psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \
|
|
--command "
|
|
SELECT tablename
|
|
FROM pg_tables
|
|
WHERE schemaname = 'public'
|
|
AND tablename <> 'spatial_ref_sys'
|
|
ORDER BY tablename;
|
|
"
|
|
)
|
|
|
|
table_count=0
|
|
total_rows=0
|
|
|
|
for table in $tables; do
|
|
restored_count=$(
|
|
docker compose exec -T db \
|
|
psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \
|
|
--command "SELECT count(*) FROM \"$table\";"
|
|
)
|
|
|
|
table_count=$((table_count + 1))
|
|
total_rows=$((total_rows + restored_count))
|
|
done
|
|
|
|
if [ "$table_count" -eq 0 ]; then
|
|
echo "The restored database contains no public application tables." >&2
|
|
exit 1
|
|
fi
|
|
|
|
postgis_version=$(
|
|
docker compose exec -T db \
|
|
psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \
|
|
--command "SELECT PostGIS_Lib_Version();"
|
|
)
|
|
|
|
case "$DATABASE_URL" in
|
|
*\?*)
|
|
database_base=${DATABASE_URL%%\?*}
|
|
database_query="?${DATABASE_URL#*\?}"
|
|
;;
|
|
|
|
*)
|
|
database_base=$DATABASE_URL
|
|
database_query=
|
|
;;
|
|
esac
|
|
|
|
database_prefix=${database_base%/*}
|
|
|
|
if [ "$database_prefix" = "$database_base" ]; then
|
|
echo "Could not derive the temporary drill DATABASE_URL." >&2
|
|
exit 1
|
|
fi
|
|
|
|
drill_database_url="$database_prefix/$drill_db$database_query"
|
|
|
|
docker compose run --rm --no-deps \
|
|
--env APP_ROLE=migrate \
|
|
--env "DATABASE_URL=$drill_database_url" \
|
|
migrate /app/bin/migrate
|
|
|
|
docker compose run --rm --no-deps \
|
|
--env APP_ROLE=migrate \
|
|
--env "DATABASE_URL=$drill_database_url" \
|
|
migrate /app/bin/who_need_help eval 'WhoNeedHelp.Release.await_migrations()'
|
|
|
|
migration_count=$(
|
|
docker compose exec -T db \
|
|
psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \
|
|
--command "SELECT count(*) FROM schema_migrations;"
|
|
)
|
|
|
|
docker compose exec -T db \
|
|
dropdb --username "$POSTGRES_USER" "$drill_db"
|
|
created=false
|
|
trap - EXIT HUP INT TERM
|
|
|
|
remaining=$(
|
|
docker compose exec -T db \
|
|
psql --username "$POSTGRES_USER" --dbname postgres --tuples-only --no-align \
|
|
--command "SELECT count(*) FROM pg_database WHERE datname = '$drill_db';"
|
|
)
|
|
|
|
if [ "$remaining" != "0" ]; then
|
|
echo "Restore drill database was not removed: $drill_db" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Restore drill passed for: $dump_name"
|
|
echo "Readable public tables: $table_count"
|
|
echo "Restored rows read: $total_rows"
|
|
echo "Applied migrations: $migration_count"
|
|
echo "PostGIS library: $postgis_version"
|
|
echo "Temporary database removed: $drill_db"
|