#!/usr/bin/env bash # # xaval - xiringuito connection manager # [[ "${DEBUG}" == "true" ]] && set -x set -e set -o pipefail declare -r ROOT_DIR=${HOME}/.xiringuito declare -r DIR=${ROOT_DIR}/profiles; mkdir -p ${DIR} declare -r LOG_DIR=${ROOT_DIR}/logs; mkdir -p ${LOG_DIR} declare -r RECONNECT_AFTER=5 declare -r WAIT_TIMEOUT=15 declare -r ATTACH_MARKER="${ROOT_DIR}/attach" if [[ -f "${ATTACH_MARKER}" ]]; then declare -r ATTACH=true else declare -r ATTACH=false fi function print_help(){ cat </dev/null && echo "true" || echo "false") DISCOVERY_OFF=$(egrep "(^| )-X " ${PROFILE_FILE} >/dev/null && echo "true" || echo "false") if [[ "${ROUTES_PASSED}" == "false" && "${DISCOVERY_OFF}" == "false" ]]; then echo "true" else echo "false" fi } function select_profile(){ local START_NUMBER=1 local PROFILE_COUNT=$(list_profiles | wc -l | sed 's/ //g') if [[ ${PROFILE_COUNT} -eq 0 ]]; then print_help echo "You have no profiles configured..." exit 0 fi list_profiles | awk '{printf "%2d) %s\n", NR, $0}' echo; read -p "PROFILE NUMBER (${START_NUMBER}-${PROFILE_COUNT})>" PROFILE_NUMBER if [[ ${PROFILE_NUMBER} =~ "^[0-9]+$" ]]; then commit_suicide "Should be a natural number!" fi if [[ ${PROFILE_NUMBER} -lt ${START_NUMBER} ]]; then commit_suicide "Should be >= ${START_NUMBER}" fi if [[ ${PROFILE_NUMBER} -gt ${PROFILE_COUNT} ]]; then commit_suicide "Should be <= ${PROFILE_COUNT}" fi local PROFILE=$(list_profiles | head -n${PROFILE_NUMBER} | tail -n1 | cut -d' ' -f1) if [[ "${ATTACH}" == "true" ]]; then attach_profile ${PROFILE} else connect_profile ${PROFILE} fi } function list_profiles(){ local FILTER_EXPR="${@}" if [[ -z "${FILTER_EXPR}" ]]; then FILTER_EXPR=".*" fi for PROFILE in $(find ${DIR} -type f | awk -F"/" '{print $NF}' | egrep "${FILTER_EXPR}" | sort); do printf "%-20s %-4s = %s\n" ${PROFILE} $(get_profile_status ${PROFILE}) "$(cat ${DIR}/${PROFILE})" done } function create_profile(){ local PROFILE=${1}; shift suicide_on_existing_profile ${PROFILE} echo "${@}" >${DIR}/${PROFILE} } function update_profile(){ local PROFILE=${1}; shift suicide_on_absent_profile ${PROFILE} echo "${@}" >${DIR}/${PROFILE} } function upsert_profile(){ local PROFILE=${1}; shift echo "${@}" >${DIR}/${PROFILE} } function delete_profile(){ local PROFILE=${1} suicide_on_absent_profile ${PROFILE} rm ${DIR}/${PROFILE} } function toggle_attach { if [[ "${ATTACH}" == "true" ]]; then rm "${ATTACH_MARKER}" echo "ATTACH: ON->OFF" else touch "${ATTACH_MARKER}" echo "ATTACH: OFF->ON" fi } function loop_connection() { trap "echo 'HUP is trapped'" HUP local PROFILE=${1} local TRY=true local OPTS="" set +e while [[ ${TRY} == true ]]; do $(dirname ${0})/xiringuito ${OPTS} $(cat ${DIR}/${PROFILE}) if [[ ${?} -eq 0 || ${?} -eq 143 ]]; then echo "=> Will sleep ${RECONNECT_AFTER} seconds before reconnection..." OPTS="-c" sleep ${RECONNECT_AFTER} else TRY=false fi done } function attach_profile(){ local PROFILE=${1} suicide_on_absent_profile ${PROFILE} suicide_on_profile_up ${PROFILE} loop_connection ${PROFILE} } function connect_profile(){ echo -n "[ sudo check ] "; sudo true; echo local PROFILE=${1} suicide_on_absent_profile ${PROFILE} suicide_on_profile_up ${PROFILE} local LOG_FILE=${LOG_DIR}/${PROFILE} if [[ "$(do_mfa_prewarm ${PROFILE})" == "true" ]]; then ./discover-routes $(awk '{print $NF}' ${DIR}/${PROFILE}) >/dev/null fi echo echo "Connecting (in background): ${PROFILE}" echo echo "Use \"xaval logs ${PROFILE}\" to see connection logs" loop_connection ${PROFILE} &>${LOG_FILE} & wait_connection ${PROFILE} } function wait_connection(){ local PROFILE=${1} sleep 2 local WAIT_TIME=0 while [[ "$(get_profile_status ${PROFILE})" != "UP" ]]; do if [[ ${WAIT_TIME} -ge ${WAIT_TIMEOUT} ]]; then dump_profile_log ${PROFILE} commit_suicide "Unable to bring up \"${PROFILE}\" after ${WAIT_TIMEOUT} seconds" fi echo "* Waiting for connection to come up..." sleep 1 ((++WAIT_TIME)) done } function kill_profile() { local PROFILE=${1} suicide_on_absent_profile ${PROFILE} suicide_on_profile_down ${PROFILE} kill -HUP $(get_profile_pid ${PROFILE}) } function logs_profile() { local PROFILE=${1} suicide_on_absent_profile ${PROFILE} local LOG_FILE=${LOG_DIR}/${PROFILE} cat ${LOG_FILE} echo echo "STATUS: $(get_profile_status ${PROFILE})" } function dump_profile_log() { local PROFILE=${1} suicide_on_absent_profile ${PROFILE} local LOG_FILE=${LOG_DIR}/${PROFILE} echo "--- LOG ---" >>/dev/stderr cat ${LOG_FILE} >>/dev/stderr echo "--- LOG ---" >>/dev/stderr } function rename_profile(){ local OLD_PROFILE=${1} local NEW_PROFILE=${2} suicide_on_absent_profile ${OLD_PROFILE} suicide_on_existing_profile ${NEW_PROFILE} mv ${DIR}/${OLD_PROFILE} ${DIR}/${NEW_PROFILE} } if [[ $(echo "${@}" | egrep "((^|(^| )-{1,2})help|^-h)($| )") ]]; then print_help exit 0 fi if [[ ${#} -eq 0 ]]; then select_profile fi declare -r CMD=${1}; shift if [[ "${CMD}" == "" ]]; then echo "- Bye bye!" exit 0 fi if [[ ! $(validate_command ${CMD}) ]]; then print_help_and_commit_suicide "Illegal command: ${CMD}" fi if [[ "${CMD}" == "list" ]]; then list_profiles "${@}" exit 0 fi # ... this happens when you do not like case..esac ... if [[ "${CMD}" == "connect" || "${CMD}" == "attach" || "${CMD}" == "delete" || "${CMD}" == "kill" || "${CMD}" == "logs" ]]; then if [[ ${#} -ne 1 ]]; then print_help_and_commit_suicide "Command requires exactly 1 parameter: ${CMD}" fi elif [[ ${CMD} == "rename" ]]; then if [[ ${#} -ne 2 ]]; then print_help_and_commit_suicide "Command requires exactly 2 parameters: ${CMD}" fi elif [[ ${CMD} == "toggle" ]]; then if [[ ${#} -ne 0 ]]; then print_help_and_commit_suicide "Command does not require any parameters: ${CMD}" fi toggle_attach exit 0 else if [[ ${#} -lt 2 ]]; then print_help_and_commit_suicide "Not enough parameters for the command: ${CMD}" fi fi eval ${CMD}_profile ${@}