#!/usr/bin/env bash
# Install OpenVox Agent bootstrap script

# ---------------------------------------------------------------------------
#                                                                 usage
# ---------------------------------------------------------------------------

script=$(basename $0)

USAGE="\
Usage:  $script -h
        $script [--reconf] [server [CA]]
Where:  -h|--help Invokes help text
        --reconf  Specifies reconfiguration even if an existing OpenVox install
                  is detected
	--9	  Install OpenVox 9 instead of 8
        server    Refers to the OpenVox server this host will use
                  (default: puppet.[this host's domain])
        CA        Refers to the OpenVox certificate authority this host will use
                  (default: puppet.computecanada.ca)
"

usage()
{
  echo "$USAGE"
  exit 0
}

# ---------------------------------------------------------------------------
#                                                                 functions
# ---------------------------------------------------------------------------

# Display current status
--()
{
  echo "$@"
}

# Fatal error; bail
fatal()
{
  echo "$1" >> /dev/stderr
  exit 1
}

# This is for catching unexpected errors.  Bash's implementation of this is
# problematic, but it's a last-ditch catchall for errors.
trap_err()
{
  rc=$1
  lineno=$2
  func=$3
  cat <<EOF >>/dev/stderr
Unexpected failure of subshell command.  Preceeding lines may offer some clue.
Please consider updating the script with adequate testing.

Exit status: $rc
Line:        $lineno
Function:    $func
EOF
}

# Ubuntu is a little more complicated than RH variants because apt and dpkg
# do not accept URLs as packages
ubuntu_install()
{
  url=$1

  tmpf=$(mktemp) || fatal "Could not create temporary file for package download"
  curl $url -o $tmpf || fatal "Could not download Puppet repo package from '$url' to '$tmpf'"
  dpkg -i $tmpf || fatal "Could not install Puppet repo package"
  rm $tmpf
  apt update
}

# ---------------------------------------------------------------------------
#                                                                 init
# ---------------------------------------------------------------------------

# exit immediately if a pipeline, subshell command or command enclosed in 
# braces fails
set -e

# and should that happen, print out a message with any available information
trap 'trap_err $? $LINENO ${FUNCNAME}' ERR

# interpret parameters
if [ "$1" == "-h" -o "$1" == "--help" ]
then
  usage
elif [ "$1" == "--9" ]
then
 vox9=1
 shift
elif [ "$1" == "--reconf" ]
then
  reconf=1
  shift
fi

# If they don't pass a puppet server, assume it's puppet.DOMAIN
OPENVOX_DOMAIN=$(hostname -d) || fatal "Could not determine host's domain."
if [ -n "$1" ]
then
  OPENVOX_SERVER=$1
else
  OPENVOX_SERVER="openvox.${PUPPET_DOMAIN}"
fi

# OpenVox CA server defaults to openvox.driirn.ca
if [ -n "$2" ]
then
  OPENVOX_CA_SERVER=$2
else
  OPENVOX_CA_SERVER="openvox.driirn.ca"
fi

if [ -n "$3" ]
then
 OPENVOX_ENV=$3
else
 OPENVOX_ENV='production'
fi

# ---------------------------------------------------------------------------
#                                                          preflight checks
# ---------------------------------------------------------------------------

# get OS information if available
OSINFO=/etc/os-release
if [ -f $OSINFO ]
then
  . $OSINFO
else
  fatal "Could not find $OSINFO; what are you running?"
fi

cat <<EOF
We're going to configure the agent like so:

OpenVox Server:      $OPENVOX_SERVER
OpenVox CA Server:   $OPENVOX_CA_SERVER
OpenVox Environment: $OPENVOX_ENV

EOF

# RedHat uses VERSION_ID=8.3, CentOS uses VERSION_ID=8
if [ -n "$VERSION_ID" ]
then
  VERSION_ID_MAJOR=${VERSION_ID%.*}
fi

if (( $vox9 ))
then
 echo "OpenVox 9 selected"
 YUM_REPO_URL="https://yum.voxpupuli.org/openvox9-release-el-{VERSION_ID_MAJOR}.noarch.rpm"
 APT_REPO_URL="https://yum.voxpupuli.org/openvox9-release-${VERSION_CODENAME}.deb"
else
 echo "OpenVox 8 selected"
 YUM_REPO_URL="https://yum.voxpupuli.org/openvox8-release-el-${VERSION_ID_MAJOR}.noarch.rpm"
 APT_REPO_URL="https://yum.voxpupuli.org/openvox8-release-${VERSION_CODENAME}.deb"
fi

# determine what repo we should be using and commands to run
case "$ID" in
  rocky|almalinux|centos|rhel)
    REPO_URL=$YUM_REPO_URL
    CHECK_OPENVOX="rpm --quiet -q openvox-agent"
    INSTALL_REPO="dnf -y install ${REPO_URL}"
    INSTALL_OPENVOX="dnf -y install openvox-agent"
    ;;
  ubuntu)
    REPO_URL=$APT_REPO_URL
    CHECK_OPENVOX="dpkg-query -Wf'\${db:Status-abbrev}' openvox 2>/dev/null | grep -q '^i'"
    INSTALL_REPO="ubuntu_install ${REPO_URL}"
    INSTALL_OPENVOX="apt install -y openvox-agent"
    ;;
  *)
    fatal "Unrecognized Linux distribution: no configured OpenVox repository"
    ;;
esac

# Check and see if puppet is installed
if eval $CHECK_OPENVOX
then
  if (( $reconf ))
  then
    echo "WARNING: OpenVox appears to be installed; reconfiguring"
  else
    fatal "WARNING: OpenVox appears to be installed and may already be configured"
  fi
fi

# Make sure that they are root
if [ "$EUID" -ne "0" ]
then
  fatal "You must be root to install OpenVox."
fi


# ---------------------------------------------------------------------------
#                                                                 main
# ---------------------------------------------------------------------------

if ! (( $reconf ))
then

  -- Installing release package for Openvox repository
  if ! $INSTALL_REPO
  then
    fatal "Unable to install release package from $REPO_URL"
  fi

  -- Installing Openvox Agent
  if ! $INSTALL_OPENVOX
  then
    fatal "Unable to install OpenVox"
  fi
fi

-- Updating path to include Puppet
export PATH=/opt/puppetlabs/bin:$PATH

-- Configuring Agent for initial Run
if ! puppet config set server ${OPENVOX_SERVER} --section agent 
then
  fatal "Could not configure agent (setting server)"
fi

# Only set the proxy if we aren't connecting directly to the MOM
if [ $OPENVOX_SERVER != $OPENVOX_CA_SERVER ]
then
  # Adding HTTP Proxy via ${OPENVOX_SERVER}
  puppet config set http_proxy_host ${OPENVOX_SERVER} --section agent \
    || fatal "Could not configure agent (http_proxy_host)"
  puppet config set http_proxy_port 3128 --section agent \
    || fatal "Could not configure agent (http_proxy_port)"
fi
puppet config set ca_server ${OPENVOX_CA_SERVER} --section agent \
  || fatal "Could not configure agent (CA server)"
puppet config set environment ${OPENVOX_ENV} --section agent \
  || fatal "Could not configure agent (Environment)"

-- Openvox agent configured
cat <<EOF

This host is now configured for its initial run against ${OPENVOX_SERVER} Next, to generate 
a certificate for subsequent runs,
please run:

  sudo puppet agent --test --noop

Sign the certificate, and then you will be able to run:

  sudo puppet agent --test

To start the first "real" Openvox run.

Please see https://wiki.computecanada.ca/staff/Puppet/Installation for more
information.

EOF

