Skip to main content
Version: 3.9

Upgrade Keycloak v17.0 to 19.0

Starting from Keycloak v.18.x.x, the Keycloak server has been moved from the Wildfly (JBoss) Application Server to Quarkus framework and is called Keycloak.X.

There are two ways to upgrade Keycloak v.17.0.x-legacy to v.19.0.x on Kubernetes, please perform the steps described in the Prerequisites section of this tutorial, and then select a suitable upgrade strategy for your environment:

Prerequisites​

Before upgrading Keycloak, please perform the steps below:

  1. Create a backup/snapshot of the Keycloak database volume. Locate the AWS volumeID and then create its snapshot on AWS:

    • Find the PVC name attached to the Postgres pod. It can be similar to data-keycloak-postgresql-0 if the Postgres StatefulSet name is keycloak-postgresql:

      kubectl get pods keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumes[*].persistentVolumeClaim.claimName}{"\n"}'
    • Locate the PV volumeName in the data-keycloak-postgresql-0 Persistent Volume Claim:

      kubectl get pvc data-keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumeName}{"\n"}'
    • Get volumeID in the Persistent Volume:

      kubectl get pv ${pv_name} -n security -o jsonpath='{.spec.awsElasticBlockStore.volumeID}{"\n"}'
  2. Add two additional keys: password and postgres-password, to the keycloak-postgresql secret in the Keycloak namespace.

    note
    • The password key must have the same value as the postgresql-password key.
    • The postgres-password key must have the same value as the postgresql-postgres-password key.

    The latest chart for Keycloak.X does not have an option to override Postgres password and admin password keys in the secret, and it uses the Postgres defaults, therefore, a new secret scheme must be implemented:

    kubectl -n security edit secret keycloak-postgresql
    data:
    postgresql-password: XXXXXX
    postgresql-postgres-password: YYYYYY
    password: XXXXXX
    postgres-password: YYYYYY
  3. Save Keycloak StatefulSet names, for example, keycloak and keycloak-postgresql. These names will be used in the new Helm deployments:

    $ kubectl get statefulset -n security
    NAME READY AGE
    keycloak 1/1 18h
    keycloak-postgresql 1/1 18h

Upgrade Postgres Database to a Minor Release v.11.17​

To upgrade Keycloak by upgrading Postgres Database to a minor release v.11.17, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:

Delete Keycloak Resources​

  1. Delete Keycloak and Postgres StatefulSets:

    kubectl delete statefulset keycloak keycloak-postgresql -n security
  2. Delete the Keycloak Ingressobject, to prevent hostname duplication issues:

    kubectl delete ingress keycloak -n security

