#!/bin/bash
# Copyright (C) 2023 Rusbitech-Astra <support@rusbitech.ru>
# shellcheck disable=SC2086

#set -x

if [[ $# -gt 1 ]]; then
    echo "Usage: $0 [--test dir]"
fi

MODE=$1
if [[ "${MODE}" == "--test" ]]; then
    readonly SOCKET_FILE="/var/run/brest-kub.socket"
    readonly FIFO_FILE="/var/run/brest-kub.fifo"
    readonly TEMPLATE="/var/lib/brest-kub/template"
    readonly RUNTIME_STORAGE="/dev/shm/brest-kub"
    readonly KUB_SCRIPTS="/var/lib/brest-kub/scripts/"
    readonly MACHINES_FILE="/etc/cockpit/machines.d/90-brest.json"
    readonly PID_REGEX='^[0-9]+$'
    readonly REPO_STORAGE="/usr/share/cockpit/static/repo"
    readonly REPO_LOCK_FILE="/var/lock/brest-kub-repo.lock"
#else
fi


readonly SOCKET_FILE="/var/run/brest-kub.socket"
readonly FIFO_FILE="/var/run/brest-kub.fifo"
readonly TEMPLATE="/var/lib/brest-kub/template"
readonly RUNTIME_STORAGE="/dev/shm/brest-kub"
readonly KUB_SCRIPTS="/var/lib/brest-kub/scripts/"
readonly MACHINES_FILE="/etc/cockpit/machines.d/90-brest.json"
readonly PID_REGEX='^[0-9]+$'
readonly REPO_STORAGE="/usr/share/cockpit/static/repo"
readonly REPO_LOCK_FILE="/var/lock/brest-kub-repo.lock"

KUB_USER=""
PERMANENT_STORAGE="" #~/.brest-kub

REPO_PROCESS="IDLE"
CLUSTER_PROCESS="IDLE"
TERMINATE_FLAG=false
LAST_INSTALL_STEP="NONE"
CONFIG_NAME=""
CONFIG_CLUE=""

declare -A CONFIGURE_PROCESSES #USAGE: CONFIGURE_PROCESSES[HOSTNAME]=VALUE, where VALUE is process PID or "FAIL" or "SUCCESS"
declare -A HOST_STATES

declare -A EC_LABELS
EC_LABELS[0]="PREPARED"               # Prepared for ansible
EC_LABELS[1]="ASTRA_MODE_ERROR"       # Retry later
EC_LABELS[2]="INTERNAL_ERROR"         # Invalid script usage
EC_LABELS[3]="WAITING"                # Check state later
EC_LABELS[4]="PREPARE_FAILED"         # Configuring by KUB failed
EC_LABELS[5]="IP_UNAVAILABLE"         # Ping failed
EC_LABELS[6]="SSH_FAILED"             # Cannot login via ssh
EC_LABELS[7]="SUDO_ERROR"             # User has no sudo rights OR sudo is under password
EC_LABELS[8]="NETWORK_MANAGER_ERROR"  # network manager is not running
EC_LABELS[9]="AVAILABLE"              # Available for preparation
# Unknown state - not listed

ASTRA_VERSION="UNKNOWN"
ANSIBLE_VERSION="UNKNOWN"
BREST_ANSIBLE_VERSION="UNKNOWN"
BREST_KUB_VERSION="UNKNOWN"

clean_runtime_storage() {
    chmod 700 "${RUNTIME_STORAGE}" || return 1
    rm -rf "${RUNTIME_STORAGE:?}/"
    mkdir -p "${RUNTIME_STORAGE}" || return 1
    chown -R "${KUB_USER}:${KUB_USER}" "${RUNTIME_STORAGE}"
    chmod 700 "${RUNTIME_STORAGE}" || return 1
}

create_config() {
    mkdir -p "${RUNTIME_STORAGE}" || return 1
    cp -r "${TEMPLATE}" "${RUNTIME_STORAGE}/${CONFIG_NAME}" || return 1
    chmod -R 700 "${RUNTIME_STORAGE}"
    chown -R "${KUB_USER}:${KUB_USER}" "${RUNTIME_STORAGE}"

    # Write versions info
    ASTRA_VERSION="$(cat /etc/astra/build_version)"
    ANSIBLE_VERSION="$(dpkg -s ansible | grep '^Version:' | awk '{print $2}')"
    BREST_ANSIBLE_VERSION="$(dpkg -s brest-ansible | grep '^Version:' | awk '{print $2}')"
    BREST_KUB_VERSION="$(dpkg -s brest-manager | grep '^Version:' | awk '{print $2}')"

    local VERSION_FILE="${RUNTIME_STORAGE}/${CONFIG_NAME}/version"
    {
        echo "ASTRA_VERSION=${ASTRA_VERSION}"
        echo "ANSIBLE_VERSION=${ANSIBLE_VERSION}"
        echo "BREST_ANSIBLE_VERSION=${BREST_ANSIBLE_VERSION}"
        echo "BREST_KUB_VERSION=${BREST_KUB_VERSION}"
    } > "${VERSION_FILE}"
}

check_if_config_process_is_running() {
    if [[ $# -lt 1 ]]; then
        echo "INVALID_COMMAND_USAGE"
        return 1
    fi
    if [[ -z $CONF_HOST ]]; then
        #echo "Configure process for host ${CONF_HOST} is empty"
        return 1
    fi
    local CONF_HOST=$1

    if [[ ${CONFIGURE_PROCESSES[$CONF_HOST]} =~ $PID_REGEX ]]; then
        kill -0 "${CONFIGURE_PROCESSES[$CONF_HOST]}" &> /dev/null && return 0
    fi
    return 1
}

write_repo_link_line() {
    local HOST=$1
    if [[ -n $HOST ]]; then
        echo "http://${HOST}:443/cockpit/static/repo/"
    fi
}

generate_repo_links_for_all_ifs() {
    mkdir -p "${REPO_STORAGE}" || return 1
    for host in $( hostname -I ); do
        write_repo_link_line $host || return 1
    done
    write_repo_link_line "$( dnsdomainname )" || return 1
}

run_user() {
    local CMD=$1

    if [[ $CMD == "lock" ]] && [[ $# -eq 2 ]]; then
        KUB_USER=$2

        # Lock socket
        chown "${KUB_USER}:${KUB_USER}" "${SOCKET_FILE}"
        chmod 700 "${SOCKET_FILE}"

        # Process permanent storage
        local HOMEDIR
        HOMEDIR=$( getent passwd "${KUB_USER}" | cut -d: -f6 )
        PERMANENT_STORAGE="${HOMEDIR}/.brest-kub"
        mkdir -p "${PERMANENT_STORAGE}" || return 1
        chown -R "${KUB_USER}:${KUB_USER}" "${PERMANENT_STORAGE}" || return 1
        chmod -R 700 "${PERMANENT_STORAGE}" || return 1

        # Process repo storage
        mkdir -p "${REPO_STORAGE}" || return 1
        chown "${KUB_USER}:${KUB_USER}" "${REPO_STORAGE}" || return 1 # non-recursive

        # Process run-time storage
        if [[ -d "${RUNTIME_STORAGE}" ]]; then
            STORAGE_OWNER="$(stat -c '%U' "${RUNTIME_STORAGE}")"
            if [[ "${STORAGE_OWNER}" != "${KUB_USER}" ]]; then
                clean_runtime_storage
                cd "${RUNTIME_STORAGE}" # to avoid path error
            fi
        else
            mkdir -p "${RUNTIME_STORAGE}" || return 1
        fi
        chown -R "${KUB_USER}:${KUB_USER}" "${RUNTIME_STORAGE}"
        chmod -R 700 "${RUNTIME_STORAGE}"

        # Process config name
        if [[ -z ${CONFIG_NAME} ]]; then
            FOUND_CONFIG=$(ls -1 /dev/shm/brest-kub/ | head -n 1)
            if [[ -n ${FOUND_CONFIG} ]]; then
                # This is needed for the case of service restart
                # User will be asked for a password when saving
                CONFIG_NAME="${FOUND_CONFIG}"
            fi
        fi

        echo "CONFIG_NAME ${CONFIG_NAME}"
    elif [[ $CMD == "unlock" ]]; then
        KUB_USER=""
        PERMANENT_STORAGE=""
        CONFIG_NAME=""
        CONFIG_CLUE=""
        chmod 777 "${SOCKET_FILE}" || return 1
        chown "root:root" "${SOCKET_FILE}" || return 1
        clean_runtime_storage
    else
        echo "INVALID_COMMAND_USAGE"
        return 1
    fi
}

run_config() {
    local CMD=$1
    local CONFIG=$2
    local PASS=$3

    #if [[ ! -d "${RUNTIME_STORAGE}/${CONFIG}" ]]; then
    #    create_config
    #fi
    cd "${RUNTIME_STORAGE}" || return 1

    if [[ -z $CONFIG ]]; then
        if [[ -z $CONFIG_NAME ]]; then
            CONFIG="cluster"
        else
            CONFIG=$CONFIG_NAME
        fi
    fi

    if [[ $CMD == "list" ]]; then
        #cd "${PERMANENT_STORAGE}"/ || return 1
        ls -1 "${PERMANENT_STORAGE}"/ | sed "s/^${CONFIG_NAME}\$/> ${CONFIG_NAME}/g"
        #file -- * 2>/dev/null || echo ""
        #cd - &>/dev/null || return 1
    elif [[ $CMD == "new" ]]; then
        CONFIG_NAME=$CONFIG
        CONFIG_CLUE=$PASS
        clean_runtime_storage
        create_config
        return 0
    elif [[ $CMD == "clean" ]]; then
        clean_runtime_storage
        create_config
        return 0
    elif [[ $CMD == "close" ]]; then
        CONFIG_NAME=""
        CONFIG_CLUE=""
        clean_runtime_storage
        return 0
    elif [[ $CMD == "import" ]]; then
        if [[ -z $PASS ]]; then
            if [[ -z $CONFIG_CLUE ]]; then
                echo "PASSWORD_NOT_PROVIDED"
                return 1
            fi
            PASS=$CONFIG_CLUE
        else
            CONFIG_CLUE=$PASS
        fi
        if [[ ! -f "${CONFIG}" ]]; then
            echo "FILE_NOT_FOUND ${CONFIG}"
            return 1
        fi
        CONFIG_NAME=$(basename "${CONFIG}")
        cp "${CONFIG}" "${CONFIG_NAME}.enc" || return 1
        echo "Decrypt"
        openssl enc -aes-256-cbc -pbkdf2 -d -pass "pass:${PASS}" -in "${CONFIG_NAME}.enc" -out "${CONFIG_NAME}.tar" || return 1
        rm -vf "${CONFIG_NAME}.enc"
        #tar -xvf "${CONFIG_NAME}.tar" || return 1
        mkdir -p "${RUNTIME_STORAGE}/${CONFIG_NAME}"
        tar --extract  --strip-components=1 --file "${CONFIG_NAME}.tar" -C "${RUNTIME_STORAGE}/${CONFIG_NAME}"
        rm -vf "${CONFIG_NAME}.tar"
        chown -R "${KUB_USER}:${KUB_USER}" "${RUNTIME_STORAGE}/${CONFIG_NAME}"
        ln -sf "${RUNTIME_STORAGE}/${CONFIG_NAME}/machines.json" "${MACHINES_FILE}" || return 1
    elif [[ $CMD == "export" ]]; then
        if [[ -z $PASS ]]; then
            if [[ -z $CONFIG_CLUE ]]; then
                echo "PASSWORD_NOT_PROVIDED"
                return 1
            fi
            PASS=$CONFIG_CLUE
        fi
        tar -cvf "${CONFIG_NAME}.tar" "${CONFIG_NAME}" || return 1
        echo "Encrypt"
        openssl enc -aes-256-cbc -salt -pbkdf2 -pass "pass:${PASS}" -in "${CONFIG_NAME}.tar" -out  "${CONFIG_NAME}.enc" || return 1
        mv "${CONFIG_NAME}.enc" "${CONFIG}" || return 1
        rm -v "${CONFIG_NAME}.tar"
    elif [[ $CMD == "load" ]]; then
        CONFIG_NAME=$CONFIG
        run_config "import" "${PERMANENT_STORAGE}/${CONFIG}" "${PASS}"
    elif [[ $CMD == "save" ]]; then
        run_config "export" "${PERMANENT_STORAGE}/${CONFIG}" "${PASS}"
    elif [[ $CMD == "add" ]]; then
        NEW_CONFIG_NAME=$(basename "${CONFIG}")
        if [[ -f "${PERMANENT_STORAGE}/${NEW_CONFIG_NAME}" ]]; then
            echo "CONFIG_ALREADY_EXISTS ${NEW_CONFIG_NAME}"
            return 1
        fi
        mv "${CONFIG}" "${PERMANENT_STORAGE}/${NEW_CONFIG_NAME}"
    elif [[ $CMD == "delete" ]]; then
        shift 1
        for CONFIG in "$@"; do
            if [[ ! -f "${PERMANENT_STORAGE}/${CONFIG}" ]]; then
                echo "FILE_NOT_FOUND ${PERMANENT_STORAGE}/${CONFIG}"
                return 1
            fi
            echo "Removing ${CONFIG}"
            rm -rvf "${PERMANENT_STORAGE:?}/${CONFIG:?}" || return 1
        done
    else
        echo "INVALID_COMMAND_USAGE"
        return 1
    fi
}

run_state() {
    #echo "RECEIVED STATE REQUEST" | systemd-cat -t brest-kub -p info
    local STATE_TYPE=$1
    local STATE_OPERATION=$2
    if [[ -z "$STATE_TYPE" ]]; then
        STATE_TYPE="full"
    fi

    echo "CONFIG_NAME ${CONFIG_NAME}"

    local OVERALL_STATE="IDLE"
    if [[ "$STATE_TYPE" == "hosts" ]] || [[ "$STATE_TYPE" == "full" ]]; then
        for CHOST in "${!CONFIGURE_PROCESSES[@]}"; do
            CHOST_STATE="${CONFIGURE_PROCESSES[$CHOST]}"
            if [[ ${CHOST_STATE} =~ $PID_REGEX ]]; then
                if ! kill -0 "${CHOST_STATE}" &> /dev/null; then
                    wait "${CHOST_STATE}"
                    CONFIGURE_PROCESSES[$CHOST]=${EC_LABELS[$?]}
                fi
            fi
            if [[ -z ${CONFIGURE_PROCESSES[$CHOST]} ]]; then
                CONFIGURE_PROCESSES[$CHOST]="UNKNOWN"
            fi
            echo "HOST ${CHOST} ${CONFIGURE_PROCESSES[$CHOST]} ${HOST_STATES[$CHOST]}"
        done

        OVERALL_HOSTS_STATE="IDLE"
        PREV_STATE="PREPARED"
        for CHOST in "${!CONFIGURE_PROCESSES[@]}"; do
            CHOST_STATE="${CONFIGURE_PROCESSES[$CHOST]}"
            if [[ ${CHOST_STATE} == "PREPARED" ]] && [[ ${PREV_STATE} == "PREPARED" ]]; then
                OVERALL_HOSTS_STATE="SUCCESS"
            elif [[ ${CHOST_STATE} =~ $PID_REGEX ]]; then
                OVERALL_HOSTS_STATE="ONGOING"
                OVERALL_STATE="ONGOING"
                break;
            else
                OVERALL_HOSTS_STATE="NOT_CONFIGURED"
            fi
        done
        PREV_STATE=$CHOST_STATE
        echo "CONFIGURE_PROCESSES ${OVERALL_HOSTS_STATE}"
    fi

    if [[ "$STATE_TYPE" == "cluster" ]] || [[ "$STATE_TYPE" == "full" ]]; then
        if [[ ${CLUSTER_PROCESS} =~ $PID_REGEX ]]; then
            if ! kill -0 "${CLUSTER_PROCESS}" &> /dev/null; then
                wait "${CLUSTER_PROCESS}"
                CLUSTER_PROCESS="C$?"
            else
                if [[ "${TERMINATE_FLAG}" == true ]]; then
                    OVERALL_STATE="TERMINATING"
                else
                    OVERALL_STATE="ONGOING"
                fi
            fi
        fi
        echo "CLUSTER_PROCESS ${CLUSTER_PROCESS}"
        if [[ ${CLUSTER_PROCESS} == C* ]]; then
            if [[ ${STATE_OPERATION} == "collect" ]]; then
                CLUSTER_PROCESS="IDLE"
                TERMINATE_FLAG=false
            fi
        fi
        echo "LAST_INSTALL_STEP ${LAST_INSTALL_STEP}"
    fi

    if [[ "$STATE_TYPE" == "repo" ]] || [[ "$STATE_TYPE" == "full" ]]; then
        echo "AVAILABLE_REPOS $(ls -xw0 ${REPO_STORAGE}/)"

        if [[ ${REPO_PROCESS} =~ $PID_REGEX ]]; then
            if ! kill -0 "${REPO_PROCESS}" &> /dev/null; then
                wait "${REPO_PROCESS}"
                REPO_PROCESS="C$?"
            else
                OVERALL_STATE="ONGOING"
            fi
        fi
        echo "REPO_PROCESS ${REPO_PROCESS}"
        if [[ ${REPO_PROCESS} == C* ]]; then
            if [[ ${STATE_OPERATION} == "collect" ]]; then
                REPO_PROCESS="IDLE"
            fi
        fi
    fi

    if [[ "$STATE_TYPE" == "full" ]]; then
        echo "OVERALL_STATE ${OVERALL_STATE}"
    fi
}

run_host() {
    if [[ $# -lt 2 ]]; then
        echo "INVALID_COMMAND_USAGE"
        return 1
    fi

    local CMD=$1
    local HOST=$2
    shift 2
    local ARGS=$*

    if [[ $CMD == "delete" ]]; then
        unset "CONFIGURE_PROCESSES[$HOST]"
        unset "HOST_STATES[$HOST]"
        return 0
    elif [[ $CMD == "set-state" ]]; then
        HOST_STATES[$HOST]="${ARGS}"
        return 0
    fi

    echo "brest-kub-host ${CONFIG_NAME} ${CMD} ${HOST}" | systemd-cat -t brest-kub -p info
    # return if process exists for this host
    check_if_config_process_is_running "${HOST}" && return 0

    /bin/su -c "${KUB_SCRIPTS}/brest-kub-host ${CONFIG_NAME} ${CMD} ${HOST}" - "${KUB_USER}" &
    CONFIGURE_PROCESSES[$HOST]=$!
    HOST_STATES[$HOST]=""
    echo "Start host ${HOST} configure process, PID: ${CONFIGURE_PROCESSES[$HOST]}"
     #| systemd-cat -t brest-kub-host -p info
}

run_cluster() {
    # clear array
    unset CONFIGURE_PROCESSES
    unset HOST_STATES
    declare -gA CONFIGURE_PROCESSES
    declare -gA HOST_STATES

    CLUSTER_CMD=$1
    if [[ "${CLUSTER_CMD}" == "check" ]]; then
        echo "brest-kub-checker ${CONFIG_NAME}" | systemd-cat -t brest-kub -p info
        /bin/su -c "flock -n /var/lock/brest-kub-checker.lock -c '${KUB_SCRIPTS}/brest-kub-checker ${CONFIG_NAME}'" - "${KUB_USER}" &
    elif [[ "${CLUSTER_CMD}" == "step" ]]; then
        local INSTALL_STEP=$2
        if [[ -z ${INSTALL_STEP} ]]; then
            echo "STEP_NOT_SPECIFIED"
            return 1
        fi
        LAST_INSTALL_STEP="${INSTALL_STEP}"
    elif [[ "${CLUSTER_CMD}" == "terminate" ]]; then
        if [[ $CLUSTER_PROCESS =~ $PID_REGEX ]] ; then
            echo "Terminating $CLUSTER_PROCESS"
            TERMINATE_FLAG=true
            pkill -f "/bin/bash ${KUB_SCRIPTS}/brest-kub-installer ${CONFIG_NAME} install"
            # note pkill may exit with non-zero exit code, which may impact function return code
        fi
    else #pass args to install script
        TERMINATE_FLAG=false
        LAST_INSTALL_STEP="NONE"
        echo "brest-kub-installer ${CONFIG_NAME} ${CLUSTER_CMD}" | systemd-cat -t brest-kub -p info
        /bin/su -c "flock -n /var/lock/brest-kub-installer.lock -c '${KUB_SCRIPTS}/brest-kub-installer ${CONFIG_NAME} ${CLUSTER_CMD}'" - "${KUB_USER}" &

        CLUSTER_PROCESS=$!
        echo "Cluster handler process PID: ${CLUSTER_PROCESS}"
    fi
}

run_repo() {
    if [[ $# -lt 2 ]]; then
        echo "INVALID_COMMAND_USAGE"
        return 1
    fi
    local CMD=$1
    if [[ $CMD == "links" ]]; then
        local OPERATION=$2
        if [[ $OPERATION == "list" ]]; then
            generate_repo_links_for_all_ifs
        fi
        return 0
    fi

    if [[ $CMD == "delete" ]]; then
        :
    elif [[ $CMD == "create" ]]; then
        local NAME=$2
        local SOURCE=$3
        local REPO_DIR="${REPO_STORAGE}/${NAME}"
        if [[ ! -e "${SOURCE}" ]]; then
            return 1
        fi
        if [[ -e "${REPO_DIR}" ]]; then
            return 1
        fi
    else
        return 1
    fi

    ( # runs in background
        flock -n 200 || return 1
        if [[ $CMD == "delete" ]]; then
            shift 1
            for NAME in "$@"; do
                local TMP_REPO_DIR="${REPO_STORAGE}/.${NAME}"
                local REPO_DIR="${REPO_STORAGE}/${NAME}"

                mv "${REPO_DIR}" "${TMP_REPO_DIR}" || return 1
                rm -rf "${TMP_REPO_DIR:?}" || return 1
                echo "DELETED ${NAME}"
            done
        elif [[ $CMD == "create" ]]; then
            local NAME=$2
            local SOURCE=$3
            shift 3
            local LINK="$*"
            local TMP_REPO_DIR="${REPO_STORAGE}/.${NAME}"
            local REPO_DIR="${REPO_STORAGE}/${NAME}"

            if [[ -z $SOURCE ]]; then
                return 1
            fi

            if [[ ! -e "${SOURCE}" ]]; then
                return 1
            fi

            local TYPE="unknown"
            if [[ -d "${SOURCE}" ]]; then
                TYPE="cdrom"
            elif [[ -f "${SOURCE}" ]]; then
                TYPE="iso"
            else
                echo "INVALID_REPO_SOURCE_TYPE ${SOURCE}"
                return 1
            fi

            local RC=0

            #TODO: calc needed space and WARN admin?
            mkdir -p "${TMP_REPO_DIR}" || return 1

            if [[ ${TYPE} == "iso" ]]; then
                osirrox -indev "${SOURCE}" -extract / "${TMP_REPO_DIR}" || RC=1
                # TODO: add dependency on final iso unpacker - TODO test all unpackers:
                #xorriso/mount/bsdtar/7z(fails)
            elif [[ ${TYPE} == "cdrom" ]]; then
                cp -a "${SOURCE}"/* "${TMP_REPO_DIR}" || RC=1
            fi

            if [[ $RC -eq 0 ]]; then
                echo "${LINK}" >> "${TMP_REPO_DIR}/.link" || RC=1
                mv "${TMP_REPO_DIR}" "${REPO_DIR}" || RC=1
                chmod a+rx "${REPO_DIR}"
                echo "CREATED ${NAME}"
            fi

            if [[ $RC -ne 0 ]]; then
                rm -rvf "${TMP_REPO_DIR:?}"
                return 1
            fi
        fi
    ) 200>"${REPO_LOCK_FILE}" &
    REPO_PROCESS=$!
    echo "REPO_PROCESS ${REPO_PROCESS}"
}

run_help() {
    echo "commands:
    user lock <user>
    user unlock
    config <list/reset>
    config <import/export> <path> [password]
    config <save/load> <name> [password]
    state [hosts/cluster/repo/full]
        full - is default, when no arguments were specified
    host <check/configure/delete> <host>
    cluster <check/configure/install/terminate>
    repo create <name> <source iso file or mounted cdrom path> [link]
    repo delete <names separated by space>
    repo links list
    help
        prints this help"
}

run_command() {
    local CMD=$1
    shift 1
    local ARGS=$*
    #echo "Received command: ${CMD} ${ARGS}" | systemd-cat -t brest-kub -p info

    if [[ "$CMD" == "help" ]]; then
        run_help || return 1
    elif [[ "$CMD" == "user" ]]; then
        run_user $ARGS || return 1
    elif [[ "$KUB_USER" == "" ]]; then
        echo "NEED_TO_LOCK_SESSION"; return 1
    elif [[ "$CMD" == "config" ]]; then
        run_config ${ARGS} || return 1
    elif [[ "$CMD" == "state" ]]; then
        run_state ${ARGS} || return 1
    elif [[ "$CMD" == "repo" ]]; then
        run_repo ${ARGS} || return 1
    elif [[ -z ${CONFIG_NAME} ]]; then
        echo "NEED_TO_OPEN_CONFIG"; return 1
    elif [[ "$CMD" == "host" ]]; then
        run_host ${ARGS} || return 1
    elif [[ "$CMD" == "cluster" ]]; then
        run_cluster ${ARGS} || return 1
    else
        echo "UNKNOWN_COMMAND ${CMD}"
    fi

    cd "${RUNTIME_STORAGE}" # clean error
    #echo "SUCCESS"
} # |& systemd-cat -t brest-kub

command_handler() {
    while read -r line; do
        run_command $line || echo "OPERATION_FAILED"
    done > "${FIFO_FILE}"
}

# MAIN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(
    flock -n 200 || exit 1 #NO WAIT
    rm  -f "${FIFO_FILE:?}" "${SOCKET_FILE:?}"
    mkfifo "${FIFO_FILE}" -m 700
    # shellcheck disable=SC2002
    cat "${FIFO_FILE}" | socat "UNIX-LISTEN:${SOCKET_FILE},mode=777,reuseaddr,fork" STDIO | command_handler
) 200>/var/lock/brest-kub.lock
