#!/bin/bash

set -e

current_dir=$(dirname "$(readlink -f "$0")")
# ------------------ Сохранение аргументов в лог -----------
args="$*"

date_local=$(date '+%Y-%m-%d %H:%M:%S')

args_log_path="$current_dir/args-compose-tools.log"

echo "[$date_local] compose-tools.sh run with: $args" >> "$args_log_path"
# ------------------ Установка переменных ------------------
images_dir="$current_dir/images"

# eccm
eccm_dir="$current_dir/eccm"
env_path="$eccm_dir/.env"
common_compose_path="$eccm_dir/docker-compose.yml"
jaeger_tracing_compose_path="$eccm_dir/docker-compose.tracing.yml"
https_compose_path="$eccm_dir/docker-compose.https.yml"
monitoring_compose_path="$eccm_dir/docker-compose.monitoring.yml"
eccm_composes="-f ${common_compose_path} --env-file $env_path"
eccm_docker_profiles=''

# value from .env
eccm_syslog_port=$(cat "$env_path" | grep ECCM_SYSLOG_PORT | cut -d "=" -f2)
eccm_syslog_port=${eccm_syslog_port:-514}

conntrack_delete_ports=(68 162 "$eccm_syslog_port")

# postgres
postgres_dir="$current_dir/postgres"
postgres_compose_path="$postgres_dir/docker-compose.yml"
postgres_env_path="$postgres_dir/.env"
postgres_composes="-f $postgres_compose_path --env-file $postgres_env_path"

log_levels=('DEBUG' 'INFO')

# peeper
peeper_client_dir="$current_dir/peeper"
peeper_start_command="$peeper_client_dir/compose.yml"

need_pull=false
need_save=false
need_load=false
need_clean=false
need_run=false
need_stop=false
interactive_run=false
monitoring_enabled=false
need_delete_containers=false
peeper_integration_enabled=false
internal_postgres_enabled=true

dist_ubuntu="Ubuntu"
dist_redos="RED SOFT"
dist_astralinux="AstraLinux"
dist_altlinux="ALT"

help="Script usage: $0 -s <IP-ADDRESS> [OPTIONS]

Options:
  --clean, -c                           clean containers with its data
  --delete-containers                   delete containers
  --dhcp                                run ECCM with DHCP server enabled
  --database-host <HOST>                external database hostname, prevent start internal postgres
  --database-port <PORT>                external database port (default: 5432), prevent start internal postgres
  --help, -h                            help
  --https                               enable https mode, required to have certificates
  --install                             install docker, docker-compose to host
  --interactive, -i                     use with --start, running docker-compose in foreground
  --load                                load all available .tar.gz archives from images directory to docker
  --logging, -l <LEVEL>                 turn on log level for eccm project. Available: DEBUG,INFO
  --logging-aspect                      turn on logging aspect 
  --metrics, -m                         run with \"metrics\" profile
  --peeper                              enable integration with peeper. Must be first parameter.
  --pull, -p                            pull images before launching compose
  --rootlog <LEVEL>                     turn on log level for all project. Available: DEBUG,INFO
  --save                                save all docker images to .tar.gz archives
  --start, -s <ADDRESS>                 start compose with external IP address of this host
  --stop                                stop containers
  --storage <ADDRESS>                   firmware storage interface address
  --tracing, -t <ADDRESS>               run with enabled jaeger OpenTracing reporting.
  --show-containers                     lists all containers
  --show-images                         lists all images
  --recreate-service <SERVICE>          recreates specified service
"
# ----------------- Проверка дистрибутива -----------------

function extra_astralinux() {
    echo "Add extras for start on Astralinux"

    # the problem with start postgres resolved in docker 20.10.10
    # but in Astralinux repo saved only 20.10.2
    # we need start postgres in privileged mode

    echo "set POSTGRES_PRIVILEGED_MODE=true" && \
    export POSTGRES_PRIVILEGED_MODE=true

}

function extra_redos() {
    echo "Add extras for start on RED OS"
}

function extra_ubuntu() {
    echo "Add extras for start on Ubuntu"
}

function extra_alt_linux() {
    echo "Add extras for start on Alt linux"
}

function extra_other_os() {
    echo "Other OS. No extras will be added."
}

DISTR_ID=$(lsb_release -i --short)

case ${DISTR_ID} in
    $dist_redos ) extra_redos;;
    $dist_astralinux ) extra_astralinux;;
    $dist_ubuntu ) extra_ubuntu;;
    $dist_altlinux ) extra_alt_linux;;
    * ) extra_other_os;;
esac


function install_docker_debian() {
    echo "Install docker for ${DISTR_ID} (Debian)"
    echo -e "\nInstallation requires privileged mode"
    require_package curl conntrack
    echo "Remove unofficial docker versions..."
    sudo apt remove docker docker-engine docker.io containerd runc || true
    DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
    rm -f $DOCKER_CONFIG/cli-plugins/docker-compose
    echo -e "\nInstall official docker and docker compose..."
    curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
    sudo sh /tmp/get-docker.sh
    sudo usermod -aG docker $USER
    echo -e "\nInstall is complete"
    echo "Relogin is required to apply changes"
    newgrp docker
}

function install_docker_redos() {
    echo "Install docker for REDOS"
    sudo dnf install -y docker-ce docker-compose git wget curl conntrack
    sudo usermod -aG docker $USER
    sudo systemctl enable docker
    sudo systemctl restart docker
    echo -e "\nInstall is complete"
    echo "Relogin is required to apply changes"
}

