#!/bin/bash
#------------------------------------------------------------------------------
set -u

# Version ID Block. Relies on +k filetype modifier.
#------------------------------------------------------------------------------
# shellcheck disable=SC2016
declare VersionID='$Id: //p4-sdp/r26.1.0.BETA/test/run_docker_tests.sh#1 $ $Change: 33444 $'
declare VersionStream=${VersionID#*//}; VersionStream=${VersionStream#*/}; VersionStream=${VersionStream%%/*};
declare VersionCL=${VersionID##*: }; VersionCL=${VersionCL%% *}
declare Version=${VersionStream}.${VersionCL}
[[ "$VersionStream" == r* ]] || Version="${Version^^}"

declare ThisScript="${0##*/}"
declare ThisUser=
declare ThisHost=${HOSTNAME%%.*}

#------------------------------------------------------------------------------
# Run the Docker tests for the SDP - updated to use podman

# Usage Examples from 'test' dir under workspace branch root:
#    sdp/test/run_docker_tests.sh
#    sdp/test/run_docker_tests.sh ubuntu20
#    sdp/test/run_docker_tests.sh rocky9
#    sdp/test/run_docker_tests.sh centos7 ubuntu22
#    sdp/test/run_docker_tests.sh all
#    sdp/test/run_docker_tests.sh ALL
#
# Goes together with run_docker_tests.sh
#
# Note that this file is expecting to be mapped into the root of the workspace
# and with the sdp directory in the same root.
#
# So workspace view should look something like:
#    View:
#        //guest/perforce_software/sdp/main/... //myws.sdp/sdp/...

declare oses=

function msg () { echo -e "$*"; }
function bail () { msg "\\nError: ${1:-Unknown Error}\\n"; exit "${2:-1}"; }

# This file should be in <workspace-root>/sdp/test/
# We calculate dir relative to directory of script
script_dir="${0%/*}"
root_dir="$(cd "$script_dir/../.."; pwd -P)"

if [[ "${1:-Unset}" == "Unset" ]]; then
   # Set Default.
   oses="rocky9"
else
   for os in $(echo "$@" | tr ',' ' '); do
      case "$os" in
         (all) oses="rocky8 rocky9 ubuntu20 ubuntu22";;
         (ALL) oses="rocky8 rocky9 ubuntu20 ubuntu22";;
         (ubuntu20) oses+="ubuntu20";;
         (ubuntu22) oses+="ubuntu22";;
         (rocky8) oses+="rocky8";;
         (rocky9) oses+="rocky9";;
         
         (*)
            msg "Warning: Unknown OS [$os]."
            oses+="$os"
         ;;
      esac
   done
fi

if command -v getenforce > /dev/null; then
   selinux=$(getenforce)
   msg "Detected SELinux mode: $selinux"
   # If enforcing mode then you have to allow container to write to the output dir below - for now just bail.
   if [[ "$selinux" == "Enforcing" ]]; then
      msg "Warning: SELinux is enabled in Enforcing mode on this machine $(hostname), IP $(hostname -I). Disabling it."
      msg "Changing /etc/selinux/config:"
      cp -p /etc/selinux/config /etc/selinux/config.bak
      sed -i -e s@SELINUX=enforcing@SELINUX=disabled@g /etc/selinux/config
      diff /etc/selinux/config.bak /etc/selinux/config
      msg "Running: setenforce 0"
      setenforce 0
      msg "Running: getenforce"
      getenforce
   else
      msg "Verified: SELinux is not in enforcing mode on this machine $(hostname), IP $(hostname -I)."
   fi
fi

# Directory where test output is put by the container
# Easier to make it under sdp which is a mounted volume
test_output_dir="$script_dir/output"
[[ -d "$test_output_dir" ]] || mkdir "$test_output_dir"
all_test_output="$test_output_dir/alltests.out"
if [[ -f "$all_test_output" ]]; then
   rm -f "$all_test_output"
fi

msg "Running SDP tests"
tests_failed=0
for os in $oses
do
   test_output="$test_output_dir/test-${os}.out"
   if [[ -f $test_output ]]; then
       rm "$test_output"
   fi
   docker_dir="$root_dir/sdp/test/docker"

   # Either a single $dockerfile will exist, or both $dockerfile_base and dockerfile_sdp
   # will exist.
   dockerfile_base="${docker_dir}/Dockerfile.${os}.base"
   dockerfile_sdp="${docker_dir}/Dockerfile.${os}.sdp"
   dockerfile="${docker_dir}/Dockerfile.${os}"

   # If there is a Dockerfile.${os} file, do a single podman build with that file.
   # If instead there are Dockerfile.${os}.base and Dockerfile.${os}.sdp files,
   # build the base Docker for the OS first, and then the SDP variant on top.
   if [[ -r "$dockerfile" ]]; then
      podman build --rm=true -t="perforce/${os}-sdp-${VersionStream}" -f "${dockerfile}" "${docker_dir}" ||
         bail "podman build failed for $dockerfile."
   elif [[ -r "$dockerfile_base" && -r "$dockerfile_sdp" ]]; then
      podman build --rm=true -t="perforce/${os}-base" -f "${dockerfile_base}" "${docker_dir}" ||
         bail "podman build failed for $dockerfile_base."
      podman build --rm=true -t="perforce/${os}-sdp-${VersionStream}" -f "${dockerfile_sdp}" "${docker_dir}" ||
         bail "podman build failed for $dockerfile_sdp."
   else
      bail "Can't find needed Docker files. Must have either $dockerfile OR ($dockerfile_base AND dockerfile_sdp)."
   fi

   # Run the Docker image, mounting the /sdp directory within it. The SDP image
   # has a default RUN command which is configured within it.
   # We don't directly stop on error but process a little later below so that nice
   # messages are written to Jenkins console output.
   # Note to use setcap with p4d >= 2023.1 we need --cap-add=SYS_RESOURCE for podman!
   set +e -x
   podman run --log-level debug --replace --detach --rm --cap-add=SYS_RESOURCE --cap-add=CAP_AUDIT_WRITE -v "${root_dir}/sdp:/sdp" -e "TESTOS=${os}" --name "${os}-sdp-${VersionStream}" "localhost/perforce/${os}-sdp-${VersionStream}"
   podman exec "${os}-sdp-${VersionStream}" /p4/docker_entry.sh
   tests_failed=$?
   set +x
   set -e
   echo "$os" >> "$all_test_output"
   # Avoid Jenkins immediately failing job without letting us cat the output
   set +e
   cat "$test_output" >> "$all_test_output"
   set -e
   if [[ "$tests_failed" -ne 0 ]]; then
      break
   fi
   set -x
   podman kill "${os}-sdp-${VersionStream}"
   # podman rm "${os}-sdp"
   set +x
done
cat "$all_test_output"

exit "$tests_failed"
