#!/usr/bin/env bash

# Perform deploy tasks on target system

set -e

# Environment vars
# MIX_ENV: location of files in _build dir, defaults to "prod"
MIX_ENV="${MIX_ENV:-prod}"
# VERSION: version of release, defaults to version when script was generated
VERSION="${VERSION:-<%= version %>}"
# DESTDIR, prefix for target files, optional

DEPLOY_USER="${DEPLOY_USER:-<%= deploy_user %>}"
DEPLOY_GROUP="${DEPLOY_GROUP:-<%= deploy_group %>}"
APP_USER="${APP_USER:-<%= app_user %>}"
APP_GROUP="${APP_USER:-<%= app_group %>}"

export LANG="<%= env_lang %>"

SERVICE_NAME="<%= service_name %>"
EXT_NAME="<%= ext_name %>"
APP_NAME="<%= app_name %>"
DEPLOY_DIR="<%= deploy_dir %>"
RELEASES_DIR="<%= releases_dir %>"

# Create users on target
# Local and CodeDeploy
function do_create_users(){
    id -u "$DEPLOY_USER" &>/dev/null || useradd "$DEPLOY_USER"
    if [ "$APP_USER" != "$DEPLOY_USER" ]; then
        id -u "$APP_USER" &>/dev/null || useradd "$APP_USER"
    fi
}

# Create app dirs on target
# Local and CodeDeploy
function do_create_dirs(){
<%= for {enabled, path, user, group, mode, comment} <- create_dirs, enabled == true do %>
    # <%= comment %>
    echo "==> Creating dir ${DESTDIR}<%= path %>"
    mkdir -p "${DESTDIR}<%= path %>"
    chown <%= user %>:<%= group %> "${DESTDIR}<%= path %>"
    chmod <%= Integer.to_string(mode, 8) %> "${DESTDIR}<%= path %>"

<% end %>
}

