Add -e, -c and ABRA_STACK_DIR options..

..and tidy up a little
This commit is contained in:
3wc 2020-09-22 16:04:28 +02:00
parent f4798bf3bd
commit 1d52c0f5ed
1 changed files with 111 additions and 59 deletions

170
abra
View File

@ -1,22 +1,18 @@
#!/bin/bash #!/bin/bash
PROGRAM_NAME=$(basename "$0") PROGRAM_NAME=$(basename "$0")
ABRA_CONFIG=abra.yml
if [ -z "$COMPOSE_FILE" ]; then ###### Utility functions
COMPOSE_FILE="compose.yml"
fi
yml_pattern_exists() { yml_pattern_exists() {
PATTERN=$1 PATTERN=$1
if ! type yq > /dev/null 2>&1; then if ! type yq > /dev/null 2>&1; then
echo "$(tput setaf 1)ERROR: yq program is not installed$(tput sgr0)" error "yq program is not installed"
exit
fi fi
if [ -f $ABRA_CONFIG ]; then if [ -f "$ABRA_CONFIG" ]; then
RESULT=$(yq read $ABRA_CONFIG "$PATTERN") RESULT=$(yq read "$ABRA_CONFIG" "$PATTERN")
if [ "$RESULT" != 0 ]; then if [ "$RESULT" != 0 ]; then
return 0 return 0
@ -26,54 +22,123 @@ yml_pattern_exists() {
return 1 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 if [ "$1" == "-a" ]; then
STACK_NAME=$2 STACK_NAME=$2
shift 2 shift 2
fi fi
if [ -f abra.yml ]; then ###### Load config
if [ -f "$ABRA_CONFIG" ]; then
if yml_pattern_exists stack_name; 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 fi
# FIXME load other variables somehow
fi 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 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 )" error "no stack_name, export \$STACK_NAME=my_cool_app or add it to abra.yml"
exit
fi fi
if type direnv > /dev/null 2>&1 && ! direnv status | grep -q 'Found RC allowed true'; then if [ -z "$ABRA_ENV" ] && [ -f .envrc ] && 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)" error "direnv is blocked, run direnv allow"
exit
fi fi
###### Custom commands
if [ -f abra-commands.sh ]; then if [ -f abra-commands.sh ]; then
# shellcheck disable=SC1091 # shellcheck disable=SC1091
. abra-commands.sh source abra-commands.sh
fi fi
###### Global help
sub_help() { sub_help() {
echo "Usage: $PROGRAM_NAME [-a STACK_NAME] <subcommand> [options]" echo "Usage: $PROGRAM_NAME [-a STACK_NAME] [-c CONFIG] [-e ENV_FILE] <subcommand> [options]"
echo "" echo ""
echo "Subcommands:" echo "Subcommands:"
echo " context [--help] [SUBCOMMAND] manage remote swarm contexts"
echo " cp SRC_PATH SERVICE:DEST_PATH copy files to a container" echo " cp SRC_PATH SERVICE:DEST_PATH copy files to a container"
echo " deploy let 'em rip" echo " deploy let 'em rip"
echo " logs SERVICE [ARGS] tail logs from a deployed service" 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 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 " 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 " ... (custom commands)" echo " ... (custom commands)"
echo "" 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 ""
echo "Runs compose.yml by default, set e.g. COMPOSE_FILE=\"compose.yml:compose2.yml\" to override" echo "Runs compose.yml by default, set e.g. COMPOSE_FILE=\"compose.yml:compose2.yml\" to override"
} }
###### Subcommand `secret`
sub_secret_help() { sub_secret_help() {
echo "Usage: $PROGRAM_NAME [-a STACK_NAME] secret <subcommand> [options]" echo "Usage: $PROGRAM_NAME [-a STACK_NAME] secret <subcommand> [options]"
echo "" echo ""
echo "Subcommands:" echo "Subcommands:"
echo " generate [PW] generate & store secret" echo " generate SECRET VERSION [PW] generate & store secret"
} }
sub_secret_generate(){ sub_secret_generate(){
@ -98,6 +163,8 @@ sub_secret() {
parse_subcommand "$SUBCOMMAND" "secret" $@ parse_subcommand "$SUBCOMMAND" "secret" $@
} }
###### Subcommand `run`
sub_run_args(){ sub_run_args(){
SERVICE=$1 SERVICE=$1
DOCKER_ARGS=$2 DOCKER_ARGS=$2
@ -131,9 +198,11 @@ sub_run(){
sub_run_args "$SERVICE" "" "$@" sub_run_args "$SERVICE" "" "$@"
} }
###### Subcommand `deploy`
sub_deploy (){ sub_deploy (){
echo "About to 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 if [ -n "$DOMAIN" ]; then
echo " Domain: $(tput setaf 2)${DOMAIN}$(tput sgr0)" echo " Domain: $(tput setaf 2)${DOMAIN}$(tput sgr0)"
fi fi
@ -147,18 +216,23 @@ sub_deploy (){
* ) return;; * ) return;;
esac esac
# shellcheck disable=SC2086 (
if docker stack deploy -c ${COMPOSE_FILE/:/ -c } "$STACK_NAME"; then cd "$ABRA_STACK_DIR" || error "\$ABRA_STACK_DIR '$ABRA_STACK_DIR' not found"
if [ -n "$DOMAIN" ]; then # shellcheck disable=SC2086
echo "$(tput setaf 2)Yay! App should be available at https://${DOMAIN}$(tput sgr0)" 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 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 fi
else )
echo "$(tput setaf 1)Oh no! Something went wrong 😕 Check errors above$(tput sgr0)"
fi
} }
###### Subcommand `logs`
sub_logs (){ sub_logs (){
SERVICE=$1 SERVICE=$1
@ -179,6 +253,8 @@ sub_logs (){
docker service logs "${STACK_NAME}_${SERVICE}" $LOGS_ARGS docker service logs "${STACK_NAME}_${SERVICE}" $LOGS_ARGS
} }
###### Subcommand `cp`
sub_cp() { sub_cp() {
SOURCE=$1 SOURCE=$1
DEST=$2 DEST=$2
@ -187,18 +263,17 @@ sub_cp() {
SERVICE=$(echo "$SERVICE" | tr -d ':') SERVICE=$(echo "$SERVICE" | tr -d ':')
if [ -z "$SERVICE" ]; then 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 "Usage: $PROGRAM_NAME cp SERVICE:SRC_PATH DEST_PATH"
echo " $PROGRAM_NAME cp SRC_PATH SERVICE:DEST_PATH" echo " $PROGRAM_NAME cp SRC_PATH SERVICE:DEST_PATH"
exit echo ""
error "Can't find SERVICE in either SRC or DEST"
fi fi
CONTAINER=$(docker container ls --format "table {{.ID}},{{.Names}}" \ CONTAINER=$(docker container ls --format "table {{.ID}},{{.Names}}" \
| grep "${STACK_NAME}_${SERVICE}" | cut -d',' -f1) | grep "${STACK_NAME}_${SERVICE}" | cut -d',' -f1)
if [ -z "$CONTAINER" ]; then 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 exit
fi fi
@ -208,6 +283,8 @@ sub_cp() {
docker cp $CP_ARGS docker cp $CP_ARGS
} }
###### Subcommand `context`
sub_context_help() { sub_context_help() {
echo "Usage: $PROGRAM_NAME [-a STACK_NAME] context <subcommand> [options]" echo "Usage: $PROGRAM_NAME [-a STACK_NAME] context <subcommand> [options]"
echo "" echo ""
@ -244,34 +321,9 @@ sub_context() {
parse_subcommand "$SUBCOMMAND2" "context" $@ parse_subcommand "$SUBCOMMAND2" "context" $@
} }
parse_subcommand() { ###### Main
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
}
SUBCOMMAND=$1 SUBCOMMAND=$1
shift shift
# shellcheck disable=SC2086,SC2068 # shellcheck disable=SC2086,SC2068
parse_subcommand $SUBCOMMAND "" $@ parse_subcommand $SUBCOMMAND "" $@