#!/bin/bash
#
# This script runs the Jenkins server inside the Docker container.
# It copies the configuration and plugins from /opt/openshift/configuration to
# ${JENKINS_HOME}.
#
# It also sets the admin password to ${JENKINS_PASSWORD}.
#

default_version=$(cat /tmp/release.version)
JENKINS_SLAVE_IMAGE_TAG=${JENKINS_SLAVE_IMAGE_TAG:-${default_version}}

create_jenkins_location_configuration_xml() {
  # Gets the jenkins URL only from the *first* route available in namespace service the service named $JENKINS_SERVICE_NAME
  JENKINS_SCHEME="https://"
  if [ $( oc get routes -o json | jq -c -r '.items[0].spec.tls')  == "null" ]; then
    JENKINS_SCHEME="http://"
  fi
  JENKINS_URL="$JENKINS_SCHEME$(oc get routes -o json | jq -c -r '.items[0].spec | select (.to.name == env.JENKINS_SERVICE_NAME ) | .host ')"
  echo "Using JENKINS_SERVICE_NAME=$JENKINS_SERVICE_NAME"
  echo "Generating jenkins.model.JenkinsLocationConfiguration.xml using (${JENKINS_HOME}/jenkins.model.JenkinsLocationConfiguration.xml.tpl) ..."
  export JENKINS_URL
  echo "Jenkins URL set to: $JENKINS_URL in file: ${JENKINS_HOME}/jenkins.model.JenkinsLocationConfiguration.xml"
  envsubst < "${image_config_dir}/jenkins.model.JenkinsLocationConfiguration.xml.tpl" > "${JENKINS_HOME}/jenkins.model.JenkinsLocationConfiguration.xml"
}

create_jenkins_location_configuration_xml

source /usr/local/bin/jenkins-common.sh
source /usr/local/bin/kube-slave-common.sh

shopt -s dotglob

function update_admin_password() {
  # get random admin dir
  ADMIN_DIR=`ls /var/lib/jenkins/users | grep admin`
  ls ${JENKINS_HOME}/users/${ADMIN_DIR}
  new_password_hash=$(obfuscate_password ${JENKINS_PASSWORD:-password})
  sed -i "s,<passwordHash>.*</passwordHash>,<passwordHash>#jbcrypt:$new_password_hash</passwordHash>,g" "${JENKINS_HOME}/users/${ADMIN_DIR}/config.xml"
  echo $new_password_hash > ${JENKINS_HOME}/password
}

function create_jenkins_config_xml() {
  # copy the default configuration from the image into the jenkins config path (which should be a volume for persistence).
  if [ ! -f "${image_config_path}" ]; then
    # If it contains a template (tpl) file, we can do additional manipulations to customize
    # the configuration.
    if [ -f "${image_config_path}.tpl" ]; then
      export KUBERNETES_CONFIG=$(generate_kubernetes_config)
      echo "Generating kubernetes-plugin configuration (${image_config_path}.tpl) ..."
      # we check the value of KUBE_CA here too, but print an informational message
      # in the log here, vs. simply not including it in the config returned by the echo
      # performed in generate_kubernetes_config
      if [ ! -z "${KUBE_CA}" ]; then
        openssl x509 -in $KUBE_CA > /dev/null
        if [ $? -eq 1 ] ; then
            echo "The file referenced by the KUBE_CA environment variable does not have a valid x509 certificate."
            echo "You will need to manually configure the server certificate used by the kubernetes-plugin."
        fi
      fi
      export ADMIN_MON_CONFIG=$(generate_administrative_monitors_config)
      echo "Generating administrative monitor configuration (${image_config_path}.tpl) ..."
      envsubst < "${image_config_path}.tpl" > "${image_config_path}"
    fi
  fi
}

function generate_administrative_monitors_config() {
  if [[ "${DISABLE_ADMINISTRATIVE_MONITORS}" == "true" ]]; then
      echo '
        <string>hudson.model.UpdateCenter$CoreUpdateMonitor</string>
        <string>jenkins.security.UpdateSiteWarningsMonitor</string>
      '
      return
  fi
  echo ""
}

