Skip to content

Commit

Permalink
Merge pull request #24 from balena-io/upgrade-script
Browse files Browse the repository at this point in the history
upgrade: Container upgrades existing data on start
  • Loading branch information
Rich Bayliss authored Apr 9, 2020
2 parents 67d5577 + 59717dc commit 525f5eb
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker

COPY create-resin-db.sh /docker-entrypoint-initdb.d/
COPY balena-entrypoint.sh /balena-entrypoint.sh

CMD [ "postgres" ]
ENTRYPOINT [ "/balena-entrypoint.sh" ]
118 changes: 118 additions & 0 deletions balena-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash

set -e

# creates a backup archive of the dir $1...
backup_data () {
gosu postgres tar --exclude backup.tar.gz -zcf /tmp/backup.tar.gz -C "$1" .
mv /tmp/backup.tar.gz "${1}/backup.tar.gz"
}

# 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
sed -i 's/$/ '"$1"'/' /etc/apt/sources.list.d/pgdg.list

apt-get -qq update \
&& apt-get install -qq -y --no-install-recommends \
"postgresql-$1" \
&& rm -rf /var/lib/apt/lists/*
fi
}

# creates a dir at $1 which is valid for Postgres data to live in...
create_postgres_data_dir () {
echo "=== Creating data dir $1"
mkdir -p "$1"
chmod 700 "$1"
chown -R postgres:postgres "$1"
}

# echo a message and die...
die_with_message () {
echo "[FATAL] $1"
exit 2
}

# check that this is running from within a valid Postgres container environment...
[ ! -z "$PG_MAJOR" ] || die_with_message "Not a compatible Postgres runtime environment"

# set our target version...
TARGET_VERSION="$PG_MAJOR"

# 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)"

# does the data need upgrading...
if [ "$SOURCE_VERSION" -ne "$TARGET_VERSION" ]; then
echo "=== Upgrading data from v${SOURCE_VERSION} to v${TARGET_VERSION}"

# define our directories...
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 extisting 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 "=== Initialising new data directory ${PGDATANEW}"
rm -rf "${PGDATANEW}"
create_postgres_data_dir "${PGDATANEW}"
gosu postgres initdb -D "$PGDATANEW" -U "$POSTGRES_USER" $POSTGRES_INITDB_ARGS

echo "=== Beginning pg_upgrade"
cd /tmp
gosu postgres pg_upgrade \
-U "$POSTGRES_USER" \
--old-datadir="$PGDATAOLD" \
--new-datadir="$PGDATANEW" \
--old-bindir="$PGBINOLD" \
--new-bindir="$PGBINNEW" \
--check

gosu postgres pg_upgrade \
-U "$POSTGRES_USER" \
--old-datadir="$PGDATAOLD" \
--new-datadir="$PGDATANEW" \
--old-bindir="$PGBINOLD" \
--new-bindir="$PGBINNEW"

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 extisting data to directory "${PGDATA}/${TARGET_VERSION}""
find "$PGDATA" -maxdepth 1 \
! -path "$PGDATA" \
| xargs mv -t "${PGDATA}/${TARGET_VERSION}"
fi
fi

# set our runtime data directory to the versioned one...
export PGDATA="${PGDATA}/${TARGET_VERSION}"

# run the existing Postgres entrypoint script...
. /docker-entrypoint.sh
_main "$@"

0 comments on commit 525f5eb

Please sign in to comment.