subcommand restructure and bashstyle refactor. closes #1579

This commit is contained in:
Michael S. Hobbs
2016-03-01 13:26:35 -08:00
committed by Michael Hobbs
parent 76e27f0333
commit 89f289b433
105 changed files with 1969 additions and 1306 deletions

View File

@@ -2,6 +2,7 @@
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
has_tty() {
local desc="return 0 if we have a tty"
if [[ "$(/usr/bin/tty || true)" == "not a tty" ]]; then
return 1
else
@@ -10,19 +11,23 @@ has_tty() {
}
dokku_apps() {
local desc="prints list of all local apps"
local INSTALLED_APPS=$(find "$DOKKU_ROOT" -follow -maxdepth 1 -mindepth 1 -type d ! -name 'tls' ! -name '.*' -printf "%f\n" | sort) || (dokku_log_fail "You haven't deployed any applications yet")
[[ $INSTALLED_APPS ]] && echo "$INSTALLED_APPS"
}
dokku_log_info1() {
local desc="log info1 formatter"
echo "-----> $*"
}
dokku_log_info2() {
local desc="log info2 formatter"
echo "=====> $*"
}
dokku_log_info1_quiet() {
local desc="log info1 formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo "-----> $*"
else
@@ -31,6 +36,7 @@ dokku_log_info1_quiet() {
}
dokku_log_info2_quiet() {
local desc="log info2 formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo "=====> $*"
else
@@ -39,10 +45,12 @@ dokku_log_info2_quiet() {
}
dokku_col_log_info1() {
local desc="columnar log info1 formatter"
printf "%-6s %-18s %-25s %-25s %-25s\n" "----->" "$@"
}
dokku_col_log_info1_quiet() {
local desc="columnar log info1 formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-6s %-18s %-25s %-25s %-25s\n" "----->" "$@"
else
@@ -51,10 +59,12 @@ dokku_col_log_info1_quiet() {
}
dokku_col_log_info2() {
local desc="columnar log info2 formatter"
printf "%-6s %-18s %-25s %-25s %-25s\n" "=====>" "$@"
}
dokku_col_log_info2_quiet() {
local desc="columnar log info2 formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-6s %-18s %-25s %-25s %-25s\n" "=====>" "$@"
else
@@ -63,10 +73,12 @@ dokku_col_log_info2_quiet() {
}
dokku_col_log_msg() {
local desc="columnar log formatter"
printf "%-25s %-25s %-25s %-25s\n" "$@"
}
dokku_col_log_msg_quiet() {
local desc="columnar log formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-25s %-25s %-25s %-25s\n" "$@"
else
@@ -75,6 +87,7 @@ dokku_col_log_msg_quiet() {
}
dokku_log_verbose_quiet() {
local desc="log verbose formatter (with quiet option)"
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo " $*"
else
@@ -83,23 +96,28 @@ dokku_log_verbose_quiet() {
}
dokku_log_verbose() {
local desc="log verbose formatter"
echo " $*"
}
dokku_log_warn() {
local desc="log warning formatter"
echo " ! $*"
}
dokku_log_fail() {
local desc="log fail formatter"
echo "$@" 1>&2
exit 1
}
dokku_log_event() {
local desc="log dokku events"
logger -t dokku -i -- "$@"
}
dokku_log_plugn_trigger_call() {
local desc="log plugn trigger calls"
local l_hook
l_hook="$1" ; shift
@@ -107,6 +125,7 @@ dokku_log_plugn_trigger_call() {
}
dokku_container_log_verbose_quiet() {
local desc="log verbose container output (with quiet option)"
local CID=$1;
shift
@@ -119,6 +138,7 @@ dokku_container_log_verbose_quiet() {
}
verify_app_name() {
local desc="verify app name format and app existence"
local APP="$1"
[[ ! -n "$APP" ]] && dokku_log_fail "(verify_app_name) APP must not be null"
if [[ ! "$APP" =~ ^[a-z].* && ! "$APP" =~ ^[0-9].* ]]; then
@@ -131,6 +151,7 @@ verify_app_name() {
}
verify_image() {
local desc="verify image existence"
local IMAGE="$1"
if (docker inspect "$IMAGE" &>/dev/null); then
return 0
@@ -140,14 +161,14 @@ verify_image() {
}
get_app_image_repo() {
# central definition of our image repo pattern
local desc="central definition of image repo pattern"
local APP="$1"; local IMAGE_REPO="dokku/$APP"
[[ -z "$APP" ]] && dokku_log_fail "(get_app_image_repo) APP must not be null"
echo "$IMAGE_REPO"
}
get_app_image_name() {
# return image identifier for a given app, tag tuple. validate if tag is presented
local desc="return image identifier for a given app, tag tuple. validate if tag is presented"
local APP="$1"; local IMAGE_TAG="$2"; local IMAGE_REPO=$(get_app_image_repo "$APP")
[[ -z "$APP" ]] && dokku_log_fail "(get_app_image_name) APP must not be null"
@@ -161,7 +182,7 @@ get_app_image_name() {
}
get_running_image_tag() {
# retrieve current image tag for a given app. returns empty string if no deployed containers are found
local desc="retrieve current image tag for a given app. returns empty string if no deployed containers are found"
local APP="$1"
[[ ! -n "$APP" ]] && dokku_log_fail "(get_running_image_tag) APP must not be null"
verify_app_name "$APP"
@@ -172,12 +193,14 @@ get_running_image_tag() {
}
is_image_herokuish_based() {
local desc="returns true if app image is based on herokuish"
# circleci can't support --rm as they run lxc in lxc
[[ ! -f "/home/ubuntu/.circlerc" ]] && local DOCKER_ARGS="--rm"
docker run "$DOKKU_GLOBAL_RUN_ARGS" --entrypoint="/bin/sh" $DOCKER_ARGS "$@" -c "test -f /exec"
}
is_number() {
local desc="returns 0 if input is a number"
local NUMBER=$1; local NUM_RE='^[0-9]+$'
if [[ $NUMBER =~ $NUM_RE ]]; then
return 0
@@ -187,6 +210,7 @@ is_number() {
}
is_abs_path() {
local desc="returns 0 if input path is absolute"
local TEST_PATH=$1
if [[ "$TEST_PATH" = /* ]]; then
return 0
@@ -196,6 +220,7 @@ is_abs_path() {
}
parse_args() {
local desc="top-level cli arg parser"
local next_index=1; local skip=false; local args=("$@")
for arg in "$@"; do
$skip && skip=false && continue
@@ -222,6 +247,7 @@ parse_args() {
}
copy_from_image() {
local desc="copy file from named image to destination"
local IMAGE="$1"; local SRC_FILE="$2"; local DST_DIR="$3"
verify_app_name "$APP"
@@ -240,6 +266,7 @@ copy_from_image() {
}
get_app_container_ids() {
local desc="returns list of docker container ids for given app"
local APP="$1"; local CONTAINER_TYPE="$2"
verify_app_name "$APP"
[[ -f $DOKKU_ROOT/$APP/CONTAINER ]] && DOKKU_CIDS+=$(< "$DOKKU_ROOT/$APP/CONTAINER")
@@ -265,6 +292,7 @@ get_app_container_ids() {
}
get_app_running_container_ids() {
local desc="return list of running docker container ids for given apps"
local APP=$1
verify_app_name "$APP"
@@ -280,6 +308,7 @@ get_app_running_container_ids() {
}
get_cmd_from_procfile() {
local desc="parse cmd from app Procfile"
local APP=$1; local PROC_TYPE=$2; local DOKKU_PROCFILE="$DOKKU_ROOT/$APP/DOKKU_PROCFILE"
local name; local command;
verify_app_name "$APP"
@@ -297,6 +326,7 @@ get_cmd_from_procfile() {
}
is_deployed() {
local desc="return 0 if given app has a running container"
local APP="$1"
if [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] || [[ $(ls "$DOKKU_ROOT/$APP"/CONTAINER.* &> /dev/null; echo $?) -eq 0 ]]; then
return 0
@@ -306,6 +336,7 @@ is_deployed() {
}
is_container_running () {
local desc="return 0 if given docker container id is in running state"
local CID=$1
local CONTAINER_STATUS=$(docker inspect -f '{{.State.Running}}' "$CID" || true)
@@ -317,6 +348,7 @@ is_container_running () {
}
is_container_status () {
local desc="return 0 if given docker container id is in given state"
local CID=$1
local TEMPLATE="{{.State.$2}}"
local CONTAINER_STATUS=$(docker inspect -f "$TEMPLATE" "$CID" || true)
@@ -329,6 +361,7 @@ is_container_status () {
}
is_app_running() {
local desc="return 0 if given app has a running container"
local APP="$1"
verify_app_name "$APP"
@@ -342,20 +375,21 @@ is_app_running() {
}
release_and_deploy() {
local desc="main function for releasing and deploying an app"
local APP="$1"; local IMAGE_TAG="$2"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG")
verify_app_name "$APP"
if verify_image "$IMAGE"; then
if is_image_herokuish_based "$IMAGE"; then
IMAGE_SOURCE_TYPE="herokuish"
local IMAGE_SOURCE_TYPE="herokuish"
else
IMAGE_SOURCE_TYPE="dockerfile"
local IMAGE_SOURCE_TYPE="dockerfile"
fi
DOKKU_APP_SKIP_DEPLOY="$(dokku config:get "$APP" DOKKU_SKIP_DEPLOY || true)"
DOKKU_GLOBAL_SKIP_DEPLOY="$(dokku config:get --global DOKKU_SKIP_DEPLOY || true)"
local DOKKU_APP_SKIP_DEPLOY="$(dokku config:get "$APP" DOKKU_SKIP_DEPLOY || true)"
local DOKKU_GLOBAL_SKIP_DEPLOY="$(dokku config:get --global DOKKU_SKIP_DEPLOY || true)"
DOKKU_SKIP_DEPLOY=${DOKKU_APP_SKIP_DEPLOY:="$DOKKU_GLOBAL_SKIP_DEPLOY"}
local DOKKU_SKIP_DEPLOY=${DOKKU_APP_SKIP_DEPLOY:="$DOKKU_GLOBAL_SKIP_DEPLOY"}
dokku_log_info1 "Releasing $APP ($IMAGE)..."
dokku release "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG"
@@ -374,6 +408,7 @@ release_and_deploy() {
}
docker_cleanup() {
local desc="cleans up all exited/dead containers and removes all dangling images"
# delete all non-running containers
# shellcheck disable=SC2046
docker rm $(docker ps -a -f 'status=exited' -q) &> /dev/null || true
@@ -388,6 +423,7 @@ docker_cleanup() {
}
get_available_port() {
local desc="returns first currently unused port > 1024"
while true; do
local port=$(shuf -i 1025-65535 -n 1)
if ! nc -z 0.0.0.0 "$port"; then
@@ -400,6 +436,7 @@ get_available_port() {
}
dokku_auth() {
local desc="calls user-auth plugin trigger"
export SSH_USER=${SSH_USER:=$USER}
export SSH_NAME=${NAME:="default"}
if ! plugn trigger user-auth "$SSH_USER" "$SSH_NAME" "$@" ; then
@@ -409,10 +446,12 @@ dokku_auth() {
}
_ipv4_regex() {
local desc="ipv4 regex"
echo "([0-9]{1,3}[\.]){3}[0-9]{1,3}"
}
_ipv6_regex() {
local desc="ipv6 regex"
local RE_IPV4="$(_ipv4_regex)"
local RE_IPV6="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" # TEST: 1:2:3:4:5:6:7:8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,7}:|" # TEST: 1:: 1:2:3:4:5:6:7::
@@ -430,6 +469,7 @@ _ipv6_regex() {
}
get_ipv4_regex() {
local desc="returns ipv4 regex"
local RE_IPV4="$(_ipv4_regex)"
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
@@ -437,6 +477,7 @@ get_ipv4_regex() {
}
get_ipv6_regex() {
local desc="returns ipv6 regex"
local RE_IPV6="$(_ipv6_regex)"
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
@@ -444,9 +485,10 @@ get_ipv6_regex() {
}
get_global_vhost() {
local GLOBAL_VHOST_FILE="$DOKKU_ROOT/VHOST"
[[ -f "$GLOBAL_VHOST_FILE" ]] && local GLOBAL_VHOST=$(< "$GLOBAL_VHOST_FILE")
echo "$GLOBAL_VHOST"
local desc="return global vhost"
local GLOBAL_VHOST_FILE="$DOKKU_ROOT/VHOST"
[[ -f "$GLOBAL_VHOST_FILE" ]] && local GLOBAL_VHOST=$(< "$GLOBAL_VHOST_FILE")
echo "$GLOBAL_VHOST"
}
is_global_vhost_enabled() {
@@ -464,8 +506,9 @@ is_global_vhost_enabled() {
is_app_vhost_enabled() {
local desc="returns true or false if vhost support is enabled for a given application"
local APP=$1; verify_app_name "$APP"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
local APP=$1; verify_app_name "$APP"
local NO_VHOST=$(config_get "$APP" NO_VHOST)
local APP_VHOST_ENABLED=true
@@ -478,6 +521,8 @@ is_app_vhost_enabled() {
disable_app_vhost() {
local desc="disable vhost support for given application"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
local APP=$1; verify_app_name "$APP"
local APP_VHOST_FILE="$DOKKU_ROOT/$APP/VHOST"
local APP_URLS_FILE="$DOKKU_ROOT/$APP/URLS"
@@ -506,6 +551,8 @@ disable_app_vhost() {
enable_app_vhost() {
local desc="enable vhost support for given application"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
local APP=$1; verify_app_name "$APP"
config_unset --no-restart "$APP" DOKKU_NGINX_PORT DOKKU_NGINX_SSL_PORT
@@ -515,11 +562,15 @@ enable_app_vhost() {
}
get_dockerfile_exposed_ports() {
local desc="return all exposed ports from passed file path"
local DOCKERFILE_PORTS=$(egrep "^EXPOSE " "$1" | awk '{ print $2 }' | xargs) || true
echo "$DOCKERFILE_PORTS"
}
get_app_raw_tcp_ports() {
local desc="extracts raw tcp port numbers from DOCKERFILE_PORTS config variable"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
local APP="$1"; verify_app_name "$APP"
local DOCKERFILE_PORTS="$(config_get "$APP" DOKKU_DOCKERFILE_PORTS)"
for p in $DOCKERFILE_PORTS; do
@@ -528,11 +579,12 @@ get_app_raw_tcp_ports() {
raw_tcp_ports+="$p "
fi
done
raw_tcp_ports="$(echo "$raw_tcp_ports"| xargs)"
local raw_tcp_ports="$(echo "$raw_tcp_ports"| xargs)"
echo "$raw_tcp_ports"
}
get_container_ports() {
local desc="returns published ports from app containers"
local APP="$1"; verify_app_name "$APP"
local APP_CIDS="$(get_app_container_ids "$APP")"
local cid
@@ -545,6 +597,9 @@ get_container_ports() {
}
get_app_urls() {
local desc="print an app's available urls"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
local APP="$2"; verify_app_name "$APP"
local RAW_TCP_PORTS="$(get_app_raw_tcp_ports "$APP")"
local URLS_FILE="$DOKKU_ROOT/$APP/URLS"
@@ -609,7 +664,7 @@ get_app_urls() {
}
get_json_value() {
# return value of provided json key from a json stream on stdin
local desc="return value of provided json key from a json stream on stdin"
# JSON_NODE should be expresses as either a top-level object that has no children
# or in the format of json.node.path
local JSON_NODE="$1"
@@ -619,7 +674,7 @@ get_json_value() {
}
get_json_keys() {
# return space-separated list of json keys from json provided on stdin
local desc="return space-separated list of json keys from json provided on stdin"
# JSON_NODE should be expressed as json.node.path and is expected to have children
local JSON_NODE="$1"
local JSON_NODE=${JSON_NODE//\./\"][\"}