#! /bin/bash

# Helper script which runs YaST in a container.
#
# Usage:
#   yast_container <options> <yast_module> <module_arguments>
#     - uses ncurses UI (text mode)
#   yast2_container <options> <yast_module> <module_arguments>
#     - uses Qt UI (graphical mode)
#   yast2_web_container <options> <yast_module> <module_arguments>
#     - uses Qt UI (graphical mode) with HTTPS access
#     - you need to configure the access password first, see the README.md
#     - open https://localhost:4984/ in browser after starting the script
#     - by default it uses a self-signed certificate
#
# The script needs to be started as "root" unless you use Docker with non-root
# access enabled.
#
# All command line arguments are passed to YaST.
#

set -e

# adds special podman command line parameters to read the secrets with
# passwords and certificates
podman_secret_params () {
    arr=( "yast_vnc_password" "yast_vnc_password_bin" "vnc_ssl_cert")
    for name in "${arr[@]}"; do
        # check if the secret exists
        if podman secret inspect "$name" >/dev/null 2>&1; then
            EXTRA_OPTIONS+=("--secret" "$name")
        fi
    done
}

# check whether the host system is compatible with the container image,
# can be disabled with VERSION_CHECK=0, use on your risk!!
. /etc/os-release
if [ "$VERSION_CHECK" != "0" ] && [ "$ID" != "opensuse-tumbleweed" ] && [ "$ID" != "alp" ] && { [ "$VERSION_ID" != "15.4" ] || { [ "$ID" != "sles" ] && [ "$ID" != "opensuse-leap" ]; }; }; then
    echo "ERROR: Unsupported system: $PRETTY_NAME" >&2
    echo "Currently supported systems:"
    echo "- openSUSE Tumbleweed"
    echo "- ALP"
    echo "- openSUSE Leap 15.4"
    echo "- SLES-15-SP4"
    echo ""
    echo "On your risk you can disable this check by setting VERSION_CHECK=0"
    exit 1
fi

if [ -z "$YCONTAINERS_SKIP_WARNING" ]; then
  echo "** WARNING: This is an experimental tool, do not use it in production systems!!"
  echo "** There is a risk of breaking the system or data loss!"
  echo
  echo "** WARNING: Using development containers which are not stable."
  echo
  echo "Set env variable YCONTAINERS_SKIP_WARNING to skip this warning."
  echo
  echo "Press enter to continue or ctrl+c to abort."
  read -r || exit 1
fi

# use podman, if not available try docker
if command -v podman &> /dev/null; then
    TOOL="podman"
elif command -v docker &> /dev/null; then
    TOOL="docker"
else
    echo "ERROR: Container runtime not installed, install 'podman' or 'docker' package" >&2
    exit 1
fi

# specific docker/podman options
EXTRA_OPTIONS=()
# the default command to run
: "${CMD=/sbin/yast2}"
# the extra command arguments
EXTRA_ARGS=()

# when called as "yast2_web_container" use the web image
if [ "$(basename "$0")" == "yast2_web_container" ]; then
    IMAGE_NAME="registry.opensuse.org/yast/head/containers/containers/yast-mgmt-web"

    # add podman secret parameters, unfortunately the docker secrets are only
    # supported in the swarm (cluster) mode :-/
    if [ "$TOOL" = "podman" ]; then
        podman_secret_params
    fi

    # run YaST in fullscreen without extra borders, just like in standard installation
    if [ "$CMD" = "/sbin/yast2" ]; then
        EXTRA_ARGS=( "--fullscreen" "--noborder" )
    fi
# when called as "yast_container" or when $DISPLAY is not set use the smaller ncurses image
elif [ "$(basename "$0")" == "yast_container" ] || [ -z "$DISPLAY" ]; then
    IMAGE_NAME="registry.opensuse.org/yast/head/containers/containers/yast-mgmt-ncurses"
else
    # otherwise use the bigger Qt image and start the container with extra
    # options to allow accessing the local X server from inside the container
    EXTRA_OPTIONS=(-e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:ro -v "$XAUTHORITY:$XAUTHORITY:ro" -e XAUTHORITY)
    IMAGE_NAME="registry.opensuse.org/yast/head/containers/containers/yast-mgmt-qt:latest"
fi

# display progress popup for downloading the image when running in X and not in terminal
# use 3s timout, if the image is already downloaded the popup would be just flashing
if [ -n "$DISPLAY" ] && [ ! -t 0 ]; then
    # KDE specific tool
    if command -v kdialog &> /dev/null; then
        (
            sleep 3
            kdialog --title "Please wait" --passivepopup "Downloading container image..." 10000 &
            wait 2> /dev/null || :
        ) &
        POPUP_PID=$!
    # GNOME zenity in SLE15 unfortunately does not support the "--notification" option :-(
    # fallback to the generic tool
    elif command -v xmessage &> /dev/null; then
        (
            sleep 3
            xmessage -center -buttons "" "Downloading container image..." &
            wait 2> /dev/null || :
        ) &
        POPUP_PID=$!
    fi
fi

# make sure the container image is up to date
$TOOL pull $IMAGE_NAME

if [ -n "$POPUP_PID" ]; then
  pkill -P "$POPUP_PID"
  kill "$POPUP_PID"
  # avoid printing "Terminated" message at exit
  wait "$POPUP_PID" 2> /dev/null || :
fi

# where is the host system root mounted in the container
CHROOT_DIR="/mnt"

# print the podman/docker command started for easier testing or debugging
set -x

# start the container
$TOOL run -it --privileged --pid=host --ipc=host --net=host \
    -v /dev:/dev "${EXTRA_OPTIONS[@]}" \
    --mount type=bind,source=/,target=$CHROOT_DIR,bind-propagation=rshared \
    -e ZYPP_LOCKFILE_ROOT=$CHROOT_DIR -e YAST_SCR_TARGET=$CHROOT_DIR \
    -e LIBSTORAGE_LOCKFILE_ROOT=$CHROOT_DIR -e LIBSTORAGE_ROOTPREFIX=$CHROOT_DIR \
    --rm $IMAGE_NAME "$CMD" "$@" "${EXTRA_ARGS[@]}"
