Collection of cookbooks for Podman Quadlets
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

153 lines
5.6 KiB

#!/bin/bash
set -Eeuo pipefail
# Find the latest PostgreSQL data directory
SOURCE_PGDATA=""
last_version=""
for version_file in /var/lib/postgresql/*/docker/PG_VERSION; do
if [ -f "$version_file" ]; then
version_dir=$(dirname "$version_file")
version_major=$(cat "$version_file")
if [ -z "$last_version" ] || [ "$version_major" -gt "$last_version" ]; then
last_version="$version_major"
SOURCE_PGDATA="$version_dir"
fi
fi
done
if [ -z "$SOURCE_PGDATA" ] || [ ! -d "$SOURCE_PGDATA" ]; then
echo "No PostgreSQL data directory found."
exit 1
fi
echo "Using PostgreSQL data directory: $SOURCE_PGDATA"
# Upgrade destination
TARGET_MAJOR_VERSION=${PGTARGET%%.*}
TARGET_PATH="/usr/local/bin/"
TARGET_PGDATA="/var/lib/postgresql/${TARGET_MAJOR_VERSION}/docker"
# Upgrade source
SOURCE_MAJOR_VERSION=$(cat "${SOURCE_PGDATA}/PG_VERSION")
SOURCE_PATH="/usr/local-pg${SOURCE_MAJOR_VERSION}/bin"
# Reuse functions from the official entrypoint script
source /usr/local/bin/postgres-docker-entrypoint.sh
# Because they may have been over by the sourced script, reset all flags
set -Eeuo pipefail
# if first arg looks like a flag, assume we want to run postgres server
if [ "$#" -eq 0 ] || [ "${1:0:1}" = '-' ]; then
set -- postgres "$@"
fi
# Setup environment variables
docker_setup_env
##
## Sanity checks
##
# No need to upgrade if same major version
if [ "${SOURCE_MAJOR_VERSION}" == "${TARGET_MAJOR_VERSION}" ]; then
echo "PostgreSQL data files version matches target version. No upgrade required."
exit 0
fi
# No automatic upgrade support for PostgreSQL versions less than 14
if [ "${SOURCE_MAJOR_VERSION}" -lt 14 ]; then
echo "PosgreSQL <14 is no longer supported for automatic upgrade. Please perform a manual upgrade."
exit 1
fi
# No downgrade support
if [ "${SOURCE_MAJOR_VERSION}" -gt "${TARGET_MAJOR_VERSION}" ]; then
echo "Downgrades are not supported. Aborting."
exit 1
fi
# Check for concurrent upgrade processes
if [ -f "${SOURCE_PGDATA}/upgrade_in_progress.lock" ]; then
echo "Another upgrade process seems to be running (upgrade_in_progress.lock file found). Aborting."
exit 2
fi
# On PG v18, we have to check that data checksums, be it positive or negative, is set on the initdb args
# even when the user already provided initdb args, because otherwise Postgres v18 assumes you want checksums
# we now do this on every version to avoid one more conditional
# it also adds support for people who used Postgres with checksums before v18
if [[ -z "${POSTGRES_INITDB_ARGS:-}" || "${POSTGRES_INITDB_ARGS:-}" != *"data-checksums"* ]]; then
DATA_CHECKSUMS_ENABLED=$(echo 'SHOW DATA_CHECKSUMS' | "${SOURCE_PATH}/postgres" --single "${@:2}" -D "${SOURCE_PGDATA}" "${POSTGRES_DB}" | grep 'data_checksums = "' | cut -d '"' -f 2)
if [ "$DATA_CHECKSUMS_ENABLED" == "on" ]; then
DATA_CHECKSUMS_PARAMETER="--data-checksums"
elif [ "$TARGET_MAJOR_VERSION" -eq 18 ]; then
# Postgres v18 enables data checksums by default and is the only version with this opt-out parameter
DATA_CHECKSUMS_PARAMETER="--no-data-checksums"
fi
POSTGRES_INITDB_ARGS="${POSTGRES_INITDB_ARGS:-} ${DATA_CHECKSUMS_PARAMETER:-}"
fi
# Flags the data directory as being in the middle of an upgrade
mkdir -p "${TARGET_PGDATA}"
touch "${SOURCE_PGDATA}/upgrade_in_progress.lock"
# Now PGDATA points to the target data directory
export PGDATA="${TARGET_PGDATA}"
# Initialize target data directory
docker_verify_minimum_env
docker_init_database_dir
# Change into the PostgreSQL database directory, to avoid a pg_upgrade error about write permissions
cd "${PGDATA}"
# Perform the upgrade
echo "Upgrading PostgreSQL from version ${SOURCE_MAJOR_VERSION} to ${TARGET_MAJOR_VERSION}..."
"${TARGET_PATH}/pg_upgrade" --username="${POSTGRES_USER}" --link \
--old-datadir "${SOURCE_PGDATA}" --new-datadir "${TARGET_PGDATA}" \
--old-bindir "${SOURCE_PATH}" --new-bindir "${TARGET_PATH}" \
--socketdir="/var/run/postgresql" \
--old-options "${run_options[*]}" --new-options "${run_options[*]}"
# Re-use the pg_hba.conf and pg_ident.conf from the old data directory
cp -f "${SOURCE_PGDATA}/pg_hba.conf" "${SOURCE_PGDATA}/pg_ident.conf" "${TARGET_PGDATA}"
# Set PGPASSWORD in case password authentication is used
if [ -z "${PGPASSWORD:-}" ] && [ -n "${POSTGRES_PASSWORD:-}" ]; then
export PGPASSWORD="${POSTGRES_PASSWORD}"
fi
# Start a temporary PostgreSQL server
docker_temp_server_start "$@"
if [ -n "${POSTGRES_UPDATE_SCRIPT:-}" ] && [ -f "${POSTGRES_UPDATE_SCRIPT}" ]; then
echo "Running update script: ${POSTGRES_UPDATE_SCRIPT}"
psql --username="${POSTGRES_USER}" -f "${POSTGRES_UPDATE_SCRIPT}"
fi
echo "Updating query planner stats"
declare -a database_list=( $(echo 'SELECT datname FROM pg_catalog.pg_database WHERE datistemplate IS FALSE' | psql --username="${POSTGRES_USER}" -1t --csv "${POSTGRES_DB}") )
for database in "${database_list[@]}"; do
echo "VACUUM (ANALYZE, VERBOSE, INDEX_CLEANUP FALSE)" | psql --username="${POSTGRES_USER}" -t --csv "${database}"
done
if [[ "${PGAUTO_REINDEX:-}" != "no" ]]; then
echo "Reindexing the databases"
if [[ "$TARGET_MAJOR_VERSION" -le 15 ]]; then
reindexdb --all --username="${POSTGRES_USER}"
else
reindexdb --all --concurrently --username="${POSTGRES_USER}"
fi
echo "End of reindexing the databases"
fi
# Stop the temporary PostgreSQL server
unset PGPASSWORD
docker_temp_server_stop
# Remove old data directory
echo "Removing old PostgreSQL data directory: ${SOURCE_PGDATA}"
rm -rf "${SOURCE_PGDATA}"
# Clean up lock files
rm -f "${SOURCE_PGDATA}/upgrade_in_progress.lock"
echo "PostgreSQL upgrade from version ${SOURCE_MAJOR_VERSION} to ${TARGET_MAJOR_VERSION} completed successfully."