#!/bin/sh

# This program is Copyright (c) 2013-2014 VividCortex, Inc. All rights reserved.

# This is a placeholder that is populated with the version of agents
# that the script is deployed with. It is here for information purposes only - DO NOT USE
VERSION=1.6.239

# Placeholder that is populated with the base URI for the download server - DO NOT USE
baseuri=https://download.vividcortex.com

# Override the baseuri when $VC_CUSTOM_URI var is set
if [ ! -z "$VC_CUSTOM_URI" ]; then baseuri=$VC_CUSTOM_URI; fi

globalconf=/etc/vividcortex/global.conf
confdir="$(dirname "$globalconf")"
logdir=/var/log/vividcortex
tempdir=""


msg()
{
	if [ $# -gt 0 ]; then
		echo "$1" >&2
	else
		echo >&2
	fi
}

abort()
{
	if [ $# -gt 0 ]; then
		msg
		msg "$1"
		msg
	fi
	[ -n "$tempdir" ] && rm -Rf "$tempdir" >/dev/null 2>&1
	exit 1
}

createdir()
{
	mkdir -p "$1" || abort "Unable to create directory $1"
}

getfile()
{
	failed=0
	if command -v curl >/dev/null 2>&1 ; then
		curl -f -s "$1" > "$2" && return 0
		failed=1
	fi
	if command -v wget >/dev/null 2>&1 ; then
		wget -q -O - "$1" > "$2" && return 0
		failed=1
	fi
	if command -v fetch >/dev/null 2>&1 ; then
		fetch -q -o - "$1" > "$2" && return 0
		failed=1
	fi

	if [ $failed -eq 0 ]; then
		abort "No suitable tool for file download found"
	fi

	case "$initver" in
		FreeBSD)
			abort "Unable to retrieve $1
Please verify proxy/firewall and install or update CA Root Certificates - e.g. pkg install security/ca_root_nss"
			;;
		Redhat)
			abort "Unable to retrieve $1
Please verify proxy/firewall and install or update CA Root Certificates - e.g. yum update ca-certificates"
			;;
		Debian|OpenRC|systemd)
			abort "Unable to retrieve $1
Please verify proxy/firewall and install or update CA Root Certificates - e.g. update-ca-certificates"
			;;
		*)
			abort "Unable to retrieve $1
Please verify proxy/firewall and install or update CA Root Certificates."
			;;
	esac
}

usage()
{
	abort "Usage: install [-h|--help] [--autostart|--no-autostart] [-s|--start-now]
               [--no-proxy] [-p|--proxy HTTP-proxy] [-t|--token API-token] [-v|--version version-number]"
}

set -u
POSIXLY_CORRECT=1
export POSIXLY_CORRECT

if [ $(id -u) -ne 0 ]; then
	abort "This script must be run as root"
fi

if [ "$(hostname)" = "" ]; then
	abort "VividCortex requires hostname to be set"
fi

test -d /usr || abort "/usr not mounted"

# Note that I am using the external getopt(1) here rather than the bash-
# internal getopts() because /bin/sh on some operating systems (e.g. FreeBSD)
# is not bash.
(getopt -T) >/dev/null 2>&1
exitcode=$?
if [ $exitcode -eq 4 ]; then
	# GNU version, supports long options
	GETARGS=$(getopt -o "hsp:t:v:" -l "help,autostart,no-autostart,start-now,no-proxy,proxy:,token:,version:" -n "$0" -- "$@")
	test $? -eq 0 || usage
	eval set -- "$GETARGS"
else
	# BSD, cannot validate
	eval set -- "$*"
fi

AUTOSTART=""
NOPROXY=""
PROXY=""
STARTNOW=""
VCTOKEN=""
INSTALL_VERSION=current

