#!/bin/bash

# Copyright: 2023 Virtuozzo International GmbH

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.



inherit default os envinfo output exceptor hooks;
VERSION="1";
DEFAULT_ACTION="Usage";
DESCRIPTION="Compute node operations";

inherit_check "$deploy_module_inherit" || {
    writeJSONResponseErr "result=>4060" "message=>Invalid deploy module";
    kill ${MANAGE_KILL_TARGET} 2>/dev/null; exit 255; }
include "$replication_module_inherit";
include cartridge-common decrypt-passwd;

DOWNLOADS='/var/cache/downloads';
TMPCONF="/tmp/tmp.conf.$$";

$PROGRAM 'wget';
$PROGRAM 'unzip';
$PROGRAM 'tar';


[ "x${COMPUTE_TYPE}" == "xcartridge" ] && restoreEnvironmentVariables && {
    [ -f "${CARTRIDGE_HOME}/jelastic/scripts/deploy.sh" ] && source "${CARTRIDGE_HOME}/jelastic/scripts/deploy.sh";
    WEBROOT="${Webroot_Path}";
}

[[ -n "${WEBROOT}" ]] && [ ! -d "$WEBROOT" ] && mkdir -p "$WEBROOT";


function doUsage() {
    showUsageMessage;
}

function preDeployCallback(){
    ensureDiskSpaceIsOK;
    local temp=$(getopt -o u:,c:,e:,a:  -- $@);
    [[ $? != 0 ]] && die -q "Terminating...";
    eval set -- "$temp";
    while [ $# -gt 0 ]
    do
        case "$1" in
            -u)
                package_url=$2;
                shift;
                ;;
            -c)
                context=$2;
                [ "x$context" == "xroot" ]  && context='ROOT';
                [ "x$context" == "x/" ]  && context='ROOT';
                shift;
                ;;
            -a)
                atomic_deploy=$2;
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
        shift;
    done;

        if [[ -z "$package_url" ]]
        then
                writeJSONResponseErr "result=>4058" "message=>Wrong arguments for deploy" ;
                exit 1
        fi
        if [[ -z "$context" ]]
        then
                writeJSONResponseErr "result=>4058" "message=>Wrong arguments for deploy" ;
                exit 1
        fi
    local result=0
    isFunction "postPreDeploy" && { postPreDeploy; result=$?; }
    return $result;
}