Upgrade Keycloak​

  1. Make sure the Keycloak chart repository is added:

    helm repo add codecentric https://codecentric.github.io/helm-charts
    helm repo update
  2. Create values for Keycloak:

    note

    Since the Keycloak.X release, Keycloak and Postgres database charts are separated. Upgrade Keycloak, and then install the Postgres database.

    note
    • nameOverride: "keycloak" sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet.

    • Change Ingress host name to the Keycloak host name.

    • hostname: keycloak-postgresql is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql.

    • "/opt/keycloak/bin/kc.sh start --auto-build" was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.

    • Optionally, use the following command for applying the old Keycloak theme:

      bin/kc.sh start --features-disabled=admin2
    View: keycloak-values.yaml
    nameOverride: "keycloak"

    replicas: 1

    # Deploy the latest verion
    image:
    tag: "19.0.1"

    # start: create OpenShift realm which is required by KubeRocketCI
    extraInitContainers: |
    - name: realm-provider
    image: busybox
    imagePullPolicy: IfNotPresent
    command:
    - sh
    args:
    - -c
    - |
    echo '{"realm": "openshift","enabled": true}' > /opt/keycloak/data/import/openshift.json
    volumeMounts:
    - name: realm
    mountPath: /opt/keycloak/data/import

    extraVolumeMounts: |
    - name: realm
    mountPath: /opt/keycloak/data/import

    extraVolumes: |
    - name: realm
    emptyDir: {}

    command:
    - "/opt/keycloak/bin/kc.sh"
    - "--verbose"
    - "start"
    - "--http-enabled=true"
    - "--http-port=8080"
    - "--hostname-strict=false"
    - "--hostname-strict-https=false"
    - "--spi-events-listener-jboss-logging-success-level=info"
    - "--spi-events-listener-jboss-logging-error-level=warn"
    - "--import-realm"

    extraEnv: |
    - name: KC_PROXY
    value: "passthrough"
    - name: KEYCLOAK_ADMIN
    valueFrom:
    secretKeyRef:
    name: keycloak-admin-creds
    key: username
    - name: KEYCLOAK_ADMIN_PASSWORD
    valueFrom:
    secretKeyRef:
    name: keycloak-admin-creds
    key: password
    - name: JAVA_OPTS_APPEND
    value: >-
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=50.0
    -Djava.awt.headless=true
    -Djgroups.dns.query={{ include "keycloak.fullname" . }}-headless

    # This block should be uncommented if you install Keycloak on Kubernetes
    ingress:
    enabled: true
    annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/affinity: cookie
    rules:
    - host: keycloak.<ROOT_DOMAIN>
    paths:
    - path: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/'
    pathType: Prefix

    # This block should be uncommented if you set Keycloak to OpenShift and change the host field
    # route:
    # enabled: false
    # # Path for the Route
    # path: '/'
    # # Host name for the Route
    # host: "keycloak.<ROOT_DOMAIN>"
    # # TLS configuration
    # tls:
    # enabled: true

    resources:
    limits:
    memory: "2048Mi"
    requests:
    cpu: "50m"
    memory: "512Mi"

    # Check database readiness at startup
    dbchecker:
    enabled: true

    database:
    vendor: postgres
    existingSecret: keycloak-postgresql
    hostname: keycloak-postgresql
    port: 5432
    username: admin
    database: keycloak
  3. Upgrade the Keycloak Helm chart:

    note
    • The Helm chart is substituted with the new KeyacloakX instance.
    • Change the namespace and the values file name if required.
    helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security
    note

    If there are error messages when upgrading via Helm, make sure that StatefulSets are removed. If they are removed and the error still persists, try to add the --force flag to the Helm command:

    helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security --force

Install Postgres​

  1. Add Bitnami chart repository and update Helm repos:

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm repo update
  2. Create values for Postgres:

    note
    • Postgres v.11 and Postgres v.14.5 are not compatible.
    • Postgres image will be upgraded to a minor release v.11.17.
    • fullnameOverride: "keycloak-postgresql" sets the name of the Postgres StatefulSet. It must be the same as in the previous StatefulSet.
    View: postgres-values.yaml
    fullnameOverride: "keycloak-postgresql"

    # PostgreSQL read only replica parameters
    readReplicas:
    # Number of PostgreSQL read only replicas
    replicaCount: 1

    global:
    postgresql:
    auth:
    username: admin
    existingSecret: keycloak-postgresql
    secretKeys:
    adminPasswordKey: postgres-password
    userPasswordKey: password
    database: keycloak

    image:
    registry: docker.io
    repository: bitnami/postgresql
    tag: 11.17.0-debian-11-r3

    auth:
    existingSecret: keycloak-postgresql
    secretKeys:
    adminPasswordKey: postgres-password
    userPasswordKey: password

    primary:
    persistence:
    enabled: true
    size: 3Gi
    # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL
    # (the code is given below).
    # If the default StorageClass will be used - change "gp2-retain" to "gp2"
    storageClass: "gp2-retain"
  3. Install the Postgres database chart:

    note

    Change the namespace and the values file name if required.

    helm install postgresql bitnami/postgresql \
    --version 11.7.6 \
    --values postgres-values.yaml \
    --namespace security
  4. Log in to Keycloak and check that everything works as expected.

Clean and Analyze Database​

Optionally, run the vacuumdb application on the database, to recover space occupied by "dead tuples" in the tables, analyze the contents of database tables, and collect statistics for PostgreSQL query engine to improve performance:

PGPASSWORD="${postgresql_postgres-password}" vacuumdb --analyze --verbose -d keycloak -U postgres

For all databases, run the following command:

PGPASSWORD="${postgresql_postgres-password}" vacuumdb --analyze --verbose --all -U postgres

Migrate Postgres Database From Postgres v.11.x to v.14.5​

info

There is a Postgres database migration script at the end of this tutorial. Please read the section below before using the script.

To upgrade Keycloak by migrating Postgres database from Postgres v.11.x to v.14.5, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:

