feat(controller-peers-env-fallback): fall back to XCE_CONTROLLER_PEERS in the controller and name the value's source (task 2.3)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-03 06:14:25 +00:00
parent 25e2807355
commit 64d3429cd8
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
3 changed files with 154 additions and 14 deletions

View file

@ -320,7 +320,7 @@ case_controller_log_flushed_on_early_exit() {
_show_tail "$d/stderr"
return 1
fi
if ! grep -Eq -- 'No --peers flag; running as single-node primary' \
if ! grep -Eq -- 'No --peers flag and XCE_CONTROLLER_PEERS unset or empty; running as single-node primary' \
"$d/controller.log" 2>/dev/null; then
missing=$((missing + 1))
red " run $i: last startup line missing from $d/controller.log"
@ -335,6 +335,127 @@ case_controller_log_flushed_on_early_exit() {
add_case case_controller_log_flushed_on_early_exit \
"controller: log flushed before the certificate pre-flight exit ($FLUSH_RUNS runs)"
# ── Task 2.3 (Req 1.1-1.5, 1.7, 1.8): controller resolves its candidate list
# from --peers, else XCE_CONTROLLER_PEERS, else runs standalone.
#
# run_controller <dir> <env-args...> -- [controller args...]
# Run the controller with scratch --workdir/--certdir (empty)/--logfile in
# <dir>, so it stops at the certificate pre-flight. <env-args> are env(1)
# arguments (NAME=value or `-u NAME`) placed before the binary.
run_controller() {
local dir="$1"; shift
local envargs=()
while [ $# -gt 0 ] && [ "$1" != -- ]; do
envargs+=("$1"); shift
done
[ $# -gt 0 ] && shift
mkdir -p "$dir/work" "$dir/certs"
run_to_completion "$dir" 10 "${envargs[@]}" "$CONTROLLER_BIN" \
--workdir "$dir/work" --certdir "$dir/certs" \
--logfile "$dir/controller.log" "$@"
}
# The cert pre-flight (or an argument error) must have stopped the run: a
# zero status or a timeout means it went further than these cases expect.
_assert_stopped_early() {
if [ "$RUN_RC" -eq 0 ] || [ "$RUN_RC" -ge 124 ]; then
red " expected the controller to stop early, exit status $RUN_RC"
_show_tail "$1/stderr"
return 1
fi
}
ENV3="a=localhost:1,b=localhost:2,c=localhost:3"
STANDALONE_RE='No --peers flag and XCE_CONTROLLER_PEERS unset or empty; running as single-node primary'
case_controller_env_list() {
local d; d="$(new_scratch controller-env-list)"
run_controller "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- --myname a
_assert_stopped_early "$d" || return 1
assert_grep "$d/controller.log" 'HA mode: 3 controller candidates, identity=a' || return 1
assert_no_grep "$d/controller.log" 'No --peers flag' || return 1
}
add_case case_controller_env_list \
"controller: XCE_CONTROLLER_PEERS used when --peers is absent (1.2)"
case_controller_peers_wins() {
local d; d="$(new_scratch controller-peers-wins)"
run_controller "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- \
--myname solo --peers solo=localhost:7
_assert_stopped_early "$d" || return 1
assert_grep "$d/controller.log" 'HA mode: 1 controller candidates, identity=solo' || return 1
assert_no_grep "$d/controller.log" 'HA mode: 3 controller candidates' || return 1
assert_no_grep "$d/controller.log" 'from XCE_CONTROLLER_PEERS' || return 1
}
add_case case_controller_peers_wins \
"controller: explicit --peers wins over XCE_CONTROLLER_PEERS (1.1)"
case_controller_neither_set() {
local d; d="$(new_scratch controller-neither)"
run_controller "$d" -u XCE_CONTROLLER_PEERS -- --myname ctrl-none
_assert_stopped_early "$d" || return 1
assert_grep "$d/controller.log" "$STANDALONE_RE" || return 1
assert_no_grep "$d/controller.log" 'HA mode' || return 1
}
add_case case_controller_neither_set \
"controller: neither --peers nor the variable -> standalone, line names the variable (1.3, 1.8)"
case_controller_env_empty() {
local d; d="$(new_scratch controller-env-empty)"
run_controller "$d" "XCE_CONTROLLER_PEERS=" -- --myname ctrl-empty
_assert_stopped_early "$d" || return 1
assert_grep "$d/controller.log" "$STANDALONE_RE" || return 1
assert_no_grep "$d/controller.log" 'HA mode' || return 1
}
add_case case_controller_env_empty \
"controller: empty XCE_CONTROLLER_PEERS behaves as unset (1.7, 1.8)"
case_controller_parse_error_source() {
local d
d="$(new_scratch controller-parse-env)"
run_controller "$d" "XCE_CONTROLLER_PEERS=a=nocolon" -- --myname a
assert_rc 1 || return 1
assert_grep "$d/stderr" 'XCE_CONTROLLER_PEERS parse error' "stderr (env value)" || return 1
d="$(new_scratch controller-parse-flag)"
run_controller "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- --myname a --peers a=nocolon
assert_rc 1 || return 1
assert_grep "$d/stderr" -- '--peers parse error' "stderr (--peers value)" || return 1
assert_no_grep "$d/stderr" 'XCE_CONTROLLER_PEERS' "stderr (--peers value)" || return 1
}
add_case case_controller_parse_error_source \
"controller: parse error names --peers or XCE_CONTROLLER_PEERS (1.4)"
case_controller_even_count_source() {
local d
d="$(new_scratch controller-even-env)"
run_controller "$d" "XCE_CONTROLLER_PEERS=a=localhost:1,b=localhost:2" -- --myname a
assert_rc 1 || return 1
assert_grep "$d/stderr" 'XCE_CONTROLLER_PEERS: even peer count \(2\)' "stderr (env value)" || return 1
d="$(new_scratch controller-even-flag)"
run_controller "$d" "XCE_CONTROLLER_PEERS=$ENV3" -- --myname a \
--peers a=localhost:1,b=localhost:2
assert_rc 1 || return 1
assert_grep "$d/stderr" -- '--peers: even peer count \(2\)' "stderr (--peers value)" || return 1
assert_no_grep "$d/stderr" 'XCE_CONTROLLER_PEERS' "stderr (--peers value)" || return 1
}
add_case case_controller_even_count_source \
"controller: even-count error names --peers or XCE_CONTROLLER_PEERS (1.4)"
case_controller_help_names_variable() {
local d; d="$(new_scratch controller-help)"
run_to_completion "$d" 10 -u XCE_CONTROLLER_PEERS "$CONTROLLER_BIN" --help
assert_rc 0 || return 1
# argp wraps help text, so join the lines before matching.
tr '\n' ' ' <"$d/stdout" | tr -s ' ' >"$d/help.txt"
assert_grep "$d/help.txt" 'XCE_CONTROLLER_PEERS' "--help output" || return 1
assert_grep "$d/help.txt" 'unset or empty' "--help output" || return 1
assert_grep "$d/help.txt" 'standalone' "--help output" || return 1
}
add_case case_controller_help_names_variable \
"controller: --help documents XCE_CONTROLLER_PEERS and the opt-out (1.5, 1.7)"
# ════════════════════════════════════════════════════════════════════════════
# main