#!/bin/bash

set -e

ARGS=$@
PROG=$(basename $0)

IMAGE_ID=
LOOP=
LIVE=
LOCAL=
TARGET_HOST=
TARGET_PORT=80
NO_SSL_CHECK=

RUNPATH=testaccept/

usage() {
    cat << EOF
USAGE: $0 [--local|--live|<image-id>|--host <name>] [--debug] [--loop]

Run acceptance tests against either a local docker container
or the remote live server.

OPTIONS:
  <image-id>      ID of a docker image to start and test against.
  --live          Run tests against the server pointed at by 'eb status'.
  --host <dns>    Run tests against a specific IP address or hostname.
  --local         Run tests against server specified in KLUE_SERVER_(HOST|PORT)
  --loop          Run the tests in a loop, until failure
  --no-ssl-check  Don't check SSL certificate

EOF
}


parse_args() {
    while [ "$1" != "" ]; do
        case $1 in
            "--debug")        set -x;;
            "--live")         export LIVE=1;;
            "--local")        export LOCAL=1;;
            "--loop")         export LOOP=1;;
            "--host")         shift; TARGET_HOST=$1;;
            "--port")         shift; TARGET_PORT=$1;;
            "--no-ssl-check") export NO_SSL_CHECK=1;;
            "-h" | "--help")  usage; exit 0;;
            *)                IMAGE_ID=$1;;
        esac
        shift
    done
}

parse_args $ARGS

# Force re-generation of recent auth token
unset KLUE_JWT_TOKEN

# Make sure we can connect to aws
if [ -z $AWS_SECRET_ACCESS_KEY ]; then
    SECRETS_FILE=~/.env.secrets
    if [ ! -e "$SECRETS_FILE" ]; then
        echo "ERROR: no secrets file at $SECRETS_FILE"
    else
        source $SECRETS_FILE
    fi
fi

if [ ! -z "$LIVE" ]; then
    echo "=> Finding out CNAME of current Elastic Beanstalk environment"
    KLUE_SERVER_HOST=$(klue_config --live-host)
    KLUE_SERVER_PORT=$(klue_config --live-port)

    if [ ! -z "$IMAGE_ID" ]; then
        echo "=> Will execute tests $IMAGE_ID"
        RUNPATH=$IMAGE_ID
    fi

elif [ ! -z "$LOCAL" ]; then
    echo "=> Running against $KLUE_SERVER_HOST:$KLUE_SERVER_PORT"

    if [ ! -z "$IMAGE_ID" ]; then
        echo "=> Will execute tests $IMAGE_ID"
        RUNPATH=$IMAGE_ID
    fi

    # TODO: check that server is indeed running locally. If not, start it
elif [ ! -z "$TARGET_HOST" ]; then
    echo "=> Running against $TARGET_HOST:$TARGET_PORT"
    KLUE_SERVER_HOST=$TARGET_HOST
    KLUE_SERVER_PORT=$TARGET_PORT

    if [ ! -z "$IMAGE_ID" ]; then
        echo "=> Will execute tests $IMAGE_ID"
        RUNPATH=$IMAGE_ID
    fi

else

    if [ -z "$IMAGE_ID" ]; then
        usage
        exit 1
    fi

    # Start the container, passing all secrets as environment variables,
    # just like in the amazon EBS setup
    CMD="docker run"
    for VAR in $(klue_config --env-secrets)
    do
        echo "=> Passing env variable $VAR"
        VALUE=$(env | grep "^$VAR=" | cut -d '=' -f 2)
        if [ -z "$VALUE" ]; then
            echo "ERROR: variable $VAR has no value in env"
            exit 1
        fi
        CMD="$CMD -e $VAR=$VALUE"
    done
    CMD="$CMD --rm -P $IMAGE_ID"

    echo "=> Starting container for image $IMAGE_ID"
    echo "EXEC [$CMD]"
    eval $CMD &
    RC=$?
    if [ $RC != 0 ]; then
        echo "ERROR: failed to start docker container"
        exit 1
    fi

    echo "=> Waiting for container to start"
    sleep 7

    CONTAINER_ID=$(docker ps | grep $IMAGE_ID | awk '{ print $1 }')

    if [ "$OS" == 'Darwin' ]; then
        KLUE_SERVER_HOST=$(docker-machine ip default)

        # Make sure docker-machine's vm has a working dns resolver
        docker-machine ssh default "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"

        KLUE_SERVER_PORT=$(docker port $CONTAINER_ID | cut -d ':' -f 2)
    else
        KLUE_SERVER_HOST=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CONTAINER_ID})
        KLUE_SERVER_PORT=80
    fi

    if [ -z "$KLUE_SERVER_PORT" ]; then
        echo "ERROR: cannot find port exposed by container."
        echo "       did the container crash?"
        exit 1
    fi
fi

if [ -z "$KLUE_JWT_TOKEN" ]; then
    echo "=> Getting an access token for the test user"
    export KLUE_JWT_TOKEN=$(get_test_jwt_token | grep 'token:' | cut -d ':' -f 2)
    echo "=> Using token: $KLUE_JWT_TOKEN"

    if [ -z "$KLUE_JWT_TOKEN" ]; then
        echo "ERROR: failed to get an auth token for test user"
    fi
fi

echo "=> Running acceptance tests against $KLUE_SERVER_HOST:$KLUE_SERVER_PORT"
RC=0
if [ -z "$LOOP" ]; then
    nosetests -xv $RUNPATH || RC=$?
else
    while true; do
        nosetests -xv $RUNPATH || RC=$?
    done
fi

if [ ! -z "$CONTAINER_ID" ]; then
    echo "=> Stopping container $CONTAINER_ID"
    docker kill $CONTAINER_ID
fi

if [ "$RC" -ne 0 ]; then
    exit $RC
fi