Export Postgres Databases​

  1. Log in to the current Keycloak Postgres pod and create a logical backup of all roles and databases using the pg_dumpall application. If there is no access to the Postgres Superuser, backup the Keycloak database with the pg_dump application:

    note
    • The secret key postgresql-postgres-password is for the postgres Superuser and postgresql-password is for admin user. The admin user is indicated by default in the Postgres Helm chart.
      The admin user may not have enough permissions to dump all Postgres databases and roles, so the preferred option for exporting all objects is using the pg_dumpall tool with the postgres Superuser.
    • If the PGPASSWORD variable is not specified before using the pg_dumpall tool, you will be prompted to enter a password for each database during the export.
    • If the -l keycloak parameter is specified, pg_dumpall will connect to the keycloak database for dumping global objects and discovering what other databases should be dumped. By default, pg_dumpall will try to connect to postgres or template1 databases. This parameter is optional.
    • The pg_dumpall --clean option adds SQL commands to the dumped file for dropping databases before recreating them during import, as well as DROP commands for roles and tablespaces (pg_dump also has this option). If the --clean parameter is specified, connect to the postgres database initially during import via psql. The psql script will attempt to drop other databases immediately, and that will fail for the database you are connected to. This flag is optional, and it is not included into this tutorial.
    PGPASSWORD="${postgresql_postgres-password}" pg_dumpall -h localhost -p 5432 -U postgres -l keycloak > /tmp/keycloak_wildfly_db_dump.sql
    note

    If there is no working password for the postgres Superuser, try the admin user using the pg_dump tool to export the keycloak database without global roles:

    PGPASSWORD="${postgresql_password}" pg_dump -h localhost -p 5432 -U admin -d keycloak > /tmp/keycloak_wildfly_db_dump.sql
    info

    Double-check that the contents of the dumped file is not empty. It usually contains more than 4000 lines.

  2. Copy the file with the database dump to a local machine. Since tar may not be present in the pod and kubectl cp will not work without tar, use the following command:

    kubectl exec -n security ${postgresql_pod} -- cat /tmp/keycloak_wildfly_db_dump.sql  > keycloak_wildfly_db_dump.sql
    note

    Please find below the alternative commands for exporting the database to the local machine without copying the file to a pod for Postgres and admin users:

    kubectl exec -n security ${postgresql_pod} "--" sh -c "PGPASSWORD='"${postgresql_postgres-password}"' pg_dumpall -h localhost -p 5432 -U postgres" > keycloak_wildfly_db_dump.sql
    kubectl exec -n security ${postgresql_pod} "--" sh -c "PGPASSWORD='"${postgresql_password}"' pg_dump -h localhost -p 5432 -U admin -d keycloak" > keycloak_wildfly_db_dump.sql
  3. Delete the dumped file from the pod for security reasons:

    kubectl exec -n security ${postgresql_pod} "--" sh -c "rm /tmp/keycloak_wildfly_db_dump.sql"

Delete Keycloak Resources​

  1. Delete all previous Keycloak resources along with the Postgres database and keycloak StatefulSets, Ingress, and custom resources via Helm, or via the tool used for their deployment.

    helm list -n security
    helm delete keycloak -n security
    warning

    Don't delete the whole namespace. Keep the keycloak-postgresql and keycloak-admin-creds secrets.

  2. Delete the volume in AWS, from which a snapshot has been created. Then delete the PVC:

    kubectl delete pvc data-keycloak-postgresql-0 -n security

Install Postgres​

  1. Add Bitnami chart repository and update Helm repos:

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm repo update
  2. Create Postgres values:

    note

    fullnameOverride: "keycloak-postgresql" sets the name of the Postgres StatefulSet. It must be same as in the previous StatefulSet.

    View: postgres-values.yaml
    nameOverride: "keycloak-postgresql"

    # PostgreSQL read only replica parameters
    readReplicas:
    # Number of PostgreSQL read only replicas
    replicaCount: 1

    global:
    postgresql:
    auth:
    username: admin
    existingSecret: keycloak-postgresql
    secretKeys:
    adminPasswordKey: postgres-password
    userPasswordKey: password
    database: keycloak

    auth:
    existingSecret: keycloak-postgresql
    secretKeys:
    adminPasswordKey: postgres-password
    userPasswordKey: password

    primary:
    persistence:
    enabled: true
    size: 3Gi
    # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL
    # (the code is given below).
    # If the default StorageClass will be used - change "gp2-retain" to "gp2"
    storageClass: "gp2-retain"
  3. Install the Postgres database:

    note

    Change the namespace and the values file name if required.

    helm install postgresql bitnami/postgresql \
    --version 11.7.6 \
    --values postgres-values.yaml \
    --namespace security
  4. Wait for the database to be ready.

