#!/bin/bash
## START_OF_BASH_PLUS
red="\033[38;5;196m"
neutral='\033[0m'
cyan='\033[00;34m'
white='\033[97m'
green="\033[38;5;46m"
ok=${green}"✔"${neutral}
# fail=${red}"✖"${neutral}

epoch () {
  echo `python -c "import time; print  ('{:0.0f}'.format(time.time()))"`
}

stopwatch () {
  BEGIN=$1
  NOW=`epoch`
  let DIFF=$(( $NOW - $BEGIN ))
  echo $DIFF
}

info () {
  >&2 printf " [ ${cyan}INFO${neutral} ] $1 $2\n"
}

user () {
  # shellcheck disable=SC2059
 >&2 printf "\r  [ \033[0;33m?\033[0m ] $1 "
}

success () {
  >&2 printf "   [ ${green}OK${neutral} ] $1 $2\n"
}

fatal () {
  error $2
  exit 1
}

error(){
 >&2  printf "[ ${red}ERROR${neutral} ] $1 $2\n"
}

# log a message with a seconds since program start prefix
log() {
  if [[ "$START" == "" ]]; then
      START=$(epoch)
  fi
  >&2 printf "[ $(printf %05d $(stopwatch $START)) ] $1\n"
}


die(){
    printf ${red}"$1${neutral} "$2"\n"
    exit 1
}

hr(){
  >&2   echo "================================================================================"
}

hr2(){
  >&2   echo "=================================================="
}

hr3(){
  >&2   echo "========================================"
}

strict_mode() {

  set -o errexit
  set -o nounset
  set -o pipefail
}

strict_mode_off() {
  unset -o errexit
  unset -o nounset
  unset -o pipefail
}

is_linux(){
    if [ "$(uname -s)" = "Linux" ]; then
        return 0
    else
        return 1
    fi
}

is_mac(){
    if [ "$(uname -s)" = "Darwin" ]; then
        return 0
    else
        return 1
    fi
}

is_jenkins(){
    if [ -n "${JENKINS_URL:-}" ]; then
        return 0
    else
        return 1
    fi
}

is_travis(){
    if [ -n "${TRAVIS:-}" ]; then
        return 0
    else
        return 1
    fi
}

is_CI(){
    if [ -n "${CI:-}" -o -n "${CI_NAME:-}" ] || is_jenkins || is_travis; then
        return 0
    else
        return 1
    fi
}
timestamp=$(date +%s)
## END_OF_BASH_PLUS
#!/bin/bash
# ARG_OPTIONAL_SINGLE([inventory],[i],[ansible inventory file or directory])
# ARG_OPTIONAL_SINGLE([host-prefix],[],[The prefix to add to each hostname],[])
# ARG_OPTIONAL_SINGLE([template],[],[AMI or VMWare template to use to provision],[])
# ARG_OPTIONAL_SINGLE([target],[],[The provisioning target, one of: aws, vmware, azure, aws-service-catalog],[])
# ARG_OPTIONAL_SINGLE([count],[],[Number of instances to provision],[1])
# ARG_OPTIONAL_SINGLE([cloud-init],[],[Path to cloud-init file to use],[])
# ARG_OPTIONAL_SINGLE([group],[],[Ansible inventory group name],[])
# ARG_OPTIONAL_SINGLE([hostname],[],[Hostname to use for instance],[])
# ARG_OPTIONAL_BOOLEAN([dev-mode],[],[skip role pinning],[off])
# ARG_OPTIONAL_SINGLE([git-base],[],[The git repository base for roles],[https://github.com/moshloop])
# ARG_HELP([])
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.8.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info


die()
{
	local _ret=$2
	test -n "$_ret" || _ret=1
	test "$_PRINT_HELP" = yes && print_help >&2
	echo "$1" >&2
	exit ${_ret}
}


