Files
ems/scripts/import_ems_db.sh
Dusan Vojacek 2f7d3c2770
Some checks failed
deploy / deploy (push) Failing after 0s
test / smoke-test (push) Has been cancelled
upgrade na pg18
2026-04-05 10:45:39 +02:00

135 lines
5.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Import zálohy EMS (pg_dump -Fc) do Postgresu v Dockeru na serveru.
#
# Předpoklad: čerstvý volume nebo vědomá obnova přes existující data.
# Spouštěj na serveru z /opt/ems-deploy (nebo nastav EMS_DEPLOY_ROOT).
#
# Postup (nová instance, ještě bez plného stacku):
# 1) /opt/ems-deploy/.env vyplněné (DB_USER, DB_PASSWORD stejné jako v cílové DB po initu db)
# 2) docker compose -f /opt/ems-deploy/docker-compose.yml --env-file /opt/ems-deploy/.env up -d db
# 3) Počkej na healthy: docker compose ... ps
# 4) bash app/scripts/import_ems_db.sh /tmp/ems.dump
# 5) flyway migrate (doplní PK / FK po problematickém restore V032V034)
# 6) Celý stack: /opt/ems-deploy/deploy.sh (nebo docker compose up -d)
#
# Volby prostředí:
# EMS_DEPLOY_ROOT=/opt/ems-deploy (výchozí)
# COMPOSE_FILE, ENV_FILE přepíšou cesty k souborům
# EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 přeskočí timescaledb_pre_restore / post_restore (jen výjimečně)
#
# TimescaleDB doporučení z dokumentace (full restore):
# - Cílová DB má mít rozšíření timescaledb před restore.
# - Před pg_restore: SELECT timescaledb_pre_restore();
# - Po pg_restore: ALTER EXTENSION timescaledb UPDATE; (srovná katalog zálohy s verzí v imagi
# jinak post_restore hlásí „catalog version mismatch expected … seen …“)
# - Pak: SELECT timescaledb_post_restore();
# - Ideálně stejná major verze Postgres + Timescale jako u zálohy; jinak pin imagí
# (např. timescale/timescaledb:2.25.2-pg16 místo latest-pg16).
# - Bez paralelního pg_restore (-j) může rozbít pořadí objektů a chunky.
#
# pg_restore z běžného pg_dump i tak může u hypertable vygenerovat nevhodné DDL (např. ALTER TABLE ONLY
# u FK). Po importu proto spusťte flyway migrate (V034 doplní chybějící FK).
#
# Robustnější varianta (schema + data zvlášť) viz oficiální návod Timescale / Tiger Data:
# pg_dump -Fc --section=pre-data --exclude-schema='_timescaledb*' …
# na cíli znovu create_hypertable(...) (např. přes Flyway), data COPY / parallel-copy.
# Tento skript řeší klasický jednosouborový -Fc restore, ne oddělené sekce.
set -euo pipefail
ROOT="${EMS_DEPLOY_ROOT:-/opt/ems-deploy}"
COMPOSE_FILE="${COMPOSE_FILE:-$ROOT/docker-compose.yml}"
ENV_FILE="${ENV_FILE:-$ROOT/.env}"
if [[ $# -lt 1 ]]; then
echo "Usage: $0 /cesta/k/ems.dump" >&2
exit 1
fi
DUMP="$(readlink -f "$1")"
if [[ ! -f "$DUMP" ]]; then
echo "ERROR: soubor neexistuje: $DUMP" >&2
exit 1
fi
if [[ ! -f "$COMPOSE_FILE" ]]; then
echo "ERROR: compose not found: $COMPOSE_FILE" >&2
exit 1
fi
if [[ ! -f "$ENV_FILE" ]]; then
echo "ERROR: .env not found: $ENV_FILE" >&2
exit 1
fi
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
: "${DB_USER:?DB_USER missing in $ENV_FILE}"
: "${DB_PASSWORD:?DB_PASSWORD missing in $ENV_FILE}"
cd "$ROOT"
if ! docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps --status running -q db | grep -q .; then
echo "ERROR: db neběží. Spusť jen databázi, např.:" >&2
echo " docker compose -f \"$COMPOSE_FILE\" --env-file \"$ENV_FILE\" up -d db" >&2
exit 1
fi
compose_db() {
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T \
-e "PGPASSWORD=${DB_PASSWORD}" \
db \
"$@"
}
CID="$(docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps -q db)"
echo "Kopíruji dump do kontejneru..."
docker cp "$DUMP" "${CID}:/tmp/ems_import.dump"
if [[ "${EMS_SKIP_TIMESCALE_RESTORE_HOOKS:-0}" != "1" ]]; then
echo "Timescale: CREATE EXTENSION + timescaledb_pre_restore()…"
compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
-c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
-c "SELECT timescaledb_pre_restore();"
else
echo "WARN: EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 přeskakuji pre_restore"
fi
echo "Obnovuji databázi ems (--clean smaže existující objekty ve schématech ze zálohy)…"
set +e
compose_db pg_restore -U "$DB_USER" -d ems --clean --if-exists --no-owner --no-acl --verbose /tmp/ems_import.dump
RESTORE_EXIT=$?
set -e
if [[ "${EMS_SKIP_TIMESCALE_RESTORE_HOOKS:-0}" != "1" ]]; then
echo "Timescale: ALTER EXTENSION timescaledb UPDATE (katalog ze zálohy → verze v imagi)…"
if compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
-c "ALTER EXTENSION timescaledb UPDATE;"; then
echo "Timescale: timescaledb_post_restore()…"
if ! compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
-c "SELECT timescaledb_post_restore();"; then
echo "ERROR: timescaledb_post_restore() selhal (zkontroluj verze PG/Timescale vs. záloha)." >&2
RESTORE_EXIT=1
fi
else
echo "ERROR: ALTER EXTENSION timescaledb UPDATE selhalo nespouštím post_restore." >&2
echo " Zkus v compose stejný Timescale tag jako u zdroje dumpu (např. :2.25.2-pg16), nebo nový dump po upgrade zdroje." >&2
RESTORE_EXIT=1
fi
else
echo "WARN: EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 přeskakuji post_restore"
fi
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T db rm -f /tmp/ems_import.dump
if [[ "$RESTORE_EXIT" -ne 0 ]]; then
echo "WARN: pg_restore skončil s kódem $RESTORE_EXIT (časté u FK na hypertable). Spusť flyway migrate." >&2
fi
echo "Import dokončen (exit pg_restore=$RESTORE_EXIT). Doporučeno: flyway migrate, pak deploy.sh / docker compose up -d."
exit "$RESTORE_EXIT"