docker_test/common.bash (189 lines of code) (raw):
# Common variables and functions
# Source the common.bash file from the same path as the script
source $(dirname "$0")/ansi_clean.bash
#MANUAL_PROJECT_NAME=project_name
DOCKER_PORT=9200
LOCAL_PORT=9200
URL_HOST=127.0.0.1
ESUSR=elastic
ENVFILE=.env
SHELLENVFILE=.env-shell
CURLFILE=.kurl
REPODOCKER=/media
REPOJSON=createrepo.json
REPONAME=testing
LIMIT=30 # How many seconds to wait to obtain the credentials
IMAGE=docker.elastic.co/elasticsearch/elasticsearch
MEMORY=1GB # The heap will be half of this
JAVA_OPTS="-Xms512m -Xmx512m"
CLUSTER_NAME="docker_test"
DISCOVERY_TYPE="single-node"
#############################
### Function declarations ###
#############################
docker_logline () {
# Return the line number that contains "${1}"
echo $(docker logs ${NAME} | grep -n "${1}" | awk -F\: '{print $1}')
}
initial_value () {
# $1 is the value representation
local searchstr=''
case ${1} in
'password')
searchstr='elasticsearch-reset-password'
;;
'nodetoken')
searchstr='\--enrollment-token'
;;
esac
local linenum=$(docker_logline ${searchstr})
# Increment the linenum (because we want the next line)
((++linenum))
# Get the (next) line, i.e. incremented and tailed to isolate
retval=$(docker logs ${NAME} | head -n ${linenum} | tail -1 | awk '{print $1}')
# Strip the ANSI color/bold here. External function because of the control-M sequence
ansi_clean "${retval}"
}
add2envfiles () {
# $1 is the env var name
# $2 is the value
echo "${1}=\"${2}\"" >> ${ENVCFG}
echo "export ${1}=\"${2}\"" >> ${SHELLENVCFG}
}
get_espw () {
# Start with an empty value
linenum=''
# Make a pretty spinner
spin='-\|/'
# spin modulo tracker
s=0
# tenths incrementer (of a second)
tenths=0
# tenths modulo tracker
t=0
# seconds incrementer
seconds=0
# Loop until we get a valid line number, or LIMIT tries
while [ "x${linenum}" == "x" ] && [ $seconds -lt $LIMIT ]; do
# increment $s and modulo 4
s=$(( (s+1) %4 ))
# increment $tenths
((++tenths))
# increment $t and modulo 10
t=$(( (t+1) %10 ))
# if $t is 0 (it was evenly divisible by 10)
if [ $t -eq 0 ]; then
# we increment seconds, because 1 second has elapsed
((++seconds))
# Get the docker log line associated with elasticsearch-reset-password
linenum=$(docker_logline "elasticsearch-reset-password")
fi
# Print the spinner to stderr (so it shows up)
printf "\r${spin:$s:1} ${seconds}s elapsed (typically 15s - 25s)..." >&2
# wait 1/10th of a second before looping again
sleep 0.1
done
# end while loop
# Error out if we didn't get it
if [ "x${linenum}" == "x" ] || [ $seconds -ge $LIMIT ]; then
echo "ERROR: Unable to get password for user ${ESUSR}. Unable to continue. Exiting..."
exit 1
fi
ESPWD=$(initial_value 'password')
NODETOKEN=$(initial_value 'nodetoken')
}
change_espw () {
# To shorten the command-line, we put this as a variable
exec_cmd=/usr/share/elasticsearch/bin/elasticsearch-reset-password
#################################################
# The change password command: #
# docker exec -it ${1} ${exec_cmd} -b -u $ESUSR #
#################################################
#############################################################################
# Output 1: Not ready response: #
# ERROR: Failed to determine the health of the cluster. , with exit code 69 #
#############################################################################
#######################################################
# Output 2: Successful response: #
# Password for the [elastic] user successfully reset. #
# New value: NEW_PASSWORD #
#######################################################
# awk '{print $3}' of the "Not ready response" is "to"
# So we start with retval='to'
retval='to'
# We're only going to try this to the $LIMIT
count=0
# Loop until we get the expected response, or LIMIT tries
while [ "x$retval" == "xto" ] && [ $count -lt $LIMIT ]; do
retval=$(docker exec -it ${NAME} $exec_cmd -b -u ${ESUSR} | tail -1 | awk '{print $3}')
((++count))
sleep 1
done
# If we still don't have a value, send an empty reponse back, rather than "to"
if [ "x${retval}" == "xto" ]; then
echo ''
else
echo ${retval}
fi
}
xpack_fork () {
echo "Getting Elasticsearch credentials from container ${NAME}..."
# Get the password from the get_espw function. It sets ESPWD
get_espw
# If we have an empty value, that's a problem
if [ "x${ESPWD}" == "x" ]; then
echo "ERROR: Unable to get password for user ${ESUSR}. Unable to continue. Exiting..."
exit 1
fi
# Add variables to .env files
add2envfiles ESCLIENT_USERNAME ${ESUSR}
add2envfiles TEST_USER ${ESUSR}
# We escape the quotes so we can include them in case of special characters
add2envfiles ESCLIENT_PASSWORD ${ESPWD}
add2envfiles TEST_PASS ${ESPWD}
# Get the CA certificate and copy it to the PROJECT_ROOT
docker cp -q ${NAME}:/usr/share/elasticsearch/config/certs/http_ca.crt ${PROJECT_ROOT}
# Put the credentials into ${CURLCFG}
echo "-u ${ESUSR}:${ESPWD}" >> ${CURLCFG}
echo "--cacert ${CACRT}" >> ${CURLCFG}
# Complete
# echo "Credentials captured!"
}
# Save original execution path
EXECPATH=$(pwd)
# Extract the path for the script
SCRIPTPATH="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)"
# Ensure we are in the script path
cd ${SCRIPTPATH}
# Get the directory name
SCRIPTPATH_NAME=$(pwd | awk -F\/ '{print $NF}')
# Go up a level
cd ../
# Find out what the last part of this directory is called
PROJECT_NAME=$(pwd | awk -F\/ '{print $NF}')
# Manually override the project name, if specified
if [ "x${MANUAL_PROJECT_NAME}" != "x" ]; then
PROJECT_NAME=${MANUAL_PROJECT_NAME}
fi
# We should be at the project root dir now
PROJECT_ROOT=$(pwd)
if [ "${SCRIPTPATH_NAME}" != "docker_test" ]; then
echo "$0 is not in parent directory 'docker_test'"
echo "This could cause issues as that is expected."
echo "PROJECT_ROOT is now set to ${SCRIPTPATH}"
echo "You may want to set MANUAL_PROJECT_NAME in common.bash"
PROJECT_ROOT=${SCRIPTPATH}
fi
# If we have a tests/integration path, then we'll use that
if [ -d "tests/integration" ]; then
TESTPATH=${PROJECT_ROOT}/tests/integration
else
# Otherwise we will just dump it into the $SCRIPTPATH
TESTPATH=${SCRIPTPATH}
fi
# Set the CACRT var
CACRT=${PROJECT_ROOT}/http_ca.crt
# Set the .env file
ENVCFG=${PROJECT_ROOT}/${ENVFILE}
SHELLENVCFG=${PROJECT_ROOT}/${SHELLENVFILE}
# Set the curl config file and ensure we're not reusing an old one
CURLCFG=${SCRIPTPATH}/${CURLFILE}
# Determine local IPs
OS=$(uname -a | awk '{print $1}')
if [[ "$OS" = "Linux" ]]; then
IPLIST=$(ip -4 -o addr show scope global | grep -v docker |awk '{gsub(/\/.*/,"",$4); print $4}')
elif [[ "$OS" = "Darwin" ]]; then
IPLIST=$(ifconfig | awk -F "[: ]+" '/inet / { if ($2 != "127.0.0.1") print $2 }')
else
echo "Could not determine local IPs for assigning environment variables..."
echo "Please manually determine your local non-loopback IP address and assign it,"
echo "e.g. TEST_ES_SERVER=https://A.B.C.D:${LOCAL_PORT}"
exit 0
fi
#######################
### Set Docker vars ###
#######################
# Set the TRUNK
TRUNK=${PROJECT_NAME}-test
# Set the Docker container number
NUM=0
# Set the Docker container name
NAME=${TRUNK}-${NUM}
# Set the bind mount path for the snapshot repository
REPOLOCAL=${SCRIPTPATH}/repo
# Navigate back to the script path
cd ${SCRIPTPATH}
############################
### URL CHECKER FUNCTION ###
############################
check_url () {
# URL = $1
# EXPECTED = $2
if [ "x${EXPECTED}" == "x" ]; then
local EXPECTED=200
else
local EXPECTED=${2}
fi
# Start with an empty value
local ACTUAL=0
# Initialize loop counter
local COUNTER=0
# Loop until we get our 200 code
while [ "${ACTUAL}" != "${EXPECTED}" ] && [ ${COUNTER} -lt ${LIMIT} ]; do
# Get our actual response
ACTUAL=$(curl -K ${CURLCFG} ${1})
# If we got what we expected, we're great!
if [ "${ACTUAL}" != "${EXPECTED}" ]; then
# Sleep and try again
sleep 1
((++COUNTER))
fi
done
# End while loop
# If we still don't have what we expected, we hit the LIMIT
if [ "${ACTUAL}" != "${EXPECTED}" ]; then
echo "Unable to connect to ${1} in ${LIMIT} seconds. Unable to continue. Exiting..."
exit 1
fi
echo ${ACTUAL}
}
################################
### Start a Docker container ###
################################
start_container () {
# $1 node_number
# $2 enrollment_token
# $3 node roles
if [ "x${2}" == "x" ]; then
local token=''
else
local token=${2}
fi
if [ "x${3}" == "x" ]; then
local roles="'data', 'data_cold', 'data_content', 'data_hot', 'data_warm', 'ingest', 'master'"
else
local roles="${3}"
fi
local fromzero=$(( ${1} - 1 ))
local nodename="${TRUNK}-${fromzero}"
local portnum=$(( 9200 + ${fromzero} ))
echo -en "Container ID: "
docker run -q -d -it \
--name ${nodename} \
--network ${TRUNK}-net \
-m ${MEMORY} \
-p ${portnum}:${DOCKER_PORT} \
-v ${REPOLOCAL}:${REPODOCKER} \
-e ENROLLMENT_TOKEN="${token}" \
-e ES_JAVA_OPTS="${JAVA_OPTS}" \
-e "discovery.type=${DISCOVERY_TYPE}" \
-e "cluster.name=${CLUSTER_NAME}" \
-e "node.name=node-${fromzero}" \
-e "node.roles=[${roles}]" \
-e "xpack.searchable.snapshot.shared_cache.size=100MB" \
-e "xpack.monitoring.templates.enabled=false" \
-e "path.repo=${REPODOCKER}" \
${IMAGE}:${VERSION}
}
##################
### END COMMON ###
##################