From b01fee3c86c639f07ceff6a33091f37699e7664d Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Tue, 22 Sep 2020 16:04:28 +0200 Subject: [PATCH] Add -e, -c and ABRA_STACK_DIR options.. ..and tidy up a little --- abra | 170 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 59 deletions(-) diff --git a/abra b/abra index 7f02436..f0e9f9b 100755 --- a/abra +++ b/abra @@ -1,22 +1,18 @@ #!/bin/bash PROGRAM_NAME=$(basename "$0") -ABRA_CONFIG=abra.yml -if [ -z "$COMPOSE_FILE" ]; then - COMPOSE_FILE="compose.yml" -fi +###### Utility functions yml_pattern_exists() { PATTERN=$1 if ! type yq > /dev/null 2>&1; then - echo "$(tput setaf 1)ERROR: yq program is not installed$(tput sgr0)" - exit + error "yq program is not installed" fi - if [ -f $ABRA_CONFIG ]; then - RESULT=$(yq read $ABRA_CONFIG "$PATTERN") + if [ -f "$ABRA_CONFIG" ]; then + RESULT=$(yq read "$ABRA_CONFIG" "$PATTERN") if [ "$RESULT" != 0 ]; then return 0 @@ -26,55 +22,124 @@ yml_pattern_exists() { return 1 } +parse_subcommand() { + SUBCOMMAND="$1" + PREFIX=$2 + + if [ -n "$PREFIX" ]; then + PPREFIX="_$2" + SPREFIX="$2 " + SSPREFIX=" $2" + fi + + case $SUBCOMMAND in + "" | "-h" | "--help") + "sub${PPREFIX}_help" + ;; + *) + shift 2 + "sub${PPREFIX}_${SUBCOMMAND}" "$@" + if [ $? = 127 ]; then + echo "Error: '$SPREFIX$SUBCOMMAND' is not a known subcommand." >&2 + echo " Run '$PROGRAM_NAME$SSPREFIX --help' for a list of known subcommands." >&2 + exit 1 + fi + ;; + esac +} + +error() { + echo "$(tput setaf 1)ERROR: $*$(tput sgr0)" + exit +} + +###### Top-level arguments + +ABRA_CONFIG=abra.yml +if [ "$1" == "-c" ]; then + ABRA_CONFIG=$2 + shift 2 +fi + +if [ "$1" == "-e" ]; then + ABRA_ENV=$2 + shift 2 +fi + if [ "$1" == "-a" ]; then STACK_NAME=$2 shift 2 fi -if [ -f abra.yml ]; then +###### Load config + +if [ -f "$ABRA_CONFIG" ]; then if yml_pattern_exists stack_name; then - STACK_NAME=$(yq read abra.yml stack_name) + STACK_NAME=$(yq read "$ABRA_CONFIG" stack_name) fi + # FIXME load other variables somehow fi +if [ -n "$ABRA_ENV" ]; then + # shellcheck disable=SC1090 + source "$ABRA_ENV" +fi + +###### Default settings + +if [ -z "$COMPOSE_FILE" ]; then + COMPOSE_FILE="compose.yml" +fi + +if [ -z "$ABRA_STACK_DIR" ]; then + ABRA_STACK_DIR="../stacks/$SERVICE" +fi + +###### Safety checks + if [ -z "$STACK_NAME" ]; then - echo "$(tput setaf 1)ERROR: \$STACK_NAME must be set (e.g. export STACK_NAME=my_cool_app)$(tput sgr0 )" - exit + error "no stack_name, export \$STACK_NAME=my_cool_app or add it to abra.yml" fi -if type direnv > /dev/null 2>&1 && ! direnv status | grep -q 'Found RC allowed true'; then - echo "$(tput setaf 1)ERROR: direnv is blocked, run direnv allow$(tput sgr0)" - exit +if [ -z "$ABRA_ENV" ] && [ -f .envrc ] && type direnv > /dev/null 2>&1 && ! direnv status | grep -q 'Found RC allowed true'; then + error "direnv is blocked, run direnv allow" fi +###### Custom commands + if [ -f abra-commands.sh ]; then # shellcheck disable=SC1091 - . abra-commands.sh + source abra-commands.sh fi +###### Global help + sub_help() { - echo "Usage: $PROGRAM_NAME [-a STACK_NAME] [options]" + echo "Usage: $PROGRAM_NAME [-a STACK_NAME] [-c CONFIG] [-e ENV_FILE] [options]" echo "" echo "Subcommands:" + echo " context [--help] [SUBCOMMAND] manage remote swarm contexts" echo " cp SRC_PATH SERVICE:DEST_PATH copy files to a container" echo " deploy let 'em rip" echo " logs SERVICE [ARGS] tail logs from a deployed service" echo " run SERVICE CMD run a command in the specified service's container" echo " run_args SERVICE ARGS CMD run, passing extra args to docker exec" - echo " secret_generate SECRET VERSION [CMD] generate a secret, store it in pass & as a Docker secret" + echo " secret [--help] [SUBCOMMAND] manage secrets" echo " upgrade upgrade to the latest version" echo " ... (custom commands)" echo "" - echo "Make sure \$STACK_NAME is set using direnv or -a" + echo "Make sure \$STACK_NAME is set using direnv, -a, -e or -c" echo "" echo "Runs compose.yml by default, set e.g. COMPOSE_FILE=\"compose.yml:compose2.yml\" to override" } +###### Subcommand `secret` + sub_secret_help() { echo "Usage: $PROGRAM_NAME [-a STACK_NAME] secret [options]" echo "" echo "Subcommands:" - echo " generate [PW] generate & store secret" + echo " generate SECRET VERSION [PW] generate & store secret" } sub_secret_generate(){ @@ -99,6 +164,8 @@ sub_secret() { parse_subcommand "$SUBCOMMAND" "secret" $@ } +###### Subcommand `run` + sub_run_args(){ SERVICE=$1 DOCKER_ARGS=$2 @@ -132,9 +199,11 @@ sub_run(){ sub_run_args "$SERVICE" "" "$@" } +###### Subcommand `deploy` + sub_deploy (){ echo "About to deploy:" - echo " Compose: $(tput setaf 3)${PWD}/${COMPOSE_FILE}$(tput sgr0)" + echo " Compose: $(tput setaf 3)${ABRA_STACK_DIR}/${COMPOSE_FILE}$(tput sgr0)" if [ -n "$DOMAIN" ]; then echo " Domain: $(tput setaf 2)${DOMAIN}$(tput sgr0)" fi @@ -148,18 +217,23 @@ sub_deploy (){ * ) return;; esac - # shellcheck disable=SC2086 - if docker stack deploy -c ${COMPOSE_FILE/:/ -c } "$STACK_NAME"; then - if [ -n "$DOMAIN" ]; then - echo "$(tput setaf 2)Yay! App should be available at https://${DOMAIN}$(tput sgr0)" + ( + cd "$ABRA_STACK_DIR" || error "\$ABRA_STACK_DIR '$ABRA_STACK_DIR' not found" + # shellcheck disable=SC2086 + if docker stack deploy -c ${COMPOSE_FILE/:/ -c } "$STACK_NAME"; then + if [ -n "$DOMAIN" ]; then + echo "$(tput setaf 2)Yay! App should be available at https://${DOMAIN}$(tput sgr0)" + else + echo "$(tput setaf 2)Yay! That worked. No \$DOMAIN defined, check logs.(tput sgr0)" + fi else - echo "$(tput setaf 2)Yay! That worked. No \$DOMAIN defined, check logs.(tput sgr0)" + error "Oh no! Something went wrong 😕 Check errors above" fi - else - echo "$(tput setaf 1)Oh no! Something went wrong 😕 Check errors above$(tput sgr0)" - fi + ) } +###### Subcommand `logs` + sub_logs (){ SERVICE=$1 @@ -180,6 +254,8 @@ sub_logs (){ docker service logs "${STACK_NAME}_${SERVICE}" $LOGS_ARGS } +###### Subcommand `cp` + sub_cp() { SOURCE=$1 DEST=$2 @@ -188,18 +264,17 @@ sub_cp() { SERVICE=$(echo "$SERVICE" | tr -d ':') if [ -z "$SERVICE" ]; then - echo "$(tput setaf 1)ERROR: Can't find SERVICE in either SRC or DEST$(tput sgr0)" - echo "" echo "Usage: $PROGRAM_NAME cp SERVICE:SRC_PATH DEST_PATH" echo " $PROGRAM_NAME cp SRC_PATH SERVICE:DEST_PATH" - exit + echo "" + error "Can't find SERVICE in either SRC or DEST" fi CONTAINER=$(docker container ls --format "table {{.ID}},{{.Names}}" \ | grep "${STACK_NAME}_${SERVICE}" | cut -d',' -f1) if [ -z "$CONTAINER" ]; then - echo "$(tput setaf 1)ERROR: Can't find a ${STACK_NAME}_${SERVICE}$(tput sgr0)" + error "Can't find a ${STACK_NAME}_${SERVICE}" exit fi @@ -209,6 +284,8 @@ sub_cp() { docker cp $CP_ARGS } +###### Subcommand `context` + sub_context_help() { echo "Usage: $PROGRAM_NAME [-a STACK_NAME] context [options]" echo "" @@ -249,34 +326,9 @@ sub_context() { parse_subcommand "$SUBCOMMAND2" "context" $@ } -parse_subcommand() { - SUBCOMMAND="$1" - PREFIX=$2 - - if [ -n "$PREFIX" ]; then - PPREFIX="_$2" - SPREFIX="$2 " - SSPREFIX=" $2" - fi - - case $SUBCOMMAND in - "" | "-h" | "--help") - "sub${PPREFIX}_help" - ;; - *) - shift 2 - "sub${PPREFIX}_${SUBCOMMAND}" "$@" - if [ $? = 127 ]; then - echo "Error: '$SPREFIX$SUBCOMMAND' is not a known subcommand." >&2 - echo " Run '$PROGRAM_NAME$SSPREFIX --help' for a list of known subcommands." >&2 - exit 1 - fi - ;; - esac -} +###### Main SUBCOMMAND=$1 shift - # shellcheck disable=SC2086,SC2068 parse_subcommand $SUBCOMMAND "" $@