#!/bin/sh
set -e

testdir=$(dirname "$(readlink -f "$0")")
. "$testdir/.env"

usage()
{
    cat <<EOF
usage: test/env [<OPTS>]    -f <IMAGE> -q <QENETH-DIR> <COMMAND> [<ARGS>...]
       test/env [<OPTS>] -C -t <TOPOLOGY>   <COMMAND> [<ARGS>...]

  Run <COMMAND> in a pre-packaged container with all the packages
  required for running the test suite installed.

  Options:

    -C
      Don't containerize the command, run it directly in the current
      namespaces

    -f <IMAGE>
      Infix image to test. When starting a qeneth network, this image is
      used on all nodes.

    -h
      Show this help message

    -K
      Even if /dev/kvm is usable, do not map it the container. This is
      useful to see how tests will run in a CI setting, where KVM is
      typically not available

    -p <BUNDLE>
      Infix RAUC bundle to use for upgrade tests.

    -q <QENETH-DIR>
      Directory containing a topology.dot.in, suitable for consumption
      by qeneth. A copy of this network is created, and launched. The
      resulting topology is used as the default physical topology when
      running tests

    -t <TOPOLOGY>
      Rather than starting a qeneth network, attach to this existing
      topology. Mostly useful together with -C

EOF
}

start_topology()
{
    qenethdir="$1"
    imgfile="$2"

    [ "$qenethdir" ] || { true && return; }

    rm -rf "$envdir/qeneth"
    cp -a "$qenethdir" "$envdir/qeneth"
    if [ "$imgfile" ]; then
	imgname="$(basename "$imgfile")"
	imgfile=$(readlink -f "$imgfile")

	ln -sf "$imgfile" "$envdir/qeneth/$imgname"
    fi

    (cd "$envdir/qeneth/" && $qeneth generate && $qeneth start)
    INFAMY_ARGS="$INFAMY_ARGS $envdir/qeneth/topology.dot"

    cat <<EOF >"$envdir/bin/qeneth"
#!/bin/sh
set -x
cd $envdir/qeneth && exec $testdir/qeneth/qeneth "\$@"
EOF
    chmod +x "$envdir/bin/qeneth"
}

name()
{
    nm=infamy
    id=0

    names=$($(runner) ps -f name='infamy.*' --format '{{.Names}}')
    while true; do
	name="$nm$id"
	unset hit
	for n in $names; do
	    if [ "$name" = "$n" ]; then
		hit=true
		break;
	    fi
	done

	if [ -n "$hit" ]; then
	    id=$((id + 1))
	    continue
	fi
	break;
    done

    echo "$name"
}

# Global options
containerize=yes
[ -c /dev/kvm ] && kvm="--device=/dev/kvm"

while getopts "Cf:hiKp:q:t:" opt; do
    case ${opt} in
	C)
	    containerize=
	    ;;
	f)
	    imgfile="$OPTARG"
	    ;;
	h)
	    usage && exit 0
	    ;;
	i)
	    interactive="--interactive"
	    ;;
	K)
	    kvm=
	    ;;
	p)
	    INFAMY_ARGS="$INFAMY_ARGS -p $OPTARG"
	    ;;
	q)
	    qenethdir="$OPTARG"
	    ;;
	t)
	    topology="$OPTARG"
	    ;;
	*)
	    >&2 echo "Unknown option -$opt"
	    usage
	    exit 1
	    ;;
    esac
done

if [ "$containerize" ]; then
    # shellcheck disable=SC2016
        exec $(runner) run \
	 --cap-add=NET_ADMIN \
	 --device=/dev/net/tun \
	 --env VIRTUAL_ENV_DISABLE_PROMPT=yes \
	 --env PROMPT_DIRTRIM="$ixdir" \
	 --env PS1='\e[1m$(date "+%H:%M:%S") \h\e[0m:\W # ' \
	 --expose 9001-9010 --publish-all \
	 --hostname "$(name)" \
	 --name "$(name)" \
	 $interactive \
	 --rm \
	 --security-opt seccomp=unconfined \
	 --sysctl net.ipv6.conf.all.disable_ipv6=0 \
	 --tty \
	 --volume "$ixdir":"$ixdir" \
	 --workdir "$ixdir/test" \
	 $kvm \
	 $INFIX_TEST \
	 "$0" -C "$@"
else
    if [ ! -f ~/.9pm.rc ]; then
       cat <<-EOF >~/.9pm.rc
		# Generated by Infix env
		SSH_OPTS: "-o StrictHostKeyChecking=no"
		LOG_PATH: "$logdir"
		EOF
    fi
fi

shift $((OPTIND - 1))

if [ $# -lt 1 ]; then
    usage && exit 1
fi

# shellcheck disable=SC1091
. "$envdir/bin/activate"
export PYTHONPATH="$testdir"
INFAMY_ARGS="$INFAMY_ARGS -y $envdir/yangdir"
start_topology "$qenethdir" "$imgfile"
[ "$topology" ] && INFAMY_ARGS="$INFAMY_ARGS $topology"
export INFAMY_ARGS

exec "$@"
