improve errors for alertmanager

This commit is contained in:
HgO 2022-07-09 10:38:40 +02:00
parent 5d2d109da1
commit 687afe32ef
5 changed files with 37 additions and 156 deletions

View file

@ -9,7 +9,7 @@ from aiohttp import ClientError
from diskcache import Cache
from matrix_alertbot.errors import (
AlertmanagerError,
AlertmanagerServerError,
AlertNotFoundError,
SilenceNotFoundError,
)
@ -30,7 +30,9 @@ class AlertmanagerClient:
response.raise_for_status()
return await response.json()
except ClientError as e:
raise AlertmanagerError(f"Cannot fetch alerts from Alertmanager") from e
raise AlertmanagerServerError(
f"Cannot fetch alerts from Alertmanager"
) from e
async def get_alert(self, fingerprint: str) -> Dict:
alerts = await self.get_alerts()
@ -66,7 +68,7 @@ class AlertmanagerClient:
response.raise_for_status()
data = await response.json()
except ClientError as e:
raise AlertmanagerError(
raise AlertmanagerServerError(
f"Cannot create silence for alert fingerprint {fingerprint}"
) from e
@ -93,7 +95,9 @@ class AlertmanagerClient:
) as response:
response.raise_for_status()
except ClientError as e:
raise AlertmanagerError(f"Cannot delete silence with ID {silence}") from e
raise AlertmanagerServerError(
f"Cannot delete silence with ID {silence}"
) from e
@staticmethod
def _find_alert(fingerprint: str, alerts: List[Dict]) -> Dict:

View file

@ -6,11 +6,7 @@ from nio import AsyncClient, MatrixRoom, RoomMessageText
from matrix_alertbot.alertmanager import AlertmanagerClient
from matrix_alertbot.chat_functions import react_to_event, send_text_to_room
from matrix_alertbot.config import Config
from matrix_alertbot.errors import (
AlertmanagerError,
AlertNotFoundError,
SilenceNotFoundError,
)
from matrix_alertbot.errors import AlertmanagerError
logger = logging.getLogger(__name__)
@ -93,7 +89,7 @@ class Command:
alert_fingerprint, duration, self.room.user_name(self.event.sender)
)
count_created_silences += 1
except (AlertNotFoundError, AlertmanagerError) as e:
except AlertmanagerError as e:
logger.exception(f"Unable to create silence: {e}", exc_info=e)
await send_text_to_room(
@ -128,7 +124,7 @@ class Command:
alert_fingerprint
)
count_removed_silences += len(removed_silences)
except (AlertNotFoundError, SilenceNotFoundError, AlertmanagerError) as e:
except AlertmanagerError as e:
logger.exception(f"Unable to delete silence: {e}", exc_info=e)
await send_text_to_room(

View file

@ -1,29 +1,31 @@
# This file holds custom error types that you can define for your application.
class ConfigError(RuntimeError):
"""An error encountered during reading the config file.
Args:
msg: The message displayed to the user on error.
"""
class ConfigError(Exception):
"""An error encountered during reading the config file."""
pass
class AlertNotFoundError(RuntimeError):
"""An error encountered when an alert cannot be found in database.
Args:
msg: The message displayed to the user on error.
"""
class AlertmanagerError(Exception):
"""An error encountered with Alertmanager."""
pass
class SilenceNotFoundError(RuntimeError):
class AlertNotFoundError(AlertmanagerError):
"""An error encountered when an alert cannot be found in Alertmanager."""
pass
class AlertmanagerError(RuntimeError):
class SilenceNotFoundError(AlertmanagerError):
"""An error encountered when a silence cannot be found in Alertmanager."""
pass
class AlertmanagerServerError(AlertmanagerError):
"""An error encountered with Alertmanager server."""
pass

View file

@ -13,7 +13,7 @@ from diskcache import Cache
from matrix_alertbot.alertmanager import AlertmanagerClient
from matrix_alertbot.errors import (
AlertmanagerError,
AlertmanagerServerError,
AlertNotFoundError,
SilenceNotFoundError,
)
@ -163,7 +163,7 @@ class AlertmanagerClientTestCase(unittest.IsolatedAsyncioTestCase):
f"http://localhost:{port}", self.fake_cache
)
async with aiotools.closing_async(alertmanager) as alertmanager:
with self.assertRaises(AlertmanagerError):
with self.assertRaises(AlertmanagerServerError):
await alertmanager.get_alerts()
async def test_get_alert_happy(self) -> None:
@ -200,7 +200,7 @@ class AlertmanagerClientTestCase(unittest.IsolatedAsyncioTestCase):
f"http://localhost:{port}", self.fake_cache
)
async with aiotools.closing_async(alertmanager) as alertmanager:
with self.assertRaises(AlertmanagerError):
with self.assertRaises(AlertmanagerServerError):
await alertmanager.get_alert("fingerprint1")
async def test_create_silence_happy(self) -> None:
@ -234,7 +234,7 @@ class AlertmanagerClientTestCase(unittest.IsolatedAsyncioTestCase):
async with aiotools.closing_async(alertmanager) as alertmanager:
await alertmanager.get_alert("fingerprint1")
with self.assertRaises(AlertmanagerError):
with self.assertRaises(AlertmanagerServerError):
await alertmanager.create_silence("fingerprint1", "1d", "user")
async def test_delete_silences_happy(self) -> None:
@ -276,7 +276,7 @@ class AlertmanagerClientTestCase(unittest.IsolatedAsyncioTestCase):
async with aiotools.closing_async(alertmanager) as alertmanager:
await alertmanager.get_alert("fingerprint1")
with self.assertRaises(AlertmanagerError):
with self.assertRaises(AlertmanagerServerError):
await alertmanager.delete_silences("fingerprint2")
async def test_find_alert_happy(self) -> None:

