feat(controller-peers-env-fallback): accept name= prefixes and report malformed controller entries cleanly (task 4.1)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-03 07:31:38 +00:00
parent 65ae25a1e6
commit 6eab344c6e
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
4 changed files with 89 additions and 7 deletions

View file

@ -8,7 +8,13 @@ import socket
import pytest
from xcecommon.errors import ConnectionTimeoutError, NoPrimaryError, ReplyDecodeError, TooManyRedirectsError
from xcecommon.errors import (
ConnectionTimeoutError,
ControllerValueError,
NoPrimaryError,
ReplyDecodeError,
TooManyRedirectsError,
)
from xcecommon.schema import load_schema
from xceadmin import discovery
@ -261,6 +267,40 @@ def test_resolve_controllers_strips_whitespace_and_drops_empty_entries():
]
def test_resolve_controllers_strips_name_prefix_from_single_entry():
# XCE_CONTROLLER_PEERS uses xce_parse_peers()'s "name=host:port" form;
# the name is the controller's Raft identity, not part of the address.
assert discovery.resolve_controllers("ctrl-1=somehost:1234") == [("somehost", 1234)]
def test_resolve_controllers_mixed_named_and_bare_entries_keep_order():
assert discovery.resolve_controllers("a=h1:1, h2:2,c=h3") == [
("h1", 1),
("h2", 2),
("h3", 9991),
]
def test_resolve_controllers_strips_only_up_to_the_first_equals_sign():
assert discovery.resolve_controllers("a=b=h:5") == [("b=h", 5)]
def test_resolve_controllers_empty_host_after_name_passes_through_like_a_bare_entry():
# "a=:5" parses exactly like ":5" does today: the name= stripping adds
# no host validation of its own.
assert discovery.resolve_controllers("a=:5") == discovery.resolve_controllers(":5") == [("", 5)]
@pytest.mark.parametrize("entry", ["a=h:x", "h:x", "ctrl-2=h:"])
def test_resolve_controllers_non_numeric_port_raises_controller_value_error(entry):
with pytest.raises(ControllerValueError) as excinfo:
discovery.resolve_controllers(f"good:1, {entry} ,other:2")
# The entry is quoted exactly as the user wrote it (name= included,
# surrounding whitespace stripped) so it can be found in the value.
assert f"'{entry}'" in excinfo.value.message
assert excinfo.value.entry == entry
# ---------------------------------------------------------------------------
# follow_redirects_any(): tries each (host, port) candidate in order,
# failing over past ones that are unreachable at the network level.