fix: validate run:logs arguments

This commit is contained in:
Jose Diaz-Gonzalez
2026-09-24 18:43:50 -04:00
parent 114c6115b9
commit 1516f84cee
5 changed files with 137 additions and 57 deletions

View File

@@ -206,13 +206,17 @@ cmd-run-logs() {
dokku_log_fail "No container or app specified"
fi
if ! is_number "$NUM"; then
dokku_log_fail "Invalid value for num: must be an integer"
fi
if [[ -n "$CONTAINER_NAME" ]]; then
if [[ "$(echo "$CONTAINER_NAME" | grep -o '\.' | wc -l)" -ne 2 ]]; then
dokku_log_fail "Invalid container name specified: $CONTAINER_NAME"
fi
if [[ -n "$APP" ]] && [[ "$APP" != "$(echo "$CONTAINER_NAME" | cut -d'.' -f1)" ]]; then
dokku_log_fail "Specified app does not app in container name"
dokku_log_fail "Specified app does not match app in container name"
fi
APP="$(echo "$CONTAINER_NAME" | cut -d'.' -f1)"

View File

@@ -3,18 +3,31 @@ set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
fn-scheduler-docker-local-container-logs() {
declare desc="outputs logs for a single app container"
declare CID="$1" DYNO="$2" PRETTY_PRINT="$3" COLOR="$4"
shift 4
if [[ "$PRETTY_PRINT" == "true" ]]; then
"$DOCKER_BIN" logs "$@" "$CID" 2>&1
return
fi
"$DOCKER_BIN" logs -t "$@" "$CID" 2>&1 | sed -u -r "s/^([^Z]+Z )/\x1b[${COLOR}m\1app[${DYNO}]:\x1b[0m /gm"
}
trigger-scheduler-docker-local-scheduler-logs() {
declare desc="scheduler-docker-local scheduler-logs plugin trigger"
declare trigger="scheduler-logs"
declare DOKKU_SCHEDULER="$1" APP="$2" PROCESS_TYPE="$3" TAIL="$4" PRETTY_PRINT="$5" NUM="$6"
local DOKKU_LOGS_ARGS=""
local DOCKER_LOGS_ARGS=("--tail" "$NUM")
if [[ "$DOKKU_SCHEDULER" != "docker-local" ]]; then
return
fi
if [[ "$TAIL" == "true" ]]; then
DOKKU_LOGS_ARGS="--follow "
DOCKER_LOGS_ARGS+=("--follow")
fi
local APP_ROOT="$DOKKU_ROOT/$APP"
@@ -26,25 +39,19 @@ trigger-scheduler-docker-local-scheduler-logs() {
fi
[[ -z $(stat -t "${CONTAINERS[0]}" 2>/dev/null) ]] && exit 0
local DOKKU_LOGS_ARGS+="--tail $NUM"
((MAX_INDEX = ${#CONTAINERS[*]} - 1)) || true
for i in ${!CONTAINERS[*]}; do
local DYNO=$(echo "${CONTAINERS[i]}" | sed -r 's/.*CONTAINER\.(.*)/\1/')
local CID=$(<"${CONTAINERS[i]}")
local COLOR=${COLORS[i % ${#COLORS[*]}]}
if [[ $PRETTY_PRINT == "true" ]]; then
local DOKKU_LOGS_CMD+="($DOCKER_BIN logs $DOKKU_LOGS_ARGS $CID 2>&1)"
local MAX_INDEX
((MAX_INDEX = ${#CONTAINERS[@]} - 1)) || true
for i in "${!CONTAINERS[@]}"; do
local DYNO="$(echo "${CONTAINERS[i]}" | sed -r 's/.*CONTAINER\.(.*)/\1/')"
local CID="$(<"${CONTAINERS[i]}")"
local COLOR="${COLORS[i % ${#COLORS[@]}]}"
if [[ "$i" != "$MAX_INDEX" ]]; then
fn-scheduler-docker-local-container-logs "$CID" "$DYNO" "$PRETTY_PRINT" "$COLOR" "${DOCKER_LOGS_ARGS[@]}" &
else
local DOKKU_LOGS_PRETTY_PRINT_CMD="sed -u -r 's/^([^Z]+Z )/\x1b[${COLOR}m\1app[$DYNO]:\x1b[0m /gm'"
local DOKKU_LOGS_CMD+="($DOCKER_BIN logs -t $DOKKU_LOGS_ARGS $CID 2>&1 | $DOKKU_LOGS_PRETTY_PRINT_CMD)"
fi
if [[ $i != "$MAX_INDEX" ]]; then
local DOKKU_LOGS_CMD+="& "
else
local DOKKU_LOGS_CMD+="; "
fn-scheduler-docker-local-container-logs "$CID" "$DYNO" "$PRETTY_PRINT" "$COLOR" "${DOCKER_LOGS_ARGS[@]}"
fi
done
bash -c "($DOKKU_LOGS_CMD)"
wait
}
trigger-scheduler-docker-local-scheduler-logs "$@"

View File

@@ -8,7 +8,7 @@ trigger-scheduler-docker-local-scheduler-logs-failed() {
declare trigger="scheduler-logs-failed"
declare DOKKU_SCHEDULER="$1" APP="$2"
local FAILED_CONTAINERS_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/$APP/failed-containers"
local DEAD_CONTAINERS=() DOKKU_LOGS_CMD=() RUNNING_CONTAINERS=()
local DEAD_CONTAINERS=() RUNNING_CONTAINERS=()
local CID LINE PREFIX
shift 2
@@ -41,17 +41,16 @@ trigger-scheduler-docker-local-scheduler-logs-failed() {
return
fi
((MAX_INDEX = ${#RUNNING_CONTAINERS[*]} - 1)) || true
for i in ${!RUNNING_CONTAINERS[*]}; do
local CID="${RUNNING_CONTAINERS[i]}"
DOKKU_LOGS_CMD+="($DOCKER_BIN logs $DOKKU_LOGS_ARGS $CID 2>&1)"
if [[ $i != "$MAX_INDEX" ]]; then
local DOKKU_LOGS_CMD+="& "
local MAX_INDEX
((MAX_INDEX = ${#RUNNING_CONTAINERS[@]} - 1)) || true
for i in "${!RUNNING_CONTAINERS[@]}"; do
if [[ "$i" != "$MAX_INDEX" ]]; then
"$DOCKER_BIN" logs "${RUNNING_CONTAINERS[i]}" 2>&1 &
else
local DOKKU_LOGS_CMD+="; "
"$DOCKER_BIN" logs "${RUNNING_CONTAINERS[i]}" 2>&1
fi
done
bash -c "($DOKKU_LOGS_CMD)"
wait
}
trigger-scheduler-docker-local-scheduler-logs-failed "$@"

View File

@@ -3,51 +3,59 @@ set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
fn-scheduler-docker-local-run-container-logs() {
declare desc="outputs logs for a single run container"
declare CONTAINER_NAME="$1" PRETTY_PRINT="$2" COLOR="$3"
shift 3
local DYNO="$(echo "$CONTAINER_NAME" | cut -d. -f3)"
if [[ "$PRETTY_PRINT" == "true" ]]; then
"$DOCKER_BIN" logs "$@" "$CONTAINER_NAME" 2>&1
return
fi
"$DOCKER_BIN" logs -t "$@" "$CONTAINER_NAME" 2>&1 | sed -u -r "s/^([^Z]+Z )/\x1b[${COLOR}m\1app[${DYNO}]:\x1b[0m /gm"
}
trigger-scheduler-docker-local-scheduler-logs() {
declare desc="scheduler-docker-local scheduler-logs plugin trigger"
declare trigger="scheduler-logs"
declare DOKKU_SCHEDULER="$1" APP="$2" CONTAINER_NAME="$3" TAIL="$4" PRETTY_PRINT="$5" NUM="$6"
local DOKKU_LOGS_ARGS=""
local DOCKER_LOGS_ARGS=("--tail" "$NUM")
local COLORS=(36 33 32 35 31)
local CONTAINERS=() NAME NAMES
if [[ "$DOKKU_SCHEDULER" != "docker-local" ]]; then
return
fi
if [[ "$TAIL" == "true" ]]; then
DOKKU_LOGS_ARGS="--follow "
DOCKER_LOGS_ARGS+=("--follow")
fi
local COLORS=(36 33 32 35 31)
if [[ -n "$CONTAINER_NAME" ]]; then
local CONTAINERS=("$CONTAINER_NAME")
else
local CONTAINERS=()
NAMES="$("$DOCKER_BIN" container ls --all --filter "label=com.dokku.app-name=$APP" --filter "label=com.dokku.container-type=run" --format '{{ .Names }}')"
while IFS= read -r CONTAINER_NAME; do
CONTAINERS+=("$CONTAINER_NAME")
done <<<"$NAMES"
fi
local DOKKU_LOGS_ARGS+="--tail $NUM"
((MAX_INDEX = ${#CONTAINERS[*]} - 1)) || true
for i in ${!CONTAINERS[*]}; do
local DYNO="$(echo "${CONTAINERS[i]}" | cut -d. -f3)"
local CID="${CONTAINERS[i]}"
local COLOR=${COLORS[i % ${#COLORS[*]}]}
if [[ $PRETTY_PRINT == "true" ]]; then
local DOKKU_LOGS_CMD+="($DOCKER_BIN logs $DOKKU_LOGS_ARGS $CID 2>&1)"
else
local DOKKU_LOGS_PRETTY_PRINT_CMD="sed -u -r 's/^([^Z]+Z )/\x1b[${COLOR}m\1app[$DYNO]:\x1b[0m /gm'"
local DOKKU_LOGS_CMD+="($DOCKER_BIN logs -t $DOKKU_LOGS_ARGS $CID 2>&1 | $DOKKU_LOGS_PRETTY_PRINT_CMD)"
NAMES="$("$DOCKER_BIN" container ls --all --filter "label=com.dokku.app-name=$APP" --filter "label=com.dokku.container-type=run" --format '{{ .Names }}')"
while IFS= read -r NAME; do
[[ -z "$NAME" ]] && continue
if [[ -z "$CONTAINER_NAME" ]] || [[ "$NAME" == "$CONTAINER_NAME" ]]; then
CONTAINERS+=("$NAME")
fi
if [[ $i != "$MAX_INDEX" ]]; then
local DOKKU_LOGS_CMD+="& "
done <<<"$NAMES"
if [[ -n "$CONTAINER_NAME" ]] && [[ ${#CONTAINERS[@]} -eq 0 ]]; then
dokku_log_fail "Specified container does not exist"
fi
local MAX_INDEX
((MAX_INDEX = ${#CONTAINERS[@]} - 1)) || true
for i in "${!CONTAINERS[@]}"; do
local COLOR="${COLORS[i % ${#COLORS[@]}]}"
if [[ "$i" != "$MAX_INDEX" ]]; then
fn-scheduler-docker-local-run-container-logs "${CONTAINERS[i]}" "$PRETTY_PRINT" "$COLOR" "${DOCKER_LOGS_ARGS[@]}" &
else
local DOKKU_LOGS_CMD+="; "
fn-scheduler-docker-local-run-container-logs "${CONTAINERS[i]}" "$PRETTY_PRINT" "$COLOR" "${DOCKER_LOGS_ARGS[@]}"
fi
done
bash -c "($DOKKU_LOGS_CMD)"
wait
}
trigger-scheduler-docker-local-scheduler-logs "$@"

View File

@@ -140,3 +140,65 @@ teardown() {
assert_success
assert_output_not_contains "$container_id"
}
@test "(run:logs) run:logs" {
run deploy_app
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku run:detached $TEST_APP worker"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku run:list $TEST_APP --format json | jq -r '.[0].name'"
echo "output: $output"
echo "status: $status"
assert_success
local RUN_CONTAINER="$output"
sleep 5
run /bin/bash -c "dokku run:logs $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "sleeping for 60 seconds"
run /bin/bash -c "dokku run:logs $TEST_APP -n 1 -q"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "sleeping for 60 seconds"
run /bin/bash -c "dokku run:logs --container $RUN_CONTAINER -q"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "sleeping for 60 seconds"
run /bin/bash -c "dokku run:stop $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
}
@test "(run:logs) invalid arguments" {
run /bin/bash -c "dokku run:logs $TEST_APP -n abc"
echo "output: $output"
echo "status: $status"
assert_failure
assert_output_contains "Invalid value for num: must be an integer"
run /bin/bash -c "dokku run:logs $TEST_APP --container other-app.run.1"
echo "output: $output"
echo "status: $status"
assert_failure
assert_output_contains "Specified app does not match app in container name"
run /bin/bash -c "dokku run:logs --container $TEST_APP.run.1"
echo "output: $output"
echo "status: $status"
assert_failure
assert_output_contains "Specified container does not exist"
}