mirror of
https://github.com/bitnami/containers.git
synced 2026-03-15 14:58:17 +08:00
438 lines
13 KiB
Bash
438 lines
13 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Bitnami Solr library
|
|
|
|
# shellcheck disable=SC1091
|
|
|
|
# Load Generic Libraries
|
|
. /opt/bitnami/scripts/libfile.sh
|
|
. /opt/bitnami/scripts/liblog.sh
|
|
. /opt/bitnami/scripts/libos.sh
|
|
. /opt/bitnami/scripts/libpersistence.sh
|
|
. /opt/bitnami/scripts/libservice.sh
|
|
. /opt/bitnami/scripts/libvalidations.sh
|
|
|
|
|
|
|
|
########################
|
|
# Create initial security.json
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_generate_initial_security() {
|
|
info "Generating initial security file"
|
|
cat > "${SOLR_BASE_DIR}/server/solr/security.json" << EOF
|
|
{
|
|
"authentication":{
|
|
"blockUnknown": true,
|
|
"class":"solr.BasicAuthPlugin",
|
|
"credentials":{"${SOLR_ADMIN_USERNAME}":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="},
|
|
"forwardCredentials": false
|
|
},
|
|
"authorization":{
|
|
"class":"solr.RuleBasedAuthorizationPlugin",
|
|
"permissions":[{"name":"security-edit",
|
|
"role":"admin"}],
|
|
"user-role":{"${SOLR_ADMIN_USERNAME}":"admin"}
|
|
}}
|
|
EOF
|
|
}
|
|
|
|
########################
|
|
# Validate settings in SOLR_* env. variables
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_validate() {
|
|
info "Validating settings in SOLR_* env vars..."
|
|
local error_code=0
|
|
|
|
# Auxiliary functions
|
|
print_validation_error() {
|
|
error "$1"
|
|
error_code=1
|
|
}
|
|
|
|
! is_yes_no_value "$SOLR_ENABLE_AUTHENTICATION" && print_validation_error "SOLR_ENABLE_AUTHENTICATION posible values are yes or no"
|
|
|
|
if is_boolean_yes "$SOLR_ENABLE_AUTHENTICATION"; then
|
|
[[ -z "$SOLR_ADMIN_USERNAME" ]] && print_validation_error "You need to provide an username in SOLR_USERNAME"
|
|
[[ -z "$SOLR_ADMIN_PASSWORD" ]] && print_validation_error "You need to provide a password for the user: ${SOLR_ADMIN_USERNAME}"
|
|
fi
|
|
|
|
! is_yes_no_value "$SOLR_ENABLE_CLOUD_MODE" && print_validation_error "SOLR_ENABLE_CLOUD_MODE posible values are yes or no"
|
|
is_boolean_yes "$SOLR_ENABLE_CLOUD_MODE" && [[ -z "$SOLR_ZK_HOSTS" ]] && print_validation_error "You need to provide the Zookeper node list in SOLR_ZK_HOSTS"
|
|
! is_boolean_yes "$SOLR_CLOUD_BOOTSTRAP" && is_boolean_yes "$SOLR_ENABLE_CLOUD_MODE" && [[ -n "$SOLR_CORE" ]] && info "This node is not a boostrap node and will not create the collection"
|
|
|
|
[[ "$SOLR_NUMBER_OF_NODES" -lt $(( "$SOLR_COLLECTION_REPLICAS" * "$SOLR_COLLECTION_SHARDS" )) ]] && print_validation_error "Not enough nodes for the replicas and shards indicated"
|
|
|
|
[[ "$error_code" -eq 0 ]] || exit "$error_code"
|
|
}
|
|
|
|
########################
|
|
# Wait for Zookeeper to be up
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_wait_for_zookeeper() {
|
|
local host
|
|
local port
|
|
|
|
info "Waiting for Zookeeper to be up"
|
|
read -r -a zoo_nodes <<< "$(tr ',' ' ' <<< "${SOLR_ZK_HOSTS}")"
|
|
for zoo_node in "${zoo_nodes[@]}"; do
|
|
if [[ "$zoo_node" =~ (.*):([0-9]*) ]]; then
|
|
host="${BASH_REMATCH[1]}"
|
|
port="${BASH_REMATCH[2]}"
|
|
debug "Trying: $host:$port"
|
|
if ! retry_while "debug_execute nc -z ${host} ${port}" "$SOLR_ZK_MAX_RETRIES" "$SOLR_ZK_SLEEP_TIME"; then
|
|
error "Failed to connect to the zookeeper node at ${host}:${port}"
|
|
return 1
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
#########################
|
|
# Create SOLR core
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# $1 - Core name
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_create_core() {
|
|
local -r core="${1:?Missing core}"
|
|
local -r exec="curl"
|
|
local command_args=("--silent")
|
|
|
|
is_boolean_yes "$SOLR_ENABLE_AUTHENTICATION" && command_args+=("--user" "${SOLR_ADMIN_USERNAME}:${SOLR_ADMIN_PASSWORD}")
|
|
|
|
mkdir -p "${SOLR_SERVER_DIR}/solr/${core}/data"
|
|
cp -r "${SOLR_SERVER_DIR}"/solr/configsets/_default/* "${SOLR_SERVER_DIR}/solr/${core}/"
|
|
|
|
command_args+=( "http://localhost:${SOLR_PORT_NUMBER}/solr/admin/cores?action=CREATE&name=${SOLR_CORE}&instanceDir=${SOLR_CORE}&config=solrconfig.xml&schema=schema.xml&dataDir=data" )
|
|
|
|
info "Creating solr core: ${SOLR_CORE}"
|
|
|
|
if ! debug_execute "$exec" "${command_args[@]}" > /dev/null; then
|
|
error "There was an error when creating the core"
|
|
exit 1
|
|
else
|
|
info "Core created"
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Update user password
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# $1 - username
|
|
# $2 - password
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_update_password() {
|
|
local -r exec="curl"
|
|
local -r default_password="SolrRocks"
|
|
local -r username="${1:?user is required}"
|
|
local -r password="${2:?password is required}"
|
|
local command_args=("--silent" "--user" "${username}:${default_password}" "http://localhost:${SOLR_PORT_NUMBER}/api/cluster/security/authentication" "-H" "'Content-type:application/json'" "-d" "{\"set-user\":{\"${username}\":\"${password}\"}}" )
|
|
|
|
info "Updating user password"
|
|
|
|
if ! debug_execute "$exec" "${command_args[@]}" > /dev/null; then
|
|
error "There was an error when updating the user password"
|
|
exit 1
|
|
else
|
|
info "Password updated"
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Create SOLR cloud user
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# $1 - username
|
|
# $2 - password
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_create_cloud_user() {
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local -r username="${1:?user is required}"
|
|
local -r password="${2:?password is required}"
|
|
local command_args=("auth" "enable" "-type" "basicAuth" "-credentials" "${username}:${password}" "-blockUnknown" "true" "-z" "$SOLR_ZK_HOSTS")
|
|
|
|
info "Creating user: ${username}"
|
|
|
|
if ! debug_execute "$exec" "${command_args[@]}" > /dev/null; then
|
|
error "There was an error when creating the user"
|
|
exit 1
|
|
else
|
|
info "User created"
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Create SOLR collection
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_create_collection() {
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local command_args=("create_collection" "-c" "$SOLR_COLLECTION" "-replicationFactor" "$SOLR_COLLECTION_REPLICAS" "-shards" "$SOLR_COLLECTION_SHARDS")
|
|
|
|
info "Creating collection:${SOLR_COLLECTION} with ${SOLR_COLLECTION_REPLICAS} replicas and ${SOLR_COLLECTION_SHARDS} shards"
|
|
|
|
[[ -n "$SOLR_PORT_NUMBER" ]] && command_args+=("-p" "$SOLR_PORT_NUMBER")
|
|
|
|
#Check if the collection exists before creating it
|
|
if ! solr_collection_exists "$SOLR_COLLECTION"; then
|
|
# Will wait for other nodes to join before creating a collection with shards and/or replicas
|
|
if [[ "$SOLR_COLLECTION_REPLICAS" -gt 1 ]] || [[ "$SOLR_COLLECTION_SHARDS" -gt 1 ]]; then
|
|
info "Waiting for other nodes to be available"
|
|
if ! retry_while "solr_check_number_of_nodes ${SOLR_NUMBER_OF_NODES}" "$SOLR_ZK_MAX_RETRIES" "$SOLR_ZK_SLEEP_TIME"; then
|
|
error "There are not enough nodes to create the collection"
|
|
fi
|
|
fi
|
|
|
|
if ! debug_execute "$exec" "${command_args[@]}"; then
|
|
error "There was an error when creating the collection"
|
|
exit 1
|
|
else
|
|
info "Collection created"
|
|
fi
|
|
else
|
|
info "Skipping. Collection already exists."
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Check if a collection already exists
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# $1 - Collection name
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_collection_exists() {
|
|
local -r collection="${1:?collection is required}"
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local command_args=("zk" "ls" "/solr/collections" "-z" "$SOLR_ZK_HOSTS")
|
|
debug "Checking if ${collection} exists"
|
|
|
|
"$exec" "${command_args[@]}" | grep -q "$collection"
|
|
}
|
|
|
|
########################
|
|
# Check the number of nodes in the cluster
|
|
# Arguments:
|
|
# $1 - expected number of nodes
|
|
# Returns:
|
|
# Boolean
|
|
########################
|
|
solr_check_number_of_nodes() {
|
|
local -r nodes="${1:-1}"
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local command_args=("zk" "ls" "/solr/live_nodes" "-z" "$SOLR_ZK_HOSTS")
|
|
|
|
[[ $("$exec" "${command_args[@]}" | wc -l) -ge "$nodes" ]]
|
|
}
|
|
|
|
########################
|
|
# Check if zookeeper has been initialized
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# Boolean
|
|
########################
|
|
solr_is_zk_initialized() {
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local command_args=("zk" "ls" "/solr" "-z" "$SOLR_ZK_HOSTS")
|
|
|
|
info "Checking if solr has been initialized in zookeeper"
|
|
|
|
if ! debug_execute "$exec" "${command_args[@]}" 2> /dev/null; then
|
|
info "Zookeeper was not initialized."
|
|
return 1
|
|
else
|
|
info "Zookeeper was initialized."
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Start solr in background
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# $1 - Mode: cloud or empty
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_start_bg() {
|
|
local -r mode="${1:-}"
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local start_args=("start" "-p" "${SOLR_PORT_NUMBER}" "-d" "server")
|
|
|
|
info "Starting solr in background"
|
|
if [[ "$mode" == "cloud" ]]; then
|
|
start_args+=("-cloud" "-z" "$SOLR_ZK_HOSTS/solr")
|
|
fi
|
|
debug_execute "$exec" "${start_args[@]}"
|
|
}
|
|
|
|
#########################
|
|
# Stop SOLR
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_stop() {
|
|
info "Stopping solr"
|
|
stop_service_using_pid "$SOLR_PID_FILE"
|
|
}
|
|
|
|
#########################
|
|
# Create root in zookeeper
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_zk_initialize() {
|
|
local -r exec="${SOLR_BIN_DIR}/solr"
|
|
local command_args=("zk" "mkroot" "/solr" "-z" "$SOLR_ZK_HOSTS")
|
|
|
|
if solr_is_zk_initialized; then
|
|
info "Zookeeper is already initialized"
|
|
else
|
|
info "Creating root in zookeeper"
|
|
debug_execute "$exec" "${command_args[@]}" || true
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Create root in zookeeper
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_migrate_old_data() {
|
|
local -r exec="mv"
|
|
local command_args=("${SOLR_VOLUME_DIR}/data" "${SOLR_VOLUME_DIR}/server/solr")
|
|
|
|
if am_i_root; then
|
|
warn "Persisted data detected in old location. Migrating and changing permissions"
|
|
ensure_dir_exists "${SOLR_VOLUME_DIR}/server"
|
|
debug_execute "$exec" "${command_args[@]}"
|
|
configure_permissions_ownership "${SOLR_VOLUME_DIR}/server/solr" -d 775 -f 664 -g "root"
|
|
warn "Data migrated."
|
|
else
|
|
error "Persisted data detected in old location. You will need to run first the container as root to migrate the data"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
|
|
#########################
|
|
# Initialize SOLR
|
|
# Globals:
|
|
# SOLR_*
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#########################
|
|
solr_initialize() {
|
|
info "Initializing Solr ..."
|
|
|
|
# Check if there is persisted data from old version and migrate it
|
|
! is_dir_empty "${SOLR_VOLUME_DIR}/data" && [[ -f "$SOLR_VOLUME_DIR/.initialized" ]] && solr_migrate_old_data
|
|
|
|
# Check if Solr has already been initialized and persisted in a previous run
|
|
local -r app_name="solr"
|
|
if ! is_app_initialized "$app_name"; then
|
|
# Ensure the solr base directory exists and has proper permissions
|
|
info "Configuring file permissions for Solr"
|
|
ensure_dir_exists "$SOLR_VOLUME_DIR"
|
|
|
|
rm -f "${SOLR_TMP_DIR}/solr*.pid"
|
|
|
|
if is_boolean_yes "$SOLR_ENABLE_CLOUD_MODE"; then
|
|
info "Deploying Solr Cloud from scratch"
|
|
|
|
if ! solr_wait_for_zookeeper; then
|
|
error "Zookeeper not detected"
|
|
exit 1
|
|
fi
|
|
|
|
if is_boolean_yes "$SOLR_CLOUD_BOOTSTRAP"; then
|
|
solr_zk_initialize
|
|
|
|
solr_start_bg "cloud"
|
|
|
|
[[ -n "$SOLR_COLLECTION" ]] && solr_create_collection
|
|
is_boolean_yes "$SOLR_ENABLE_AUTHENTICATION" && solr_create_cloud_user "$SOLR_ADMIN_USERNAME" "$SOLR_ADMIN_PASSWORD"
|
|
|
|
solr_stop
|
|
fi
|
|
else
|
|
info "Deploying Solr from scratch"
|
|
|
|
is_boolean_yes "$SOLR_ENABLE_AUTHENTICATION" && solr_generate_initial_security
|
|
|
|
solr_start_bg
|
|
|
|
is_boolean_yes "$SOLR_ENABLE_AUTHENTICATION" && solr_update_password "$SOLR_ADMIN_USERNAME" "$SOLR_ADMIN_PASSWORD"
|
|
|
|
[[ -n "$SOLR_CORE" ]] && solr_create_core "$SOLR_CORE"
|
|
|
|
solr_stop
|
|
fi
|
|
|
|
info "Persisting Solr installation"
|
|
persist_app "$app_name" "$SOLR_DATA_TO_PERSIST"
|
|
else
|
|
info "Restoring persisted Solr installation"
|
|
|
|
# Compatibility with previous container images
|
|
if [[ "$(ls "$SOLR_VOLUME_DIR")" = "data" ]]; then
|
|
warn "The persisted data for this Solr installation is located at '${SOLR_VOLUME_DIR}/data' instead of '${SOLR_VOLUME_DIR}'"
|
|
warn "This is deprecated and support for this may be removed in a future release"
|
|
rm "${SOLR_BASE_DIR}/server/solr"
|
|
ln -s "${SOLR_VOLUME_DIR}/data" "${SOLR_BASE_DIR}/server/solr"
|
|
fi
|
|
restore_persisted_app "$app_name" "$SOLR_DATA_TO_PERSIST"
|
|
fi
|
|
}
|