#!/bin/bash
#
# Test RPM/DEB packages. Two test types are supported:
# 1. Latest nightly package
# 2. Latest stable/testing package
# 3. Upgrade from stable to nightly/testing packages
#
# The script determines the OS automatically.
#
# Usage: ./pkg_test.sh (nightly|stable|testing|upgrade)
#
# Return: 0 on success, non-zero otherwise
#

PROG=$(basename $0)

readonly SUPPORTED_OPTS="(nightly|stable|testing|upgrade)"
readonly CENTOS7="centos7"
readonly CENTOS8="centos8"
readonly CENTOS7GDAL2="centos7_gdal2"
readonly JESSIE="jessie"
readonly BUSTER="buster"
readonly STRETCH="stretch"
readonly TRUSTY="trusty"
readonly XENIAL="xenial"
readonly BIONIC="bionic"
readonly FOCAL="focal"
readonly JAMMY="jammy"

RMANHOME="/opt/rasdaman"
readonly UPDATEDB="$RMANHOME/bin/update_db.sh"
readonly pkgs_url="https://download.rasdaman.org/packages"
readonly tomcat_url="http://localhost:8080"

readonly demo_coverages="AverageTemperature AverageChlorophyll mean_summer_airtemp"

# global variables
test_type=
os=
tomcat="tomcat" # on centos 7 only

error() { echo "$PROG: $@" 2>&1; exit 1; }
log()   { echo "$PROG: $@"; }
usage() {
  echo "$@" 2>&1
  echo
  echo "Usage: ./pkg_test.sh $SUPPORTED_OPTS"
  echo
  echo "Test RPM/DEB packages. Two test types are supported:"
  echo "1. Latest nightly package"
  echo "2. Latest stable/testing package"
  echo "3. Upgrade from stable to nightly/testing packages"
  echo
  echo "Supported OS: CentOS 7, Debian 8, Ubuntu 14.04, Ubuntu 16.04, Ubuntu 18.04"
  exit 1
}

check_args() {
  test_type="$1"
  [ -n "$test_type" ] || usage "No test type specified."
  echo "$SUPPORTED_OPTS" | grep "$test_type" -q || usage "Invalid test type $test_type."
}

check_root() {
  [ "$EUID" -eq 0 ] || error "This script has to be executed with root user."
}
check_deps() {
  wget --help > /dev/null 2>&1 || error "Please install wget."
}

get_os() {
  log "Checking OS..."
  if [ -f "/etc/centos-release" ]; then
    grep -q "CentOS Linux release 7" /etc/centos-release
    if [ $? -eq 0 ]; then
      if [ -f "/usr/lib/libgdal.so.20" ]; then
        os=$CENTOS7GDAL2
      else
        os=$CENTOS7
      fi
    else
      grep -q "CentOS Linux release 8" /etc/centos-release
      if [ $? -eq 0 ]; then
        os=$CENTOS8
      else
        error "$(cat /etc/centos-release) is not supported."
      fi
    fi
    pkg_type="rpm"
  else
    tomcat="tomcat7"
    local version=$(lsb_release -a 2>&1 | grep Description \
      | sed 's/Description: *//' | tr -d '[:space:]' || error "Unsupported OS.")
    case "$version" in
      Ubuntu14.*) os=$TRUSTY;;
      Ubuntu16.*) os=$XENIAL; tomcat="tomcat8";;
      Ubuntu18.*) os=$BIONIC; tomcat="tomcat9";;
      Ubuntu20.*) os=$FOCAL; tomcat="tomcat9";;
      UbuntuJammy*) os=$JAMMY; tomcat="tomcat9";;
      Debian*8*)  os=$JESSIE;;
      Debian*9*)  os=$STRETCH; tomcat="tomcat8";;
      Debian*buster*)  os=$BUSTER; tomcat="tomcat9";;
      *) error "Unsupported OS $version";;
    esac
    pkg_type="deb"
  fi
  log "Done, detected OS '$os'."
}

clear_apt_locks() {
  # Ubuntu 16.04/18.04 runs into this error
  # E: Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)
  # E: Unable to lock directory /var/lib/apt/lists/
  # -> So remove this lock file to fix it
  sudo killall -9 apt apt-get > /dev/null 2>&1
  sudo rm -f /var/lib/apt/lists/lock
  sudo rm -f /var/cache/apt/archives/lock
  for f in /var/lib/dpkg/lock*; do
    sudo rm -f "$f"
  done
  sudo dpkg --configure -a
}
download() {
  local url="$1"
  local dest="$2"
  log "Downloading '$url' to '$dest'..."
  wget --no-check-certificate --quiet --tries 2 "$url" -O "$dest"
  if [ $? -ne 0 ]; then
    curl -sS "$url" 2>&1
    error "Failed, terminating."
  fi
  log "Done."
}

