mirror of
https://github.com/dokku/dokku.git
synced 2025-12-16 03:57:43 +01:00
This makes standard use of shellcheck work without needing to provide extra configuration anywhere. Also remove use of inline 'shellcheck disable' calls that are already defined in the .shellcheckrc and don't need to be set inline.
254 lines
7.8 KiB
Bash
Executable File
254 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
|
set -eo pipefail
|
|
[[ $DOKKU_TRACE ]] && set -x
|
|
|
|
cmd-scheduler-docker-local-report() {
|
|
declare desc="displays a scheduler-docker-local report for one or more apps"
|
|
declare cmd="scheduler-docker-local:report"
|
|
[[ "$1" == "$cmd" ]] && shift 1
|
|
declare APP="$1" INFO_FLAG="$2"
|
|
|
|
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
|
INFO_FLAG="$APP"
|
|
APP=""
|
|
fi
|
|
|
|
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
|
INFO_FLAG="true"
|
|
fi
|
|
|
|
if [[ -z "$APP" ]]; then
|
|
for app in $(dokku_apps); do
|
|
cmd-scheduler-docker-local-report-single "$app" "$INFO_FLAG" | tee || true
|
|
done
|
|
else
|
|
cmd-scheduler-docker-local-report-single "$APP" "$INFO_FLAG"
|
|
fi
|
|
}
|
|
|
|
cmd-scheduler-docker-local-report-single() {
|
|
declare APP="$1" INFO_FLAG="$2"
|
|
if [[ "$INFO_FLAG" == "true" ]]; then
|
|
INFO_FLAG=""
|
|
fi
|
|
verify_app_name "$APP"
|
|
local flag_map=(
|
|
"--scheduler-docker-local-disable-chown: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "disable-chown" "")"
|
|
"--scheduler-docker-local-init-process: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "init-process" "true")"
|
|
"--scheduler-docker-local-parallel-schedule-count: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "parallel-schedule-count" "")"
|
|
)
|
|
|
|
if [[ -z "$INFO_FLAG" ]]; then
|
|
dokku_log_info2_quiet "${APP} scheduler-docker-local information"
|
|
for flag in "${flag_map[@]}"; do
|
|
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
|
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
|
done
|
|
else
|
|
local match=false
|
|
local value_exists=false
|
|
for flag in "${flag_map[@]}"; do
|
|
valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)"
|
|
if [[ "$flag" == "${INFO_FLAG}:"* ]]; then
|
|
value=${flag#*: }
|
|
size="${#value}"
|
|
if [[ "$size" -ne 0 ]]; then
|
|
echo "$value" && match=true && value_exists=true
|
|
else
|
|
match=true
|
|
fi
|
|
fi
|
|
done
|
|
[[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}"
|
|
[[ "$value_exists" == "true" ]] || dokku_log_fail "not deployed"
|
|
fi
|
|
}
|
|
|
|
fn-scheduler-docker-local-retire-container() {
|
|
declare APP="$1" CID="$2"
|
|
local STATE
|
|
|
|
dokku_log_verbose_quiet "Attempting to retire $APP container $CID"
|
|
STATE="$("$DOCKER_BIN" container inspect --format "{{ .State.Status }}" "$CID" 2>/dev/null || true)"
|
|
if [[ -z "$STATE" ]]; then
|
|
return
|
|
fi
|
|
|
|
DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)"
|
|
[[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}"
|
|
|
|
if [[ "$STATE" == "restarting" ]]; then
|
|
"$DOCKER_BIN" container update --restart=no "$CID" >/dev/null 2>&1
|
|
fi
|
|
|
|
if [[ "$STATE" != "dead" ]] && [[ "$STATE" != "exited" ]]; then
|
|
# Attempt to stop, if that fails, then force a kill as docker seems
|
|
# to not send SIGKILL as the docs would indicate. If that fails, move
|
|
# on to the next.
|
|
"$DOCKER_BIN" container stop $DOCKER_STOP_TIME_ARG "$CID" \
|
|
|| "$DOCKER_BIN" container kill "$CID" \
|
|
|| dokku_log_warn "Unable to kill container ${CID}"
|
|
fi
|
|
|
|
STATE="$("$DOCKER_BIN" container inspect --format "{{ .State.Status }}" "$CID" 2>/dev/null || true)"
|
|
if [[ -z "$STATE" ]]; then
|
|
return
|
|
fi
|
|
|
|
if [[ "$STATE" != "dead" ]] && [[ "$STATE" != "exited" ]]; then
|
|
if ! "$DOCKER_BIN" container kill "$CID"; then
|
|
dokku_log_warn "Unable to kill container ${CID}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
fn-scheduler-docker-local-retire-containers() {
|
|
local DEAD_CONTAINER_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/dead-containers"
|
|
local APP CID CURRENT_TIME DEAD_TIME STATE
|
|
declare SCHEDULER="$1" APP="$2"
|
|
|
|
if [[ ! -f "$DEAD_CONTAINER_FILE" ]]; then
|
|
return
|
|
fi
|
|
|
|
DEAD_CONTAINERS=()
|
|
while read line; do
|
|
[[ -z "$line" ]] && continue
|
|
CURRENT_TIME="$(date +%s)"
|
|
RETIRE_APP="$(echo "$line" | cut -d ' ' -f1)"
|
|
CID="$(echo "$line" | cut -d ' ' -f2)"
|
|
DEAD_TIME="$(echo "$line" | cut -d ' ' -f3)"
|
|
|
|
if [[ -n "$APP" ]] && [[ "$APP" != "$RETIRE_APP" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "$CURRENT_TIME" -le "$DEAD_TIME" ]]; then
|
|
continue
|
|
fi
|
|
|
|
fn-scheduler-docker-local-retire-container "$RETIRE_APP" "$CID"
|
|
STATE="$("$DOCKER_BIN" container inspect --format "{{ .State.Status }}" "$CID" 2>/dev/null || true)"
|
|
if [[ -z "$STATE" ]]; then
|
|
DEAD_CONTAINERS+=("$CID")
|
|
continue
|
|
fi
|
|
|
|
if [[ "$STATE" == "running" ]]; then
|
|
dokku_log_warn "Container ${CID} still running"
|
|
continue
|
|
fi
|
|
|
|
"$DOCKER_BIN" container rm --force "$CID" >/dev/null 2>&1 || true
|
|
if "$DOCKER_BIN" container inspect "${CID}" >/dev/null 2>&1; then
|
|
dokku_log_warn "Container ${CID} still running"
|
|
continue
|
|
fi
|
|
|
|
DEAD_CONTAINERS+=("$CID")
|
|
done <"$DEAD_CONTAINER_FILE"
|
|
|
|
for CID in "${DEAD_CONTAINERS[@]}"; do
|
|
sed -i "/${CID}/d" "$DEAD_CONTAINER_FILE"
|
|
done
|
|
}
|
|
|
|
fn-scheduler-docker-local-retire-images() {
|
|
local DEAD_IMAGE_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/dead-images"
|
|
local APP IMAGE_ID CURRENT_TIME DEAD_TIME STATE RM_OUTPUT
|
|
declare SCHEDULER="$1" APP="$2"
|
|
|
|
if [[ ! -f "$DEAD_IMAGE_FILE" ]]; then
|
|
return
|
|
fi
|
|
|
|
DEAD_IMAGES=()
|
|
while read line; do
|
|
[[ -z "$line" ]] && continue
|
|
CURRENT_TIME="$(date +%s)"
|
|
RETIRE_APP="$(echo "$line" | cut -d ' ' -f1)"
|
|
IMAGE_ID="$(echo "$line" | cut -d ' ' -f2)"
|
|
DEAD_TIME="$(echo "$line" | cut -d ' ' -f3)"
|
|
|
|
if [[ -n "$APP" ]] && [[ "$APP" != "$RETIRE_APP" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "$CURRENT_TIME" -le "$DEAD_TIME" ]]; then
|
|
continue
|
|
fi
|
|
|
|
STATE="$("$DOCKER_BIN" image inspect --format "{{ .Id }}" "$IMAGE_ID" 2>/dev/null || true)"
|
|
if [[ -z "$STATE" ]]; then
|
|
DEAD_IMAGES+=("$IMAGE_ID")
|
|
continue
|
|
fi
|
|
|
|
dokku_log_verbose_quiet "Attempting to retire $RETIRE_APP image $IMAGE_ID"
|
|
if RM_OUTPUT="$("$DOCKER_BIN" image remove "$IMAGE_ID" 2>&1)"; then
|
|
DEAD_IMAGES+=("$IMAGE_ID")
|
|
continue
|
|
fi
|
|
|
|
if echo "$RM_OUTPUT" | grep -q "image has dependent child images"; then
|
|
TAG_COUNT="$(docker inspect "$IMAGE_ID" --format '{{ json .RepoTags }}' | jq '. | length')"
|
|
if [[ "$TAG_COUNT" -eq 0 ]]; then
|
|
dokku_log_warn "Image ${IMAGE_ID} has children images and is untagged, skipping rm and marking dead"
|
|
DEAD_IMAGES+=("$IMAGE_ID")
|
|
continue
|
|
fi
|
|
|
|
dokku_log_warn "Image ${IMAGE_ID} has children images and has $TAG_COUNT tags, skipping rm"
|
|
continue
|
|
fi
|
|
|
|
if echo "$RM_OUTPUT" | grep -q "image is being used by running container"; then
|
|
dokku_log_warn "Image ${IMAGE_ID} has running containers, skipping rm"
|
|
continue
|
|
fi
|
|
|
|
dokku_log_warn "Image ${IMAGE_ID} still running"
|
|
done <"$DEAD_IMAGE_FILE"
|
|
|
|
for IMAGE_ID in "${DEAD_IMAGES[@]}"; do
|
|
sed -i "/${IMAGE_ID}/d" "$DEAD_IMAGE_FILE"
|
|
done
|
|
|
|
sort -o "$DEAD_IMAGE_FILE" -r "$DEAD_IMAGE_FILE"
|
|
}
|
|
|
|
fn-scheduler-docker-local-register-retired() {
|
|
declare TYPE="$1" APP="$2" DOCKER_ID="$3" WAIT="$4"
|
|
local DEAD_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/dead-containers"
|
|
if [[ "$TYPE" == "image" ]]; then
|
|
local DEAD_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/dead-images"
|
|
fi
|
|
local CURRENT_TIME DEAD_TIME
|
|
|
|
CURRENT_TIME="$(date +%s)"
|
|
DEAD_TIME=$((CURRENT_TIME + WAIT))
|
|
touch "$DEAD_FILE"
|
|
if ! grep -q "$DOCKER_ID" "$DEAD_FILE"; then
|
|
echo "${APP} ${DOCKER_ID} ${DEAD_TIME}" >>"${DEAD_FILE}"
|
|
fi
|
|
}
|
|
|
|
fn-scheduler-docker-local-start-app-container() {
|
|
declare desc="starts a single app container"
|
|
declare APP="$1"
|
|
shift
|
|
|
|
declare -a DOCKER_ARGS
|
|
for i in "$@"; do
|
|
DOCKER_ARGS+=("$i")
|
|
done
|
|
set -- "${DOCKER_ARGS[@]}"
|
|
|
|
eval "$(config_export app "$APP" --merged)"
|
|
# shellcheck disable=SC2124
|
|
"$DOCKER_BIN" container create "$@"
|
|
}
|