#!/bin/bash
set -e

for file in /gitlab-configs /run/secrets/gitlab-secrets; do
	if [[ -e "$file" ]]; then
		echo "Loading $file"
		source "$file"
	fi
done
echo "Loading ${GITLAB_RUNTIME_DIR}/env-defaults"
source ${GITLAB_RUNTIME_DIR}/env-defaults

SYSCONF_TEMPLATES_DIR="${GITLAB_RUNTIME_DIR}/config"
USERCONF_TEMPLATES_DIR="${GITLAB_DATA_DIR}/config"

GITLAB_CONFIG="${GITLAB_INSTALL_DIR}/config/gitlab.yml"
GITLAB_DATABASE_CONFIG="${GITLAB_INSTALL_DIR}/config/database.yml"
GITLAB_PUMA_CONFIG="${GITLAB_INSTALL_DIR}/config/puma.rb"
GITLAB_RELATIVE_URL_CONFIG="${GITLAB_INSTALL_DIR}/config/initializers/relative_url.rb"
GITLAB_SMTP_CONFIG="${GITLAB_INSTALL_DIR}/config/initializers/smtp_settings.rb"
GITLAB_RESQUE_CONFIG="${GITLAB_INSTALL_DIR}/config/resque.yml"
GITLAB_ACTIONCABLE_CONFIG="${GITLAB_INSTALL_DIR}/config/cable.yml"
GITLAB_SECRETS_CONFIG="${GITLAB_INSTALL_DIR}/config/secrets.yml"
GITLAB_ROBOTS_CONFIG="${GITLAB_INSTALL_DIR}/public/robots.txt"
GITLAB_SHELL_CONFIG="${GITLAB_SHELL_INSTALL_DIR}/config.yml"
GITLAB_NGINX_CONFIG="/etc/nginx/conf.d/gitlab.conf"
GITLAB_CI_NGINX_CONFIG="/etc/nginx/conf.d/gitlab_ci.conf"
GITLAB_REGISTRY_NGINX_CONFIG="/etc/nginx/conf.d/gitlab-registry.conf"
GITLAB_PAGES_NGINX_CONFIG="/etc/nginx/conf.d/gitlab-pages.conf"
GITLAB_PAGES_CONFIG="${GITLAB_INSTALL_DIR}/gitlab-pages-config"
GITLAB_GITALY_CONFIG="${GITLAB_GITALY_INSTALL_DIR}/config.toml"

# Compares two version strings `a` and `b`
# Returns
#   - negative integer, if `a` is less than `b`
#   - 0, if `a` and `b` are equal
#   - non-negative integer, if `a` is greater than `b`
vercmp() {
  expr '(' "$1" : '\([^.]*\)' ')' '-' '(' "$2" : '\([^.]*\)' ')' '|' \
       '(' "$1.0" : '[^.]*[.]\([^.]*\)' ')' '-' '(' "$2.0" : '[^.]*[.]\([^.]*\)' ')' '|' \
       '(' "$1.0.0" : '[^.]*[.][^.]*[.]\([^.]*\)' ')' '-' '(' "$2.0.0" : '[^.]*[.][^.]*[.]\([^.]*\)' ')' '|' \
       '(' "$1.0.0.0" : '[^.]*[.][^.]*[.][^.]*[.]\([^.]*\)' ')' '-' '(' "$2.0.0.0" : '[^.]*[.][^.]*[.][^.]*[.]\([^.]*\)' ')'
}

## Execute a command as GITLAB_USER
exec_as_git() {
  if [[ $(whoami) == ${GITLAB_USER} ]]; then
    $@
  else
    sudo -HEu ${GITLAB_USER} "$@"
  fi
}

## Copies configuration template to the destination as the specified USER
### Looks up for overrides in ${USERCONF_TEMPLATES_DIR} before using the defaults from ${SYSCONF_TEMPLATES_DIR}
# $1: copy-as user
# $2: source file
# $3: destination location
# $4: mode of destination
install_template() {
  local OWNERSHIP=${1}
  local SRC=${2}
  local DEST=${3}
  local MODE=${4:-0644}
  if [[ -f ${USERCONF_TEMPLATES_DIR}/${SRC} ]]; then
    cp ${USERCONF_TEMPLATES_DIR}/${SRC} ${DEST}
  elif [[ -f ${SYSCONF_TEMPLATES_DIR}/${SRC} ]]; then
    cp ${SYSCONF_TEMPLATES_DIR}/${SRC} ${DEST}
  fi
  chmod ${MODE} ${DEST}
  chown ${OWNERSHIP} ${DEST}
}

## Replace placeholders with values
# $1: file with placeholders to replace
# $x: placeholders to replace
update_template() {
  local FILE=${1?missing argument}
  shift

  [[ ! -f ${FILE} ]] && return 1

  local VARIABLES=($@)
  local USR=$(stat -c %U ${FILE})
  local tmp_file=$(mktemp)
  cp -a "${FILE}" ${tmp_file}

  local variable
  for variable in ${VARIABLES[@]}; do
    # Keep the compatibilty: {{VAR}} => ${VAR}
    sed -ri "s/[{]{2}$variable[}]{2}/\${$variable}/g" ${tmp_file}
  done

  # Replace placeholders
  (
    export ${VARIABLES[@]}
    local IFS=":"; sudo -HEu ${USR} envsubst "${VARIABLES[*]/#/$}" < ${tmp_file} > ${FILE}
  )
  rm -f ${tmp_file}
}

gitlab_finalize_database_parameters() {
  # is a postgresql database linked?
  # requires that the postgresql containers have exposed port 5432.
  DB_HOST=${DB_HOST:-${POSTGRESQL_PORT_5432_TCP_ADDR}}
  DB_PORT=${DB_PORT:-${POSTGRESQL_PORT_5432_TCP_PORT}}

  # support for linked official postgres image
  DB_USER=${DB_USER:-${POSTGRESQL_ENV_POSTGRES_USER}}
  DB_PASS=${DB_PASS:-${POSTGRESQL_ENV_POSTGRES_PASSWORD}}
  DB_NAME=${DB_NAME:-${POSTGRESQL_ENV_POSTGRES_DB}}
  DB_NAME=${DB_NAME:-${POSTGRESQL_ENV_POSTGRES_USER}}

  # support for linked sameersbn/postgresql image
  DB_USER=${DB_USER:-${POSTGRESQL_ENV_DB_USER}}
  DB_PASS=${DB_PASS:-${POSTGRESQL_ENV_DB_PASS}}
  DB_NAME=${DB_NAME:-${POSTGRESQL_ENV_DB_NAME}}

  # support for linked orchardup/postgresql image
  DB_USER=${DB_USER:-${POSTGRESQL_ENV_POSTGRESQL_USER}}
  DB_PASS=${DB_PASS:-${POSTGRESQL_ENV_POSTGRESQL_PASS}}
  DB_NAME=${DB_NAME:-${POSTGRESQL_ENV_POSTGRESQL_DB}}

  # support for linked paintedfox/postgresql image
  DB_USER=${DB_USER:-${POSTGRESQL_ENV_USER}}
  DB_PASS=${DB_PASS:-${POSTGRESQL_ENV_PASS}}
  DB_NAME=${DB_NAME:-${POSTGRESQL_ENV_DB}}


  if [[ -z ${DB_HOST} ]]; then
    echo
    echo "ERROR: "
    echo "  Please configure the database connection."
    echo "  Refer http://git.io/wkYhyA for more information."
    echo "  Cannot continue without a database. Aborting..."
    echo
    return 1
  fi

  # set default port number if not specified
  DB_PORT=${DB_PORT:-5432}

  DB_ENCODING=${DB_ENCODING:-unicode}

  # set default user and database
  DB_USER=${DB_USER:-root}
  DB_NAME=${DB_NAME:-gitlabhq_production}
}

gitlab_check_database_connection() {

  prog=$(command -v pg_isready)
  prog="${prog} -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} -t 1"

  timeout=60
  while ! ${prog} >/dev/null 2>&1
  do
    timeout=$(expr $timeout - 1)
    if [[ $timeout -eq 0 ]]; then
      echo
      echo "Could not connect to database server. Aborting..."
      return 1
    fi
    echo -n "."
    sleep 1
  done
  echo
}