install_deb() {
  local repo_type="$1" # nightly/stable
  log "Installing $repo_type repo..."

  log "Importing GPG public key..."
  wget --no-check-certificate -q -t 2 -O - $pkgs_url/rasdaman.gpg | apt-key add - \
    || error "Failed importing GPG key."

  local repo_file="/etc/apt/sources.list.d/rasdaman.list"
  echo "deb [arch=amd64] $pkgs_url/deb $os $repo_type" > "$repo_file"
  clear_apt_locks
  apt-get -qq update
  # automate the configuration update dialog
  log "Installing rasdaman from DEB package..."
  export DEBIAN_FRONTEND=noninteractive
  apt-get -o Dpkg::Options::="--force-confdef" install -y rasdaman \
    || error "Failed installing rasdaman."
  log "Done."
}

install_yum() {
  log "Installing $repo_type repo..."
  local repo_type="$1" # nightly/stable
  local repo_file="/etc/yum.repos.d/rasdaman.repo"
  download "$pkgs_url/rpm/$repo_type/CentOS/7/x86_64/rasdaman.repo" "$repo_file"
  yum clean all
  yum install -y epel-release
  log "Installing rasdaman from RPM package..."
  # --setopt=obsoletes=0 disables removal of obsolete packages
  yum install --setopt=obsoletes=0 -y rasdaman || error "Failed installing rasdaman."
  log "Done."
}

restart_all() {
  log "Restarting service $tomcat..."
  service $tomcat restart
  sleep 30
}

clear_demo_coverage_logs() {
  # remove these logs because they are with different permission and
  # petascope_insertdemo.sh will fail
  for c in $demo_coverages; do rm -f /tmp/$c.log; done
}
install_pkg() {
  local repo_type="$1" # nightly/stable
  case "$pkg_type" in
    rpm) install_yum "$repo_type";;
    deb) install_deb "$repo_type";;
    *)   error "Unknown package type: $pkg_type.";;
  esac
  log "Sourcing /etc/profile.d/rasdaman.sh..."
  source /etc/profile.d/rasdaman.sh \
    || error "source /etc/profile.d/rasdaman.sh failed."

  log "Updating RASBASE with $UPDATEDB..."
  sudo -u rasdaman $UPDATEDB || error "$UPDATEDB failed."

  clear_demo_coverage_logs
  sleep 30
}

test_install() {
  log "------------------------------------------------------------------------"
  log "Testing installation..."
  echo

  log "Testing rasdaman query..."
  rasql -q 'SELECT C FROM RAS_COLLECTIONNAMES AS C' --out string > /dev/null \
    || error "rasdaman test query failed."

  log "Inserting rasdaman demo images..."
  local images_path=/opt/rasdaman/share/rasdaman/examples/images
  rasdaman_insertdemo.sh localhost 7001 "$images_path" rasadmin rasadmin > /dev/null \
    || error "rasdaman_insertdemo.sh failed."

  log "Testing SECORE request..."
  local secore_test_url="$tomcat_url/rasdaman/def/"
  if find /var/lib -name def.war 2>&1 | grep -q def.war; then
    secore_test_url="$tomcat_url/def/"
  fi
  download "$secore_test_url" "/dev/null"

  log "Testing petascope request..."
  local get_cap_request="service=WCS&request=GetCapabilities&version=2.0.1"
  download "$tomcat_url/rasdaman/ows?$get_cap_request" "/dev/null"

  log "Inserting petascope demo coverages..."
  clear_demo_coverage_logs
  petascope_insertdemo.sh || error "petascope_insertdemo.sh failed."
  clear_demo_coverage_logs

  echo
  log "Installation test done."
  log "------------------------------------------------------------------------"
}

dropcov() {
  wget -q "$tomcat_url/rasdaman/ows?service=WCS&version=2.0.1&request=DeleteCoverage&coverageId=$1" -O /dev/null \
    && echo ok. || echo "Failed deleting $1."
}

run_test() {
  case "$test_type" in
    nightly|stable|testing)
      install_pkg "$test_type"
      ;;
    upgrade)
      install_pkg "stable"
      test_install
      service rasdaman stop
      install_pkg "nightly"
      download "$tomcat_url/rasdaman/def/" "/dev/null" # make sure tomcat is up
      restart_tomcat
      # drop coverages inserted by petascope_insertdemo.sh
      for c in $demo_coverages; do dropcov $c; done
      ;;
    *)
      error "Unknown test type: $test_type."
      ;;
  esac
  test_install
}

check_args "$@"
check_root
check_deps
get_os
run_test

log "Done."
