Ship with multiple versions of postgresql-client

It is intended to work even in environments without an internet connection.

- Use latest version of pg_isready on checking database connection
- Switch postgresql-client version checking server on startup
- If the server versions do not match exactly, use the latest installed client
  and warn on docker log

From postgresql documentation:
https://www.postgresql.org/docs/15/app-pgdump.html#PG-DUMP-NOTES

> Also, it is not guaranteed that pg_dump's output can be loaded
> into a server of an older major version — not even if the dump
> was taken from a server of that version.

To switch client version, generate a file ~/.postgresqlrc with content like:

{server side major version} {server hostname}:{server port} {default database}

See detail on:
https://manpages.ubuntu.com/manpages/bionic/man5/postgresqlrc.5.html

Following messages appear on docker log:

- Detected server version: 140007
- Generating /home/git/.postgresqlrc
This commit is contained in:
Kazunori Kimura 2023-04-20 18:59:25 +09:00
parent d35c73ce72
commit 260f548c5b
2 changed files with 57 additions and 2 deletions

View File

@ -44,7 +44,8 @@ RUN set -ex && \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
sudo supervisor logrotate locales curl \
nginx openssh-server postgresql-client-12 postgresql-contrib-12 redis-tools \
nginx openssh-server postgresql-contrib redis-tools \
postgresql-client-12 postgresql-client-13 postgresql-client-14 postgresql-client-15 \
python3 python3-docutils nodejs yarn gettext-base graphicsmagick \
libpq5 zlib1g libyaml-0-2 libssl1.1 \
libgdbm6 libreadline8 libncurses5 libffi7 \

View File

@ -149,7 +149,7 @@ gitlab_finalize_database_parameters() {
gitlab_check_database_connection() {
prog=$(find /usr/lib/postgresql/ -name pg_isready)
prog=$(find /usr/lib/postgresql/ -name pg_isready -type f | sort | tail -n1)
prog="${prog} -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} -t 1"
timeout=60
@ -167,11 +167,65 @@ gitlab_check_database_connection() {
echo
}
gitlab_generate_postgresqlrc() {
echo "Configuring /home/${GITLAB_USER}/.postgresqlrc to avoid version mismatch on dumping"
# server_version_num property is a number built from version string:
# https://www.postgresql.org/docs/15/libpq-status.html#LIBPQ-PQSERVERVERSION
# > The result is formed by multiplying the server's major version number by 10000 and adding the minor version number.
# > For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000. Zero is returned if the connection is bad.
# >
# > Prior to major version 10, PostgreSQL used three-part version numbers in which the first two parts together represented the major version.
# > For those versions, PQserverVersion uses two digits for each part;
# > for example version 9.1.5 will be returned as 90105, and version 9.2.0 will be returned as 90200.
#
# This difference also appends to apt package name.
# For example, in ubuntu:focal, postgresql-client-{8.2, 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10, 11, 12, 13, 14, 15} are available.
#
DB_SERVER_VERSION=$(PGPASSWORD=${DB_PASS} psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" -Atw -c "SHOW server_version_num")
if [[ "${DB_SERVER_VERSION}" -eq 0 ]]; then
echo
echo "Could not retrieve database server version correctly. Aborting..."
return 1
fi
echo "- Detected server version: ${DB_SERVER_VERSION}"
# Anyway, we can get major version (8, 9, 10 and so on) by dividing by 10000.
# DB_SERVER_VERSION_MAJOR=${DB_SERVER_VERSION%%.*}
DB_SERVER_VERSION_MAJOR=$((DB_SERVER_VERSION/10000))
DB_CLIENT_VERSION_PACKAGE_NAME=
if [[ "${DB_SERVER_VERSION_MAJOR}" -ge 10 ]]; then
# v10 or later: use "rought major version" as version number in package name
DB_CLIENT_VERSION_PACKAGE_NAME=${DB_SERVER_VERSION_MAJOR}
else
# prior to v10: convert
# FIXME: rough implementation
# It exploits the fact that there is no version such as 9.10, and it lacks versatility.
# divide by 100, then replace first 0 to comma
DB_CLIENT_VERSION_PACKAGE_NAME=$((DB_SERVER_VERSION/100))
DB_CLIENT_VERSION_PACKAGE_NAME=${DB_CLIENT_VERSION_PACKAGE_NAME/0/.}
fi
# if exact-match client not found, select latest version from installed clients
if [[ "$(apt-cache pkgnames postgresql-client | grep -e "-${DB_CLIENT_VERSION_PACKAGE_NAME}" | wc -l)" -ne 1 ]]; then
LATEST_CLIENT="$(apt-cache pkgnames postgresql-client | grep -v -e "-common" | sort --version-sort | tail -n1)"
DB_CLIENT_VERSION_PACKAGE_NAME=${LATEST_CLIENT/postgresql-client-/}
echo "gitlab_generate_postgresqlrc(): WARNING - Suitable client not installed. postgresql-client-${DB_CLIENT_VERSION_PACKAGE_NAME} will be used but you may face issue (database in backup will be empty, for example)"
fi
# generate ~/.postgresqlrc to switch client version
GITLAB_USER_POSTGRESQLRC="/home/${GITLAB_USER}/.postgresqlrc"
echo "- Generating ${GITLAB_USER_POSTGRESQLRC}"
echo "${DB_CLIENT_VERSION_PACKAGE_NAME} ${DB_HOST}:${DB_PORT} ${DB_NAME}" | exec_as_git tee "${GITLAB_USER_POSTGRESQLRC}"
}
gitlab_configure_database() {
echo -n "Configuring gitlab::database"
gitlab_finalize_database_parameters
gitlab_check_database_connection
gitlab_generate_postgresqlrc
update_template ${GITLAB_DATABASE_CONFIG} \
DB_ENCODING \