#!/bin/bash

# Copyright UiPath 2021
#
# =================
# LICENSE AGREEMENT
# -----------------
#   Use of paid UiPath products and services is subject to the licensing agreement
#   executed between you and UiPath. Unless otherwise indicated by UiPath, use of free
#   UiPath products is subject to the associated licensing agreement available here:
#   https://www.uipath.com/legal/trust-and-security/legal-terms (or successor website).

set -e
OS=""
HAA_URL='https://download.uipath.com/haa/2023.10.1/$OS/haa-2023.10.1.tar.gz'
HAA_FILE='haa-2023.10.1.tar.gz'

function info() {
  echo -e "\e[0;32m[INFO] [$(date +'%Y-%m-%dT%H:%M:%S%z')]:\e[0m $*"
}

function warn() {
  echo -e "\e[1;33m[WARN] [$(date +'%Y-%m-%dT%H:%M:%S%z')]:\e[0m $*"
}


info "Configuring High Availability Add-On"
usage() {
    cat <<EOF
usage: $0 options
Examples: $0 -u user@company.net -p my_password -j 10.10.22.10
OPTIONS:
   -u                           Username
   -p                           Password
   -d	                        DNS
   -j                           Master node IP. If this is specified, then the node is created as slave node.
   -h                           Show this help
   -l                           License code.
   -o                           Operating system of the host. Supported values: Rhel8 and UbuntuFocal.
   --manual                     Installs HAA in manual mode. This optional argument won't configure the cluster or join any node to existing cluster.
   --advanced                   This optional argument won't install HAA, but download and decompress the HAA package. Also it displays the help with more optional arguments for the advanced installation.
   --accept-license-agreement   Use this parameter to agree to the applicable licensing agreement.
   --offline                    Use this flag if you already copied the archive $HAA_FILE to the same folder as this installation script.
   --verbose                    Verbose mode.
EOF
}

optspec="hu:p:j:l:d:o:-:"
# set initial values
VERBOSE=false
ADVANCED=false
MANUAL=false
while getopts "$optspec" option; do
    case "${option}" in

        h) usage exit 1 ;;
        u) USERNAME=${OPTARG} ;;
        p) PASSWORD=${OPTARG} ;;
		d) DNS=${OPTARG} ;;
        j) CLUSTER=${OPTARG} ;;
        l) LICENSE=${OPTARG} ;;
        o) 
            OS=${OPTARG}
            [[ $OS == "Rhel8" ||  $OS == "UbuntuFocal" ]] || (usage; exit 1)
            ;;
        -)
            case "${OPTARG}" in
                verbose)
                    VERBOSE=true
                    ;;
                advanced)
                    ADVANCED=true
                    ;;
                manual)
                    MANUAL=true
                    ;;
                accept-license-agreement)
                    LICENSE_AGREEMENT="accept"
                    ;;
                offline)
                    OFFLINE="true"
                    ;;
                *)
                    if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
                        echo "Unknown option --${OPTARG}" >&2
                    fi
                    ;;
            esac;;
        ?) usage exit 1 ;;
        *)
            if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
                echo "Non-option argument: '-${OPTARG}'" >&2
                exit 2
            fi
            ;;
    esac
done

function check_eula() {
    [[ -z "${LICENSE_AGREEMENT}" ]] || EULA="${LICENSE_AGREEMENT}"
    if [[ "${EULA}" != "accept" ]]; then
      echo "Use of paid UiPath products and services is subject to the licensing agreement executed between you and UiPath."
      echo "Unless otherwise indicated by UiPath, use of free UiPath products is subject to the associated licensing agreement available here: https://www.uipath.com/legal/trust-and-security/legal-terms (or successor website)."
      echo "By setting the environment variable LICENSE_AGREEMENT=accept or by using the --accept-license-agreement argument, you agree to the applicable licensing agreement."
      exit 0
    fi
}

function get_os() {
    OS_TYPE=$(cat /etc/os-release | grep "^ID=" | tr -d '"' | tr '[:upper:]' '[:lower:]' | awk -F '=' '{print $NF}')
    OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | tr -d '"' | awk -F '=' '{print $NF}' | awk -F '.' '{print $1}')
    case "$OS_TYPE" in
        rhel) OS="Rhel$OS_VERSION";;
        ubuntu) if [[ "$OS_VERSION" == "20" ]]; then OS="UbuntuFocal"; fi;;
        *) OS=""
    esac
    if ! [[ $OS == "Rhel8" || $OS == "UbuntuFocal" ]]; 
      then 
      OS="Rhel8" 
      warn "Couldn't determine a compatible OS. Using default OS Rhel 8."
    fi
}

download_haa(){
  if [[ "${OFFLINE}" != "true" ]]; then
    if [ -z "$OS" ]; then
        warn "Installation type is online and no OS provided. Trying to determine the OS..."
        get_os
    fi
    info "Downloading High Availability Add-On on $OS"
    eval PACKAGE_URL=$HAA_URL
    wget "$PACKAGE_URL" -O $HAA_FILE
  fi
}

decompress_haa(){
  info "Decompressing archive"
  tar -xf "$HAA_FILE"
  chmod a+x "./install.sh"
  chmod a+x "./install-haa.sh"
}

check_eula

