#!/bin/bash
set -o errexit \
    -o nounset \
    -o pipefail

usage() {
  cat <<'EOF'
usage: validate [type] [path]

Program:
    This application performs quick checks on the provided InfluxDB
    package. InfluxDB should *not* be installed on the system before
    running this application. This validates new installations and
    performs specific checks relevant only to InfluxDB.

Options:
    type    Must be "deb" or "rpm". This option instructs the
            application to use the package manager associated
            with "type".
    path    Path to InfluxDB package to validate.
EOF
}

if [[ ! "${1:-}" ]] || [[ ! "${2:-}" ]] || [[ ! "${3:-}" ]]
then
  (usage) && exit 1
fi
PACKAGE_ARCH="${1}"
PACKAGE_TYPE="${2}"
PACKAGE_PATH="${3}"

install_deb() {
  # When installing the package, ensure that the latest repository listings
  # are available. This might be required so that all dependencies resolve.
  # Since this needs to be run by CI, we supply "noninteractive" and "-y"
  # so no prompts stall the pipeline.
  export DEBIAN_FRONTEND=noninteractive
  apt-get update
  # "apt-get install" should be used instead of "dpkg -i", because "dpkg"
  # does not resolve dependencies. "apt-get" requires that the package
  # path looks like a path (either fullpath or prefixed with "./").
  apt-get install -y binutils $1
}

install_rpm() {
  # see "install_deb" for "update"
  yum update -y
  yum install -y binutils
  yum install -y shadow-utils       # for useradd
  yum install -y libxcrypt-compat   # for libcrypt.so.1
  yum localinstall -y $1
}

bin=$(find $PACKAGE_PATH -name "*${PACKAGE_ARCH}.${PACKAGE_TYPE}")
[ ! -f $bin ] && echo "unable to find ${PACKAGE_TYPE} in ${PACKAGE_PATH}" && exit 1

case ${PACKAGE_TYPE}
in
  deb)
    (install_deb $bin)
    ;;
  rpm)
    (install_rpm $bin)
    ;;
esac

if ! which influxdb3 &>/dev/null
then
  printf 'ERROR: Failed to locate influxdb3 executable!\n' >&2
  exit 2
fi

NEEDED="$(readelf -d "$(which influxdb3)" | (grep 'NEEDED' || true ))"

# shellcheck disable=SC2181
if [[ ${?} -ne 0 ]]
then
  cat <<'EOF'
ERROR: readelf could not analyze the influxdb3 executable! This
       might be the consequence of installing a package built
       for another platform OR invalid compiler/linker flags.
EOF
  exit 2
fi

if [[ "${NEEDED:-}" ]]
then
  if echo "$NEEDED" | grep -Eq "Shared library: \[libpython" ; then
    # if have libpython, ensure we are only linking things we expect
    if echo "$NEEDED" | grep -Ev "Shared library: \[(ld-linux.*|libc|libdl|libgcc_s|libm|libpthread|libpython3.[0-9]{2}|librt)\.so" ; then
      cat <<'EOF'
ERROR: found unexpected dynamically linked libraries! This may
       prevent all platforms from running influxdb3 without
       installing these dependencies.
EOF
      exit 2
    fi

    CUR_LATEST="$(readelf -s "$(which influxdb3)" | grep @GLIBC_ | sed 's/@@/@/' | cut -d @ -f 2 | cut -d ' ' -f 1 | cut -d _ -f 2 | grep -E '^[0-9]+\.[0-9][0-9.]*[0-9]$' | sort -uV | tail -1)" || true
    if [ -z "$CUR_LATEST" ]; then
        cat <<EOF
ERROR: could not find any GLIBC symbols! The GLIBC compatibility
       cannot be determined.
EOF
        exit 2
    fi

    MAX_VERSION="2.23"  # the portability we desire
    if [[ $(printf '%s\n%s\n' "$CUR_LATEST" "$MAX_VERSION" | sort -V | tail -n 1) != "$MAX_VERSION" ]]; then
        cat <<EOF
ERROR: found GLIBC symbol version $CUR_LATEST > $MAX_VERSION. This will
       prevent platforms with GLIBC < $CUR_LATEST from working.
EOF
        exit 2
    fi
  else
    # if no libpython, then complain if any are NEEDED
    cat <<'EOF'
ERROR: influxdb3 not statically linked! This may prevent all
       platforms from running influxdb3 without installing
       separate dependencies.
EOF
    exit 2
  fi
fi

printf 'Finished validating influxdb3!\n'
