feat(controller-peers-env-fallback): fall back to XCE_CONTROLLER_PEERS in the worker (task 3.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
55193fcb4b
commit
05a7e6dd0c
3 changed files with 203 additions and 17 deletions
|
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Helpers and the *_BIN variables are used by the cases later tasks add (and
|
||||
# on_exit via trap), which shellcheck cannot see while the case list is empty.
|
||||
# shellcheck disable=SC2329,SC2034
|
||||
# main() runs every case through the registry ("$fn"), an indirect call that
|
||||
# the linter cannot follow, so it reports each case_* function -- and every
|
||||
# helper only cases call -- as never invoked (SC2329).
|
||||
# shellcheck disable=SC2329
|
||||
# verify-controller-peers-env.sh -- controller-peers-env-fallback regression
|
||||
# script (.kiro/specs/controller-peers-env-fallback, design.md "Testing
|
||||
# Strategy -> Scripted Regression Verification").
|
||||
|
|
@ -95,6 +96,8 @@ unset XCE_CONTROLLER_PEERS
|
|||
CONTROLLER_BIN=""
|
||||
SCHEDULER_BIN=""
|
||||
WORKER_BIN=""
|
||||
# Set by preflight; the harness cases (task 3.3) are its only reader.
|
||||
# shellcheck disable=SC2034
|
||||
HARNESS_BIN=""
|
||||
|
||||
# component:relative-path:variable
|
||||
|
|
@ -650,6 +653,150 @@ case_scheduler_sim_ignores_variable() {
|
|||
add_case case_scheduler_sim_ignores_variable \
|
||||
"scheduler: --sim never reaches the peers block, even with the variable set"
|
||||
|
||||
# ── Task 3.2 (Req 1.1-1.5, 1.7, 1.8): the worker (xcecd_virtual, which needs
|
||||
# no root) resolves its candidate list from --peers, else XCE_CONTROLLER_PEERS,
|
||||
# else the single-controller path. Its startup line is logged before the log
|
||||
# file is set up, so it lands on STDOUT. tlog writes it there unbuffered (the
|
||||
# line is in the redirected stdout file within ~0.3s while the worker keeps
|
||||
# running), so it is waited for while the worker runs, like the scheduler's.
|
||||
# The worker ignores SIGTERM for longer than stop_proc's 3s grace, so it is
|
||||
# SIGKILLed once the line is there. Argument errors exit on their own, before
|
||||
# the log directory is created; in an ASAN build those early returns must not
|
||||
# leak (the -l directory string), which the env-value error cases check.
|
||||
|
||||
WORKER_ANCHOR_RE='HA cluster config|No --peers flag'
|
||||
WORKER_STANDALONE_RE='No --peers flag and XCE_CONTROLLER_PEERS unset or empty; using single-controller path \(host=localhost port=9990\), version '
|
||||
|
||||
# _split_env_args: shared by start_worker/run_worker -- fills WENV with the
|
||||
# env(1) arguments before `--` and WARGS with the worker arguments after it.
|
||||
WENV=()
|
||||
WARGS=()
|
||||
_split_env_args() {
|
||||
WENV=(); WARGS=()
|
||||
while [ $# -gt 0 ] && [ "$1" != -- ]; do
|
||||
WENV+=("$1"); shift
|
||||
done
|
||||
[ $# -gt 0 ] && shift
|
||||
WARGS=("$@")
|
||||
}
|
||||
|
||||
# start_worker <dir> <env-args...> -- [worker args...]
|
||||
# Start xcecd_virtual in the background with -l <dir>/logs, wait for its
|
||||
# startup line on stdout, then kill it. Fails (with the output tails) when
|
||||
# the line never appears.
|
||||
start_worker() {
|
||||
local dir="$1" pid; shift
|
||||
_split_env_args "$@"
|
||||
start_bg "$dir" "${WENV[@]}" "$WORKER_BIN" -l "$dir/logs" \
|
||||
"${WARGS[@]+"${WARGS[@]}"}"
|
||||
pid="$LAST_PID"
|
||||
if ! wait_for_line "$dir/stdout" "$WORKER_ANCHOR_RE" 10 "$pid"; then
|
||||
kill -KILL "$pid" 2>/dev/null || true
|
||||
stop_proc "$pid"
|
||||
red " worker never printed its startup line"
|
||||
_show_tail "$dir/stdout"
|
||||
_show_tail "$dir/stderr"
|
||||
return 1
|
||||
fi
|
||||
kill -KILL "$pid" 2>/dev/null || true
|
||||
stop_proc "$pid"
|
||||
}
|
||||
|
||||
# run_worker <dir> <env-args...> -- [worker args...]
|
||||
# Run xcecd_virtual to completion (argument errors, -h) with -l <dir>/logs.
|
||||
run_worker() {
|
||||
local dir="$1"; shift
|
||||
_split_env_args "$@"
|
||||
run_to_completion "$dir" 10 "${WENV[@]}" "$WORKER_BIN" -l "$dir/logs" \
|
||||
"${WARGS[@]+"${WARGS[@]}"}"
|
||||
}
|
||||
|
||||
case_worker_env_list() {
|
||||
local d; d="$(new_scratch worker-env-list)"
|
||||
start_worker "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- -n w-env || return 1
|
||||
assert_grep "$d/stdout" \
|
||||
'HA cluster config: 3 candidate\(s\), identity=w-env \(from XCE_CONTROLLER_PEERS\), version ' "stdout" || return 1
|
||||
assert_no_grep "$d/stdout" 'No --peers flag' "stdout" || return 1
|
||||
}
|
||||
add_case case_worker_env_list \
|
||||
"worker: XCE_CONTROLLER_PEERS used when --peers is absent (1.2)"
|
||||
|
||||
case_worker_peers_wins() {
|
||||
local d; d="$(new_scratch worker-peers-wins)"
|
||||
start_worker "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- -n w-flag \
|
||||
--peers solo=localhost:7 || return 1
|
||||
assert_grep "$d/stdout" \
|
||||
'HA cluster config: 1 candidate\(s\), identity=w-flag, version ' "stdout" || return 1
|
||||
assert_no_grep "$d/stdout" '3 candidate|from XCE_CONTROLLER_PEERS' "stdout" || return 1
|
||||
}
|
||||
add_case case_worker_peers_wins \
|
||||
"worker: explicit --peers wins over XCE_CONTROLLER_PEERS (1.1)"
|
||||
|
||||
case_worker_neither_set() {
|
||||
local d; d="$(new_scratch worker-neither)"
|
||||
start_worker "$d" -u XCE_CONTROLLER_PEERS -- -n w-none || return 1
|
||||
assert_grep "$d/stdout" "$WORKER_STANDALONE_RE" "stdout" || return 1
|
||||
assert_no_grep "$d/stdout" 'HA cluster config' "stdout" || return 1
|
||||
}
|
||||
add_case case_worker_neither_set \
|
||||
"worker: neither --peers nor the variable -> single-controller path, line names the variable (1.3, 1.8)"
|
||||
|
||||
case_worker_env_empty() {
|
||||
local d; d="$(new_scratch worker-env-empty)"
|
||||
start_worker "$d" "XCE_CONTROLLER_PEERS=" -- -n w-empty || return 1
|
||||
assert_grep "$d/stdout" "$WORKER_STANDALONE_RE" "stdout" || return 1
|
||||
assert_no_grep "$d/stdout" 'HA cluster config' "stdout" || return 1
|
||||
}
|
||||
add_case case_worker_env_empty \
|
||||
"worker: empty XCE_CONTROLLER_PEERS behaves as unset (1.7, 1.8)"
|
||||
|
||||
case_worker_parse_error_source() {
|
||||
local d
|
||||
d="$(new_scratch worker-parse-env)"
|
||||
run_worker "$d" "XCE_CONTROLLER_PEERS=a=nocolon" -- -n w-perr
|
||||
assert_rc 1 || return 1
|
||||
assert_grep "$d/stderr" 'xcecd: XCE_CONTROLLER_PEERS parse error' "stderr (env value)" || return 1
|
||||
assert_no_grep "$d/stderr" 'LeakSanitizer' "stderr (ASAN build: early return must free)" || return 1
|
||||
|
||||
d="$(new_scratch worker-parse-flag)"
|
||||
run_worker "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- -n w-perr --peers a=nocolon
|
||||
assert_rc 1 || return 1
|
||||
assert_grep "$d/stderr" 'xcecd: --peers parse error' "stderr (--peers value)" || return 1
|
||||
assert_no_grep "$d/stderr" 'XCE_CONTROLLER_PEERS' "stderr (--peers value)" || return 1
|
||||
}
|
||||
add_case case_worker_parse_error_source \
|
||||
"worker: parse error names --peers or XCE_CONTROLLER_PEERS (1.4)"
|
||||
|
||||
case_worker_validate_error_source() {
|
||||
local d
|
||||
d="$(new_scratch worker-port0-env)"
|
||||
run_worker "$d" "XCE_CONTROLLER_PEERS=a=localhost:0" -- -n w-verr
|
||||
assert_rc 1 || return 1
|
||||
assert_grep "$d/stderr" 'xcecd: XCE_CONTROLLER_PEERS: invalid cluster config .* in "a=localhost:0"' "stderr (env value)" || return 1
|
||||
assert_no_grep "$d/stderr" 'LeakSanitizer' "stderr (ASAN build: early return must free)" || return 1
|
||||
|
||||
d="$(new_scratch worker-port0-flag)"
|
||||
run_worker "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- -n w-verr --peers a=localhost:0
|
||||
assert_rc 1 || return 1
|
||||
assert_grep "$d/stderr" 'xcecd: --peers: invalid cluster config .* in "a=localhost:0"' "stderr (--peers value)" || return 1
|
||||
assert_no_grep "$d/stderr" 'XCE_CONTROLLER_PEERS' "stderr (--peers value)" || return 1
|
||||
}
|
||||
add_case case_worker_validate_error_source \
|
||||
"worker: cluster-config validation error (port 0) names --peers or XCE_CONTROLLER_PEERS (1.4)"
|
||||
|
||||
case_worker_help_names_variable() {
|
||||
local d; d="$(new_scratch worker-help)"
|
||||
run_to_completion "$d" 10 -u XCE_CONTROLLER_PEERS "$WORKER_BIN" -h
|
||||
assert_rc 0 || return 1
|
||||
tr '\n' ' ' <"$d/stdout" | tr -s ' ' >"$d/help.txt"
|
||||
assert_grep "$d/help.txt" 'XCE_CONTROLLER_PEERS' "-h output" || return 1
|
||||
assert_grep "$d/help.txt" 'unset or empty' "-h output" || return 1
|
||||
assert_grep "$d/help.txt" 'single-controller' "-h output" || return 1
|
||||
assert_grep "$d/help.txt" 'sudo --preserve-env=XCE_CONTROLLER_PEERS' "-h output" || return 1
|
||||
}
|
||||
add_case case_worker_help_names_variable \
|
||||
"worker: -h documents XCE_CONTROLLER_PEERS, the opt-out and that sudo drops it (1.5, 1.7)"
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
# main
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue