#!/usr/bin/env bash

set -euo pipefail

LOGFILE=/opt/logs/commander.log

err_report() {
    echo "ERROR! On line $1 in commander script"
}

trap 'err_report $LINENO' INT TERM ERR

dn=$(dirname $0)
source "$dn/utils.sh"

function wait_server() {
    local url="$1"

    local status=0
    local cnt=0

    set +e
    res=$(curl -o /dev/null -sSLk --head --write-out '%{http_code}\n' $url 2>&1)
    if [ $? -ne 0 ]; then
        echo -n $res
    fi
    set -e
    while [ $cnt -lt 40 ] && [ "$status" != "200" ]; do
        status=$(curl -o /dev/null -sSL --head --write-out '%{http_code}\n' $url 2>>$LOGFILE)
        let cnt=$cnt+1
        if [ "$status" != "200" ]; then
            sleep 5
        fi
    done
}


read txt
case $txt in
"docker-restart")
    cd /opt/boulder
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart boulder bmysql bconsul bpkimetal bredis gui nginx &>>$LOGFILE
    sleep 45
    wait_up $PS_MYSQL &>>$LOGFILE
    wait_up $PS_CONSUL 2 &>>$LOGFILE
    wait_up $PS_PKIMETAL &>>$LOGFILE
    wait_up $PS_LABCA &>>$LOGFILE
    wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
    ;;
"acme-request")
    wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
    cd /etc/nginx/ssl

    if [ -e labca_cert.pem ]; then
        hash=$(openssl x509 -hash -noout -in labca_cert.pem)
        issuer_hash=$(openssl x509 -issuer_hash -noout -in labca_cert.pem)
    fi
    if [ "$hash" == "$issuer_hash" ] || ! expires=$(openssl x509 -checkend 172800 -noout -in labca_cert.pem); then
        url=http://boulder:4001/directory
        wait_server $url
        sleep 10
        /opt/labca/renew

        sleep 5
        cd /opt/boulder
        docker compose exec -i boulder ./bin/boulder crl-updater --config labca/config/crl-updater.json -runOnce -debug-addr :18021
        /opt/labca/checkcrl
    fi

    ln -sf /opt/labca/cron_d /etc/cron.d/labca
    ln -sf /opt/labca/logrotate_d /etc/logrotate.d/labca
    ;;
"acme-change")
    read fqdn
    cd /etc/nginx/ssl

    url=http://boulder:4001/directory
    wait_server $url
    sleep 10
    /opt/labca/renew
    ;;
"nginx-remove-redirect")
    perl -i -p0e 's/\n    # BEGIN temporary redirect\n    location = \/ \{\n        return 302 \/admin\/;\n    }\n    # END temporary redirect\n//igs' /etc/nginx/conf.d/labca.conf
    ;;
"nginx-reload")
    cd /opt/boulder
    docker compose exec nginx nginx -s reload &>>$LOGFILE
    ;;
"nginx-restart")
    cd /opt/boulder
    docker compose restart nginx &>>$LOGFILE
    ;;
"log-cert")
    [ -f /etc/nginx/ssl/certbot.log ] && tail -200 /etc/nginx/ssl/certbot.log || /bin/true
    exit 0
    ;;
"log-commander")
    [ -f $LOGFILE ] && tail -200 $LOGFILE || /bin/true
    exit 0
    ;;
"log-control-notail")
    cd /opt/boulder
    docker compose logs --no-color --tail=50 control
    ;;
"log-cron")
    [ -f /opt/logs/cron.log ] && tail -n200 -f /opt/logs/cron.log || /bin/true
    exit 0
    ;;
"log-boulder")
    cd /opt/boulder
    docker compose logs -f --no-color --tail=50 boulder
    ;;
"log-boulder-notail")
    cd /opt/boulder
    docker compose logs --no-color --tail=50 boulder
    ;;
"log-audit")
    cd /opt/boulder
    docker compose logs --no-color boulder | grep "\[AUDIT\]" | grep -v "grpc: parseServiceConfig error unmarshaling  due to unexpected end of JSON input" | tail -50
    docker compose logs -f --no-color --tail=0 boulder | grep "\[AUDIT\]"
    ;;
"log-activity")
    cd /opt/boulder
    echo "GMT"
    docker compose logs --no-color boulder | grep "\[AUDIT\]" | grep -v "grpc: parseServiceConfig error unmarshaling  due to unexpected end of JSON input" | tail -15
    exit 0
    ;;
"log-labca")
    cd /opt/boulder
    docker compose logs -f --no-color --tail=50 gui
    ;;
"log-labca-notail")
    cd /opt/boulder
    docker compose logs --no-color --tail=50 gui
    ;;
"log-web")
    cd /opt/boulder
    docker compose logs -f --no-color --tail=50 nginx
    ;;