gitlab_generate_postgresqlrc() {
  echo "Configuring /home/${GITLAB_USER}/.postgresqlrc to avoid version mismatch on dumping"
  # server_version_num property is a number built from version string:
  # https://www.postgresql.org/docs/15/libpq-status.html#LIBPQ-PQSERVERVERSION 
  # > The result is formed by multiplying the server's major version number by 10000 and adding the minor version number. 
  # > For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000. Zero is returned if the connection is bad.
  # >
  # > Prior to major version 10, PostgreSQL used three-part version numbers in which the first two parts together represented the major version.
  # > For those versions, PQserverVersion uses two digits for each part;
  # > for example version 9.1.5 will be returned as 90105, and version 9.2.0 will be returned as 90200.
  #
  # This difference also appends to apt package name.
  # For example, in ubuntu:focal, postgresql-client-{8.2, 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10, 11, 12, 13, 14, 15} are available.
  # 
  DB_SERVER_VERSION=$(PGPASSWORD=${DB_PASS} psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" -Atw -c "SHOW server_version_num")
  if [[ "${DB_SERVER_VERSION}" -eq 0 ]]; then
    echo
    echo "Could not retrieve database server version correctly. Aborting..."
    return 1
  fi

  echo "- Detected server version: ${DB_SERVER_VERSION}"

  # remove leading zero (prior to 10.x it was like "090605" so that cannot treated as number)
  DB_SERVER_VERSION="${DB_SERVER_VERSION#0}"

  # Anyway, we can get major version (8, 9, 10 and so on) by dividing by 10000.
  # DB_SERVER_VERSION_MAJOR=${DB_SERVER_VERSION%%.*}
  DB_SERVER_VERSION_MAJOR=$((DB_SERVER_VERSION/10000))
  DB_CLIENT_VERSION_PACKAGE_NAME=

  # Check version requirement
  if [[ "${DB_SERVER_VERSION}" -lt "${POSTGRESQL_SERVER_REQUIRED_VERSION_MINIMUM}" ]]; then
    echo "  ERROR: Version requirement mismatch for your PostgreSQL server!"
    echo 
    echo "  Consider upgrading your PostgreSQL server before running this or later versions"
    echo "  of this image."
    echo
    echo "  Minimal required version is: ${POSTGRESQL_SERVER_REQUIRED_VERSION_MINIMUM}"
    echo "  Your provided version is   : ${DB_SERVER_VERSION}"
    echo 
    echo "  Aborting..."
    return 1
  fi
  
  if [[ "${DB_SERVER_VERSION}" -gt "${POSTGRESQL_SERVER_TESTED_VERSION_MAXIMUM}" ]]; then
    echo "  WARNING: Version requirement mismatch for your PostgreSQL server!"
    echo
    echo "  Maximal tested version is: ${POSTGRESQL_SERVER_TESTED_VERSION_MAXIMUM}"
    echo "  Your provided version is : ${DB_SERVER_VERSION}"
    echo
  fi

  if [[ "${DB_SERVER_VERSION_MAJOR}" -ge 10 ]]; then
    # v10 or later: use "rough major version" as version number in package name
    DB_CLIENT_VERSION_PACKAGE_NAME=${DB_SERVER_VERSION_MAJOR}
  else
    # prior to v10: convert
    # FIXME: rough implementation
    # It exploits the fact that there is no version such as 9.10, and it lacks versatility.
    # divide by 100, then replace first 0 to comma
    DB_CLIENT_VERSION_PACKAGE_NAME=$((DB_SERVER_VERSION/100))
    DB_CLIENT_VERSION_PACKAGE_NAME=${DB_CLIENT_VERSION_PACKAGE_NAME/0/.}
  fi

  # if exact-match client not found, select latest version from installed clients
  if [[ "$(apt-cache pkgnames postgresql-client | grep -e "-${DB_CLIENT_VERSION_PACKAGE_NAME}" | wc -l)" -ne 1 ]]; then
    LATEST_CLIENT="$(apt-cache pkgnames postgresql-client | grep -v -e "-common" | sort --version-sort | tail -n1)"
    DB_CLIENT_VERSION_PACKAGE_NAME=${LATEST_CLIENT/postgresql-client-/}
    echo "gitlab_generate_postgresqlrc(): WARNING - Suitable client not installed. postgresql-client-${DB_CLIENT_VERSION_PACKAGE_NAME} will be used but you may face issue (database in backup will be empty, for example)"
  fi

  # generate ~/.postgresqlrc to switch client version
  GITLAB_USER_POSTGRESQLRC="/home/${GITLAB_USER}/.postgresqlrc"
  echo "- Generating ${GITLAB_USER_POSTGRESQLRC}"
  echo "${DB_CLIENT_VERSION_PACKAGE_NAME} ${DB_HOST}:${DB_PORT} ${DB_NAME}" | exec_as_git tee "${GITLAB_USER_POSTGRESQLRC}"
}

gitlab_uninstall_unused_database_client() {
  if [[ -f "/home/${GITLAB_USER}/.postgresqlrc" ]]; then
    # refer /home/${GITLAB_USER}/.postgresqlrc and pick up versions in use
    # .postgresqlrc contains following information per line
    #   database_major_version host:port database_name
    # - ignore lines starts with # by specifying pattern /^[^#]/
    # - first field is the version number in use.
    # - cocnat whole lines into single string. convert newline to \|
    #   this is escaped regex "OR"
    # now we got the following regex that can be used as an option to grep:
    #   \|-12\|-13
    DB_CLIENT_VERSIONS_IN_USE="$(awk '/^[^#]/ {printf("\|-%s",$1)}' "/home/${GITLAB_USER}/.postgresqlrc")"

    # we also need to keep postgresql-client-common package to switch based on ~/.postgresqlrc
    REGEX_DB_CLIENT_VERSIONS_IN_USE="-common${DB_CLIENT_VERSIONS_IN_USE}"

    # remove unused client using regex above
    # grep may return non-zero code on mo match, so fake the exit code with the `|| true` to swallow that
    UNUSED_DB_CLIENTS=$(apt-cache pkgnames postgresql-client | grep -v -e "${REGEX_DB_CLIENT_VERSIONS_IN_USE}" || true)
    if [[ "${UNUSED_DB_CLIENTS}" == "" ]]; then
      echo "- All installed version of clients are in use. Did not uninstalled any client..."
      return
    fi

    # just to get clean log, convert newline (package name delimiter) to single whitespace
    UNUSED_DB_CLIENTS=$(echo ${UNUSED_DB_CLIENTS} | tr '\n' ' ')

    echo "- Uninstalling unused client(s): ${UNUSED_DB_CLIENTS}"
    DEBIAN_FRONTEND=noninteractive apt-get -qq -y purge -- ${UNUSED_DB_CLIENTS} >/dev/null
  fi
}

gitlab_configure_database() {
  echo -n "Configuring gitlab::database"

  gitlab_finalize_database_parameters
  gitlab_check_database_connection
  gitlab_generate_postgresqlrc
  gitlab_uninstall_unused_database_client

  update_template ${GITLAB_DATABASE_CONFIG} \
    DB_ENCODING \
    DB_HOST \
    DB_PORT \
    DB_NAME \
    DB_USER \
    DB_PASS \
    DB_POOL \
    DB_PREPARED_STATEMENTS
}

gitlab_finalize_redis_parameters() {
  # is a redis container linked?
  if [[ -n ${REDISIO_PORT_6379_TCP_ADDR} ]]; then
    REDIS_HOST=${REDIS_HOST:-${REDISIO_PORT_6379_TCP_ADDR}}
    REDIS_PORT=${REDIS_PORT:-${REDISIO_PORT_6379_TCP_PORT}}
  fi

  # set default redis port if not specified
  REDIS_PORT=${REDIS_PORT:-6379}

  if [[ -z ${REDIS_HOST} ]]; then
    echo
    echo "ERROR: "
    echo "  Please configure the redis connection."
    echo "  Refer http://git.io/PMnRSw for more information."
    echo "  Cannot continue without a redis connection. Aborting..."
    echo
    return 1
  fi
}

gitlab_check_redis_connection() {
  timeout=60
  while ! redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -n ${REDIS_DB_NUMBER} ping >/dev/null 2>&1
  do
    timeout=$(expr $timeout - 1)
    if [[ $timeout -eq 0 ]]; then
      echo ""
      echo "Could not connect to redis server. Aborting..."
      return 1
    fi
    echo -n "."
    sleep 1
  done
  echo
}

gitlab_configure_redis() {
  echo -n "Configuring gitlab::redis"

  gitlab_finalize_redis_parameters
  gitlab_check_redis_connection

  update_template ${GITLAB_RESQUE_CONFIG} \
    REDIS_HOST \
    REDIS_PORT \
    REDIS_DB_NUMBER
}

gitlab_configure_actioncable() {
  echo -n "Configuring gitlab::actioncable"

  gitlab_finalize_redis_parameters
  gitlab_check_redis_connection

  update_template ${GITLAB_ACTIONCABLE_CONFIG} \
    REDIS_HOST \
    REDIS_PORT \
    REDIS_DB_NUMBER
}

gitlab_configure_gitaly() {
  echo "Configuring gitlab::gitaly..."
  update_template ${GITLAB_GITALY_CONFIG} \
    GITALY_SOCKET_PATH \
    GITLAB_GITALY_INSTALL_DIR \
    GITLAB_LOG_DIR \
    GITLAB_REPOS_DIR \
    GITLAB_SHELL_INSTALL_DIR \
    GITLAB_RELATIVE_URL_ROOT

  update_template ${GITLAB_CONFIG} \
    GITALY_CLIENT_PATH \
    GITALY_TOKEN

}

gitlab_configure_monitoring() {
  echo "Configuring gitlab::monitoring..."

  if [ "${GITLAB_MONITORING_IP_WHITELIST}" == "" ]; then
    exec_as_git sed -i "/{{GITLAB_MONITORING_IP_WHITELIST}}/d" ${GITLAB_CONFIG}
  fi

  update_template ${GITLAB_CONFIG} \
    GITLAB_MONITORING_UNICORN_SAMPLER_INTERVAL \
    GITLAB_MONITORING_IP_WHITELIST \
    GITLAB_MONITORING_SIDEKIQ_EXPORTER_ENABLED \
    GITLAB_MONITORING_SIDEKIQ_EXPORTER_ADDRESS \
    GITLAB_MONITORING_SIDEKIQ_EXPORTER_PORT
}

gitlab_configure_gitlab_workhorse() {
  echo "Configuring gitlab::gitlab-workhorse..."
  update_template /etc/supervisor/conf.d/gitlab-workhorse.conf \
    GITLAB_RELATIVE_URL_ROOT \
    GITLAB_WORKHORSE_TIMEOUT
}

gitlab_configure_puma() {
  echo "Configuring gitlab::puma..."
  if [[ -n ${GITLAB_RELATIVE_URL_ROOT} ]]; then
    update_template ${GITLAB_PUMA_CONFIG} GITLAB_RELATIVE_URL_ROOT
  else
    exec_as_git sed -i "/{{GITLAB_RELATIVE_URL_ROOT}}/d" ${GITLAB_PUMA_CONFIG}
  fi

  update_template ${GITLAB_PUMA_CONFIG} \
    GITLAB_INSTALL_DIR \
    PUMA_THREADS_MIN \
    PUMA_THREADS_MAX \
    PUMA_WORKERS \
    PUMA_PER_WORKER_MAX_MEMORY_MB \
    PUMA_MASTER_MAX_MEMORY_MB \
    PUMA_TIMEOUT
}

gitlab_configure_relative_url() {
  if [[ -n ${GITLAB_RELATIVE_URL_ROOT} ]]; then
    echo "Configuring gitlab::relative_url..."
    update_template ${GITLAB_RELATIVE_URL_CONFIG} GITLAB_RELATIVE_URL_ROOT
  fi
}

gitlab_configure_trusted_proxies() {
  if [[ -n ${GITLAB_TRUSTED_PROXIES} ]]; then
    echo "Configuring gitlab::trusted_proxies..."
    update_template ${GITLAB_CONFIG} GITLAB_TRUSTED_PROXIES
  else
    exec_as_git sed -i "/{{GITLAB_TRUSTED_PROXIES}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_timezone() {
  echo "Configuring gitlab::timezone..."
  update_template ${GITLAB_CONFIG} GITLAB_TIMEZONE
}

gitlab_configure_mail_delivery() {
  if [[ ${SMTP_ENABLED} == true ]]; then
    echo "Configuring gitlab::smtp_settings..."

    if [[ -z "${SMTP_USER}" ]]; then
      exec_as_git sed -i \
        -e '/{{SMTP_USER}}/d' \
        -e '/{{SMTP_PASS}}/d' \
        ${GITLAB_SMTP_CONFIG}
    else
      if [[ -z "${SMTP_PASS}" ]]; then
        exec_as_git sed -i '/{{SMTP_PASS}}/d' ${GITLAB_SMTP_CONFIG}
      fi
    fi

    update_template ${GITLAB_SMTP_CONFIG} \
      SMTP_USER \
      SMTP_PASS \
      SMTP_HOST \
      SMTP_PORT \
      SMTP_DOMAIN \
      SMTP_STARTTLS \
      SMTP_TLS \
      SMTP_OPENSSL_VERIFY_MODE

    case ${SMTP_AUTHENTICATION} in
      "") exec_as_git sed -i "/{{SMTP_AUTHENTICATION}}/d" ${GITLAB_SMTP_CONFIG} ;;
      *) update_template ${GITLAB_SMTP_CONFIG} SMTP_AUTHENTICATION ;;
    esac

    if [[ ${SMTP_CA_ENABLED} == true ]]; then
      if [[ -d ${SMTP_CA_PATH} ]]; then
        update_template ${GITLAB_SMTP_CONFIG} SMTP_CA_PATH
      fi
      if [[ -f ${SMTP_CA_FILE} ]]; then
        update_template ${GITLAB_SMTP_CONFIG} SMTP_CA_FILE
      fi
    else
      exec_as_git sed -i \
        -e "/{{SMTP_CA_PATH}}/d" \
        -e "/{{SMTP_CA_FILE}}/d" \
        ${GITLAB_SMTP_CONFIG}
    fi
  fi

  update_template ${GITLAB_CONFIG} \
    GITLAB_EMAIL_ENABLED \
    GITLAB_EMAIL \
    GITLAB_EMAIL_DISPLAY_NAME \
    GITLAB_EMAIL_REPLY_TO \
    GITLAB_EMAIL_SUBJECT_SUFFIX

  if [[ ${GITLAB_EMAIL_SMIME_ENABLE} == true ]]; then
    exec_as_git sed -i "/#start-email-smime/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#end-email-smime/d" ${GITLAB_CONFIG}
    update_template ${GITLAB_CONFIG} \
      GITLAB_EMAIL_SMIME_ENABLE \
      GITLAB_EMAIL_SMIME_KEY_FILE \
      GITLAB_EMAIL_SMIME_CERT_FILE
  else
    exec_as_git sed -i "/#start-email-smime/,/#end-email-smime/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_microsoft_graph_mailer() {
  if [[ ${MICROSOFT_GRAPH_MAILER_ENABLED} == true ]]; then
    echo "Configuring gitlab::microsoft_graph_mailer..."
    exec_as_git sed -i "/#start-microsoft-graph-mailer/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#end-microsoft-graph-mailer/d" ${GITLAB_CONFIG}
    update_template ${GITLAB_CONFIG} \
      MICROSOFT_GRAPH_MAILER_ENABLED \
      MICROSOFT_GRAPH_MAILER_USER_ID \
      MICROSOFT_GRAPH_MAILER_TENANT \
      MICROSOFT_GRAPH_MAILER_CLIENT_ID \
      MICROSOFT_GRAPH_MAILER_CLIENT_SECRET \
      MICROSOFT_GRAPH_MAILER_AZURE_AD_ENDPOINT \
      MICROSOFT_GRAPH_MAILER_GRAPH_ENDPOINT
  else
    exec_as_git sed -i "/#start-microsoft-graph-mailer/,/#end-microsoft-graph-mailer/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_mailroom() {
  if [[ ${IMAP_ENABLED} == true ]]; then
    echo "Configuring gitlab::incoming_email..."

    if [[ -z "${IMAP_USER}" ]]; then
      exec_as_git sed -i \
        -e '/{{IMAP_USER}}/d' \
        -e '/{{IMAP_PASS}}/d' \
        ${GITLAB_CONFIG}
    else
      if [[ -z "${IMAP_PASS}" ]]; then
        exec_as_git sed -i '/{{IMAP_PASS}}/d' ${GITLAB_CONFIG}
      fi
    fi
  else
    exec_as_git sed -i \
      -e "/{{IMAP_USER}}/d" \
      -e "/{{IMAP_PASS}}/d" \
      -e "/{{IMAP_HOST}}/d" \
      -e "/{{IMAP_PORT}}/d" \
      -e "/{{IMAP_SSL}}/d" \
      -e "/{{IMAP_STARTTLS}}/d" \
      -e "/{{IMAP_MAILBOX}}/d" \
      -e "/{{IMAP_TIMEOUT}}/d" \
      ${GITLAB_CONFIG}
  fi

  update_template ${GITLAB_CONFIG} \
    GITLAB_INCOMING_EMAIL_ADDRESS \
    GITLAB_INCOMING_EMAIL_ENABLED \
    IMAP_USER \
    IMAP_PASS \
    IMAP_HOST \
    IMAP_PORT \
    IMAP_SSL \
    IMAP_STARTTLS \
    IMAP_MAILBOX \
    IMAP_TIMEOUT

  # enable/disable startup of mailroom
  echo "mail_room_enabled=${GITLAB_INCOMING_EMAIL_ENABLED}" >> /etc/default/gitlab
  update_template /etc/supervisor/conf.d/mail_room.conf GITLAB_INCOMING_EMAIL_ENABLED
}

gitlab_configure_ldap() {
  echo "Configuring gitlab::ldap..."
  update_template ${GITLAB_CONFIG} \
    LDAP_ENABLED \
    LDAP_HOST \
    LDAP_PORT \
    LDAP_UID \
    LDAP_METHOD \
    LDAP_VERIFY_SSL \
    LDAP_CA_FILE \
    LDAP_SSL_VERSION \
    LDAP_BIND_DN \
    LDAP_PASS \
    LDAP_TIMEOUT \
    LDAP_ACTIVE_DIRECTORY \
    LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN \
    LDAP_BLOCK_AUTO_CREATED_USERS \
    LDAP_BASE \
    LDAP_USER_FILTER \
    LDAP_LOWERCASE_USERNAMES \
    LDAP_USER_ATTRIBUTE_USERNAME \
    LDAP_USER_ATTRIBUTE_MAIL \
    LDAP_USER_ATTRIBUTE_NAME \
    LDAP_USER_ATTRIBUTE_FIRSTNAME \
    LDAP_USER_ATTRIBUTE_LASTNAME \
    LDAP_LABEL \
    LDAP_PREVENT_LDAP_SIGN_IN
}