function doDeploy(){
    # Contexts validation

    [ -n "$Context_Regex" ] && context_regex="/${Context_Regex}/p";

    case ${COMPUTE_TYPE} in

        tomcat)
            case "${COMPUTE_TYPE_VERSION}" in

                7|8|9|10|11)
                context_regex='/^((([a-zA-Z0-9])+((-|_|\.|#{1})?([a-zA-Z0-9])+)+(#{2}[0-9]+)?)|([a-zA-Z0-9]+))$/p;'
                ;;

                *)
                context_regex='/^((([a-zA-Z0-9])+((-|_|\.|#{1})([a-zA-Z0-9])+)+)|([a-zA-Z0-9]+))$/p;'
                ;;

            esac
        ;;

        jetty)
        context_regex='/^((([a-zA-Z0-9])+((-|_{1})([a-zA-Z0-9])+)+)|([a-zA-Z0-9]+))$/p;';
        ;;

        glassfish|payara|wildfly)
        context_regex='/^((([a-zA-Z0-9])+((-|_|\.{1})([a-zA-Z0-9])+)+)|([a-zA-Z0-9]+))$/p;';
        ;;

        apache-ruby|nginx-ruby)
        context_regex='/^(production|development|test)$/p;';
        ;;

    esac

    [ -z "$context_regex" ] && context_regex='/^((([a-zA-Z0-9])+(-{1}([a-zA-Z0-9])+)+)|([a-zA-Z0-9]+))$/p;'

    if [[ -z $($SED  -nre  "$context_regex" <<< $context ) ]]
    then
        writeJSONResponseErr "result=>4079" "message=>Invalid context name specified" ; exit 1;
    fi

    [ "x${COMPUTE_TYPE}" == "xapache-ruby" -o "x${COMPUTE_TYPE}" == "xnginx-ruby" ] && {
        if ! $GREP -q ${context} <<< "development production test" ; then
            writeJSONResponseErr "result=>4079" "message=>Invalid context name specified" ; exit 1;
        fi
    }

    applyHook ${context} preDeploy || { writeJSONResponseErr "result=>4125" "message=>Pre-deploy hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; };

    local vcs_project_properties="/var/lib/jelastic/vcs/${context}.properties";
    [ -f "$vcs_project_properties" ] && { set -f; rm -f "$vcs_project_properties"; set +f; }
    
    deploy_function="deploy"
 
    [ "x${COMPUTE_TYPE}" == "xcartridge" ] && { isFunction "_deploy" && deploy_function="_deploy"; CARTRIDGE_STDERR_REDIRECT="2>&1"; }

    ${deploy_function} "$package_url" "$context" "$ext" >> "$ACTIONS_LOG" "$CARTRIDGE_STDERR_REDIRECT" || {
        result=$?;
        [ $result -eq 156 ] && result=4078;
        [ $result -eq 56  ] && result=4071;
        [ ! -z "$result" ] && [ $result -lt 4000 ] && result=4060;
        writeJSONResponseErr "result=>$result" "message=>Deploy failed" ; return 1;
    };

    if [ "x${COMPUTE_TYPE}" == "xcartridge" ]; then
        ${SUDO_COMMAND} service cartridge build ; 
        ${SUDO_COMMAND} service cartridge deploy;
    fi

    applyHook ${context} postDeploy || {
        local hook_error_message="message=>Post-deploy hook execution failed. See hooks log for details: ${HOOKS_LOG}" 
        if [ "x${atomic_deploy}" == "xtrue" ]; then
            CURRENT_DIR=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1);
            PREVIOUS_DIR=$(ls -1 ${WEBROOT}  | grep "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n2|head -n 1);
            if [ -n "${PREVIOUS_DIR}" ]; then 
                ln -sfT ${WEBROOT}/${PREVIOUS_DIR} ${WEBROOT}/ROOT
                hook_error_message="${hook_error_message}. ROOT context now points to directory ${WEBROOT}/${PREVIOUS_DIR}."
                if [ "${PREVIOUS_DIR}" != "${CURRENT_DIR}" ]; then
                    rm -rf ${WEBROOT}/${CURRENT_DIR}
                fi
            fi
        fi
        writeJSONResponseErr "result=>4126" "${hook_error_message}"; return 1; 
    }

    writeJSONResponseOut "result=>0" "message=>Application deployed successfully"
}

function doUndeploy(){
    ensureDiskSpaceIsOK;
        local temp=$(getopt -o c: -- $@);
    [[ $? != 0 ]] && die -q "Terminating...";
    eval set -- "$temp";
    while [ $# -gt 0 ]
    do
        case "$1" in
            -c)
                context=$2;
                [ "x$context" == "xroot" ]  && context='ROOT';
                [ "x$context" == "x/" ]  && context='ROOT';
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
        shift;
    done;
    lUndeploy="undeploy" #added for backwards compatibility with Openshift cartridge templates
    isFunction "_undeploy" && lUndeploy="_undeploy" #must be removed after the cartridge support is finished
    "$lUndeploy" "$context" && removeHooks "$context" &&  writeJSONResponseOut "result=>0" "message=>Application removed successfully" || writeJSONResponseErr "result=>4061" "message=>Undeploy failed" ;
}