function install_docker_astralinux() {
    echo "Install docker for Astralinux"
    echo "Check configured Astrlinux deb repositories"
    sudo apt update
    cached_docker_compose_version=$(apt-cache madison docker-compose | cut -d"|" -f2)
    expected_compose_version="1.29.2"

    # нужно проверить, какая версия docker-compose в кэше apt
    if [[ ${cached_docker_compose_version} < ${expected_compose_version} ]]
    then
        echo "В репозитории старая версия docker-compose: $(cached_docker_compose_version)."
        echo "Для запуска проекта нужна версия $(expected_compose_version) или новее."

        echo "Добавить официальные публичные репозитории Astralinux и получить нужные версии оттуда?"
        read -r -p "[y/N] " response
        case "$response" in
            [yY][eE][sS]|[yY])
                repos=(
                  "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-main/ 1.7_x86-64 main contrib non-free"
                  "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-update/ 1.7_x86-64 main contrib non-free"
                  "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-base/ 1.7_x86-64 main contrib non-free"
                  "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-extended/ 1.7_x86-64 main contrib non-free"
                )
                ;;
            *)
                echo "Пожалуйста, подключите репозитории с версией docker-compose >= 1.29.2. И повторите установку."
                echo "Или установите docker и docker-compose самостоятельно."
                exit 1
                ;;
        esac
    elif [ -z "$(apt-cache madison conntrack)" ]
    then
        echo "В репозитории нет пакета conntrack."
        echo "Для запуска проекта нужен conntrack."

        echo "Добавить официальный публичный репозиторий Astralinux и получить пакет оттуда?"
        read -r -p "[y/N] " response
        case "$response" in
            [yY][eE][sS]|[yY])
                repos=(
                  "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-extended/ 1.7_x86-64 main contrib non-free"
                )
                ;;
            *)
                echo "Пожалуйста, подключите репозитории с версией docker-compose >= 1.29.2. И повторите установку."
                echo "Или установите docker и docker-compose самостоятельно."
                exit 1
                ;;
        esac
    fi

    readarray -t target < /etc/apt/sources.list

    for repo_index in "${!repos[@]}"
    do
        for value in "${target[@]}"
        do
        if [[ "${repos[$repo_index]}" == "$value" ]]
          then unset repos["$repo_index"]
        fi
        done
    done

    if [ ${#repos[@]} -ne 0 ]; then
        # делаем бэкап
        SOURCE_BACKUP_FILE=/etc/apt/sources.list.backup_$(date +"%Y%m%dT%H%M%S")
        cp -p /etc/apt/sources.list ${SOURCE_BACKUP_FILE}
        echo "SourceList was copied to ${SOURCE_BACKUP_FILE}"
        for repo in "${repos[@]}"
        do
            echo "$repo" >> /etc/apt/sources.list
        done
        echo "SourceList was updated"
        sudo apt update
        cached_docker_compose_version_2=$(apt-cache madison docker-compose | cut -d"|" -f2)
        if [[ ${cached_docker_compose_version_2} < ${expected_compose_version} ]]
        then
            echo "Не удалось получить обновления из репозиториев. Возможно нет доступа в интернет."
            exit 1
        fi
    fi

    sudo apt install -y docker.io docker-compose git wget curl conntrack
    sudo usermod -aG docker $USER
    echo -e "\nInstall is complete"
    echo "Relogin is required to apply changes"

}

function install_docker_alt_linux() {
    echo "Install docker for Alt linux"
    sudo apt-get update
    sudo apt-get install -y docker-engine docker-compose git wget curl conntrack-tools
    sudo usermod -aG docker $USER
    sudo systemctl start docker
    sudo systemctl enable docker
    echo -e "\nInstall is complete"
    echo "Relogin is required to apply changes"
}

# ------------------ Установка переменных ------------------


#------------------- Блок общих функций --------------------

# Функции нужны для того, чтобы определить способ запуска контейнеров из описания docker-compose.yml
# в зависимости от наличия в системе пакета docker-compose-plugin.
#
# Будет использоваться команда `docker compose`, если пакет docker-compose-plugin установлен
# в ином случае будет использоваться команда `docker-compose`.
#
# Способ поиска пакета docker-compose-plugin в зависимости от системы отличается.
# В Alt Linux и RED OS он представлен командой `rpm`, а в остальных - `dpkg`.
function dct_docker_compose_plugin() {
    if dpkg -l docker-compose-plugin &> /dev/null; then
        docker compose "$@"
    else
        docker-compose "$@"
    fi
}

function dct_docker_compose() {
    if rpm -qa --qf '%{name}\n' | grep -w '^docker-compose$' &> /dev/null; then
        docker compose "$@"
    else
        docker-compose "$@"
    fi
}

function dct_docker_compose_v2() {
    if rpm -qa --qf '%{name}\n' | grep -w '^docker-compose-v2$' &> /dev/null; then
        docker compose "$@"
    else
        docker-compose "$@"
    fi
}

function dct() {
    case ${DISTR_ID} in
        $dist_redos ) dct_docker_compose "$@";;
        $dist_astralinux ) dct_docker_compose_plugin "$@";;
        $dist_altlinux ) dct_docker_compose_v2 "$@";;
        * ) dct_docker_compose_plugin "$@";;
    esac
}

#------------------- Блок общих функций --------------------


# ------------------ STOP ------------------
function stop_if_needed() {
    if ${need_stop}; then
        echo "Stopping services..."
        stop_eccm
        stop_monitoring
        stop_postgres
        echo "Services stopped"
    fi
}

function stop_eccm() {
    dct ${eccm_composes} stop
}

function stop_postgres() {
    if ${internal_postgres_enabled}; then
        dct ${postgres_composes} stop
    fi
}

function stop_monitoring() {
    dct -f ${monitoring_compose_path} stop
}

# ------------------ STOP ------------------

# ------------------ DELETE CONTAINERS ------------------

function delete_containers_if_need() {
    if ${need_delete_containers}; then
        echo "Deleting containers"
        delete_containers_eccm
        delete_containers_monitoring
        delete_containers_postgres
    fi
}

function delete_containers_eccm() {
    dct ${eccm_composes} down --remove-orphans
    echo -e "ECCM containers have been removed\n"
}

