Skip to content

Commit

Permalink
Extend migrator to support upgrading between versioned data directories
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dfunckt committed Feb 17, 2022
1 parent 66bca3c commit bb35884
Showing 1 changed file with 43 additions and 34 deletions.
77 changes: 43 additions & 34 deletions balena-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down

0 comments on commit bb35884

Please sign in to comment.