#!/bin/bash

JFROG_PLATFORM_NAMESPACE="jfrog-platform"
JFROG_HOST_IP=$(hostname -i 2>/dev/null | awk '{print $1}')
JFROG_BIN_DIR=${JFROG_BIN_DIR:-"/usr/bin"}
INSTALL_K3S_VERSION=${INSTALL_K3S_VERSION:-"v1.25.14+k3s1"}
JFROG_CHART_REGISTRY_URL=${JFROG_CHART_REGISTRY_URL:-"https://charts.jfrog.io"}
JFROG_CHART_VERSION=${JFROG_CHART_VERSION:-"11.5.3"}
# REF https://misc.flogisoft.com/bash/tip_colors_and_formatting
cClear="\e[0m"
cYellow="\e[1;33m"
cRedBright="\e[38;5;197m"
cGreen="\e[0;32m"
cBold="\e[1m"

exitError(){
  echo -e "[${cRedBright}ERROR${cClear}]  $1" 2>&1
  exit 1
}

bannerStart() {
    title=$1
    echo
    echo -e "${cBold}${title}${cClear}"
    echo
}

logInfo(){
    echo -e "[INFO ]  $1"
}

warn(){
    echo -e "[${cYellow}WARN${cClear} ]  $1"
}

validateSudo () {
    local OS_TYPE=$(uname)
    if [ "$OS_TYPE" == "Linux" ] && [ $EUID -ne 0 ]; then
        exitError "This script must be run as root or with sudo"
    fi
}

checkTools(){
    local toolsList="curl netstat"
    local notInstalled=""

    for tool in ${toolsList}; do
        if ! hash ${tool} >/dev/null 2>&1; then
            notInstalled="${notInstalled} ${tool}"
        fi
    done
    if [ -n "${notInstalled}" ]; then
        exitError "The following tools [ ${notInstalled} ] are missing, the script uses these to perform few actions, please install them and retry."
    fi
}

checkUrl(){
    local url="$1"
    if ! curl --output /dev/null -L --silent --head --fail "$url"; then
      exitError "Unable to access the url [ $url ], check if this environment has access to internet"
    fi
}

checkResource() {
    local recommendedMinRAM=16777216                 # 16G Total RAM => 16*1024*1024k=16777216
    local recommendedMinCPU=8

    local osType=$(uname)
    local totalRam=
    local freeCPU=

    logInfo "Validating system requirements"

    if [[ $osType == "Darwin" ]]; then
        totalRam="$(sysctl hw.memsize | awk '{print$2}')"
        freeCPU="$(sysctl hw.physicalcpu | awk '{print$2}')"
    elif [[ $osType == "Linux" ]]; then
        totalRAM="$(grep ^MemTotal /proc/meminfo | awk '{print $2}')"
        freeCPU="$(grep -c ^processor /proc/cpuinfo)"
    fi

    local msg=""

    if [[ ${totalRAM} -lt ${recommendedMinRAM} ]]; then
        let "totalRAMToShow = ${totalRAM} / 1024 / 1024"
        let "recommendedMinRAMToSHOW = ${recommendedMinRAM} / 1024 / 1024"
        warn "Running with ${totalRAMToShow}GB Total RAM. Recommended value: ${recommendedMinRAMToSHOW}GB"
    fi;

    if [ ${freeCPU} -lt ${recommendedMinCPU} ]; then
        warn "Running with ${freeCPU} CPU Cores. Recommended value: ${recommendedMinCPU} Cores"
    fi;
}

installHelm(){
  if hash helm >/dev/null 2>&1; then
      logInfo "Helm client is installed"
      return
  fi

  local url="https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3"
  checkUrl "${url}"

  logInfo "Installing Helm..."
  export HELM_INSTALL_DIR="${JFROG_BIN_DIR}"
  curl -fsSL -o get_helm.sh ${url} && \
  chmod 700 get_helm.sh && \
  ./get_helm.sh || exitError "Failed to install helm client"
}

