diff --git a/scripts/ops/README.md b/scripts/ops/README.md new file mode 100644 index 000000000..5b8dd4f3e --- /dev/null +++ b/scripts/ops/README.md @@ -0,0 +1,40 @@ +# Armadillo for OPS + +To monitor and control Armadillo and its DataShield docker containers we need to use the Armadillo API. + +## Armadillo Controller + +With `armadilloctl` you can control the DataShield docker containers. + +To make this possible Armadillo must have an admin user set. + +### env.dist + +The file [`env.dist`](./env.dist) lists the required environment variables. + +- Copy this over to a location of choice ie `/etc/armadillo/acc.env` + +### run + +Make sure to `source` the file in your current `bash` or through a new shell. + +```bash +bash -c "source /etc/armadillo/acc.env ; ./armadilloctl.bash" +``` + +### examples + +- `./armadillo.bash statusAll` +- `./armadillo.bash autoStart` +- `./armadillo.bash stop default` +- `./armadillo.bash startAll` + +### Test script (WIP) + +You can test `armadilloctl.bash` using `test_armadilloctl.bash`. + +We source the environment variables to not contaminate our current shell. + +```bash +bash -c "source /etc/armadillo/acc.env ; ./test_armadilloctl.bash" || echo FAILED +``` diff --git a/scripts/ops/armadilloctl.bash b/scripts/ops/armadilloctl.bash new file mode 100755 index 000000000..750ddb5cf --- /dev/null +++ b/scripts/ops/armadilloctl.bash @@ -0,0 +1,184 @@ +#!/usr/bin/env bash + +CURL_OPTS=--silent + +OK="\033[32m" +WARN="\033[33m" +ERR="\033[31m" +B="\033[0m" + +success() { + echo -e "${OK}${1}${B}" +} + +warning() { + echo -e "WARNING: ${WARN}${1}${B}" +} + +error() { + echo -e "ERROR: ${ERR}${1}${B}" + exit 1 +} + +is_armadillo_running() { + cmd="${ARMADILLO_URL}" + curl $CURL_OPTS --request "GET" "${cmd}" > /dev/null || (error "Armadillo not running."; exit 1) +} + +get_profiles() { + cmd="$ARMADILLO_URL/ds-profiles" + profile_names=$(curl $CURL_OPTS --user "${CREDENTIALS}" --request "GET" --header "accept: application/json" "${cmd}" | jq -r '.[] | "\(.name)"') +} + +status() { + if [ -z "$1" ]; then + error "$0 needs profile name. Or try ${0}All" + fi + name=$1 + + cmd="${ARMADILLO_URL}/ds-profiles/{$name}" + stats=$(curl $CURL_OPTS --user "${CREDENTIALS}" --request "GET" --header "accept: application/json" "${cmd}" | jq -r '"\(.name) = \(.container.status)"') + success "$stats" +} + +start() { + if [ -z "$1" ]; then + error "$0 needs profile name. Or try ${0}All" + fi + + profile="$1" + cmd="$ARMADILLO_URL/ds-profiles/$profile/start" + echo "Starting '$profile' on $cmd" + + curl $CURL_OPTS --user $CREDENTIALS --request "POST" "$cmd" --data "" +} + +stop() { + if [ -z "$1" ]; then + error "$0 needs profile name. Or try ${0}All" + fi + + profile="$1" + cmd="$ARMADILLO_URL/ds-profiles/$profile/stop" + echo "Stopping '$profile' on $cmd" + + curl $CURL_OPTS --user $CREDENTIALS --request "POST" $cmd --data "" +} + +restart() { + if [ -z "$1" ]; then + error "$0 needs profile name. Or try ${0}All" + fi + + profile=$1 + echo "Restarting $profile" + stop "$profile" + sleep 5 + start "$profile" + sleep 5 + status "$profile" + +} + +is_auto_start() { + if [[ $ARMADILLO_PROFILES_AUTOSTART =~ (^|[[:space:]])$1($|[[:space:]]) ]] + then + return 0 + else + return 1 + fi +} + +doAll() { + command=$1 + get_profiles + + echo "${profile_names}" | while read -r item; do + "$command" "${item}" + done +} + +statusAll() { + doAll status +} + +startAll() { + doAll start +} + +stopAll() { + doAll stop +} + +restartAll() { + doAll stop + sleep 5 + doAll start +} + +autoStart() { + get_profiles + echo "Auto starting ..." + echo "${profile_names}" | while read -r item + do + if is_auto_start "${item}" + then + start "${item}" + fi + done + statusAll +} + +check_dependencies() { + if ! which jq > /dev/null ; then + echo "Please install jq for json parsing ... exiting" + exit 1 + fi +} + +var_found() { + echo "Variable $1 found ..." +} + +var_empty() { + warning "Variable $1 not set! ... exiting" + exit 1 +} + +all_set() { + [[ -n "$ARMADILLO_URL" ]] && var_found ARMADILLO_URL + [[ -z "$ARMADILLO_URL" ]] && var_empty ARMADILLO_URL + + [[ -n "$ARMADILLO_ADMIN_USER" ]] && var_found ARMADILLO_ADMIN_USER + [[ -z "$ARMADILLO_ADMIN_USER" ]] && var_empty ARMADILLO_ADMIN_USER + + [[ -n "$ARMADILLO_ADMIN_PASSWORD" ]] && var_found ARMADILLO_ADMIN_PASSWORD + [[ -z "$ARMADILLO_ADMIN_PASSWORD" ]] && var_empty ARMADILLO_ADMIN_PASSWORD + + # Set to all if not set with value. + [[ -n "${ARMADILLO_PROFILES_AUTOSTART}" ]] && var_found ARMADILLO_PROFILES_AUTOSTART + [[ -z "${ARMADILLO_PROFILES_AUTOSTART}" ]] && ARMADILLO_PROFILES_AUTOSTART="__ALL__" + + CREDENTIALS="${ARMADILLO_ADMIN_USER}:${ARMADILLO_ADMIN_PASSWORD}" + + echo "" + echo "Armadillo settings:" + echo " ARMADILLO_URL : ${ARMADILLO_URL}" + echo " ARMADILLO_ADMIN_USER : ${ARMADILLO_ADMIN_USER}" + echo " ARMADILLO_PROFILES_AUTOSTART : ${ARMADILLO_PROFILES_AUTOSTART}" +} + +check_dependencies || exit + +all_set || exit + +is_armadillo_running || exit + +get_profiles + +if [[ "$1" =~ ^(status|start|stop|restart|statusAll|startAll|stopAll|restartAll|autoStart)$ ]]; then + "$@" +else + warning "Please provide one of the following arguments: status | start | stop | restart | statusAll | startAll | stopAll | restartAll | autoStart" + error "Got argument '$1'" +fi diff --git a/scripts/ops/env.dist b/scripts/ops/env.dist new file mode 100644 index 000000000..712f423b4 --- /dev/null +++ b/scripts/ops/env.dist @@ -0,0 +1,8 @@ +# copy this file to ie "/etc/armadillo/acc.env" + +export ARMADILLO_URL=http://localhost:8080 +export ARMADILLO_ADMIN_USER=admin +export ARMADILLO_ADMIN_PASSWORD=admin + +# Space separated values between double quotes. Leaving empty falls back to all profiles. +export ARMADILLO_PROFILES_AUTOSTART="default rock" diff --git a/scripts/ops/test_armadilloctl.bash b/scripts/ops/test_armadilloctl.bash new file mode 100755 index 000000000..03007166e --- /dev/null +++ b/scripts/ops/test_armadilloctl.bash @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +OUT=/dev/stdout +if [ -z "$1" ]; then + OUT="/dev/null" +fi + +usage() { + echo 'bash -c "source dev.env ; ./test_armadilloctl.bash" || echo FAILED' +} + +colors() { + for c in {0..255}; do + printf "\033[48;5;%sm%3d\033[0m " "$c" "$c" + if (( c == 15 )) || (( c > 15 )) && (( (c-15) % 6 == 0 )); then + printf "\n" + fi + done +} + +OK="\033[32m" +WARN="\033[33m" +ERR="\033[31m" +B="\033[0m" + +error() { + echo -e "TEST:: ERROR: ${ERR}${1}${B}" +} + +warning() { + echo -e "TEST:: WARNING: ${WARN}${1}${B}" +} + +success() { + echo -e "TEST:: SUCCES: ${OK}${1}${B}" +} + + +failed() { + warn $0 +} +do_sleep() { + warning "Pausing for $1 seconds before '$2'." + sleep "$1" + echo "..." +} + +error "NOTE: controller exit values are incomplete ... needs eyes" +warning "Make sure Armadillo is running" + +./armadilloctl.bash > $OUT || success "Needs a command." + +./armadilloctl.bash status > $OUT || success "status needs profile name" +./armadilloctl.bash statusAll > $OUT && success "statusAll needs running Armadillo" + +./armadilloctl.bash stopAll > $OUT && success "stopAll needs running Armadillo" + +do_sleep 5 "autoStart" +./armadilloctl.bash autoStart > $OUT && success "autoStart needs running Armadillo" + +do_sleep 5 "startAll" +./armadilloctl.bash startAll > $OUT && success "startAll needs running Armadillo" + +do_sleep 5 "restartAll" +./armadilloctl.bash restartAll > $OUT && success "restartAll needs running Armadillo" + +# colors