if [[ "$ADVANCED" == "true" ]]; then
    download_haa
    decompress_haa
    echo "Advanced mode selected, please run ./install-haa.sh with optional argumets provided in this help."
    ./install-haa.sh -h
    exit 1
fi

if [[ "$MANUAL" == "false" ]]; then
    if [[ -z "$USERNAME" ]] || [[ -z "$PASSWORD" ]]; then
        usage
        exit 1
    fi
    email_regex="\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"
    if [[ ! $USERNAME =~ $email_regex ]]; then
        usage
        exit 1
    fi
fi

download_haa
decompress_haa

info "Installing High Availability Add-On"
if [[ "$VERBOSE" == "true" ]]; then
    bash ./install-haa.sh -y
else
    bash ./install-haa.sh -y 1> /dev/null
fi

post_create_db(){
    cat<<EOF
{
    "name": "uipath-orchestrator",
    "type": "redis",
    "memory_size": 2147483648,
    "port" : 10000,
    "slave_ha": true,
    "authentication_redis_pass": "${PASSWORD}",
    "uid": 3
}
EOF
}

put_update_db(){
    cat<<EOF
{
    "replication": true
}
EOF
}

post_create_cluster(){
    cat<<EOF
{
    "action": "create_cluster",
    "cluster": {
       "nodes": [],
       "name": "${DNS:=uipath.cluster}"
    },
    "credentials": {
       "username": "${USERNAME}",
       "password": "${PASSWORD}"
    }
}
EOF
}

post_join_cluster(){
    cat<<EOF
{
    "action": "join_cluster",
    "cluster": {
       "nodes": ["${CLUSTER}"],
       "name": "${DNS:=uipath.cluster}"
    },
    "credentials": {
       "username": "${USERNAME}",
       "password": "${PASSWORD}"
    }
}
EOF
}

put_license() {
    cat <<EOF
{
    "license": "----- LICENSE START -----\n${LICENSE}\n----- LICENSE END -----\n"
}
EOF
}

if [[ "$MANUAL" == "false" ]]; then
    if [[ -z "$CLUSTER" ]]; then
        info "This node will be the master node."
        info "Waiting for the API to be ready..."
        tries=0
        maxTries=12
        #Check api is up
        until $(curl --output /dev/null --silent --head --fail -k https://localhost:9443/v1/bootstrap); do
            tries=$((tries+1))
            echo "[$tries/$maxTries] Trying to reach the local API..."
            if [[ "$tries" == "$maxTries" ]]
            then
                info "Timed out while trying to reach the local API."
                exit 1
            fi
            sleep 5
        done
        info "API up and running."

        info "Creating cluster..."
        curl -k -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST --data "$(post_create_cluster)" "https://127.0.0.1:9443/v1/bootstrap/create_cluster"
        tries=0
        #Wait for node to create the cluster
        until curl -u "${USERNAME}:${PASSWORD}" -k --silent https://localhost:9443/v1/bootstrap | tr -d '[:space:]' | grep "\"state\":\"completed\""; do
            tries=$((tries+1))
            echo "[$tries/$maxTries] Waiting for the cluster to be ready..."
            if [[ "$tries" == "$maxTries" ]]
            then
                info "Timed out while waiting for the cluster to be ready"
                exit 1
            fi
            sleep 5
        done
        info "Cluster created"

        info "Creating UiPath database..."
        curl -u "${USERNAME}:${PASSWORD}" -k -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST --data "$(post_create_db)" "https://127.0.0.1:9443/v1/bdbs"

    else
        info "Waiting for the API to be ready..."
        tries=0
        maxTries=12
        #Check api is up
        until $(curl --output /dev/null --silent --head --fail -k https://localhost:9443/v1/bootstrap); do
            tries=$((tries+1))
            echo "[$tries/$maxTries] Trying to reach the local API..."
            if [[ "$tries" == "$maxTries" ]]
            then
                info "Timed out while trying to reach the local API."
                exit 1
            fi
            sleep 5
        done
        info "API up and running."
        info "Joining node to cluster... $CLUSTER" 
        curl -k -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST --data "$(post_join_cluster)" "https://127.0.0.1:9443/v1/bootstrap/join_cluster"
        #Wait for node to join the cluster
        tries=0
        until curl -u "${USERNAME}:${PASSWORD}" -k --silent https://localhost:9443/v1/bootstrap | tr -d '[:space:]' | grep "\"state\":\"completed\""; do
            tries=$((tries+1))
            echo "[$tries/$maxTries] Waiting for the node to join the cluster..."
            if [[ "$tries" == "$maxTries" ]]
            then
                info "Timed out while waiting to join the cluster."
                exit 1
            fi
            sleep 5
        done
        info "Activating DB Replication..."
        curl -u "${USERNAME}:${PASSWORD}" -k -i -H "Accept: application/json" -H "Content-Type:application/json" -X PUT --data "$(put_update_db)" "https://${CLUSTER}:9443/v1/bdbs/3"
    fi
    if [[ -n "$LICENSE" ]]; then
        curl -u "${USERNAME}:${PASSWORD}" -k -i -H "Accept: application/json" -H "Content-Type:application/json" -X PUT --data "$(put_license)" "https://127.0.0.1:9443/v1/license"
    fi
fi

info "Installation and Configuration of High Availability Add-On is finished."

set +e