gitlab_configure_oauth_cas3() {
  if [[ -n ${OAUTH_CAS3_SERVER} ]]; then
    echo "Configuring gitlab::oauth::cas3..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_CAS3_LABEL \
      OAUTH_CAS3_SERVER \
      OAUTH_CAS3_DISABLE_SSL_VERIFICATION \
      OAUTH_CAS3_LOGIN_URL \
      OAUTH_CAS3_VALIDATE_URL \
      OAUTH_CAS3_LOGOUT_URL
  else
    exec_as_git sed -i "/name: 'cas3'/,/{{OAUTH_CAS3_LOGOUT_URL}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_google() {
  if [[ -n ${OAUTH_GOOGLE_API_KEY} && -n ${OAUTH_GOOGLE_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::google..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    if [[ -n ${OAUTH_GOOGLE_RESTRICT_DOMAIN} ]]; then
      update_template ${GITLAB_CONFIG} \
        OAUTH_GOOGLE_API_KEY \
        OAUTH_GOOGLE_APP_SECRET \
        OAUTH_GOOGLE_RESTRICT_DOMAIN \
        OAUTH_GOOGLE_APPROVAL_PROMPT
    else
      exec_as_git sed -i "/ hd\: \[{{OAUTH_GOOGLE_RESTRICT_DOMAIN}}\]/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "s/approval_prompt: '{{OAUTH_GOOGLE_APPROVAL_PROMPT}}',/approval_prompt: '{{OAUTH_GOOGLE_APPROVAL_PROMPT}}' } }/" ${GITLAB_CONFIG}
      update_template ${GITLAB_CONFIG} \
        OAUTH_GOOGLE_API_KEY \
        OAUTH_GOOGLE_APP_SECRET \
        OAUTH_GOOGLE_APPROVAL_PROMPT
    fi
  else
    exec_as_git sed -i "/name: 'google_oauth2'/,/{{OAUTH_GOOGLE_RESTRICT_DOMAIN}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_facebook() {
  if [[ -n ${OAUTH_FACEBOOK_API_KEY} && -n ${OAUTH_FACEBOOK_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::facebook..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_FACEBOOK_API_KEY \
      OAUTH_FACEBOOK_APP_SECRET
  else
    exec_as_git sed -i "/name: 'facebook'/,/{{OAUTH_FACEBOOK_APP_SECRET}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_twitter() {
  if [[ -n ${OAUTH_TWITTER_API_KEY} && -n ${OAUTH_TWITTER_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::twitter..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_TWITTER_API_KEY \
      OAUTH_TWITTER_APP_SECRET
  else
    exec_as_git sed -i "/name: 'twitter'/,/{{OAUTH_TWITTER_APP_SECRET}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_authentiq() {
  if [[ -n ${OAUTH_AUTHENTIQ_CLIENT_ID} && -n ${OAUTH_AUTHENTIQ_CLIENT_SECRET} ]]; then
    echo "Configuring gitlab::oauth::authentiq..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_AUTHENTIQ_CLIENT_ID \
      OAUTH_AUTHENTIQ_CLIENT_SECRET \
      OAUTH_AUTHENTIQ_SCOPE \
      OAUTH_AUTHENTIQ_REDIRECT_URI
  else
    exec_as_git sed -i "/name: 'authentiq'/,/{{OAUTH_AUTHENTIQ_SCOPE}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_github() {
  if [[ -n ${OAUTH_GITHUB_API_KEY} && -n ${OAUTH_GITHUB_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::github..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_GITHUB_API_KEY \
      OAUTH_GITHUB_APP_SECRET \
      OAUTH_GITHUB_URL \
      OAUTH_GITHUB_VERIFY_SSL \
      OAUTH_GITHUB_SCOPE
  else
    exec_as_git sed -i "/name: 'github'/,/{{OAUTH_GITHUB_SCOPE}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_gitlab() {
  if [[ -n ${OAUTH_GITLAB_API_KEY} && -n ${OAUTH_GITLAB_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::gitlab..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_GITLAB_API_KEY \
      OAUTH_GITLAB_APP_SECRET \
      OAUTH_GITLAB_SCOPE
  else
    exec_as_git sed -i "/name: 'gitlab'/,/{{OAUTH_GITLAB_SCOPE}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_bitbucket() {
  if [[ -n ${OAUTH_BITBUCKET_API_KEY} && -n ${OAUTH_BITBUCKET_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::bitbucket..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_BITBUCKET_API_KEY \
      OAUTH_BITBUCKET_APP_SECRET \
      OAUTH_BITBUCKET_URL
  else
    exec_as_git sed -i "/name: 'bitbucket'/,/{{OAUTH_BITBUCKET_URL}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_saml_attribute_statements() {
  if [[ -n ${OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL} ]]; then
    echo "Configuring gitlab::oauth::saml::attribute_statements..."
    update_template ${GITLAB_CONFIG} \
      OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL \
      OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME \
      OAUTH_SAML_ATTRIBUTE_STATEMENTS_USERNAME \
      OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME \
      OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME
    # Remove undefined optional attributes
    exec_as_git sed -i "/email: \\[''\\],/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/name: \\[''\\],/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/username: \\[''\\],/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/first_name: \\[''\\],/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/last_name: \\[''\\],/d" ${GITLAB_CONFIG}
  else
    exec_as_git sed -i "/attribute_statements:/,/{{OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_saml() {
  if [[ -n ${OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL} && \
        -n ${OAUTH_SAML_IDP_CERT_FINGERPRINT} && \
        -n ${OAUTH_SAML_IDP_SSO_TARGET_URL} && \
        -n ${OAUTH_SAML_ISSUER} && \
        -n ${OAUTH_SAML_NAME_IDENTIFIER_FORMAT} ]]; then
    echo "Configuring gitlab::oauth::saml..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_SAML_LABEL \
      OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL \
      OAUTH_SAML_IDP_CERT_FINGERPRINT \
      OAUTH_SAML_IDP_SSO_TARGET_URL \
      OAUTH_SAML_ISSUER \
      OAUTH_SAML_NAME_IDENTIFIER_FORMAT \
      OAUTH_SAML_GROUPS_ATTRIBUTE \
      OAUTH_SAML_EXTERNAL_GROUPS
    exec_as_git sed -i "/groups_attribute: '',/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/external_groups: \\[\\],/d" ${GITLAB_CONFIG}
    gitlab_configure_oauth_saml_attribute_statements
  else
    exec_as_git sed -i "/name: 'saml'/,/{{OAUTH_SAML_NAME_IDENTIFIER_FORMAT}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth2_generic() {
  if [[ -n ${OAUTH2_GENERIC_APP_ID} && \
        -n ${OAUTH2_GENERIC_APP_SECRET} ]]; then
    echo "Configuring gitlab::oauth::generic..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
    OAUTH2_GENERIC_APP_ID \
    OAUTH2_GENERIC_APP_SECRET \
    OAUTH2_GENERIC_CLIENT_SITE \
    OAUTH2_GENERIC_CLIENT_USER_INFO_URL \
    OAUTH2_GENERIC_CLIENT_AUTHORIZE_URL \
    OAUTH2_GENERIC_CLIENT_TOKEN_URL \
    OAUTH2_GENERIC_CLIENT_END_SESSION_ENDPOINT \
    OAUTH2_GENERIC_ID_PATH \
    OAUTH2_GENERIC_USER_UID \
    OAUTH2_GENERIC_USER_NAME \
    OAUTH2_GENERIC_USER_EMAIL \
    OAUTH2_GENERIC_AUTHORIZE_PARAMS_SCOPE \
    OAUTH2_GENERIC_LABEL \
    OAUTH2_GENERIC_NAME
  else
      exec_as_git sed -i "/name: 'oauth2_generic'/,/{{OAUTH2_GENERIC_NAME}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_crowd() {
  if [[ -n ${OAUTH_CROWD_SERVER_URL} && \
        -n ${OAUTH_CROWD_APP_NAME} && \
        -n ${OAUTH_CROWD_APP_PASSWORD} ]]; then
    echo "Configuring gitlab::oauth::crowd..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_CROWD_SERVER_URL \
      OAUTH_CROWD_APP_NAME \
      OAUTH_CROWD_APP_PASSWORD
  else
    exec_as_git sed -i "/name: 'crowd'/,/{{OAUTH_CROWD_APP_PASSWORD}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_auth0() {
  if [[ -n ${OAUTH_AUTH0_CLIENT_ID} && \
        -n ${OAUTH_AUTH0_CLIENT_SECRET} && \
	-n ${OAUTH_AUTH0_SCOPE} && \
        -n ${OAUTH_AUTH0_DOMAIN} ]]; then
    echo "Configuring gitlab::oauth::auth0..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_AUTH0_CLIENT_ID \
      OAUTH_AUTH0_CLIENT_SECRET \
      OAUTH_AUTH0_DOMAIN \
      OAUTH_AUTH0_SCOPE
  else
    exec_as_git sed -i "/name: 'auth0'/,/{{OAUTH_AUTH0_SCOPE}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_azure() {
  if [[ -n ${OAUTH_AZURE_API_KEY} && \
        -n ${OAUTH_AZURE_API_SECRET} && \
        -n ${OAUTH_AZURE_TENANT_ID} ]]; then
    echo "Configuring gitlab::oauth::azure..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_AZURE_API_KEY \
      OAUTH_AZURE_API_SECRET \
      OAUTH_AZURE_TENANT_ID
  else
    exec_as_git sed -i "/name: 'azure_oauth2'/,/{{OAUTH_AZURE_TENANT_ID}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_azure_ad_v2() {
  # we don't check if OAUTH_AZURE_ACTIVEDIRECTORY_V2_LABEL because it is optional
  if [[ -n ${OAUTH_AZURE_ACTIVEDIRECTORY_V2_CLIENT_ID} && \
        -n ${OAUTH_AZURE_ACTIVEDIRECTORY_V2_CLIENT_SECRET} && \
        -n ${OAUTH_AZURE_ACTIVEDIRECTORY_V2_TENANT_ID} ]]; then
    echo "Configuring gitlab::oauth::azure_activedirectory_v2..."
    update_template ${GITLAB_CONFIG} \
      OAUTH_AZURE_ACTIVEDIRECTORY_V2_LABEL \
      OAUTH_AZURE_ACTIVEDIRECTORY_V2_CLIENT_ID \
      OAUTH_AZURE_ACTIVEDIRECTORY_V2_CLIENT_SECRET \
      OAUTH_AZURE_ACTIVEDIRECTORY_V2_TENANT_ID
  else
    exec_as_git sed -i "/name: 'azure_activedirectory_v2'/,/{{OAUTH_AZURE_ACTIVEDIRECTORY_V2_TENANT_ID}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_oidc() {
  if [[ -n ${OAUTH_OIDC_ISSUER} && \
        -n ${OAUTH_OIDC_CLIENT_ID} ]]; then
    echo "Configuring gitlab::oauth::oidc..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_OIDC_LABEL \
      OAUTH_OIDC_ICON \
      OAUTH_OIDC_SCOPE \
      OAUTH_OIDC_RESPONSE_TYPE \
      OAUTH_OIDC_ISSUER \
      OAUTH_OIDC_DISCOVERY \
      OAUTH_OIDC_CLIENT_AUTH_METHOD \
      OAUTH_OIDC_UID_FIELD \
      OAUTH_OIDC_SEND_SCOPE_TO_TOKEN_EP \
      OAUTH_OIDC_PKCE \
      OAUTH_OIDC_CLIENT_ID \
      OAUTH_OIDC_CLIENT_SECRET \
      OAUTH_OIDC_REDIRECT_URI
  else
    exec_as_git sed -i "/name: 'openid_connect'/,/{{OAUTH_OIDC_REDIRECT_URI}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth_jwt() {
  if [[ -n ${OAUTH_JWT_SECRET} && \
        -n ${OAUTH_JWT_AUTH_URL} ]]; then
    echo "Configuring gitlab::oauth::jwt..."
    OAUTH_ENABLED=${OAUTH_ENABLED:-true}
    update_template ${GITLAB_CONFIG} \
      OAUTH_JWT_LABEL \
      OAUTH_JWT_SECRET \
      OAUTH_JWT_ALGORITHM \
      OAUTH_JWT_UID_CLAIM \
      OAUTH_JWT_REQUIRED_CLAIMS \
      OAUTH_JWT_INFO_MAP_NAME \
      OAUTH_JWT_INFO_MAP_EMAIL \
      OAUTH_JWT_AUTH_URL \
      OAUTH_JWT_VALID_WITHIN
  else
    exec_as_git sed -i "/name: 'jwt'/,/{{OAUTH_JWT_VALID_WITHIN}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_oauth() {
  echo "Configuring gitlab::oauth..."

  gitlab_configure_oauth_cas3
  gitlab_configure_oauth_google
  gitlab_configure_oauth_facebook
  gitlab_configure_oauth_twitter
  gitlab_configure_oauth_authentiq
  gitlab_configure_oauth_github
  gitlab_configure_oauth_gitlab
  gitlab_configure_oauth_bitbucket
  gitlab_configure_oauth_saml
  gitlab_configure_oauth2_generic
  gitlab_configure_oauth_crowd
  gitlab_configure_oauth_auth0
  gitlab_configure_oauth_azure
  gitlab_configure_oauth_azure_ad_v2
  gitlab_configure_oauth_oidc
  gitlab_configure_oauth_jwt

  OAUTH_ENABLED=${OAUTH_ENABLED:-false}
  update_template ${GITLAB_CONFIG} \
    OAUTH_ENABLED \
    OAUTH_ALLOW_SSO \
    OAUTH_BLOCK_AUTO_CREATED_USERS \
    OAUTH_AUTO_LINK_LDAP_USER \
    OAUTH_AUTO_LINK_SAML_USER \
    OAUTH_AUTO_LINK_USER \
    OAUTH_EXTERNAL_PROVIDERS \
    OAUTH_ALLOW_BYPASS_TWO_FACTOR

  case ${OAUTH_AUTO_SIGN_IN_WITH_PROVIDER} in
    cas3|google_oauth2|facebook|twitter|github|gitlab|bitbucket|saml|crowd|azure_oauth2|azure_activedirectory_v2|oauth2_generic|$OAUTH2_GENERIC_NAME|oidc|jwt)
      update_template ${GITLAB_CONFIG} OAUTH_AUTO_SIGN_IN_WITH_PROVIDER
      ;;
    *)
      exec_as_git sed -i "/{{OAUTH_AUTO_SIGN_IN_WITH_PROVIDER}}/d" ${GITLAB_CONFIG}
      ;;
  esac
}

gitlab_configure_secrets() {
  echo "Configuring gitlab::secrets..."
  if [[ -z $GITLAB_SECRETS_DB_KEY_BASE ]]; then
    echo "ERROR: "
    echo "  Please configure the GITLAB_SECRETS_DB_KEY_BASE parameter."
    echo "  Cannot continue. Aborting..."
    return 1
  fi

  if [[ -z $GITLAB_SECRETS_SECRET_KEY_BASE ]]; then
    echo "ERROR: "
    echo "  Please configure the GITLAB_SECRETS_SECRET_KEY_BASE parameter."
    echo "  Cannot continue. Aborting..."
    return 1
  fi

  if [[ -z $GITLAB_SECRETS_OTP_KEY_BASE ]]; then
    echo "ERROR: "
    echo "  Please configure the GITLAB_SECRETS_OTP_KEY_BASE parameter."
    echo "  Cannot continue. Aborting..."
    return 1
  fi

  update_template ${GITLAB_SECRETS_CONFIG} \
  GITLAB_SECRETS_DB_KEY_BASE \
  GITLAB_SECRETS_SECRET_KEY_BASE \
  GITLAB_SECRETS_OTP_KEY_BASE \
  GITLAB_SECRETS_ENCRYPTED_SETTINGS_KEY_BASE \
  GITLAB_SECRETS_ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY \
  GITLAB_SECRETS_ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY \
  GITLAB_SECRETS_ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT

  local shell_secret="${GITLAB_INSTALL_DIR}/.gitlab_shell_secret"
  if [[ ! -f "${shell_secret}" ]]; then
    exec_as_git openssl rand -hex -out "${shell_secret}" 16
    chmod 600 "${shell_secret}"
  fi

  local workhorse_secret="${GITLAB_INSTALL_DIR}/.gitlab_workhorse_secret"
  if [[ ! -f "${workhorse_secret}" ]]; then
    exec_as_git openssl rand -base64 -out "${workhorse_secret}" 32
    chmod 600 "${workhorse_secret}"
  fi

  local pages_secret="${GITLAB_INSTALL_DIR}/.gitlab_pages_secret"
  if [[ ! -f "${pages_secret}" ]]; then
    exec_as_git openssl rand -base64 -out "${pages_secret}" 32
    chmod 600 "${pages_secret}"
  fi
}

gitlab_configure_sidekiq() {
  echo "Configuring gitlab::sidekiq..."

  # configure gitlab sidekiq log format
  update_template ${GITLAB_CONFIG} \
    GITLAB_SIDEKIQ_LOG_FORMAT

  # configure sidekiq
  update_template /etc/supervisor/conf.d/sidekiq.conf \
    SIDEKIQ_CONCURRENCY \
    SIDEKIQ_SHUTDOWN_TIMEOUT

  # enable SidekiqMemoryKiller
  ## The MemoryKiller is enabled by gitlab if the `SIDEKIQ_MEMORY_KILLER_MAX_RSS` is
  ## defined in the programs environment and has a non-zero value.
  ##
  ## Simply exporting the variable makes it available in the programs environment and
  ## therefore should enable the MemoryKiller.
  ##
  ## Every other MemoryKiller option specified in the docker env will automatically
  ## be exported, so why bother
  export SIDEKIQ_MEMORY_KILLER_MAX_RSS
}

gitlab_configure_backups_schedule() {
  case ${GITLAB_BACKUP_SCHEDULE} in
    daily|weekly|monthly)
      if ! crontab -u ${GITLAB_USER} -l >/tmp/cron.${GITLAB_USER} 2>/dev/null || ! grep -q 'bundle exec rake gitlab:backup:create' /tmp/cron.${GITLAB_USER}; then
        echo "Configuring gitlab::backups::schedule..."
        gitlab_backup_log="${GITLAB_LOG_DIR}/gitlab/gitlab-backup.log"
        read -r hour min <<< "${GITLAB_BACKUP_TIME//[:]/ }"
        day_of_month="*"
        month="*"
        day_of_week="*"
        case ${GITLAB_BACKUP_SCHEDULE} in
          daily) ;;
          weekly) day_of_week=0 ;;
          monthly) day_of_month=01 ;;
        esac
        if [[ -n ${GITLAB_BACKUP_DIR_GROUP} ]]; then
            echo "$min $hour $day_of_month $month $day_of_week /bin/bash -l -c 'cd ${GITLAB_INSTALL_DIR} && bundle exec rake gitlab:backup:create SKIP=${GITLAB_BACKUP_SKIP} DIRECTORY=${GITLAB_BACKUP_DIR_GROUP} RAILS_ENV=${RAILS_ENV}' >> ${gitlab_backup_log} 2>&1" >> "/tmp/cron.${GITLAB_USER}"
        else
            echo "$min $hour $day_of_month $month $day_of_week /bin/bash -l -c 'cd ${GITLAB_INSTALL_DIR} && bundle exec rake gitlab:backup:create SKIP=${GITLAB_BACKUP_SKIP} RAILS_ENV=${RAILS_ENV}' >> ${gitlab_backup_log} 2>&1" >> "/tmp/cron.${GITLAB_USER}"
        fi
        crontab -u ${GITLAB_USER} /tmp/cron.${GITLAB_USER}
      fi
      rm -rf /tmp/cron.${GITLAB_USER}
      ;;
  esac
}

gitlab_configure_backups_aws() {
    echo "Configuring gitlab::backups::aws..."
    exec_as_git sed -i "/#start-gcs/,/#end-gcs/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#start-aws/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#end-aws/d" ${GITLAB_CONFIG}

    if [[ -z ${AWS_BACKUP_MULTIPART_CHUNK_SIZE} ]]; then
      exec_as_git sed -i "/#start-multipart/,/#end-multipart/d" ${GITLAB_CONFIG}
    fi

    if [[ -z ${AWS_BACKUP_MULTIPART_CHUNK_SIZE} ]]; then
      exec_as_git sed -i "/#start-multipart-aws/,/#end-multipart-aws/d" ${GITLAB_CONFIG}
    fi

    if [[ ${AWS_BACKUP_ENCRYPTION} != true ]]; then
      exec_as_git sed -i "/#start-encryption-aws/,/#end-encryption-aws/d" ${GITLAB_CONFIG}
    fi

    if [[ -z ${AWS_BACKUP_REGION} && -z ${AWS_BACKUP_ENDPOINT} ]]; then
      echo "\nMissing AWS region or endpoint. Aborting...\n"
      return 1
    fi

    if [[ ! -z ${AWS_BACKUP_ENDPOINT} ]]; then
      AWS_BACKUP_PATH_STYLE="true"
    fi

    if [[ -z ${AWS_BACKUP_ACCESS_KEY_ID} || -z ${AWS_BACKUP_SECRET_ACCESS_KEY} || -z ${AWS_BACKUP_BUCKET} ]]; then
      echo "\nMissing AWS options. Aborting...\n"
      return 1
    fi

    update_template ${GITLAB_CONFIG} \
      AWS_BACKUP_REGION \
      AWS_BACKUP_ENDPOINT \
      AWS_BACKUP_PATH_STYLE \
      AWS_BACKUP_ACCESS_KEY_ID \
      AWS_BACKUP_SECRET_ACCESS_KEY \
      AWS_BACKUP_BUCKET \
      AWS_BACKUP_MULTIPART_CHUNK_SIZE \
      AWS_BACKUP_STORAGE_CLASS \
      AWS_BACKUP_SIGNATURE_VERSION
}

gitlab_configure_backup_gcs() {
    echo "Configuring gitlab::backups::gcs..."
    exec_as_git sed -i "/#start-aws/,/#end-aws/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#start-gcs/d" ${GITLAB_CONFIG}
    exec_as_git sed -i "/#end-gcs/d" ${GITLAB_CONFIG}
    if [[ -z ${GCS_BACKUP_ACCESS_KEY_ID} || -z ${GCS_BACKUP_SECRET_ACCESS_KEY} || -z ${GCS_BACKUP_BUCKET} ]]; then
      printf "\nMissing GCS options. Aborting...\n"
      return 1
    fi
    update_template ${GITLAB_CONFIG} \
      GCS_BACKUP_ACCESS_KEY_ID \
      GCS_BACKUP_SECRET_ACCESS_KEY \
      GCS_BACKUP_BUCKET
}

gitlab_configure_backups() {
  echo "Configuring gitlab::backups..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_BACKUP_DIR \
    GITLAB_BACKUP_EXPIRY \
    GITLAB_BACKUP_PG_SCHEMA \
    GITLAB_BACKUP_ARCHIVE_PERMISSIONS
  gitlab_configure_backups_schedule
  if [[ ${AWS_BACKUPS} != true && ${GCS_BACKUPS} != true ]]; then
    exec_as_git sed -i "/\s\+#start-aws/,/#end-gcs/d" ${GITLAB_CONFIG}
    return 0
  fi
  if [[ ${AWS_BACKUPS} == true && ${GCS_BACKUPS} == true ]]; then
    printf "\nAWS and GCE cannot be enabled together, please choose one...\n"
    return 1
  fi
  if [[ ${AWS_BACKUPS} == true ]]; then
    gitlab_configure_backups_aws
  fi
  if [[ ${GCS_BACKUPS} == true ]]; then
    gitlab_configure_backup_gcs
  fi
}

gitlab_configure_gravatar() {
  update_template ${GITLAB_CONFIG} GITLAB_GRAVATAR_ENABLED

  if [[ -n ${GITLAB_GRAVATAR_HTTP_URL} ]]; then
    echo "Configuring gitlab::gravatar::http..."
    update_template ${GITLAB_CONFIG} GITLAB_GRAVATAR_HTTP_URL
  else
    exec_as_git sed -i "/{{GITLAB_GRAVATAR_HTTP_URL}}/d" ${GITLAB_CONFIG}
  fi

  if [[ -n ${GITLAB_GRAVATAR_HTTPS_URL} ]]; then
    echo "Configuring gitlab::gravatar::https..."
    update_template ${GITLAB_CONFIG} GITLAB_GRAVATAR_HTTPS_URL
  else
    exec_as_git sed -i "/{{GITLAB_GRAVATAR_HTTPS_URL}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_cron_jobs() {
  echo "Configuring gitlab::cron_jobs..."

  if [[ -n "${GITLAB_PIPELINE_SCHEDULE_WORKER_CRON}" ]]; then
    update_template ${GITLAB_CONFIG} GITLAB_PIPELINE_SCHEDULE_WORKER_CRON
  else
    exec_as_git sed -i "/{{GITLAB_PIPELINE_SCHEDULE_WORKER_CRON}}/d" ${GITLAB_CONFIG}
  fi

  if [[ -n "${GITLAB_ADMIN_EMAIL_WORKER_CRON}" ]]; then
    update_template ${GITLAB_CONFIG} GITLAB_ADMIN_EMAIL_WORKER_CRON
  else
    exec_as_git sed -i "/{{GITLAB_ADMIN_EMAIL_WORKER_CRON}}/d" ${GITLAB_CONFIG}
  fi

  if [[ -n "${GITLAB_PERSONAL_ACCESS_TOKEN_EXPIRING_WORKER_CRON}" ]]; then
    update_template ${GITLAB_CONFIG} GITLAB_PERSONAL_ACCESS_TOKEN_EXPIRING_WORKER_CRON
  else
    exec_as_git sed -i "/{{GITLAB_PERSONAL_ACCESS_TOKEN_EXPIRING_WORKER_CRON}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_analytics_google() {
  if [[ -n ${GOOGLE_ANALYTICS_ID} ]]; then
  echo "Configuring gitlab::analytics:google..."
    update_template ${GITLAB_CONFIG} GOOGLE_ANALYTICS_ID
  else
    exec_as_git sed -i "/{{GOOGLE_ANALYTICS_ID}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_analytics_piwik() {
  if [[ -n ${PIWIK_URL} && -n ${PIWIK_SITE_ID} ]]; then
    echo "Configuring gitlab::analytics:piwik..."
    update_template ${GITLAB_CONFIG} \
      PIWIK_URL \
      PIWIK_SITE_ID
  else
    exec_as_git sed -i \
      -e "/{{PIWIK_URL}}/d" \
      -e "/{{PIWIK_SITE_ID}}/d" \
      ${GITLAB_CONFIG}
  fi
}

gitlab_configure_analytics() {
  gitlab_configure_analytics_google
  gitlab_configure_analytics_piwik
}

gitlab_configure_rack_attack() {
  echo "Configuring gitlab::rack_attack..."

  # validity check : RACK_ATTACK_WHITELIST should be an array of valid IP Address string
  echo " Validating RACK_ATTACK_WHITELIST..."
  /usr/bin/env ruby << SCRIPT
  require 'ipaddr'
  ${RACK_ATTACK_WHITELIST}.each do |host|
    begin
      printf("  input=%s, to_range=%s\n", host, IPAddr.new(host).to_range)
    rescue IPAddr::InvalidAddressError => e
      p e
      exit 1
    rescue => e
      put "Unexpected error", e
      exit 1
    end
  end
SCRIPT

  update_template ${GITLAB_CONFIG} \
    RACK_ATTACK_ENABLED \
    RACK_ATTACK_WHITELIST \
    RACK_ATTACK_MAXRETRY \
    RACK_ATTACK_FINDTIME \
    RACK_ATTACK_BANTIME
}

gitlab_configure_ci() {
  echo "Configuring gitlab::ci..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_NOTIFY_ON_BROKEN_BUILDS \
    GITLAB_NOTIFY_PUSHER GITLAB_BUILDS_DIR
}

gitlab_configure_artifacts() {
  update_template ${GITLAB_CONFIG} \
    GITLAB_ARTIFACTS_OBJECT_STORE_ENABLED

  if [[ ${GITLAB_ARTIFACTS_OBJECT_STORE_ENABLED} == true ]]; then
    echo "Configuring gitlab::artifacts:object_store"

    if [[ "${GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_PROVIDER}" == "Google" ]]; then
        echo " -> Google ARTIFACTS provider selected removing aws config"
        exec_as_git sed -i "/#start-artifacts-aws/,/#end-artifacts-aws/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#start-artifacts-gcs/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#end-artifacts-gcs/d" ${GITLAB_CONFIG}
    fi
    if [[ "${GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_PROVIDER}" == "AWS" ]]; then
      echo " -> AWS ARTIFACTS provider selected removing Google config"
      exec_as_git sed -i "/#start-artifacts-gcs/,/#end-artifacts-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-artifacts-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-artifacts-aws/d" ${GITLAB_CONFIG}
    fi

    update_template ${GITLAB_CONFIG} \
      GITLAB_ARTIFACTS_OBJECT_STORE_REMOTE_DIRECTORY \
      GITLAB_ARTIFACTS_OBJECT_STORE_DIRECT_UPLOAD \
      GITLAB_ARTIFACTS_OBJECT_STORE_BACKGROUND_UPLOAD \
      GITLAB_ARTIFACTS_OBJECT_STORE_PROXY_DOWNLOAD \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_PROVIDER \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_ACCESS_KEY_ID \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_SECRET_ACCESS_KEY \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_REGION \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_HOST \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_ENDPOINT \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_PATH_STYLE \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_AWS_SIGNATURE_VERSION \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_GOOGLE_PROJECT \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_GOOGLE_CLIENT_EMAIL \
      GITLAB_ARTIFACTS_OBJECT_STORE_CONNECTION_GOOGLE_JSON_KEY_LOCATION
  else
    exec_as_git sed -i -e "/path: {{GITLAB_ARTIFACTS_DIR}}/{n;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d;}" ${GITLAB_CONFIG}
  fi

  echo "Configuring gitlab::artifacts..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_ARTIFACTS_ENABLED \
    GITLAB_ARTIFACTS_DIR
}


gitlab_configure_packages() {
  update_template ${GITLAB_CONFIG} \
    GITLAB_PACKAGES_OBJECT_STORE_ENABLED

  if [[ ${GITLAB_PACKAGES_OBJECT_STORE_ENABLED} == true ]]; then
    echo "Configuring gitlab::packages:object_store"

    if [[ "${GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_PROVIDER}" == "Google" ]]; then
        echo " -> Google PACKAGES provider selected removing aws config"
        exec_as_git sed -i "/#start-packages-aws/,/#end-packages-aws/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#start-packages-gcs/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#end-packages-gcs/d" ${GITLAB_CONFIG}
    fi
    if [[ "${GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_PROVIDER}" == "AWS" ]]; then
      echo " -> AWS PACKAGES provider selected removing Google config"
      exec_as_git sed -i "/#start-packages-gcs/,/#end-packages-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-packages-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-packages-aws/d" ${GITLAB_CONFIG}
    fi

    update_template ${GITLAB_CONFIG} \
      GITLAB_PACKAGES_OBJECT_STORE_REMOTE_DIRECTORY \
      GITLAB_PACKAGES_OBJECT_STORE_DIRECT_UPLOAD \
      GITLAB_PACKAGES_OBJECT_STORE_BACKGROUND_UPLOAD \
      GITLAB_PACKAGES_OBJECT_STORE_PROXY_DOWNLOAD \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_PROVIDER \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_ACCESS_KEY_ID \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_SECRET_ACCESS_KEY \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_REGION \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_HOST \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_ENDPOINT \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_PATH_STYLE \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_AWS_SIGNATURE_VERSION \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_GOOGLE_PROJECT \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_GOOGLE_CLIENT_EMAIL \
      GITLAB_PACKAGES_OBJECT_STORE_CONNECTION_GOOGLE_JSON_KEY_LOCATION
  else
    exec_as_git sed -i -e "/path: {{GITLAB_PACKAGES_DIR}}/{n;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d;}" ${GITLAB_CONFIG}
  fi

  echo "Configuring gitlab::packages..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_PACKAGES_ENABLED \
    GITLAB_PACKAGES_DIR
}

gitlab_configure_terraform_state() {
  update_template ${GITLAB_CONFIG} \
    GITLAB_TERRAFORM_STATE_OBJECT_STORE_ENABLED
  
  if [[ ${GITLAB_TERRAFORM_STATE_OBJECT_STORE_ENABLED} == true ]]; then
    echo "Configuring gitlab::terraform_state:object_store"

    if [[ "${GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_PROVIDER}" == "Google" ]]; then
        echo " -> Google TERRAFORM STATE provider selected removing aws config"
        exec_as_git sed -i "/#start-terraform_state-aws/,/#end-terraform_state-aws/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#start-terraform_state-gcs/d" ${GITLAB_CONFIG}
        exec_as_git sed -i "/#end-terraform_state-gcs/d" ${GITLAB_CONFIG}
    fi
    if [[ "${GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_PROVIDER}" == "AWS" ]]; then
      echo " -> AWS TERRAFORM STATE provider selected removing Google config"
      exec_as_git sed -i "/#start-terraform_state-gcs/,/#end-terraform_state-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-terraform_state-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-terraform_state-aws/d" ${GITLAB_CONFIG}
    fi

    update_template ${GITLAB_CONFIG} \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_REMOTE_DIRECTORY \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_PROVIDER \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_ACCESS_KEY_ID \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_SECRET_ACCESS_KEY \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_REGION \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_HOST \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_ENDPOINT \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_PATH_STYLE \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_AWS_SIGNATURE_VERSION \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_GOOGLE_PROJECT \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_GOOGLE_CLIENT_EMAIL \
      GITLAB_TERRAFORM_STATE_OBJECT_STORE_CONNECTION_GOOGLE_JSON_KEY_LOCATION
  else
    exec_as_git sed -i -e "/storage_path: {{GITLAB_TERRAFORM_STATE_STORAGE_PATH}}/{n;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d;}" ${GITLAB_CONFIG}
  fi

  echo "Configuring gitlab::terraform_state..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_TERRAFORM_STATE_ENABLED \
    GITLAB_TERRAFORM_STATE_STORAGE_PATH
}

gitlab_configure_lfs() {
  update_template ${GITLAB_CONFIG} \
    GITLAB_LFS_OBJECT_STORE_ENABLED \
  
  if [[ ${GITLAB_LFS_OBJECT_STORE_ENABLED} == true ]]; then
    echo "Configuring gitlab::lfs:object_store"

    if [[ "${GITLAB_LFS_OBJECT_STORE_CONNECTION_PROVIDER}" == "Google" ]]; then
      echo " -> Google LFS provider selected removing aws config"
      exec_as_git sed -i "/#start-lfs-aws/,/#end-lfs-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-lfs-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-lfs-gcs/d" ${GITLAB_CONFIG}
    fi
    if [[ "${GITLAB_LFS_OBJECT_STORE_CONNECTION_PROVIDER}" == "AWS" ]]; then
      echo " -> AWS LFS provider selected removing Google config"
      exec_as_git sed -i "/#start-lfs-gcs/,/#end-lfs-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-lfs-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-lfs-aws/d" ${GITLAB_CONFIG}
    fi

    update_template ${GITLAB_CONFIG} \
      GITLAB_LFS_OBJECT_STORE_REMOTE_DIRECTORY \
      GITLAB_LFS_OBJECT_STORE_DIRECT_UPLOAD \
      GITLAB_LFS_OBJECT_STORE_BACKGROUND_UPLOAD \
      GITLAB_LFS_OBJECT_STORE_PROXY_DOWNLOAD \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_PROVIDER \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_ACCESS_KEY_ID \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_SECRET_ACCESS_KEY \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_REGION \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_HOST \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_ENDPOINT \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_PATH_STYLE \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_AWS_SIGNATURE_VERSION \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_GOOGLE_PROJECT \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_GOOGLE_CLIENT_EMAIL \
      GITLAB_LFS_OBJECT_STORE_CONNECTION_GOOGLE_JSON_KEY_LOCATION
  else
    exec_as_git sed -i -e "/path: {{GITLAB_LFS_OBJECTS_DIR}}/{n;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d;}"  ${GITLAB_CONFIG}
  fi

  echo "Configuring gitlab::lfs..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_LFS_ENABLED \
    GITLAB_LFS_OBJECTS_DIR
}

gitlab_configure_uploads() {
  update_template ${GITLAB_CONFIG} \
    GITLAB_UPLOADS_OBJECT_STORE_ENABLED

  if [[ ${GITLAB_UPLOADS_OBJECT_STORE_ENABLED} == true ]]; then
    echo "Configuring gitlab::uploads:object_store"

    if [[ "${GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_PROVIDER}" == "Google" ]]; then
      echo " -> Google UPLOADS provider selected removing aws config"
      exec_as_git sed -i "/#start-uploads-aws/,/#end-uploads-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-uploads-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-uploads-gcs/d" ${GITLAB_CONFIG}
    fi
    if [[ "${GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_PROVIDER}" == "AWS" ]]; then
      echo " -> AWS UPLOADS provider selected removing Google config"
      exec_as_git sed -i "/#start-uploads-gcs/,/#end-uploads-gcs/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#start-uploads-aws/d" ${GITLAB_CONFIG}
      exec_as_git sed -i "/#end-uploads-aws/d" ${GITLAB_CONFIG}
    fi

    update_template ${GITLAB_CONFIG} \
      GITLAB_UPLOADS_OBJECT_STORE_REMOTE_DIRECTORY \
      GITLAB_UPLOADS_OBJECT_STORE_DIRECT_UPLOAD \
      GITLAB_UPLOADS_OBJECT_STORE_BACKGROUND_UPLOAD \
      GITLAB_UPLOADS_OBJECT_STORE_PROXY_DOWNLOAD \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_PROVIDER \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_ACCESS_KEY_ID \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_SECRET_ACCESS_KEY \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_REGION \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_HOST \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_ENDPOINT \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_PATH_STYLE \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_AWS_SIGNATURE_VERSION \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_GOOGLE_PROJECT \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_GOOGLE_CLIENT_EMAIL \
      GITLAB_UPLOADS_OBJECT_STORE_CONNECTION_GOOGLE_JSON_KEY_LOCATION

  else
    exec_as_git sed -i -e "/base_dir: {{GITLAB_UPLOADS_BASE_DIR}}/{n;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d;}"  ${GITLAB_CONFIG}
  fi

  echo "Configuring gitlab::uploads..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_UPLOADS_STORAGE_PATH \
    GITLAB_UPLOADS_BASE_DIR
}

gitlab_configure_mattermost() {
  echo "Configuring gitlab::mattermost..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_MATTERMOST_ENABLED \
    GITLAB_MATTERMOST_URL
}

gitlab_configure_project_features() {
  echo "Configuring gitlab::project_features..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_PROJECTS_ISSUES \
    GITLAB_PROJECTS_MERGE_REQUESTS \
    GITLAB_PROJECTS_WIKI \
    GITLAB_PROJECTS_SNIPPETS \
    GITLAB_PROJECTS_BUILDS \
    GITLAB_PROJECTS_CONTAINER_REGISTRY \
    GITLAB_WEBHOOK_TIMEOUT
}

gitlab_configure_registry(){
  echo "Configuring gitlab::registry..."

  if [[ ${GITLAB_REGISTRY_PORT} == 443 ]]; then
    # Sets GITLAB_REGISTRY_PORT empty for the scope of this function.
    # This helps us to add an empty key to `.gitlab-ci.yml`.
    # Because 443 is the default https port it doesn't need to be included in docker push/pull commands
    # and shouldn't be displayed on the gitlab ui.
    # Example: `docker pull registry:443/some/image` is the same as `docker pull registry/some/image`
    local GITLAB_REGISTRY_PORT=""
  fi

  update_template ${GITLAB_CONFIG} \
    GITLAB_REGISTRY_ENABLED \
    GITLAB_REGISTRY_DIR \
    GITLAB_REGISTRY_HOST \
    GITLAB_REGISTRY_PORT \
    GITLAB_REGISTRY_API_URL \
    GITLAB_REGISTRY_KEY_PATH \
    GITLAB_REGISTRY_ISSUER
}

gitlab_configure_pages(){
  echo "Configuring gitlab::pages..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_PAGES_ENABLED \
    GITLAB_PAGES_DOMAIN \
    GITLAB_PAGES_PORT \
    GITLAB_PAGES_HTTPS \
    GITLAB_PAGES_ARTIFACTS_SERVER \
    GITLAB_PAGES_ACCESS_CONTROL \
    GITLAB_PAGES_NAMESPACE_IN_PATH

  if [[ -n ${GITLAB_PAGES_EXTERNAL_HTTP} ]]; then
    update_template ${GITLAB_CONFIG} \
      GITLAB_PAGES_EXTERNAL_HTTP
  else
    exec_as_git sed -ie "/{{GITLAB_PAGES_EXTERNAL_HTTP}}/d" ${GITLAB_CONFIG}
  fi

  if [[ -n ${GITLAB_PAGES_EXTERNAL_HTTPS} ]]; then
    update_template ${GITLAB_CONFIG} \
      GITLAB_PAGES_EXTERNAL_HTTPS
  else
    exec_as_git sed -ie "/{{GITLAB_PAGES_EXTERNAL_HTTPS}}/d" ${GITLAB_CONFIG}
  fi
}

gitlab_configure_sentry(){
  echo "Configuring gitlab::sentry..."
  update_template ${GITLAB_CONFIG} \
    SENTRY_ENABLED \
    SENTRY_DSN \
    SENTRY_CLIENTSIDE_DSN \
    SENTRY_ENVIRONMENT
}

gitlab_configure_content_security_policy(){
  echo "Configuring gitlab::content_security_policy..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_CONTENT_SECURITY_POLICY_ENABLED \
    GITLAB_CONTENT_SECURITY_POLICY_REPORT_ONLY \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_BASE_URI \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_CHILD_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_CONNECT_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_DEFAULT_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_FONT_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_FORM_ACTION \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_FRAME_ANCESTORS \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_FRAME_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_IMG_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_MANIFEST_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_MEDIA_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_OBJECT_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_SCRIPT_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_STYLE_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_WORKER_SRC \
    GITLAB_CONTENT_SECURITY_POLICY_DIRECTIVES_REPORT_URI
}

nginx_configure_gitlab_ssl() {
  if [[ ${GITLAB_HTTPS} == true && -f ${SSL_CERTIFICATE_PATH} && -f ${SSL_KEY_PATH} && -f ${SSL_DHPARAM_PATH} ]]; then
    echo "Configuring nginx::gitlab::ssl..."

    if [[ ! -f ${SSL_CA_CERTIFICATES_PATH} ]]; then
      sed -i "/{{SSL_CA_CERTIFICATES_PATH}}/d" ${GITLAB_NGINX_CONFIG}
    fi
    update_template ${GITLAB_NGINX_CONFIG} \
      SSL_CERTIFICATE_PATH \
      SSL_KEY_PATH \
      SSL_DHPARAM_PATH \
      SSL_VERIFY_CLIENT \
      SSL_CA_CERTIFICATES_PATH \
      SSL_CIPHERS \
      SSL_PROTOCOLS
  fi
}

nginx_configure_gitlab_hsts() {
  if [[ ${GITLAB_HTTPS} == true ]]; then
    echo "Configuring nginx::gitlab::hsts..."
    if [[ ${NGINX_HSTS_ENABLED} != true ]]; then
      sed -i "/{{NGINX_HSTS_MAXAGE}}/d" ${GITLAB_NGINX_CONFIG}
    fi
    update_template ${GITLAB_NGINX_CONFIG} NGINX_HSTS_MAXAGE
  else
    sed -i "/{{NGINX_HSTS_MAXAGE}}/d" ${GITLAB_NGINX_CONFIG}
  fi
}

nginx_configure_gitlab_ipv6() {
  if [[ ! -f /proc/net/if_inet6 ]]; then
    # disable ipv6 support in nginx for gitlab
    sed -i \
      -e "/listen \[::\]:80/d" \
      -e "/listen \[::\]:443/d" \
      ${GITLAB_NGINX_CONFIG}
    # disable ipv6 support in nginx for pages
    if [[ ${GITLAB_PAGES_ENABLED} == true ]]; then
      if [[ ${GITLAB_PAGES_NGINX_PROXY} == true ]]; then
        sed -i \
          -e "/listen \[::\]:80/d" \
          -e "/listen \[::\]:443/d" \
          ${GITLAB_PAGES_NGINX_CONFIG}
      fi
    fi
  fi
}

nginx_configure_gitlab_real_ip() {
  if [[ ${NGINX_REAL_IP_RECURSIVE} == on && \
     -n ${NGINX_REAL_IP_TRUSTED_ADDRESSES} ]]; then
    echo "Configuring nginx::gitlab::real_ip..."
    update_template ${GITLAB_NGINX_CONFIG} \
      NGINX_REAL_IP_RECURSIVE \
      NGINX_REAL_IP_TRUSTED_ADDRESSES
  else
    NGINX_REAL_IP_RECURSIVE="off"
    update_template ${GITLAB_NGINX_CONFIG} \
      NGINX_REAL_IP_RECURSIVE
    sed -i "/{{NGINX_REAL_IP_TRUSTED_ADDRESSES}}/d" ${GITLAB_NGINX_CONFIG}
  fi
}

nginx_configure_gitlab() {
  echo "Configuring nginx::gitlab..."
  update_template ${GITLAB_NGINX_CONFIG} \
    GITLAB_HOME \
    GITLAB_INSTALL_DIR \
    GITLAB_LOG_DIR \
    GITLAB_HOST \
    GITLAB_PORT \
    NGINX_PROXY_BUFFERING \
    NGINX_ACCEL_BUFFERING \
    NGINX_X_FORWARDED_PROTO \
    NGINX_CUSTOM_GITLAB_SERVER_CONFIG

  nginx_configure_gitlab_ssl
  nginx_configure_gitlab_hsts
  nginx_configure_gitlab_ipv6
  nginx_configure_gitlab_real_ip
}

nginx_configure_gitlab_ci() {
  if [[ -n $GITLAB_CI_HOST ]]; then
    echo "Configuring nginx::gitlab_ci..."
    DNS_RESOLVERS=$(cat /etc/resolv.conf  | grep '^\s*nameserver' | awk '{print $2}' ORS=' ')
    update_template ${GITLAB_CI_NGINX_CONFIG} \
      GITLAB_LOG_DIR \
      GITLAB_HOST \
      GITLAB_CI_HOST \
      DNS_RESOLVERS
  fi
}

nginx_configure_gitlab_registry() {
  if [[ $GITLAB_REGISTRY_ENABLED == true && -f ${SSL_REGISTRY_CERT_PATH} && -f ${SSL_REGISTRY_KEY_PATH} ]]; then
    echo "Configuring nginx::gitlab-registry..."
    update_template ${GITLAB_REGISTRY_NGINX_CONFIG} \
      GITLAB_LOG_DIR \
      GITLAB_REGISTRY_PORT \
      GITLAB_REGISTRY_HOST \
      GITLAB_REGISTRY_API_URL \
      SSL_REGISTRY_KEY_PATH \
      SSL_REGISTRY_CERT_PATH \
      SSL_REGISTRY_CIPHERS \
      SSL_REGISTRY_PROTOCOLS
  fi
}

nginx_configure_pages(){
  local GITLAB_PAGES_DOMAIN=$(echo $GITLAB_PAGES_DOMAIN | sed 's/\./\\\\./g')
  if [[ ${GITLAB_PAGES_ENABLED} == true ]]; then
    echo "Configuring nginx::gitlab-pages..."
    if [[ ${GITLAB_PAGES_NGINX_PROXY} == true ]]; then
      if [[ ${GITLAB_PAGES_HTTPS} == true ]]; then
        update_template ${GITLAB_PAGES_NGINX_CONFIG} \
          GITLAB_PORT \
          GITLAB_PAGES_DOMAIN \
          GITLAB_PAGES_PORT \
          GITLAB_LOG_DIR \
          GITLAB_PAGES_DOMAIN \
          SSL_PAGES_CERT_PATH \
          SSL_PAGES_KEY_PATH \
          SSL_PAGES_CIPHERS \
          SSL_PAGES_PROTOCOLS \
          SSL_DHPARAM_PATH \
          GITLAB_LOG_DIR
      else
        update_template ${GITLAB_PAGES_NGINX_CONFIG} \
          GITLAB_PAGES_DOMAIN \
          GITLAB_LOG_DIR
      fi
    else
      echo "Gitlab pages nginx proxy disabled"
      echo "Assuming custom domain setup with own HTTP(S) load balancer'"
    fi
  fi
}


#   _|_|_|              _|        _|  _|
#   _|    _|  _|    _|  _|_|_|    _|        _|_|_|
#   _|_|_|    _|    _|  _|    _|  _|  _|  _|
#   _|        _|    _|  _|    _|  _|  _|  _|
#   _|          _|_|_|  _|_|_|    _|  _|    _|_|_|

map_uidgid() {
  USERMAP_ORIG_UID=$(id -u ${GITLAB_USER})
  USERMAP_ORIG_GID=$(id -g ${GITLAB_USER})
  USERMAP_GID=${USERMAP_GID:-${USERMAP_UID:-$USERMAP_ORIG_GID}}
  USERMAP_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
  if [[ ${USERMAP_UID} != ${USERMAP_ORIG_UID} ]] || [[ ${USERMAP_GID} != ${USERMAP_ORIG_GID} ]]; then
    echo "Mapping UID and GID for ${GITLAB_USER}:${GITLAB_USER} to $USERMAP_UID:$USERMAP_GID"
    groupmod -o -g ${USERMAP_GID} ${GITLAB_USER}
    sed -i -e "s|:${USERMAP_ORIG_UID}:${USERMAP_GID}:|:${USERMAP_UID}:${USERMAP_GID}:|" /etc/passwd
    find ${GITLAB_HOME} -path ${GITLAB_DATA_DIR}/\* -prune -o -print0 | xargs -0 chown -h ${GITLAB_USER}:
  fi
}

update_ca_certificates() {
  if [[ -f ${SSL_CERTIFICATE_PATH} || -f ${SSL_CA_CERTIFICATES_PATH} || -f ${SSL_REGISTRY_CERT_PATH} ]]; then
    echo "Updating CA certificates..."
    [[ -f ${SSL_CERTIFICATE_PATH} ]] && cp "${SSL_CERTIFICATE_PATH}" /usr/local/share/ca-certificates/gitlab.crt
    [[ -f ${SSL_CA_CERTIFICATES_PATH} ]] && cp "${SSL_CA_CERTIFICATES_PATH}" /usr/local/share/ca-certificates/ca.crt
    [[ -f ${SSL_REGISTRY_CERT_PATH} ]] && cp "${SSL_REGISTRY_CERT_PATH}" /usr/local/share/ca-certificates/registry-ca.crt
    update-ca-certificates --fresh >/dev/null
  fi
}

initialize_logdir() {
  echo "Initializing logdir..."
  mkdir -p ${GITLAB_LOG_DIR}/supervisor
  chmod -R 0755 ${GITLAB_LOG_DIR}/supervisor
  chown -R root: ${GITLAB_LOG_DIR}/supervisor

  mkdir -p ${GITLAB_LOG_DIR}/nginx
  chmod -R 0755 ${GITLAB_LOG_DIR}/nginx
  chown -R ${GITLAB_USER}: ${GITLAB_LOG_DIR}/nginx

  mkdir -p ${GITLAB_LOG_DIR}/gitlab
  chmod -R 0755 ${GITLAB_LOG_DIR}/gitlab
  chown -R ${GITLAB_USER}: ${GITLAB_LOG_DIR}/gitlab

  mkdir -p ${GITLAB_LOG_DIR}/gitlab-shell
  chmod -R 0755 ${GITLAB_LOG_DIR}/gitlab-shell
  chown -R ${GITLAB_USER}: ${GITLAB_LOG_DIR}/gitlab-shell

  mkdir -p ${GITLAB_LOG_DIR}/gitaly
  chmod -R 0755 ${GITLAB_LOG_DIR}/gitaly
  chown -R ${GITLAB_USER}: ${GITLAB_LOG_DIR}/gitaly
}

initialize_datadir() {
  echo "Initializing datadir..."
  chmod 755 ${GITLAB_DATA_DIR}
  chown ${GITLAB_USER}: ${GITLAB_DATA_DIR}

  # create the ssh directory for server keys
  mkdir -p ${GITLAB_DATA_DIR}/ssh
  chown -R root: ${GITLAB_DATA_DIR}/ssh

  # create the repositories directory and make sure it has the right permissions
  mkdir -p ${GITLAB_REPOS_DIR}
  chown ${GITLAB_USER}: ${GITLAB_REPOS_DIR}
  chmod ug+rwX,o-rwx ${GITLAB_REPOS_DIR}
  exec_as_git chmod g+s ${GITLAB_REPOS_DIR}

  # create build traces directory
  mkdir -p ${GITLAB_BUILDS_DIR}
  chmod u+rwX ${GITLAB_BUILDS_DIR}
  chown ${GITLAB_USER}: ${GITLAB_BUILDS_DIR}

  # gitlab:backup:create does not respect the builds_path configuration, so we
  # symlink ${GITLAB_INSTALL_DIR}/builds -> ${GITLAB_BUILDS_DIR}
  rm -rf ${GITLAB_INSTALL_DIR}/builds
  ln -sf ${GITLAB_BUILDS_DIR} ${GITLAB_INSTALL_DIR}/builds

  # create downloads directory
  mkdir -p ${GITLAB_DOWNLOADS_DIR}
  chmod u+rwX ${GITLAB_DOWNLOADS_DIR}
  chown ${GITLAB_USER}: ${GITLAB_DOWNLOADS_DIR}

  # create shared directory
  mkdir -p ${GITLAB_SHARED_DIR}
  chmod u+rwX ${GITLAB_SHARED_DIR}
  chown ${GITLAB_USER}: ${GITLAB_SHARED_DIR}

  # create the ci_secure_files directory
  mkdir -p ${GITLAB_SHARED_DIR}/ci_secure_files
  chmod u+rwX ${GITLAB_SHARED_DIR}/ci_secure_files
  chown ${GITLAB_USER}: ${GITLAB_SHARED_DIR}/ci_secure_files

  # create external-diffs dir
  mkdir -p ${GITLAB_SHARED_DIR}/external-diffs
  chmod u+rwX ${GITLAB_SHARED_DIR}/external-diffs
  chown ${GITLAB_USER}: ${GITLAB_SHARED_DIR}/external-diffs

  # create agent plan content directory required by GitLab backup
  install -d -o ${GITLAB_USER} -g ${GITLAB_USER} -m 0700 ${GITLAB_SHARED_DIR}/agent_plan_content

  # create artifacts dir
  mkdir -p ${GITLAB_ARTIFACTS_DIR}
  chmod u+rwX ${GITLAB_ARTIFACTS_DIR}
  chown ${GITLAB_USER}: ${GITLAB_ARTIFACTS_DIR}

  # create pages dir
  mkdir -p ${GITLAB_PAGES_DIR}
  chmod u+rwX ${GITLAB_PAGES_DIR}
  chown ${GITLAB_USER}: ${GITLAB_PAGES_DIR}

  # symlink ${GITLAB_INSTALL_DIR}/shared -> ${GITLAB_DATA_DIR}/shared
  rm -rf ${GITLAB_INSTALL_DIR}/shared
  ln -sf ${GITLAB_SHARED_DIR} ${GITLAB_INSTALL_DIR}/shared

  # create lfs-objects directory
  mkdir -p ${GITLAB_LFS_OBJECTS_DIR}
  chmod u+rwX ${GITLAB_LFS_OBJECTS_DIR}
  chown ${GITLAB_USER}: ${GITLAB_LFS_OBJECTS_DIR}

  # create terraform_state directory
  if [[ ${GITLAB_TERRAFORM_STATE_ENABLED} == true ]]; then
    mkdir -p ${GITLAB_TERRAFORM_STATE_STORAGE_PATH}
    chmod u+rwX ${GITLAB_TERRAFORM_STATE_STORAGE_PATH}
    chown ${GITLAB_USER}: ${GITLAB_TERRAFORM_STATE_STORAGE_PATH}
  fi

  # create registry dir
  if [[ ${GITLAB_REGISTRY_ENABLED} == true ]]; then
    mkdir -p ${GITLAB_REGISTRY_DIR}
    chmod u+rwX ${GITLAB_REGISTRY_DIR}
    chown ${GITLAB_USER}: ${GITLAB_REGISTRY_DIR}
  fi

  # create packages directory
  if [[ ${GITLAB_PACKAGES_ENABLED} == true ]]; then
    mkdir -p ${GITLAB_PACKAGES_DIR}
    chmod u+rwX ${GITLAB_PACKAGES_DIR}
    chown ${GITLAB_USER}: ${GITLAB_PACKAGES_DIR}
  fi

  # create the backups directory
  mkdir -p ${GITLAB_BACKUP_DIR}
  if [[ ${GITLAB_BACKUP_DIR_CHOWN} == true ]]; then
    chown ${GITLAB_USER}: ${GITLAB_BACKUP_DIR}
  fi

  # create the uploads directory
  mkdir -p ${GITLAB_DATA_DIR}/uploads
  chmod 0700 ${GITLAB_DATA_DIR}/uploads
  chown ${GITLAB_USER}: ${GITLAB_DATA_DIR}/uploads

  # create the .ssh directory
  mkdir -p ${GITLAB_DATA_DIR}/.ssh
  touch ${GITLAB_DATA_DIR}/.ssh/authorized_keys
  chmod 700 ${GITLAB_DATA_DIR}/.ssh
  chmod 600 ${GITLAB_DATA_DIR}/.ssh/authorized_keys
  chown -R ${GITLAB_USER}: ${GITLAB_DATA_DIR}/.ssh
}

sanitize_datadir() {
  echo "Sanitizing datadir. Please be patient..."
  chmod -R ug+rwX,o-rwx ${GITLAB_REPOS_DIR}/
  chmod -R ug-s ${GITLAB_REPOS_DIR}/
  find ${GITLAB_REPOS_DIR}/ -type d -print0 | xargs -0 chmod g+s
  chown -R ${GITLAB_USER}: ${GITLAB_REPOS_DIR}

  chmod -R u+rwX ${GITLAB_BUILDS_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_BUILDS_DIR}

  chmod -R u+rwX ${GITLAB_DOWNLOADS_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_DOWNLOADS_DIR}

  chmod -R u+rwX ${GITLAB_TEMP_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_TEMP_DIR}

  chmod -R u+rwX ${GITLAB_SHARED_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_SHARED_DIR}

  chmod -R u+rwX ${GITLAB_ARTIFACTS_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_ARTIFACTS_DIR}

  chmod -R u+rwX ${GITLAB_PAGES_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_PAGES_DIR}

  chmod -R u+rwX ${GITLAB_LFS_OBJECTS_DIR}
  chown -R ${GITLAB_USER}: ${GITLAB_LFS_OBJECTS_DIR}

  # create terraform_state directory
  # TODO : wrap with "if [[ _ENABLED ]]" condition
  chmod u+rwX ${GITLAB_SHARED_DIR}/terraform_state
  chown ${GITLAB_USER}: ${GITLAB_SHARED_DIR}/terraform_state

  if [[ ${GITLAB_REGISTRY_ENABLED} == true ]]; then
    chmod -R u+rwX ${GITLAB_REGISTRY_DIR}
    chown -R ${GITLAB_USER}: ${GITLAB_REGISTRY_DIR}
  fi

  if [[ ${GITLAB_PACKAGES_ENABLED} ]]; then
    chmod u+rwX ${GITLAB_PACKAGES_DIR}
    chown ${GITLAB_USER}: ${GITLAB_PACKAGES_DIR}
  fi

  find ${GITLAB_DATA_DIR}/uploads -type f -exec chmod 0644 {} \;
  find ${GITLAB_DATA_DIR}/uploads -type d -not -path ${GITLAB_DATA_DIR}/uploads -exec chmod 0755 {} \;
  chmod 0700 ${GITLAB_DATA_DIR}/uploads/
  chown ${GITLAB_USER}: ${GITLAB_DATA_DIR}/uploads/

  echo "Creating gitlab-shell hooks..."
  exec_as_git ${GITLAB_SHELL_INSTALL_DIR}/bin/create-hooks
}

generate_ssh_key() {
  echo -n "${1^^} "
  ssh-keygen -qt ${1} -N '' -f ${2}
}

generate_ssh_host_keys() {
  sed -i "s|^[#]*MaxStartups[^$]*|MaxStartups ${GITLAB_SSH_MAXSTARTUPS}|" /etc/ssh/sshd_config
  sed -i "s|#HostKey /etc/ssh/|HostKey ${GITLAB_DATA_DIR}/ssh/|g" /etc/ssh/sshd_config
  if [[ ! -e ${GITLAB_DATA_DIR}/ssh/ssh_host_rsa_key ]]; then
    echo -n "Generating OpenSSH host keys... "
    generate_ssh_key rsa      ${GITLAB_DATA_DIR}/ssh/ssh_host_rsa_key
    generate_ssh_key dsa      ${GITLAB_DATA_DIR}/ssh/ssh_host_dsa_key
    generate_ssh_key ecdsa    ${GITLAB_DATA_DIR}/ssh/ssh_host_ecdsa_key
    generate_ssh_key ed25519  ${GITLAB_DATA_DIR}/ssh/ssh_host_ed25519_key
    echo
  fi

  # ensure existing host keys have the right permissions
  chmod 0600 ${GITLAB_DATA_DIR}/ssh/*_key
  chmod 0644 ${GITLAB_DATA_DIR}/ssh/*.pub
}

update_ssh_listen_port() {
  sed -i "s|#Port 22|Port ${GITLAB_SSH_LISTEN_PORT}|g" /etc/ssh/sshd_config
}

generate_healthcheck_script() {
  # configure healthcheck script
  ## https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html
  local HEALTHCHECK_PROTOCOL="http"
  if [[ "${GITLAB_HTTPS}" == true && "${SSL_SELF_SIGNED}" == false ]]; then
    HEALTHCHECK_PROTOCOL="${HEALTHCHECK_PROTOCOL}s"
  fi
cat > /usr/local/sbin/healthcheck <<EOF
#!/bin/bash
url=${HEALTHCHECK_PROTOCOL}://127.0.0.1${GITLAB_RELATIVE_URL_ROOT}/-/liveness
options=( '--insecure' '--silent' )
curl "\${options[@]}" \$url
[[ "\$(curl \${options[@]} -o /dev/null -I -w '%{http_code}' \$url)" == "200" ]]
EOF
  chmod +x /usr/local/sbin/healthcheck
}

configure_container_timezone() {
  # Perform sanity check of provided timezone value
  if [ -e /usr/share/zoneinfo/${TIMEZONE} ]; then
    # Configured timezone is available

    # Set localtime
    ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime

    # Set timezone
    echo ${TIMEZONE} > /etc/timezone

    echo "Container TimeZone -> ${TIMEZONE}"
  fi
}

initialize_system() {
  map_uidgid
  initialize_logdir
  initialize_datadir
  update_ca_certificates
  generate_ssh_host_keys
  update_ssh_listen_port
  configure_container_timezone
  install_configuration_templates
  rm -rf /var/run/supervisor.sock
}

install_configuration_templates() {
  echo "Installing configuration templates..."
  install_template ${GITLAB_USER}: gitlabhq/gitlab.yml ${GITLAB_CONFIG} 0640
  install_template ${GITLAB_USER}: gitlabhq/database.yml ${GITLAB_DATABASE_CONFIG} 0640
  install_template ${GITLAB_USER}: gitlabhq/puma.rb ${GITLAB_PUMA_CONFIG} 0644
  install_template ${GITLAB_USER}: gitlabhq/resque.yml ${GITLAB_RESQUE_CONFIG} 0640
  install_template ${GITLAB_USER}: gitlabhq/secrets.yml ${GITLAB_SECRETS_CONFIG} 0600
  install_template ${GITLAB_USER}: gitlab-shell/config.yml ${GITLAB_SHELL_CONFIG} 0640
  install_template ${GITLAB_USER}: gitlabhq/cable.yml ${GITLAB_ACTIONCABLE_CONFIG} 0640

  if [[ -n ${GITLAB_RELATIVE_URL_ROOT} ]]; then
    install_template ${GITLAB_USER}: gitlabhq/relative_url.rb ${GITLAB_RELATIVE_URL_CONFIG} 0644
  fi

  if [[ ${SMTP_ENABLED} == true  ]]; then
    install_template ${GITLAB_USER}: gitlabhq/smtp_settings.rb ${GITLAB_SMTP_CONFIG}
  fi

  # custom user specified robots.txt
  if [[ -f ${GITLAB_ROBOTS_PATH} ]]; then
    exec_as_git cp ${GITLAB_ROBOTS_PATH} ${GITLAB_ROBOTS_CONFIG}
  fi

  ## ${GITLAB_NGINX_CONFIG}
  if [[ ${GITLAB_HTTPS} == true ]]; then
    if [[ -f ${SSL_CERTIFICATE_PATH} && -f ${SSL_KEY_PATH} && -f ${SSL_DHPARAM_PATH} ]]; then
      install_template root: nginx/gitlab-ssl ${GITLAB_NGINX_CONFIG}
    else
      echo "SSL Key, SSL Certificate and DHParam were not found."
      echo "Assuming that the container is running behind a HTTPS enabled load balancer."
      install_template root: nginx/gitlab ${GITLAB_NGINX_CONFIG}
    fi
  else
    install_template root: nginx/gitlab ${GITLAB_NGINX_CONFIG}
  fi


  ## ${GITLAB_PAGES_NGINX_CONFIG}
  if [[ ${GITLAB_PAGES_ENABLED} == true ]]; then
    install_template ${GITLAB_USER}: gitlab-pages/config ${GITLAB_PAGES_CONFIG} 0640
    if [[ ${GITLAB_PAGES_HTTPS} == true && -f ${SSL_PAGES_CERT_PATH} && -f ${SSL_PAGES_KEY_PATH} ]]; then
      if [[ ${GITLAB_PAGES_NGINX_PROXY} == true ]]; then
        install_template root: nginx/gitlab-pages-ssl ${GITLAB_PAGES_NGINX_CONFIG}
      else
        echo "Gitlab pages nginx proxy disabled"
        echo "Assuming custom domain setup with own HTTP(S) load balancer'"
      fi
    else
      if [[ ${GITLAB_PAGES_NGINX_PROXY} == true ]]; then
        echo "SSL Key, SSL Certificate were not found."
        echo "Assuming that the container is running behind a HTTPS enabled load balancer."
        install_template root: nginx/gitlab-pages ${GITLAB_PAGES_NGINX_CONFIG}
      else
        echo "Gitlab pages nginx proxy disabled"
        echo "Assuming custom domain setup with own HTTP(S) load balancer'"
      fi
    fi
  fi



  if [[ -n $GITLAB_CI_HOST ]]; then
    install_template root: nginx/gitlab_ci ${GITLAB_CI_NGINX_CONFIG}
  fi

  if [[ ${GITLAB_REGISTRY_ENABLED} == true ]]; then
    if [[ -f ${SSL_REGISTRY_CERT_PATH} && -f ${SSL_REGISTRY_KEY_PATH} ]]; then
      install_template root: nginx/gitlab-registry ${GITLAB_REGISTRY_NGINX_CONFIG}
    else
      echo "SSL key and certificates for Registry were not found"
      echo "Assuming that the Registry is running behind a HTTPS enabled load balancer."
    fi
  fi

  install_template ${GITLAB_USER}: gitaly/config.toml ${GITLAB_GITALY_CONFIG}
}

configure_gitlab() {
  echo "Configuring gitlab..."
  update_template ${GITLAB_CONFIG} \
    GITLAB_INSTALL_DIR \
    GITLAB_SHELL_INSTALL_DIR \
    GITLAB_DATA_DIR \
    GITLAB_REPOS_DIR \
    GITLAB_DOWNLOADS_DIR \
    GITLAB_SHARED_DIR \
    GITLAB_HOME \
    GITLAB_HOST \
    GITLAB_PORT \
    GITLAB_RELATIVE_URL_ROOT \
    GITLAB_HTTPS \
    GITLAB_SSH_HOST \
    GITLAB_SSH_LISTEN_PORT \
    GITLAB_SSH_PORT \
    GITLAB_SIGNUP_ENABLED \
    GITLAB_IMPERSONATION_ENABLED \
    GITLAB_PROJECTS_LIMIT \
    GITLAB_USERNAME_CHANGE \
    GITLAB_DEFAULT_THEME \
    GITLAB_CREATE_GROUP \
    GITLAB_ISSUE_CLOSING_PATTERN

  gitlab_configure_database
  gitlab_configure_redis
  gitlab_configure_actioncable
  gitlab_configure_secrets
  gitlab_configure_sidekiq
  gitlab_configure_gitaly
  gitlab_configure_monitoring
  gitlab_configure_gitlab_workhorse
  gitlab_configure_relative_url
  gitlab_configure_trusted_proxies
  gitlab_configure_puma
  gitlab_configure_timezone
  gitlab_configure_rack_attack
  gitlab_configure_ci
  gitlab_configure_artifacts
  gitlab_configure_packages
  gitlab_configure_terraform_state
  gitlab_configure_lfs
  gitlab_configure_uploads
  gitlab_configure_mattermost
  gitlab_configure_project_features
  gitlab_configure_mail_delivery
  gitlab_configure_microsoft_graph_mailer
  gitlab_configure_mailroom
  gitlab_configure_oauth
  gitlab_configure_ldap
  gitlab_configure_gravatar
  gitlab_configure_cron_jobs
  gitlab_configure_analytics
  gitlab_configure_backups
  generate_registry_certificates
  gitlab_configure_registry
  gitlab_configure_pages
  gitlab_configure_sentry
  generate_healthcheck_script
  gitlab_configure_content_security_policy

  # remove stale gitlab.socket
  rm -rf ${GITLAB_INSTALL_DIR}/tmp/sockets/gitlab.socket
}

# feature flags are recorded to database (schema "application_settings") so requires DB is (at least) initialized
gitlab_configure_feature_flags() {  
  echo "Configuring gitlab::feature_flags..."

  if [[ -z "${GITLAB_FEATURE_FLAGS_ENABLE_TARGETS}" && -z "${GITLAB_FEATURE_FLAGS_ENABLE_TARGETS}" ]]; then
    # Do nothing and reports no error if no targets specified
    echo "- No targets specified. skipping..."
    return 0
  fi

  # Build command line argument for script only when target is specified
  # If not, scripts fails because option specifier is recognized as feature flags for example
  # like "--disable --enable" : for this case, --disable is recognized as a value of option "--enable"
  if [[ -n "${GITLAB_FEATURE_FLAGS_DISABLE_TARGETS}" ]]; then
    GITLAB_FEATURE_FLAGS_DISABLE_TARGETS="--disable ${GITLAB_FEATURE_FLAGS_DISABLE_TARGETS}"
  fi
  # The same goes for --enable (this is the last option passed to "rails runner" that will be run below)
  # For this case (final option), it throws "missing argument" error for execution like:
  # like "--disable feature1,feature2 --enable"
  if [[ -n "${GITLAB_FEATURE_FLAGS_ENABLE_TARGETS}" ]]; then
    GITLAB_FEATURE_FLAGS_ENABLE_TARGETS="--enable ${GITLAB_FEATURE_FLAGS_ENABLE_TARGETS}"
  fi

  PWD_ORG=${PWD}
  cd "${GITLAB_INSTALL_DIR}"

  # copy the script to temporal directory : to avoid permission issue
  cp "${GITLAB_RUNTIME_DIR}/scripts/configure_feature_flags.rb" "${GITLAB_TEMP_DIR}/"
  chown "${GITLAB_USER}:" "${GITLAB_TEMP_DIR}/configure_feature_flags.rb"

  echo "- Launching rails runner to set feature flags. This will take some time...."

  # If arguments are empty, the script will do nothing and print object dump like below:
  #  - specified feature flags: {:to_be_disabled=>[], :to_be_enabled=>[]}
  # DO NOT qupte variables : word splitting must be enabled.
  # If disabled, whole string like '--disable feature_name_1,feature_name_2'
  # will be recognized as single option and results to invalid argument error
  #
  # shellcheck disable=SC2086
  exec_as_git bundle exec rails runner "${GITLAB_TEMP_DIR}/configure_feature_flags.rb" \
    ${GITLAB_FEATURE_FLAGS_DISABLE_TARGETS} \
    ${GITLAB_FEATURE_FLAGS_ENABLE_TARGETS}

  rm "${GITLAB_TEMP_DIR}/configure_feature_flags.rb"
  cd "${PWD_ORG}"
}

configure_gitlab_requires_db() {
  gitlab_configure_feature_flags
}

configure_gitlab_shell() {
  echo "Configuring gitlab-shell..."
  update_template ${GITLAB_SHELL_CONFIG} \
    GITLAB_RELATIVE_URL_ROOT \
    GITLAB_HOME \
    GITLAB_LOG_DIR \
    GITLAB_SHELL_INSTALL_DIR \
    SSL_SELF_SIGNED \
    REDIS_HOST \
    REDIS_PORT \
    REDIS_DB_NUMBER

  # update custom_hooks_dir if set $GITLAB_SHELL_CUSTOM_HOOKS_DIR
  if [[ -n ${GITLAB_SHELL_CUSTOM_HOOKS_DIR} ]]; then
    exec_as_git sed -i \
      "s|custom_hooks_dir:.*|custom_hooks_dir: $GITLAB_SHELL_CUSTOM_HOOKS_DIR|g" \
      ${GITLAB_SHELL_CONFIG}
  fi
}


configure_gitlab_pages() {
  if [[ ${GITLAB_PAGES_ENABLED} == true ]]; then
  echo "Configuring gitlab-pages..."
cat > /etc/supervisor/conf.d/gitlab-pages.conf <<EOF
[program:gitlab-pages]
priority=20
directory=${GITLAB_INSTALL_DIR}
environment=HOME=${GITLAB_HOME}
command=/usr/local/bin/gitlab-pages
  -pages-domain ${GITLAB_PAGES_DOMAIN}
  -pages-root ${GITLAB_PAGES_DIR}
  -listen-proxy :8090
EOF

if [[ -n ${GITLAB_PAGES_EXTERNAL_HTTP} ]]; then
cat >> /etc/supervisor/conf.d/gitlab-pages.conf <<EOF
  -listen-http ${GITLAB_PAGES_EXTERNAL_HTTP}
EOF
fi


if [[ -n ${GITLAB_PAGES_EXTERNAL_HTTPS} ]]; then
cat >> /etc/supervisor/conf.d/gitlab-pages.conf <<EOF
  -listen-https ${GITLAB_PAGES_EXTERNAL_HTTPS}
  -root-cert ${SSL_PAGES_CERT_PATH}
  -root-key ${SSL_PAGES_KEY_PATH}
EOF
fi

if [[ ${GITLAB_PAGES_ACCESS_CONTROL} == true ]]; then
  if [[ -z ${GITLAB_PAGES_ACCESS_SECRET} ]]; then
    GITLAB_PAGES_ACCESS_SECRET=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 40 ; echo '')
  fi

  update_template ${GITLAB_PAGES_CONFIG} \
      GITLAB_RELATIVE_URL_ROOT \
      GITLAB_PAGES_ACCESS_CLIENT_ID \
      GITLAB_PAGES_ACCESS_CLIENT_SECRET \
      GITLAB_PAGES_ACCESS_REDIRECT_URI \
      GITLAB_PAGES_ACCESS_SECRET \
      GITLAB_PAGES_ACCESS_CONTROL_SERVER \
      GITLAB_PAGES_NAMESPACE_IN_PATH \
      GITLAB_PAGES_LOG_VERBOSE \
      GITLAB_INSTALL_DIR

  if [[ -n ${GITLAB_PAGES_ARTIFACTS_SERVER_URL} ]]; then
    update_template ${GITLAB_PAGES_CONFIG} GITLAB_PAGES_ARTIFACTS_SERVER_URL
  else
    exec_as_git sed -i "/{{GITLAB_PAGES_ARTIFACTS_SERVER_URL}}/d" ${GITLAB_PAGES_CONFIG}
  fi
else
  update_template ${GITLAB_PAGES_CONFIG} \
      GITLAB_RELATIVE_URL_ROOT \
      GITLAB_PAGES_NAMESPACE_IN_PATH \
      GITLAB_PAGES_LOG_VERBOSE \
      GITLAB_INSTALL_DIR

  exec_as_git sed -i "/{{GITLAB_PAGES_ACCESS_CLIENT_ID}}/d" ${GITLAB_PAGES_CONFIG}
  exec_as_git sed -i "/{{GITLAB_PAGES_ACCESS_CLIENT_SECRET}}/d" ${GITLAB_PAGES_CONFIG}
  exec_as_git sed -i "/{{GITLAB_PAGES_ACCESS_REDIRECT_URI}}/d" ${GITLAB_PAGES_CONFIG}
  exec_as_git sed -i "/{{GITLAB_PAGES_ACCESS_SECRET}}/d" ${GITLAB_PAGES_CONFIG}
  exec_as_git sed -i "/{{GITLAB_PAGES_ACCESS_CONTROL_SERVER}}/d" ${GITLAB_PAGES_CONFIG}
  exec_as_git sed -i "/{{GITLAB_PAGES_ARTIFACTS_SERVER_URL}}/d" ${GITLAB_PAGES_CONFIG}
fi

cat >> /etc/supervisor/conf.d/gitlab-pages.conf <<EOF
  -config ${GITLAB_PAGES_CONFIG}
EOF

cat >> /etc/supervisor/conf.d/gitlab-pages.conf <<EOF
user=git
autostart=true
autorestart=true
stdout_logfile=${GITLAB_INSTALL_DIR}/log/%(program_name)s.log
stderr_logfile=${GITLAB_INSTALL_DIR}/log/%(program_name)s.log
EOF
fi
}

configure_nginx() {
  echo "Configuring nginx..."
  sed -i \
  -e "s|worker_processes .*|worker_processes ${NGINX_WORKERS};|" \
  -e "s|# server_names_hash_bucket_size 64;|server_names_hash_bucket_size ${NGINX_SERVER_NAMES_HASH_BUCKET_SIZE};|" \
  /etc/nginx/nginx.conf

  nginx_configure_gitlab
  nginx_configure_gitlab_ci
  nginx_configure_gitlab_registry
  nginx_configure_pages
}

migrate_database() {
  # run the `gitlab:setup` rake task if required
  QUERY="SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';"
  COUNT=$(PGPASSWORD="${DB_PASS}" psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} -Atw -c "${QUERY}")


  if [[ -z ${COUNT} || ${COUNT} -eq 0 ]]; then
    echo "Setting up GitLab for firstrun. Please be patient, this could take a while..."
    exec_as_git force=yes bundle exec rake gitlab:setup \
      ${GITLAB_ROOT_PASSWORD:+GITLAB_ROOT_PASSWORD=$GITLAB_ROOT_PASSWORD} \
      ${GITLAB_ROOT_EMAIL:+GITLAB_ROOT_EMAIL=$GITLAB_ROOT_EMAIL} >/dev/null
  fi

  # migrate database if the gitlab version has changed.
  CACHE_VERSION=
  [[ -f ${GITLAB_TEMP_DIR}/VERSION ]] && CACHE_VERSION=$(cat ${GITLAB_TEMP_DIR}/VERSION)
  if [[ ${GITLAB_VERSION} != ${CACHE_VERSION} ]]; then
    ## version check, only upgrades are allowed
    if [[ -n ${CACHE_VERSION} && $(vercmp ${GITLAB_VERSION} ${CACHE_VERSION}) -lt 0 ]]; then
      echo
      echo "ERROR: "
      echo "  Cannot downgrade from GitLab version ${CACHE_VERSION} to ${GITLAB_VERSION}."
      echo "  Only upgrades are allowed. Please use sameersbn/gitlab:${CACHE_VERSION} or higher."
      echo "  Cannot continue. Aborting!"
      echo
      return 1
    fi

    if [[ $(vercmp ${GITLAB_VERSION} 8.0.0) -gt 0 ]]; then
      if [[ -n ${CACHE_VERSION} && $(vercmp ${CACHE_VERSION} 8.0.0) -lt 0 ]]; then
        echo
        echo "ABORT: "
        echo "  Upgrading to GitLab ${GITLAB_VERSION} from ${CACHE_VERSION} is not recommended."
        echo "  Please upgrade to version 8.0.5-1 before upgrading to 8.1.0 or higher."
        echo "  Refer to https://git.io/vur4j for CI migration instructions."
        echo "  Aborting for your own safety!"
        echo
        return 1
      fi
    fi

    echo "Migrating database..."
    exec_as_git bundle exec rake db:migrate >/dev/null

    echo "${GITLAB_VERSION}" > ${GITLAB_TEMP_DIR}/VERSION
    rm -rf ${GITLAB_TEMP_DIR}/GITLAB_RELATIVE_URL_ROOT # force cache cleanup
  fi

  # clear cache if relative_url has changed.
  [[ -f ${GITLAB_TEMP_DIR}/GITLAB_RELATIVE_URL_ROOT ]] && CACHE_GITLAB_RELATIVE_URL_ROOT=$(cat ${GITLAB_TEMP_DIR}/GITLAB_RELATIVE_URL_ROOT)
  if [[ ! -f ${GITLAB_TEMP_DIR}/GITLAB_RELATIVE_URL_ROOT || ${GITLAB_RELATIVE_URL_ROOT} != ${CACHE_GITLAB_RELATIVE_URL_ROOT} ]]; then
    echo "Clearing cache..."
    exec_as_git bundle exec rake cache:clear >/dev/null 2>&1
    echo "${GITLAB_RELATIVE_URL_ROOT}" > ${GITLAB_TEMP_DIR}/GITLAB_RELATIVE_URL_ROOT
  fi
}

execute_raketask() {
  if [[ -z ${1} ]]; then
    echo "Please specify the rake task to execute. See https://github.com/gitlabhq/gitlabhq/tree/master/doc/raketasks"
    return 1
  fi

  if [[ ${1} == gitlab:backup:create  ]]; then
    /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
    supervisorctl stop gitlab_extensions:*
    supervisorctl stop gitlab:*
  fi

  if [[ ${1} == gitlab:backup:restore ]]; then
    /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
    supervisorctl stop gitlab_extensions:*
    supervisorctl stop gitlab:*
    interactive=true
    for arg in $@
    do
      if [[ $arg == BACKUP=* ]]; then
        interactive=false
        break
      fi
    done

    # user needs to select the backup to restore
    if [[ $interactive == true ]]; then
      nBackups=$(ls ${GITLAB_BACKUP_DIR}/*_gitlab_backup.tar | wc -l)
      if [[ $nBackups -eq 0 ]]; then
        echo "No backup present. Cannot continue restore process.".
        return 1
      fi

      echo
      for b in $(ls ${GITLAB_BACKUP_DIR} | grep _gitlab_backup | sort -r)
      do
        echo "‣ $b (created at $(date --date="@${b%%_*_gitlab_backup.tar}" +'%d %b, %G - %H:%M:%S %Z'))"
      done
      echo

      read -p "Select a backup to restore: " file

      if [[ -z ${file} ]]; then
        echo "Backup not specified. Exiting..."
        return 1
      fi

      if [[ ! -f ${GITLAB_BACKUP_DIR}/${file} ]]; then
        echo "Specified backup does not exist. Aborting..."
        return 1
      fi

      BACKUP=${file%%_gitlab_backup.tar}
    fi
  elif [[ ${1} == gitlab:import:repos ]]; then
    # sanitize the datadir to avoid permission issues
    sanitize_datadir
  fi
  echo "Running raketask ${1}..."
  exec_as_git bundle exec rake $@ ${BACKUP:+BACKUP=$BACKUP}
}

generate_registry_certificates() {
  if [[ ${GITLAB_REGISTRY_GENERATE_INTERNAL_CERTIFICATES} == true ]]; then
    echo 'Generating GitLab Registry internal certificates for communication between Gitlab and a Docker Registry'
    PREVIOUS_DIRECTORY=$(pwd)
    # Get directory from cert file path
    if [[ -z $GITLAB_REGISTRY_KEY_PATH ]]; then
        echo "\$GITLAB_REGISTRY_KEY_PATH is empty"
        return 1
    fi
    DIRECTORY=$(dirname "$GITLAB_REGISTRY_KEY_PATH")
    echo "Registry internal certificates will be generated in directory: $DIRECTORY"
    # Make certs directory if it doesn't exists
    mkdir -p "$DIRECTORY"
    # Go to the temporary directory
    cd "$DIRECTORY" || return
    # Get key filename
    KEY_FILENAME=$(basename "$GITLAB_REGISTRY_KEY_PATH")
    echo "Registry internal key filename: $KEY_FILENAME"
    # Generate cert filename, by default, in same directory as $KEY_FILENAME, with same name, but with extension .crt
    CERT_FILENAME=$(echo "$KEY_FILENAME" | sed "s|key|crt|" -)
    echo "Registry internal cert filename: $CERT_FILENAME"
    # Generate a random password password_file used in the next commands
    if [[ -f password_file ]] ; then
        echo "password_file exists"
    else
        openssl rand -hex -out password_file 32
    fi
    # Create a PKCS#10 certificate request
    echo "Generating internal certificate request"
    if [[ -f registry.csr ]] ; then
        echo "registry.csr exists"
    else
        openssl req -new -passout file:password_file -newkey rsa:4096 -batch > registry.csr
    fi
    # Process RSA key
    echo "Processing RSA internal key"
    if [[ -f $KEY_FILENAME ]] ; then
        echo "$KEY_FILENAME exists"
    else
        openssl rsa -passin file:password_file -in privkey.pem -out "$KEY_FILENAME"
    fi

    # Generate certificate
    echo "Generating internal certificate"
    if [[ -f $CERT_FILENAME ]] ; then
        echo "$CERT_FILENAME exists"
    else
        openssl x509 -in registry.csr -out "$CERT_FILENAME" -req -signkey "$KEY_FILENAME" -days 10000
    fi
    chown -R ${GITLAB_USER}: ${DIRECTORY}
    cd ${PREVIOUS_DIRECTORY}
  fi
}
