From b406e0c2fc4ee585782960e01bc080b428b1fee6 Mon Sep 17 00:00:00 2001 From: ffalqui Date: Mon, 9 Feb 2026 12:08:30 +0100 Subject: [PATCH] Upgrade base images to Rocky 9/UBI 9 and PostgreSQL 18.1 - Update base images from Rocky Linux 8 to 9 and UBI 8 to UBI 9 - Upgrade PostgreSQL from 14.8 to 18.1 - Add pg_dumpall migration script for existing deployments - update pipeline --- .github/configure | 20 ++ .github/pr-title-checker-config.json | 14 -- .github/workflows/build.yml | 53 +++++ .github/workflows/ga-publication.yml | 64 ------ .github/workflows/post-merge.yml | 41 ---- .github/workflows/pr.yml | 163 -------------- .github/workflows/publication.yml | 112 ---------- Dockerfile.rocky8 | 52 ----- Dockerfile.rocky9 | 54 +++++ Dockerfile.ubi8 => Dockerfile.ubi9 | 22 +- README.md | 8 +- check-container | 2 +- docker-entrypoint.sh | 4 +- entando-project | 2 +- upgrade-pg14-to-pg18.sh | 311 +++++++++++++++++++++++++++ 15 files changed, 458 insertions(+), 464 deletions(-) create mode 100755 .github/configure delete mode 100644 .github/pr-title-checker-config.json create mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/ga-publication.yml delete mode 100644 .github/workflows/post-merge.yml delete mode 100644 .github/workflows/pr.yml delete mode 100644 .github/workflows/publication.yml delete mode 100644 Dockerfile.rocky8 create mode 100644 Dockerfile.rocky9 rename Dockerfile.ubi8 => Dockerfile.ubi9 (52%) create mode 100755 upgrade-pg14-to-pg18.sh diff --git a/.github/configure b/.github/configure new file mode 100755 index 0000000..1d1ea23 --- /dev/null +++ b/.github/configure @@ -0,0 +1,20 @@ +#!/bin/bash + +git config --global advice.detachedHead false + +( + cd .github + git clone --depth 1 --branch "${ENTANDO_GITHUB_TOOLS_VERSION}" "https://github.com/entando-ps/github-tools" &>/dev/null +) + +. .github/github-tools/lib.sh + +configure.start "$1" + +if [[ "$GITHUB_REF" == refs/tags/* ]]; then + . .github/github-tools/base.configure --tag "$GITHUB_REF" +else + . .github/github-tools/base.configure "$GH_PR_TITLE" "$GH_PR_NUMBER" +fi + +configure.complete diff --git a/.github/pr-title-checker-config.json b/.github/pr-title-checker-config.json deleted file mode 100644 index bfcc715..0000000 --- a/.github/pr-title-checker-config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "LABEL": { - "name": "title needs correct naming convention", - "color": "EEEEEE" - }, - "CHECKS": { - "regexp": "[A-Z]{2,5}-[0-9]{1,5}" - }, - "MESSAGES": { - "success": "All OK", - "failure": "Failing PR test", - "notice": "Check the naming convention rules to naming PRs" - } -} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..465c531 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,53 @@ +name: Maven MultiModule PR + +env: + ENTANDO_GITHUB_TOOLS_VERSION: "v0.1.1" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_PR_TITLE: ${{ github.event.pull_request.title }} + GH_PR_NUMBER: ${{ github.event.pull_request.number }} + GH_PR_RUN_NUMBER: ${{ github.run_number }} + IMAGES_TO_BUILD: "Dockerfile.rocky9:entando-postgres-rocky,Dockerfile.ubi9:entando-postgres-ubi" + ENTANDO_CRANE_VERSION: ${{ vars.ENTANDO_CRANE_VERSION || 'v0.10.0' }} + GITHUB_REF: ${{ github.ref }} + +on: + push: + branches: [ "develop", "release/*" ] + tags: [ 'v*' ] + pull_request: + branches: [ "develop", "release/*" ] + +jobs: + publish: + permissions: + contents: read + pull-requests: write + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Configure + run: if [ -f ".github/configure" ]; then . .github/configure "publish"; fi + + - name: Build Docker image + run: | + .github/github-tools/docker.multiBuild \ + "${IMAGES_TO_BUILD}" \ + "${ARTIFACT_VERSION}" \ + "${{ vars.DOCKER_ORG }}" \ + ; + + - name: Publish Docker image + run: | + GH_DO_COMMENT=true \ + .github/github-tools/docker.multiPublish \ + "${IMAGES_TO_BUILD}" \ + "${ARTIFACT_VERSION}" \ + "${{ vars.DOCKER_ORG }}" \ + "${{ vars.DOCKER_REGISTRY }}" \ + "${{ secrets.DOCKER_USERNAME }}" \ + "${{ secrets.DOCKER_PASSWORD }}" \ + "${ARTIFACT_PUB_TYPE}" \ + ; diff --git a/.github/workflows/ga-publication.yml b/.github/workflows/ga-publication.yml deleted file mode 100644 index 3c94f7d..0000000 --- a/.github/workflows/ga-publication.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: GA Publication - -on: - release: - types: - - created - -env: - ENTANDO_OPT_USE_PPL_TAG: "v1.2.1" - ENTANDO_OPT_FEATURES: "${{ secrets.ENTANDO_OPT_FEATURES }}" - ENTANDO_OPT_GLOBAL_FEATURES: "${{ secrets.ENTANDO_OPT_GLOBAL_FEATURES }}" - ENTANDO_OPT_LOG_LEVEL: "${{ secrets.ENTANDO_OPT_LOG_LEVEL }}" - ENTANDO_OPT_REPO_BOM_URL: "${{ secrets.ENTANDO_OPT_REPO_BOM_URL }}" - ENTANDO_OPT_CUSTOM_ENV: "${{ secrets.ENTANDO_OPT_CUSTOM_ENV }}" - PPL_CONTEXT: ${{ toJson(github) }} - GIT_USER_NAME: "${{ secrets.GIT_USER_NAME }}" - GIT_USER_EMAIL: "${{ secrets.GIT_USER_EMAIL }}" - LOCAL_CLONE_DIR: "local-checkout" - - -jobs: - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # GA PUBLICATION - - ga-publish: - env: - ENTANDO_OPT_MAVEN_REPO_GA: ${{ secrets.ENTANDO_OPT_MAVEN_REPO_GA }} - ENTANDO_BOT_TOKEN: ${{ secrets.ENTANDO_BOT_TOKEN }} - runs-on: ubuntu-latest - steps: - - name: "PR PIPELINE START" - run: | - ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} - ~/ppl-run status-report - - name: "Checkout" - run: | - ~/ppl-run checkout-branch base \ - --id "CHECKOUT FOR GA PUBLICATION" \ - --lcd "$LOCAL_CLONE_DIR" - - name: "Cache Maven packages" - uses: actions/cache@v2 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - - name: "Configure GA Repository" - uses: actions/setup-java@v1 - with: - java-version: 11 - server-id: maven-central - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - name: "Publish package to GA" - run: | - ~/ppl-run mvn GA-PUBLICATION \ - --id "GA-PUBLICATION" \ - --lcd "$LOCAL_CLONE_DIR" - env: - MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml deleted file mode 100644 index b58efd7..0000000 --- a/.github/workflows/post-merge.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Post-Merge - -on: - push: - branches: - - develop - - epic/* - - release/* - -env: - ENTANDO_OPT_USE_PPL_TAG: "v1.2.1" - ENTANDO_OPT_FEATURES: "${{ secrets.ENTANDO_OPT_FEATURES }}" - ENTANDO_OPT_GLOBAL_FEATURES: "${{ secrets.ENTANDO_OPT_GLOBAL_FEATURES }}" - ENTANDO_OPT_LOG_LEVEL: "${{ secrets.ENTANDO_OPT_LOG_LEVEL }}" - ENTANDO_OPT_REPO_BOM_URL: "${{ secrets.ENTANDO_OPT_REPO_BOM_URL }}" - PPL_CONTEXT: ${{ toJson(github) }} - GIT_USER_NAME: "${{ secrets.GIT_USER_NAME }}" - GIT_USER_EMAIL: "${{ secrets.GIT_USER_EMAIL }}" - LOCAL_CLONE_DIR: "local-checkout" - - -jobs: - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # SNAPSHOT TAG - - add-version-tag: - runs-on: ubuntu-latest - steps: - - name: "ADD SNAPSHOT TAG" - run: | - ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} - - ~/ppl-run pr-status-report \ - .. checkout-branch base \ - --id "CHECKOUT-BASE" \ - --lcd "$LOCAL_CLONE_DIR" \ - --token "${{ secrets.ENTANDO_BOT_TOKEN }}" \ - .. publication tag-git-version \ - --id "TAG-VERSION" \ - --lcd "$LOCAL_CLONE_DIR" diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index 90bd640..0000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,163 +0,0 @@ -name: PR-CYCLE - -on: - pull_request: - types: - - opened - - synchronize - - reopened - branches: - - develop - - epic/* - - release/* - -env: - ENTANDO_OPT_USE_PPL_TAG: "v1.2.1" - ENTANDO_OPT_FEATURES: "${{ secrets.ENTANDO_OPT_FEATURES }}" - ENTANDO_OPT_GLOBAL_FEATURES: "${{ secrets.ENTANDO_OPT_GLOBAL_FEATURES }}" - ENTANDO_OPT_LOG_LEVEL: "${{ secrets.ENTANDO_OPT_LOG_LEVEL }}" - ENTANDO_OPT_REPO_BOM_URL: "${{ secrets.ENTANDO_OPT_REPO_BOM_URL }}" - ENTANDO_OPT_CUSTOM_ENV: "${{ secrets.ENTANDO_OPT_CUSTOM_ENV }}" - ENTANDO_OPT_OKD_LOGIN: "${{ secrets.ENTANDO_OPT_OKD_LOGIN }}" - ENTANDO_OPT_IMAGE_REGISTRY_OVERRIDE: "${{ secrets.ENTANDO_OPT_IMAGE_REGISTRY_OVERRIDE }}" - ENTANDO_OPT_DOCKER_ORG: "${{ secrets.ENTANDO_OPT_DOCKER_ORG }}" - ENTANDO_OPT_TEST_NAMESPACE: "${{ secrets.ENTANDO_OPT_TEST_NAMESPACE }}" - ENTANDO_OPT_HELM_CLI_URL: "${{ secrets.ENTANDO_OPT_HELM_CLI_URL }}" - ENTANDO_OPT_TEST_POSTDEP_PLAN: "${{ secrets.ENTANDO_OPT_TEST_POSTDEP_PLAN }}" - ENTANDO_OPT_TEST_COMPOSE_FILE: "${{ secrets.ENTANDO_OPT_TEST_COMPOSE_FILE }}" - ENTANDO_OPT_TEST_OPERATOR_BUNDLE_URL: "${{ secrets.ENTANDO_OPT_TEST_OPERATOR_BUNDLE_URL }}" - ENTANDO_OPT_TEST_OPERATOR_BUNDLE_VERSION: "${{ secrets.ENTANDO_OPT_TEST_OPERATOR_BUNDLE_VERSION }}" - PPL_CONTEXT: ${{ toJson(github) }} - GIT_USER_NAME: "${{ secrets.GIT_USER_NAME }}" - GIT_USER_EMAIL: "${{ secrets.GIT_USER_EMAIL }}" - LOCAL_CLONE_DIR: "local-checkout" - ENTANDO_OPT_SNYK_ORG: "${{ secrets.ENTANDO_OPT_SNYK_ORG }}" - - -jobs: - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # PREPARE - - prepare: - runs-on: ubuntu-latest - outputs: - SCAN_MATRIX: ${{ steps.START.outputs.SCAN_MATRIX }} - steps: - #~ - - name: "PR PIPELINE START" - id: START - run: | - ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} - ~/ppl-run \ - .. status-report \ - .. @checkout-branch --lcd "$LOCAL_CLONE_DIR" \ - .. @setup-feature-flags "PR_PREFLIGHT_CHECKS" "BOM_CHECK" "BOM" \ - .. @setup-features-list "SCAN_MATRIX" --prefix "MTX-ENP-,MTX-SCAN-" \ - ; - - name: "PR preflight checks" - if: steps.START.outputs.PR_PREFLIGHT_CHECKS != 'false' - id: pr-preflight-checks - run: | - ~/ppl-run pr-preflight-checks --lcd "$LOCAL_CLONE_DIR" - - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # FULL-BUILD - - full-build: - needs: [ 'prepare' ] - runs-on: ubuntu-latest - env: - ENTANDO_BOT_TOKEN: ${{ secrets.ENTANDO_BOT_TOKEN }} - ENTANDO_OPT_OKD_LOGIN_URL: "${{ secrets.ENTANDO_OPT_OKD_LOGIN_URL }}" - ENTANDO_OPT_OKD_LOGIN_TOKEN: "${{ secrets.ENTANDO_OPT_OKD_LOGIN_TOKEN }}" - ENTANDO_OPT_OKD_LOGIN_NAMESPACE: "${{ secrets.ENTANDO_OPT_OKD_LOGIN_NAMESPACE }}" - ENTANDO_OPT_OKD_LOGIN_INSECURE: "${{ secrets.ENTANDO_OPT_OKD_LOGIN_INSECURE }}" - ENTANDO_OPT_OKD_CLI_URL: "${{ secrets.ENTANDO_OPT_OKD_CLI_URL }}" - steps: - #~ CHECKOUT - - name: "CHECKOUT" - id: CHECKOUT - run: | - ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} - ~/ppl-run checkout-branch \ - --lcd "$LOCAL_CLONE_DIR" \ - --token "$ENTANDO_BOT_TOKEN" \ - ; - ~/ppl-run generic GENERATE-BUILD-CACHE-KEY "BUILD_CACHE_KEY" --lcd "$LOCAL_CLONE_DIR" >> $GITHUB_ENV - ~/ppl-run generic GENERATE-BUILD-TARGET-DIR "BUILD_TARGET_DIR" --lcd "$LOCAL_CLONE_DIR" >> $GITHUB_ENV - #~ BUILD CACHE - - name: "Cache Build Dir" - id: build-cache - uses: actions/cache@v2 - with: - path: "${{ env.LOCAL_CLONE_DIR}}/${{ env.BUILD_TARGET_DIR }}/" - key: ${{ runner.os }}-enp-build-${{ env.BUILD_CACHE_KEY }} - #~ BUILD - - name: "FULL BUILD" - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - run: | - ~/ppl-run generic FULL-BUILD --lcd "$LOCAL_CLONE_DIR" - - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # SCANS -# scans: -# needs: [ 'prepare', 'full-build' ] -# runs-on: ubuntu-latest -# if: ${{ needs.prepare.outputs.SCAN_MATRIX != '' }} -# strategy: -# max-parallel: 5 -# fail-fast: false -# matrix: -# mtx-step: ${{fromJson(needs.prepare.outputs.SCAN_MATRIX)}} -# -# steps: -# #~ CHECKOUT -# - name: "CHECKOUT" -# run: | -# ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} -# ~/ppl-run checkout-branch pr --lcd "$LOCAL_CLONE_DIR" -# ~/ppl-run generic GENERATE-BUILD-CACHE-KEY "BUILD_CACHE_KEY" --lcd "$LOCAL_CLONE_DIR" >> $GITHUB_ENV -# ~/ppl-run generic GENERATE-BUILD-TARGET-DIR "BUILD_TARGET_DIR" --lcd "$LOCAL_CLONE_DIR" >> $GITHUB_ENV -# #~ BUILD CACHE -# - name: "Cache Build Dir" -# id: build-cache -# uses: actions/cache@v2 -# with: -# path: "${{ env.LOCAL_CLONE_DIR}}/${{ env.BUILD_TARGET_DIR }}/" -# key: ${{ runner.os }}-enp-build-${{ env.BUILD_CACHE_KEY }} -# #~ SCAN -# - name: "Run the matrix step ${{ matrix.mtx-step }}" -# run: | -# MTX_STEP="${{ matrix.mtx-step }}" -# ~/ppl-run generic GENERATE-REQUIREMENT-SPEC "MTX_REQUIREMENT" "$MTX_STEP" >> $GITHUB_ENV -# for spec in (("${{ env.MTX_REQUIREMENT }}")); do -# case "${{ env.MTX_REQUIREMENT }}" in -# ENTANDO-REQ-GITHUB-SPECIAL) -# export GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" -# ;; -# ENTANDO-REQ-SNYK) -# export SNYK_TOKEN="${{ secrets.SNYK_TOKEN }}" -# ;; -# ENTANDO-REQ-POST-DEP) -# export ENTANDO_OPT_OKD_LOGIN_URL="${{ secrets.ENTANDO_OPT_OKD_LOGIN_URL }}" -# export ENTANDO_OPT_OKD_LOGIN_TOKEN="${{ secrets.ENTANDO_OPT_OKD_LOGIN_TOKEN }}" -# export ENTANDO_OPT_OKD_LOGIN_NAMESPACE="${{ secrets.ENTANDO_OPT_OKD_LOGIN_NAMESPACE }}" -# export ENTANDO_OPT_OKD_LOGIN_INSECURE="${{ secrets.ENTANDO_OPT_OKD_LOGIN_INSECURE }}" -# export ENTANDO_OPT_OKD_CLI_URL="${{ secrets.ENTANDO_OPT_OKD_CLI_URL }}" -# export ENTANDO_OPT_IMAGE_REGISTRY_CREDENTIALS="${{ secrets.ENTANDO_OPT_IMAGE_REGISTRY_CREDENTIALS }}" -# export ENTANDO_OPT_TEST_NAMESPACE="${{ secrets.ENTANDO_OPT_TEST_NAMESPACE }}" -# export ENTANDO_OPT_TEST_HOSTNAME_SUFFIX="${{ secrets.ENTANDO_OPT_TEST_HOSTNAME_SUFFIX }}" -# export ENTANDO_OPT_DOCKER_BUILDS="${{ secrets.ENTANDO_OPT_DOCKER_BUILDS }}" -# export ENTANDO_OPT_DOCKER_ORG="${{ secrets.ENTANDO_OPT_DOCKER_ORG }}" -# export ENTANDO_OPT_DOCKER_USERNAME="${{ secrets.ENTANDO_OPT_DOCKER_USERNAME }}" -# export ENTANDO_OPT_DOCKER_PASSWORD="${{ secrets.ENTANDO_OPT_DOCKER_PASSWORD }}" -# export ENTANDO_OPT_TEST_TLS_CRT="${{ secrets.ENTANDO_OPT_TEST_TLS_CRT }}" -# export ENTANDO_OPT_TEST_TLS_KEY="${{ secrets.ENTANDO_OPT_TEST_TLS_KEY }}" -# ;; -# esac -# done -# ~/ppl-run generic "$MTX_STEP" --id "$MTX_STEP" --lcd "$LOCAL_CLONE_DIR" diff --git a/.github/workflows/publication.yml b/.github/workflows/publication.yml deleted file mode 100644 index 9bb5094..0000000 --- a/.github/workflows/publication.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: PUB - -on: - push: - tags: - - "v*" - -env: - PPL_TEMPLATE_VERSION: "v2.0.0" - ENTANDO_BOT_TOKEN: ${{ secrets.ENTANDO_BOT_TOKEN }} - PR_CHECKER_PATH: ".github/pr-title-checker-config.json" - - DOCKER_ROCKY_IMAGE_BASE_NAME: entando/entando-postgres-rocky - DOCKER_UBI_IMAGE_BASE_NAME: entando/entando-postgres-ubi - DOCKER_IMAGE_ARCHITECTURE: linux/amd64,linux/arm64 - DOCKER_IMAGE_CONTEXT: . - DOCKER_ROCKY_IMAGE_FILE: Dockerfile.rocky8 - DOCKER_UBI_IMAGE_FILE: Dockerfile.ubi8 - DOCKER_IMAGE_PUSH: true - -jobs: - - check-pr: - runs-on: ubuntu-latest - steps: - - uses: thehanimo/pr-title-checker@v1.3.7 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - pass_on_octokit_error: false - configuration_path: ${{ env.PR_CHECKER_PATH }} - - publication: - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Docker meta-rocky - id: meta-rocky - uses: docker/metadata-action@v4 - with: - images: | - ${{ env.DOCKER_ROCKY_IMAGE_BASE_NAME }} - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr,value={{base_ref}} - type=ref,event=tag - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - type=raw,event=pr,value={{base_ref}} - - - name: Docker meta-ubi - id: meta-ubi - uses: docker/metadata-action@v4 - with: - images: | - ${{ env.DOCKER_UBI_IMAGE_BASE_NAME }} - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr - type=ref,event=tag - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - type=raw,event=pr,value={{branch}} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - platforms: ${{ env.DOCKER_IMAGE_ARCHITECTURE }} - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.ENTANDO_OPT_DOCKER_USERNAME }} - password: ${{ secrets.ENTANDO_OPT_DOCKER_PASSWORD }} - - - name: Login to RHT - uses: docker/login-action@v2 - with: - registry: ${{ secrets.ENTANDO_RHT_DOCKER_REGISTRY }} - username: ${{ secrets.ENTANDO_RHT_DOCKER_USERNAME }} - password: ${{ secrets.ENTANDO_RHT_DOCKER_PASSWORD }} - - - name: Build and push Rocky image - uses: docker/build-push-action@v4 - with: - context: ${{ env.DOCKER_IMAGE_CONTEXT }} - file: ${{ env.DOCKER_ROCKY_IMAGE_FILE }} - push: ${{ env.DOCKER_IMAGE_PUSH }} - tags: ${{ steps.meta-rocky.outputs.tags }} - labels: ${{ steps.meta-rocky.outputs.labels }} - platforms: ${{ env.DOCKER_IMAGE_ARCHITECTURE }} - - - name: Build and push Ubi image - uses: docker/build-push-action@v4 - with: - context: ${{ env.DOCKER_IMAGE_CONTEXT }} - file: ${{ env.DOCKER_UBI_IMAGE_FILE }} - push: ${{ env.DOCKER_IMAGE_PUSH }} - tags: ${{ steps.meta-ubi.outputs.tags }} - labels: ${{ steps.meta-ubi.outputs.labels }} - platforms: ${{ env.DOCKER_IMAGE_ARCHITECTURE }} diff --git a/Dockerfile.rocky8 b/Dockerfile.rocky8 deleted file mode 100644 index 50b50d9..0000000 --- a/Dockerfile.rocky8 +++ /dev/null @@ -1,52 +0,0 @@ -FROM rockylinux:8.7 - -ARG TARGETPLATFORM - -ENV PGDATA /var/lib/pgsql/data/userdata -ENV PGUSER postgres -ENV POSTGRESQL_USER=${POSTGRESQL_USER} -ENV POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD} -ENV POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE} -ENV POSTGRESQL_ADMIN_PASSWORD=${POSTGRESQL_ADMIN_PASSWORD} -ENV PATH $PATH:$PGDATA - -# Install PostgreSQL for linux/amd64 -RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ - dnf update -y && \ - dnf install -y langpacks-en glibc-all-langpacks -y \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-server-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-libs-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-contrib-14.8-1PGDG.rhel8.x86_64.rpm; \ - fi - -# Install PostgreSQL for linux/arm64 -RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ - dnf update -y && \ - dnf install -y langpacks-en glibc-all-langpacks -y \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-server-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-libs-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-contrib-14.8-1PGDG.rhel8.aarch64.rpm; \ - fi - -COPY docker-entrypoint.sh / -COPY check-container /usr/libexec/ -RUN chmod a+xr /docker-entrypoint.sh \ - && usermod -a -G root postgres \ - && chgrp -R root "/var/lib/pgsql/" \ - && chmod g+rwX "/var/lib/pgsql/" \ - && chgrp -R root "/var/run/postgresql" \ - && chmod g+rw "/var/run/postgresql" \ - && chmod ug+x "/usr/libexec/check-container" \ - ; - -USER 26 - -ENTRYPOINT ["/docker-entrypoint.sh"] - -STOPSIGNAL SIGINT - -EXPOSE 5432 - -CMD ["/usr/pgsql-14/bin/postgres"] diff --git a/Dockerfile.rocky9 b/Dockerfile.rocky9 new file mode 100644 index 0000000..1f3c767 --- /dev/null +++ b/Dockerfile.rocky9 @@ -0,0 +1,54 @@ +FROM rockylinux:9 + +ARG TARGETPLATFORM + +ENV PGDATA /var/lib/pgsql/data/userdata +ENV PGUSER postgres +ENV POSTGRESQL_USER=${POSTGRESQL_USER} +ENV POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD} +ENV POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE} +ENV POSTGRESQL_ADMIN_PASSWORD=${POSTGRESQL_ADMIN_PASSWORD} +ENV PATH $PATH:$PGDATA + +# Install PostgreSQL for linux/amd64 +RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ + dnf -qy module disable postgresql && \ + dnf update -y && \ + dnf install -y langpacks-en glibc-all-langpacks -y \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-server-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-libs-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-contrib-18.1-1PGDG.rhel9.x86_64.rpm; \ + fi + +# Install PostgreSQL for linux/arm64 +RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ + dnf -qy module disable postgresql && \ + dnf update -y && \ + dnf install -y langpacks-en glibc-all-langpacks -y \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-server-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-libs-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-contrib-18.1-2PGDG.rhel9.aarch64.rpm; \ + fi + +COPY docker-entrypoint.sh / +COPY check-container /usr/libexec/ +RUN chmod a+xr /docker-entrypoint.sh \ + && usermod -a -G root postgres \ + && chgrp -R root "/var/lib/pgsql/" \ + && chmod g+rwX "/var/lib/pgsql/" \ + && chgrp -R root "/var/run/postgresql" \ + && chmod g+rw "/var/run/postgresql" \ + && chmod ug+x "/usr/libexec/check-container" \ + ; + +USER 26 + +ENTRYPOINT ["/docker-entrypoint.sh"] + +STOPSIGNAL SIGINT + +EXPOSE 5432 + +CMD ["/usr/pgsql-18/bin/postgres"] \ No newline at end of file diff --git a/Dockerfile.ubi8 b/Dockerfile.ubi9 similarity index 52% rename from Dockerfile.ubi8 rename to Dockerfile.ubi9 index dc5ea11..0c54ae6 100644 --- a/Dockerfile.ubi8 +++ b/Dockerfile.ubi9 @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.7-1107 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.5 ARG TARGETPLATFORM @@ -14,26 +14,28 @@ ENV PATH $PATH:$PGDATA RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ rm -f etc/rpm/macros.image-language-conf && \ microdnf install -y dnf && \ + dnf -qy module disable postgresql && \ dnf update -y && \ dnf install -y \ langpacks-en glibc-all-langpacks -y \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-server-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-libs-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-14.8-1PGDG.rhel8.x86_64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-x86_64/postgresql14-contrib-14.8-1PGDG.rhel8.x86_64.rpm; \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-server-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-libs-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-18.1-1PGDG.rhel9.x86_64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-x86_64/postgresql18-contrib-18.1-1PGDG.rhel9.x86_64.rpm; \ fi #Install PostgreSQL for linux/arm64 RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ rm -f etc/rpm/macros.image-language-conf && \ microdnf install -y dnf && \ + dnf -qy module disable postgresql && \ dnf update -y && \ dnf install -y \ langpacks-en glibc-all-langpacks -y \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-server-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-libs-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-14.8-1PGDG.rhel8.aarch64.rpm \ - https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8.7-aarch64/postgresql14-contrib-14.8-1PGDG.rhel8.aarch64.rpm; \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-server-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-libs-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-18.1-2PGDG.rhel9.aarch64.rpm \ + https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-9-aarch64/postgresql18-contrib-18.1-2PGDG.rhel9.aarch64.rpm; \ fi COPY docker-entrypoint.sh / @@ -57,4 +59,4 @@ STOPSIGNAL SIGINT EXPOSE 5432 -CMD ["/usr/pgsql-14/bin/postgres"] +CMD ["/usr/pgsql-18/bin/postgres"] \ No newline at end of file diff --git a/README.md b/README.md index ff3dc5b..db62134 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# PostgreSQL 14.8 SQL Database Server container image -This container image includes PostgreSQL 14.1 SQL database server for general usage. Users can choose between RHEL(ubi8) and Rocky based images. +# PostgreSQL 18.1 SQL Database Server container image +This container image includes PostgreSQL 18.1 SQL database server for general usage. Users can choose between RHEL(ubi9) and Rocky based images. ## Quick Start * Clone or download this repository * Go inside of directory, `cd entando-postgres` -* Run this command `docker build -f Dockerfile.rocky8 -t (image:tag) .` -* Run this command `docker build -f Dockerfile.ubi8 -t (image:tag) .` +* Run this command `docker build -f Dockerfile.rocky9 -t (image:tag) .` +* Run this command `docker build -f Dockerfile.ubi9 -t (image:tag) .` ## Environment variables and volumes The image recognizes the following environment variables. diff --git a/check-container b/check-container index bd9a4b7..5f3e21e 100755 --- a/check-container +++ b/check-container @@ -20,7 +20,7 @@ fi # Readiness check follows, the --timeout is set to "infinite" because it # is handled externally (readinessProbe.timeoutSeconds). -/usr/pgsql-14/bin/pg_isready -q \ +/usr/pgsql-18/bin/pg_isready -q \ -h 127.0.0.1 \ ${POSTGRESQL_USER+-U "$POSTGRESQL_USER"} \ ${POSTGRESQL_DATABASE+-d "$POSTGRESQL_DATABASE"} \ diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 08fd012..f0e28e4 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,6 +1,6 @@ #!/bin/sh -PGCTL="/usr/pgsql-14/bin/pg_ctl" +PGCTL="/usr/pgsql-18/bin/pg_ctl" [[ "$PGDATA" != */ ]] && PGDATA="$PGDATA/" @@ -31,7 +31,7 @@ else # Before PostgreSQL can function correctly, the database cluster must be initialized: [ ! -d "$PGDATA" ] && { - LANG=${LANG:-en_US.utf8} /usr/pgsql-14/bin/initdb -D "$PGDATA" --username "$PGUSER" + LANG=${LANG:-en_US.utf8} /usr/pgsql-18/bin/initdb -D "$PGDATA" --username "$PGUSER" } chmod -R 0700 "$PGDATA" diff --git a/entando-project b/entando-project index 7ab30b7..29948b0 100644 --- a/entando-project +++ b/entando-project @@ -1,2 +1,2 @@ ENTANDO_PRJ_NAME=entando-postgres -ENTANDO_PRJ_VERSION=14.1.0-SNAPSHOT \ No newline at end of file +ENTANDO_PRJ_VERSION=18.1.0-SNAPSHOT \ No newline at end of file diff --git a/upgrade-pg14-to-pg18.sh b/upgrade-pg14-to-pg18.sh new file mode 100755 index 0000000..e399210 --- /dev/null +++ b/upgrade-pg14-to-pg18.sh @@ -0,0 +1,311 @@ +#!/bin/bash +# +# PostgreSQL 14 → 18.1 Migration Script for Entando Kubernetes Deployment +# +# This script performs a full logical backup (pg_dumpall) from the running PG 14 +# container, recreates the PVC with a fresh PG 18.1 instance, and restores the data. +# +# IMPORTANT: This causes downtime. The database will be unavailable during migration. +# +# Prerequisites: +# - kubectl installed +# - The new image (entando/entando-postgres-rocky:18.1) must be accessible from the cluster +# - Sufficient local disk space for the dump file +# +# Usage: +# chmod +x upgrade-pg14-to-pg18.sh +# ./upgrade-pg14-to-pg18.sh +# ./upgrade-pg14-to-pg18.sh --kubeconfig /path/to/kubeconfig --context my-context +# + +set -euo pipefail + +# ============================================================================ +# KUBECTL SETTINGS — override via CLI args or environment variables +# ============================================================================ +KUBECONFIG_FILE="${KUBECONFIG:-}" +KUBECONTEXT="${KUBECONTEXT:-}" + +while [[ $# -gt 0 ]]; do + case "$1" in + --kubeconfig) KUBECONFIG_FILE="$2"; shift 2 ;; + --context) KUBECONTEXT="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +KUBECTL="kubectl" +[ -n "$KUBECONFIG_FILE" ] && KUBECTL="$KUBECTL --kubeconfig $KUBECONFIG_FILE" +[ -n "$KUBECONTEXT" ] && KUBECTL="$KUBECTL --context $KUBECONTEXT" + +# ============================================================================ +# CONFIGURATION — adjust these if your deployment differs +# ============================================================================ +NAMESPACE="entando" +DEPLOYMENT="default-postgresql-dbms-in-namespace-deployment" +CONTAINER="db-container" +PVC_NAME="default-postgresql-dbms-in-namespace-db-pvc" +NEW_IMAGE="entando/entando-postgres-rocky:18.1" +BACKUP_FILE="pg14_backup_$(date +%Y%m%d_%H%M%S).sql" + +# Derived from the deployment env vars +DB_NAME="default_postgresql_dbms_in_namespace_db" +DB_USER="default_postgresql_dbms_in_namespace_db_user" + +# ============================================================================ +# HELPER FUNCTIONS +# ============================================================================ +log() { echo "[$(date '+%H:%M:%S')] $*"; } + +fail() { echo "[ERROR] $*" >&2; exit 1; } + +# Prints a snapshot of all databases, schemas and table counts +# Usage: db_snapshot +db_snapshot() { + local pod="$1" + local pg_bin="$2" + log "--- Database snapshot ---" + $KUBECTL exec -n "$NAMESPACE" "$pod" -c "$CONTAINER" -- \ + "$pg_bin/psql" -U postgres -t -A -c \ + "SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;" \ + 2>/dev/null | while IFS= read -r dbname; do + [ -z "$dbname" ] && continue + log " Database: $dbname" + $KUBECTL exec -n "$NAMESPACE" "$pod" -c "$CONTAINER" -- \ + "$pg_bin/psql" -U postgres -d "$dbname" -t -A -c \ + "SELECT table_schema, count(*) FROM information_schema.tables \ + WHERE table_schema NOT IN ('information_schema', 'pg_catalog') \ + GROUP BY table_schema ORDER BY table_schema;" \ + 2>/dev/null | while IFS='|' read -r schema count; do + [ -z "$schema" ] && continue + log " schema: $schema tables: $count" + done + done + log "--- End snapshot ---" +} + +wait_for_pod_ready() { + local timeout=300 + local interval=5 + local elapsed=0 + log "Waiting for pod to become ready (timeout: ${timeout}s)..." + while [ $elapsed -lt $timeout ]; do + local ready + ready=$($KUBECTL get pods -n "$NAMESPACE" -l "entando.org/deployment=$( echo "$DEPLOYMENT" | sed 's/-deployment$//' )" \ + -o jsonpath='{.items[0].status.containerStatuses[0].ready}' 2>/dev/null || echo "false") + if [ "$ready" = "true" ]; then + log "Pod is ready." + return 0 + fi + sleep $interval + elapsed=$((elapsed + interval)) + done + fail "Timed out waiting for pod to become ready" +} + +get_pod_name() { + $KUBECTL get pods -n "$NAMESPACE" \ + -l "entando.org/deployment=$(echo "$DEPLOYMENT" | sed 's/-deployment$//')" \ + -o jsonpath='{.items[0].metadata.name}' 2>/dev/null +} + +# ============================================================================ +# PRE-FLIGHT CHECKS +# ============================================================================ +log "=== PostgreSQL 14 → 18.1 Migration ===" +log "" +log "Namespace: $NAMESPACE" +log "Deployment: $DEPLOYMENT" +log "PVC: $PVC_NAME" +log "New image: $NEW_IMAGE" +log "Backup file: $BACKUP_FILE" +log "" + +# Verify kubectl connectivity and show context +CURRENT_CONTEXT=$($KUBECTL config current-context 2>/dev/null || echo "unknown") +log "Kube context: $CURRENT_CONTEXT" +[ -n "$KUBECONFIG_FILE" ] && log "Kubeconfig: $KUBECONFIG_FILE" +log "" + +# Verify deployment exists and is running +$KUBECTL get deployment "$DEPLOYMENT" -n "$NAMESPACE" > /dev/null 2>&1 \ + || fail "Deployment '$DEPLOYMENT' not found in namespace '$NAMESPACE'" + +POD_NAME=$(get_pod_name) +[ -n "$POD_NAME" ] || fail "No running pod found for deployment" +log "Current pod: $POD_NAME" + +# Verify current image is PG 14 +CURRENT_IMAGE=$($KUBECTL get deployment "$DEPLOYMENT" -n "$NAMESPACE" \ + -o jsonpath='{.spec.template.spec.containers[0].image}') +log "Current image: $CURRENT_IMAGE" + +echo "" +echo "============================================================" +echo " WARNING: This will cause database downtime!" +echo " A full backup will be taken before any destructive action." +echo "============================================================" +echo "" +read -r -p "Continue? (yes/no): " CONFIRM +[ "$CONFIRM" = "yes" ] || { log "Aborted."; exit 0; } + +# ============================================================================ +# STEP 1: BACKUP (pg_dumpall from the running PG 14 container) +# ============================================================================ +log "" +log "=== STEP 1/6: Backing up all databases with pg_dumpall ===" + +log "" +log "State BEFORE migration (PG 14):" +db_snapshot "$POD_NAME" "/usr/pgsql-14/bin" +log "" + +$KUBECTL exec -n "$NAMESPACE" "$POD_NAME" -c "$CONTAINER" -- \ + /usr/pgsql-14/bin/pg_dumpall -U postgres --clean --if-exists \ + > "$BACKUP_FILE" + +BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1) +log "Backup complete: $BACKUP_FILE ($BACKUP_SIZE)" + +# Sanity check: backup must not be empty +[ -s "$BACKUP_FILE" ] || fail "Backup file is empty — aborting" + +# Verify backup contains expected database +grep -q "CREATE DATABASE.*${DB_NAME}" "$BACKUP_FILE" \ + || log "WARNING: Database '${DB_NAME}' not found in dump — it may be empty or use a different name" + +# ============================================================================ +# STEP 2: SCALE DOWN +# ============================================================================ +log "" +log "=== STEP 2/6: Scaling down deployment ===" + +$KUBECTL scale deployment "$DEPLOYMENT" -n "$NAMESPACE" --replicas=0 +$KUBECTL rollout status deployment "$DEPLOYMENT" -n "$NAMESPACE" --timeout=120s +log "Deployment scaled to 0" + +# ============================================================================ +# STEP 3: DELETE AND RECREATE PVC +# ============================================================================ +log "" +log "=== STEP 3/6: Recreating PVC ===" + +# Capture current PVC spec before deletion +STORAGE_CLASS=$($KUBECTL get pvc "$PVC_NAME" -n "$NAMESPACE" \ + -o jsonpath='{.spec.storageClassName}' 2>/dev/null || echo "") +STORAGE_SIZE=$($KUBECTL get pvc "$PVC_NAME" -n "$NAMESPACE" \ + -o jsonpath='{.spec.resources.requests.storage}') +ACCESS_MODES=$($KUBECTL get pvc "$PVC_NAME" -n "$NAMESPACE" \ + -o jsonpath='{.spec.accessModes[0]}') + +log "Current PVC: storageClass=$STORAGE_CLASS, size=$STORAGE_SIZE, accessMode=$ACCESS_MODES" + +# Delete old PVC +$KUBECTL delete pvc "$PVC_NAME" -n "$NAMESPACE" --wait=true +log "Old PVC deleted" + +# Recreate PVC with same specs +STORAGE_CLASS_FIELD="" +if [ -n "$STORAGE_CLASS" ]; then + STORAGE_CLASS_FIELD="storageClassName: $STORAGE_CLASS" +fi + +$KUBECTL apply -f - <&1 | grep -i "error" | grep -vi "does not exist, skipping" || true + +log "Restore complete" + +# ============================================================================ +# STEP 6: VERIFY +# ============================================================================ +log "" +log "=== STEP 6/6: Verification ===" + +# Check PG version +PG_VERSION=$($KUBECTL exec -n "$NAMESPACE" "$NEW_POD" -c "$CONTAINER" -- \ + /usr/pgsql-18/bin/psql -U postgres -t -c "SELECT version();" 2>/dev/null | head -1) +log "PostgreSQL version: $PG_VERSION" + +# Check database exists +DB_EXISTS=$($KUBECTL exec -n "$NAMESPACE" "$NEW_POD" -c "$CONTAINER" -- \ + /usr/pgsql-18/bin/psql -U postgres -t -c \ + "SELECT 1 FROM pg_database WHERE datname = '${DB_NAME}';" 2>/dev/null | tr -d '[:space:]') + +if [ "$DB_EXISTS" = "1" ]; then + log "Database '${DB_NAME}' exists — OK" +else + log "WARNING: Database '${DB_NAME}' not found after restore!" +fi + +# Check user exists +USER_EXISTS=$($KUBECTL exec -n "$NAMESPACE" "$NEW_POD" -c "$CONTAINER" -- \ + /usr/pgsql-18/bin/psql -U postgres -t -c \ + "SELECT 1 FROM pg_roles WHERE rolname = '${DB_USER}';" 2>/dev/null | tr -d '[:space:]') + +if [ "$USER_EXISTS" = "1" ]; then + log "User '${DB_USER}' exists — OK" +else + log "WARNING: User '${DB_USER}' not found after restore!" +fi + +log "" +log "State AFTER migration (PG 18.1):" +db_snapshot "$NEW_POD" "/usr/pgsql-18/bin" + +log "" +log "=== Migration complete ===" +log "" +log "Backup file kept at: $(pwd)/$BACKUP_FILE" +log "You can delete it once you've verified everything works." +log "" +log "If something went wrong, you can restore from the backup file" +log "by scaling down, recreating the PVC, starting with the OLD image," +log "and running:" +log " kubectl exec -i ... -- /usr/pgsql-14/bin/psql -U postgres -f - < $BACKUP_FILE" \ No newline at end of file