#!/bin/bash
# Helper functions for interacting with Hubs infrastructure.

# hab-run [results-dir]
# Loads the most-recently-built Habitat .hart package into the local running Habitat supervisor,
# first stopping and unloading any existing version of the same package. Starts the package running.
function hab-run {
    local RESULTS_DIR=${1:-./results}
    local RESULTS_ENV=$RESULTS_DIR/last_build.env
    (export $(cat $RESULTS_ENV | xargs) && sudo -E hab svc unload $pkg_origin/$pkg_name)
    (export $(cat $RESULTS_ENV | xargs) && sudo -E hab pkg install $RESULTS_DIR/$pkg_artifact)
    (export $(cat $RESULTS_ENV | xargs) && sudo -E hab svc load $pkg_ident)
    (export $(cat $RESULTS_ENV | xargs) && sudo -E hab svc start $pkg_ident)
}

# hab-build-and-run [plan-dir]
# Builds a Habitat plan and runs the output locally using hab-run.
function hab-build-and-run {
    local PLAN_DIR=${1:-.}
    hab pkg build $PLAN_DIR && hab-run
}

# moz-ec2 [env] [asg]
# Lists active hosts from EC2, displaying environment, ASG, name, private IP, and public IP.
function moz-ec2 {
    local FILTERS="[{\"Name\": \"instance-state-name\",\"Values\": [\"running\"]}"
    if [ ! -z "$1" ]
    then
        FILTERS="$FILTERS,{\"Name\": \"tag:env\",\"Values\": [\"$1\"]}"
    fi
    if [ ! -z "$2" ]
    then
        FILTERS="$FILTERS,{\"Name\": \"tag:aws:autoscaling:groupName\",\"Values\":[\"$1-$2\"]}"
    fi
    FILTERS="$FILTERS]"
    local ALL=$(aws ec2 describe-instances --output json --filters "$FILTERS")
    local OUTPUT=$(jq -r '.Reservations | map(.Instances) | flatten | .[] | [
      ((.Tags//[])[]|select(.Key=="env")|.Value) // "null",
      ((.Tags//[])[]|select(.Key=="aws:autoscaling:groupName")|.Value) // "null",
      ((.Tags//[])[]|select(.Key=="Name")|.Value) // "null",
      .PrivateIpAddress // "null",
      .PublicIpAddress // "null"
    ] | @tsv' <<< "$ALL")
    echo "${OUTPUT}" | sort -k2,2 -k3,3 | column -t -s $'\t'
}

# moz-host env asg
# Gets the name of a random host from EC2 with the given environment and ASG.
function moz-host {
    moz-ec2 $1 $2 | shuf | head -n 1 | awk '{print $3}'
}

# moz-proxy cmd env ...cmd-args
# Proxies the given OpenSSH command through the given environment's bastion host.
function moz-proxy {
    $1 -o ProxyJump="$(moz-host $2 bastion).reticulum.io" "${@:3}"
}

# moz-ssh target ...cmd-args
# SSHes into the given target through its bastion host, e.g. `moz-ssh dazzling-druid`.
function moz-ssh {
    local ALL_INSTANCES=$(moz-ec2)
    local DESTINATION=$(echo "$ALL_INSTANCES" | grep "$1" | shuf | head -n 1)
    local DESTINATION_ENV=$(echo "$DESTINATION" | awk "{print \$1}")
    local DESTINATION_HOST=$(echo "$DESTINATION" | awk "{print \$3}")
    local BASTION=$(echo "$ALL_INSTANCES" | awk "/$DESTINATION_ENV-bastion/ {print \$3}")
    ssh -o ProxyJump="$BASTION.reticulum.io" "$DESTINATION_HOST-local.reticulum.io" "${@:2}"
}

# moz-tunnel target local-port remote-port ...cmd-args
# Opens an SSH tunnel to the given target through its bastion host, e.g. `moz-tunnel dev-ci 8088 8080`.
function moz-tunnel {
    local ALL_INSTANCES=$(moz-ec2)
    local DESTINATION=$(echo "$ALL_INSTANCES" | grep "$1" | shuf | head -n 1)
    local DESTINATION_ENV=$(echo "$DESTINATION" | awk "{print \$1}")
    local DESTINATION_HOST=$(echo "$DESTINATION" | awk "{print \$3}")
    local BASTION=$(echo "$ALL_INSTANCES" | awk "/$DESTINATION_ENV-bastion/ {print \$3}")
    ssh -L "$2:$DESTINATION_HOST-local.reticulum.io:$3" "$BASTION.reticulum.io" "${@:4}"
}

# moz-tunnel-postgrest ...cmd-args
# Opens an SSH tunnel to the prod Postgrest admin console. (This is magically different from SSH tunnels
# to anything else because there is an ALB in front of the instance with a hardcoded DNS, and
# the instance won't talk to anyone except the ALB. The dev ALB is called postgrest-dev.reticulum.io.)
function moz-admin {
    ssh -L "3000:postgrest.reticulum.io:3000" "$(moz-host prod bastion).reticulum.io" "${@:1}"
}

function moz-admin-dev {
    ssh -L "3000:postgrest-dev.reticulum.io:3000" "$(moz-host dev bastion).reticulum.io" "${@:1}"
}

# moz-iex target ...cmd-args
# SSHes into a Reticulum host and opens an Elixir console.
function moz-iex {
    SCRIPT_PATH=$(dirname "$BASH_SOURCE[0]")
    moz-ssh "$1" "$(< $SCRIPT_PATH/bin/remote_console.sh)" "${@:3}"
}

# Creates a tunnel to the CI host's web interface on port 8088.
alias moz-ci='moz-tunnel dev-ci 8088 8080'

# Proxies SCP over a bastion host, e.g. `moz-scp prod dazzling-druid-local.reticulum.io:~/core core`.
alias moz-scp='moz-proxy scp'
