#!/usr/bin/env bash
set -o pipefail
IFS=$'\n\t'

# Copyright (c) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2020 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
# This script helps install ELS repository

# Before use the script you should get a license key in CLN. Then use to to run
# the script and wait until it done.


VERSION="0.6"
REPO_PATH="/etc/apt/sources.list.d/ubuntu-els.list"
CLN_SERVER="https://cln.cloudlinux.com"
TOKEN_END_POINT="/cln/api/els/server/register"
GPG_KEY_URL="https://www.repo.cloudlinux.com/cloudlinux/security/RPM-GPG-KEY-CloudLinux"

exec 3>&1
trap "exec 3>&-" EXIT

log() {
    printf "%s\\n" "$1" 1>&3
}

show_help() {
    cat << EOF
    Install script for ELS by Cloudlinux repository

    Options:
        -h, --help      Show this help message
        -V, --version   Show version information
        --license-key   User license key
        --cln-server    CLN server
        --hostname      Custom hostname
        --force         Force re-register if repo exist
EOF
}

do_opts() {
    if [ $# -eq 0 ]; then
        log "$(show_help)"
        exit 1
    fi
    while [ $# -gt 0 ]; do
        key="$1"
        case $key in
            -h|--help)
            log "$(show_help)"
            exit 1
            ;;
            -V|--version)
            show_version
            exit 0
            ;;
            --license-key)
            LICENSE_KEY="$2"
            shift
            ;;
            --cln-server)
            CLN_SERVER="$2"
            shift
            ;;
            --hostname)
            HOSTNAME="$2"
            shift
            ;;
            --force)
            FORCE=true
            ;;
            *)
            log "Unknown option: $key"
            log "$(show_help)"
            exit 1
            ;;
        esac
        shift
    done
    if [ -z "$LICENSE_KEY" ]; then
        log "Required argument not provided: --license-key"
        log "$(show_help)"
        exit 1
    fi
}

show_version() {
    log "$VERSION"
}

pre_run_check() {
    log "Check that repository isn't created... "
    if [ -f "$REPO_PATH" ]; then
        log "Repository exists."
        return 1
    fi
    log "Ok"
    return 0
}

get_auth_token() {
    log "Request repository token for this server... "
    local data="{\"key\": \"$3\", \"host_name\": \"$2\"}"
    local ret
    ret=$(curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d "$data" "$1")
    if [ $? -ne 0 ]; then
        log "Error (Curl command failed)"
        return 1
    fi
    if [ "$(echo "$ret" | jq -r '.token')" != "null" ]; then
        log "Ok"
        echo "$ret" | jq -r '.token'
        return 0
    fi
    log "Error (No token was returned from CLN)"
    return 1
}

get_repo_config() {
    echo "deb https://repo.cloudlinux.com/ubuntu18_04-els/$1/updates bionic main"
    echo "# deb-src https://repo.cloudlinux.com/ubuntu18_04-els/$1/updates bionic main"
}

save_repo() {
    log "Save repo file to $1... "
    if echo "$2" > "$1"; then
        log "Ok"
        return 0
    else
        log "Error (Could not write to the file $1)"
        return 1
    fi
}

get_dist_name() {
    local system_release_path="/etc/lsb-release"
    local dist_name
    log "Get OS info... "
    if [ ! -f "$system_release_path" ]; then
        log "Error (Could not determine OS: $system_release_path does not exist)"
        return 0
    fi
    dist_name=$(grep -oP '^DISTRIB_ID=\K.*' "$system_release_path")
    if [ -z "$dist_name" ]; then
        log "Error (Could not determine OS: DISTRIB_ID key not found in $system_release_path)"
        return 0
    fi
    echo "$dist_name"
    return 0
}

add_gpg_key_to_apt() {
    log "Add Cloudlinux gpg key to apt... "
    if apt-key adv --fetch-keys $GPG_KEY_URL; then
        log "Ok"
        return 0
    else
        log "Error (Could not add gpg key to apt)"
        return 1
    fi
}

remove_els_repo() {
    log "Removing repo file $1... "
    if rm "$1"; then
        log "Ok"
        return 0
    else
        log "Error (Could not remove $1)"
        return 1
    fi
}

install_els_define() {
    log "Checking els-define installation..."
    if ! dpkg -l | grep '^ii.*els-define' &>/dev/null; then
        log "Installing els-define..."
        if ! apt-get -yq install els-define 1>&3; then
            log "Failed to install els-define"
            return 1
        fi
    else
        log "els-define is already installed"
    fi
    return 0
}

main() {
    do_opts "$@"

    if [ "$(get_dist_name)" != "Ubuntu" ]; then
        return 11
    fi

    if ! pre_run_check; then
        if [ "$FORCE" = "true" ]; then
            remove_els_repo "$REPO_PATH"
        else
            log "For re-registration license run script with --force ."
            return 2
        fi
    fi

    log "Checking dependencies..."
    if ! apt-get -yq install gnupg jq 1>&3; then
        return 1
    fi

    if [ -z "$HOSTNAME" ]; then
        HOSTNAME="$(hostname)"
    fi

    local url="${CLN_SERVER}${TOKEN_END_POINT}"
    local token
    token=$(get_auth_token "$url" "$HOSTNAME" "$LICENSE_KEY")
    if [ $? -ne 0 ]; then
        return 3
    fi

    local repo_config
    repo_config="$(get_repo_config "$token")"
    if ! save_repo "$REPO_PATH" "$repo_config"; then
        return 4
    fi

    if ! add_gpg_key_to_apt; then
        return 7
    fi

    log "Updating cache..."
    if ! apt-get -yq update 1>&3; then
        log "Error (Could not update repository cache)"
        return 6
    fi

    if ! install_els_define; then
        return 8
    fi

    log "Ok"

    return 0
}

main "$@"