while [ $# -ne 0 ] ; do
	case "$1" in
		--autostart)
			shift
			AUTOSTART=1
			;;
		--no-autostart)
			shift
			AUTOSTART=0
			;;
		-s|--start-now)
			shift
			STARTNOW=1
			;;
		--no-proxy)
			shift
			NOPROXY=1
			PROXY=""
			;;
		-p|--proxy)
			shift
			if [ -n "$1" ]; then
				PROXY="$1"
				NOPROXY=""
				shift
			fi
			# Undocumented, but worth honoring anyway just to be neighborly.
			if [ "$PROXY" = "no" -o "$PROXY" = "none" -o "$PROXY" = "false" -o "$PROXY" = "off" ]; then
				PROXY=""
				NOPROXY=1
			fi
			;;
		-t|--token)
			shift
			if [ -n "$1" ]; then
				VCTOKEN="$1"
				shift
			fi
			;;
		-v|--version)
			shift
			if [ -n "$1" ]; then
				INSTALL_VERSION="$1"
				shift
			fi
			;;
		-h|--help)
			shift
			echo
			echo "Usage: install [-h|--help] [--autostart|--no-autostart] [-s|--start-now]"
			echo "               [--no-proxy] [-p|--proxy HTTP-proxy] [-t|--token API-token] [-v|--version version-number]"
			echo
			echo "Where:"
			echo
			echo "--help [-h]                Display this help information"
			echo "--autostart                Configure system to start VividCortex at boot"
			echo "--no-autostart             Do not configure system to start VividCortex at boot"
			echo "--start-now [-s]           Start VividCortex services after installation"
			echo "--no-proxy                 Do not configure an HTTP proxy"
			echo "--proxy [-p] 'HTTP-proxy'  Configure HTTP proxy to 'HTTP-proxy'"
			echo "--token [-t] 'API-token'   Configure VividCortex token to 'API-token'"
			echo "--version [-t] 'Version'   Install the specified version of VividCortex (installs latest if not specified)"
			echo
			echo "For some configuration parameters, if no option is specified, 'install' will"
			echo "fall back to interactive querying to obtain the parameters."
			echo
			exit 0
			;;
		--)
			shift
			break
			;;
		*)
			shift
			usage
			;;
	esac
done

platform=$(uname -s | tr A-Z a-z)
distro=""
arch=""
initver=""
initdir=""
initname="vividcortex"
initperm=755
startcmd=""
stopcmd=""
installcmd=""
uninstallcmd="true"

longbit=$(getconf LONG_BIT 2>/dev/null)
if [ -z "$longbit" ]; then
	if /usr/bin/file /bin/cat | grep 64.bit >/dev/null 2>&1 ; then
		longbit=64
	fi
fi

case "$longbit" in
	64)
		arch="amd64"
		;;
	*)
		arch="386"
		abort "VividCortex isn't supported on 32-bit systems"
		;;
esac