function delete_containers_postgres() {
    if ${internal_postgres_enabled}; then
        dct ${postgres_composes} down --remove-orphans
        echo -e "Posgres container has been removed\n"
    fi
}

function delete_containers_monitoring() {
    dct -f ${monitoring_compose_path} down --remove-orphans
    echo -e "Monitoring containers have been removed\n"
}

# ------------------ DELETE CONTAINERS ------------------

# ------------------ CLEAN ------------------
function clean_if_needed() {
    if ${need_clean}; then
        clean_eccm
        clean_monitoring
        clean_postgres
    fi
}

function clean_eccm() {
    echo "Cleaning ECCM..."
    dct ${eccm_composes} down -v --remove-orphans
    echo -e "ECCM stopped and removed\n"
}

function clean_postgres() {
    if ${internal_postgres_enabled}; then
        echo "Cleaning postgres..."
        dct ${postgres_composes} down -v --remove-orphans
        echo -e "Postgres stopped and removed\n"
    fi
}

function clean_monitoring() {
    echo "Cleaning monitoring..."
    dct -f ${monitoring_compose_path} down -v --remove-orphans
    echo -e "Monitoring containers stopped and removed\n"
}
# ------------------ CLEAN ------------------

# ------------------ PULL ------------------
function pull_if_needed() {
    if ${need_pull}; then
        echo "Pulling images..."
        pull_eccm
        pull_monitoring
        pull_postgres
        echo "Images pulled"
    fi
}

function pull_eccm() {
    dct ${eccm_composes} pull
}

function pull_postgres() {
    if ${internal_postgres_enabled}; then
        dct ${postgres_composes} pull
    fi
}

function pull_monitoring() {
    dct -f ${monitoring_compose_path} pull
}
# ------------------ PULL ------------------

# ------------------ SAVE ------------------
function save_images_if_needed() {
    if ${need_save}; then
        echo "Saving images..."
        mkdir --parent $images_dir
        save_eccm_images
        save_monitoring_images
        save_postgres_images
        echo "Images saved to '$images_dir'"
    fi
}

function save_eccm_images() {
    docker save $(dct ${eccm_composes} config | grep -oP '^\s+image: \K(.*)$') | gzip -f > $images_dir/eccm.tar.gz
}

function save_postgres_images() {
    docker save $(dct ${postgres_composes} config | grep -oP '^\s+image: \K(.*)$') | gzip -f > $images_dir/postgres.tar.gz
}

function save_monitoring_images() {
    docker save $(dct -f ${monitoring_compose_path} config | grep -oP '^\s+image: \K(.*)$') | gzip -f > $images_dir/monitoring.tar.gz
}
# ------------------ SAVE ------------------

# ------------------ LOAD ------------------
function load_images_if_needed() {
    if ${need_load}; then
        echo "Loading images from '$images_dir'..."
        [ ! -d "$images_dir" ] && echo "Directory to load not found '$images_dir'." && return
        load_images
        echo "Images loaded"
    fi
}

