#!/bin/bash # Copyright Broadcom, Inc. All Rights Reserved. # SPDX-License-Identifier: APACHE-2.0 # # Bitnami Grafana library # shellcheck disable=SC1091 # Load generic libraries . /opt/bitnami/scripts/liblog.sh . /opt/bitnami/scripts/libos.sh . /opt/bitnami/scripts/libvalidations.sh . /opt/bitnami/scripts/libversion.sh # Load database library if [[ -f /opt/bitnami/scripts/libmysqlclient.sh ]]; then . /opt/bitnami/scripts/libmysqlclient.sh elif [[ -f /opt/bitnami/scripts/libmysql.sh ]]; then . /opt/bitnami/scripts/libmysql.sh elif [[ -f /opt/bitnami/scripts/libmariadb.sh ]]; then . /opt/bitnami/scripts/libmariadb.sh fi ######################## # Print the value of a Grafana environment variable # Globals: # GF_* # GRAFANA_CFG_* # Arguments: # None # Returns: # The value in the environment variable ######################### grafana_env_var_value() { local -r name="${1:?missing name}" local gf_env_var="GF_${name}" local grafana_cfg_env_var="GRAFANA_CFG_${name}" if [[ -n "${!gf_env_var:-}" ]]; then echo "${!gf_env_var:-}" elif [[ -n "${!grafana_cfg_env_var}" ]]; then echo "${!grafana_cfg_env_var:-}" else error "${gf_env_var} or ${grafana_cfg_env_var} must be set" fi } ######################## # Validate settings in GRAFANA_* env vars # Globals: # GRAFANA_* # Arguments: # None # Returns: # 0 if the validation succeeded, 1 otherwise ######################### grafana_validate() { debug "Validating settings in GRAFANA_* environment variables..." local error_code=0 # Auxiliary functions print_validation_error() { error "$1" error_code=1 } check_path_exists() { if [[ ! -e "$1" ]]; then print_validation_error "The directory ${1} does not exist" fi } # Validate user inputs [[ -e "$GF_OP_PATHS_CONFIG" ]] || check_path_exists "$(grafana_env_var_value PATHS_CONFIG)" [[ -e "$GF_OP_PATHS_DATA" ]] || check_path_exists "$(grafana_env_var_value PATHS_DATA)" [[ -e "$GF_OP_PATHS_LOGS" ]] || check_path_exists "$(grafana_env_var_value PATHS_LOGS)" [[ -e "$GF_OP_PATHS_PROVISIONING" ]] || check_path_exists "$(grafana_env_var_value PATHS_PROVISIONING)" return "$error_code" } ######################## # Ensure Grafana is initialized # Globals: # GRAFANA_* # Arguments: # None # Returns: # None ######################### grafana_initialize() { # Ensure compatibility with Grafana Operator local grafana_var grafana_operator_var for path_suffix in "config" "data" "logs" "provisioning"; do grafana_var="GF_PATHS_${path_suffix^^}" grafana_operator_var="GF_OP_PATHS_${path_suffix^^}" if [[ -e "${!grafana_operator_var}" && "${!grafana_operator_var}" != "${!grafana_var}" ]]; then info "Ensuring ${!grafana_operator_var} points to ${!grafana_var}" rm -rf "${!grafana_var}" ln -sfn "${!grafana_operator_var}" "${!grafana_var}" fi done if am_i_root; then for dir in "$GF_PATHS_DATA" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS"; do is_mounted_dir_empty "$dir" && configure_permissions_ownership "$dir" -d "775" -f "664" -u "$GRAFANA_DAEMON_USER" done fi # Install plugins in a Grafana operator-compatible environment, useful to for starting the image as an init container # Based on https://github.com/grafana-operator/grafana-operator/blob/master/controllers/grafana/pluginsHelper.go if [[ -d "$GF_OP_PLUGINS_INIT_DIR" ]]; then info "Detected mounted plugins directory at '${GF_OP_PLUGINS_INIT_DIR}'. The container will exit after installing plugins as grafana-operator." if [[ -n "$GF_INSTALL_PLUGINS" ]]; then GF_PATHS_PLUGINS="$GF_OP_PLUGINS_INIT_DIR" grafana_install_plugins else warn "There are no plugins to install" fi return 255 fi # Recover plugins installed when building the image if [[ ! -e "$(grafana_env_var_value PATHS_PLUGINS)" ]] || [[ -z "$(ls -A "$(grafana_env_var_value PATHS_PLUGINS)")" ]]; then mkdir -p "$(grafana_env_var_value PATHS_PLUGINS)" if [[ -e "$GRAFANA_DEFAULT_PLUGINS_DIR" ]] && [[ -n "$(ls -A "$GRAFANA_DEFAULT_PLUGINS_DIR")" ]]; then cp -r "$GRAFANA_DEFAULT_PLUGINS_DIR"/* "$(grafana_env_var_value PATHS_PLUGINS)" fi fi # Configure configuration file based on environment variables grafana_configure_from_environment_variables # Install plugins grafana_install_plugins # Configure Grafana feature toggles ! is_empty_value "$GF_FEATURE_TOGGLES" && grafana_conf_set "feature_toggles" "enable" "$GF_FEATURE_TOGGLES" # If using an external database, avoid nodes collition during migration if is_boolean_yes "$GRAFANA_MIGRATION_LOCK"; then grafana_migrate_db fi # Avoid exit code of previous commands to affect the result of this function true } ######################## # Runs Grafana migration using a database lock to avoid collision with other Grafana nodes # If database is locked, wait until unlocked and continue. Otherwise, run Grafana to perform migration. # Globals: # GRAFANA_CFG_* # Arguments: # None # Returns: # None ######################### grafana_migrate_db() { local -r db_host="${GRAFANA_CFG_DATABASE_HOST:-mysql}" local -r db_port="${GRAFANA_CFG_DATABASE_PORT:-3306}" local -r db_name="${GRAFANA_CFG_DATABASE_NAME:-}" local -r db_user="${GRAFANA_CFG_DATABASE_USER:-}" local -r db_pass="${GRAFANA_CFG_DATABASE_PASSWORD:-}" local -r grafana_host="${GRAFANA_CFG_SERVER_HTTP_ADDR:-localhost}" local -r grafana_port="${GRAFANA_CFG_SERVER_HTTP_PORT:-3000}" local -r grafana_protocol="${GRAFANA_CFG_SERVER_PROTOCOL:-http}" local -r sleep_time="${GRAFANA_SLEEP_TIME:-5}" local -r retries="${GRAFANA_RETRY_ATTEMPTS:-12}" lock_db() { debug_execute mysql_remote_execute_print_output "$db_host" "$db_port" "$db_name" "$db_user" "$db_pass" <