begins_with_short_option()
{
	local first_option all_short_options='ih'
	first_option="${1:0:1}"
	test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

# THE DEFAULTS INITIALIZATION - OPTIONALS
inventory=
host_prefix=
template=
target=
count="1"
cloud_init=
group=
hostname=
dev_mode="off"
git_base="https://github.com/moshloop"


print_help()
{
	printf 'Usage: %s [-i|--inventory <arg>] [--host-prefix <arg>] [--template <arg>] [--target <arg>] [--count <arg>] [--cloud-init <arg>] [--group <arg>] [--hostname <arg>] [--(no-)dev-mode] [--git-base <arg>] [-h|--help]\n' "$0"
	printf '\t%s\n' "-i, --inventory: ansible inventory file or directory (no default)"
	printf '\t%s\n' "--host-prefix: The prefix to add to each hostname (no default)"
	printf '\t%s\n' "--template: AMI or VMWare template to use to provision (no default)"
	printf '\t%s\n' "--target: The provisioning target, one of: aws, vmware, azure, aws-service-catalog (no default)"
	printf '\t%s\n' "--count: Number of instances to provision (default: '1')"
	printf '\t%s\n' "--cloud-init: Path to cloud-init file to use (no default)"
	printf '\t%s\n' "--group: Ansible inventory group name (no default)"
	printf '\t%s\n' "--hostname: Hostname to use for instance (no default)"
	printf '\t%s\n' "--dev-mode, --no-dev-mode: skip role pinning (off by default)"
	printf '\t%s\n' "--git-base: The git repository base for roles (default: 'https://github.com/moshloop')"
	printf '\t%s\n' "-h, --help: Prints help"
}


parse_commandline()
{
	while test $# -gt 0
	do
		_key="$1"
		case "$_key" in
			-i|--inventory)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				inventory="$2"
				shift
				;;
			--inventory=*)
				inventory="${_key##--inventory=}"
				;;
			-i*)
				inventory="${_key##-i}"
				;;
			--host-prefix)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				host_prefix="$2"
				shift
				;;
			--host-prefix=*)
				host_prefix="${_key##--host-prefix=}"
				;;
			--template)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				template="$2"
				shift
				;;
			--template=*)
				template="${_key##--template=}"
				;;
			--target)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				target="$2"
				shift
				;;
			--target=*)
				target="${_key##--target=}"
				;;
			--count)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				count="$2"
				shift
				;;
			--count=*)
				count="${_key##--count=}"
				;;
			--cloud-init)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				cloud_init="$2"
				shift
				;;
			--cloud-init=*)
				cloud_init="${_key##--cloud-init=}"
				;;
			--group)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				group="$2"
				shift
				;;
			--group=*)
				group="${_key##--group=}"
				;;
			--hostname)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				hostname="$2"
				shift
				;;
			--hostname=*)
				hostname="${_key##--hostname=}"
				;;
			--no-dev-mode|--dev-mode)
				dev_mode="on"
				test "${1:0:5}" = "--no-" && dev_mode="off"
				;;
			--git-base)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				git_base="$2"
				shift
				;;
			--git-base=*)
				git_base="${_key##--git-base=}"
				;;
			-h|--help)
				print_help
				exit 0
				;;
			-h*)
				print_help
				exit 0
				;;
			*)
				_PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
				;;
		esac
		shift
	done
}

parse_commandline "$@"

# OTHER STUFF GENERATED BY Argbash

### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash

log "Starting"

ROLE_NAME=provision
DIR=~/.ansible/roles/$ROLE_NAME
GIT_BASE=$_arg_git_base
DEV_MODE=$_arg_dev_mode
PLAYBOOK=.ansible-$ROLE_NAME.yml
inventory=$_arg_inventory
group=$_arg_group
host_prefix=$_arg_host_prefix
ARGS=


if [[ "$_args_cloud_init" != "" ]]; then
  ARGS+=" -e cloud_init_path=$_args_cloud_init"
fi

if [[ "$_args_count" != "" ]]; then
  ARGS+=" -e instance_count=$_args_count"
fi

if [[ "$_args_template" != "" ]]; then
  ARGS+=" -e template=$_args_template"
fi

if [[ "$inventory" == "" && -d inventory ]]; then
  ARGS+=" -i inventory"
  inventory="inventory"
fi


checkout_role() {
  DIR=~/.ansible/roles/$1
  if [[ ! -e $DIR ]]; then
    git clone $GIT_BASE/ansible-$1.git $DIR
  fi
  pwd=$(pwd)

  if [[ "$ARG1" == "install" ]]; then
    return
  elif [[  "$ARG1" == "update" ]]; then
    cd $DIR
    git fetch --all
    cd $pwd
    return
  fi

  filter="._meta.hostvars | values[] | .ansible_$1_version"
  desired_tag=$( ansible-inventory -i $inventory --list | jq -r "$filter" | head -n1)

  pwd=$(pwd)
  cd $DIR
  current_tag=$(git describe --tags)

  if [[ "$desired_tag" != "null" && "$desired_tag" != "" && "$desired_tag" != "$current_tag" ]]; then
    echo "Checking out $desired_tag"
    git fetch
    git checkout $desired_tag
  fi
  echo "Using ansible-${1} $(git log -n1 --oneline)"
  cd $pwd
}

function finish {
  rm $PLAYBOOK
}

if [[ ! -e $PLAYBOOK ]]; then
  ln -s $DIR/$ROLE_NAME.yml $PLAYBOOK
fi

if [[ "$DEV_MODE" == 'false' ]]; then
  checkout_role "deploy"
  checkout_role "provision"
  trap finish EXIT
fi

if [[ "$ARG1" == "install" || "$ARG1" == "update" ]]; then
  exit
fi

# ARGS="$ARGS $@"

if [[ ! -e $inventory/hosts && ! -e $inventory/hosts.ini ]]; then
  echo "No hosts detected using $host_prefix/$group"
  echo "[$group]" > $inventory/hosts
  echo "${host_prefix}" >> $inventory/hosts
  delete_hosts() {
    rm inventory/hosts
  }
  trap delete_hosts EXIT
fi

export ANSIBLE_HASH_BEHAVIOUR=merge
export DISPLAY_SKIPPED_HOSTS=false
export DISPLAY_OK_HOSTS=false
export ANSIBLE_CALLBACK_WHITELIST=dense2
export ANSIBLE_STDOUT_CALLBACK=dense2
export ANSIBLE_CALLBACK_PLUGINS=$DIR/callback_plugins
export ANSIBLE_INVENTORY_IGNORE_REGEX=build/*

echo ansible-playbook $PLAYBOOK $ARGS
eval ansible-playbook  $ARGS $@ $PLAYBOOK

# ] <-- needed because of Argbash
