feat(scheduler-core): build xceadmin scheduler recording client functions (task 10.3)
Adds record_start()/record_stop()/record_status() to new src/xceadmin/src/xceadmin/scheduler.py, following push_config()'s exact pipeline shape (load_schema -> follow_redirects -> decode_reply). Deliberately diverges from push_config()'s "return failure as data" convention because this task's own Observable text requires raising a typed error on an error reply, not just connection/decode failure -- a new SchedAdminError (xcecommon/errors.py) carries the full reply state (error/recording/file/ event_count/started_at) when SchedAdminReply.ok is false. test_scheduler.py mirrors test_config_push_mock.py's real mock-TLS-server technique, covering all three actions, redirect-following (standby-to- primary), and the error-reply-raises-SchedAdminError path across the error codes reference table. 188 passed, 3 skipped via the real xceadmin test runner (meson compile -C xce.build xceadmin).
This commit is contained in:
parent
30ff995cac
commit
b64875f4c3
5 changed files with 677 additions and 1 deletions
|
|
@ -21,6 +21,7 @@ from xcecommon.errors import (
|
|||
NoPrimaryError,
|
||||
ReplyDecodeError,
|
||||
ReservedNameError,
|
||||
SchedAdminError,
|
||||
SchemaNotFoundError,
|
||||
TooManyRedirectsError,
|
||||
ValidationError,
|
||||
|
|
@ -36,6 +37,7 @@ ALL_SUBCLASSES = [
|
|||
ReplyDecodeError,
|
||||
TooManyRedirectsError,
|
||||
NoPrimaryError,
|
||||
SchedAdminError,
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -171,6 +173,31 @@ def test_no_primary_error_carries_host_and_port() -> None:
|
|||
assert caught.port == 9991
|
||||
|
||||
|
||||
def test_sched_admin_error_carries_error_and_reply_state() -> None:
|
||||
"""Requirement 5.10 (declared here, raised by a later task): a
|
||||
``SchedAdminReply{ok=false, error=...}`` is surfaced as a typed error
|
||||
carrying the reason plus the reply's recording/file/event/started-at
|
||||
state (e.g. "already recording" still reports the current file)."""
|
||||
with pytest.raises(XceAdminError) as exc_info:
|
||||
raise SchedAdminError(
|
||||
"scheduler admin request failed: already recording",
|
||||
error="already recording",
|
||||
recording=True,
|
||||
file="/var/log/xce/current.replay",
|
||||
event_count=42,
|
||||
started_at=1234567890,
|
||||
)
|
||||
|
||||
caught = exc_info.value
|
||||
assert isinstance(caught, SchedAdminError)
|
||||
assert caught.message == "scheduler admin request failed: already recording"
|
||||
assert caught.error == "already recording"
|
||||
assert caught.recording is True
|
||||
assert caught.file == "/var/log/xce/current.replay"
|
||||
assert caught.event_count == 42
|
||||
assert caught.started_at == 1234567890
|
||||
|
||||
|
||||
def test_catching_base_type_recovers_message_for_every_subclass() -> None:
|
||||
"""The entire point of the shared exception contract (design.md,
|
||||
xceadmin.cli Implementation Note): a single `except XceAdminError as e`
|
||||
|
|
@ -186,6 +213,12 @@ def test_catching_base_type_recovers_message_for_every_subclass() -> None:
|
|||
(ReplyDecodeError("msg-f", reason="r"), "msg-f"),
|
||||
(TooManyRedirectsError("msg-g", hops=3), "msg-g"),
|
||||
(NoPrimaryError("msg-h", host="h", port=1), "msg-h"),
|
||||
(
|
||||
SchedAdminError(
|
||||
"msg-i", error="e", recording=False, file="", event_count=0, started_at=0
|
||||
),
|
||||
"msg-i",
|
||||
),
|
||||
]
|
||||
|
||||
for exc, expected_message in cases:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue