fix issue with multiple db creation and add test for this (#443)

* fix issue with multiple db creation and add test for this
kubectl-fix^2
mazano 2023-08-31 17:37:28 +02:00 zatwierdzone przez GitHub
rodzic 80b4b715b6
commit 74bb497307
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 195 dodań i 18 usunięć

Wyświetl plik

@ -39,6 +39,7 @@ jobs:
- extensions
- logical_replication
- init_scripts
- multiple_databases
include:
- distro: debian
imageVersion: bookworm

Wyświetl plik

@ -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"

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Wyświetl plik

@ -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'
@ -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
@ -447,7 +450,7 @@ 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;;
@ -455,7 +458,7 @@ function entry_point_script {
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;;
@ -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

Wyświetl plik

@ -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"
@ -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"
@ -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

Wyświetl plik

@ -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}"
@ -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