#!/bin/sh
#
### BEGIN INIT INFO
# Provides:          buildbot-direct
# Required-Start:    $remote_fs $syslog docker
# Required-Stop:     $remote_fs $syslog docker
# Default-Start:     
# Default-Stop:      
# Short-Description: wrapper around docker
# Description:       Wrapper around docker to manage buildbot master.
### END INIT INFO
#
set -e
set -u

DOCKER="/usr/bin/docker"
SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)

EXT_BASEDIR="/opt/buildbot/masters"
INT_BASEDIR="/opt/buildbot/masters"

# образ собран из рабочей копии и привезён через docker save/docker load для скорости отладки и чтобы не загружать в общий registry ключ от робота
# TODO убрать ключ из сборки (вместо этого тепеь монтируется /etc/direct-tokens), загрузить в registry, поменять здесь имя образа
IMAGE="buildbot-master:0.8.12-04"
MASTER_NAME="direct"
USER="nobody"

CONTAINER_NAME="buildbot-master-$MASTER_NAME"
EXT_DIR="$EXT_BASEDIR/$MASTER_NAME"
INT_DIR="$INT_BASEDIR/$MASTER_NAME"
PID_FILE="$EXT_DIR/twistd.pid"

LOG_LINES=20

# noop if docker not present
test -x $DOCKER || exit 0

. /lib/lsb/init-functions

CID=''

function update_cid {
    CID=$($DOCKER ps --all=true --quiet=true --filter=name=$CONTAINER_NAME)
}

function check_running {
    SHORT_STATUS=$($DOCKER inspect --format='{{ .State.Running }} {{ .State.Restarting }}' $CID)
    if [ "$SHORT_STATUS" == 'true false' ]; then
        log_end_msg 0
    else
        log_failure_msg "docker container is not running normally. see twisted.log or check status for details"
    fi
}

function create_and_start {
    log_daemon_msg "remove pid file if exists"
    rm -f $PID_FILE
    log_daemon_msg "run docker container $CONTAINER_NAME"
    $DOCKER run \
        --net=host \
        --detach=true \
        --name=$CONTAINER_NAME \
        --restart=always \
        --read-only \
        --volume=$EXT_DIR:$INT_DIR:rw \
        --volume=/etc/direct-tokens:/etc/direct-tokens:ro \
        --user=$USER \
        --workdir=$INT_DIR \
        $IMAGE \
        buildbot start --nodaemon . > /dev/null
    update_cid
    sleep 1
    check_running
}

function upgrade_master {
    log_daemon_msg "run docker container $CONTAINER_NAME-upgrade"
    $DOCKER run \
        --net=host \
        --detach=false \
        --name="$CONTAINER_NAME-upgrade" \
        --restart=no \
        --read-only \
        --rm=true \
        --volume=$EXT_DIR:$INT_DIR:rw \
        --volume=/etc/direct-tokens:/etc/direct-tokens:ro \
        --user=$USER \
        --workdir=$INT_DIR \
        $IMAGE \
        buildbot upgrade-master .
}

function checkconfig {
    log_daemon_msg "run docker container $CONTAINER_NAME-checkconfig"
    $DOCKER run \
        --net=host \
        --detach=false \
        --name="$CONTAINER_NAME-checkconfig" \
        --restart=no \
        --read-only \
        --rm=true \
        --volume=$EXT_DIR:$INT_DIR:rw \
        --volume=/etc/direct-tokens:/etc/direct-tokens:ro \
        --user=$USER \
        --workdir=$INT_DIR \
        $IMAGE \
        buildbot checkconfig .
}

function stop {
    if [ -n "$CID" ]; then
        log_daemon_msg "stop docker container $CONTAINER_NAME"
        $DOCKER stop $CID > /dev/null
        SHORT_STATUS=$($DOCKER inspect --format='{{ .State.Running }}' $CID)
        if [ "$SHORT_STATUS" == "false" ]; then
            log_end_msg 0
        else
            log_failure_msg "failed to stop docker container"
        fi
    else
        log_daemon_msg "docker container $CONTAINER_NAME doesn't exists"
    fi
}

function start {
    if [ -n "$CID" ]; then
        log_daemon_msg "start docker container $CONTAINER_NAME"
        $DOCKER start $CID > /dev/null
        sleep 1
        check_running
    else
        create_and_start
    fi
}

function restart {
    if [ -n "$CID" ]; then
        log_daemon_msg "restart docker container $CONTAINER_NAME"
        $DOCKER restart $CID > /dev/null
        sleep 1
        check_running
    else
        create_and_start
    fi
}

function print_detailed_status {
    log_daemon_msg "detailed status:"
    $DOCKER inspect --format='{{ range $key, $value := .State }}{{"\t"}}{{ $key }}={{ $value }}{{"\n"}}{{ end }}' $CID
}

function status {
    if [ -n "$CID" ]; then
        SHORT_STATUS=$($DOCKER inspect --format='{{ .State.Running }} {{ .State.Restarting }}' $CID)
        if [ "$SHORT_STATUS" == 'true false' ]; then
            log_daemon_msg "docker container $CONTAINER_NAME is running normally"
            print_detailed_status
        elif [ "$SHORT_STATUS" == 'true true' ]; then
            log_daemon_msg "docker container $CONTAINER_NAME is restarting"
            print_detailed_status
        elif [ "$SHORT_STATUS" == 'false false' ]; then
            log_daemon_msg "docker container $CONTAINER_NAME is not running"
        else
            log_failure_msg "docker container $CONTAINER_NAME is in the strange state"
            print_detailed_status
        fi
    else
        log_daemon_msg "docker container $CONTAINER_NAME doesn't exists"
    fi
}

function drop {
    if [ -n "$CID" ]; then
        stop
        log_daemon_msg "remove docker container $CONTAINER_NAME"
        $DOCKER rm $CID > /dev/null
        update_cid
        if [ -z $CID ]; then
            log_end_msg 0
        else
            log_failure_msg "failed to remove docker container"
        fi
    else
        log_daemon_msg "docker container $CONTAINER_NAME doesn't exists"
    fi
}

function logs {
    if [ -n "$CID" ]; then
        log_daemon_msg "showing last $LOG_LINES lines of docker container $CONTAINER_NAME logs:"
        $DOCKER logs --tail="$LOG_LINES" $CID
    else
        log_daemon_msg "docker container $CONTAINER_NAME doesn't exists"
    fi
}


update_cid

case "${1:-''}" in
  'start')
    start
    ;;

  'stop')
    stop
    ;;

  'restart')
    restart
    ;;

  'status')
    status
    ;;

  'upgrade-master')
    upgrade_master
    ;;

  'checkconfig')
    checkconfig
    ;;

  'drop')
    drop
    ;;

  'logs')
    set +u
    if [ -n "$2" ]; then
        LOG_LINES=$2
    fi
    set -u
    logs
    ;;

  *)
    echo "Usage: $SELF start|stop|restart|status|upgrade-master|checkconfig|drop|logs"
    exit 1
    ;;
esac