Import Postgres Databases​

  1. Upload the database dump to the new Keycloak Postgres pod:

    cat keycloak_wildfly_db_dump.sql | kubectl exec -i -n security ${postgresql_pod} "--" sh -c "cat > /tmp/keycloak_wildfly_db_dump.sql"
    warning

    Database import must be done before deploying Keycloak, because Keycloak will write its own data to the database during the start, and the import will partially fail.
    If that happened, scale down the keycloak StatefulSet, and try to drop the Keycloak database in the Postgres pod:

    dropdb -i -e keycloak -p 5432 -h localhost -U postgres

    If there still are some conflicting objects like roles, drop them via the DROP ROLE command.

    If the previous steps do not help, downscale the Keycloak and Postgres StatefulSets and delete the attached PVC (save the volumeID before removing), and delete the volume on AWS if using gp2-retain. In case of using gp2, the volume will be deleted automatically after removing PVC. After that, redeploy the Postgres database, so that the new PVC is automatically created.

  2. Import the SQL dump file to the Postgres database cluster:

    info

    Since the databases were exported in the sql format, the psql tool will be used to restore (reload) them. pg_restore does not support this plain-text format.

    • If the entire Postgres database cluster was migrated with the postgres Superuser using pg_dumpall, use the import command without indicating the database:

      psql -U postgres -f /tmp/keycloak_wildfly_db_dump.sql
    • If the database was migrated with the admin user using pg_dump, the postgres Superuser still can be used to restore it, but, in this case, a database must be indicated:

      warning

      If the database name was not indicated during the import for the file dumped with pg_dump, the psql tool will import this database to a default Postgres database called postgres.

      psql -U postgres -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql
    • If the postgres Superuser is not accessible in the Postgres pod, run the command under the admin or any other user that has the database permissions. In this case, indicate the database as well:

      psql -U admin -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql
  3. After a successful import, delete the dump file from the pod for security reasons:

    kubectl exec -n security ${postgresql_pod} "--" sh -c "rm /tmp/keycloak_wildfly_db_dump.sql"
    note

    Please find below the alternative commands for importing the database from the local machine to the pod without storing the backup on a pod for postgres or admin users:

    cat "keycloak_wildfly_db_dump.sql" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" sh -c "cat | PGPASSWORD='"${postgresql_superuser_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}""
    cat "keycloak_wildfly_db_dump.sql" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" sh -c "cat | PGPASSWORD='"${postgresql_superuser_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}""
    cat "keycloak_wildfly_db_dump.sql" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" sh -c "cat | PGPASSWORD='"${postgresql_admin_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}""

