#!/bin/sh

set -e

INFIX_TEST=ghcr.io/kernelkit/infix-test:0.7

extract_yang()
{
    local imgfile="$1"

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

    unsquashfs -q -n -f \
               -d $envdir/yangdir \
	       "$imgfile" \
	       /usr/share/yang

    INFAMY_ARGS="$INFAMY_ARGS -y $envdir/yangdir"
}

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

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

    rm -rf $envdir/qeneth
    cp -a "$qenethdir" $envdir/qeneth
    if [ "$imgfile" ]; then
	local 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 $ixdir/qeneth/qeneth "\$@"
EOF
    chmod +x "$envdir/bin/qeneth"
}

usage()
{
    cat <<EOF
usage: test/env [<OPTS>]    -f <IMAGE> -q <QENETH-DIR> <COMMAND> [<ARGS>...]
       test/env [<OPTS>] -C -f <IMAGE> -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. YANG models from this image are extracted
      for use by Infamy. 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
}

testdir=$(dirname $(readlink -f "$0"))
ixdir=$(readlink -f "$testdir/..")
logdir=$(readlink -f "$testdir/.log")
envdir="$HOME/.infix-test-venv"
qeneth="$ixdir/qeneth/qeneth"

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

while getopts "Cf:hKp:q:t:" opt; do
    case ${opt} in
	C)
	    containerize=
	    ;;
	f)
	    imgfile="$OPTARG"
	    ;;
	h)
	    usage && exit 0
	    ;;
	K)
	    kvm=
	    ;;
	p)
	    INFAMY_ARGS="$INFAMY_ARGS -p $OPTARG"
	    ;;
	q)
	    qenethdir="$OPTARG"
	    ;;
	t)
	    topology="$OPTARG"
	    ;;
    esac
done

if [ "$containerize" ]; then
    if which podman >/dev/null; then
	runner=podman
    elif which docker >/dev/null; then
	runner=docker
    else
	echo "Error: Neither podman nor docker is installed"
	exit 1
    fi

    exec $runner run \
	 --cap-add=NET_ADMIN \
	 --device=/dev/net/tun \
	 --interactive \
	 --rm \
	 --security-opt seccomp=unconfined \
	 --sysctl net.ipv6.conf.all.disable_ipv6=0 \
	 --tty \
	 --volume "$ixdir":"$ixdir" \
	 --workdir $(pwd) \
	 $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

. "$envdir/bin/activate"
export PYTHONPATH="$testdir"

extract_yang "$imgfile"
start_topology "$qenethdir" "$imgfile"
[ "$topology" ] && INFAMY_ARGS="$INFAMY_ARGS $topology"
export INFAMY_ARGS

exec "$@"
