fix: retry, semaphore, reload lock, activation verify, bans_by_jail diagnostics
Stage 1.1-1.3: reload_all include/exclude_jails params already implemented; added keyword-arg assertions in router and service tests. Stage 2.1/6.1: _send_command_sync retry loop (3 attempts, 150ms exp backoff) retrying on EAGAIN/ECONNREFUSED/ENOBUFS; immediate raise on all other errors. Stage 2.2: asyncio.Lock at module level in jail_service.reload_all to serialize concurrent reload--all commands. Stage 3.1: activate_jail re-queries _get_active_jail_names after reload; returns active=False with descriptive message if jail did not start. Stage 4.1/6.2: asyncio.Semaphore (max 10) in Fail2BanClient.send, lazy- initialized; logs fail2ban_command_waiting_semaphore at debug when waiting. Stage 5.1/5.2: unit tests asserting reload_all is called with include_jails and exclude_jails; activation verification happy/sad path tests. Stage 6.3: TestSendCommandSyncRetry (5 cases) + TestFail2BanClientSemaphore concurrency test. Stage 7.1-7.3: _since_unix uses time.time(); bans_by_jail debug logging with since_iso; diagnostic warning when total==0 despite table rows; unit test verifying the warning fires for stale data.
This commit is contained in:
@@ -292,7 +292,7 @@ class TestJailControls:
|
||||
with _patch_client(
|
||||
{
|
||||
"status": _make_global_status("sshd, nginx"),
|
||||
"reload|--all|[]|[['start', 'sshd'], ['start', 'nginx']]": (0, "OK"),
|
||||
"reload|--all|[]|[['start', 'nginx'], ['start', 'sshd']]": (0, "OK"),
|
||||
}
|
||||
):
|
||||
await jail_service.reload_all(_SOCKET) # should not raise
|
||||
@@ -307,6 +307,38 @@ class TestJailControls:
|
||||
):
|
||||
await jail_service.reload_all(_SOCKET) # should not raise
|
||||
|
||||
async def test_reload_all_include_jails(self) -> None:
|
||||
"""reload_all with include_jails adds the new jail to the stream."""
|
||||
with _patch_client(
|
||||
{
|
||||
"status": _make_global_status("sshd, nginx"),
|
||||
"reload|--all|[]|[['start', 'apache-auth'], ['start', 'nginx'], ['start', 'sshd']]": (0, "OK"),
|
||||
}
|
||||
):
|
||||
await jail_service.reload_all(_SOCKET, include_jails=["apache-auth"])
|
||||
|
||||
async def test_reload_all_exclude_jails(self) -> None:
|
||||
"""reload_all with exclude_jails removes the jail from the stream."""
|
||||
with _patch_client(
|
||||
{
|
||||
"status": _make_global_status("sshd, nginx"),
|
||||
"reload|--all|[]|[['start', 'nginx']]": (0, "OK"),
|
||||
}
|
||||
):
|
||||
await jail_service.reload_all(_SOCKET, exclude_jails=["sshd"])
|
||||
|
||||
async def test_reload_all_include_and_exclude(self) -> None:
|
||||
"""reload_all with both include and exclude applies both correctly."""
|
||||
with _patch_client(
|
||||
{
|
||||
"status": _make_global_status("old, nginx"),
|
||||
"reload|--all|[]|[['start', 'new'], ['start', 'nginx']]": (0, "OK"),
|
||||
}
|
||||
):
|
||||
await jail_service.reload_all(
|
||||
_SOCKET, include_jails=["new"], exclude_jails=["old"]
|
||||
)
|
||||
|
||||
async def test_start_not_found_raises(self) -> None:
|
||||
"""start_jail raises JailNotFoundError for unknown jail."""
|
||||
with _patch_client({"start|ghost": (1, Exception("Unknown jail: 'ghost'"))}), pytest.raises(JailNotFoundError):
|
||||
|
||||
Reference in New Issue
Block a user