Files
dokku/plugins/common/functions
Jose Diaz-Gonzalez fc125d41e8 Add user-auth plugin trigger
This plugin trigger should allow users to pair down the available commands for a given user. While this does not affect help output - or any output at all - this is a good first step in allowing administrative access to certain commands while still allowing users to deploy/manage given applications.

Note that because of how dokku works, all parsing of commands must be done within the pluginhook, and we cannot give visibility into the actual command or application that will be affected by a given run.
2015-11-08 15:36:04 -05:00

358 lines
7.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
has_tty() {
if [[ "$(/usr/bin/tty || true)" == "not a tty" ]]; then
return 1
else
return 0
fi
}
dokku_log_info1() {
echo "-----> $*"
}
dokku_log_info2() {
echo "=====> $*"
}
dokku_log_info1_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo "-----> $*"
else
return 0
fi
}
dokku_log_info2_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo "=====> $*"
else
return 0
fi
}
dokku_col_log_info1() {
printf "%-6s %-18s %-25s %-25s %-25s\n" "----->" "$@"
}
dokku_col_log_info1_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-6s %-18s %-25s %-25s %-25s\n" "----->" "$@"
else
return 0
fi
}
dokku_col_log_info2() {
printf "%-6s %-18s %-25s %-25s %-25s\n" "=====>" "$@"
}
dokku_col_log_info2_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-6s %-18s %-25s %-25s %-25s\n" "=====>" "$@"
else
return 0
fi
}
dokku_col_log_msg() {
printf "%-25s %-25s %-25s %-25s\n" "$@"
}
dokku_col_log_msg_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
printf "%-25s %-25s %-25s %-25s\n" "$@"
else
return 0
fi
}
dokku_log_verbose_quiet() {
if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then
echo " $*"
else
return 0
fi
}
dokku_log_verbose() {
echo " $*"
}
dokku_log_warn() {
echo " ! $*"
}
dokku_log_fail() {
echo "$@" 1>&2
exit 1
}
dokku_log_event() {
logger -t dokku -i -- "$@"
}
dokku_log_plugn_trigger_call() {
local l_hook
l_hook="$1" ; shift
dokku_log_event "INVOKED: ${l_hook}( $* ) NAME=$NAME FINGERPRINT=$FINGERPRINT"
}
dokku_container_log_verbose_quiet() {
local CID=$1;
shift
OIFS=$IFS
IFS=$'\n'
for line in $(docker logs $CID 2>&1); do
dokku_log_verbose_quiet "$line"
done
IFS=$OIFS
}
verify_app_name() {
local APP="$1"
[[ ! -n "$APP" ]] && dokku_log_fail "(verify_app_name) APP must not be null"
[[ ! -d "$DOKKU_ROOT/$APP" ]] && dokku_log_fail "App $APP does not exist"
return 0
}
verify_image() {
local IMAGE="$1"
if (docker inspect "$IMAGE" &>/dev/null); then
return 0
else
return 1
fi
}
get_app_image_repo() {
# central definition of our 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 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"
if [[ -n "$IMAGE_TAG" ]]; then
IMAGE="$IMAGE_REPO:$IMAGE_TAG"
verify_image "$IMAGE" || dokku_log_fail "app image ($IMAGE) not found"
else
IMAGE="$IMAGE_REPO:latest"
fi
echo $IMAGE
}
get_running_image_tag() {
# 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"
CIDS=( $(get_app_container_ids $APP) )
RUNNING_IMAGE_TAG=$(docker ps -a --no-trunc | egrep ${CIDS[0]} 2>/dev/null | awk '{ print $2 }' | awk -F: '{ print $2 }' || echo '')
echo $RUNNING_IMAGE_TAG
}
is_image_herokuish_based() {
# circleci can't support --rm as they run lxc in lxc
[[ ! -f "/home/ubuntu/.circlerc" ]] && local DOCKER_ARGS="--rm"
docker run --entrypoint="/bin/sh" $DOCKER_ARGS "$@" -c "test -f /exec"
}
is_number() {
local NUMBER=$1; local NUM_RE='^[0-9]+$'
if [[ $NUMBER =~ $NUM_RE ]]; then
return 0
else
return 1
fi
}
parse_args() {
for arg in "$@"; do
case "$arg" in
--quiet)
export DOKKU_QUIET_OUTPUT=1
;;
--trace)
export DOKKU_TRACE=1
;;
--rm-container|--rm)
export DOKKU_RM_CONTAINER=1
;;
--force)
export DOKKU_APPS_FORCE_DELETE=1
;;
esac
done
return 0
}
copy_from_image() {
local IMAGE="$1"; local SRC_FILE="$2"; local DST_DIR="$3"
verify_app_name $APP
if verify_image "$IMAGE"; then
CID=$(docker run -d $IMAGE bash)
docker cp "$CID:$SRC_FILE" "$DST_DIR"
docker rm -f "$CID" &> /dev/null
else
return 1
fi
}
get_app_container_ids() {
local APP="$1"; local CONTAINER_TYPE="$2"
verify_app_name $APP
[[ -f $DOKKU_ROOT/$APP/CONTAINER ]] && DOKKU_CIDS+=$(< $DOKKU_ROOT/$APP/CONTAINER)
if [[ -n "$CONTAINER_TYPE" ]]; then
CONTAINER_PATTERN="$DOKKU_ROOT/$APP/CONTAINER.$CONTAINER_TYPE.*"
if [[ $CONTAINER_TYPE == *.* ]]; then
CONTAINER_PATTERN="$DOKKU_ROOT/$APP/CONTAINER.$CONTAINER_TYPE"
[[ ! -f $CONTAINER_PATTERN ]] && echo "" && return 0
fi
else
CONTAINER_PATTERN="$DOKKU_ROOT/$APP/CONTAINER.*"
fi
shopt -s nullglob
for DOKKU_CID_FILE in $CONTAINER_PATTERN; do
DOKKU_CIDS+=" "
DOKKU_CIDS+=$(< $DOKKU_CID_FILE)
DOKKU_CIDS+=" "
done
shopt -u nullglob
echo $DOKKU_CIDS
}
get_dockerfile_exposed_port() {
local DOCKERFILE_PORT=$(grep "^EXPOSE \+[[:digit:]]\+\(\/tcp\)\? *$" $1 | head -1 | sed 's/EXPOSE \+\([[:digit:]]\+\)\(\/tcp\)\?.*/\1/' || true)
echo "$DOCKERFILE_PORT"
}
get_app_running_container_ids() {
local APP=$1
verify_app_name $APP
! (is_deployed $APP) && dokku_log_fail "App $APP has not been deployed"
local CIDS=$(get_app_container_ids $APP)
for CID in $CIDS; do
local APP_CONTAINER_STATUS=$(docker inspect -f '{{.State.Running}}' "$CID" || true)
[[ "$APP_CONTAINER_STATUS" == "true" ]] && local APP_RUNNING_CONTAINER_IDS+="$CID "
done
echo "$APP_RUNNING_CONTAINER_IDS"
}
is_deployed() {
local APP="$1"
if [[ -f "$DOKKU_ROOT/$APP/CONTAINER" ]] || [[ $(ls $DOKKU_ROOT/$APP/CONTAINER.* &> /dev/null; echo $?) -eq 0 ]]; then
return 0
else
return 1
fi
}
is_container_running () {
local CID=$1
local CONTAINER_STATUS=$(docker inspect -f '{{.State.Running}}' "$CID" || true)
if [[ "$CONTAINER_STATUS" == "true" ]]; then
return 0
else
return 1
fi
}
is_container_status () {
local CID=$1
local TEMPLATE="{{.State.$2}}"
local CONTAINER_STATUS=$(docker inspect -f "$TEMPLATE" "$CID" || true)
if [[ "$CONTAINER_STATUS" == "true" ]]; then
return 0
else
return 1
fi
}
is_app_running() {
local APP="$1"
verify_app_name $APP
local APP_RUNNING_CONTAINER_IDS=$(get_app_running_container_ids $APP)
if [[ -n "$APP_RUNNING_CONTAINER_IDS" ]]; then
return 0
else
return 1
fi
}
release_and_deploy() {
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"
else
IMAGE_SOURCE_TYPE="dockerfile"
fi
dokku_log_info1 "Releasing $APP ($IMAGE)..."
dokku release "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG"
dokku_log_info1 "Deploying $APP ($IMAGE)..."
dokku deploy "$APP" "$IMAGE_TAG"
dokku_log_info2 "Application deployed:"
dokku urls $APP | sed "s/^/ /"
echo
fi
}
docker_cleanup() {
# delete all non-running containers
# shellcheck disable=SC2046
docker rm $(docker ps -a -f 'status=exited' -q) &> /dev/null || true
# delete all dead containers
# shellcheck disable=SC2046
docker rm $(docker ps -a -f 'status=dead' -q) &> /dev/null || true
# delete unused images
# shellcheck disable=SC2046
docker rmi $(docker images -f 'dangling=true' -q) &> /dev/null &
}
get_available_port() {
while true; do
local port=$(shuf -i 1025-65535 -n 1)
if ! nc -z 0.0.0.0 $port; then
echo $port
return 0
else
continue
fi
done
}
dokku_auth() {
export SSH_USER=${SSH_USER:=$USER}
export SSH_NAME=${NAME:="default"}
if ! plugn trigger user-auth $SSH_USER $SSH_NAME "$@" ; then
return 1
fi
return 0
}