# Copy files to target
# Local deploy or staging files using DESTDIR
function do_copy_files(){
<%= for {src, dst, user, group, mode} <- copy_files do %>
    echo "==> Copying file ${DESTDIR}<%= dst %>"
    cp <%= src %> "${DESTDIR}<%= dst %>"
    chown <%= user %>:<%= group %> "${DESTDIR}<%= dst %>"
    chmod <%= Integer.to_string(mode, 8) %> "${DESTDIR}<%= dst %>"

<% end %>
    echo "==> Copying systemd unit files for $SERVICE_NAME"
    mkdir -p "${DESTDIR}/lib/systemd/system"
    cp _build/${MIX_ENV}/systemd/lib/systemd/system/* "${DESTDIR}/lib/systemd/system/"
    chmod 644 ${DESTDIR}/lib/systemd/system/${SERVICE_NAME}*

<%= if sudo_deploy or sudo_app do %>
    echo "==> Copying sudoers.d/${EXT_NAME}"
    mkdir -p "${DESTDIR}/etc/sudoers.d"
    cp "_build/${MIX_ENV}/deploy/etc/sudoers.d/${EXT_NAME}" "${DESTDIR}/etc/sudoers.d/"
    chmod 600 "${DESTDIR}/etc/sudoers.d/${EXT_NAME}"
<% end %>
}

# Extract release
# CodeDeploy
function do_extract_release(){
    CURRENT_DIR="${DESTDIR}${DEPLOY_DIR}/current"
    TAR_FILE="${APP_NAME}.tar.gz"

    echo "==> Extracting release from tar file $TAR_FILE"
    mkdir -p "$CURRENT_DIR"
    tar -C "$CURRENT_DIR" -xzf "$TAR_FILE"
    chown -R ${DEPLOY_USER}:${APP_GROUP} "${CURRENT_DIR}"

    # Clean up archive
    rm "$TAR_FILE"
}

# Deploy release from local build
# Env var VERSION specifies version
# Local deploy
function do_deploy_release(){
    CURRENT_LINK="${DESTDIR}${DEPLOY_DIR}/current"
    TAR_FILE="_build/${MIX_ENV}/rel/${APP_NAME}/releases/${VERSION}/${APP_NAME}.tar.gz"

    TIMESTAMP=$(date +%Y%m%d%H%M%S)
    RELEASE_DIR="${DESTDIR}${RELEASES_DIR}/${TIMESTAMP}"

    echo "==> Deploying release $VERSION to $RELEASE_DIR"
    mkdir -p "$RELEASE_DIR"

    echo "===> Extracting release from tar file $TAR_FILE"
    tar -C "$RELEASE_DIR" -xf "$TAR_FILE"
    chown -R ${DEPLOY_USER}:${APP_GROUP} "${CURRENT_LINK}"

    echo "===> Setting current symlink $CURRENT_LINK"
    if [[ -L "$CURRENT_LINK" ]]; then
        rm "$CURRENT_LINK"
    fi
    ln -s "$RELEASE_DIR" "$CURRENT_LINK"
}

# Rollback release to previous
# Local deploy
function do_rollback_release(){
    CURRENT_LINK="${DESTDIR}${DEPLOY_DIR}/current"
    # TODO: error handling
    PREV_DIR=$(find "${DESTDIR}${RELEASES_DIR}" -maxdepth 1 | sort | tail -2 | head -1)
    PREV_NAME=$(basename "${PREV_DIR}")
    RELEASE="${RELEASE:-$PREV_NAME}"

    echo "==> Rolling back to release $RELEASE"
    if [[ -L "$CURRENT_LINK" ]]; then
        rm "$CURRENT_LINK"
    fi
    ln -s "${DESTDIR}${RELEASES_DIR}/${PREV_NAME}" "$CURRENT_LINK"
}

# Enable systemd units on target
function do_enable(){
    echo "==> Enabling systemd unit $SERVICE_NAME"
    /bin/systemctl enable "${SERVICE_NAME}"

<%= if restart_method == :systemd_flag do %>
    echo "==> Enabling systemd unit ${SERVICE_NAME}-restart"
    /bin/systemctl enable "${SERVICE_NAME}-restart"
<% end %>

<%= if runtime_environment_service do %>
    echo "==> Enabling systemd unit ${SERVICE_NAME}-runtime-environment"
    /bin/systemctl enable "${SERVICE_NAME}-runtime-environment"
<% end %>
}

# Start service
function do_start(){
<%= if runtime_environment_service do %>
    /bin/systemctl start "${SERVICE_NAME}-runtime-environment"
<% end %>
    /bin/systemctl start "${SERVICE_NAME}"
}

# Stop service if it is running
function do_stop(){
    if /bin/systemctl is-active "${SERVICE_NAME}"; then
        /bin/systemctl stop "${SERVICE_NAME}"
    fi
}

# Restart service
function do_restart(){
    /bin/systemctl restart "${SERVICE_NAME}"
}

function do_runtime_environment(){
    # https://cloudinit.readthedocs.io/en/latest/topics/network-config.html#network-configuration-outputs

    # Digital Ocean
    # IP_ADDR=$(jq -r '.ds.meta_data.interfaces.public[0].anchor_ipv4.ip_address' < /run/cloud-init/instance-data.json)

    # AWS
    IP_ADDR=$(jq -r '.ds."meta-data"."local-ipv4"' < /run/cloud-init/instance-data.json)
    # IP_ADDR=$(jq -r '.ds."meta-data"."public-ipv4"' < /run/cloud-init/instance-data.json)

    echo "DEFAULT_IPV4=$IP_ADDR" > <%= runtime_dir %>/runtime-environment
}

if [ -z "$1" ]; then
    echo "deploy: no task specified."
    echo "deploy: Options: init create_users create_dirs copy_files"
    echo "deploy:          deploy_release rollback_release extract_release"
    echo "deploy:          runtime_environment enable start stop restart"
    exit 1
fi

case $1 in
    create_users)
        do_create_users
        ;;
    create_dirs)
        do_create_dirs
        ;;
    copy_files)
        do_copy_files
        ;;
    deploy_release)
        do_deploy_release
        ;;
    rollback_release)
        do_rollback_release
        ;;
    extract_release)
        do_extract_release
        ;;
    enable)
        do_enable
        ;;
    start)
        do_start
        ;;
    stop)
        do_stop
        ;;
    restart)
        do_restart_service
        ;;
    runtime_environment)
        do_runtime_environment
        ;;
    init)
        do_create_users && do_create_dirs && do_copy_files && do_enable
        ;;
    *)
        echo "Invalid command $1"
        exit 1
        ;;
esac

exit 0
