Skip to content

Commit

Permalink
Automatically do post upgrade steps (vacuum analyze, database reindex…
Browse files Browse the repository at this point in the history
…ing) (#50)
  • Loading branch information
justinclift authored Oct 3, 2024
1 parent 253b8e1 commit 93c5fd8
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 39 deletions.
5 changes: 4 additions & 1 deletion Dockerfile.alpine
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG PGTARGET=16
ARG PGTARGET=17

### Things we need in all build containers
FROM alpine:3.20 AS base-build
Expand Down Expand Up @@ -179,6 +179,9 @@ RUN apk update && \
# Pass the PG build target through to the running image
ENV PGTARGET=${PGTARGET}

# Copy across the post-upgrade shell script
COPY pgautoupgrade-postupgrade.sh /usr/local/bin/

# Set up the script run by the container when it starts
WORKDIR /var/lib/postgresql
COPY docker-entrypoint.sh /usr/local/bin/
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile.bookworm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG PGTARGET=16
ARG PGTARGET=17

### Things we need in all build containers
FROM debian:bookworm AS base-build
Expand Down Expand Up @@ -174,6 +174,9 @@ RUN apt update && \
# Pass the PG build target through to the running image
ENV PGTARGET=${PGTARGET}

# Copy across the post-upgrade shell script
COPY pgautoupgrade-postupgrade.sh /usr/local/bin/

# Set up the script run by the container when it starts
WORKDIR /var/lib/postgresql
COPY docker-entrypoint.sh /usr/local/bin/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ like to upgrade to, then change your docker image to match:

### "One shot" mode

If you just want to perform the upgrade without starting PostgreSQL
If you just want to perform the upgrade without running PostgreSQL
afterwards, then you can use "[One Shot](https://github.com/pgautoupgrade/docker-pgautoupgrade/issues/13)" mode.

To do that, add an environment variable called `PGAUTO_ONESHOT`
Expand Down
41 changes: 32 additions & 9 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ _main() {

# For development of pgautoupgrade. This spot leaves the container running, prior to the pgautoupgrade scripting
# executing
local UPGRADE_PERFORMED=0
if [ "x${PGAUTO_DEVEL}" = "xbefore" ]; then
echo "---------------------------------------------------------------------------"
echo "In pgautoupgrade development mode, paused prior to pgautoupgrade scripting."
Expand Down Expand Up @@ -540,7 +541,7 @@ _main() {
echo "Running pg_upgrade command, from $(pwd)"
echo "---------------------------------------"
bin_path=$(get_bin_path)
${bin_path}/pg_upgrade --username="${POSTGRES_USER}" --link -d "${OLD}" -D "${NEW}" -b "${OLDPATH}/bin" -B "${bin_path}" --socketdir="/var/run/postgresql"
"${bin_path}/pg_upgrade" --username="${POSTGRES_USER}" --link -d "${OLD}" -D "${NEW}" -b "${OLDPATH}/bin" -B "${bin_path}" --socketdir="/var/run/postgresql"
echo "--------------------------------------"
echo "Running pg_upgrade command is complete"
echo "--------------------------------------"
Expand Down Expand Up @@ -572,9 +573,13 @@ _main() {
echo "Removing left over database files is complete"
echo "---------------------------------------------"

echo "**********************************************************"
echo "Automatic upgrade process finished with no errors reported"
echo "**********************************************************"
UPGRADE_PERFORMED=1

echo "***************************************************************************************"
echo "Automatic upgrade process finished upgrading the data format to PostgreSQL ${PGTARGET}."
echo "The database has not yet been reindexed nor updated the query planner stats. Those "
echo "will be done by a background task shortly. "
echo "***************************************************************************************"
fi

### The main pgautoupgrade scripting ends here ###
Expand All @@ -588,14 +593,32 @@ _main() {
sleep 5
done
else
if [ "x${PGAUTO_ONESHOT}" = "xyes" ]; then
echo "*****************************************************************************************************"
echo "'One shot' automatic upgrade was requested, so exiting now rather than starting the PostgreSQL server"
echo "*****************************************************************************************************"
else
# If the upgrade process ran, then we need to launch the post-upgrade script in the background while PG runs
if [ "${UPGRADE_PERFORMED}" -eq 1 ]; then
/usr/local/bin/pgautoupgrade-postupgrade.sh "${PGDATA}" "${PGAUTO_ONESHOT}" 2>&1 &
echo "****************************"
echo "Post upgrade script launched"
echo "****************************"

# Start PostgreSQL
exec "$@"
else
# If no upgrade was performed, then we start PostgreSQL as per normal as long as "one shot" mode wasn't requested
if [ "x${PGAUTO_ONESHOT}" = "xyes" ]; then
echo "***********************************************************************************"
echo "'One shot' automatic upgrade was requested, so exiting as there is no upgrade to do"
echo "If you're seeing this message and expecting an upgrade to be happening, it probably"
echo "means the container is being started in a loop and a previous run already did it :)"
echo "***********************************************************************************"
else
# Start PostgreSQL
exec "$@"
fi
fi
fi

# Run a sync before exiting, just to ensure everything is flushed to disk before docker terminates the process
sync
}

if ! _is_sourced; then
Expand Down
90 changes: 90 additions & 0 deletions pgautoupgrade-postupgrade.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env bash

set -e

if [ $# -ne 2 ]; then
echo "Required number of arguments not passed to post upgrade script. 2 expected, $# received"
exit 1
fi

PGDATA=$1
PGAUTO_ONESHOT=$2

# Wait for PostgreSQL to start and become available
COUNT=0
RUNNING=1
while [ $RUNNING -ne 0 ] && [ $COUNT -le 20 ]; do
# Check if PostgreSQL is running yet
echo "------ Checking if PostgreSQL is running, loop count ${COUNT} ------"
set +e
pg_isready -q
RUNNING=$?
set -e

if [ $RUNNING -eq 0 ]; then
echo "PostgreSQL is running. Post upgrade tasks will start shortly"
else
echo "PostgreSQL is not yet running, lets wait then try again..."
sleep 3
fi

COUNT=$((COUNT+1))
done

if [ $RUNNING -ne 0 ]; then
echo "PostgreSQL did not start before timeout expired"
exit 2
fi

# Get the list of databases in the database cluster
DB_LIST=$(echo 'SELECT datname FROM pg_catalog.pg_database WHERE datistemplate IS FALSE' | psql -1t --csv postgres)

# Update query planner statistics
echo "----------------------------"
echo "Updating query planner stats"
echo "----------------------------"

for DATABASE in ${DB_LIST}; do
echo "VACUUM (ANALYZE, VERBOSE, INDEX_CLEANUP FALSE)" | psql -t --csv "${DATABASE}"
done

echo "-------------------------------------"
echo "Finished updating query planner stats"
echo "-------------------------------------"

# Reindex the databases
echo "------------------------"
echo "Reindexing the databases"
echo "------------------------"

# For each database, reindex it
for DATABASE in ${DB_LIST}; do
echo "-------------------------------"
echo "Starting reindex of ${DATABASE}"
echo "-------------------------------"

echo 'REINDEX DATABASE CONCURRENTLY' | psql -t --csv "${DATABASE}"

echo "-------------------------------"
echo "Finished reindex of ${DATABASE}"
echo "-------------------------------"
done

echo "-------------------------------"
echo "End of reindexing the databases"
echo "-------------------------------"

# If "one shot" mode was requested, then shut down PostgreSQL
if [ "x${PGAUTO_ONESHOT}" = "xyes" ]; then
echo "****************************************************************************************************"
echo "'One shot' automatic upgrade was requested, so exiting now that the post upgrade tasks have finished"
echo "****************************************************************************************************"
pg_ctl stop -D "${PGDATA}"
else
echo "*************************************************************************************************"
echo "Post upgrade tasks have finished successfully. PostgreSQL should now be fully updated and online"
echo "*************************************************************************************************"
fi

# Run a sync before exiting, just to ensure everything is flushed to disk before docker terminates the process
sync
65 changes: 48 additions & 17 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ FAILURE=0
# Array of PostgreSQL versions for testing
PG_VERSIONS=(9.5 9.6 10 11 12 13 14 15 16 17)

# Useful output display
banner() {
set +x
CHAR=$1
MSG=$2
NUMSTARS=$((${#MSG}+1))
echo
for i in $(seq 2 "$NUMSTARS"); do printf "%s" "${CHAR}"; done; echo
echo "${MSG}"
for i in $(seq 2 "$NUMSTARS"); do printf "%s" "${CHAR}"; done; echo
echo
set -x
}

# Stop any existing containers from previous test runs
test_down() {
docker compose -f test/docker-compose-pgauto.yml down
Expand All @@ -31,21 +45,42 @@ test_run() {
# Verify the PostgreSQL data files are now the target version
PGVER=$(sudo cat postgres-data/PG_VERSION)
if [ "$PGVER" != "${TARGET}" ]; then
echo
echo "****************************************************************************"
echo "Automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} FAILED!"
echo "****************************************************************************"
echo
banner '*' "Standard automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} FAILED!"
FAILURE=1
else
echo
echo "*******************************************************************************"
echo "Automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} SUCCEEDED!"
echo "*******************************************************************************"
echo
banner '*' "Standard automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} SUCCEEDED!"
fi

# Shut down containers from previous test runs
# Shut down any containers that are still running
docker compose -f docker-compose-pgauto.yml down --remove-orphans

# Delete the upgraded PostgreSQL data directory
sudo rm -rf postgres-data

##
## Tests for one shot mode
##
banner '-' "Testing 'one shot' automatic upgrade mode for PostgreSQL ${VERSION} to ${TARGET}"

# Create the PostgreSQL database using a specific version of PostgreSQL
docker compose -f "docker-compose-pg${VERSION}.yml" run --rm server create_db

# Shut down all of the containers
docker compose -f "docker-compose-pg${VERSION}.yml" down --remove-orphans

# Run the PostgreSQL container in one shot mode
TARGET_TAG="${TARGET}-${FLAVOR}" docker compose -f docker-compose-pgauto.yml run --rm -e PGAUTO_ONESHOT=yes postgres

# Verify the PostgreSQL data files are now the target version
PGVER=$(sudo cat postgres-data/PG_VERSION)
if [ "$PGVER" != "${TARGET}" ]; then
banner '*' "'One shot' automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} FAILED!"
FAILURE=1
else
banner '*' "'One shot' automatic upgrade of PostgreSQL from version ${VERSION} to ${TARGET} SUCCEEDED!"
fi

# Shut down any containers that are still running
docker compose -f docker-compose-pgauto.yml down

# If running on CI, delete the Postgres Docker image to avoid space problems
Expand Down Expand Up @@ -76,12 +111,8 @@ done

# Check for failure
if [ "${FAILURE}" -ne 0 ]; then
echo
echo "FAILURE: Automatic upgrade of PostgreSQL failed in one of the tests. Please investigate."
echo
banner ' ' "FAILURE: Automatic upgrade of PostgreSQL failed in one of the tests. Please investigate."
exit 1
else
echo
echo "SUCCESS: Automatic upgrade testing of PostgreSQL to all versions up to $PGTARGET passed without issue."
echo
banner ' ' "SUCCESS: Automatic upgrade testing of PostgreSQL to all versions up to $PGTARGET passed without issue."
fi
1 change: 0 additions & 1 deletion test/docker-compose-pg10.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg11.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg12.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg13.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg14.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg15.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg16.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg9.5.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pg9.6.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down
1 change: 0 additions & 1 deletion test/docker-compose-pgauto.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "2.1"
x-redash-service: &redash-service
image: redash/redash:10.1.0.b50633
depends_on:
Expand Down

0 comments on commit 93c5fd8

Please sign in to comment.