Emitting the restart policy as a `--restart` argument from a `docker-args-process-deploy` trigger exposed a latent gluing bug: proxy and builder triggers concatenated `$STDIN$output` with no separator, and the scheduler and builders appended `docker-args-process-*` output directly onto the older `docker-args-*` output, so adjacent arguments could merge into values like `--restart=on-failure:10--label`. A space is now inserted at both the trigger echo and the concatenation so arguments always stay separated.
180 lines
6.9 KiB
Bash
Executable File
180 lines
6.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
[[ $DOKKU_TRACE ]] && set -x
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/scheduler-docker-local/internal-functions"
|
|
|
|
trigger-scheduler-docker-local-scheduler-run() {
|
|
declare desc="runs command in container based on app image"
|
|
declare trigger="scheduler-run"
|
|
declare DOKKU_SCHEDULER="$1" APP="$2" ENV_COUNT="$3"
|
|
local CONTAINER_ID
|
|
shift 3
|
|
|
|
declare RUN_ENV=("${@:1:ENV_COUNT}")
|
|
shift "$ENV_COUNT"
|
|
declare RUN_COMMAND=()
|
|
|
|
if [[ "$DOKKU_SCHEDULER" != "docker-local" ]]; then
|
|
return
|
|
fi
|
|
|
|
local IMAGE_TAG=$(get_running_image_tag "$APP")
|
|
local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG")
|
|
local IMAGE_STAGE="$("$DOCKER_BIN" image inspect -f '{{ index .Config.Labels "com.dokku.image-stage" }}' "$IMAGE")"
|
|
if [[ "$IMAGE_STAGE" != "release" ]]; then
|
|
dokku_log_warn "Invalid image stage detected: expected 'release', got '$IMAGE_STAGE'"
|
|
dokku_log_warn "Successfully deploy your app to fix dokku run calls"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -z "$DOKKU_RM_CONTAINER" ]]; then
|
|
local DOKKU_APP_RM_CONTAINER=$(config_get "$APP" DOKKU_RM_CONTAINER || true)
|
|
local DOKKU_GLOBAL_RM_CONTAINER=$(config_get --global DOKKU_RM_CONTAINER || true)
|
|
local DOKKU_RM_CONTAINER=${DOKKU_APP_RM_CONTAINER:="$DOKKU_GLOBAL_RM_CONTAINER"}
|
|
fi
|
|
|
|
local DOCKER_ARGS=$(: | plugn trigger docker-args-run "$APP" "$IMAGE_TAG")
|
|
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true "
|
|
|
|
local PROCESS_TYPE=run
|
|
local concurrency_policy="allow"
|
|
if [[ -n "$DOKKU_CRON_ID" ]]; then
|
|
PROCESS_TYPE=cron
|
|
DOCKER_ARGS+=" --label=com.dokku.cron-id=$DOKKU_CRON_ID"
|
|
|
|
if [[ -n "$DOKKU_CONCURRENCY_POLICY" ]]; then
|
|
concurrency_policy="$DOKKU_CONCURRENCY_POLICY"
|
|
fi
|
|
DOCKER_ARGS+=" --label=com.dokku.concurrency-policy=$concurrency_policy"
|
|
|
|
if [[ "$concurrency_policy" == "forbid" ]]; then
|
|
# check if there is a running docker container with the same com.dokku.cron-id label
|
|
local RUNNING_CONTAINERS="$("$DOCKER_BIN" container ls --filter "label=com.dokku.cron-id=$DOKKU_CRON_ID" --filter "status=running" --quiet || true)"
|
|
if [[ -n "$RUNNING_CONTAINERS" ]]; then
|
|
dokku_log_warn "$APP currently has a cron lock in place for $DOKKU_CRON_ID. Exiting..."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$concurrency_policy" == "replace" ]]; then
|
|
local RUNNING_CONTAINERS="$("$DOCKER_BIN" container ls --filter "label=com.dokku.cron-id=$DOKKU_CRON_ID" --filter "status=running" --quiet || true)"
|
|
if [[ -n "$RUNNING_CONTAINERS" ]]; then
|
|
dokku_log_warn "Replacing running container for $DOKKU_CRON_ID"
|
|
"$DOCKER_BIN" container update --restart=no "$RUNNING_CONTAINERS" &>/dev/null || true
|
|
"$DOCKER_BIN" container stop "$RUNNING_CONTAINERS" >/dev/null && "$DOCKER_BIN" container kill "$RUNNING_CONTAINERS" &>/dev/null
|
|
plugn trigger scheduler-register-retired "$APP" "$RUNNING_CONTAINERS"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
local DYNO_NUMBER="$RANDOM"
|
|
local IMAGE_SOURCE_TYPE="dockerfile"
|
|
is_image_herokuish_based "$IMAGE" "$APP" && IMAGE_SOURCE_TYPE="herokuish"
|
|
is_image_cnb_based "$IMAGE" && IMAGE_SOURCE_TYPE="pack"
|
|
DOCKER_ARGS+=" $(: | plugn trigger docker-args-process-run "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG")"
|
|
DOCKER_ARGS+=" -e DYNO=$PROCESS_TYPE.$DYNO_NUMBER --name $APP.$PROCESS_TYPE.$DYNO_NUMBER"
|
|
|
|
if [[ "$DOKKU_RM_CONTAINER" ]]; then
|
|
DOCKER_ARGS+=" --rm"
|
|
fi
|
|
if has_tty; then
|
|
DOCKER_ARGS+=" --interactive"
|
|
DOCKER_ARGS+=" --tty"
|
|
fi
|
|
for env_pair in "${RUN_ENV[@]}"; do
|
|
DOCKER_ARGS+=" --env=$env_pair"
|
|
done
|
|
|
|
if [[ -n "$DOKKU_GLOBAL_FLAGS" ]]; then
|
|
read -ra flags <<<"$DOKKU_GLOBAL_FLAGS"
|
|
for flag in "${flags[@]}"; do
|
|
if [[ "$flag" =~ ^--label.* ]]; then
|
|
DOCKER_ARGS+=" $flag"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
local EXEC_CMD=""
|
|
[[ "$IMAGE_SOURCE_TYPE" == "herokuish" ]] && EXEC_CMD="/exec"
|
|
|
|
if [[ "$1" == "--" ]]; then
|
|
shift
|
|
fi
|
|
|
|
local POTENTIAL_PROCFILE_KEY="$1"
|
|
if [[ -n "$POTENTIAL_PROCFILE_KEY" ]]; then
|
|
PROC_CMD=$(plugn trigger procfile-get-command "$APP" "$POTENTIAL_PROCFILE_KEY" "5000" 2>/dev/null || echo '')
|
|
|
|
if [[ -n "$PROC_CMD" ]]; then
|
|
dokku_log_info1_quiet "Found '$POTENTIAL_PROCFILE_KEY' in Procfile, running that command"
|
|
DOCKER_ARGS+=" --label=com.dokku.process-type=$POTENTIAL_PROCFILE_KEY"
|
|
read -ra proc_array <<<"$PROC_CMD"
|
|
set -- "${proc_array[@]}" "${@:2}"
|
|
fi
|
|
fi
|
|
|
|
local DOKKU_IMAGE_ARCHITECTURE="$("$DOCKER_BIN" image inspect --format '{{.Architecture}}' "$IMAGE")"
|
|
if [[ "$DOKKU_IMAGE_ARCHITECTURE" == "amd64" ]] && [[ "$(dpkg --print-architecture 2>/dev/null || true)" != "amd64" ]]; then
|
|
dokku_log_warn "Detected linux/amd64 image, forcing --platform=linux/amd64"
|
|
DOCKER_ARGS+=" --platform=linux/amd64"
|
|
fi
|
|
|
|
if [[ -n "$DOKKU_RUN_TTL_SECONDS" ]]; then
|
|
DOCKER_ARGS+=" --label=com.dokku.active-deadline-seconds=$DOKKU_RUN_TTL_SECONDS"
|
|
fi
|
|
|
|
# shellcheck disable=SC2124
|
|
DOCKER_ARGS+=" --label=com.dokku.container-type=$PROCESS_TYPE"
|
|
DOCKER_ARGS+=" --label=com.dokku.app-name=$APP"
|
|
# $DOKKU_GLOBAL_RUN_ARGS"
|
|
DOCKER_ARGS+=" $IMAGE"
|
|
DOCKER_ARGS+=" $EXEC_CMD"
|
|
|
|
declare -a ARG_ARRAY
|
|
eval "ARG_ARRAY=($DOCKER_ARGS)"
|
|
|
|
RUN_COMMAND=("$@")
|
|
if [[ "${#RUN_COMMAND[@]}" -eq 0 ]]; then
|
|
if [[ -z "$DOKKU_SHELL" ]]; then
|
|
local DOKKU_APP_SHELL=$(fn-plugin-property-get-default "scheduler" "$APP" "shell" "")
|
|
local DOKKU_GLOBAL_SHELL=$(fn-plugin-property-get-default "scheduler" "--global" "shell" "")
|
|
local DOKKU_SHELL=${DOKKU_APP_SHELL:="$DOKKU_GLOBAL_SHELL"}
|
|
fi
|
|
|
|
if [[ -z "$DOKKU_SHELL" ]]; then
|
|
DOKKU_SHELL="/bin/bash"
|
|
fi
|
|
ARG_ARRAY=("${ARG_ARRAY[@]}" "$DOKKU_SHELL")
|
|
else
|
|
ARG_ARRAY=("${ARG_ARRAY[@]}" "${RUN_COMMAND[@]}")
|
|
fi
|
|
|
|
CONTAINER_ID=$(fn-scheduler-docker-local-start-app-container "$APP" "${ARG_ARRAY[@]}")
|
|
plugn trigger post-container-create "app" "$CONTAINER_ID" "$APP" "run"
|
|
|
|
declare -a DOCKER_START_ARGS_ARRAY
|
|
if [[ "$DOKKU_DETACH_CONTAINER" != "1" ]]; then
|
|
DOCKER_START_ARGS_ARRAY+=("--attach")
|
|
|
|
has_tty && DOCKER_START_ARGS_ARRAY+=("--interactive")
|
|
fi
|
|
|
|
local EXIT_CODE=0 DOKKU_CONTAINER_EXIT_CODE=0
|
|
if [[ "$DOKKU_DETACH_CONTAINER" == "1" ]]; then
|
|
"$DOCKER_BIN" container start "${DOCKER_START_ARGS_ARRAY[@]}" "$CONTAINER_ID" >/dev/null || DOKKU_CONTAINER_EXIT_CODE=$?
|
|
"$DOCKER_BIN" container inspect --format "{{.Name}}" "$CONTAINER_ID" | cut -c2-
|
|
else
|
|
"$DOCKER_BIN" container start "${DOCKER_START_ARGS_ARRAY[@]}" "$CONTAINER_ID" || EXIT_CODE=$?
|
|
DOKKU_CONTAINER_EXIT_CODE="$("$DOCKER_BIN" container wait "$CONTAINER_ID" 2>/dev/null || echo "$EXIT_CODE")"
|
|
[[ -z "$DOKKU_CONTAINER_EXIT_CODE" ]] && DOKKU_CONTAINER_EXIT_CODE=0
|
|
fi
|
|
|
|
plugn trigger scheduler-post-run "$DOKKU_SCHEDULER" "$APP" "$CONTAINER_ID" "$DOKKU_CONTAINER_EXIT_CODE"
|
|
return "$DOKKU_CONTAINER_EXIT_CODE"
|
|
}
|
|
|
|
trigger-scheduler-docker-local-scheduler-run "$@"
|