Skip to content

Commit

Permalink
fix issue with multiple db creation and add test for this (#443)
Browse files Browse the repository at this point in the history
* fix issue with multiple db creation and add test for this
  • Loading branch information
NyakudyaA authored Aug 31, 2023
1 parent 80b4b71 commit 74bb497
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 18 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-latest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
- extensions
- logical_replication
- init_scripts
- multiple_databases
include:
- distro: debian
imageVersion: bookworm
Expand Down
50 changes: 50 additions & 0 deletions scenario_tests/multiple_databases/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

version: '2.1'

volumes:
pg-db-data-dir:
pg-db-schema-dir:


services:
pg-database:
image: 'kartoza/postgis:${TAG:-manual-build}'
restart: 'always'
# You can optionally mount to volume, to play with the persistence and
# observe how the node will behave after restarts.
volumes:
- pg-db-data-dir:/var/lib/postgresql
- ./tests:/tests
- ../utils:/lib/utils
environment:
POSTGRES_DB: 'gis,data'
POSTGRES_PASS: 'docker'
ALL_DATABASES: TRUE
SCHEMA_NAME: demo
healthcheck:
interval: 60s
timeout: 30s
retries: 3
test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker -d gis"

pg-schema:
image: 'kartoza/postgis:${TAG:-manual-build}'
restart: 'always'
# You can optionally mount to volume, to play with the persistence and
# observe how the node will behave after restarts.
volumes:
- pg-db-schema-dir:/var/lib/postgresql
- ./tests:/tests
- ../utils:/lib/utils
environment:
POSTGRES_DB: 'gis,data'
POSTGRES_PASS: 'docker'
ALL_DATABASES: FALSE
SCHEMA_NAME: demo
healthcheck:
interval: 60s
timeout: 30s
retries: 3
test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker -d gis"


53 changes: 53 additions & 0 deletions scenario_tests/multiple_databases/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash

# exit immediately if test fails
set -e

source ../test-env.sh
if [[ $(dpkg -l | grep "docker-compose") > /dev/null ]];then
VERSION='docker-compose'
else
VERSION='docker compose'
fi


# Run service as root
${VERSION} up -d pg-database

if [[ -n "${PRINT_TEST_LOGS}" ]]; then
${VERSION} logs -f &
fi

sleep 30

# Preparing all databases and all schemas
until ${VERSION} exec -T pg-database pg_isready; do
sleep 1
done;

# Execute tests
${VERSION} exec -T pg-database /bin/bash /tests/test_schemas.sh


${VERSION} down -v


# Run service for pg-schema
${VERSION} up -d pg-schema

if [[ -n "${PRINT_TEST_LOGS}" ]]; then
${VERSION} logs -f &
fi

sleep 30

# Preparing all databases and single schema
until ${VERSION} exec -T pg-schema pg_isready; do
sleep 1
done;

# Execute tests
${VERSION} exec -T pg-schema /bin/bash /tests/test_schemas.sh


${VERSION} down -v
Empty file.
50 changes: 50 additions & 0 deletions scenario_tests/multiple_databases/tests/test_schema_existence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import unittest
import psycopg2
import os


class TestSchemaExistence(unittest.TestCase):

def setUp(self):
self.db_host = os.environ.get('POSTGRES_HOST', 'localhost')
self.db_port = os.environ.get('POSTGRES_PORT', '5432')
self.db_user = os.environ.get('POSTGRES_USER', 'docker')
self.db_pass = os.environ.get('POSTGRES_PASS', 'docker')
self.db_names = os.environ.get('POSTGRES_DB', '').split(',')
self.schemas = os.environ.get('SCHEMA_NAME', '').split(',')
self.all_databases = os.environ.get('ALL_DATABASES', 'TRUE').lower() == 'true'

def connect_to_db(self, db_name):
try:
conn = psycopg2.connect(
dbname=db_name,
user=self.db_user,
password=self.db_pass,
host=self.db_host,
port=self.db_port
)
return conn
except psycopg2.Error as e:
self.fail(f"Failed to connect to the database: {e}")

def test_schema_existence(self):
for idx, db_name in enumerate(self.db_names):
conn = self.connect_to_db(db_name)
cursor = conn.cursor()

for schema in self.schemas:
query = f"SELECT schema_name, catalog_name FROM information_schema.schemata \
WHERE schema_name = '{schema}' and catalog_name = '{db_name}';"
cursor.execute(query)
exists = cursor.fetchone()

if not self.all_databases and idx > 0:
self.assertIsNone(exists, f"Schema '{schema}' should not exist in database '{db_name}'")
else:
self.assertIsNotNone(exists, f"Schema '{schema}' does not exist in database '{db_name}'")

conn.close()


if __name__ == '__main__':
unittest.main()
13 changes: 13 additions & 0 deletions scenario_tests/multiple_databases/tests/test_schemas.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

set -e

source /scripts/env-data.sh

# execute tests
pushd /tests

PGHOST=localhost \
PGDATABASE=gis \
PYTHONPATH=/lib \
python3 -m unittest -v test_schema_existence.TestSchemaExistence
15 changes: 9 additions & 6 deletions scripts/env-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,10 @@ if [ -n "${POSTGRES_INITDB_ARGS}" ]; then
INITDB_EXTRA_ARGS=${POSTGRES_INITDB_ARGS}
fi

list=$(echo "${POSTGRES_DBNAME}" | tr ',' ' ')
arr=("${list}")
SINGLE_DB=${arr[0]}
IFS=','
read -a dbarr <<< "$POSTGRES_DBNAME"
SINGLE_DB=${dbarr[0]}
export ${SINGLE_DB}

if [ -z "${TIMEZONE}" ]; then
TIMEZONE='Etc/UTC'
Expand Down Expand Up @@ -437,6 +438,8 @@ function restart_postgres {

function entry_point_script {
SETUP_LOCKFILE="${SCRIPTS_LOCKFILE_DIR}/.entry_point.lock"
IFS=','
read -a dbarr <<< "$POSTGRES_DBNAME"
# If lockfile doesn't exists, proceed.
if [[ ! -f "${SETUP_LOCKFILE}" ]] || [[ "${IGNORE_INIT_HOOK_LOCKFILE}" =~ [Tt][Rr][Uu][Ee] ]]; then
if find "/docker-entrypoint-initdb.d" -mindepth 1 -print -quit 2>/dev/null | grep -q .; then
Expand All @@ -447,15 +450,15 @@ function entry_point_script {
if [[ "${ALL_DATABASES}" =~ [Ff][Aa][Ll][Ss][Ee] ]]; then
psql "${SINGLE_DB}" -U ${POSTGRES_USER} -p 5432 -h localhost -f "${f}" || true
else
for db in $(echo "${POSTGRES_DBNAME}" | tr ',' ' '); do
for db in "${dbarr[@]}";do
psql "${db}" -U ${POSTGRES_USER} -p 5432 -h localhost -f "${f}" || true
done
fi;;
*.sql.gz) echo "$0: running $f";
if [[ "${ALL_DATABASES}" =~ [Ff][Aa][Ll][Ss][Ee] ]]; then
gunzip < "$f" | psql "${SINGLE_DB}" -U ${POSTGRES_USER} -p 5432 -h localhost || true
else
for db in $(echo "${POSTGRES_DBNAME}" | tr ',' ' '); do
for db in "${dbarr[@]}";do
gunzip < "$f" | psql "${db}" -U ${POSTGRES_USER} -p 5432 -h localhost || true
done
fi;;
Expand Down Expand Up @@ -493,7 +496,7 @@ function configure_replication_permissions {
}

function streaming_replication {
until ${START_COMMAND} "${PG_BASEBACKUP} -X stream -h ${REPLICATE_FROM} -p ${REPLICATE_PORT} -D ${DATADIR} -U ${REPLICATION_USER} -R -vP -w --label=gis_pg_custer"
until START_COMMAND "${PG_BASEBACKUP} -X stream -h ${REPLICATE_FROM} -p ${REPLICATE_PORT} -D ${DATADIR} -U ${REPLICATION_USER} -R -vP -w --label=gis_pg_custer"
do
echo -e "[Entrypoint] \e[1;31m Waiting for master to connect... \033[0m"
sleep 1s
Expand Down
15 changes: 9 additions & 6 deletions scripts/setup-database.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ export PGPASSWORD=${POSTGRES_PASS}
# Create a default db called 'gis' or $POSTGRES_DBNAME that you can use to get up and running quickly
# It will be owned by the docker db user
# Since we now pass a comma separated list in database creation we need to search for all databases as a test
for db in $(echo "${POSTGRES_DBNAME}" | tr ',' ' '); do
IFS=','
read -a dbarr <<< "$POSTGRES_DBNAME"

for db in "${dbarr[@]}";do
RESULT=$(su - postgres -c "psql -t -c \"SELECT count(1) from pg_database where datname='${db}';\"")
if [[ ${RESULT} -eq 0 ]]; then
echo -e "\e[32m [Entrypoint] Create database \e[1;31m ${db} \033[0m"
Expand All @@ -117,16 +120,16 @@ for db in $(echo "${POSTGRES_DBNAME}" | tr ',' ' '); do
extension_install "${db}" "${ext}"
# enable extensions in template1 if env variable set to true
if [[ "$(boolean "${POSTGRES_TEMPLATE_EXTENSIONS}")" =~ [Tt][Rr][Uu][Ee] ]] ; then
extension_install template1
extension_install template1 "${ext}"
fi
done
echo -e "\e[32m [Entrypoint] loading legacy sql in database \e[1;31m ${db} \033[0m"
psql "${db}" -U "${POSTGRES_USER}" -p 5432 -h localhost -f "${SQLDIR}"/legacy_minimal.sql || true
psql "${db}" -U "${POSTGRES_USER}" -p 5432 -h localhost -f "${SQLDIR}"/legacy_gist.sql || true
if [[ "$WAL_LEVEL" =~ [Ll][Oo][Gg][Ii][Cc][Aa][Ll] ]];then
psql "${db}" -U "${POSTGRES_USER}" -p 5432 -h localhost -c "CREATE PUBLICATION logical_replication;"
fi

if [[ "${WAL_LEVEL,,}" == "logical" ]]; then
psql -d "${db}" -U "${POSTGRES_USER}" -p 5432 -h localhost -c "CREATE PUBLICATION logical_replication;"
fi
else
echo -e "\e[32m [Entrypoint] Database \e[1;31m ${db} \e[32m already exists \033[0m"

Expand All @@ -136,7 +139,7 @@ done


# Create schemas in the DB
for db in $(echo "${POSTGRES_DBNAME}" | tr ',' ' '); do
for db in "${dbarr[@]}";do
for schema in $(echo "${SCHEMA_NAME}" | tr ',' ' '); do
SCHEMA_RESULT=$(psql -t "${db}" -U "${POSTGRES_USER}" -p 5432 -h localhost -c "select count(1) from information_schema.schemata where schema_name = '${schema}' and catalog_name = '${db}';")
if [[ ${SCHEMA_RESULT} -eq 0 ]] && [[ "${ALL_DATABASES}" =~ [Ff][Aa][Ll][Ss][Ee] ]]; then
Expand Down
16 changes: 10 additions & 6 deletions scripts/setup-replication.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ source /scripts/env-data.sh
# Adapted from https://github.com/DanielDent/docker-postgres-replication
# To set up replication
if [[ ${RUN_AS_ROOT} =~ [Ff][Aa][Ll][Ss][Ee] ]];then
echo "gosu ${USER_NAME}:${DB_GROUP_NAME} bash -c" > /tmp/gosu_subs.txt
envsubst < /tmp/gosu_subs.txt > /tmp/gosu_command.txt
START_COMMAND=$(cat /tmp/gosu_command.txt)
rm /tmp/gosu_subs.txt /tmp/gosu_command.txt
function START_COMMAND() {
PARAM=$1
gosu ${USER_NAME} bash -c "$1"
}
else
START_COMMAND='su - postgres -c'
function START_COMMAND() {
PARAM=$1
su postgres -c "$1"
}
fi

create_dir "${WAL_ARCHIVE}"
Expand All @@ -24,8 +27,9 @@ if [[ "$WAL_LEVEL" == 'replica' && "${REPLICATION}" =~ [Tt][Rr][Uu][Ee] ]]; then
echo "Specify the master address/hostname in REPLICATE_FROM and REPLICATE_PORT variable."
exit 1
fi


until ${START_COMMAND} "/usr/bin/pg_isready -h ${REPLICATE_FROM} -p ${REPLICATE_PORT}"
until START_COMMAND "/usr/lib/postgresql/${POSTGRES_MAJOR_VERSION}/bin/pg_isready -h ${REPLICATE_FROM} -p ${REPLICATE_PORT}"
do
echo -e "[Entrypoint] \e[1;31m Waiting for master to ping... \033[0m"
sleep 1s
Expand Down

0 comments on commit 74bb497

Please sign in to comment.