@@ -195,7 +195,9 @@ cleanup_docker() {
195195 docker rm " $CONTAINER " 2> /dev/null || true
196196
197197 echo " Removing volumes..."
198- docker volume rm pgdata pgrepo 2> /dev/null || true
198+ docker volume rm -f pgdata pgrepo 2> /dev/null || true
199+ # Wait a moment to ensure volumes are fully removed
200+ sleep 1
199201
200202 # Check and free up port 5433 if in use
201203 if lsof -ti:5433 > /dev/null 2>&1 ; then
@@ -629,6 +631,25 @@ test_azure_blob() {
629631 echo " "
630632 print_success " PostgreSQL is ready (took ${ELAPSED} s)"
631633
634+ # Check if PostgreSQL is in recovery mode and promote if needed
635+ RECOVERY_STATUS=$( docker exec " $CONTAINER " psql -U postgres -d postgres -t -c " SELECT pg_is_in_recovery();" 2> /dev/null | xargs || echo " t" )
636+ if [ " $RECOVERY_STATUS " = " t" ]; then
637+ print_warning " PostgreSQL is in recovery mode, promoting..."
638+ docker exec " $CONTAINER " psql -U postgres -d postgres -c " SELECT pg_wal_replay_resume();" > /dev/null 2>&1 || true
639+ sleep 2
640+ # Wait for PostgreSQL to be ready again after promotion
641+ ELAPSED=0
642+ until docker exec " $CONTAINER " pg_isready -U postgres > /dev/null 2>&1 ; do
643+ if [ $ELAPSED -ge 30 ]; then
644+ print_error " PostgreSQL failed to start after promotion"
645+ return 1
646+ fi
647+ sleep 1
648+ ELAPSED=$(( ELAPSED + 1 ))
649+ done
650+ print_success " PostgreSQL promoted successfully"
651+ fi
652+
632653 # Create test data (this will also download Northwind if needed)
633654 create_test_data " $CONTAINER "
634655
@@ -672,6 +693,170 @@ test_azure_blob() {
672693 # Clean local backups
673694 docker exec " $CONTAINER " rm -rf /var/lib/pgbackrest/archive/* /var/lib/pgbackrest/backup/* 2> /dev/null || true
674695
696+ # Debug: Check PostgreSQL data directory and pgBackRest config
697+ print_header " Debug: Check PostgreSQL Paths"
698+ echo " PGDATA environment:"
699+ docker exec " $CONTAINER " bash -c ' echo "PGDATA=$PGDATA"'
700+ echo " "
701+ echo " PostgreSQL data directory locations:"
702+ docker exec " $CONTAINER " bash -c ' ls -la /var/lib/postgresql/ 2>/dev/null || echo "Cannot list /var/lib/postgresql"'
703+ echo " "
704+ echo " pgBackRest config pg1-path:"
705+ docker exec " $CONTAINER " bash -c ' grep "pg1-path" /etc/pgbackrest/pgbackrest.conf || echo "pg1-path not found in config"'
706+ echo " "
707+ echo " Actual PostgreSQL data directory (from postgres process):"
708+ ACTUAL_DATA_DIR=$( docker exec " $CONTAINER " bash -c ' psql -U postgres -d postgres -t -c "SHOW data_directory;" 2>/dev/null | xargs' || echo " " )
709+ if [ -n " $ACTUAL_DATA_DIR " ]; then
710+ echo " Found data directory: $ACTUAL_DATA_DIR "
711+ echo " "
712+ echo " Updating pgBackRest config with correct path..."
713+ # Remove old pg1-path and add new one with correct directory
714+ # Use /tmp for temp file and Python to avoid all permission issues
715+ docker exec -e DATA_DIR=" $ACTUAL_DATA_DIR " " $CONTAINER " bash -c " python3 <<'PYEOF'
716+ import sys
717+ import os
718+
719+ data_dir = os.environ['DATA_DIR']
720+ config_file = '/etc/pgbackrest/pgbackrest.conf'
721+ tmp_file = '/tmp/pgbackrest.conf.tmp'
722+
723+ # Read current config
724+ with open(config_file, 'r') as f:
725+ lines = f.readlines()
726+
727+ # Process lines: remove old pg1-path, add new one after [demo]
728+ output = []
729+ in_demo = False
730+ pg1_added = False
731+
732+ for line in lines:
733+ stripped = line.strip()
734+
735+ # Track when we enter [demo] section
736+ if stripped == '[demo]':
737+ in_demo = True
738+ output.append(line)
739+ continue
740+
741+ # Track when we leave [demo] section
742+ if stripped.startswith('[') and stripped != '[demo]':
743+ if in_demo and not pg1_added:
744+ output.append('pg1-path=' + data_dir + '\n')
745+ pg1_added = True
746+ in_demo = False
747+ output.append(line)
748+ continue
749+
750+ # Skip old pg1-path lines
751+ if stripped.startswith('pg1-path='):
752+ continue
753+
754+ # Add pg1-path after [demo] when we hit first empty line or end
755+ if in_demo and not pg1_added and (stripped == '' or lines.index(line) == len(lines) - 1):
756+ output.append('pg1-path=' + data_dir + '\n')
757+ pg1_added = True
758+
759+ output.append(line)
760+
761+ # If [demo] section exists but pg1-path was never added
762+ if in_demo and not pg1_added:
763+ output.append('pg1-path=' + data_dir + '\n')
764+
765+ # If [demo] section doesn't exist, add it
766+ if '[demo]' not in ''.join(output):
767+ output.append('\n[demo]\n')
768+ output.append('pg1-path=' + data_dir + '\n')
769+
770+ # Write to temp file
771+ with open(tmp_file, 'w') as f:
772+ f.writelines(output)
773+
774+ # Copy back and set permissions
775+ import shutil
776+ import pwd
777+ import grp
778+
779+ shutil.copy(tmp_file, config_file)
780+ postgres_uid = pwd.getpwnam('postgres').pw_uid
781+ postgres_gid = grp.getgrnam('postgres').gr_gid
782+ os.chown(config_file, postgres_uid, postgres_gid)
783+ os.chmod(config_file, 0o640)
784+ os.remove(tmp_file)
785+ PYEOF
786+ "
787+ echo " Updated config:"
788+ docker exec " $CONTAINER " bash -c ' grep "pg1-path" /etc/pgbackrest/pgbackrest.conf'
789+ else
790+ print_warning " Could not determine PostgreSQL data directory, using default"
791+ fi
792+ echo " "
793+
794+ # Verify repo2 is configured
795+ print_header " Verify Azure (repo2) Configuration"
796+ if ! docker exec " $CONTAINER " grep -q " repo2-type=azure" /etc/pgbackrest/pgbackrest.conf; then
797+ echo " repo2 not found in config, running configure-azure.sh..."
798+ docker exec " $CONTAINER " bash -lc " /usr/local/bin/configure-azure.sh" || echo " configure-azure.sh returned error, will configure manually"
799+
800+ # Check if it worked
801+ if ! docker exec " $CONTAINER " grep -q " repo2-type=azure" /etc/pgbackrest/pgbackrest.conf; then
802+ echo " configure-azure.sh didn't add repo2, configuring manually..."
803+ docker exec -e AZURE_ACCOUNT=" $AZURE_ACCOUNT " -e AZURE_CONTAINER=" $AZURE_CONTAINER " -e AZURE_KEY_TYPE=" $AZURE_KEY_TYPE " -e AZURE_REPO_PATH=" $AZURE_REPO_PATH " " $CONTAINER " bash -c "
804+ AZURE_REPO_PATH=\$ {AZURE_REPO_PATH:-/demo-repo}
805+ TMP_FILE=/tmp/pgbackrest_repo2.$$
806+ cat /etc/pgbackrest/pgbackrest.conf > \$ TMP_FILE
807+ echo '' >> \$ TMP_FILE
808+ echo 'repo2-type=azure' >> \$ TMP_FILE
809+ echo \" repo2-azure-account=\$ {AZURE_ACCOUNT}\" >> \$ TMP_FILE
810+ echo \" repo2-azure-container=\$ {AZURE_CONTAINER}\" >> \$ TMP_FILE
811+ echo \" repo2-azure-key-type=\$ {AZURE_KEY_TYPE}\" >> \$ TMP_FILE
812+ echo \" repo2-azure-key=\$ {AZURE_KEY}\" >> \$ TMP_FILE
813+ echo \" repo2-path=\$ {AZURE_REPO_PATH}\" >> \$ TMP_FILE
814+ echo 'repo2-retention-full=4' >> \$ TMP_FILE
815+ cp \$ TMP_FILE /etc/pgbackrest/pgbackrest.conf
816+ chown postgres:postgres /etc/pgbackrest/pgbackrest.conf
817+ chmod 640 /etc/pgbackrest/pgbackrest.conf
818+ rm -f \$ TMP_FILE
819+ "
820+ fi
821+ echo " Config after configuration:"
822+ docker exec " $CONTAINER " grep -E " repo2|azure" /etc/pgbackrest/pgbackrest.conf || echo " No repo2 config found"
823+ else
824+ echo " repo2 configuration found:"
825+ docker exec " $CONTAINER " grep -E " repo2|azure" /etc/pgbackrest/pgbackrest.conf
826+ fi
827+ echo " "
828+
829+ # Ensure archiving is enabled before backups
830+ print_header " Ensure PostgreSQL Archiving Enabled"
831+ ARCHIVE_MODE=$( docker exec " $CONTAINER " psql -U postgres -At -c " show archive_mode" )
832+
833+ if [ " $ARCHIVE_MODE " != " on" ]; then
834+ echo " archive_mode is currently $ARCHIVE_MODE - enabling..."
835+ docker exec " $CONTAINER " bash -lc '
836+ set -e
837+ PGDATA_DIR=${PGDATA:-/var/lib/postgresql/data}
838+ {
839+ echo ""
840+ echo "# pgBackRest archiving configuration"
841+ echo "archive_mode = on"
842+ echo "archive_command = ' \' ' pgbackrest --stanza=demo archive-push %p' \' ' "
843+ echo "archive_timeout = 60"
844+ echo "wal_level = replica"
845+ echo "max_wal_senders = 3"
846+ echo "max_replication_slots = 3"
847+ } >> "$PGDATA_DIR/postgresql.conf"
848+ '
849+
850+ docker restart " $CONTAINER " > /dev/null
851+ echo " Waiting for PostgreSQL to restart with archiving enabled..."
852+ until docker exec " $CONTAINER " pg_isready -U postgres > /dev/null 2>&1 ; do
853+ sleep 1
854+ done
855+ else
856+ echo " archive_mode already enabled"
857+ fi
858+ echo " "
859+
675860 # Create stanza
676861 print_header " Create Stanza (Azure Blob Storage)"
677862 docker exec " $CONTAINER " pgbackrest --stanza=demo stanza-create
@@ -727,10 +912,27 @@ test_azure_blob() {
727912 -v pgrepo:/var/lib/pgbackrest \
728913 " $IMAGE " \
729914 -lc " /usr/local/bin/configure-azure.sh || true; \
915+ if ! grep -q \" repo2-type=azure\" /etc/pgbackrest/pgbackrest.conf; then \
916+ AZURE_REPO_PATH=\$ {AZURE_REPO_PATH:-/demo-repo}; \
917+ TMP_FILE=/tmp/pgbackrest_repo2.\$\$ ; \
918+ cat /etc/pgbackrest/pgbackrest.conf > \$ TMP_FILE; \
919+ echo '' >> \$ TMP_FILE; \
920+ echo 'repo2-type=azure' >> \$ TMP_FILE; \
921+ echo \" repo2-azure-account=\$ {AZURE_ACCOUNT}\" >> \$ TMP_FILE; \
922+ echo \" repo2-azure-container=\$ {AZURE_CONTAINER}\" >> \$ TMP_FILE; \
923+ echo \" repo2-azure-key-type=\$ {AZURE_KEY_TYPE}\" >> \$ TMP_FILE; \
924+ echo \" repo2-azure-key=\$ {AZURE_KEY}\" >> \$ TMP_FILE; \
925+ echo \" repo2-path=\$ {AZURE_REPO_PATH}\" >> \$ TMP_FILE; \
926+ echo 'repo2-retention-full=4' >> \$ TMP_FILE; \
927+ cp \$ TMP_FILE /etc/pgbackrest/pgbackrest.conf; \
928+ chown postgres:postgres /etc/pgbackrest/pgbackrest.conf; \
929+ chmod 640 /etc/pgbackrest/pgbackrest.conf; \
930+ rm -f \$ TMP_FILE; \
931+ fi; \
730932 DATA_DIR=\$ {ACTUAL_DATA_DIR:-/var/lib/postgresql/data}; \
731933 echo \" Restoring to data directory: \$ DATA_DIR\" ; \
732934 rm -rf \"\$ DATA_DIR\" /* && \
733- pgbackrest --stanza=demo restore --set='$BACKUP_LABEL_AZURE ' --type=immediate --pg1-path=\"\$ DATA_DIR\" "
935+ pgbackrest --repo=2 -- stanza=demo restore --set='$BACKUP_LABEL_AZURE ' --type=immediate --pg1-path=\"\$ DATA_DIR\" "
734936
735937 print_success " Restore complete"
736938
0 commit comments