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:
- Upgrade Postgres database to a minor release v.11.17
- Migrate Postgres database from Postgres v.11.x to v.14.5
Prerequisites βοΈ
Before upgrading Keycloak, please perform the steps below:
-
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 todata-keycloak-postgresql-0
if the PostgresStatefulSet
name iskeycloak-postgresql
:
-
Locate the
PV
volumeName
in thedata-keycloak-postgresql-0
Persistent Volume Claim:
-
Get
volumeID
in the Persistent Volume:
-
-
Add two additional keys:
password
andpostgres-password
, to thekeycloak-postgresql
secret in the Keycloak namespace.Note
- The
password
key must have the same value as thepostgresql-password
key. - The
postgres-password
key must have the same value as thepostgresql-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:
- The
-
Save Keycloak
StatefulSet
names, for example,keycloak
andkeycloak-postgresql
. These names will be used in the new Helm deployments:
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βοΈ
-
Delete
Keycloak
andProstgres
StatefulSets
: -
Delete the Keycloak
Ingress
object, to prevent hostname duplication issues:
Upgrade KeycloakβοΈ
-
Make sure the Keycloak chart repository is added:
-
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 previousStatefulSet
.- 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:
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 EDP 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
-
Upgrade the Keycloak Helm chart:
Note
- The Helm chart is substituted with the new Keyacloak.X 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:
Install PostgresβοΈ
-
Add Bitnami chart repository and update Helm repos:
-
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 previousStatefulSet
.
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"
-
Install the Postgres database chart:
Note
Change the namespace and the values file name if required.
-
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:
For all databases, run the following command: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βοΈ
-
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 thepostgres
Superuser andpostgresql-password
is foradmin
user. Theadmin
user is indicated by default in the Postgres Helm chart.
Theadmin
user may not have enough permissions to dump all Postgres databases and roles, so the preferred option for exporting all objects is using thepg_dumpall
tool with thepostgres
Superuser. - If the
PGPASSWORD
variable is not specified before using thepg_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 thekeycloak
database for dumping global objects and discovering what other databases should be dumped. By default,pg_dumpall
will try to connect topostgres
ortemplate1
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 asDROP
commands for roles and tablespaces (pg_dump
also has this option). If the--clean
parameter is specified, connect to thepostgres
database initially during import viapsql
. Thepsql
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 theadmin
user using the pg_dump tool to export thekeycloak
database without global roles:Info
Double-check that the contents of the dumped file is not empty. It usually contains more than 4000 lines.
- The secret key
-
Copy the file with the database dump to a local machine. Since
tar
may not be present in the pod andkubectl cp
will not work withouttar
, 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
-
Delete the dumped file from the pod for security reasons:
Delete Keycloak ResourcesβοΈ
-
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.Warning
Don't delete the whole namespace. Keep the
keycloak-postgresql
andkeycloak-admin-creds
secrets. -
Delete the volume in AWS, from which a snapshot has been created. Then delete the PVC:
Install PostgresβοΈ
-
Add Bitnami chart repository and update Helm repos:
-
Create Postgres values:
Note
fullnameOverride: "keycloak-postgresql"
sets the name of the Postgres StatefulSet. It must be same as in the previousStatefulSet
.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"
-
Install the Postgres database:
Note
Change the namespace and the values file name if required.
-
Wait for the database to be ready.
Import Postgres DatabasesβοΈ
-
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 keycloakStatefulSet
, and try to drop the Keycloak database in the Postgres pod: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 attachedPVC
(save thevolumeID
before removing), and delete the volume on AWS if usinggp2-retain
. In case of usinggp2
, the volume will be deleted automatically after removing PVC. After that, redeploy the Postgres database, so that the newPVC
is automatically created. -
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 usingpg_dumpall
, use the import command without indicating the database:
-
If the database was migrated with the
admin
user usingpg_dump
, thepostgres
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
, thepsql
tool will import this database to a default Postgres database calledpostgres
.
-
If the
postgres
Superuser is not accessible in the Postgres pod, run the command under theadmin
or any other user that has the database permissions. In this case, indicate the database as well:
-
-
After a successful import, delete the dump file from the pod for security reasons:
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
oradmin
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βοΈ
-
Make sure the Keycloak chart repository is added:
-
Create Keycloak values:
Note
nameOverride: "keycloak"
sets the name of the Keycloak pod. It must be the same Keycloak name as in the previousStatefulSet
.- 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:
Info
Automatic database migration will start after the Keycloak installation.
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 EDP 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
-
Deploy Keycloak:
Note
Change the namespace and the values file name if required.
-
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:
For all databases, run the following command: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
, andvacuumdb
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 thevacuumdb
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