function create_jenkins_proxy_xml() {

  if [ ! -f "${image_config_dir}/proxy.yaml" ]; then
    if [ -f "${image_config_dir}/proxy.yaml.tpl" ]; then
      if [ -n "$http_proxy" ]; then
        json=$( parse_url $http_proxy )
        export PROXY_HOST=$( echo $json | jq -r .host)
        export PROXY_PORT=$( echo $json | jq -r .port)
        export PROXY_USER=$( echo $json | jq -r .username)
        export PROXY_PASSWORD=$( echo $json | jq -r .password)
        if [ -n "$no_proxy" ]; then
          export NO_PROXY=$(convert_no_proxy $no_proxy)
        fi
        envsubst < "${image_config_dir}/proxy.yaml.tpl" > "${image_config_dir}/proxy.yaml"
      fi
      # create an empty proxy.yaml file anyway because it is configured in the template
      touch ${image_config_dir}/proxy.yaml
    fi
  fi
}

function create_jenkins_config_from_templates() {
  find ${image_config_dir} -type f -name "*.tpl" -print0 | while IFS= read -r -d '' template_path; do
    local target_path=${template_path%.tpl}
    if [[ ! -f "${target_path}" ]]; then
      case "${target_path}" in
        "${image_config_path}")
          create_jenkins_config_xml
          ;;
        "${image_config_dir}/proxy.yaml")
          create_jenkins_proxy_xml
          ;;
        *)
          # Allow usage of environment variables in templated files, e.g. ${DOLLAR}MY_VAR is replaced by $MY_VAR
          DOLLAR='$' envsubst < "${template_path}" > "${target_path}"
          ;;
      esac
    fi
  done
}