# aborts or sets (distro) or (distro,initdir,initver)
case "${platform}" in
	linux)
		initdir="/etc/init.d"

		if grep -i ubuntu /etc/*-release >/dev/null 2>&1 ; then
			distro="Ubuntu"
			initver="Debian"
		elif grep -i debian /etc/*-release >/dev/null 2>&1 ; then
			distro="Debian"
			initver="Debian"
		elif grep -i amazon /etc/*-release >/dev/null 2>&1 ; then
			distro="Amazon"
			initver="Redhat"
		elif grep -i centos /etc/*-release >/dev/null 2>&1 ; then
			distro="CentOS"
			initver="Redhat"
		elif grep -i red.hat.enterprise /etc/*-release >/dev/null 2>&1 ; then
			distro="RHEL"
			initver="Redhat"
		elif grep -i fedora /etc/*-release >/dev/null 2>&1 ; then
			distro="Fedora"
			initver="Redhat"
		elif [ -e /etc/redhat-release ]; then
			distro="Redhat"
			initver="Redhat"
		elif [ -e /etc/debian_version ]; then
			distro="Debian"
			initver="Debian"
		elif [ -e /etc/gentoo-release ]; then
			distro="Gentoo"
			initver="OpenRC"
		elif [ -e /etc/SuSE-release ]; then
			distro="SuSE"
			initver="systemd"
			initdir="/etc/systemd/system"
			initname="vividcortex.service"
		else
			abort "Could not determine Linux distribution.
Please contact VividCortex for installation support."
		fi
		;;
	freebsd)
		initdir="/etc/rc.d"
		distro="FreeBSD"
		initver="FreeBSD"
		;;
	darwin)
		distro="Darwin"
		initver="launchd"
		initdir="/Library/LaunchDaemons"
		initname="com.vividcortex.supervisor.plist"
		;;
	*)
		abort "Sorry, this install script doesn't support the '${platform}' platform.
Please contact VividCortex for installation support."
		;;
esac

# verify initver dependencies and set startcmd/stopcmd/installcmd
case "${initver}" in
	Redhat)
		startcmd="${initdir}/vividcortex start"
		stopcmd="${initdir}/vividcortex stop"
		installcmd="/sbin/chkconfig --add vividcortex"
		command -v /sbin/chkconfig >/dev/null 2>&1 || initver=""
		;;
	Debian)
		startcmd="${initdir}/vividcortex start"
		stopcmd="${initdir}/vividcortex stop"
		installcmd="update-rc.d vividcortex defaults"
		command -v update-rc.d >/dev/null 2>&1 || initver=""
		;;
	OpenRC)
		startcmd="rc-service vividcortex start"
		stopcmd="rc-service vividcortex stop"
		installcmd="rc-update add vividcortex"
		command -v rc-update >/dev/null 2>&1 || initver=""
		command -v rc-service >/dev/null 2>&1 || initver=""
		;;
	systemd)
		startcmd="systemctl start vividcortex.service"
		stopcmd="systemctl stop vividcortex.service"
		installcmd="systemd_install"
		initperm=644
		command -v systemctl >/dev/null 2>&1 || initver=""
		;;
	launchd)
		startcmd="launchctl start com.vividcortex.supervisor"
		stopcmd="launchctl stop com.vividcortex.supervisor"
		installcmd="launchctl load -w ${initdir}/${initname}"
		uninstallcmd="launchctl unload -w ${initdir}/${initname}"
		command -v launchctl >/dev/null 2>&1 || initver=""
		# to-do
		if [ "${AUTOSTART}" = "0" ]; then
			abort "Not-autostarting unsupported"
		fi
		AUTOSTART="1"
		;;
	FreeBSD)
		startcmd="${initdir}/vividcortex start"
		stopcmd="${initdir}/vividcortex stop"
		installcmd="true"
		if [ "${AUTOSTART}" = "0" ]; then
			abort "Not-autostarting unsupported"
		fi
		AUTOSTART="1"
		;;
	*)
		initver=""
		;;
esac

systemd_install () {
	systemctl daemon-reload
	systemctl enable vividcortex.service
}


if [ "${initver}" = "" -o "${initdir}" = "" -o ! -d "${initdir}" ]; then
	abort "Sorry, this install script does not yet support your version or flavor of ${distro}.
Please contact VividCortex for installation support."
fi


if [ -e "$globalconf" ]; then
	abort "$globalconf exists; stopping.
Remove and re-run if you want to replace an existing install."
fi

# agents are installed in /usr/local/bin; make sure it exists
if [ ! -d /usr/local/bin ]; then
	if [ ! -d /usr/local ]; then
		mkdir /usr/local >/dev/null 2>&1
		chmod 755 /usr/local >/dev/null 2>&1
	fi
	mkdir /usr/local/bin >/dev/null 2>&1
	chmod 755 /usr/local/bin >/dev/null 2>&1
	test -d /usr/local/bin || abort "Cannot create /usr/local/bin"
fi

# customer consented a reinstall by removing globalconf; make sure service isn't running
if [ -e "${initdir}/${initname}" ]; then
	${stopcmd} >/dev/null 2>&1
	${uninstallcmd} >/dev/null 2>&1
fi

# remove service file
rm -f "${initdir}/${initname}"

if [ -z "${VCTOKEN}" ]; then
	echo
	echo -n "Please enter your VividCortex API token: "

	if ! read VCTOKEN; then
		abort "Unable to read API token."
	fi

	if [ -z "$VCTOKEN" ]; then
		abort "A token has to be provided."
	fi
fi

echo
echo "Installing the VividCortex vc-agent-007 agent for ${platform} ${distro} ${arch}."

if [ -n "${NOPROXY}" ]; then
	proxy=""
elif [ -n "${PROXY}" ]; then
	proxy="${PROXY}"
else
	proxy=""
	resp=""
	echo
	echo -n "Do you need to set up an HTTP proxy? [y/N] "
	if read resp && [ "$resp" = 'Y' -o "$resp" = 'y' ]; then
		proxy=${http_proxy:-''}
		echo -n "Please input your proxy URL [$proxy] "
		read proxy

		if [ -z "$proxy" ]; then
			proxy=${http_proxy:-''}
		fi

		if ! echo $proxy | grep "^https\?://" >/dev/null 2>&1 ; then
			proxy="http://$proxy"
		fi
	fi
fi

export http_proxy=$proxy
export https_proxy=$proxy

# Download to temp folder in case we need to abort
tempdir=$(mktemp -d /tmp/vividcortex.XXXX)

if [ $? -ne 0 ]; then
	abort "Unable to create temp folder under /tmp"
fi

if [ $INSTALL_VERSION != "current" ]; then
	echo
	echo "Installing VividCortex version: $INSTALL_VERSION"
fi

getfile "$baseuri/$platform/$arch/$INSTALL_VERSION/vc-agent-007" "$tempdir/vc-agent-007"
getfile "$baseuri/$platform/init-scripts/$initver/$INSTALL_VERSION/vividcortex" "$tempdir/vividcortex"

mv -f $tempdir/vc-agent-007 /usr/local/bin/ || abort "Unable to install vc-agent-007"
chmod 700 /usr/local/bin/vc-agent-007 || abort "Unable to set /usr/local/bin/vc-agent-007 permissions"

# Verify that env looks good to 007

{ /usr/local/bin/vc-agent-007 -self-test -proxy-uri="${https_proxy}" -config-file="" -api-token="${VCTOKEN}"; } >/dev/null 2>&1
exitcode=$?
# 0 exitSuccess, 2 exitBadOptions (pre-1.6.143 vc-agent-007 doesn't support -self-test)
if [ $exitcode -ne 0 -a $exitcode -ne 2 ]; then
	rm -f /usr/local/bin/vc-agent-007
	if   [ $exitcode -eq 3 ]; then  # exitNoToken
		abort "The API token you used, ${VCTOKEN}, is not valid, please verify and retry installation"
	elif [ $exitcode -eq 4 ]; then  # exitBadProxy
		abort "Cannot use proxy [ ${https_proxy} ], please verify and retry installation"
	elif [ $exitcode -eq 7 ]; then  # exitCantReachAPI
		if [ "$platform" = "freebsd" -a ! -f /usr/local/share/certs/ca-root-nss.crt ]; then
			abort "Cannot reach VividCortex, please verify that proxy/firewall allows outgoing https (port 443) to app.vividcortex.com, CA root certificates present (pkg install security/ca_root_nss), and retry installation"
		else
			abort "Cannot reach VividCortex, please verify that proxy/firewall allows outgoing https (port 443) to app.vividcortex.com, and retry installation"
		fi
	elif [ $exitcode -eq 8 -o $exitcode -ge 128 ]; then # exitUnsupported or segfault
		abort "OS version probably unsupported, please contact VividCortex.
Additional information: ${distro}/${arch} (exitcode=${exitcode}) `uname -a`"
	else
		abort "Installation failed. Please retry and, if the problem persists, contact VividCortex.
Additional information: ${distro}/${arch} (exitcode=${exitcode}) `uname -a`"
	fi
fi

mv -f "${tempdir}/vividcortex" "${initdir}/${initname}" || abort "Unable to install vividcortex init script"
chmod ${initperm} "${initdir}/${initname}" || abort "Unable to set ${initdir}/${initname} permissions"

rm -Rf $tempdir >/dev/null 2>&1
tempdir=""

createdir "$confdir"
createdir "$logdir"

cat - > "$globalconf" <<EOF
{
    "api-token": "$VCTOKEN",
    "proxy-uri": "$proxy"
}
EOF

chmod 600 "$globalconf"

[ $? -eq 0 ] || abort "Unable to create $globalconf"

echo
echo "VividCortex agents successfully installed"
echo

resp=""
if [ -z "$AUTOSTART" ]; then
	echo -n "Would you like to schedule automatic service startup? [Y/n] "
	read resp
	echo
fi

if [ "$resp" = 'Y' -o "$resp" = 'y' -o "$AUTOSTART" = "1" ]; then
	if [ "${installcmd}" = "" ]; then
		msg "Sorry, don't know how to enable init scripts for '${initver}'."
		msg "Please enable the 'vividcortex' init script manually."
		msg "Please also tell VividCortex how to improve this script to do that."
		abort ""
	else
		${installcmd} >/dev/null 2>&1 || abort "Unable to install init script using '${installcmd}'"
	fi
	echo "VividCortex init script scheduled for automatic start/stop"
else
	echo "VividCortex init script *NOT* scheduled for automatic start/stop"
fi

echo

if [ "$STARTNOW" = 1 ]; then
	echo "Starting VividCortex service"
	${startcmd} >/dev/null 2>&1

	if [ $? -ne 0 ]; then
		msg
		msg "VividCortex service startup may have failed."
		msg "Please inspect '$logdir/vc-agent-007.log' for details."
		msg
		msg "VividCortex service can be started by running:"
		msg
		msg "    ${startcmd}"
	fi
else
	echo "VividCortex service can be started by running:"
	echo
	echo "    ${startcmd}"
fi

echo
echo "Installation is done; please check the VividCortex app to see the new host"
echo
exit 0