View file

@ -8,20 +8,16 @@ from diskcache import Cache
import matrix_alertbot.callback
from matrix_alertbot.alertmanager import AlertmanagerClient
from matrix_alertbot.command import Command
from matrix_alertbot.errors import (
AlertmanagerError,
AlertNotFoundError,
SilenceNotFoundError,
)
from matrix_alertbot.errors import AlertmanagerError
from tests.utils import make_awaitable
async def create_silence_raise_alert_not_found(
async def create_silence_raise_alert_manager_error(
fingerprint: str, duration: str, user: str
) -> str:
if fingerprint == "fingerprint1":
raise AlertNotFoundError
raise AlertmanagerError
return "silence1"
@ -33,22 +29,10 @@ async def create_silence_raise_alertmanager_error(
return "silence2"
async def delete_silence_raise_silence_not_found(fingerprint: str) -> List[str]:
if fingerprint == "fingerprint1":
raise SilenceNotFoundError
return ["silence1"]
async def delete_silence_raise_alert_not_found(fingerprint: str) -> List[str]:
if fingerprint == "fingerprint1":
raise AlertNotFoundError
return ["silence1", "silence2"]
async def delete_silence_raise_alertmanager_error(fingerprint: str) -> List[str]:
if fingerprint == "fingerprint1":
raise AlertmanagerError
return ["silence1", "silence2", "silence3"]
return ["silence1"]
class CommandTestCase(unittest.IsolatedAsyncioTestCase):
@ -283,47 +267,6 @@ class CommandTestCase(unittest.IsolatedAsyncioTestCase):
"Created 2 silences with a duration of 2d.",
)
@patch.object(matrix_alertbot.command, "send_text_to_room")
async def test_ack_raise_alert_not_found(
self, fake_send_text_to_room: Mock
) -> None:
"""Tests the callback for InviteMemberEvents"""
# Tests that the bot attempts to join a room after being invited to it
self.fake_message_event.source = self.fake_source_in_reply
command = Command(
self.fake_client,
self.fake_cache,
self.fake_alertmanager,
self.fake_config,
"ack",
self.fake_room,
self.fake_message_event,
)
self.fake_alertmanager.create_silence.side_effect = (
create_silence_raise_alert_not_found
)
await command._ack()
# Check that we attempted to create silences
self.fake_alertmanager.create_silence.assert_has_calls(
[
call(
fingerprint,
"1d",
self.fake_message_event.sender,
)
for fingerprint in self.fake_fingerprints
]
)
fake_send_text_to_room.assert_called_once_with(
self.fake_client,
self.fake_room.room_id,
"Created 1 silences with a duration of 1d.",
)
@patch.object(matrix_alertbot.command, "send_text_to_room")
async def test_ack_raise_alertmanager_error(
self, fake_send_text_to_room: Mock
@ -391,70 +334,6 @@ class CommandTestCase(unittest.IsolatedAsyncioTestCase):
self.fake_client, self.fake_room.room_id, "Removed 4 silences."
)
@patch.object(matrix_alertbot.command, "send_text_to_room")
async def test_unack_raise_silence_not_found(
self, fake_send_text_to_room: Mock
) -> None:
"""Tests the callback for InviteMemberEvents"""
# Tests that the bot attempts to join a room after being invited to it
self.fake_message_event.source = self.fake_source_in_reply
command = Command(
self.fake_client,
self.fake_cache,
self.fake_alertmanager,
self.fake_config,
"unack",
self.fake_room,
self.fake_message_event,
)
self.fake_alertmanager.delete_silences.side_effect = (
delete_silence_raise_silence_not_found
)
await command._unack()
# Check that we attempted to create silences
self.fake_alertmanager.delete_silences.assert_has_calls(
[call(fingerprint) for fingerprint in self.fake_fingerprints]
)
fake_send_text_to_room.assert_called_with(
self.fake_client, self.fake_room.room_id, "Removed 1 silences."
)
@patch.object(matrix_alertbot.command, "send_text_to_room")
async def test_unack_raise_alert_not_found(
self, fake_send_text_to_room: Mock
) -> None:
"""Tests the callback for InviteMemberEvents"""
# Tests that the bot attempts to join a room after being invited to it
self.fake_message_event.source = self.fake_source_in_reply
command = Command(
self.fake_client,
self.fake_cache,
self.fake_alertmanager,
self.fake_config,
"unack",
self.fake_room,
self.fake_message_event,
)
self.fake_alertmanager.delete_silences.side_effect = (
delete_silence_raise_alert_not_found
)
await command._unack()
# Check that we attempted to create silences
self.fake_alertmanager.delete_silences.assert_has_calls(
[call(fingerprint) for fingerprint in self.fake_fingerprints]
)
fake_send_text_to_room.assert_called_with(
self.fake_client, self.fake_room.room_id, "Removed 2 silences."
)
@patch.object(matrix_alertbot.command, "send_text_to_room")
async def test_unack_silence_raise_alertmanager_error(
self, fake_send_text_to_room: Mock
@ -484,7 +363,7 @@ class CommandTestCase(unittest.IsolatedAsyncioTestCase):
[call(fingerprint) for fingerprint in self.fake_fingerprints]
)
fake_send_text_to_room.assert_called_with(
self.fake_client, self.fake_room.room_id, "Removed 3 silences."
self.fake_client, self.fake_room.room_id, "Removed 1 silences."
)