function install_plugins() {
  # If the INSTALL_PLUGINS variable is populated, then attempt to install
  # those plugins before copying them over to JENKINS_HOME
  # The format of the INSTALL_PLUGINS variable is a comma-separated list
  # of pluginId:pluginVersion strings
  if [[ -n "${INSTALL_PLUGINS:-}" ]]; then
    echo "Installing additional plugins: ${INSTALL_PLUGINS} ..."

    # Create a temporary file in the format of plugins.txt
    plugins_file=$(mktemp)
    IFS=',' read -ra plugins <<< "${INSTALL_PLUGINS}"
    for plugin in "${plugins[@]}"; do
      echo "${plugin}" >> "${plugins_file}"
    done

    # Call install plugins with the temporary file
    /usr/local/bin/install-plugins.sh "${plugins_file}"
  fi
  
  if [ "$(ls /opt/openshift/plugins/* 2>/dev/null)" ]; then
    mkdir -p ${JENKINS_HOME}/plugins
    echo "Copying $(ls /opt/openshift/plugins/* | wc -l) files to ${JENKINS_HOME} ..."
    # in case of rhel, if there are plugins in /opt/openshift/plugins, that means the user is overriding
    # the image's base set of plugins and taking ownership of the plugin's version going forward; and
    # so we break the link to /usr/lib/jenkins via use of --remove-destination; in the case of centos, it
    # is not necessary (no links are in play) but has no ill effect so we maintain a common path for
    # both offerings
    for FILENAME in /opt/openshift/plugins/* ; do
        # also need to nuke the metadir; it will get properly populated on jenkins startup
        basefilename=`basename $FILENAME .jpi`
        rm -rf "${JENKINS_HOME}/plugins/${basefilename}"
  	cp --remove-destination $FILENAME ${JENKINS_HOME}/plugins
    done
    rm -rf /opt/openshift/plugins
  fi
}

function migrate_slave_configuration() {
  # replace [docker.io/]openshift/jekins-agent-xxxx-centos7[:optionaltag] with docker.io/openshift/jenkins-agent-xxxx-centos7:VersionTag
  sed -i "s#<image>\(docker.io/\)\{0,1\}openshift/jenkins-agent-maven-35-centos7\(:.*\)\{0,1\}</image>#<image>docker.io/openshift/jenkins-agent-maven-35-centos7:${JENKINS_SLAVE_IMAGE_TAG}</image>#" /var/lib/jenkins/config.xml
  sed -i "s#<image>\(docker.io/\)\{0,1\}openshift/jenkins-agent-nodejs-8-centos7\(:.*\)\{0,1\}</image>#<image>docker.io/openshift/jenkins-agent-nodejs-8-centos7:${JENKINS_SLAVE_IMAGE_TAG}</image>#" /var/lib/jenkins/config.xml

  # replace registry.access.redhat.com/openshift3/jekins-agent-xxxx-rhel7[:optionaltag] with registry.access.redhat.com/openshift3/jenkins-agent-xxxx-rhel7:VersionTag
  sed -i "s#<image>registry.access.redhat.com/openshift3/jenkins-agent-maven-35-rhel7\(:.*\)\{0,1\}</image>#<image>registry.access.redhat.com/openshift3/jenkins-agent-maven-35-rhel7:${JENKINS_SLAVE_IMAGE_TAG}</image>#" /var/lib/jenkins/config.xml
  sed -i "s#<image>registry.access.redhat.com/openshift3/jenkins-agent-nodejs-8-rhel7\(:.*\)\{0,1\}</image>#<image>registry.access.redhat.com/openshift3/jenkins-agent-nodejs-8-rhel7:${JENKINS_SLAVE_IMAGE_TAG}</image>#" /var/lib/jenkins/config.xml
}

function force_copy_plugins() {
  echo "Either the version of this image does not match the version"
  echo "of this existing deployment, or that equality could not be established."
  echo "A one time replacement of all the plugins from the image to the"
  echo "jenkins plugin directory will occur."
  echo ""
  echo "Image version: ${OPENSHIFT_JENKINS_IMAGE_VERSION}"
  deploymentversion=`cat ${JENKINS_HOME}/image-version`
  echo "Deployment version: ${deploymentversion}"
  if [ "$(ls /usr/lib/jenkins/*.hpi 2>/dev/null)" ]; then
    # if rhel
    for FILENAME in /usr/lib/jenkins/*.hpi ; do
      basefilename=`basename $FILENAME .hpi`
      plugin_image_volume_location="${JENKINS_HOME}/plugins/${basefilename}.jpi"
      echo "Force linking ${FILENAME} to ${plugin_image_volume_location}"
      ln -sf $FILENAME $plugin_image_volume_location
      # also need to nuke the metadir; it will get properly populated on jenkins startup
      rm -rf "${JENKINS_HOME}/plugins/${basefilename}"
    done
  else
    #if centos
    # first a one time clean up:  there were versions of 3.6 and 3.7 that
    # mistakingly installed optional plugins;  those optional plugins, at
    # the older levels, will mess up plugins we do install at 3.9 or later;
    # we are removing those here
    rm -rf $JENKINS_HOME/plugins/managed-scripts*
    install_plugins
  fi 
}

# extract the different element of an url into a JSON structure
function parse_url() {
  # extract the protocol
  proto="$(echo $1 | cut -f1 -d: )"
  if [[ ! -z $proto ]] ; then
    # remove the protocol
    url="$(echo ${1/"$proto://"/})"
    # extract the user (if any)
    login="$(echo $url | grep @ | cut -d@ -f1)"
    username="$(echo $login | cut -d: -f1)"
    password="$(echo $login | cut -d: -f2)"
    # extract the host
    host_port="$(echo ${url/$login@/} | cut -d/ -f1) "
    host="$(echo $host_port | cut -f1 -d:) "
    
    # by request - try to extract the port
    port="$(echo $host_port | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')"
    # extract the uri (if any)
    resource="/$(echo $url | grep / | cut -d/ -f2-)"
  fi
  echo -n "{ \"uri\": \"$1\" , \"url\": \"$url\" , \"proto\": \"$proto\" , \"login\": \"$login\" ,"
  echo  " \"username\": \"$username\" , \"password\": \"$password\" , \"host\": \"$host\" , \"port\": \"$port\" }"
}

# converts .google.fr,.google.com into *.google.fr|*.google.com
convert_no_proxy() {
  local urls
  urls=$1
  echo "kubernetes.default|"$( echo "$urls" | tr , \| | sed 's/\./\*\./' | sed 's/|\./|\*\./g' )
}


function get_java_proxy_config() {
  local config proto json username password
  # -Dhttps.proxyHost=<your_proxy_host>
  # -Dhttps.proxyPort=3128
  # -Dhttps.proxyUser=your-proxy-user 
  # -Dhttps.proxyPassword=your-proxy-password
  # -Dhttp.nonProxyHosts="*.svc|*.svc.cluster.*|*.svc.cluster.local|172.30.*|kubernetes.default|172.30.0.1"
  proto=$1
  json=$2
  config="-D$proto.proxyHost=$(echo $json | jq -r .host)  -D$proto.proxyPort=$(echo $json | jq -r .port) "
  config="$config -D$proto.proxy=http://$(echo $json | jq -r .host | sed -e 's/[[:space:]]//g'):$(echo $json | jq -r .port)"
  username=$(echo $json | jq -r .username )
  if [ -n $username ]; then
    config="$config -D$proto.proxyUser=$username -Dproxy.username=$username"
  fi
  password=$(echo $json | jq -r .password )
  if [ -n $password ]; then
    config="$config -D$proto.proxyPassword=$password -Dproxy.password=$password"
  fi
  if [ -n "$no_proxy" ]; then
    config="$config -D$proto.nonProxyHosts=$(convert_no_proxy $no_proxy) -Dno.proxy=$no_proxy"
  fi
  echo $config
}


CONTAINER_MEMORY_IN_BYTES=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
CONTAINER_MEMORY_IN_MB=$((CONTAINER_MEMORY_IN_BYTES/2**20))

export JAVA_VERSION=${USE_JAVA_VERSION:=java-11}

export JAVA_VERSION=${USE_JAVA_VERSION:=java-11} | grep $JAVA_VERSION |
if [[ "$(uname -m)" == "x86_64" ]]; then
	alternatives --set java $(alternatives --display java | grep $JAVA_VERSION | awk '/family.*x86_64/ { print $1; }')
	alternatives --set javac $(alternatives --display javac | grep $JAVA_VERSION | awk '/family.*x86_64/ { print $1; }')
#set JVM for all other archs
else
  alternatives --set java $(alternatives --display java | grep $JAVA_VERSION | awk '/family.*'$(uname -m)'/ { print $1; }')
  alternatives --set javac $(alternatives --display javac | grep $JAVA_VERSION | awk '/family.*'$(uname -m)'/ { print $1; }')
fi

echo "CONTAINER_MEMORY_IN_MB='${CONTAINER_MEMORY_IN_MB}', using $(readlink /etc/alternatives/java) and $(readlink /etc/alternatives/javac)"

image_config_dir="/opt/openshift/configuration"
image_config_path="${image_config_dir}/config.xml"

if [[ -z "${JAVA_TOOL_OPTIONS}" ]]; then
  # these options will automatically be picked up by any JVM process but can
  # be overridden on that process' command line.
  # Container support is now integrated in Java 11, the +UseCGroupMemoryLimitForHeap option has been pruned
  JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true"
  export JAVA_TOOL_OPTIONS
fi

# update system java keystore with custom ca bundle from jenkins-trust-ca-bundle configmap
# ca bundle is injected by network operator via the configmap jenkins-trusted-ca-bundle
# see certificate-injection-using-operators_configuring-a-custom-pki in the documentation
system_ca_bundle_crt="/etc/pki/ca-trust/source/anchors/ca-bundle.crt"
if [ -f "${system_ca_bundle_crt}" ]; then
  /usr/bin/p11-kit extract --format=java-cacerts --filter=ca-anchors --overwrite --purpose server-auth ${JENKINS_HOME}/ca-anchors-keystore
fi

# assume k8s/docker memory limit was set if memory.limit_in_bytes < 1TiB
if [[ "${CONTAINER_MEMORY_IN_BYTES}" -lt $((2**40)) ]]; then
  # set this JVM's -Xmx and -Xms if not set already (not propagated to any
  # child JVMs).  -Xmx can be calculated as a percentage, capped to a maximum,
  # or specified straight.  -Xms can be calculated as a percentage or
  # specified straight.  For the JNLP slave by default we specify -Xmx of 50%,
  # uncapped; -Xms unspecified (JVM default is 1/64 of -Xmx).

  if [[ -z "$CONTAINER_HEAP_PERCENT" ]]; then
    CONTAINER_HEAP_PERCENT=0.50
  fi

  CONTAINER_HEAP_MAX=$(echo "${CONTAINER_MEMORY_IN_MB} ${CONTAINER_HEAP_PERCENT}" | awk '{ printf "%d", $1 * $2 }')
  if [[ $JENKINS_MAX_HEAP_UPPER_BOUND_MB && $CONTAINER_HEAP_MAX -gt $JENKINS_MAX_HEAP_UPPER_BOUND_MB ]]; then
    CONTAINER_HEAP_MAX=$JENKINS_MAX_HEAP_UPPER_BOUND_MB
  fi
  if [[ -z "$JAVA_MAX_HEAP_PARAM" ]]; then
    JAVA_MAX_HEAP_PARAM="-Xmx${CONTAINER_HEAP_MAX}m"
  fi

  if [[ "$CONTAINER_INITIAL_PERCENT" ]]; then
    CONTAINER_INITIAL_HEAP=$(echo "${CONTAINER_HEAP_MAX} ${CONTAINER_INITIAL_PERCENT}" | awk '{ printf "%d", $1 * $2 }')
    if [[ -z "$JAVA_INITIAL_HEAP_PARAM" ]]; then
      JAVA_INITIAL_HEAP_PARAM="-Xms${CONTAINER_INITIAL_HEAP}m"
    fi
  fi
fi

if [[ -z "$JAVA_GC_OPTS" ]]; then
  # See https://developers.redhat.com/blog/2014/07/22/dude-wheres-my-paas-memory-tuning-javas-footprint-in-openshift-part-2/ .
  # The values are aggressively set with the intention of relaxing GC CPU time
  # restrictions to enable it to free as much as possible, as well as
  # encouraging the GC to free unused heap memory back to the OS.
  JAVA_GC_OPTS="-XX:+UseParallelGC -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90"
fi

if [[ "${USE_JAVA_DIAGNOSTICS}" || "${JAVA_DIAGNOSTICS}" ]]; then
  echo "Warning: USE_JAVA_DIAGNOSTICS and JAVA_DIAGNOSTICS are legacy and may be removed in a future version of this script."
fi

if [[ "${USE_JAVA_DIAGNOSTICS}" ]]; then
  JAVA_DIAGNOSTICS="-XX:NativeMemoryTracking=summary -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UnlockDiagnosticVMOptions"
fi

if [[ "${CONTAINER_CORE_LIMIT}" ]]; then
  JAVA_CORE_LIMIT="-XX:ParallelGCThreads=${CONTAINER_CORE_LIMIT} -Djava.util.concurrent.ForkJoinPool.common.parallelism=${CONTAINER_CORE_LIMIT} -XX:CICompilerCount=2"
fi

mkdir /tmp/war
unzip -q /usr/lib/jenkins/jenkins.war -d /tmp/war

# finish the move of the default logs dir, /var/log/jenkins, to the volume mount
mkdir -p ${JENKINS_HOME}/logs
ln -sf ${JENKINS_HOME}/logs /var/log/jenkins

# clean up any plugins in JENKINS_HOME/plugins which we previously linked, but
# have since deleted from the image
for FILENAME in ${JENKINS_HOME}/plugins/*.jpi; do
  # test if it is a sym link, otherwise users have overriden, so leave alone
  # test command silent, don't need dev/null
  test -h $FILENAME
  if [ $? -eq 0 ]; then
    stat -L $FILENAME >& /dev/null
  if [ $? -eq 0 ]; then
    continue
  fi
    echo "Unlinking plugin ${FILENAME} since it has been removed"
    unlink $FILENAME
  fi
done

shopt -s nocasematch
if [[ -z "${OVERRIDE_RELEASE_MIGRATION_OVERWRITE}" || \
   "${OVERRIDE_RELEASE_MIGRATION_OVERWRITE}" != "false" ]]; then
  # image release migration
  if [[ ! -e ${JENKINS_HOME}/image-version && -e ${JENKINS_HOME}/configured ]]; then
    # 1) if the image-version file does not exist, but the configured file does, then we are upgrading from
    # earlier versions of the image which may have not sorted out the migration
    # scenario for PVs; we will do a one time replace of the /var/lib/jenkins/plugins
    # files from the appropriate image source
    force_copy_plugins
  elif [ -e ${JENKINS_HOME}/image-version ]; then
    # 2) if the image-version file does exist, but does not match this image
    # then do the one time replace
    currentversion=`cat ${JENKINS_HOME}/image-version`
    if [ "${currentversion}" != "${OPENSHIFT_JENKINS_IMAGE_VERSION}" ]; then
      force_copy_plugins
    fi
  fi
fi
shopt -u nocasematch
echo ${OPENSHIFT_JENKINS_IMAGE_VERSION} > ${JENKINS_HOME}/image-version


# otherwise, for rhel, while the plugins are initially linked to the image volume on initial start,
# some maintenance wrt transferring plugins is done on every startup;  this logic
# covers the case of a release upgrade that introduces new plugins.
#
# we employ links instead of copies, and check for the existance in JENKINS_HOME/plugins,
# so that:
# 1) we don't copy over plugins the user has overridden since this image first was started
# (either via this image's extension mechanisms or the jenkins plugin mgr console)
# 2) if versions of an existing plugin change as a result of a release upgrade, those changes
# are picked up
# 3) if new plugins result from plugin changes within a given release, they are picked up
#
# all of this is moot on centos, since our centos image does not store any plugins in /usr/lib/jenkins
if [ "$(ls /usr/lib/jenkins/*.hpi 2>/dev/null)" ]; then
  # in case very first time through, make sure plugins dir is there
  mkdir -p ${JENKINS_HOME}/plugins
   
  for FILENAME in /usr/lib/jenkins/*.hpi ; do
    basefilename=`basename $FILENAME .hpi`
    plugin_image_volume_location="${JENKINS_HOME}/plugins/${basefilename}.*"
    if [ "$(ls ${plugin_image_volume_location} 2>/dev/null)" ]; then
      continue
    fi
    # this will link new plugins introduced into /usr/lib/jenkins to JENKINS_HOME
    echo "Linking ${FILENAME} RPM installed Jenkins plugins to ${JENKINS_HOME} ..."  
    ln -s  $FILENAME ${JENKINS_HOME}/plugins/${basefilename}.jpi
  done
   
  # since this is rhel, if it is also the initial start of the image, we can remove the 
  # the /usr/lib/jenkins/*.hpi link from /opt/openshift/plugins/*.jpi that 
  # was done in the rhel7 dockefile; that link is done to assist our s2i
  # extension scenario, so that the existing plugins are available during 
  # the s2i assemble step (which precedes the s2i run step handled by this
  # script); however, we must keep any plugins pulled in by s2i assemble, so
  # we only remove files which are the same as /usr/lib/jenkins
  #
  # also, removing the /opt/openshift/plugin file will mean install_plugins
  # will not process it, and this will preserve the links if nothing has changed so that subsequent
  # release to release migrations can work since the links will result in picking
  # up the new content in /usr/lib/jenkins
  if [ ! -e ${JENKINS_HOME}/configured ]; then
    echo "Cleaning up links to base image plugins in /opt/openshift/plugins as part of this initial image start"
    for FILENAME in /opt/openshift/plugins/* ; do
      basefilename=`basename $FILENAME .jpi`
      rpm_plugin_location="/usr/lib/jenkins/${basefilename}.hpi"
      echo "Looking at ${FILENAME} and ${rpm_plugin_location}"
      if [ "$(ls ${rpm_plugin_location} 2>/dev/null)" ]; then
        optcksum=`cksum ${FILENAME} | awk '{ print $1 }'`
        rpmcksum=`cksum ${rpm_plugin_location} | awk '{ print $1 }'`
        echo "${FILENAME} cksum ${optcksum} and ${rpm_plugin_location} cksum ${rpmcksum}"
        if [ "${optcksum}" == "${rpmcksum}" ]; then
          echo "Removing ${FILENAME}"
          rm -f $FILENAME
        fi
      fi
    done
    if [ "$(ls /opt/openshift/plugins/* 2>/dev/null)" ]; then
       echo "Remaining plugins in /opt/openshift/plugins are $(ls /opt/openshift/plugins)"
    fi
  fi
fi

if [ ! -e ${JENKINS_HOME}/configured ]; then
  # This container hasn't been configured yet
  create_jenkins_config_from_templates

  echo "Copying Jenkins configuration to ${JENKINS_HOME} ..."
  cp -r $image_config_dir/* ${JENKINS_HOME}

  install_plugins

  echo "Creating initial Jenkins 'admin' user ..."
  
  update_admin_password
  
  touch ${JENKINS_HOME}/configured
else
  shopt -s nocasematch
  if [[ ! -z "${OVERRIDE_PV_CONFIG_WITH_IMAGE_CONFIG}" && \
     "${OVERRIDE_PV_CONFIG_WITH_IMAGE_CONFIG}" != "false" ]]; then
    echo "Overriding jenkins configuration stored in ${JENKINS_HOME}"

    # remove any files/directories in $JENKINS_HOME that are specified in $image_config_dir, 
    # otherwise the two will get merged when cp is run below
    for f in ${image_config_dir}/*; do
      fileName=${f#${image_config_dir}'/'}
      if [ -e "${JENKINS_HOME}/${fileName}" ]; then
        echo "---> Removing ${JENKINS_HOME}/${fileName}..."
        rm -rf "${JENKINS_HOME}/${fileName}"
      fi
    done

    create_jenkins_config_from_templates

    echo "Copying Jenkins configuration to ${JENKINS_HOME}..."
    cp -r $image_config_dir/* ${JENKINS_HOME}
  fi
    
  if [[ ! -z "${OVERRIDE_PV_PLUGINS_WITH_IMAGE_PLUGINS}" && \
     "${OVERRIDE_PV_PLUGINS_WITH_IMAGE_PLUGINS}" != "false" ]]; then
    echo "Overriding plugins stored in ${JENKINS_HOME}/plugins"
    rm -rf ${JENKINS_HOME}/plugins

    install_plugins
  fi
  shopt -u nocasematch
fi

if [[ "${DISABLE_ADMINISTRATIVE_MONITORS}" == "true" ]]; then
    echo "Disabling administrative monitors that contact the update center"
    if [ -e "${JENKINS_HOME}/init.groovy.d/update-center-init.groovy" ]; then
	echo "Turning off startup groovy init update center administrative monitor initialization"
	mv "${JENKINS_HOME}/init.groovy.d/update-center-init.groovy" "${JENKINS_HOME}/init.groovy.d/update-center-init.disabled"
    fi
else
    echo "Administrative monitors that contact the update center will remain active"
    if [ -e "${JENKINS_HOME}/init.groovy.d/update-center-init.disabled" ]; then
	echo "Turning on startup groovy init update center administrative monitor initialization"
	mv "${JENKINS_HOME}/init.groovy.d/update-center-init.disabled" "${JENKINS_HOME}/init.groovy.d/update-center-init.groovy"
    fi
fi

if [ -e ${JENKINS_HOME}/password ]; then
  # if the password environment variable has changed, update the jenkins config.
  # we don't want to just blindly do this on startup because the user might change their password via
  # the jenkins ui, so we only want to do this if the env variable has been explicitly modified from
  # the original value.
  old_password_hash=`cat ${JENKINS_HOME}/password`
  password_changed=$(has_password_changed ${JENKINS_PASSWORD:-password} ${old_password_hash} )
  if [ "$password_changed" != "" ]; then
    echo "Detected password environment variable change, updating Jenkins configuration ..."
    update_admin_password
  fi
fi

if [ -f "${CONFIG_PATH}.tpl" -a ! -f "${CONFIG_PATH}" ]; then
  echo "Processing Jenkins configuration (${CONFIG_PATH}.tpl) ..."
  envsubst < "${CONFIG_PATH}.tpl" > "${CONFIG_PATH}"
fi

rm -rf /tmp/war

shopt -s nocasematch
if [[ -z ${SKIP_SLAVE_CONFIG_MIGRATION} || \
   "${SKIP_SLAVE_CONFIG_MIGRATION}" != "false" ]]; then
  echo "Migrating slave image configuration to current version tag ..."
  migrate_slave_configuration
fi

# default log rotation in /etc/logrotate.d/jenkins handles /var/log/jenkins/access_log
if [[ ! -z "${OPENSHIFT_USE_ACCESS_LOG}" && \
   "${OPENSHIFT_USE_ACCESS_LOG}" != "false" ]]; then
    JENKINS_ACCESSLOG="--accessLoggerClassName=winstone.accesslog.SimpleAccessLogger --simpleAccessLogger.format=combined --simpleAccessLogger.file=/var/log/jenkins/access_log"
fi
shopt -u nocasematch

## The Jenkins monitoring plugin stores its data in /var/lib/jenkins/monitoring/<hostName>.
## Since the pod name changes everytime there is a deployment, any trending data is lost over
## re-deployments. We force the application name to allow for historical data collection.
##
JENKINS_SERVICE_NAME=${JENKINS_SERVICE_NAME:-JENKINS}
JENKINS_SERVICE_NAME=`echo ${JENKINS_SERVICE_NAME} | tr '[a-z]' '[A-Z]' | tr '-' '_'`

FATAL_ERROR_OPTION=""

if [[ "${ENABLE_FATAL_ERROR_LOG_FILE}" == "true" ]]; then
    echo "Fatal error log file is true. We need to set the Error File to reside in the PV."
    FATAL_ERROR_OPTION="-XX:ErrorFile=/var/lib/jenkins/logs"
fi

if [[ -z "${JENKINS_JAVA_OPTIONS}" ]]; then
    # a discover was made upstream that if the monitor plugin is installed, it creates httpsession's via its filter, which impact the login plugin bearer token support,
    # so the displayed-counters setting turns that off
    JENKINS_JAVA_OPTIONS="$JAVA_GC_OPTS $JAVA_INITIAL_HEAP_PARAM $JAVA_MAX_HEAP_PARAM $JAVA_CORE_LIMIT $JAVA_DIAGNOSTICS "
    JENKINS_JAVA_OPTIONS="$JENKINS_JAVA_OPTIONS -Dfile.encoding=UTF8 -Djavamelody.displayed-counters=log,error $JENKINS_ACCESSLOG $FATAL_ERROR_OPTION"
    JENKINS_JAVA_OPTIONS="$JENKINS_JAVA_OPTIONS -Djava.util.logging.config.file=$JENKINS_HOME/logging.properties"
    # Add default truststore if custom ca is loaded under ${JENKINS_HOME}/ca-anchors-keystore
    if [ -f "${JENKINS_HOME}/ca-anchors-keystore" ]; then
      JENKINS_JAVA_OPTIONS="$JENKINS_JAVA_OPTIONS -Djavax.net.ssl.trustStore=${JENKINS_HOME}/ca-anchors-keystore"
    fi
fi

JAVA_HTTP_PROXY_OPTIONS="-Djdk.http.auth.tunneling.disabledSchemes= -Djdk.http.auth.proxying.disabledSchemes="
if [ -n "$http_proxy" ]; then
  json=$( parse_url $http_proxy )
  proxy=$(get_java_proxy_config http "$json")
  JAVA_HTTP_PROXY_OPTIONS="$JAVA_HTTP_PROXY_OPTIONS $proxy"
fi
if [ -n "$https_proxy" ]; then
  json=$( parse_url $https_proxy )
  proxy=$(get_java_proxy_config https "$json")
  JAVA_HTTP_PROXY_OPTIONS="$JAVA_HTTP_PROXY_OPTIONS $proxy"
fi

JENKINS_JAVA_OPTIONS="$JENKINS_JAVA_OPTIONS $JAVA_HTTP_PROXY_OPTIONS"

# Deal with embedded escaped spaces in JENKINS_JAVA_OVERRIDES.
# JENKINS_JAVA_OVERRIDES='-Dfoo -Dbar' => append -Dfoo -Dbar to java invocation
# JENKINS_JAVA_OVERRIDES='-Dfoo\ bar' => append '-Dfoo bar' to java invocation
read -a JENKINS_JAVA_OVERRIDES_ARRAY <<< "$JENKINS_JAVA_OVERRIDES"

# if `docker run` first argument start with `--` the user is passing jenkins launcher arguments
if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then
  set -x
  exec java $JENKINS_JAVA_OPTIONS -Duser.home=${HOME} \
            -Djavamelody.application-name=${JENKINS_SERVICE_NAME} \
            -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true \
            -Djenkins.install.runSetupWizard=false \
            "${JENKINS_JAVA_OVERRIDES_ARRAY[@]}" \
            -jar /usr/lib/jenkins/jenkins.war $JENKINS_OPTS "$@"
fi

# As argument is not jenkins, assume user want to run his own process, for sample a `bash` shell to explore this image
exec "$@"
