apiVersion: v1
kind: ConfigMap
metadata:
  name: base-kubegres-config
  namespace: default

# This is the base configuration for all Kubegres resources. It is automatically created by the Kubernetes operator.
# It is created once for each namespace and it applies to all Kubegres resources on that namespace.
#
# Please do not remove any config and script in this file because they are referenced in the resources configured by the operator.
#
# If you would like to override shared configs by all Kubegres resources, this is the right place to edit.
#
# If you would like to override a configuration for a specific Kubegres resource only, create your custom configMap
# and there you can add any of the following data keys which will override the base one:
# - postgres.conf
# - primary_init_script.sh
# - backup_database.sh
# - pg_hba.conf
# In your Kubegres resource file, set the name of your custom configMap in 'spec.customConfig'.
#
# Note that, in your custom configMap, you cannot override these data keys:
# - primary_create_replication_role.sh
# - copy_primary_data_to_replica.sh
# - promote_replica_to_primary.sh
# We highly recommend that you do not modify these 3 data keys as it could break the operator.

data:

  # This is the standard Postgres config applying to Primary and Replica servers.
  # You can edit this config as it suits your requirement.
  #
  # Be careful with the value you set for 'listen_addresses' because you could break the operator.
  #
  # You cannot set a value for the config "wal_level=replica" because it is passed as an argument to the PostgreSql container.
  # This restriction is part of the design.
  #
  # If you edit the config in this file, your changes will apply to all Kubegres resources.
  # Alternatively, you can override it for your Kubegres resource. To do so, create a custom configMap and in your
  # Kubegres resource file set its name in 'spec.customConfig'. In your ConfigFile, copy the contents of this script
  # and edit it as its suits your requirement.
  #
  postgres.conf: |

    # Replication configs
    listen_addresses = '*'
    max_wal_senders = 10
    max_connections = 100
    shared_buffers = 128MB

    # Logging
    #log_destination = 'stderr,csvlog'
    #logging_collector = on
    #log_directory = 'pg_log'
    #log_filename= 'postgresql-%Y-%m-%d_%H%M%S.log'


  # This bash script is run once, the 1st time a Primary PostgreSql container is created. It is run in the Primary container only.
  #
  # You can edit this script as it suits your requirement. For example, you could add SQL statements to create specific
  # database(s), user(s), grant accesses, etc...
  # See the commented examples in the script below.
  #
  # This script will be located in the container folder "/docker-entrypoint-initdb.d"
  # That folder is referenced in the Postgres Docker page: https://hub.docker.com/_/postgres
  #
  # If you edit the script in this file, your changes will apply to all Kubegres resources.
  # Alternatively, you can override it for your Kubegres resource. To do so, create a custom configMap and in your
  # Kubegres resource file set its name in 'spec.customConfig'. In your ConfigFile, copy the contents of this script
  # and edit it as its suits your requirement.
  #
  primary_init_script.sh: |
    #!/bin/bash
    set -e

    # This script assumes that the env-var $POSTGRES_MYAPP_PASSWORD contains the password of the custom user to create.
    # You can add any env-var in your Kubegres resource config YAML.

    #dt=$(date '+%d/%m/%Y %H:%M:%S');
    #echo "$dt - Running init script the 1st time Primary PostgreSql container is created...";

    #customDatabaseName="my_app"
    #customUserName="my_username"

    #echo "$dt - Running: psql -v ON_ERROR_STOP=1 --username $POSTGRES_USER --dbname $POSTGRES_DB ...";

    #psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    #CREATE DATABASE $customDatabaseName;
    #CREATE USER $customUserName WITH PASSWORD '$POSTGRES_MYAPP_PASSWORD';
    #\connect $customDatabaseName;
    #CREATE TABLE account(user_id serial PRIMARY KEY, username VARCHAR (50) NOT NULL);
    #INSERT INTO account VALUES (1, 'username1');
    #INSERT INTO account VALUES (2, 'username2');
    #GRANT ALL PRIVILEGES ON DATABASE "$customDatabaseName" to $customUserName;
    #GRANT ALL ON "account" to $customUserName;
    #EOSQL

    #echo "$dt - Init script is completed";


  # If you enabled back-up for your Kubegres resource, this bash script backs-up a Postgres database into a given destination-volume.
  # It is triggered to run regularly by a Kubernetes Cronjob.
  #
  # It runs in a Replica container in order to not impact the performance of Primary. If there is no Replica then it runs in a Primary container.
  #
  # You can edit this script as it suits your requirement.
  #
  # If you edit the script in this file, your changes will apply to all Kubegres resources.
  # Alternatively, you can override it for your Kubegres resource. To do so, create a custom configMap and in your
  # Kubegres resource file set its name in 'spec.customConfig'. In your ConfigFile, copy the contents of this script
  # and edit it as its suits your requirement.
  #
  backup_database.sh: |
    #!/bin/bash
    set -e

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    fileDt=$(date '+%d_%m_%Y_%H_%M_%S');
    backUpFileName="$KUBEGRES_RESOURCE_NAME-backup-$fileDt.gz"
    backUpFilePath="$BACKUP_DESTINATION_FOLDER/$backUpFileName"

    echo "$dt - Starting DB backup of Kubegres resource $KUBEGRES_RESOURCE_NAME into file: $backUpFilePath";
    echo "$dt - Running: pg_dumpall -h $BACKUP_SOURCE_DB_HOST_NAME -U postgres -c | gzip > $backUpFilePath"

    pg_dumpall -h $BACKUP_SOURCE_DB_HOST_NAME -U postgres -c | gzip > $backUpFilePath

    if [ $? -ne 0 ]; then
      rm $backUpFilePath
      echo "Unable to execute a BackUp. Please check DB connection settings"
      exit 1
    fi

    echo "$dt - DB backup completed for Kubegres resource $KUBEGRES_RESOURCE_NAME into file: $backUpFilePath";


  # This is the standard Postgres host-based authentication (hba) config applying to Primary and Replica servers.
  # https://www.postgresql.org/docs/current/auth-pg-hba-conf.html
  #
  # You can edit this config as it suits your requirement.
  # However, please be careful if you change the rules below for 'replication' database & role
  # as it could break PostgreSql's ability to replicate.
  #
  # If you edit the config in this file, your changes will apply to all Kubegres resources.
  # Alternatively, you can override it for your Kubegres resource. To do so, create a custom configMap and in your
  # Kubegres resource file set its name in 'spec.customConfig'. In your ConfigFile, copy the contents of this script
  # and edit it as its suits your requirement.
  #
  pg_hba.conf: |
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    # Replication connections by a user with the replication privilege
    host    replication     replication     all                     md5
    # As long as it is authenticated, all connections allowed except from "0.0.0.0/0"
    local   all             all                                     md5
    host    all             all             all                     md5
    host    all             all             0.0.0.0/0               reject


  # -----------------------------------------------------------------------------------------------
  # From here, you cannot override the configs below in a custom ConfigMap
  # ------------


  # This script creates a replication role in charge of replicating data from Primary to Replica PostgreSql instances.
  # It is executed once, the 1st time a Primary PostgreSql container is created.
  # It is run in Primary container.
  #
  # If you modify this script, there is a risk of breaking the operator.
  #
  # This script will be located in the folder "/docker-entrypoint-initdb.d"
  # That folder is referenced in the Postgres Docker page: https://hub.docker.com/_/postgres
  #
  primary_create_replication_role.sh: |
    #!/bin/bash
    set -e

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    echo "$dt - Creating replication role...";
    echo "$dt - Running: psql -v ON_ERROR_STOP=1 --username $POSTGRES_USER --dbname $POSTGRES_DB ... CREATE ROLE replication WITH REPLICATION PASSWORD ... GRANT EXECUTE ON FUNCTION pg_promote TO replication;";

    psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE ROLE replication WITH REPLICATION PASSWORD '$POSTGRES_REPLICATION_PASSWORD' LOGIN;
    GRANT EXECUTE ON FUNCTION pg_promote TO replication;
    EOSQL

    echo "$dt - Replication role created";


  # This script replicates data from the Primary PostgreSql to the Replica database.
  # It is executed once, the 1st time a Replica PostgreSql container is created.
  # It is run in Replica containers.
  #
  # If you modify this script, there is a risk of breaking the operator.
  #
  # This script will be located in the folder "/tmp"
  #
  copy_primary_data_to_replica.sh: |
    #!/bin/bash
    set -e

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    echo "$dt - Attempting to copy Primary DB to Replica DB...";

    if [ -z "$(ls -A $PGDATA)" ]; then

        echo "$dt - Copying Primary DB to Replica DB folder: $PGDATA";
        echo "$dt - Running: pg_basebackup -R -h $PRIMARY_HOST_NAME -D $PGDATA -P -U replication;";

        pg_basebackup -R -h $PRIMARY_HOST_NAME -D $PGDATA -P -U replication;
        chown -R postgres:postgres $PGDATA;

        echo "$dt - Copy completed";

    else
        echo "$dt - Skipping copy from Primary DB because Replica DB already exists";
    fi


  # This script promotes a Replica to a Primary by creating a trigger-file signaling PostgreSql to start the promotion process.
  # It is executed once, when a Replica is set to become a Primary.
  # It is run in a selected Replica container by the operator.
  #
  # If you modify this script, there is a risk of breaking the operator.
  #
  # This script will be located in the folder "/tmp"
  promote_replica_to_primary.sh: |
    #!/bin/bash
    set -e

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    echo "$dt - Attempting to promote a Replica PostgreSql to Primary...";

    standbyFilePath="$PGDATA/standby.signal"

    if [ ! -f "$standbyFilePath" ]; then
      echo "$dt - Skipping as this PostgreSql is already a Primary since the file '$standbyFilePath' does not exist."
      exit 0
    fi

    promotionTriggerFilePath="$PGDATA/promote_replica_to_primary.log"

    if [ -f "$promotionTriggerFilePath" ]; then
      echo "$dt - Skipping as the promotion trigger file '$promotionTriggerFilePath' already exists"
      exit 0
    fi

    echo "$dt - Promoting by creating the promotion trigger file: '$promotionTriggerFilePath'"
    touch $promotionTriggerFilePath

