#!/bin/bash -e

source "es_util_env"

LOGLEVEL=${LOGLEVEL:-6}
loglevelint=6
case $LOGLEVEL in
    debug) loglevelint=7 ;;
    info) loglevelint=6 ;;
    warn) loglevelint=5 ;;
    error) loglevelint=4 ;;
    [1-7]) loglevelint=$LOGLEVEL ;;
    *) echo ERROR: LOGLEVEL must be a number from 1-7
       echo 7 is DEBUG, 4 is ERROR, default 6 is INFO
       exit 1 ;;
esac

# the deployment mounts the secrets at this location - not necessarily the same
# as $ES_PATH_CONF
secret_dir=${ES_PATH_CONF}/secret
provided_secret_dir=/etc/openshift/elasticsearch/secret

if [ -f /usr/share/java/elasticsearch/config/index_settings ]; then
    source /usr/share/java/elasticsearch/config/index_settings
fi
PRIMARY_SHARDS=${PRIMARY_SHARDS:-1}
REPLICA_SHARDS=${REPLICA_SHARDS:-0}

RETRY_COUNT=${RETRY_COUNT:-300}		# how many times
RETRY_INTERVAL=${RETRY_INTERVAL:-1}	# how often (in sec)
ES_REST_BASEURL=${ES_REST_BASEURL:-https://localhost:9200}
LOG_FILE=${LOG_FILE:-elasticsearch_connect_log.txt}
retry=$RETRY_COUNT
max_time=$(( RETRY_COUNT * RETRY_INTERVAL ))	# should be integer
timedout=false

log() {
    lvlint=$1
    if [ $loglevelint -ge $lvlint ] ; then
        shift
        lvl=$1
        shift
        printf "[%.23s][%-5s][container.run            ] " "`date -u +'%F %T,%N'`" $lvl
        echo "$@"
    fi
}

debug() {
    log 7 DEBUG "$@"
}

info() {
    log 6 INFO "$@"
}

warn() {
    log 5 WARN "$@"
}

error() {
    log 4 ERROR "$@"
}

get_hash() {
    printf "%s" "$1" | sha1sum | awk '{print $1}'
}

get_kibana_index_name() {
    echo .kibana.$(get_hash "$1")
}

get_master_node() {
    echo $(es_util --query="_cat/master?h=node")
}

check_index_exists() {
  local index=$1
  local response_code=$(es_util --query="${index}" --head -w '%{response_code}' -o /dev/null)

  [[ $response_code -eq 200 ]] || exit 1
}

# Pull in the certs provided in our secret and generate our necessary jks and truststore files
build_jks_truststores() {

  copy_keys_to_secretdir

  info "Building required jks files and truststore"

  # check for lack of admin.jks
  if [[ ! -e $secret_dir/admin.jks ]]; then
    build_jks_from_pem "admin" "admin-key" "admin-cert" "admin-ca"
  fi

  # check for elasticsearch.key and elasticsearch.crt
  if [[ -e $secret_dir/elasticsearch.key && -e $secret_dir/elasticsearch.crt && ! -e $secret_dir/searchguard.key ]]; then
    build_jks_from_pem "elasticsearch" "elasticsearch.key" "elasticsearch.crt" "admin-ca"
    mv $secret_dir/elasticsearch.jks $secret_dir/searchguard.key
  fi

  # check for logging-es.key and logging-es.crt
  if [[ -e $secret_dir/logging-es.key && -e $secret_dir/logging-es.crt && ! -e $secret_dir/key ]]; then
    build_jks_from_pem "logging-es" "logging-es.key" "logging-es.crt" "admin-ca"
    mv $secret_dir/logging-es.jks $secret_dir/key
  fi

  if [[ ! -e $secret_dir/truststore ]]; then
    keytool                                        \
      -import                                      \
      -file $secret_dir/admin-ca                   \
      -keystore $secret_dir/truststore             \
      -storepass tspass                            \
      -noprompt                                    \
      -alias sig-ca
  fi

  if [[ ! -e $secret_dir/searchguard.truststore ]]; then
    keytool                                        \
      -import                                      \
      -file $secret_dir/admin-ca                   \
      -keystore $secret_dir/searchguard.truststore \
      -storepass tspass                            \
      -noprompt                                    \
      -alias sig-ca
  fi
}

# Wait for Elasticsearch port to be opened. Fail on timeout or if response from Elasticsearch is unexpected.
wait_for_port_open() {
    rm -f $LOG_FILE
    # test for ES to be up first and that our SG index has been created
    info "Checking if Elasticsearch is ready"
    while ! response_code=$(es_util --query="/" \
        ${DEBUG:+-v} -s \
        --request HEAD --head \
        --max-time $max_time \
        -o $LOG_FILE --stderr $LOG_FILE -w '%{response_code}') || test $response_code != "200"
    do
        sleep $RETRY_INTERVAL
        (( retry -= 1 )) || :
        if (( retry == 0 )) ; then
            timedout=true
            break
        fi
    done

    if [ $timedout = true ] ; then
        error "Timed out waiting for Elasticsearch to be ready"
    else
        rm -f $LOG_FILE
        info Elasticsearch is ready and listening
        return 0
    fi
    if [ -f $LOG_FILE ] ; then
      cat $LOG_FILE
      rm -f $LOG_FILE
    fi
    exit 1
}

build_jks_from_pem() {

  jks_name=$1
  key_name=$2
  cert_name=$3
  ca_name=$4

  openssl                                   \
    pkcs12                                  \
    -export                                 \
    -in $secret_dir/$cert_name              \
    -inkey $secret_dir/$key_name            \
    -out $secret_dir/$jks_name.p12          \
    -passout pass:kspass

  keytool                                   \
    -importkeystore                         \
    -srckeystore $secret_dir/$jks_name.p12  \
    -srcstoretype PKCS12                    \
    -srcstorepass kspass                    \
    -destkeystore $secret_dir/$jks_name.jks \
    -deststoretype JKS                      \
    -deststorepass kspass                   \
    -noprompt

  keytool                                   \
    -changealias                            \
    -keystore $secret_dir/$jks_name.jks     \
    -storepass kspass                       \
    -alias 1                                \
    -destalias $jks_name

  keytool                                   \
    -import                                 \
    -file $secret_dir/$ca_name              \
    -keystore $secret_dir/$jks_name.jks     \
    -storepass kspass                       \
    -noprompt                               \
    -alias sig-ca
}

copy_keys_to_secretdir() {

  if [ -d $provided_secret_dir ] ; then
    info "Copying certs from ${provided_secret_dir} to ${secret_dir}"

    if [ ! -d $secret_dir ] ; then
      mkdir $secret_dir
    fi

    cp $provided_secret_dir/* $secret_dir/
    chmod 0600 $secret_dir/*
  fi
}
