diff --git a/CHANGELOG.md b/CHANGELOG.md index e626cc3..3d0d32e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- [#53] Fix race condition between startup script and post upgrade script ## [v14.17-2] - 2025-04-24 diff --git a/batsTests/post-upgrade.bats b/batsTests/post-upgrade.bats new file mode 100755 index 0000000..43f7415 --- /dev/null +++ b/batsTests/post-upgrade.bats @@ -0,0 +1,290 @@ +#! /bin/bash +# Bind an unbound BATS variables that fail all tests when combined with 'set -o nounset' +export BATS_TEST_START_TIME="0" +export BATSLIB_FILE_PATH_REM="" +export BATSLIB_FILE_PATH_ADD="" + +load '/workspace/target/bats_libs/bats-support/load.bash' +load '/workspace/target/bats_libs/bats-assert/load.bash' +load '/workspace/target/bats_libs/bats-mock/load.bash' +load '/workspace/target/bats_libs/bats-file/load.bash' + +setup() { + doguctl="$(mock_create)" + export doguctl + export PATH="${BATS_TMPDIR}:${PATH}" + mkdir ${BATS_TMPDIR}/postgresql_bats + export PGDATA="${BATS_TMPDIR}/postgresql_bats" + + ln -s "${doguctl}" "${BATS_TMPDIR}/doguctl" +} + +teardown() { + /bin/rm "${BATS_TMPDIR}/doguctl" + /bin/rm -r "${BATS_TMPDIR}/postgresql_bats" +} + +@test "versionXLessOrEqualThanY() should return true for versions less than or equal to another" { + source /workspace/resources/post-upgrade.sh + + run versionXLessOrEqualThanY "1.0.0-1" "1.0.0-1" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "1.0.0-2" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "1.1.0-2" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "1.0.2-2" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "1.0.0-2" + assert_success + run versionXLessOrEqualThanY "1.1.0-1" "1.1.0-2" + assert_success + run versionXLessOrEqualThanY "1.0.2-1" "1.0.2-2" + assert_success + run versionXLessOrEqualThanY "1.2.3-4" "1.2.3-4" + assert_success + run versionXLessOrEqualThanY "1.2.3-4" "1.2.3-5" + assert_success + + run versionXLessOrEqualThanY "1.0.0-1" "2.0.0-1" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "2.1.0-1" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "2.0.1-1" + assert_success + run versionXLessOrEqualThanY "1.0.0-1" "2.1.1-1" + assert_success + run versionXLessOrEqualThanY "5.1.3-1" "5.1.3-1" + assert_success +} + +@test "versionXLessOrEqualThanY() should return false for versions greater than another" { + source /workspace/resources/post-upgrade.sh + + run versionXLessOrEqualThanY "0.0.0-10" "0.0.0-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-1" "0.0.0-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-1" "0.0.9-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-1" "0.9.9-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-0" "0.9.9-9" + assert_failure + run versionXLessOrEqualThanY "1.1.0-1" "0.0.0-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-1" "0.0.9-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-1" "0.9.9-9" + assert_failure + run versionXLessOrEqualThanY "1.0.0-0" "0.9.9-9" + assert_failure + + run versionXLessOrEqualThanY "1.2.3-4" "0.1.2-3" + assert_failure + run versionXLessOrEqualThanY "1.2.3-5" "0.1.2-3" + assert_failure + + run versionXLessOrEqualThanY "2.0.0-1" "1.0.0-1" + assert_failure + run versionXLessOrEqualThanY "2.1.0-1" "1.0.0-1" + assert_failure + run versionXLessOrEqualThanY "2.0.1-1" "1.0.0-1" + assert_failure + run versionXLessOrEqualThanY "2.1.1-1" "1.0.0-1" + assert_failure +} + +@test "runPostUpgrade should exit early if no version change" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + startPostgresql() { + echo "startPostgresql is mocked" + } + + mock_set_output "${doguctl}" "true" 1 + mock_set_status "${doguctl}" 0 2 + run runPostUpgrade "1.0.0-1" "1.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "2" + assert_line "startPostgresql is mocked" + assert_line "FROM and TO versions are the same; Exiting..." +} + +@test "runPostUpgrade should also restrict stat visibility if no version change" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + startPostgresql() { + echo "startPostgresql is mocked" + } + restrictStatVisibility() { + echo "restrictStatVisibility is mocked" + } + + mock_set_output "${doguctl}" "false" 1 + mock_set_status "${doguctl}" 0 2 + run runPostUpgrade "1.0.0-1" "1.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "2" + assert_line "startPostgresql is mocked" + assert_line "Postgresql stats might be visible outside of their intended scope. Restricting stat visibility..." + assert_line "restrictStatVisibility is mocked" + assert_line "FROM and TO versions are the same; Exiting..." +} + +@test "runPostUpgrade should reindexAllDatabases on version upgrade" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + startPostgresql() { + echo "startPostgresql is mocked" + } + reindexAllDatabases() { + echo "reindexAllDatabases is mocked" + } + versionXLessOrEqualThanY() { + echo "versionXLessOrEqualThanY is mocked" + return 0 + } + killPostgresql() { + echo "killPostgresql is mocked" + } + + mock_set_output "${doguctl}" "true" 1 + mock_set_output "${doguctl}" "true" 2 + mock_set_status "${doguctl}" 0 3 + run runPostUpgrade "1.0.0-1" "2.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "3" + assert_line "startPostgresql is mocked" + assert_line "Postgresql version changed. Reindexing all databases..." + assert_line "reindexAllDatabases is mocked" + assert_line "versionXLessOrEqualThanY is mocked" + assert_line "killPostgresql is mocked" +} + +@test "runPostUpgrade should restrict stats visibility if not already restricted" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + startPostgresql() { + echo "startPostgresql is mocked" + } + restrictStatVisibility() { + echo "restrictStatVisibility is mocked" + } + reindexAllDatabases() { + echo "reindexAllDatabases is mocked" + } + versionXLessOrEqualThanY() { + echo "versionXLessOrEqualThanY is mocked" + return 0 + } + killPostgresql() { + echo "killPostgresql is mocked" + } + + # stats not yet restricted + mock_set_output "${doguctl}" "false" 1 + mock_set_output "${doguctl}" "true" 2 + mock_set_status "${doguctl}" 0 3 + run runPostUpgrade "1.0.0-1" "2.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "3" + assert_line "startPostgresql is mocked" + assert_line "Postgresql stats might be visible outside of their intended scope. Restricting stat visibility..." + assert_line "restrictStatVisibility is mocked" + assert_line "reindexAllDatabases is mocked" + assert_line "versionXLessOrEqualThanY is mocked" + assert_line "killPostgresql is mocked" +} + +@test "runPostUpgrade should restore db dump if dump file exists" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + prepareForBackup() { + echo "prepareForBackup is mocked" + isBackupAvailable=true + } + startPostgresql() { + echo "startPostgresql is mocked" + } + restoreBackup() { + echo "restoreBackup is mocked" + } + reindexAllDatabases() { + echo "reindexAllDatabases is mocked" + } + versionXLessOrEqualThanY() { + echo "versionXLessOrEqualThanY is mocked" + return 0 + } + killPostgresql() { + echo "killPostgresql is mocked" + } + + tmpfile="${PGDATA}/postgresqlFullBackup.dump" + touch "$tmpfile" # Create the file + + + # stats not yet restricted + mock_set_output "${doguctl}" "true" 1 + mock_set_output "${doguctl}" "true" 2 + mock_set_status "${doguctl}" 0 3 + run runPostUpgrade "1.0.0-1" "2.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "3" + assert_line "prepareForBackup is mocked" + assert_line "startPostgresql is mocked" + assert_line "restoreBackup is mocked" + assert_line "reindexAllDatabases is mocked" + assert_line "versionXLessOrEqualThanY is mocked" + assert_line "killPostgresql is mocked" + + # Cleanup: Remove the file + rm "$tmpfile" +} + +@test "runPostUpgrade should migrateConstraintsOnPartitionedTables if not yet migrated" { + source /workspace/resources/post-upgrade.sh + + # Mock the functions + startPostgresql() { + echo "startPostgresql is mocked" + } + reindexAllDatabases() { + echo "reindexAllDatabases is mocked" + } + versionXLessOrEqualThanY() { + echo "versionXLessOrEqualThanY is mocked" + return 0 + } + migrateConstraintsOnPartitionedTables() { + echo "migrateConstraintsOnPartitionedTables is mocked" + } + killPostgresql() { + echo "killPostgresql is mocked" + } + + mock_set_output "${doguctl}" "true" 1 + mock_set_output "${doguctl}" "false" 2 + mock_set_status "${doguctl}" 0 3 + run runPostUpgrade "1.0.0-1" "2.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${doguctl}")" "3" + assert_line "startPostgresql is mocked" + assert_line "Postgresql version changed. Reindexing all databases..." + assert_line "reindexAllDatabases is mocked" + assert_line "versionXLessOrEqualThanY is mocked" + assert_line "migrateConstraintsOnPartitionedTables is mocked" + assert_line "killPostgresql is mocked" +} diff --git a/batsTests/pre-upgrade.bats b/batsTests/pre-upgrade.bats new file mode 100755 index 0000000..3261a60 --- /dev/null +++ b/batsTests/pre-upgrade.bats @@ -0,0 +1,64 @@ +#! /bin/bash +# Bind an unbound BATS variables that fail all tests when combined with 'set -o nounset' +export BATS_TEST_START_TIME="0" +export BATSLIB_FILE_PATH_REM="" +export BATSLIB_FILE_PATH_ADD="" + +load '/workspace/target/bats_libs/bats-support/load.bash' +load '/workspace/target/bats_libs/bats-assert/load.bash' +load '/workspace/target/bats_libs/bats-mock/load.bash' +load '/workspace/target/bats_libs/bats-file/load.bash' + +setup() { + pg_dumpall="$(mock_create)" + doguctl="$(mock_create)" + export pg_dumpall + export doguctl + export PATH="${BATS_TMPDIR}:${PATH}" + export PGDATA="/var/lib/postgresql" + ln -s "${pg_dumpall}" "${BATS_TMPDIR}/pg_dumpall" + ln -s "${doguctl}" "${BATS_TMPDIR}/doguctl" +} + +teardown() { + rm "${BATS_TMPDIR}/pg_dumpall" + rm "${BATS_TMPDIR}/doguctl" +} + +@test "runPreUpgrade should do nothing on equal versions" { + source /workspace/resources/pre-upgrade.sh + + run runPreUpgrade "1.0.0-1" "1.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${pg_dumpall}")" "0" + assert_equal "$(mock_get_call_num "${doguctl}")" "0" + assert_line 'FROM and TO versions are the same; Exiting...' +} + +@test "runPreUpgrade should just set local_state on minor upgrade" { + source /workspace/resources/pre-upgrade.sh + mock_set_status "${doguctl}" 0 + + run runPreUpgrade "1.0.0-1" "1.1.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${pg_dumpall}")" "0" + assert_equal "$(mock_get_call_num "${doguctl}")" "1" + assert_line 'Set registry flag so startup script waits for post-upgrade to finish...' +} + +@test "runPreUpgrade should set local_state and save dump on major upgrade" { + source /workspace/resources/pre-upgrade.sh + mock_set_status "${doguctl}" 0 + mock_set_status "${pg_dumpall}" 0 + + run runPreUpgrade "1.0.0-1" "2.0.0-1" + + assert_success + assert_equal "$(mock_get_call_num "${pg_dumpall}")" "1" + assert_equal "$(mock_get_call_num "${doguctl}")" "1" + assert_line "Dumping database to /var/lib/postgresql/postgresqlFullBackup.dump..." + assert_line "Finished dumping database" + assert_line 'Set registry flag so startup script waits for post-upgrade to finish...' +} diff --git a/resources/post-upgrade.sh b/resources/post-upgrade.sh index cee6695..84402e4 100755 --- a/resources/post-upgrade.sh +++ b/resources/post-upgrade.sh @@ -3,8 +3,71 @@ set -o errexit set -o nounset set -o pipefail -FROM_VERSION="${1}" -TO_VERSION="${2}" +# shellcheck disable=SC1091 +source "$(dirname "${BASH_SOURCE[0]}")/util.sh" + +function prepareForBackup() { + isBackupAvailable=true + # Moving backup and emptying PGDATA directory + mv "${PGDATA}"/postgresqlFullBackup.dump /tmp/postgresqlFullBackup.dump + + # New PostgreSQL version requires completely empty folder + rm -rf "${PGDATA:?}"/.??* + rm -rf "${PGDATA:?}"/* + + initializePostgreSQL +} + +function startPostgresql() { + echo "start postgresql" + gosu postgres postgres & + PID=$! + + while ! pg_isready >/dev/null; do + # Postgres is not ready yet to accept connections + sleep 0.1 + done +} + +function restoreBackup() { + echo "Restoring database dump..." + psql -U postgres -f /tmp/postgresqlFullBackup.dump postgres + rm /tmp/postgresqlFullBackup.dump + echo "Restoring database dump...complete!" +} + +# see https://www.postgresql.org/docs/14/release-14-12.html#:~:text=Restrict%20visibility%20of,WITH%20ALLOW_CONNECTIONS%20false%3B for more information +function restrictStatVisibility() { + if [ ! -f /usr/share/postgresql/fix-CVE-2024-4317.sql ]; then + return 0 + fi + + while ! pg_isready >/dev/null; do + # Postgres is not ready yet to accept connections + sleep 0.1 + done + # temporarily accept connections on template0 + psql -U postgres -c "ALTER DATABASE template0 WITH ALLOW_CONNECTIONS true;" + + # get all tables + psql -U postgres -c "SELECT d.datname as \"Name\" FROM pg_catalog.pg_database d;" -X > databases + # there are four lines of sql result information (two at the start, two at the end) + for i in $(seq 3 $(($(wc -l < databases) - 2 ))); do + DATABASE_NAME=$(sed "${i}!d" databases | xargs) + psql -U postgres -d "${DATABASE_NAME}" -c "\i /usr/share/postgresql/fix-CVE-2024-4317.sql" + done + # disable connections on template0 + psql -U postgres -c "ALTER DATABASE template0 WITH ALLOW_CONNECTIONS false;" + doguctl config restricted_stat_visibility true +} + +function reindexAllDatabases() { + while ! pg_isready >/dev/null; do + # Postgres is not ready yet to accept connections + sleep 0.1 + done + reindexdb -U postgres --verbose --all +} # versionXLessOrEqualThanY returns true if X is less than or equal to Y; otherwise false function versionXLessOrEqualThanY() { @@ -114,58 +177,63 @@ function migrateConstraintsOnPartitionedTables() { doguctl config migrated_database_constraints true } -# see https://www.postgresql.org/docs/14/release-14-12.html#:~:text=Restrict%20visibility%20of,WITH%20ALLOW_CONNECTIONS%20false%3B for more information -function restrictStatVisibility() { - if [ ! -f /usr/share/postgresql/fix-CVE-2024-4317.sql ]; then - return 0 - fi +function killPostgresql() { + # Kill postgres + pkill -P ${PID} + kill ${PID} - while ! pg_isready >/dev/null; do - # Postgres is not ready yet to accept connections - sleep 0.1 + while pgrep -x postgres >/dev/null; do + # Postgres is still running + sleep 0.1 done - # temporarily accept connections on template0 - psql -U postgres -c "ALTER DATABASE template0 WITH ALLOW_CONNECTIONS true;" + echo "postgresql successfully killed (this is expected during post upgrade)" +} - # get all tables - psql -U postgres -c "SELECT d.datname as \"Name\" FROM pg_catalog.pg_database d;" -X > databases - # there are four lines of sql result information (two at the start, two at the end) - for i in $(seq 3 $(($(wc -l < databases) - 2 ))); do - DATABASE_NAME=$(sed "${i}!d" databases | xargs) - psql -U postgres -d "${DATABASE_NAME}" -c "\i /usr/share/postgresql/fix-CVE-2024-4317.sql" - done +function runPostUpgrade() { + FROM_VERSION="${1}" + TO_VERSION="${2}" - # disable connections on template0 - psql -U postgres -c "ALTER DATABASE template0 WITH ALLOW_CONNECTIONS false;" + isBackupAvailable=false + if [ -e "${PGDATA}"/postgresqlFullBackup.dump ]; then + prepareForBackup + fi - doguctl config restricted_stat_visibility true -} + startPostgresql -function reindexAllDatabases() { - while ! pg_isready >/dev/null; do - # Postgres is not ready yet to accept connections - sleep 0.1 - done - reindexdb -U postgres --verbose --all -} + if [ "${isBackupAvailable}" = "true" ]; then + restoreBackup + fi -if [[ $(doguctl config --default "false" restricted_stat_visibility) != "true" ]] ; then - # Postgres 14.12 (Dogu Version 14.15-2) fixed an issue with the visibility of hidden statistics - # since this fix comes after the version was released, always execute it if it was not executed before - echo "Postgresql stats might be visible outside of their intended scope. Restricting stat visibility..." - restrictStatVisibility -fi + if [[ $(doguctl config --default "false" restricted_stat_visibility) != "true" ]] ; then + # Postgres 14.12 (Dogu Version 14.15-2) fixed an issue with the visibility of hidden statistics + # since this fix comes after the version was released, always execute it if it was not executed before + echo "Postgresql stats might be visible outside of their intended scope. Restricting stat visibility..." + restrictStatVisibility + fi + if [ "${FROM_VERSION}" = "${TO_VERSION}" ]; then + echo "FROM and TO versions are the same; Exiting..." + doguctl config --rm "local_state" + exit 0 + else + echo "Postgresql version changed. Reindexing all databases..." + reindexAllDatabases + fi -if [ "${FROM_VERSION}" = "${TO_VERSION}" ]; then - echo "FROM and TO versions are the same; Exiting..." - exit 0 -else - echo "Postgresql version changed. Reindexing all databases..." - reindexAllDatabases -fi + if versionXLessOrEqualThanY "0.14.15-1" "0.${TO_VERSION}" && [[ $(doguctl config --default "false" migrated_database_constraints) != "true" ]] ; then + # Postgres 14.14 (Dogu Version 14.15.x) fixed an issue with constraints on partitioned tables + # If any partitioned tables have constraints on them, this migration removes and readds them + migrateConstraintsOnPartitionedTables + fi + + killPostgresql + + echo "Removing local_state registry flag so startup script can start afterwards..." + doguctl config --rm "local_state" + + echo "Postgresql post-upgrade done" +} -if versionXLessOrEqualThanY "0.14.15-1" "0.${TO_VERSION}" && [[ $(doguctl config --default "false" migrated_database_constraints) != "true" ]] ; then - # Postgres 14.14 (Dogu Version 14.15.x) fixed an issue with constraints on partitioned tables - # If any partitioned tables have constraints on them, this migration removes and readds them - migrateConstraintsOnPartitionedTables +# make the script only run when executed, not when sourced from bats tests +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + runPostUpgrade "$@" fi diff --git a/resources/pre-upgrade.sh b/resources/pre-upgrade.sh index caffd44..3dadfe3 100755 --- a/resources/pre-upgrade.sh +++ b/resources/pre-upgrade.sh @@ -3,14 +3,29 @@ set -o errexit set -o nounset set -o pipefail -FROM_VERSION="${1}" -TO_VERSION="${2}" -FROM_MAJOR_VERSION=$(echo "${FROM_VERSION}" | cut -d '.' -f1) -TO_MAJOR_VERSION=$(echo "${TO_VERSION}" | cut -d '.' -f1) +function runPreUpgrade() { + FROM_VERSION="${1}" + TO_VERSION="${2}" + FROM_MAJOR_VERSION=$(echo "${FROM_VERSION}" | cut -d '.' -f1) + TO_MAJOR_VERSION=$(echo "${TO_VERSION}" | cut -d '.' -f1) -# dump database if TO_MAJOR_VERSION is higher than FROM_MAJOR_VERSION -if [[ "${TO_MAJOR_VERSION}" -gt "${FROM_MAJOR_VERSION}" ]]; then - echo "Dumping database to ${PGDATA}/postgresqlFullBackup.dump..." - pg_dumpall -U postgres -f "${PGDATA}"/postgresqlFullBackup.dump - echo "Finished dumping database" + # dump database if TO_MAJOR_VERSION is higher than FROM_MAJOR_VERSION + if [[ "${TO_MAJOR_VERSION}" -gt "${FROM_MAJOR_VERSION}" ]]; then + echo "Dumping database to ${PGDATA}/postgresqlFullBackup.dump..." + pg_dumpall -U postgres -f "${PGDATA}"/postgresqlFullBackup.dump + echo "Finished dumping database" + fi + + if [ "${FROM_VERSION}" = "${TO_VERSION}" ]; then + echo "FROM and TO versions are the same; Exiting..." + exit 0 + fi + + echo "Set registry flag so startup script waits for post-upgrade to finish..." + doguctl config "local_state" "upgrading" +} + +# make the script only run when executed, not when sourced from bats tests +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + runPreUpgrade "$@" fi diff --git a/resources/startup.sh b/resources/startup.sh index ce82657..bdf6526 100755 --- a/resources/startup.sh +++ b/resources/startup.sh @@ -3,6 +3,9 @@ set -o errexit set -o nounset set -o pipefail +# shellcheck disable=SC1091 +source "$(dirname "${BASH_SOURCE[0]}")/util.sh" + function mask2cidr() { local storedIFS="${IFS}" NBITS=0 @@ -77,32 +80,6 @@ function write_pg_hba_conf() { create_hba >"${PGDATA}"/pg_hba.conf } -function initializePostgreSQL() { - # set stage for health check - doguctl state installing - - # install database - gosu postgres initdb - - # postgres user - POSTGRES_USER="postgres" - - # store the user - doguctl config user "${POSTGRES_USER}" - - # create random password - POSTGRES_PASSWORD=$(doguctl random) - - # store the password encrypted - doguctl config -e password "${POSTGRES_PASSWORD}" - - # open port - sed -ri "s/^#(listen_addresses\s*=\s*)\S+/\1'*'/" "$PGDATA"/postgresql.conf - - # set generated password - echo "ALTER USER ${POSTGRES_USER} WITH SUPERUSER PASSWORD '${POSTGRES_PASSWORD}';" | gosu 2>/dev/null 1>&2 postgres postgres --single -jE -} - function waitForPostgreSQLStartup() { while ! pg_isready >/dev/null; do # Postgres is not ready yet to accept connections @@ -149,38 +126,17 @@ function runMain() { mkdir -p /run/postgresql chown postgres:postgres /run/postgresql - if [ -z "$(ls -A "$PGDATA")" ]; then - initializePostgreSQL - write_pg_hba_conf - elif [ -e "${PGDATA}"/postgresqlFullBackup.dump ]; then - # Moving backup and emptying PGDATA directory - mv "${PGDATA}"/postgresqlFullBackup.dump /tmp/postgresqlFullBackup.dump - # New PostgreSQL version requires completely empty folder - - rm -rf "${PGDATA:?}"/.??* - rm -rf "${PGDATA:?}"/* + # check whether post-upgrade script is still running + while [[ "$(doguctl config "local_state" -d "empty")" == "upgrading" ]]; do + echo "Upgrade script is running. Waiting..." + sleep 3 + done + if [ -z "$(ls -A "$PGDATA")" ]; then initializePostgreSQL - - echo "Restoring database dump..." - # Start postgres to restore backup - gosu postgres postgres & - PID=$! - waitForPostgreSQLStartup - # Restore backup - psql -U postgres -f /tmp/postgresqlFullBackup.dump postgres - rm /tmp/postgresqlFullBackup.dump - # Kill postgres - pkill -P ${PID} - kill ${PID} - waitForPostgreSQLShutdown - echo "Database dump successfully restored" - - write_pg_hba_conf - else - write_pg_hba_conf fi + write_pg_hba_conf setDoguLogLevel # set stage for health check diff --git a/resources/util.sh b/resources/util.sh new file mode 100644 index 0000000..10e83c5 --- /dev/null +++ b/resources/util.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail + + +function initializePostgreSQL() { + # set stage for health check + doguctl state installing + + # install database + gosu postgres initdb + + # postgres user + POSTGRES_USER="postgres" + + # store the user + doguctl config user "${POSTGRES_USER}" + + # create random password + POSTGRES_PASSWORD=$(doguctl random) + + # store the password encrypted + doguctl config -e password "${POSTGRES_PASSWORD}" + + # open port + sed -ri "s/^#(listen_addresses\s*=\s*)\S+/\1'*'/" "$PGDATA"/postgresql.conf + + # set generated password + echo "ALTER USER ${POSTGRES_USER} WITH SUPERUSER PASSWORD '${POSTGRES_PASSWORD}';" | gosu 2>/dev/null 1>&2 postgres postgres --single -jE +} \ No newline at end of file