mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 19:01:54 +00:00
Every one of these call sites ended in `|| true`, so a failure left no trace and the surrounding script reported a clean run. service_converged.sh needed the `|| true` for a reason that had nothing to do with the command: under `set -o pipefail`, `head -10` closes the pipe and awk dies of SIGPIPE, which pipefail then reports as the pipeline's status. That made a genuine `container service ps` failure indistinguishable from a normal truncation. Capping inside awk (`n++ < 10`) removes the SIGPIPE, so the command status can be tested on its own and a real failure now prints why. give_up and report_failed_tasks carried a byte-identical copy of that block, so the fix lifts it into one report_tasks helper rather than applying it twice. The swarm-clean scripts keep going after a failed step on purpose, since the host layer below them clears what survives. They now say what did not work before continuing, instead of continuing silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
53 lines
1.5 KiB
Bash
53 lines
1.5 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
: "${SERVICE:?SERVICE env var is required}"
|
|
|
|
fail() {
|
|
echo "${SERVICE}: $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
report_tasks() {
|
|
local ps rows
|
|
if ! ps=$(timeout 15 container service ps "$SERVICE" --no-trunc \
|
|
--format '{{.Name}} {{.Node}} {{.DesiredState}} {{.CurrentState}} error={{.Error}}' 2>&1); then
|
|
printf '%s: service ps failed: %s\n' "${SERVICE}" "${ps}" >&2
|
|
return 0
|
|
fi
|
|
rows="$(printf '%s\n' "${ps}" | awk '!/error=$/ && n++ < 10')"
|
|
[ -n "${rows}" ] || return 0
|
|
printf '%s\n' "${rows}" >&2
|
|
}
|
|
|
|
give_up() {
|
|
echo "${SERVICE}: $1" >&2
|
|
report_tasks
|
|
exit 2
|
|
}
|
|
|
|
report_failed_tasks() {
|
|
echo "${SERVICE}: $1" >&2
|
|
report_tasks
|
|
exit 1
|
|
}
|
|
|
|
state=$(timeout 15 container service inspect "$SERVICE" \
|
|
--format '{{.UpdateStatus.State}}' 2>/dev/null) || state=""
|
|
case "$state" in
|
|
"" | "<no value>" | completed) ;;
|
|
rollback_started | rollback_completed) give_up "update was rolled back (UpdateStatus.State=${state}); the running spec is the previous one, not the desired one" ;;
|
|
paused | rollback_paused) give_up "update latched (UpdateStatus.State=${state}); it cannot leave this state on its own" ;;
|
|
*) fail "update in progress (UpdateStatus.State=${state})" ;;
|
|
esac
|
|
|
|
states=$(timeout 15 container service ps "$SERVICE" \
|
|
--filter desired-state=running \
|
|
--format '{{.CurrentState}}') || fail "service ps failed or timed out"
|
|
if [ -z "$states" ]; then
|
|
fail "no task carries desired-state=running"
|
|
fi
|
|
if grep -qvE '^Running' <<<"$states"; then
|
|
report_failed_tasks "tasks not running yet"
|
|
fi
|