Files
FabledSteward/tests/test_ansible_run_end.py
T
bvandeusenandClaude Opus 5.5 e2055242f1
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 1m24s
CI / unit (push) Successful in 1m32s
CI / publish (push) Successful in 1m6s
fix(host_agent): disks behind a RAID controller each keep their own name (#5806)
smartctl reports every disk behind a PERC/MegaRAID controller as /dev/bus/0
with type megaraid,N; the helper named a drive by its path alone, so all of
VDNT-Docker02's and Docker03's disks read as one drive "0", each overwriting
the last. The slot is now part of the name (bus0-megaraid3), and Steward gives
a repeated name an ordinal so two drives never share a series. Agent 1.20.1.

fix(ansible): Steward stopping mid-run logs no traceback (#5749)

The run's done-callback called exception() on a cancelled task, which raises;
it now logs a run cut short by shutdown at INFO. A finished run's in-memory
state is dropped by a timer rather than a sleeping task, which shutdown found
still pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:41:20 -04:00

53 lines
2.0 KiB
Python

"""#5749: a redeploy during an Ansible run logged two CancelledError tracebacks
from the run's done-callback and two "Task was destroyed but it is pending!"
lines for its in-memory cleanup. Steward stopping mid-run is not an error: the
next start marks the run interrupted."""
import asyncio
import logging
from steward.ansible import executor
from steward.ansible.runner import run_ended
class _App:
logger = logging.getLogger("test.ansible.run_end")
async def test_a_run_cut_short_by_shutdown_logs_no_error(caplog):
async def run():
await asyncio.sleep(60)
task = asyncio.create_task(run())
task.add_done_callback(run_ended(_App, "r1"))
await asyncio.sleep(0)
task.cancel()
with caplog.at_level(logging.INFO, logger="test.ansible.run_end"):
await asyncio.gather(task, return_exceptions=True)
await asyncio.sleep(0) # done-callbacks run on the next turn
assert [r.levelname for r in caplog.records] == ["INFO"]
assert "Ansible run r1 interrupted" in caplog.records[0].getMessage()
async def test_a_run_that_raised_is_still_an_error(caplog):
async def run():
raise RuntimeError("ansible-playbook vanished")
task = asyncio.create_task(run())
task.add_done_callback(run_ended(_App, "r2"))
with caplog.at_level(logging.INFO, logger="test.ansible.run_end"):
await asyncio.gather(task, return_exceptions=True)
await asyncio.sleep(0)
assert [(r.levelname, r.getMessage()) for r in caplog.records] == [
("ERROR", "Ansible run r2 raised: ansible-playbook vanished")]
async def test_a_finished_run_s_state_is_dropped_by_a_timer_not_a_task(monkeypatch):
"""A task left sleeping is what shutdown found pending; a timer isn't one."""
monkeypatch.setattr(executor, "_MEM_TTL_SECS", 0.01)
executor._run_lines["r3"] = ["ok"]
before = asyncio.all_tasks()
executor._schedule_cleanup("r3")
assert asyncio.all_tasks() == before
await asyncio.sleep(0.05)
assert "r3" not in executor._run_lines