function doRenameContext(){
    ensureDiskSpaceIsOK;
    local temp=$(getopt -o e:,n:,o: -- $@);
    [[ $? != 0 ]] && die -q "Terminating...";
    eval set -- "$temp";
    while [ $# -gt 0 ]
    do
        case "$1" in
            -n|--newContext)
                newContext=$2;
                [ "x$newcontext" == "xroot" ]  && newcontext='ROOT';
                shift;
                ;;
            -o|--oldContext)
                oldContext=$2;
                [ "x$oldcontext" == "xroot" ]  && oldcontext='ROOT';
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
        shift;
    done;
    if [ "x$newContext" == "x$oldContext" ]; then
        writeJSONResponseOut "result=>0" "message=>Context renamed successfully";
    else
        renameContext "$newContext" "$oldContext"  && renameHooks "$newContext" "$oldContext" && writeJSONResponseOut "result=>0" "message=>Context renamed successfully" || writeJSONResponseErr "result=>4062" "message=>Context rename failed";
    fi
}

function doEnableReplication(){
    while [ $# -gt 0 ]
    do
        case "$1" in
            -h)
                local host=$2;
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
        shift;
    done;
    [ "x${COMPUTE_TYPE}" == "xapache-ruby" ] && {
        return 0;
    }
     enableReplication "$host";
}


function doDisableReplication(){
    [ "x${COMPUTE_TYPE}" == "xapache-ruby" ] && {
        return 0;
    }
        disableReplication;
}

function doAddToCluster(){
    local res=0
    decryptPassword $@
    res=$?
    [ $res -eq 0 ] || die -q
    set -- ${JEM_PARAMS[@]}

    while [ $# -gt 0 ]
    do
        case "$1" in
            -p)
                node_password=$2;
                shift;
                ;;
            -i)
                node_ip_address=$2;
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
        shift;
    done;

    echo "$node_ip_address $node_password" >> "$password_storage";
}

function doCleanUpCluster(){
    #~ $glassfish_tools -m cleanup;
    rm -f "$password_storage";
    restartServiceSilent iptables ;
}

function doBuildCluster(){
    $glassfish_tools -m build;
    restartServiceSilent iptables ;
}

function doSetAdminPassword(){
    tmp=$(doAction passwd set "$@");
}

function doInternalCall(){
        $glassfish_tools $@ ;
}

function doCleanUp(){
        $glassfish_tools -m cleanup >> "$JEM_CALLS_LOG" && writeJSONResponseOut "result=>0" "message=>Cleanup successful" || writeJSONResponseErr "result=>4070" "message=>Сleanup failed" ;
}

function describeAddToCluster() {
    echo "Add node to cluster";
}

function describeAddToClusterParameters() {
    echo "-p <node password> -i <node_ip_address>";
}

function describeAddToClusterOptions() {
    echo "-p: node password for admin user";
    echo "-i: node ip address";
}

function describeBuildCluster() {
    echo "Build cluster";
}

function describeCleanUp() {
    echo "Сleanup configuration";
}

function describeCleanUpCluster() {
    echo "Cleanup password storage";
}

function describeDeploy() {
    echo "Deploy application";
}

function describeDeployParameters() {
    echo "-u <url> -c <context> -a <true|false>";
}

function describeDeployOptions() {
    echo "-u: url for  application deploy ";
    echo "-c: context name to act with";
    echo "-a: use atomic deploy or not<true|false>";
}

function describeDisableReplication() {
    echo "Disable nodes replication";
}

function describeEnableReplication() {
    echo "Enable nodes replication";
}

function describeEnableReplicationParameters() {
    echo "-h <host>";
}

function describeEnableReplicationOptions() {
    echo "-h: balancer node ip";
}

function describeInternalCall() {
    echo "For JEM internal use";
}

function describeRenameContext() {
    echo "Rename deployed context";
}

function describeRenameContextParameters() {
    echo "-n|--newContext <new context> -o|--oldContext <old context>";
}

function describeRenameContextOptions() {
    echo "-n|--newContext: new context name";
    echo "-o|--oldContext: old context name";
}

function describeSetAdminPassword() {
    echo "Set password for adminstrator user";
}

function describeSetAdminPasswordParameters() {
    echo "<password>";
}

function describeSetAdminPasswordOptions() {
    echo "<password>: user password";
}

function describeUndeploy() {
    echo "Undeploy deployed application";
}

function describeUndeployParameters() {
    echo "-c <context>";
}

function describeUndeployOptions() {
    echo "-c: context name to act with";
}


