From addac34cfef5467463f7644a93bcd489df94f5fa Mon Sep 17 00:00:00 2001 From: Akis Kesoglou Date: Tue, 15 Feb 2022 20:51:56 +0200 Subject: [PATCH] Extend migrator to support upgrading between versioned data directories The migrator previously would only migrate data stored directly under PGDATA (as was the case in previous versions of this project before switching to versioned directories). This adds support for upgrading between versioned data directories as well. Change-type: minor --- balena-entrypoint.sh | 77 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/balena-entrypoint.sh b/balena-entrypoint.sh index 20ccd65..b388984 100755 --- a/balena-entrypoint.sh +++ b/balena-entrypoint.sh @@ -2,14 +2,6 @@ set -e -# copies all the data from $1 to $2 -restore_volume () { - echo "=== Restoring data volume structure" - find "$1" -maxdepth 1 \ - ! -path "$1" \ - | xargs mv -t "$2" -} - # install the old version of Postgres, required when doing an upgrade install_old_version () { if [ ! -d "/usr/lib/postgresql/$1/bin" ]; then @@ -41,37 +33,49 @@ die_with_message () { # set our target version TARGET_VERSION="$PG_MAJOR" +PGDATANEW="${PGDATA}/${TARGET_VERSION}" + +migrate_pgdata_root_if_needed () { + # perform a one-time migration from storing data under $PGDATA root, + # to storing it under $PGDATA/$PG_VERSION + if [ -f "${PGDATA}/PG_VERSION" ]; then + local version="$(cat "${PGDATA}/PG_VERSION")" + if [ ! -d "${PGDATA}/${version}" ]; then + create_postgres_data_dir "${PGDATA}/${version}" + echo "=== Moving existing data to directory "${PGDATA}/${version}"" + find "$PGDATA" -maxdepth 1 \ + ! -path "$PGDATA" \ + ! -path "${PGDATA}/${version}*" \ + | xargs mv -t "${PGDATA}/${version}" + fi + fi +} -# ensure we have a versioned data directory -[ -d "${PGDATA}/${TARGET_VERSION}" ] || create_postgres_data_dir "${PGDATA}/${TARGET_VERSION}" - -# check for Postgres data in the root of the $PGDATA directory -if [ -f "${PGDATA}/PG_VERSION" ]; then - SOURCE_VERSION="$(cat ${PGDATA}/PG_VERSION)" +find_source_version () { + # find our source version by looking for a PG_VERSION file + # in every directory under $PGDATA + for src in $(find "$PGDATA" -maxdepth 2 -type f -name 'PG_VERSION' | sort -rn); do + local version="$(cat "$src")" + if [ "$version" -ne "$TARGET_VERSION" ]; then + SOURCE_VERSION="$version" + PGDATAOLD="$(dirname "$src")" # drop 'PG_VERSION' from path + break + fi + done +} +perform_migration_if_needed () { # does the data need upgrading? - if [ "$SOURCE_VERSION" -ne "$TARGET_VERSION" ]; then + if [ -n "${SOURCE_VERSION}" ]; then echo "=== Upgrading data from v${SOURCE_VERSION} to v${TARGET_VERSION}" - PGDATAOLD="${PGDATA}/${SOURCE_VERSION}" - PGDATANEW="${PGDATA}/${TARGET_VERSION}" PGBINOLD="/usr/lib/postgresql/$SOURCE_VERSION/bin" PGBINNEW="/usr/lib/postgresql/$TARGET_VERSION/bin" echo "=== Installing tools for Postgres v${SOURCE_VERSION}" install_old_version "$SOURCE_VERSION" - echo "=== Moving existing data to ${PGDATAOLD}" - create_postgres_data_dir "${PGDATAOLD}" - find "$PGDATA" -maxdepth 1 \ - ! -path "$PGDATA" \ - ! -path "$PGDATAOLD*" \ - | xargs mv -t "${PGDATAOLD}" - - trap "restore_volume ${PGDATAOLD} ${PGDATA}" ERR - echo "=== Initializing new data directory ${PGDATANEW}" - rm -rf "${PGDATANEW}" create_postgres_data_dir "${PGDATANEW}" gosu postgres initdb -D "$PGDATANEW" -U "$POSTGRES_USER" $POSTGRES_INITDB_ARGS @@ -95,16 +99,21 @@ if [ -f "${PGDATA}/PG_VERSION" ]; then echo "=== Restoring configuration files" cp "${PGDATAOLD}/pg_hba.conf" "${PGDATANEW}/pg_hba.conf" cp "${PGDATAOLD}/pg_ident.conf" "${PGDATANEW}/pg_ident.conf" - else - echo "=== Moving existing data to directory "${PGDATA}/${TARGET_VERSION}"" - find "$PGDATA" -maxdepth 1 \ - ! -path "$PGDATA" \ - | xargs mv -t "${PGDATA}/${TARGET_VERSION}" + + echo "=== Migration succeeded; removing old data directory" + rm -rf "${PGDATAOLD}" fi -fi +} + +migrate_pgdata_root_if_needed +find_source_version +perform_migration_if_needed + +# ensure we have a versioned data directory +[ -d "${PGDATANEW}" ] || create_postgres_data_dir "${PGDATANEW}" # set our runtime data directory to the target version -export PGDATA="${PGDATA}/${TARGET_VERSION}" +export PGDATA="${PGDATANEW}" # run the existing Postgres entrypoint script . /usr/local/bin/docker-entrypoint.sh