Install Keycloak​

  1. Make sure the Keycloak chart repository is added:

    helm repo add codecentric https://codecentric.github.io/helm-charts
    helm repo update
  2. Create Keycloak values:

    note
    • nameOverride: "keycloak" sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet.

    • Change Ingress host name to the Keycloak host name.

    • hostname: keycloak-postgresql is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql.

    • "/opt/keycloak/bin/kc.sh start --auto-build" was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.

    • Optionally, use the following command for applying the old Keycloak theme:

      bin/kc.sh start --features-disabled=admin2
    info

    Automatic database migration will start after the Keycloak installation.

    View: keycloak-values.yaml
    nameOverride: "keycloak"

    replicas: 1

    # Deploy the latest version
    image:
    tag: "19.0.1"

    # start: create OpenShift realm which is required by KubeRocketCI
    extraInitContainers: |
    - name: realm-provider
    image: busybox
    imagePullPolicy: IfNotPresent
    command:
    - sh
    args:
    - -c
    - |
    echo '{"realm": "openshift","enabled": true}' > /opt/keycloak/data/import/openshift.json
    volumeMounts:
    - name: realm
    mountPath: /opt/keycloak/data/import

    extraVolumeMounts: |
    - name: realm
    mountPath: /opt/keycloak/data/import

    extraVolumes: |
    - name: realm
    emptyDir: {}

    command:
    - "/opt/keycloak/bin/kc.sh"
    - "--verbose"
    - "start"
    - "--http-enabled=true"
    - "--http-port=8080"
    - "--hostname-strict=false"
    - "--hostname-strict-https=false"
    - "--spi-events-listener-jboss-logging-success-level=info"
    - "--spi-events-listener-jboss-logging-error-level=warn"
    - "--import-realm"

    extraEnv: |
    - name: KC_PROXY
    value: "passthrough"
    - name: KEYCLOAK_ADMIN
    valueFrom:
    secretKeyRef:
    name: keycloak-admin-creds
    key: username
    - name: KEYCLOAK_ADMIN_PASSWORD
    valueFrom:
    secretKeyRef:
    name: keycloak-admin-creds
    key: password
    - name: JAVA_OPTS_APPEND
    value: >-
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=50.0
    -Djava.awt.headless=true
    -Djgroups.dns.query={{ include "keycloak.fullname" . }}-headless

    # This block should be uncommented if you install Keycloak on Kubernetes
    ingress:
    enabled: true
    annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/affinity: cookie
    rules:
    - host: keycloak.<ROOT_DOMAIN>
    paths:
    - path: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/'
    pathType: Prefix

    # This block should be uncommented if you set Keycloak to OpenShift and change the host field
    # route:
    # enabled: false
    # # Path for the Route
    # path: '/'
    # # Host name for the Route
    # host: "keycloak.<ROOT_DOMAIN>"
    # # TLS configuration
    # tls:
    # enabled: true

    resources:
    limits:
    memory: "2048Mi"
    requests:
    cpu: "50m"
    memory: "512Mi"

    # Check database readiness at startup
    dbchecker:
    enabled: true

    database:
    vendor: postgres
    existingSecret: keycloak-postgresql
    hostname: keycloak-postgresql
    port: 5432
    username: admin
    database: keycloak
  3. Deploy Keycloak:

    note

    Change the namespace and the values file name if required.

    helm install keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security
  4. Log in to Keycloak and check if everything has been imported correctly.

Clean and Analyze Database​

Optionally, run the vacuumdb application on the database, to analyze the contents of database tables and collect statistics for the Postgres query optimizer:

PGPASSWORD="${postgresql_postgres-password}" vacuumdb --analyze --verbose -d keycloak -U postgres

For all databases, run the following command:

PGPASSWORD="${postgresql_postgres-password}" vacuumdb --analyze --verbose --all -U postgres

Postgres Database Migration Script​

info

Please read the Migrate Postgres Database From Postgres v.11.x to v.14.5 section of this tutorial before using the script.

note
  • The kubectl tool is required for using this script.
  • This script will likely work for any other Postgres database besides Keycloak after some adjustments. It queries the pg_dump, pg_dumpall, psql, and vacuumdb commands under the hood.

The following script can be used for exporting and importing Postgres databases as well as optimizing them with the vacuumdb application. Please examine the code and make the adjustments if required.

  • By default, the following command exports Keycloak Postgres databases from a Kubernetes pod to a local machine:

    ./script.sh

    After running the command, please follow the prompt.

  • To import a database backup to a newly created Postgres Kubernetes pod, pass a database dump sql file to the script:

      ./script.sh path-to/db_dump.sql
  • The -h flag prints help, and -c|-v runs the vacuumdb garbage collector and analyzer.

View: keycloak_db_migration.sh
#!/bin/bash

# set -x

db_migration_help(){
echo "Keycloak Postgres database migration"
echo
echo "Usage:"
echo "------------------------------------------"
echo "Export Keycloak Postgres database from pod"
echo "Run without parameters:"
echo " $0"
echo "------------------------------------------"
echo "Import Keycloak Postgres database to pod"
echo "Pass filename to script:"
echo " $0 path/to/db_dump.sql"
echo "------------------------------------------"
echo "Additional options: "
echo " $0 [OPTIONS...]"
echo "Options:"
echo "h Print Help."
echo "c|v Run garbage collector and analyzer."
}

keycloak_ns(){
printf '%s\n' 'Enter keycloak namespace: '
read -r keycloak_namespace

if [ -z "${keycloak_namespace}" ]; then
echo "Don't skip namespace"
exit 1
fi
}

postgres_pod(){
printf '%s\n' 'Enter postgres pod name: '
read -r postgres_pod_name

if [ -z "${postgres_pod_name}" ]; then
echo "Don't skip pod name"
exit 1
fi
}