installK3s(){
  if hash k3s >/dev/null 2>&1; then
      logInfo "k3s is installed"
      return
  fi

  local baseUrl="https://get.k3s.io"
  checkUrl "${baseUrl}"

  logInfo "Installing k3s..."
  export INSTALL_K3S_VERSION="${INSTALL_K3S_VERSION}"
  export INSTALL_K3S_BIN_DIR="${JFROG_BIN_DIR}"
  curl -s -fL ${baseUrl} | sh -s - server --cluster-init \
      --kube-apiserver-arg default-not-ready-toleration-seconds=10 \
      --kube-apiserver-arg default-unreachable-toleration-seconds=10 \
      --disable=traefik,servicelb || exitError "Failed to install k3s"
}

waitForK3s(){
    logInfo "Checking if k3s is running"
    local k3sStatus=1
    local max_retry=10
    local counter=0
    until [[ ${k3sStatus} == 0 || ${counter} -eq ${max_retry} ]] ; do
        [[ ${counter} -gt 0 ]] && logInfo "Retry count:${counter} Max Retry Count:${max_retry}"
        ((counter++))
        SYSTEMD_PAGER= service k3s status > /dev/null 2>&1
        k3sStatus=$?
        sleep 1
    done
    if [ "${k3sStatus}" != "0" ]; then
        exitError "k3s is not running. Gave up after waiting for ${max_retry} seconds. You can start k3s service with [ service k3s start ] or [ systemctl start k3s.service ]"
    else
        logInfo "k3s is running"
    fi
}

createTmpInstallerInfo(){
    local file=$1
    local callHomeInfo=$(cat <<TMP_INSTALLER_INFO
artifactory:
  installerInfo: '{"productId": "Helm_JFrogPlatform/{{ printf "${JFROG_CHART_VERSION}-%s" .Chart.AppVersion  }}", "features": [ { "featureId": "Platform/{{ printf "%s-%s" "kubernetes-k3s" .Capabilities.KubeVersion.Version }}"}]}'
TMP_INSTALLER_INFO
)
    echo "${callHomeInfo}" > ${file} || return 1
}

installPlatformChart(){
  waitForK3s
  logInfo "Installing/Upgrading Jfrog Platform Helm chart..."
  export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

  local baseUrl="${JFROG_CHART_REGISTRY_URL}"
  checkUrl "${baseUrl}"

  local tmpFile=$(mktemp JfrogK3sInstallerInfo.XXXXXXXX || echo "FAILED")

  if [[ "${tmpFile}" != "FAILED" ]] && createTmpInstallerInfo "${tmpFile}" &>/dev/null; then
        CUSTOM_VALUES_FILE="-f ${tmpFile}"
  fi

  helm repo add jfrog ${baseUrl} && \
  helm repo update && \
  helm upgrade --install jfrog-platform ${CUSTOM_VALUES_FILE} --namespace jfrog-platform jfrog/jfrog-platform \
      --version ${JFROG_CHART_VERSION} --create-namespace \
      || exitError "Failed to install jfrog helm chart"
  rm -f "${tmpFile}" &>/dev/null || true
}

postInstallMsg(){
    echo -e """
Your JFrog Platform is being deployed.
Since all the product images are being downloaded, this process may take around 15 minutes depending on your connection speed.

Execute the following steps to access Jfrog Platform UI,
1. You can check the status of the Platform by running the following,

        ${cGreen}export KUBECONFIG=/etc/rancher/k3s/k3s.yaml; kubectl get pods -n ${JFROG_PLATFORM_NAMESPACE}${cClear}

2. Once all pods are running, expose the port to JFrog platform UI,

        ${cGreen}nohup kubectl port-forward $(kubectl get pod -l app=artifactory,component=nginx -o jsonpath=\"{.items[0].metadata.name}\" -n ${JFROG_PLATFORM_NAMESPACE}) \
--address=localhost,\"${JFROG_HOST_IP}\" 80:80 -n ${JFROG_PLATFORM_NAMESPACE} >/dev/null 2>&1 & ${cClear}

3. Access the JFrog Platform UI via browser at: ${cGreen}http://${JFROG_HOST_IP}${cClear}
"""
}

bannerStart "Beginning JFrog Platform setup"
validateSudo
checkResource
checkTools
installK3s
installHelm
installPlatformChart
postInstallMsg
