fix(xceadmin): probe_config uses Request envelope + follow_redirects (bug-1506, bug-1507)
- probe_config() now wraps probe in Request envelope matching push_config() - Controller OPCode_probeConfigTag handler replies through xce_reply() with redirectHost/redirectPort populated - follow_redirects works identically for both push and probe flows
This commit is contained in:
parent
d70bf6a402
commit
b00e97ffe6
3 changed files with 86 additions and 54 deletions
|
|
@ -271,16 +271,18 @@ def test_config_push_connection_refused_exits_nonzero_not_raw_traceback(cluster_
|
|||
assert result.output.strip() != ""
|
||||
|
||||
|
||||
def test_config_push_dry_run_reports_generations(mock_controller, cluster_bin):
|
||||
def test_config_push_dry_run_reports_generations(mock_controller, cluster_bin, wrap_reply):
|
||||
from xcecommon import wire
|
||||
|
||||
mod = load_schema()
|
||||
|
||||
def _handler(conn):
|
||||
wire.recv_frame(conn)
|
||||
reply = mod.ProbeConfigTagReply.new_message()
|
||||
reply.configTag = 4
|
||||
wire.send_frame(conn, reply.to_bytes())
|
||||
inner = mod.RequestReply.new_message()
|
||||
inner.status = 0
|
||||
probe_reply = inner.data.init("probeconfigtagreplymsg")
|
||||
probe_reply.configTag = 4
|
||||
wire.send_frame(conn, wrap_reply(inner))
|
||||
|
||||
srv = mock_controller(_handler)
|
||||
|
||||
|
|
|
|||
|
|
@ -244,19 +244,29 @@ def test_push_config_explicit_port_parsed():
|
|||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_probe_config_reports_current_and_would_be_generation(mock_controller, cluster_bin):
|
||||
def test_probe_config_reports_current_and_would_be_generation(mock_controller, cluster_bin, wrap_reply):
|
||||
"""bug-1507: probe_config now sends a Request envelope and decodes
|
||||
through follow_redirects → decode_reply, matching push_config's path.
|
||||
The mock server must unwrap the Request envelope on receive and wrap
|
||||
its reply the same way a real controller does. """
|
||||
mod = load_schema()
|
||||
received = {}
|
||||
|
||||
def _handler(conn):
|
||||
request_bytes = wire.recv_frame(conn)
|
||||
received["request_bytes"] = request_bytes
|
||||
with mod.ProbeConfigTagRequest.from_bytes(request_bytes) as req:
|
||||
received["name"] = req.name
|
||||
# Request{opcode: probeConfigTag, body.probeconfigtagrequestmsg: ...}
|
||||
with mod.Request.from_bytes(request_bytes) as req:
|
||||
assert req.opcode == "probeConfigTag"
|
||||
assert req.body.which() == "probeconfigtagrequestmsg"
|
||||
received["name"] = req.body.probeconfigtagrequestmsg.name
|
||||
|
||||
reply = mod.ProbeConfigTagReply.new_message()
|
||||
reply.configTag = 41
|
||||
wire.send_frame(conn, reply.to_bytes())
|
||||
# Build reply: RequestReply{status:0, data.probeconfigtagreplymsg: {configTag:41}}
|
||||
inner = mod.RequestReply.new_message()
|
||||
inner.status = 0
|
||||
probe_reply = inner.data.init("probeconfigtagreplymsg")
|
||||
probe_reply.configTag = 41
|
||||
wire.send_frame(conn, wrap_reply(inner))
|
||||
|
||||
srv = mock_controller(_handler)
|
||||
|
||||
|
|
@ -266,21 +276,22 @@ def test_probe_config_reports_current_and_would_be_generation(mock_controller, c
|
|||
assert result.would_be_generation == 42
|
||||
assert result.accepted is True
|
||||
assert result.reason == ""
|
||||
assert received["name"] == "" # matches config_repl.c's xce_probe_config_tag exactly
|
||||
assert received["name"] == ""
|
||||
|
||||
|
||||
def test_probe_config_zero_generation_still_accepted(mock_controller, cluster_bin):
|
||||
def test_probe_config_zero_generation_still_accepted(mock_controller, cluster_bin, wrap_reply):
|
||||
"""A fresh cluster with no config committed yet (configTag == 0) is
|
||||
still a successful probe -- there is no rejection signal on this
|
||||
wire shape (module docstring); the caller decides significance.
|
||||
"""
|
||||
still a successful probe -- configTag == 0 is a valid, real response
|
||||
from a real controller handler now (bug-1506). """
|
||||
mod = load_schema()
|
||||
|
||||
def _handler(conn):
|
||||
wire.recv_frame(conn)
|
||||
reply = mod.ProbeConfigTagReply.new_message()
|
||||
reply.configTag = 0
|
||||
wire.send_frame(conn, reply.to_bytes())
|
||||
inner = mod.RequestReply.new_message()
|
||||
inner.status = 0
|
||||
probe_reply = inner.data.init("probeconfigtagreplymsg")
|
||||
probe_reply.configTag = 0
|
||||
wire.send_frame(conn, wrap_reply(inner))
|
||||
|
||||
srv = mock_controller(_handler)
|
||||
|
||||
|
|
@ -293,27 +304,23 @@ def test_probe_config_zero_generation_still_accepted(mock_controller, cluster_bi
|
|||
|
||||
@pytest.mark.parametrize("tag_value", [0, 1, 999999])
|
||||
def test_probe_config_has_no_wire_level_rejection_signal_by_design(
|
||||
mock_controller, cluster_bin, tag_value
|
||||
mock_controller, cluster_bin, tag_value, wrap_reply
|
||||
):
|
||||
"""5.6 asks for both an accepted and a rejected dry-run outcome, but
|
||||
``ProbeConfigTagReply`` (module docstring, ``push.py`` module
|
||||
docstring) has only a bare ``configTag`` -- no field exists on the
|
||||
real wire contract to signal rejection, matching the real C
|
||||
reference client (``config_repl.c``'s ``xce_probe_config_tag``, which
|
||||
also returns only a bare tag). This test locks in that limitation
|
||||
explicitly rather than silently having no coverage for it: every
|
||||
successful round-trip, regardless of the returned ``configTag``
|
||||
value, yields ``accepted=True`` -- there is no reachable code path
|
||||
that produces ``accepted=False`` today. A real "would this SHA be
|
||||
accepted" check is future controller-side work (Requirement 6.1).
|
||||
"""
|
||||
"""ProbeConfigTagReply (controller.capnp:909) has only a bare
|
||||
``configTag`` field -- no separate accept/reject flag exists. A
|
||||
real controller handler (bug-1506) always returns status==0 here;
|
||||
every successful round-trip, regardless of the returned configTag
|
||||
value, yields ``accepted=True``. A real "would this SHA be accepted"
|
||||
check is future work (Requirement 6.1). """
|
||||
mod = load_schema()
|
||||
|
||||
def _handler(conn):
|
||||
wire.recv_frame(conn)
|
||||
reply = mod.ProbeConfigTagReply.new_message()
|
||||
reply.configTag = tag_value
|
||||
wire.send_frame(conn, reply.to_bytes())
|
||||
inner = mod.RequestReply.new_message()
|
||||
inner.status = 0
|
||||
probe_reply = inner.data.init("probeconfigtagreplymsg")
|
||||
probe_reply.configTag = tag_value
|
||||
wire.send_frame(conn, wrap_reply(inner))
|
||||
|
||||
srv = mock_controller(_handler)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue