#!/bin/bash # Copyright Broadcom, Inc. All Rights Reserved. # SPDX-License-Identifier: APACHE-2.0 # # Bitnami MySQL library # shellcheck disable=SC1090,SC1091,SC2119,SC2120 # Load Generic Libraries . /opt/bitnami/scripts/libfile.sh . /opt/bitnami/scripts/liblog.sh . /opt/bitnami/scripts/libfs.sh . /opt/bitnami/scripts/libos.sh . /opt/bitnami/scripts/libservice.sh . /opt/bitnami/scripts/libvalidations.sh . /opt/bitnami/scripts/libversion.sh ######################## # Configure database extra start flags # Globals: # DB_* # Arguments: # None # Returns: # Array with extra flags to use ######################### mariadb_extra_flags() { local randNumber local -a dbExtraFlags=() if [[ -n "$DB_REPLICATION_MODE" ]]; then randNumber="$(head /dev/urandom | tr -dc 0-9 | head -c 3 ; echo '')" dbExtraFlags+=("--server-id=$randNumber" "--binlog-format=ROW" "--log-bin=mysql-bin" "--sync-binlog=1") if [[ "$DB_REPLICATION_MODE" = "slave" ]]; then dbExtraFlags+=("--relay-log=mysql-relay-bin" "--log-slave-updates=1" "--read-only=1") elif [[ "$DB_REPLICATION_MODE" = "master" ]]; then dbExtraFlags+=("--innodb_flush_log_at_trx_commit=1") fi fi # shellcheck disable=SC2153 read -r -a userExtraFlags <<< "$DB_EXTRA_FLAGS" [[ "${#userExtraFlags[@]}" -eq 0 ]] || dbExtraFlags+=("${userExtraFlags[@]}") echo "${dbExtraFlags[@]:-}" } ######################## # Validate settings in MARIADB_* environment variables # Globals: # DB_* # Arguments: # None # Returns: # None ######################### mariadb_validate() { info "Validating settings in MARIADB_* 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." } backslash_password_error() { print_validation_error "The password cannot contain backslashes ('\'). Set the environment variable $1 with no backslashes (more info at https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html)" } if [[ -n "$DB_REPLICATION_MODE" ]]; then if [[ "$DB_REPLICATION_MODE" = "master" ]]; then if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then empty_password_enabled_warn else if [[ -n "$DB_REPLICATION_USER" ]] && [[ -z "$DB_REPLICATION_PASSWORD" ]]; then empty_password_error "MARIADB_REPLICATION_PASSWORD" fi if [[ -z "$DB_ROOT_PASSWORD" ]]; then empty_password_error "MARIADB_ROOT_PASSWORD" fi if (( ${#DB_ROOT_PASSWORD} > 32 )); then print_validation_error "The password can not be longer than 32 characters. Set the environment variable MARIADB_ROOT_PASSWORD with a shorter value (currently ${#DB_ROOT_PASSWORD} characters)" fi if [[ -n "$DB_USER" ]] && [[ -z "$DB_PASSWORD" ]]; then empty_password_error "MARIADB_PASSWORD" fi fi elif [[ "$DB_REPLICATION_MODE" = "slave" ]]; then if [[ -z "$DB_MASTER_HOST" ]]; then print_validation_error "Slave replication mode chosen without setting the environment variable MARIADB_MASTER_HOST. Use it to indicate where the Master node is running" fi else print_validation_error "Invalid replication mode. Available options are 'master/slave'" fi else if is_boolean_yes "$ALLOW_EMPTY_PASSWORD"; then empty_password_enabled_warn else if [[ -z "$DB_ROOT_PASSWORD" ]]; then empty_password_error "MARIADB_ROOT_PASSWORD" fi if [[ -n "$DB_USER" ]] && [[ -z "$DB_PASSWORD" ]]; then empty_password_error "MARIADB_PASSWORD" fi fi fi if [[ "${DB_ROOT_PASSWORD:-}" = *\\* ]]; then backslash_password_error "MARIADB_ROOT_PASSWORD" fi if [[ -n "$DB_USER" ]] && [[ "$DB_USER" = "root" ]]; then print_validation_error "root user is already created in the database and you can't use it as username for user creation." fi if [[ "${DB_PASSWORD:-}" = *\\* ]]; then backslash_password_error "MARIADB_PASSWORD" fi if [[ "${DB_REPLICATION_PASSWORD:-}" = *\\* ]]; then backslash_password_error "MARIADB_REPLICATION_PASSWORD" fi is_empty_value "${MARIADB_COLLATION:-}" || warn "The usage of 'MARIADB_COLLATION' is deprecated and will soon be removed. Use 'MARIADB_COLLATE' instead." [[ "$error_code" -eq 0 ]] || exit "$error_code" } ######################## # Creates MariaDB configuration file # Globals: # DB_* # Arguments: # None # Returns: # None ######################### mariadb_create_default_config() { debug "Creating main configuration file" cat > "$DB_CONF_FILE" < "$dump_file" debug "Finish dump databases" # Look for the line containing "CHANGE REPLICATION SOURCE" while IFS= read -r line; do if [[ "$line" =~ CHANGE\ REPLICATION\ SOURCE\ TO\ SOURCE_LOG_FILE=\'([^\']+)\'\,\ SOURCE_LOG_POS=([0-9]+)\; ]]; then log_file="${BASH_REMATCH[1]}" log_position="${BASH_REMATCH[2]}" break fi done < "$dump_file" debug "File: $log_file and Position: $log_position" debug "Start import dump databases" mysql_execute < "$dump_file" mysql_execute "mysql" < "${DB_CONF_DIR}/admin.cnf" < "${DB_CONF_DIR}/bitnami/my_custom.cnf" if ! grep --silent "!include ${DB_CONF_DIR}/bitnami/my_custom.cnf" "${DB_CONF_FILE}"; then echo "!include ${DB_CONF_DIR}/bitnami/my_custom.cnf" >> "${DB_CONF_FILE}" fi else warn "Could not inject custom configuration for the ${DB_FLAVOR} configuration file '$DB_CONF_DIR/bitnami/my_custom.cnf' because it is not writable." fi fi if [[ -e "$DB_DATA_DIR/mysql" ]]; then info "Using persisted data" # mariadb-upgrade requires the server to be running [[ -n "$(get_master_env_var_value ROOT_PASSWORD)" ]] && export ROOT_AUTH_ENABLED="yes" # https://dev.mysql.com/doc/refman/8.0/en/replication-upgrade.html mariadb_upgrade else debug "Cleaning data directory to ensure successfully initialization" rm -rf "${DB_DATA_DIR:?}"/* info "Installing database" mariadb_install_db mariadb_start_bg wait_for_mysql_access # we delete existing users and create new ones with stricter access # commands can still be executed until we restart or run 'flush privileges' info "Configuring authentication" mysql_execute "mysql" < 32 )); then print_validation_error "The password can not be longer than 32 characters. Set the environment variable $(get_env_var ROOT_PASSWORD) with a shorter value (currently ${#DB_ROOT_PASSWORD} characters)" fi if [[ -n "$DB_USER" ]]; then if is_boolean_yes "$DB_ENABLE_LDAP" && [[ -n "$DB_PASSWORD" ]]; then warn "You enabled LDAP authentication. '$DB_USER' user will be authentication using LDAP, the password set at the environment variable $(get_env_var PASSWORD) will be ignored" elif ! is_boolean_yes "$DB_ENABLE_LDAP" && [[ -z "$DB_PASSWORD" ]]; then empty_password_error "$(get_env_var PASSWORD)" fi fi fi fi if [[ -n "$DB_GALERA_FORCE_SAFETOBOOTSTRAP" ]] && ! is_yes_no_value "$DB_GALERA_FORCE_SAFETOBOOTSTRAP"; then print_validation_error "The allowed values for $(get_env_var GALERA_FORCE_SAFETOBOOTSTRAP) are yes or no." fi if [[ -z "$DB_GALERA_CLUSTER_NAME" ]]; then print_validation_error "Galera cluster cannot be created without setting the environment variable $(get_env_var GALERA_CLUSTER_NAME)." fi if [[ -z "$(get_galera_cluster_address_value)" ]]; then print_validation_error "Galera cluster cannot be created without setting the environment variable $(get_env_var GALERA_CLUSTER_ADDRESS). If you are bootstrapping a new Galera cluster, set the environment variable $(get_env_var GALERA_CLUSTER_ADDRESS)=yes." fi if [[ "${DB_ROOT_PASSWORD:-}" = *\\* ]]; then backslash_password_error "$(get_env_var ROOT_PASSWORD)" fi if [[ "${DB_PASSWORD:-}" = *\\* ]]; then backslash_password_error "$(get_env_var PASSWORD)" fi if is_boolean_yes "$DB_ENABLE_LDAP" && { [[ -z "${LDAP_URI}" ]] || [[ -z "${LDAP_BASE}" ]] || [[ -z "${LDAP_BIND_DN}" ]] || [[ -z "${LDAP_BIND_PASSWORD}" ]]; }; then print_validation_error "The LDAP configuration is required when LDAP authentication is enabled. Set the environment variables LDAP_URI, LDAP_BASE, LDAP_BIND_DN and LDAP_BIND_PASSWORD with the LDAP configuration." fi if is_boolean_yes "$DB_ENABLE_TLS"; then if [[ -z "${DB_TLS_CERT_FILE}" ]] || [[ -z "${DB_TLS_KEY_FILE}" ]] || [[ -z "${DB_TLS_CA_FILE}" ]]; then print_validation_error "The TLS cert file, key and CA are required when TLS is enabled. Set the environment variables TLS_CERT_FILE, TLS_KEY_FILE and TLS_CA_FILE with the path to each file." fi if [[ ! -f "${DB_TLS_CERT_FILE}" ]]; then print_validation_error "The TLS_CERT file ${DB_TLS_CERT_FILE} must exist." fi if [[ ! -f "${DB_TLS_KEY_FILE}" ]]; then print_validation_error "The TLS_KEY file ${DB_TLS_KEY_FILE} must exist." fi if [[ ! -f "${DB_TLS_CA_FILE}" ]]; then print_validation_error "The TLS_CA file ${DB_TLS_CA_FILE} must exist." fi fi collation_env_var="$(get_env_var COLLATION)" is_empty_value "${!collation_env_var:-}" || warn "The usage of '$(get_env_var COLLATION)' is deprecated and will soon be removed. Use '$(get_env_var COLLATE)' instead." [[ "$error_code" -eq 0 ]] || exit "$error_code" } ######################## # Creates MySQL/MariaDB configuration file # Globals: # DB_* # Arguments: # None # Returns: # None ######################### mysql_create_default_config() { debug "Creating main configuration file" cat > "$DB_CONF_FILE" < "${DB_CONF_DIR}/bitnami/my_custom.cnf" else warn "Could not inject custom configuration for the ${DB_FLAVOR} configuration file '$DB_CONF_DIR/bitnami/my_custom.cnf' because it is not writable." fi fi if [[ -e "$DB_DATA_DIR/mysql" ]]; then info "Persisted data detected. Restoring" if is_boolean_yes "$(get_galera_cluster_bootstrap_value)"; then if is_boolean_yes "$DB_GALERA_FORCE_SAFETOBOOTSTRAP"; then set_safe_to_bootstrap fi if ! is_safe_to_bootstrap; then error "It is not safe to bootstrap form this node ('safe_to_bootstrap=0' is set in 'grastate.dat'). If you want to force bootstrap, set the environment variable MARIADB_GALERA_FORCE_SAFETOBOOTSTRAP=yes" exit 1 fi fi return else # initialization should not be performed on non-primary nodes of a galera cluster if is_boolean_yes "$(get_galera_cluster_bootstrap_value)"; then debug "Cleaning data directory to ensure successfully initialization" rm -rf "${DB_DATA_DIR:?}"/* mariadb_install_db mysql_start_bg debug "Deleting all users to avoid issues with galera configuration" mysql_execute "mysql" </dev/null hostname fi } ######################## # Check for user override of wsrep_node_address # Globals: # DB_* # Arguments: # None # Returns: # String with node address ######################### get_node_address() { if [[ -n "$DB_GALERA_NODE_ADDRESS" ]]; then echo "$DB_GALERA_NODE_ADDRESS" else # In some environments, the network may not be fully set up when starting the initialization # So, to avoid issues, we retry the 'hostname' command until it succeeds (for a few minutes) local -r retries="60" local -r seconds="5" retry_while "hostname -i" "$retries" "$seconds" >/dev/null # prefer IPv6 over IPv4 if available # This works by pulling any IPv4 addresses encountered into hold space and emitting it only when the EOF line is encountered printf '%s\nEOF' "$(hostname -i | tr ' ' '\n')" | sed '/:/{;q;};/^EOF$/{;g;q;};h;d' fi } ######################## # Starts MySQL/MariaDB in the background and waits until it's ready # Globals: # DB_* # Arguments: # None # Returns: # None ######################### mysql_start_bg() { local -a flags=("--defaults-file=${DB_CONF_FILE}" "--basedir=${DB_BASE_DIR}" "--datadir=${DB_DATA_DIR}" "--socket=${DB_SOCKET_FILE}") # Only allow local connections until MySQL is fully initialized, to avoid apps trying to connect to MySQL before it is fully initialized flags+=("--bind-address=127.0.0.1") # Add flags specified via the 'DB_EXTRA_FLAGS' environment variable read -r -a db_extra_flags <<< "$(mysql_extra_flags)" [[ "${#db_extra_flags[@]}" -gt 0 ]] && flags+=("${db_extra_flags[@]}") # Do not start as root, to avoid permission issues am_i_root && flags+=("--user=${DB_DAEMON_USER}") # The slave should only start in 'run.sh', elseways user credentials would be needed for any connection flags+=("--skip-slave-start") flags+=("$@") is_mysql_running && return info "Starting $DB_FLAVOR in background" debug_execute "${DB_SBIN_DIR}/mysqld" "${flags[@]}" & # we cannot use wait_for_mysql_access here as mysql_upgrade for MySQL >=8 depends on this command # users are not configured on slave nodes during initialization due to --skip-slave-start wait_for_mysql # Wait for WSREP to be ready. If WSREP is not ready, we cannot do any transactions, thus cannot # create any users, and WSREP instantly kills MariaDB if doing so wait_for_wsrep # Special configuration flag for system with slow disks that could take more time # in initializing if [[ -n "${DB_INIT_SLEEP_TIME}" ]]; then debug "Sleeping ${DB_INIT_SLEEP_TIME} seconds before continuing with initialization" sleep "${DB_INIT_SLEEP_TIME}" fi } ######################## # Wait for WSREP to be ready to do transactions # Arguments: # None # Returns: # None ######################## wait_for_wsrep() { local -r retries=300 local -r sleep_time=2 if ! retry_while is_wsrep_ready "$retries" "$sleep_time"; then error "WSREP did not become ready" return 1 fi } ######################## # Checks for WSREP to be ready to do transactions # Arguments: # None # Returns: # Boolean ######################## is_wsrep_ready() { debug "Checking if WSREP is ready" is_ready="$(mysql_execute_print_output "mysql" "root" <> "$custom_conf_file" cat "$old_custom_conf_file" >> "$custom_conf_file" fi if am_i_root; then [[ -e "$DB_VOLUME_DIR/.initialized" ]] && rm "$DB_VOLUME_DIR/.initialized" rm -rf "$DB_VOLUME_DIR/conf" else warn "Old custom configuration migrated, please manually remove the 'conf' directory from the volume use to persist data" fi } ######################## # Ensure a db user exists with the given password for the '%' host # Globals: # DB_* # Flags: # -p|--password - database password # -u|--user - database user # --auth-plugin - authentication plugin # --use-ldap - authenticate user via LDAP # --host - database host # --port - database host # Arguments: # $1 - database user # Returns: # None ######################### mysql_ensure_user_exists() { local -r user="${1:?user is required}" local password="" local auth_plugin="" local use_ldap="no" local hosts local auth_string="" # 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 database password}" ;; --auth-plugin) shift auth_plugin="${1:?missing authentication plugin}" ;; --use-ldap) use_ldap="yes" ;; --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 if is_boolean_yes "$use_ldap"; then auth_string="identified via pam using '$DB_FLAVOR'" elif [[ -n "$password" ]]; then if [[ -n "$auth_plugin" ]]; then auth_string="identified with $auth_plugin by '$password'" else auth_string="identified by '$password'" fi fi debug "creating database user \'$user\'" local -a mysql_execute_cmd=("mysql_execute") local -a mysql_execute_print_output_cmd=("mysql_execute_print_output") if [[ -n "$db_host" && -n "$db_port" ]]; then mysql_execute_cmd=("mysql_remote_execute" "$db_host" "$db_port") mysql_execute_print_output_cmd=("mysql_remote_execute_print_output" "$db_host" "$db_port") fi local mysql_create_user_cmd [[ "$DB_FLAVOR" = "mariadb" ]] && mysql_create_user_cmd="create or replace user" || mysql_create_user_cmd="create user if not exists" "${mysql_execute_cmd[@]}" "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <=10.4, the mysql.user table was replaced with a view: https://mariadb.com/kb/en/mysqluser-table/ # Views have a definer user, in this case set to 'root', which needs to exist for the view to work # In MySQL, to avoid issues when renaming the root user, they use the 'mysql.sys' user as a definer: https://dev.mysql.com/doc/refman/5.7/en/sys-schema.html # However, for MariaDB that is not the case, so when the 'root' user is renamed the 'mysql.user' table stops working and the view needs to be fixed if [[ "$user" != "root" && ! "$(mysql_get_version)" =~ ^10.[0123]. ]]; then alter_view_str="$(mysql_execute_print_output "mysql" "$user" "$password" "-s" <&2 return 1 ;; esac shift done local -a mysql_execute_cmd=("mysql_execute") [[ -n "$db_host" && -n "$db_port" ]] && mysql_execute_cmd=("mysql_remote_execute" "$db_host" "$db_port") local -a create_database_args=() [[ -n "$character_set" ]] && create_database_args+=("character set = '${character_set}'") [[ -n "$collate" ]] && create_database_args+=("collate = '${collate}'") debug "Creating database $database" "${mysql_execute_cmd[@]}" "mysql" "$DB_ROOT_USER" "$DB_ROOT_PASSWORD" <&2 return 1 ;; esac shift done local -a flags=("$user") [[ -n "$db_host" ]] && flags+=("--host" "${db_host}") [[ -n "$db_port" ]] && flags+=("--port" "${db_port}") if is_boolean_yes "$use_ldap"; then flags+=("--use-ldap") elif [[ -n "$password" ]]; then flags+=("-p" "$password") [[ -n "$auth_plugin" ]] && flags=("${flags[@]}" "--auth-plugin" "$auth_plugin") fi mysql_ensure_user_exists "${flags[@]}" } ######################## # Optionally create the given database, and then optionally give a user # full privileges on the database. # Flags: # -u|--user - database user # --character-set - character set # --collation - collation # --host - database host # --port - database port # Arguments: # $1 - database name # Returns: # None ######################### mysql_ensure_optional_database_exists() { local -r database="${1:?database is missing}" local character_set="" local collate="" local user="" local privileges="" # For accessing an external database local db_host="" local db_port="" # Validate arguments shift 1 while [ "$#" -gt 0 ]; do case "$1" in --character-set) shift character_set="${1:?missing character set}" ;; --collate) shift collate="${1:?missing collate}" ;; -u|--user) shift user="${1:?missing database user}" ;; --host) shift db_host="${1:?missing database host}" ;; --port) shift db_port="${1:?missing database port}" ;; --privileges) shift privileges="${1:?missing privileges}" ;; *) echo "Invalid command line flag $1" >&2 return 1 ;; esac shift done local -a flags=("$database") [[ -n "$character_set" ]] && flags+=("--character-set" "$character_set") [[ -n "$collate" ]] && flags+=("--collate" "$collate") [[ -n "$db_host" ]] && flags+=("--host" "$db_host") [[ -n "$db_port" ]] && flags+=("--port" "$db_port") mysql_ensure_database_exists "${flags[@]}" if [[ -n "$user" ]]; then mysql_ensure_user_has_database_privileges "$user" "$database" "$privileges" "$db_host" "$db_port" fi } ######################## # Add or modify an entry in the MySQL configuration file ("$DB_CONF_FILE") # Globals: # DB_* # Arguments: # $1 - MySQL variable name # $2 - Value to assign to the MySQL variable # $3 - Section in the MySQL configuration file the key is located (default: mysqld) # $4 - Configuration file (default: "$BD_CONF_FILE") # Returns: # None ######################### mysql_conf_set() { local -r key="${1:?key missing}" local -r value="${2:?value missing}" read -r -a sections <<<"${3:-mysqld}" local -r ignore_inline_comments="${4:-no}" local -r file="${5:-"$DB_CONF_FILE"}" info "Setting ${key} option" debug "Setting ${key} to '${value}' in ${DB_FLAVOR} configuration file ${file}" # Check if the configuration exists in the file for section in "${sections[@]}"; do if is_boolean_yes "$ignore_inline_comments"; then ini-file set --ignore-inline-comments --section "$section" --key "$key" --value "$value" "$file" else ini-file set --section "$section" --key "$key" --value "$value" "$file" fi done } ######################## # Update MySQL/MariaDB configuration file with user custom inputs # Globals: # DB_* # Arguments: # None # Returns: # None ######################### mysql_update_custom_config() { # Persisted configuration files from old versions ! is_dir_empty "$DB_VOLUME_DIR" && [[ -d "$DB_VOLUME_DIR/conf" ]] && mysql_migrate_old_configuration # User injected custom configuration if [[ -f "$DB_CONF_DIR/my_custom.cnf" ]]; then debug "Injecting custom configuration from my_custom.conf" cat "$DB_CONF_DIR/my_custom.cnf" > "$DB_CONF_DIR/bitnami/my_custom.cnf" fi ! is_empty_value "$DB_USER" && mysql_conf_set "user" "$DB_USER" "mysqladmin" ! is_empty_value "$DB_PORT_NUMBER" && mysql_conf_set "port" "$DB_PORT_NUMBER" "mysqld client manager" ! is_empty_value "$DB_CHARACTER_SET" && mysql_conf_set "character_set_server" "$DB_CHARACTER_SET" ! is_empty_value "$DB_COLLATE" && mysql_conf_set "collation_server" "$DB_COLLATE" ! is_empty_value "$DB_BIND_ADDRESS" && mysql_conf_set "bind_address" "$DB_BIND_ADDRESS" ! is_empty_value "$DB_AUTHENTICATION_PLUGIN" && mysql_conf_set "default_authentication_plugin" "$DB_AUTHENTICATION_PLUGIN" ! is_empty_value "$DB_SQL_MODE" && mysql_conf_set "sql_mode" "$DB_SQL_MODE" ! is_empty_value "$DB_ENABLE_SLOW_QUERY" && mysql_conf_set "slow_query_log" "$DB_ENABLE_SLOW_QUERY" ! is_empty_value "$DB_LONG_QUERY_TIME" && mysql_conf_set "long_query_time" "$DB_LONG_QUERY_TIME" # Avoid exit code of previous commands to affect the result of this function true } ######################## # Find the path to the libjemalloc library file # Globals: # None # Arguments: # None # Returns: # Path to a libjemalloc shared object file ######################### find_jemalloc_lib() { local -a locations=( "/usr/lib" "/usr/lib64" ) local -r pattern='libjemalloc.so.[0-9]' local path for dir in "${locations[@]}"; do # Find the first element matching the pattern and quit [[ ! -d "$dir" ]] && continue path="$(find "$dir" -name "$pattern" -print -quit)" [[ -n "$path" ]] && break done echo "${path:-}" } ######################## # Execute a reliable health check against the current mysql instance # Globals: # DB_ROOT_USER, DB_ROOT_PASSWORD, DB_MASTER_ROOT_PASSWORD # Arguments: # None # Returns: # mysqladmin output ######################### mysql_healthcheck() { local args=("-u${DB_ROOT_USER}" "-h0.0.0.0") local root_password root_password="$(get_master_env_var_value ROOT_PASSWORD)" if [[ -n "$root_password" ]]; then args+=("-p${root_password}") fi mysqladmin "${args[@]}" ping && mysqladmin "${args[@]}" status } ######################## # Prints flavor of 'mysql' client (useful to determine proper CLI flags that can be used) # Globals: # DB_* # Arguments: # None # Returns: # mysql client flavor ######################### mysql_client_flavor() { if "${DB_BIN_DIR}/mysql" "--version" 2>&1 | grep -q MariaDB; then echo "mariadb" else echo "mysql" fi } ######################## # Prints extra options for MySQL client calls (i.e. SSL options) # Globals: # DB_* # Arguments: # None # Returns: # List of options to pass to "mysql" CLI ######################### mysql_client_extra_opts() { # Helper to get the proper value for the MySQL client environment variable mysql_client_env_value() { local env_name="MYSQL_CLIENT_${1:?missing name}" if [[ -n "${!env_name:-}" ]]; then echo "${!env_name:-}" else env_name="DB_CLIENT_${1}" echo "${!env_name:-}" fi } local -a opts=() local key value if is_boolean_yes "${DB_ENABLE_SSL:-no}"; then if [[ "$(mysql_client_flavor)" = "mysql" ]]; then opts+=("--ssl-mode=REQUIRED") else opts+=("--ssl=TRUE") fi # Add "--ssl-ca", "--ssl-key" and "--ssl-cert" options if the env vars are defined for key in ca key cert; do value="$(mysql_client_env_value "SSL_${key^^}_FILE")" [[ -n "${value}" ]] && opts+=("--ssl-${key}=${value}") done else # Skip SSL validation if [[ "$(mysql_client_flavor)" = "mariadb" ]]; then # SSL connections are enabled by default in MariaDB >=10.11 local mysql_version="" local major_version="" local minor_version="" mysql_version="$(mysql_get_version)" major_version="$(get_sematic_version "${mysql_version}" 1)" minor_version="$(get_sematic_version "${mysql_version}" 2)" if [[ "${major_version}" -gt 10 ]] || [[ "${major_version}" -eq 10 && "${minor_version}" -eq 11 ]]; then opts+=("--skip-ssl") fi fi fi echo "${opts[@]:-}" }