From 260f548c5b4bd0c4e602740128aeca6058331f4d Mon Sep 17 00:00:00 2001 From: Kazunori Kimura Date: Thu, 20 Apr 2023 18:59:25 +0900 Subject: [PATCH] Ship with multiple versions of postgresql-client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- Dockerfile | 3 ++- assets/runtime/functions | 56 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e966e52b..f0f245c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 \ diff --git a/assets/runtime/functions b/assets/runtime/functions index 787ce5c8..34a0a0e9 100644 --- a/assets/runtime/functions +++ b/assets/runtime/functions @@ -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 \