321 lines
9.1 KiB
Bash
Executable File
321 lines
9.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config"
|
|
set -eo pipefail
|
|
[[ $DOKKU_TRACE ]] && set -x
|
|
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions"
|
|
export SUBCOMMAND_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands"
|
|
|
|
fn-help() {
|
|
declare CMD="$1"
|
|
local cmd EXIT_CODE
|
|
|
|
if [[ "$CMD" == "help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]]; then
|
|
fn-help-all "$@"
|
|
exit 0
|
|
fi
|
|
|
|
pushd "$SUBCOMMAND_ROOT" >/dev/null 2>&1
|
|
for cmd in *; do
|
|
if [[ "$CMD" == "${PLUGIN_COMMAND_PREFIX}:$cmd" ]]; then
|
|
"$SUBCOMMAND_ROOT/$cmd" "$@"
|
|
EXIT_CODE="$?"
|
|
exit "$EXIT_CODE"
|
|
fi
|
|
done
|
|
popd >/dev/null 2>&1
|
|
|
|
exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
|
}
|
|
|
|
fn-help-all() {
|
|
declare CMD="$1" SUBCOMMAND="$2"
|
|
local CMD_OUTPUT BLUE BOLD FULL_OUTPUT NORMAL
|
|
FULL_OUTPUT=true
|
|
|
|
if [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]]; then
|
|
BOLD="$(fn-help-fancy-tput bold)"
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
BLUE="$(fn-help-fancy-color "\033[0;34m")"
|
|
CYAN="$(fn-help-fancy-color "\033[1;36m")"
|
|
if [[ -n "$SUBCOMMAND" ]] && [[ "$SUBCOMMAND" != "--all" ]]; then
|
|
fn-help-contents-subcommand "$SUBCOMMAND" "$FULL_OUTPUT"
|
|
return "$?"
|
|
fi
|
|
|
|
echo -e "${BOLD}usage${NORMAL}: dokku ${PLUGIN_COMMAND_PREFIX}[:COMMAND]"
|
|
echo ''
|
|
echo -e "${BOLD}List your $PLUGIN_COMMAND_PREFIX services.${NORMAL}"
|
|
echo ''
|
|
echo -e "${BLUE}Example:${NORMAL}"
|
|
echo ''
|
|
echo " \$ dokku $PLUGIN_COMMAND_PREFIX:list"
|
|
echo ''
|
|
fn-help-list-example | column -c5 -t -s,
|
|
echo ''
|
|
echo -e "dokku ${BOLD}${PLUGIN_COMMAND_PREFIX}${NORMAL} commands: (get help with ${CYAN}dokku ${PLUGIN_COMMAND_PREFIX}:help SUBCOMMAND${NORMAL})"
|
|
echo ''
|
|
fn-help-contents | sort | column -c2 -t -s,
|
|
echo ''
|
|
elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then
|
|
fn-help-contents
|
|
else
|
|
cat <<help_desc
|
|
$PLUGIN_COMMAND_PREFIX, Plugin for managing $PLUGIN_SERVICE services
|
|
help_desc
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
fn-help-contents() {
|
|
pushd "$SUBCOMMAND_ROOT" >/dev/null 2>&1
|
|
for cmd in *; do
|
|
fn-help-contents-subcommand "$cmd" || true
|
|
done
|
|
}
|
|
|
|
fn-help-contents-subcommand() {
|
|
declare SUBCOMMAND="$1" FULL_OUTPUT="$2"
|
|
local HELP_TMPDIR=$(mktemp -d --tmpdir)
|
|
local UNCLEAN_FILE="${HELP_TMPDIR}/cmd-unclean" CLEAN_FILE="${HELP_TMPDIR}/cmd-clean"
|
|
local BOLD CMD_OUTPUT CYAN EXAMPLE LIGHT_GRAY NORMAL
|
|
trap 'rm -rf "$HELP_TMPDIR" > /dev/null' RETURN INT TERM EXIT
|
|
|
|
rm -rf "$UNCLEAN_FILE" "$CLEAN_FILE"
|
|
cat "$SUBCOMMAND_ROOT/$SUBCOMMAND" >"$UNCLEAN_FILE"
|
|
|
|
fn-help-subcommand-sanitize "$UNCLEAN_FILE" "$CLEAN_FILE"
|
|
if ! is_implemented_command "$SUBCOMMAND"; then
|
|
return 1
|
|
fi
|
|
|
|
args="$(fn-help-subcommand-args "$CLEAN_FILE" "$FULL_OUTPUT")"
|
|
SUBCOMMAND=":$SUBCOMMAND"
|
|
[[ "$SUBCOMMAND" == ":default" ]] && SUBCOMMAND=""
|
|
cmd_line="$(echo -e "${SUBCOMMAND} ${args}" | sed -e 's/[[:space:]]*$//')"
|
|
desc="$(grep desc "$CLEAN_FILE" | head -1)"
|
|
eval "$desc"
|
|
|
|
BLUE="$(fn-help-fancy-color "\033[0;34m")"
|
|
BOLD="$(fn-help-fancy-tput bold)"
|
|
CYAN="$(fn-help-fancy-color "\033[1;36m")"
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")"
|
|
LIGHT_RED="$(fn-help-fancy-color "\033[1;31m")"
|
|
CMD_OUTPUT="$(echo -e " ${PLUGIN_COMMAND_PREFIX}${cmd_line}, ${LIGHT_GRAY}${desc}${NORMAL}")"
|
|
if [[ "$FULL_OUTPUT" != "true" ]]; then
|
|
echo "$CMD_OUTPUT"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${BOLD}usage:${NORMAL} dokku ${PLUGIN_COMMAND_PREFIX}${cmd_line}"
|
|
echo ''
|
|
echo -e "${BOLD}${desc}${NORMAL}"
|
|
echo ''
|
|
|
|
ARGS="$(fn-help-subcommand-list-args "$CLEAN_FILE")"
|
|
if [[ -n "$ARGS" ]]; then
|
|
echo -e "${CYAN}arguments:${NORMAL}"
|
|
echo ''
|
|
echo "$ARGS" | column -c2 -t -s,
|
|
echo ''
|
|
fi
|
|
|
|
FLAGS="$(fn-help-subcommand-list-flags "$CLEAN_FILE")"
|
|
if [[ -n "$FLAGS" ]]; then
|
|
echo -e "${BLUE}flags:${NORMAL}"
|
|
echo ''
|
|
echo "$FLAGS" | column -c2 -t -s,
|
|
echo ''
|
|
fi
|
|
|
|
EXAMPLE="$(fn-help-subcommand-example "$CLEAN_FILE")"
|
|
if [[ -n "$EXAMPLE" ]]; then
|
|
echo -e "${LIGHT_RED}examples:${NORMAL}"
|
|
echo ''
|
|
echo "$EXAMPLE"
|
|
echo ''
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
fn-help-fancy-tput() {
|
|
declare desc="a wrapper around tput"
|
|
|
|
if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" == "unknown" ]] || [[ "$TERM" == "dumb" ]]; then
|
|
return
|
|
fi
|
|
|
|
tput "$@"
|
|
}
|
|
|
|
fn-help-fancy-color() {
|
|
declare desc="a wrapper around colors"
|
|
|
|
if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" == "unknown" ]] || [[ "$TERM" == "dumb" ]]; then
|
|
return
|
|
fi
|
|
|
|
echo "$@"
|
|
}
|
|
|
|
fn-help-list-example() {
|
|
# shellcheck disable=SC2034
|
|
declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content"
|
|
cat <<help_list
|
|
$PLUGIN_SERVICE services
|
|
service-name
|
|
help_list
|
|
}
|
|
|
|
fn-help-subcommand-args() {
|
|
declare FUNC_FILE="$1" FULL_OUTPUT="$2"
|
|
local argline arglist args argpos BLUE NORMAL
|
|
|
|
if [[ "$FULL_OUTPUT" == "true" ]]; then
|
|
BLUE="$(fn-help-fancy-color "\033[0;34m")"
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
fi
|
|
argline=$(grep declare "$FUNC_FILE" | grep -v "declare desc" | head -1 || true)
|
|
arglist=($(echo -e "${argline// /"\n"}" | awk -F= '/=/{print ""$1""}'))
|
|
args=""
|
|
argpos=0
|
|
for arg in "${arglist[@]}"; do
|
|
argpos=$((argpos + 1))
|
|
if [[ "$FULL_OUTPUT" != "true" ]] && [[ "$argpos" == 4 ]]; then
|
|
args+="..."
|
|
break
|
|
fi
|
|
|
|
if [[ "$arg" == *_FLAG ]]; then
|
|
arg="${arg/_FLAG/}"
|
|
if [[ $arg == "INFO" ]]; then
|
|
arg="SINGLE_INFO_FLAG"
|
|
args+=" ${BLUE}[--${arg//_/-}]${NORMAL}"
|
|
else
|
|
args+=" ${BLUE}[-${arg:0:1}|--${arg//_/-}]${NORMAL}"
|
|
fi
|
|
elif [[ "$arg" == *_FLAGS_LIST ]]; then
|
|
arg=${arg%_*}
|
|
args+=" [--${arg//_/-}...]"
|
|
elif [[ "$arg" == *_LIST ]]; then
|
|
arg=${arg%_*}
|
|
args+=" <${arg//_/-}...>"
|
|
elif [[ "$arg" == *_OPTIONAL ]]; then
|
|
argName="${arg/_OPTIONAL/}"
|
|
args+=" [<${argName//_/-}>]"
|
|
else
|
|
args+=" <${arg//_/-}>"
|
|
fi
|
|
done
|
|
args=$(echo "$args" | tr "\n" " ")
|
|
# shellcheck disable=SC2001
|
|
echo "${args,,}" | sed -e 's/^[[:space:]]*//'
|
|
}
|
|
|
|
fn-help-subcommand-example() {
|
|
declare FUNC_FILE="$1"
|
|
local EXAMPLE
|
|
|
|
EXAMPLE=$(grep "#E" "$FUNC_FILE" | cut -d' ' -f2- || true)
|
|
if [[ -z "$EXAMPLE" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
BOLD="$(fn-help-fancy-tput bold)"
|
|
LAST_LINE=""
|
|
LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")"
|
|
OTHER_GRAY="$(fn-help-fancy-color "\033[7;37m")"
|
|
NEWLINE=""
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
_fn-help-apply-shell-expansion "$EXAMPLE" | while read -r line; do
|
|
line="$(echo "$line" | cut -c 4-)"
|
|
if [[ "$line" == export* ]] || [[ "$line" == dokku* ]]; then
|
|
[[ "$LAST_LINE" == "command" ]] && NEWLINE=""
|
|
[[ "$LAST_LINE" == "sentence" ]] && NEWLINE="\n"
|
|
echo -e "${NEWLINE} ${LIGHT_GRAY}${line}${NORMAL}"
|
|
LAST_LINE="command"
|
|
else
|
|
[[ "$LAST_LINE" == "command" ]] && NEWLINE="\n"
|
|
[[ "$LAST_LINE" == "sentence" ]] && NEWLINE=""
|
|
[[ "$line" == \>* ]] && line="\n ${BOLD}${line}${NORMAL}"
|
|
# shellcheck disable=SC2001
|
|
[[ "$line" == " "* ]] && line=" ${OTHER_GRAY}$(echo "$line" | sed -e 's/^[[:space:]]*//')${NORMAL}"
|
|
echo -e "${NEWLINE}${line}"
|
|
LAST_LINE="sentence"
|
|
NEWLINE="\n"
|
|
fi
|
|
done
|
|
}
|
|
|
|
fn-help-subcommand-list-args() {
|
|
declare FUNC_FILE="$1"
|
|
local EXAMPLE LIGHT_GRAY NORMAL
|
|
|
|
FLAGS=$(grep "#A" "$FUNC_FILE" | cut -d'A' -f2- | sed -e 's/^[[:space:]]*//' || true)
|
|
if [[ -z "$FLAGS" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")"
|
|
|
|
_fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do
|
|
echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}"
|
|
done
|
|
}
|
|
|
|
fn-help-subcommand-list-flags() {
|
|
declare FUNC_FILE="$1"
|
|
local EXAMPLE LIGHT_GRAY NORMAL
|
|
|
|
FLAGS=$(grep "#F" "$FUNC_FILE" | cut -d'F' -f2- | sed -e 's/^[[:space:]]*//' || true)
|
|
if [[ -z "$FLAGS" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
NORMAL="$(fn-help-fancy-color "\033[m")"
|
|
LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")"
|
|
|
|
_fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do
|
|
echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}"
|
|
done
|
|
}
|
|
|
|
fn-help-subcommand-sanitize() {
|
|
declare FUNC_FILE="$1" OUTGOING_FUNC_FILE="$2"
|
|
local FUNCTION_FOUND=false
|
|
local IFS OIFS
|
|
|
|
touch "$OUTGOING_FUNC_FILE"
|
|
|
|
OIFS="$IFS"
|
|
IFS=,
|
|
while read -r p; do
|
|
IFS="$OIFS"
|
|
if [[ "$p" == *"-cmd \"\$@\""* ]] || [[ "$p" == "" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "$FUNCTION_FOUND" == true ]]; then
|
|
echo "$p" >>"$OUTGOING_FUNC_FILE"
|
|
continue
|
|
fi
|
|
|
|
if [[ "$p" == *"()"* ]]; then
|
|
FUNCTION_FOUND=true
|
|
echo "$p" >>"$OUTGOING_FUNC_FILE"
|
|
continue
|
|
fi
|
|
done <"$FUNC_FILE"
|
|
}
|
|
|
|
_fn-help-apply-shell-expansion() {
|
|
declare desc="expand environment variables for a shell command"
|
|
declare data="$1"
|
|
declare delimiter="__apply_shell_expansion_delimiter__"
|
|
declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter"
|
|
eval "$command"
|
|
}
|