"log-components")
    nginx=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -nginx-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    svc=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -control-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    boulder=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -boulder-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    labca=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- labca-gui) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    mysql=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bmysql-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    consul=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bconsul-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    pkimetal=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bpkimetal-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    redis=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bredis-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
    echo "$nginx|$svc|$boulder|$labca|$mysql|$consul|$pkimetal|$redis"
    exit 0
    ;;
"log-uptime")
    timezone=$(cat /etc/timezone)
    uptime=$(uptime -s)
    echo "$timezone|$uptime"
    exit 0
    ;;
"log-stats")
    docker stats --no-stream -a | grep " labca-"
    ;;
"revoke-cert")
    read serial
    read reason
    cd /opt/boulder
    # NOTE: admin is one of the few commands that is NOT a subcommand of boulder!
    docker compose exec boulder bin/admin -config labca/config/admin.json revoke-cert -serial $serial -reason $reason -dry-run=false 2>&1
    ;;
"boulder-start")
    cd /opt/boulder
    COMPOSE_HTTP_TIMEOUT=120 docker compose up -d bmysql bconsul bpkimetal bredis
    wait_up $PS_MYSQL &>>$LOGFILE
    wait_up $PS_CONSUL 2 &>>$LOGFILE
    wait_up $PS_PKIMETAL &>>$LOGFILE
    COMPOSE_HTTP_TIMEOUT=120 docker compose up -d boulder
    wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
    ;;
"boulder-stop")
    cd /opt/boulder
    docker compose stop boulder
    docker compose stop bmysql bconsul bpkimetal bredis
    wait_down $PS_MYSQL &>>$LOGFILE
    wait_down $PS_CONSUL &>>$LOGFILE
    wait_down $PS_PKIMETAL &>>$LOGFILE
    wait_down $PS_BOULDER &>>$LOGFILE
    ;;
"boulder-restart")
    cd /opt/boulder
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart boulder bmysql bconsul bpkimetal bredis &>>$LOGFILE
    sleep 30
    wait_up $PS_MYSQL &>>$LOGFILE
    wait_up $PS_CONSUL 2 &>>$LOGFILE
    wait_up $PS_PKIMETAL &>>$LOGFILE
    wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
    ;;
"labca-restart")
    cd /opt/boulder
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart gui
    sleep 15
    wait_up $PS_LABCA &>>$LOGFILE
    ;;
"mysql-restart")
    cd /opt/boulder
    set +e
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart bmysql
    set -e
    ;;
"consul-restart")
    cd /opt/boulder
    set +e
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart bconsul
    set -e
    ;;
"pkimetal-restart")
    cd /opt/boulder
    set +e
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart bpkimetal
    set -e
    ;;
"redis-restart")
    cd /opt/boulder
    set +e
    COMPOSE_HTTP_TIMEOUT=120 docker compose restart bredis
    set -e
    ;;
"log-backups")
    ls -1tr /opt/backup || /bin/true
    exit 0
    ;;
"log-server-backup")
    /opt/labca/backup
    exit 0
    ;;
"backup-delete")
    read backup
    rm -f /opt/backup/$backup
    ;;
"backup-restore")
    read backup
    /opt/labca/restore "$backup" &>>$LOGFILE
    sleep 3
    ;;
"server-restart")
    cd /opt/boulder
    nohup docker compose restart gui & >/dev/null
    nohup docker compose restart nginx & >/dev/null
    ;;
"version-update")
    cd $dn
    branch="$(git symbolic-ref --short HEAD 2>/dev/null)" || branch="(none)"
    if [ "$branch" == "master" ] || [ "$branch" == "main" ] || [ "$branch" == "(none)" ]; then
        nohup /labca/install &>>$LOGFILE
    else
        nohup /labca/install -b $branch &>>$LOGFILE
    fi
    ;;
"gen-root-crl")
    /opt/labca/bin/labca-gui -config /opt/labca/data/config.json -renewcrl 999 &>>$LOGFILE
    /opt/labca/checkcrl &>>$LOGFILE
    ;;
"gen-issuer-crl")
    cd /opt/boulder
    docker compose exec -i boulder ./bin/boulder crl-updater -config labca/config/crl-updater.json -runOnce -debug-addr :18021 &>>$LOGFILE
    /opt/labca/checkcrl &>>$LOGFILE
    ;;
"check-crl")
    /opt/labca/checkcrl &>>$LOGFILE
    ;;
"apply")
    [ ! -e /opt/labca/apply ] || /opt/labca/apply &>>$LOGFILE
    [ ! -e /opt/labca/gui/apply ] || /opt/labca/gui/apply &>>$LOGFILE
    [ -e /opt/labca/apply ] || [ -e /opt/labca/gui/apply ] || echo "Could not find apply script!"
    ;;
"git-version")
    if [ -x /usr/bin/git ]; then
        git config --global --add safe.directory /opt/labca &>>$LOGFILE
        gd=$(git describe --always --tags HEAD)
        echo "$gd"
    else
        echo "unknown"
    fi
    exit 0
    ;;
*)
    echo "Unknown command '$txt'. ERROR!"
    exit 1
    ;;
esac

echo "ok"