function load_images() {
    for file in "$images_dir"/*.tar.gz
    do
        docker load --quiet --input "$file"
    done
}
# ------------------ LOAD ------------------

# ------------------ RUN ------------------
function run_if_needed() {
    if ${need_run}; then
        check_postgres_params
        setup_eccm_addresses
        run_postgres
        run_eccm
    fi
}

function run_postgres() {
    if ${internal_postgres_enabled}; then
        echo "Starting postgres..."
        dct ${postgres_composes} up -d --remove-orphans
        echo -e "Postgres started\n"
    fi
}

function run_eccm() {
    setup_eccm_profile
    args=(${eccm_composes} ${eccm_docker_profiles} " up --remove-orphans")
    [[ ${interactive_run} == false ]] && args+=(" -d")
    echo "Starting ECCM services..."
    dct ${args[@]}
    echo -e "ECCM started\n"
    clear_conntrack_bindings
}

function check_postgres_params() {
    # Если используется внешняя бд и не был указан хост
    if [[ $internal_postgres_enabled == false && ! -v POSTGRES_HOST ]]; then
        echo "postgres host is not specified"
        exit 1
    fi
}
# ------------------ RUN ------------------

# ------------------ SETUP ------------------
function setup_eccm_profile() {
    setup_profile "$env_path" 'ECCM_PROFILE'
    if ${monitoring_enabled}; then
        eccm_docker_profiles="${eccm_docker_profiles} --profile metrics"
    fi
}

function setup_profile() {
    local definedProfile
    definedProfile=$(source "$1" && echo "${!2}")

    local additional_profiles="$3"
    [ -z "$additional_profiles" ] || definedProfile="$definedProfile,$additional_profiles"

    if [[ -z "$definedProfile" ]]; then
        export $2="$common_profiles"
    elif [[ -z "$common_profiles" ]]; then
        export $2="$definedProfile"
    else
        export $2="$definedProfile,$common_profiles"
    fi
}

function add_common_profile() {
    [[ -z "$common_profiles" ]] && common_profiles="$1" || common_profiles="$common_profiles,$1"
}

function setup_eccm_addresses() {

    [[ -n "$ip_address" ]] && \
        echo "set ECCM_WEB_ADDRESS=$ip_address" && \
        export ECCM_WEB_ADDRESS=${ip_address}

    [[ -n "$ip_address" ]] && \
        echo "set IDENTITY_PROVIDER_HOST=$ip_address" && \
        export IDENTITY_PROVIDER_HOST=${ip_address}

    [[ -n "$storage_address" || -n "$ip_address" ]] && \
        echo "set ECCM_BACKBONE_ADDRESS=${storage_address:-${ip_address}}" && \
        export ECCM_BACKBONE_ADDRESS=${storage_address:-${ip_address}}

    if ${internal_postgres_enabled}; then
        # set local ip address for postgres
        [[ -n "$ip_address" ]] && \
            echo "set POSTGRES_HOST=$ip_address" && \
            export POSTGRES_HOST=${ip_address}
    fi

    # При отсутствии ip_address результат функции, будет негативным, выполнение остановится
    # последняя операция должна быть удачной
    true
}
# ------------------ SETUP ------------------

# ------------------ SETUP OPTIONS ------------------
function setup_eltex_logging_level() {
    level=${1:?log level missing}

    if [[ " ${log_levels[@]} " =~ " ${level} " ]]; then
        export ECCM_LOGLEVEL=${level}
        echo "Set up ${ECCM_LOGLEVEL} logging level for eccm"
    else
        print_help
        exit 1
    fi
}

function setup_root_logging_level() {
    level=${1:?log level missing}

    if [[ " ${log_levels[@]} " =~ " ${level} " ]]; then
        export LOGGING_LEVEL_ROOT=${level}
        echo "Set up ${LOGGING_LEVEL_ROOT} logging level for root"
    else
        print_help
        exit 1
    fi
}


function clear_conntrack_bindings() {
    for port in "${conntrack_delete_ports[@]}"
    do
        echo "Clearing conntrack bindings for $port/udp"
        sudo /usr/sbin/conntrack -D -p udp --dport "$port" 1> /dev/null | true
    done
}


function show_containers() {
    local composeNames
    local filters

    composeNames=("$env_path" "$postgres_env_path")
    for ((i = 0; i < ${#composeNames[@]}; i++)); do
        name=$(export $(grep -v '^#' ${composeNames[i]} | cut -d '#' -f 1 | xargs -d '\n') && echo $COMPOSE_PROJECT_NAME)
        composeNames[i]="--filter name=^$name"
    done
    filters="${composeNames[*]}"

    docker container ls -a $filters --format "table {{.Names}}\t{{.Status}}\t{{.CreatedAt}}\t{{.Ports}}"
}

function show_images() {
    local imageIds

    imageIds=($(dct $eccm_composes images -q))
    imageIds+=($(dct $postgres_composes images -q))

    if [[ ${#imageIds[@]} == 0 ]]; then
        return
    fi

    # оставить от id первые 12 символов
    for ((i = 0; i < ${#imageIds[@]}; i++)); do
        imageIds[i]=${imageIds[i]::12}
    done

    imageIds=$(perl -le 'print join "|",@ARGV' "${imageIds[@]}")
    # всегда выводить первую строку с именами столбцов
    docker images -a | (read line; echo "$line"; grep -P $imageIds)
}

function recreate_service() {
    local service=${1:?service name is missing}
    local composes
    local config
    local recreated=false
    local running

    echo "Recreating service..."

    setup_eccm_addresses
    setup_eccm_profile

    composes=("$eccm_composes" "$postgres_composes")

    # пересоздать сервис с таким же именем у всех composes
    for compose in "${composes[@]}"; do
        config=$(dct $compose config)
        if echo "$config" | grep -qP "^\s+$service:$"; then
            recreated=true
            running=$(dct $compose ps --services --filter status=running)

            # если сервис запущен
            if echo "$running" | grep -Fxq $service; then
                dct $compose up --no-deps -d $service
            else
                dct $compose up --no-deps --no-start $service
            fi
        fi
    done

    if [[ $recreated == false ]]; then
        echo "Did not find any service with specified name"
        exit 1
    fi

    echo "Service recreated"
}
# ------------------ SETUP OPTIONS ------------------

function print_help() {
    echo "${help}"
}

function check_env() {
    if ! command -v docker &> /dev/null || ! command -v dct &> /dev/null; then
        if [[ ! "${@}" =~ "--install" ]]; then
            echo "docker/docker-compose is not installed. Run \`./compose-tools.sh --install\`"
            exit 1
        fi
    fi
}

function check_resources() {
    RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    RAM_GB=$(("$RAM_KB" / 1000000))

    CPU_COUNT=$(grep -c ^processor /proc/cpuinfo)

    if [[ $CPU_COUNT -lt 4 ]] || [[ $RAM_GB -lt 8 ]]; then
        echo "Minimal system requirement: 4 CPU/8 GB RAM"
        echo "Current configuration: $CPU_COUNT CPU/$RAM_GB GB RAM"
        exit 1
    fi
}

function check_certs() {
    cert="$(cat $env_path | grep CERT_PATH | head -n 1 | cut -d "=" -f2)"
    key="$(cat $env_path | grep KEY_PATH | head -n 1 | cut -d "=" -f2)"
    key_pass="$(cat $env_path | grep KEY_PASS_PATH | head -n 1 | cut -d "=" -f2)"

    file_exist_check $cert $eccm_dir
    file_exist_check $key $eccm_dir
    file_exist_check $key_pass $eccm_dir true
}

function file_exist_check() {
    file=$1
    dir=$2
    create_if_not_exists=$3

    if [ "${file::1}" == "/" ]
    then
            if test -f "$file"; then
                echo "$file exists."
            else
                echo "$file not exists."
                if $create_if_not_exists; then
                    touch "$file"
                else exit 1
                fi
            fi
    else
            if test -f "$dir/$file"; then
                echo "$dir/$file exists."
            else
                echo "$dir/$file not exists."
                if $create_if_not_exists; then
                    touch "$dir/$file"
                else exit 1
                fi
            fi
    fi
}

function check_args() {
    if [[ $# -lt 1 ]]; then
        print_help
        exit 1
    fi
}

# проверяет первый аргумент по regexp на то является ли он целым положительным числом.
# вернет true, если проверка пройдена, иначе false.
function check_port() {
    port=$1

    if [[ $port =~ ^[0-9]+([.][0-9]+)?$ ]]; then
        true
    else
        false
    fi
}

check_args "$@"
check_resources
check_env "$@"

# проверяет все перечисленные пакеты и устанавливает те, что не установлены.
function require_package() {
    pkgs=("$@")
    for pkg in "${pkgs[@]}"; do
        pkg_status=$(dpkg-query -W --showformat='${Status}' "$pkg" 2>/dev/null | true)
        if [ "$pkg_status" == "install ok installed" ]; then
            echo "$pkg is already installed"
        else
            echo "Installing $pkg..."
            sudo apt install -y "$pkg"
        fi
    done
}

while [[ $# -gt 0 ]]; do
    key=$1
    case ${key} in
    --install)
        case ${DISTR_ID} in
            $dist_redos ) install_docker_redos;;
            $dist_astralinux ) install_docker_astralinux;;
            $dist_altlinux ) install_docker_alt_linux;;
            * ) install_docker_debian;;
        esac
        ;;
    -s | --start)
        # ${2:0:1} - 2-ой аргумент, подстрока от 0 длиной 1
        # если передан ip установить его
        if ${peeper_integration_enabled}; then
            eccm_composes+=" -f ${peeper_start_command}"
        fi
        if [ $# -gt 1 ] && [ "${2:0:1}" != "-" ] ; then
            shift
            ip_address=$1
        fi
        need_run=true
        ;;
    --storage)
        shift
        storage_address=$1
        ;;
    --delete-containers)
        need_delete_containers=true
        ;;
    --dhcp)
        export DHCP_ENABLED=true
        ;;
    -c | --clean)
        need_clean=true
        ;;
    -l | --logging)
        shift
        setup_eltex_logging_level $1
        ;;
    --logging-aspect)
        export LOGGING_ASPECT_ENABLED=true
        echo "Set LOGGING_ASPECT_ENABLED=true"
        ;;
    --rootlog)
        shift
        setup_root_logging_level $1
        ;;
    --peeper)
        add_common_profile 'metrics'
        peeper_integration_enabled=true
        ;;
    -p | --pull)
        need_pull=true
        ;;
    --save)
        need_pull=true
        need_save=true
        ;;
    --load)
        need_load=true
        ;;
    -h | --help)
        print_help
        exit 0
        ;;
    -i | --interactive)
        interactive_run=true
        ;;
    --stop)
        need_stop=true
        ;;
    -m | --metrics)
        add_common_profile 'metrics'
        monitoring_enabled=true
        eccm_composes+=" -f ${monitoring_compose_path}"
        ;;
    -t | --tracing)
        shift
        export JAEGER_AGENT_HOST=$1
        eccm_composes=${eccm_composes}" -f "${jaeger_tracing_compose_path}
        ;;
    --https)
        check_certs
        eccm_composes=${eccm_composes}" -f "${https_compose_path}
        ;;
    --database-host)
        shift
        postgres_host=$1

        export POSTGRES_HOST=${postgres_host:?postgres host is empty}
        echo "set POSTGRES_HOST=${postgres_host}"

        # нет необходимости запускать PostgreSQL, если он уже запущен на другом сервере
        internal_postgres_enabled=false
        ;;
    --database-port)
        shift
        postgres_port=$1

        if ! check_port $postgres_port; then
            echo "postgres port '$postgres_port' is invalid"
            exit 1
        fi

        export POSTGRES_PORT=${postgres_port}
        echo "set POSTGRES_PORT=${postgres_port}"

        # нет необходимости запускать PostgreSQL, если он уже запущен на другом сервере
        internal_postgres_enabled=false
        ;;
    --show-containers)
        show_containers
        exit 0
        ;;
    --show-images)
        show_images
        exit 0
        ;;
    --recreate-service)
        shift
        recreate_service $1
        exit 0
        ;;
    *)
        print_help
        exit 1
        ;;
    esac
    shift
done

stop_if_needed
delete_containers_if_need
clean_if_needed
load_images_if_needed
pull_if_needed
save_images_if_needed
run_if_needed
# peeper_integration
