diff --git a/tests/integration/test_docker.py b/tests/integration/test_docker.py index 3dfae2a..48b7479 100644 --- a/tests/integration/test_docker.py +++ b/tests/integration/test_docker.py @@ -214,6 +214,7 @@ def test_persist_logs_stores_lines(app): def test_persist_logs_respects_toggle_and_exclude(app): """Server-side controls (Settings): an excluded container's lines are dropped while others persist; the global toggle off stores nothing new.""" + from types import SimpleNamespace from sqlalchemy import text from steward.models.hosts import Host from steward.core.settings import set_setting @@ -225,33 +226,41 @@ def test_persist_logs_respects_toggle_and_exclude(app): {"container": "noisy", "stream": "stdout", "ts": None, "line": "drop-me"}, ])] + hid = str(uuid.uuid4()) + # Stand-in host: the logs-only persist path reads only host.id, so a plain + # object sidesteps ORM attribute-expiry across the commit boundaries below. + host = SimpleNamespace(id=hid, name="loghost3") + async def _go(): async with app.db_sessionmaker() as s: + # Back-to-back begin blocks with NO read in between — a SELECT between + # them would autobegin a txn and make the next begin() collide. async with s.begin(): await s.execute(text("DELETE FROM docker_logs")) await set_setting(s, "docker.logs.enabled", True) await set_setting(s, "docker.logs.exclude", ["noisy"]) - h = Host(id=str(uuid.uuid4()), name="loghost3", address="10.7.7.10") - s.add(h) - await s.flush() - hid = h.id - await persist(s, h, [], None, None, batch) - kept = {r[0] for r in (await s.execute(text( - "SELECT DISTINCT container_name FROM docker_logs WHERE host_id=:h"), - {"h": hid})).all()} - async with s.begin(): # flip the global kill-switch off + s.add(Host(id=hid, name="loghost3", address="10.7.7.10")) + await s.flush() # host row before its log rows (FK order) + await persist(s, host, [], None, None, batch) # web kept, noisy excluded + async with s.begin(): # global kill-switch off → nothing stored await set_setting(s, "docker.logs.enabled", False) - await persist(s, h, [], None, None, batch) - after_off = (await s.execute(text( - "SELECT COUNT(*) FROM docker_logs WHERE host_id=:h"), {"h": hid})).scalar() + await persist(s, host, [], None, None, batch) async with s.begin(): # restore defaults for other tests await set_setting(s, "docker.logs.enabled", True) await set_setting(s, "docker.logs.exclude", []) + # Reads only after the last begin block (they autobegin, but nothing + # opens a begin() after them). Toggle-off added nothing, so the state + # here still reflects the exclude phase. + kept = {r[0] for r in (await s.execute(text( + "SELECT DISTINCT container_name FROM docker_logs WHERE host_id=:h"), + {"h": hid})).all()} + after_off = (await s.execute(text( + "SELECT COUNT(*) FROM docker_logs WHERE host_id=:h"), {"h": hid})).scalar() return kept, after_off kept, after_off = asyncio.run(_go()) assert kept == {"web"} # excluded 'noisy' dropped on ingest - assert after_off == 1 # toggle off → no new rows (still just the one 'web') + assert after_off == 1 # toggle off added nothing → still just the one 'web' line @_NEEDS_DB