postgres_user(){
printf '%s\n' 'Enter postgres username: '
printf '%s' "Skip to use [postgres] superuser: "
read -r postgres_username

if [ -z "${postgres_username}" ]; then
postgres_username='postgres'
fi
}

pgdb_host_info(){
database_name='keycloak'
db_host='localhost'
db_port='5432'
}

postgresql_admin_pass(){
postgresql_password='POSTGRES_PASSWORD'
postgresql_admin_password="$(kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "printenv ${postgresql_password}")"
}

postgresql_su_pass(){
postgresql_postgres_password='POSTGRES_POSTGRES_PASSWORD'
postgresql_superuser_password="$(kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "printenv ${postgresql_postgres_password}")"

if [ -z "${postgresql_superuser_password}" ]; then
echo "SuperUser password variable does not exist. Using user password instead..."
postgresql_admin_pass
postgresql_superuser_password="${postgresql_admin_password}"
fi
}

keycloak_pgdb_export(){
current_cluster="$(kubectl config current-context | tr -dc '[:alnum:]-')"
exported_db_name="keycloak_db_dump_${current_cluster}_${keycloak_namespace}_${postgres_username}_$(date +"%Y%m%d%H%M").sql"

if [ "${postgres_username}" == 'postgres' ]; then
# call a function to get a pass for postgres user
postgresql_su_pass
kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "PGPASSWORD='"${postgresql_superuser_password}"' pg_dumpall -h "${db_host}" -p "${db_port}" -U "${postgres_username}"" > "${exported_db_name}"
else
# call a function to get a pass for admin user
postgresql_admin_pass
kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "PGPASSWORD='"${postgresql_admin_password}"' pg_dump -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}"" > "${exported_db_name}"
fi

separate_lines="---------------"

if [ ! -s "${exported_db_name}" ]; then
rm -f "${exported_db_name}"
echo "${separate_lines}"
echo "Something went wrong. The database dump file is empty and was not saved."
else
echo "${separate_lines}"
grep 'Dumped' "${exported_db_name}" | sort -u
echo "Database has been exported to $(pwd)/${exported_db_name}"
fi
}

keycloak_pgdb_import(){
echo "Preparing Import"
echo "----------------"

if [ ! -f "$1" ]; then
echo "The file $1 does not exist."
exit 1
fi

keycloak_ns
postgres_pod
postgres_user
pgdb_host_info

if [ "${postgres_username}" == 'postgres' ]; then
# restore full backup with all databases and roles as superuser or a single database
postgresql_su_pass
if [ -n "$(cat "$1" | grep 'CREATE ROLE')" ]; then
cat "$1" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "cat | PGPASSWORD='"${postgresql_superuser_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}""
else
cat "$1" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "cat | PGPASSWORD='"${postgresql_superuser_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}""
fi
else
# restore a single database
postgresql_admin_pass
cat "$1" | kubectl exec -i -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "cat | PGPASSWORD='"${postgresql_admin_password}"' psql -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}""
fi
}

vacuum_pgdb(){
echo "Preparing garbage collector and analyzer"
echo "----------------------------------------"

keycloak_ns
postgres_pod
postgres_user
pgdb_host_info

if [ "${postgres_username}" == 'postgres' ]; then
postgresql_su_pass
kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "PGPASSWORD='"${postgresql_superuser_password}"' vacuumdb --analyze --all -h "${db_host}" -p "${db_port}" -U "${postgres_username}""
else
postgresql_admin_pass
kubectl exec -n "${keycloak_namespace}" "${postgres_pod_name}" "--" \
sh -c "PGPASSWORD='"${postgresql_admin_password}"' vacuumdb --analyze -h "${db_host}" -p "${db_port}" -U "${postgres_username}" -d "${database_name}""
fi
}

while [ "$#" -eq 1 ]; do
case "$1" in
-h | --help)
db_migration_help
exit 0
;;
-c | --clean | -v | --vacuum)
vacuum_pgdb
exit 0
;;
--)
break
;;
-*)
echo "Invalid option '$1'. Use -h|--help to see the valid options" >&2
exit 1
;;
*)
keycloak_pgdb_import "$1"
exit 0
;;
esac
shift
done

if [ "$#" -gt 1 ]; then
echo "Please pass a single file to the script"
exit 1
fi

echo "Preparing Export"
echo "----------------"
keycloak_ns
postgres_pod
postgres_user
pgdb_host_info
keycloak_pgdb_export