Add postgresql backing (#119)

* Add postgresql backing

Signed-off-by: Sam Winterton <sam@winterton.info>

Co-authored-by: Sam Winterton <sam@winterton.info>
This commit is contained in:
Sam Winterton 2022-05-09 22:20:38 +08:00 committed by Bitnami Containers
parent 8b00e82324
commit 1ad781b237
11 changed files with 698 additions and 20 deletions

View File

@ -30,7 +30,7 @@ RUN /opt/bitnami/scripts/mysql-client/postunpack.sh
ENV APP_VERSION="8.0.0" \
BITNAMI_APP_NAME="jasperreports" \
JAVA_HOME="/opt/bitnami/java" \
PATH="/opt/bitnami/java/bin:/opt/bitnami/common/bin:/opt/bitnami/tomcat/bin:/opt/bitnami/mysql/bin:/opt/bitnami/git/bin:$PATH"
PATH="/opt/bitnami/java/bin:/opt/bitnami/common/bin:/opt/bitnami/tomcat/bin:/opt/bitnami/mysql/bin:/opt/bitnami/postgresql/bin:/opt/bitnami/git/bin:$PATH"
EXPOSE 8009 8080 8443

View File

@ -74,7 +74,7 @@ export PATH="${BITNAMI_ROOT_DIR}/common/bin:${PATH}"
# JasperReports persistence configuration
export JASPERREPORTS_VOLUME_DIR="${BITNAMI_VOLUME_DIR}/jasperreports"
export JASPERREPORTS_DATA_TO_PERSIST="${JASPERREPORTS_DATA_TO_PERSIST:-buildomatic/default_master.properties buildomatic/conf_source/db/mysql/db.template.properties .jrsks .jrsksp}"
export JASPERREPORTS_DATA_TO_PERSIST="${JASPERREPORTS_DATA_TO_PERSIST:-buildomatic/default_master.properties buildomatic/conf_source/db/mysql/db.template.properties buildomatic/conf_source/db/postgresql/db.template.properties .jrsks .jrsksp}"
# System users (when running with a privileged user)
export JASPERREPORTS_DAEMON_USER="tomcat"
@ -104,6 +104,7 @@ JASPERREPORTS_SMTP_PROTOCOL="${JASPERREPORTS_SMTP_PROTOCOL:-"${SMTP_PROTOCOL:-}"
export JASPERREPORTS_SMTP_PROTOCOL="${JASPERREPORTS_SMTP_PROTOCOL:-}" # only used during the first initialization
# Database configuration
export JASPERREPORTS_DATABASE_TYPE="${JASPERREPORTS_DATABASE_TYPE:-mariadb}" # only used during the first initialization
export JASPERREPORTS_DEFAULT_DATABASE_HOST="mariadb" # only used at build time
JASPERREPORTS_DATABASE_HOST="${JASPERREPORTS_DATABASE_HOST:-"${MARIADB_HOST:-}"}"
export JASPERREPORTS_DATABASE_HOST="${JASPERREPORTS_DATABASE_HOST:-$JASPERREPORTS_DEFAULT_DATABASE_HOST}" # only used during the first initialization

View File

@ -18,7 +18,9 @@ set -o pipefail
print_welcome_page
if [[ "$1" = "/opt/bitnami/scripts/tomcat/run.sh" ]]; then
/opt/bitnami/scripts/postgresql-client/setup.sh
/opt/bitnami/scripts/mysql-client/setup.sh
# For compatibility with previous Helm charts, disable Tomcat auth by default
TOMCAT_ENABLE_AUTH="${TOMCAT_ENABLE_AUTH:-no}" /opt/bitnami/scripts/tomcat/setup.sh
/opt/bitnami/scripts/jasperreports/setup.sh

View File

@ -16,7 +16,7 @@ set -o pipefail
. /opt/bitnami/scripts/libfs.sh
. /opt/bitnami/scripts/liblog.sh
# Copy default configuration file
# Copy and configure configuration file
cp "${JASPERREPORTS_CONF_DIR}/sample_conf/mysql_master.properties" "$JASPERREPORTS_CONF_FILE"
# Delete duplicate example MySQL configuration lines in the configuration file so it does not break the jasperreports_conf_set function

View File

@ -19,6 +19,13 @@ elif [[ -f /opt/bitnami/scripts/mariadb-env.sh ]]; then
. /opt/bitnami/scripts/mariadb-env.sh
fi
# Load PostgreSQL client environment for 'postgresql_remote_execute'
if [[ -f /opt/bitnami/scripts/postgresql-client-env.sh ]]; then
. /opt/bitnami/scripts/postgresql-client-env.sh
elif [[ -f /opt/bitnami/scripts/postgresql-env.sh ]]; then
. /opt/bitnami/scripts/postgresql-env.sh
fi
# Load libraries
. /opt/bitnami/scripts/libjasperreports.sh

View File

@ -13,7 +13,7 @@
. /opt/bitnami/scripts/libpersistence.sh
. /opt/bitnami/scripts/libservice.sh
# Load database library
# Load MYSQL/MariaDB database library
if [[ -f /opt/bitnami/scripts/libmysqlclient.sh ]]; then
. /opt/bitnami/scripts/libmysqlclient.sh
elif [[ -f /opt/bitnami/scripts/libmysql.sh ]]; then
@ -22,6 +22,13 @@ elif [[ -f /opt/bitnami/scripts/libmariadb.sh ]]; then
. /opt/bitnami/scripts/libmariadb.sh
fi
# Load PostgreSQL database library
if [[ -f /opt/bitnami/scripts/libpostgresqlclient.sh ]]; then
. /opt/bitnami/scripts/libpostgresqlclient.sh
elif [[ -f /opt/bitnami/scripts/libpostgresql.sh ]]; then
. /opt/bitnami/scripts/libpostgresql.sh
fi
########################
# Validate settings in JASPERREPORTS_* env vars
# Globals:
@ -68,6 +75,8 @@ jasperreports_validate() {
fi
}
check_multi_value "JASPERREPORTS_DATABASE_TYPE" "mysql mariadb postgresql"
check_empty_value "JASPERREPORTS_HOST"
check_yes_no_value "JASPERREPORTS_SKIP_BOOTSTRAP"
! is_empty_value "$JASPERREPORTS_DATABASE_HOST" && check_resolved_hostname "$JASPERREPORTS_DATABASE_HOST"
@ -105,19 +114,47 @@ jasperreports_validate() {
# None
#########################
jasperreports_configure_db() {
local db_type client_version
db_type="$JASPERREPORTS_DATABASE_TYPE"
if [[ "$db_type" = "postgresql" ]]; then
jasperreports_conf_set "dbType" "postgresql"
else
jasperreports_conf_set "dbType" "mysql"
fi
jasperreports_conf_set "dbPort" "$JASPERREPORTS_DATABASE_PORT_NUMBER"
jasperreports_conf_set "dbHost" "$JASPERREPORTS_DATABASE_HOST"
! is_boolean_yes "$ALLOW_EMPTY_PASSWORD" && jasperreports_conf_set "dbPassword" "$JASPERREPORTS_DATABASE_PASSWORD"
jasperreports_conf_set "dbUsername" "$JASPERREPORTS_DATABASE_USER"
jasperreports_conf_set "js.dbName" "$JASPERREPORTS_DATABASE_NAME"
# Extract MariaDB client version from the library jar. We do it at initialization time to avoid issues when updating
local -r mariadb_client_jar="$(realpath "${JASPERREPORTS_CONF_DIR}/conf_source/db/mysql/jdbc"/mariadb-java-client-*)"
local mariadb_client_version="${mariadb_client_jar##*-}"
mariadb_client_version="${mariadb_client_version%.jar}"
# Setting the admin database url (which will be the same as JASPERREPORTS_DATABASE_NAME), which is used by the installer
# to perform several checks
jasperreports_conf_set "admin.jdbcUrl" "jdbc:mysql://${JASPERREPORTS_DATABASE_HOST}:${JASPERREPORTS_DATABASE_PORT_NUMBER}/${JASPERREPORTS_DATABASE_NAME}" "${JASPERREPORTS_CONF_DIR}/conf_source/db/mysql/db.template.properties"
jasperreports_conf_set "maven.jdbc.version" "${mariadb_client_version}"
# Extract DB client version from the library jar. We do it at initialization time to avoid issues when updating
if [[ "$db_type" = "postgresql" ]]; then
local -r postgresql_client_jar="$(realpath "${JASPERREPORTS_CONF_DIR}/conf_source/db/postgresql/jdbc"/postgresql-*)"
client_version="${postgresql_client_jar##*-}"
client_version="${client_version%.jar}"
# Setting the admin database url (which will be the same as JASPERREPORTS_DATABASE_NAME), which is used by the installer
# to perform several checks
jasperreports_conf_set "admin.jdbcUrl" "jdbc:postgresql://${JASPERREPORTS_DATABASE_HOST}:${JASPERREPORTS_DATABASE_PORT_NUMBER}/${JASPERREPORTS_DATABASE_NAME}" "${JASPERREPORTS_CONF_DIR}/conf_source/db/postgresql/db.template.properties"
# Override default mysql configuration to PostgreSQL
jasperreports_conf_set "maven.jdbc.artifactId" "postgresql"
jasperreports_conf_set "jdbcDriverClass" "org.postgresql.Driver"
jasperreports_conf_set "jdbcDataSourceClass" "org.postgresql.ds.PGConnectionPoolDataSource"
jasperreports_conf_set "maven.jdbc.groupId" "org.postgresql"
jasperreports_conf_set "maven.jdbc.artifactId" "postgresql"
else
# Extract MariaDB client version from the library jar. We do it at initialization time to avoid issues when updating
local -r mariadb_client_jar="$(realpath "${JASPERREPORTS_CONF_DIR}/conf_source/db/mysql/jdbc"/mariadb-java-client-*)"
client_version="${mariadb_client_jar##*-}"
client_version="${client_version%.jar}"
# Setting the admin database url (which will be the same as JASPERREPORTS_DATABASE_NAME), which is used by the installer
# to perform several checks
jasperreports_conf_set "admin.jdbcUrl" "jdbc:mysql://${JASPERREPORTS_DATABASE_HOST}:${JASPERREPORTS_DATABASE_PORT_NUMBER}/${JASPERREPORTS_DATABASE_NAME}" "${JASPERREPORTS_CONF_DIR}/conf_source/db/mysql/db.template.properties"
fi
jasperreports_conf_set "maven.jdbc.version" "${client_version}"
}
########################
@ -152,10 +189,24 @@ jasperreports_configure_smtp() {
# None
#########################
jasperreports_configure_user() {
local db_type
db_type="$JASPERREPORTS_DATABASE_TYPE"
info "Configuring users"
# Change the default user username and mail using the database
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"UPDATE JIUser SET username='${JASPERREPORTS_USERNAME}' WHERE id=1"
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"UPDATE JIUser SET emailAddress='${JASPERREPORTS_EMAIL}' WHERE id=1"
if [[ "$db_type" = "postgresql" ]]; then
postgresql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<-EOF
UPDATE JIUser SET emailAddress='${JASPERREPORTS_EMAIL}' WHERE id=1;
UPDATE JIUser SET username='${JASPERREPORTS_USERNAME}' WHERE id=1;
EOF
else
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<-EOF
UPDATE JIUser SET emailAddress='${JASPERREPORTS_EMAIL}' WHERE id=1;
UPDATE JIUser SET username='${JASPERREPORTS_USERNAME}' WHERE id=1;
EOF
fi
# Change the default user password using the export-import scripts
# Based on https://community.jaspersoft.com/documentation/jasperreports-server-administration-guide/v550/import-and-export-through-command-line
@ -177,13 +228,22 @@ jasperreports_configure_user() {
# None
#########################
jasperreports_run_install_scripts() {
local db_type
db_type="$JASPERREPORTS_DATABASE_TYPE"
info "Executing installation scripts"
# In order to allow empty passwords and permission issues with the ant scripts, we will use the manual database initialization steps detailed in
# the official installation guide: https://community.jaspersoft.com/wiki/installation-steps-war-file-binary-distribution
# Using source to avoid generating too much output
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"SOURCE ${JASPERREPORTS_CONF_DIR}/install_resources/sql/mysql/js-create.ddl"
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"SOURCE ${JASPERREPORTS_CONF_DIR}/install_resources/sql/mysql/quartz.ddl"
if [[ "$db_type" = "postgresql" ]]; then
postgresql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"\i ${JASPERREPORTS_CONF_DIR}/install_resources/sql/postgresql/js-create.ddl"
postgresql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"\i ${JASPERREPORTS_CONF_DIR}/install_resources/sql/postgresql/quartz.ddl"
else
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"SOURCE ${JASPERREPORTS_CONF_DIR}/install_resources/sql/mysql/js-create.ddl"
mysql_remote_execute "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD" <<<"SOURCE ${JASPERREPORTS_CONF_DIR}/install_resources/sql/mysql/quartz.ddl"
fi
# We need to move to the buildomatic folder to execute scripts
cd "${JASPERREPORTS_CONF_DIR}" || exit
@ -257,6 +317,7 @@ jasperreports_run_upgrade_scripts() {
#########################
jasperreports_initialize() {
# Check if JasperReports has already been initialized and persisted in a previous run
local db_type db_host db_port db_name db_user db_pass
local -r app_name="jasperreports"
if ! [[ -e "$BITNAMI_ROOT_DIR/tomcat/webapps/jasperserver" ]]; then
@ -270,7 +331,14 @@ jasperreports_initialize() {
# Use daemon:root ownership for compatibility when running as a non-root user
am_i_root && configure_permissions_ownership "$JASPERREPORTS_VOLUME_DIR" -d "775" -f "664" -u "$JASPERREPORTS_DAEMON_USER" -g "root"
info "Trying to connect to the database server"
jasperreports_wait_for_mysql_connection "$JASPERREPORTS_DATABASE_HOST" "$JASPERREPORTS_DATABASE_PORT_NUMBER" "$JASPERREPORTS_DATABASE_NAME" "$JASPERREPORTS_DATABASE_USER" "$JASPERREPORTS_DATABASE_PASSWORD"
db_type="$JASPERREPORTS_DATABASE_TYPE"
db_host="$JASPERREPORTS_DATABASE_HOST"
db_port="$JASPERREPORTS_DATABASE_PORT_NUMBER"
db_name="$JASPERREPORTS_DATABASE_NAME"
db_user="$JASPERREPORTS_DATABASE_USER"
db_pass="$JASPERREPORTS_DATABASE_PASSWORD"
[[ "$db_type" = "mariadb" || "$db_type" = "mysql" ]] && jasperreports_wait_for_mysql_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
[[ "$db_type" = "postgresql" ]] && jasperreports_wait_for_postgresql_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
# Configure JasperReports based on environment variables
info "Configuring JasperReports with settings provided via environment variables"
@ -309,14 +377,16 @@ jasperreports_initialize() {
info "Restoring persisted JasperReports installation"
restore_persisted_app "$app_name" "$JASPERREPORTS_DATA_TO_PERSIST"
info "Trying to connect to the database server"
local db_host db_port db_name db_user db_pass
local db_type db_host db_port db_name db_user db_pass
db_type="$(jasperreports_conf_get "dbType")"
db_host="$(jasperreports_conf_get "dbHost")"
db_port="$(jasperreports_conf_get "dbPort")"
db_name="$(jasperreports_conf_get "js.dbName")"
db_user="$(jasperreports_conf_get "dbUsername")"
# Adding true as the password may not be set
db_pass="$(jasperreports_conf_get "dbPassword" || true)"
jasperreports_wait_for_mysql_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
[[ "$db_type" = "mariadb" || "$db_type" = "mysql" ]] && jasperreports_wait_for_mysql_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
[[ "$db_type" = "postgresql" ]] && jasperreports_wait_for_postgresql_connection "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
jasperreports_run_upgrade_scripts
jasperreports_run_deployment_scripts
fi
@ -397,6 +467,34 @@ jasperreports_conf_get() {
grep -E "$sanitized_pattern" "$JASPERREPORTS_CONF_FILE" | sed -E "s|${sanitized_pattern}|\2|" | tr -d "\"' "
}
########################
# Wait until the database is accessible with the currently-known credentials
# Globals:
# *
# Arguments:
# $1 - database host
# $2 - database port
# $3 - database name
# $4 - database username
# $5 - database user password (optional)
# Returns:
# true if the database connection succeeded, false otherwise
#########################
jasperreports_wait_for_postgresql_connection() {
local -r db_host="${1:?missing database host}"
local -r db_port="${2:?missing database port}"
local -r db_name="${3:?missing database name}"
local -r db_user="${4:?missing database user}"
local -r db_pass="${5:-}"
check_postgresql_connection() {
echo "SELECT 1" | postgresql_remote_execute "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass"
}
if ! retry_while "check_postgresql_connection"; then
error "Could not connect to the database"
return 1
fi
}
########################
# Wait until the database is accessible with the currently-known credentials
# Globals:

View File

@ -0,0 +1,458 @@
#!/bin/bash
#
# Bitnami PostgreSQL Client library
# shellcheck disable=SC1091
# Load Generic Libraries
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libos.sh
. /opt/bitnami/scripts/libvalidations.sh
########################
# Checks if PostgreSQL is running
# Globals:
# DB_TMP_DIR
# Arguments:
# None
# Returns:
# Boolean
#########################
is_postgresql_running() {
local pid
pid="$(get_pid_from_file "$DB_PID_FILE")"
if [[ -z "$pid" ]]; then
false
else
is_service_running "$pid"
fi
}
########################
# Wait for PostgreSQL to be running
# Globals:
# DB_TMP_DIR
# DB_STARTUP_WAIT_RETRIES
# DB_STARTUP_WAIT_SLEEP_TIME
# Arguments:
# None
# Returns:
# Boolean
#########################
wait_for_postgresql() {
local pid
local -r retries="${DB_STARTUP_WAIT_RETRIES:-300}"
local -r sleep_time="${DB_STARTUP_WAIT_SLEEP_TIME:-2}"
if ! retry_while is_postgresql_running "$retries" "$sleep_time"; then
error "PostgreSQL failed to start"
return 1
fi
}
########################
# Validate settings in POSTGRESQL_CLIENT_* environment variables
# Globals:
# POSTGRESQL_CLIENT_*
# Arguments:
# None
# Returns:
# None
#########################
postgresql_client_validate() {
info "Validating settings in POSTGRESQL_CLIENT_* env vars"
local error_code=0
# Auxiliary functions
print_validation_error() {
error "$1"
error_code=1
}
empty_password_enabled_warn() {
warn "You set the environment variable ALLOW_EMPTY_PASSWORD=${ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment."
}
empty_password_error() {
print_validation_error "The $1 environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development."
}
# Only validate environment variables if any action needs to be performed
local -a database_names
read -r -a database_names <<< "$(tr ',;' ' ' <<< "$POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES")"
if [[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" || "${#database_names[@]}" -gt 0 ]]; then
if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then
empty_password_enabled_warn
else
if [[ -z "$POSTGRESQL_CLIENT_POSTGRES_PASSWORD" ]]; then
empty_password_error "POSTGRESQL_CLIENT_POSTGRES_PASSWORD"
fi
if [[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" ]] && [[ -z "$POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD" ]]; then
empty_password_error "POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD"
fi
fi
fi
# When enabling extensions, the DB name must be provided
local -a extensions
read -r -a extensions <<< "$(tr ',;' ' ' <<< "$POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS")"
if [[ "${#database_names[@]}" -le 0 && "${#extensions[@]}" -gt 0 ]]; then
print_validation_error "POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS requires POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES to be set."
fi
return "$error_code"
}
########################
# Perform actions to a database
# Globals:
# POSTGRESQL_CLIENT_*
# Arguments:
# None
# Returns:
# None
#########################
postgresql_client_initialize() {
local -a database_names
read -r -a database_names <<< "$(tr ',;' ' ' <<< "$POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES")"
# Wait for the database to be accessible if any action needs to be performed
if [[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" || "${#database_names[@]}" -gt 0 ]]; then
info "Trying to connect to the database server"
check_postgresql_connection() {
echo "SELECT 1" | postgresql_remote_execute "$POSTGRESQL_CLIENT_DATABASE_HOST" "$POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER" "postgres" "$POSTGRESQL_CLIENT_POSTGRES_USER" "$POSTGRESQL_CLIENT_POSTGRES_PASSWORD"
}
if ! retry_while "check_postgresql_connection"; then
error "Could not connect to the database server"
return 1
fi
fi
# Ensure a database user exists in the server
if [[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" ]]; then
info "Creating database user ${POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME}"
local -a args=("$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" "--host" "$POSTGRESQL_CLIENT_DATABASE_HOST" "--port" "$POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER")
[[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD" ]] && args+=("-p" "$POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD")
postgresql_ensure_user_exists "${args[@]}"
fi
# Ensure a database exists in the server (and that the user has write privileges, if specified)
if [[ "${#database_names[@]}" -gt 0 ]]; then
local -a createdb_args extensions
read -r -a extensions <<< "$(tr ',;' ' ' <<< "$POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS")"
for database_name in "${database_names[@]}"; do
info "Creating database ${database_name}"
createdb_args=("$database_name" "--host" "$POSTGRESQL_CLIENT_DATABASE_HOST" "--port" "$POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER")
[[ -n "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME" ]] && createdb_args+=("-u" "$POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME")
postgresql_ensure_database_exists "${createdb_args[@]}"
# Ensure the list of extensions are enabled in the specified database
if [[ "${#extensions[@]}" -gt 0 ]]; then
for extension_to_create in "${extensions[@]}"; do
echo "CREATE EXTENSION IF NOT EXISTS ${extension_to_create}" | postgresql_remote_execute "$POSTGRESQL_CLIENT_DATABASE_HOST" "$POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER" "$database_name" "$POSTGRESQL_CLIENT_POSTGRES_USER" "$POSTGRESQL_CLIENT_POSTGRES_PASSWORD"
done
fi
done
fi
# Execute a custom SQL script
if [[ -n "$POSTGRESQL_CLIENT_EXECUTE_SQL" ]]; then
info "Executing custom SQL script"
echo "$POSTGRESQL_CLIENT_EXECUTE_SQL" | postgresql_remote_execute "$POSTGRESQL_CLIENT_DATABASE_HOST" "$POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER" "postgres" "$POSTGRESQL_CLIENT_POSTGRES_USER" "$POSTGRESQL_CLIENT_POSTGRES_PASSWORD"
fi
# Avoid exit code of previous commands to affect the result of this function
true
}
########################
# Return PostgreSQL major version
# Globals:
# POSTGRESQL_*
# Arguments:
# None
# Returns:
# String
#########################
postgresql_get_major_version() {
psql --version | grep -oE "[0-9]+\.[0-9]+" | grep -oE "^[0-9]+"
}
########################
# Gets an environment variable name based on the suffix
# Arguments:
# $1 - environment variable suffix
# Returns:
# environment variable name
#########################
get_env_var_value() {
local env_var_suffix="${1:?missing suffix}"
local env_var_name
for env_var_prefix in POSTGRESQL POSTGRESQL_CLIENT; do
env_var_name="${env_var_prefix}_${env_var_suffix}"
if [[ -n "${!env_var_name:-}" ]]; then
echo "${!env_var_name}"
break
fi
done
}
########################
# Execute an arbitrary query/queries against the running PostgreSQL service and print the output
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# POSTGRESQL_*
# Arguments:
# $1 - Database where to run the queries
# $2 - User to run queries
# $3 - Password
# $4 - Extra options (eg. -tA)
# Returns:
# None
#########################
postgresql_execute_print_output() {
local -r db="${1:-}"
local -r user="${2:-postgres}"
local -r pass="${3:-}"
local opts
read -r -a opts <<<"${@:4}"
local args=("-U" "$user" "-p" "${POSTGRESQL_PORT_NUMBER:-5432}")
[[ -n "$db" ]] && args+=("-d" "$db")
[[ "${#opts[@]}" -gt 0 ]] && args+=("${opts[@]}")
# Execute the Query/queries from stdin
PGPASSWORD=$pass psql "${args[@]}"
}
########################
# Execute an arbitrary query/queries against the running PostgreSQL service
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# POSTGRESQL_*
# Arguments:
# $1 - Database where to run the queries
# $2 - User to run queries
# $3 - Password
# $4 - Extra options (eg. -tA)
# Returns:
# None
#########################
postgresql_execute() {
if [[ "${BITNAMI_DEBUG:-false}" = true ]]; then
"postgresql_execute_print_output" "$@"
elif [[ "${NO_ERRORS:-false}" = true ]]; then
"postgresql_execute_print_output" "$@" 2>/dev/null
else
"postgresql_execute_print_output" "$@" >/dev/null 2>&1
fi
}
########################
# Execute an arbitrary query/queries against a remote PostgreSQL service and print to stdout
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# $1 - Remote PostgreSQL service hostname
# $2 - Remote PostgreSQL service port
# $3 - Database where to run the queries
# $4 - User to run queries
# $5 - Password
# $6 - Extra options (eg. -tA)
# Returns:
# None
postgresql_remote_execute_print_output() {
local -r hostname="${1:?hostname is required}"
local -r port="${2:?port is required}"
local -a args=("-h" "$hostname" "-p" "$port")
shift 2
"postgresql_execute_print_output" "$@" "${args[@]}"
}
########################
# Execute an arbitrary query/queries against a remote PostgreSQL service
# Stdin:
# Query/queries to execute
# Globals:
# BITNAMI_DEBUG
# DB_*
# Arguments:
# $1 - Remote PostgreSQL service hostname
# $2 - Remote PostgreSQL service port
# $3 - Database where to run the queries
# $4 - User to run queries
# $5 - Password
# $6 - Extra options (eg. -tA)
# Returns:
# None
postgresql_remote_execute() {
if [[ "${BITNAMI_DEBUG:-false}" = true ]]; then
"postgresql_remote_execute_print_output" "$@"
elif [[ "${NO_ERRORS:-false}" = true ]]; then
"postgresql_remote_execute_print_output" "$@" 2>/dev/null
else
"postgresql_remote_execute_print_output" "$@" >/dev/null 2>&1
fi
}
########################
# Optionally create the given database user
# Flags:
# -p|--password - database password
# --host - database host
# --port - database port
# Arguments:
# $1 - user
# Returns:
# None
#########################
postgresql_ensure_user_exists() {
local -r user="${1:?user is missing}"
local password=""
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-p | --password)
shift
password="${1:?missing password}"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
local -a postgresql_execute_cmd=("postgresql_execute")
[[ -n "$db_host" && -n "$db_port" ]] && postgresql_execute_cmd=("postgresql_remote_execute" "$db_host" "$db_port")
local -a postgresql_execute_flags=("postgres" "$(get_env_var_value POSTGRES_USER)" "$(get_env_var_value POSTGRES_PASSWORD)")
"${postgresql_execute_cmd[@]}" "${postgresql_execute_flags[@]}" <<EOF
DO
\$do\$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles WHERE rolname = '${user}'
) THEN
CREATE ROLE "${user}" LOGIN PASSWORD '${password}';
END IF;
END
\$do\$;
EOF
}
########################
# Ensure a user has all privileges to access a database
# Arguments:
# $1 - database name
# $2 - database user
# $3 - database host (optional)
# $4 - database port (optional)
# Returns:
# None
#########################
postgresql_ensure_user_has_database_privileges() {
local -r user="${1:?user is required}"
local -r database="${2:?db is required}"
local -r db_host="${3:-}"
local -r db_port="${4:-}"
local -a postgresql_execute_cmd=("postgresql_execute")
[[ -n "$db_host" && -n "$db_port" ]] && postgresql_execute_cmd=("postgresql_remote_execute" "$db_host" "$db_port")
local -a postgresql_execute_flags=("postgres" "$(get_env_var_value POSTGRES_USER)" "$(get_env_var_value POSTGRES_PASSWORD)")
debug "Providing privileges to username ${user} on database ${database}"
"${postgresql_execute_cmd[@]}" "${postgresql_execute_flags[@]}" <<EOF
GRANT ALL PRIVILEGES ON DATABASE "${database}" TO "${user}";
ALTER DATABASE "${database}" OWNER TO "${user}";
EOF
}
########################
# Optionally create the given database, and then optionally give a user
# full privileges on the database.
# Flags:
# -u|--user - database user
# --host - database host
# --port - database port
# Arguments:
# $1 - database name
# Returns:
# None
#########################
postgresql_ensure_database_exists() {
local -r database="${1:?database is missing}"
local user=""
# For accessing an external database
local db_host=""
local db_port=""
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-u | --user)
shift
user="${1:?missing database user}"
;;
--host)
shift
db_host="${1:?missing database host}"
;;
--port)
shift
db_port="${1:?missing database port}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
local -a postgresql_execute_cmd=("postgresql_execute")
[[ -n "$db_host" && -n "$db_port" ]] && postgresql_execute_cmd=("postgresql_remote_execute" "$db_host" "$db_port")
local -a postgresql_execute_flags=("postgres" "$(get_env_var_value POSTGRES_USER)" "$(get_env_var_value POSTGRES_PASSWORD)")
"${postgresql_execute_cmd[@]}" "${postgresql_execute_flags[@]}" <<EOF
SELECT 'CREATE DATABASE "${database}"'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${database}')\gexec
EOF
if [[ -n "$user" ]]; then
local -a grant_flags=("$user" "$database")
[[ -n "$db_host" ]] && grant_flags+=("$db_host")
[[ -n "$db_port" ]] && grant_flags+=("$db_port")
postgresql_ensure_user_has_database_privileges "${grant_flags[@]}"
fi
}
########################
# Retrieves the WAL directory in use by PostgreSQL / to use if not initialized yet
# Globals:
# REPMGR_*
# Arguments:
# None
# Returns:
# the path to the WAL directory, or empty if not set
#########################
postgresql_get_waldir() {
if [[ -L "${POSTGRESQL_DATA_DIR}/pg_wal" && -d "${POSTGRESQL_DATA_DIR}/pg_wal" ]]; then
readlink -f "${POSTGRESQL_DATA_DIR}/pg_wal"
else
# Uninitialized - using value from $POSTGRESQL_INITDB_WAL_DIR if set
echo "$POSTGRESQL_INITDB_WAL_DIR"
fi
}

View File

@ -12,7 +12,7 @@
. /opt/bitnami/scripts/libvalidations.sh
########################
# Validate settings in MYSQL_*/MARIADB_* environment variables
# Validate settings in TOMCAT_* environment variables
# Globals:
# DB_*
# Arguments:

View File

@ -0,0 +1,92 @@
#!/bin/bash
#
# Environment configuration for postgresql-client
# The values for all environment variables will be set in the below order of precedence
# 1. Custom environment variables defined below after Bitnami defaults
# 2. Constants defined in this file (environment variables with no default), i.e. BITNAMI_ROOT_DIR
# 3. Environment variables overridden via external files using *_FILE variables (see below)
# 4. Environment variables set externally (i.e. current Bash context/Dockerfile/userdata)
# Load logging library
# shellcheck disable=SC1090,SC1091
. /opt/bitnami/scripts/liblog.sh
export BITNAMI_ROOT_DIR="/opt/bitnami"
export BITNAMI_VOLUME_DIR="/bitnami"
# Logging configuration
export MODULE="${MODULE:-postgresql-client}"
export BITNAMI_DEBUG="${BITNAMI_DEBUG:-false}"
# By setting an environment variable matching *_FILE to a file path, the prefixed environment
# variable will be overridden with the value specified in that file
postgresql_client_env_vars=(
ALLOW_EMPTY_PASSWORD
POSTGRESQL_CLIENT_DATABASE_HOST
POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER
POSTGRESQL_CLIENT_POSTGRES_USER
POSTGRESQL_CLIENT_POSTGRES_PASSWORD
POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES
POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME
POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD
POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS
POSTGRESQL_CLIENT_EXECUTE_SQL
POSTGRESQL_HOST
POSTGRESQL_PORT_NUMBER
POSTGRESQL_CLIENT_ROOT_USER
POSTGRESQL_POSTGRES_USER
POSTGRESQL_ROOT_USER
POSTGRESQL_CLIENT_ROOT_PASSWORD
POSTGRESQL_POSTGRES_PASSWORD
POSTGRESQL_ROOT_PASSWORD
POSTGRESQL_CLIENT_CREATE_DATABASE_NAME
POSTGRESQL_CLIENT_CREATE_DATABASE_USER
)
for env_var in "${postgresql_client_env_vars[@]}"; do
file_env_var="${env_var}_FILE"
if [[ -n "${!file_env_var:-}" ]]; then
if [[ -r "${!file_env_var:-}" ]]; then
export "${env_var}=$(< "${!file_env_var}")"
unset "${file_env_var}"
else
warn "Skipping export of '${env_var}'. '${!file_env_var:-}' is not readable."
fi
fi
done
unset postgresql_client_env_vars
# Paths
export POSTGRESQL_BASE_DIR="/opt/bitnami/postgresql"
export POSTGRESQL_BIN_DIR="$POSTGRESQL_BASE_DIR/bin"
export PATH="${POSTGRESQL_BIN_DIR}:${PATH}"
# PostgreSQL settings
export ALLOW_EMPTY_PASSWORD="${ALLOW_EMPTY_PASSWORD:-no}"
POSTGRESQL_CLIENT_DATABASE_HOST="${POSTGRESQL_CLIENT_DATABASE_HOST:-"${POSTGRESQL_HOST:-}"}"
export POSTGRESQL_CLIENT_DATABASE_HOST="${POSTGRESQL_CLIENT_DATABASE_HOST:-postgres}"
POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER="${POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER:-"${POSTGRESQL_PORT_NUMBER:-}"}"
export POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER="${POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER:-5432}"
POSTGRESQL_CLIENT_DATABASE_ROOT_USER="${POSTGRESQL_CLIENT_DATABASE_ROOT_USER:-"${POSTGRESQL_ROOT_USER:-}"}"
export POSTGRESQL_CLIENT_DATABASE_ROOT_USER="${POSTGRESQL_CLIENT_DATABASE_ROOT_USER:-postgres}"
export DB_ROOT_USER="$POSTGRESQL_CLIENT_DATABASE_ROOT_USER" # only used during the first initialization
POSTGRESQL_CLIENT_DATABASE_ROOT_PASSWORD="${POSTGRESQL_CLIENT_DATABASE_ROOT_PASSWORD:-"${POSTGRESQL_ROOT_PASSWORD:-}"}"
export POSTGRESQL_CLIENT_DATABASE_ROOT_PASSWORD="${POSTGRESQL_CLIENT_DATABASE_ROOT_PASSWORD:-}"
export DB_ROOT_PASSWORD="$POSTGRESQL_CLIENT_DATABASE_ROOT_PASSWORD" # only used during the first initialization
POSTGRESQL_CLIENT_POSTGRES_USER="${POSTGRESQL_CLIENT_POSTGRES_USER:-"${POSTGRESQL_CLIENT_ROOT_USER:-}"}"
POSTGRESQL_CLIENT_POSTGRES_USER="${POSTGRESQL_CLIENT_POSTGRES_USER:-"${POSTGRESQL_POSTGRES_USER:-}"}"
POSTGRESQL_CLIENT_POSTGRES_USER="${POSTGRESQL_CLIENT_POSTGRES_USER:-"${POSTGRESQL_ROOT_USER:-}"}"
export POSTGRESQL_CLIENT_POSTGRES_USER="${POSTGRESQL_CLIENT_POSTGRES_USER:-postgres}" # only used during the first initialization
POSTGRESQL_CLIENT_POSTGRES_PASSWORD="${POSTGRESQL_CLIENT_POSTGRES_PASSWORD:-"${POSTGRESQL_CLIENT_ROOT_PASSWORD:-}"}"
POSTGRESQL_CLIENT_POSTGRES_PASSWORD="${POSTGRESQL_CLIENT_POSTGRES_PASSWORD:-"${POSTGRESQL_POSTGRES_PASSWORD:-}"}"
POSTGRESQL_CLIENT_POSTGRES_PASSWORD="${POSTGRESQL_CLIENT_POSTGRES_PASSWORD:-"${POSTGRESQL_ROOT_PASSWORD:-}"}"
export POSTGRESQL_CLIENT_POSTGRES_PASSWORD="${POSTGRESQL_CLIENT_POSTGRES_PASSWORD:-}" # only used during the first initialization
POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES="${POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES:-"${POSTGRESQL_CLIENT_CREATE_DATABASE_NAME:-}"}"
export POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES="${POSTGRESQL_CLIENT_CREATE_DATABASE_NAMES:-}" # only used during the first initialization
POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME="${POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME:-"${POSTGRESQL_CLIENT_CREATE_DATABASE_USER:-}"}"
export POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME="${POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME:-}" # only used during the first initialization
export POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD="${POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD:-}" # only used during the first initialization
export POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS="${POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS:-}" # only used during the first initialization
export POSTGRESQL_CLIENT_EXECUTE_SQL="${POSTGRESQL_CLIENT_EXECUTE_SQL:-}" # only used during the first initialization
# Custom environment variables may be defined below

View File

@ -0,0 +1,19 @@
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purposes
# Load libraries
. /opt/bitnami/scripts/libpostgresqlclient.sh
# Load PostgreSQL Client environment variables
. /opt/bitnami/scripts/postgresql-client-env.sh
# Ensure PostgreSQL Client environment variables settings are valid
postgresql_client_validate
# Ensure PostgreSQL Client is initialized
postgresql_client_initialize

View File

@ -251,6 +251,7 @@ Available environment variables:
##### Database connection configuration
- `JASPERREPORTS_DATABASE_TYPE`: Database type to be used for the JasperReports installation. Allowed values: `mariadb`, `mysql`, `postgresql`. Default: **mariadb**
- `JASPERREPORTS_DATABASE_HOST`: Hostname for the MariaDB or MySQL server. Default: **mariadb**
- `JASPERREPORTS_DATABASE_PORT_NUMBER`: Port used by the MariaDB or MySQL server. Default: **3306**
- `JASPERREPORTS_DATABASE_NAME`: Database name that JasperReports will use to connect with the database. Default: **bitnami_jasperreports**