#! /usr/bin/bash

# Ensure an AWS instance is terminated.  With Resalloc API
# Copyright (C) 2021 Pavel Raiskup <praiskup@redhat.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

set -e

show_help()
{
cat <<EOHELP >&2
Usage: $0 [OPTIONS]

Stop an AWS instance according to given options.

Instead of --name, you can use \$RESALLOC_NAME env var.

Options:
  --name NAME           Name of the VM to be stopped.
  --aws-profile         Name of the aws profile, as defined in ~/.aws/config.
  --region              Region ID (might be set in aws-profile)
  --debug               Print debugging info.
EOHELP

test -z "$1" || exit "$1"
}

opt_debug=false
opt_name=$RESALLOC_NAME
opt_aws_profile=
opt_region=

info() { echo >&2 " * $*" ; }
debug() { if $opt_debug; then echo >&2 " - $*" ; fi }
error() { echo -e >&2 "!!!\n!!! $*\n!!!\n"; }
fatal_args () { error "$*"; show_help 1 ; }

run_cmd()
{
    debug "running $*"
    "$@"
}

long_opts="name:,aws-profile:,debug,help,region:"
ARGS=$( getopt -o "h" -l "$long_opts" -n "getopt" -- "$@") || show_help 1

mandatory_options="
    --aws-profile
"

# is that necessary -> should preserve whitespaces in option arguments
# see: http://linuxwell.com/2011/07/14/getopt-in-bash/
eval set -- "$ARGS"

option_variable()
{
    opt=$1
    opt=${1##--}
    opt=${opt##-}
    opt=${opt//-/_}
    # drop the '--no' prefix
    if test -n "$2"; then
        opt=${opt//no_/}
    fi
    option_variable_result=opt_$opt
}

while true; do
    # now the name is in $1 and argument in $2
    case $1 in
    -h|--help)
        show_help 0
        ;;

    --name|--aws-profile|--region)
        option_variable "$1"
        eval "$option_variable_result=\$2"
        shift 2
        ;;

    --debug)
        option_variable "$1"
        eval "$option_variable_result=:"
        shift
        ;;

    --) shift; break ;;  # end
    *) echo "programmer mistake ($1)" >&2; exit 1 ;;
    esac
done

test -z "$opt_name" && fatal_args "\$RESALLOC_NAME or --name required"

for mandatory_option in $mandatory_options
do
    option_variable "$mandatory_option"
    eval "test -z \$$option_variable_result" && \
        fatal_args "$mandatory_option is required"
done

aws=(
    aws --profile "$opt_aws_profile"
        --output text
)

test -n "$opt_region" && aws+=( --region "$opt_region" )

instance_id=$(
    run_cmd "${aws[@]}" ec2 describe-instances \
    --filters "Name=tag:Name,Values=$opt_name" \
    --output text \
    --query 'Reservations[*].Instances[*].{Instance:InstanceId}'
)

test -n "$instance_id"
info "Terminating instance ID: $instance_id"
run_cmd "${aws[@]}" ec2 terminate-instances --instance-ids "$instance_id"
