diff --git a/engine/apps/alerts/migrations/0058_alter_alertgroup_reason_to_skip_escalation.py b/engine/apps/alerts/migrations/0058_alter_alertgroup_reason_to_skip_escalation.py new file mode 100644 index 0000000000..16f0c9f18f --- /dev/null +++ b/engine/apps/alerts/migrations/0058_alter_alertgroup_reason_to_skip_escalation.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.15 on 2024-09-02 13:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('alerts', '0057_remove_alertgroup_slack_log_message_db'), + ] + + operations = [ + migrations.AlterField( + model_name='alertgroup', + name='reason_to_skip_escalation', + field=models.IntegerField(choices=[(0, 'account_inactive'), (1, 'is_archived'), (2, 'no_reason'), (3, 'rate_limited'), (4, 'channel_not_specified'), (5, 'restricted_action'), (6, 'invalid_auth')], default=2), + ), + ] diff --git a/engine/apps/alerts/models/alert_group.py b/engine/apps/alerts/models/alert_group.py index 4f30e47dce..44bdab903c 100644 --- a/engine/apps/alerts/models/alert_group.py +++ b/engine/apps/alerts/models/alert_group.py @@ -365,14 +365,23 @@ def status(self) -> int: else: return AlertGroup.NEW - ACCOUNT_INACTIVE, CHANNEL_ARCHIVED, NO_REASON, RATE_LIMITED, CHANNEL_NOT_SPECIFIED, RESTRICTED_ACTION = range(6) + ( + ACCOUNT_INACTIVE, + CHANNEL_ARCHIVED, + NO_REASON, + RATE_LIMITED, + CHANNEL_NOT_SPECIFIED, + RESTRICTED_ACTION, + INVALID_AUTH, + ) = range(7) REASONS_TO_SKIP_ESCALATIONS = ( (ACCOUNT_INACTIVE, "account_inactive"), - (CHANNEL_ARCHIVED, "channel_archived"), + (CHANNEL_ARCHIVED, "is_archived"), (NO_REASON, "no_reason"), (RATE_LIMITED, "rate_limited"), (CHANNEL_NOT_SPECIFIED, "channel_not_specified"), (RESTRICTED_ACTION, "restricted_action"), + (INVALID_AUTH, "invalid_auth"), ) reason_to_skip_escalation = models.IntegerField(choices=REASONS_TO_SKIP_ESCALATIONS, default=NO_REASON) diff --git a/engine/apps/slack/scenarios/distribute_alerts.py b/engine/apps/slack/scenarios/distribute_alerts.py index 52ded93241..6bac3db91a 100644 --- a/engine/apps/slack/scenarios/distribute_alerts.py +++ b/engine/apps/slack/scenarios/distribute_alerts.py @@ -16,6 +16,7 @@ SlackAPIChannelArchivedError, SlackAPIChannelNotFoundError, SlackAPIError, + SlackAPIInvalidAuthError, SlackAPIMessageNotFoundError, SlackAPIRatelimitError, SlackAPIRestrictedActionError, @@ -161,6 +162,10 @@ def _post_alert_group_to_slack( alert_group.reason_to_skip_escalation = AlertGroup.ACCOUNT_INACTIVE alert_group.save(update_fields=["reason_to_skip_escalation"]) logger.info("Not delivering alert due to account_inactive.") + except SlackAPIInvalidAuthError: + alert_group.reason_to_skip_escalation = AlertGroup.INVALID_AUTH + alert_group.save(update_fields=["reason_to_skip_escalation"]) + logger.info("Not delivering alert due to invalid_auth.") except SlackAPIChannelArchivedError: alert_group.reason_to_skip_escalation = AlertGroup.CHANNEL_ARCHIVED alert_group.save(update_fields=["reason_to_skip_escalation"]) diff --git a/engine/apps/slack/tests/test_scenario_steps/test_distribute_alerts.py b/engine/apps/slack/tests/test_scenario_steps/test_distribute_alerts.py index 7d73febee8..00d029319d 100644 --- a/engine/apps/slack/tests/test_scenario_steps/test_distribute_alerts.py +++ b/engine/apps/slack/tests/test_scenario_steps/test_distribute_alerts.py @@ -3,7 +3,7 @@ import pytest from apps.alerts.models import AlertGroup -from apps.slack.errors import SlackAPIRestrictedActionError +from apps.slack.errors import get_error_class from apps.slack.models import SlackMessage from apps.slack.scenarios.distribute_alerts import AlertShootingStep from apps.slack.scenarios.scenario_step import ScenarioStep @@ -11,11 +11,21 @@ @pytest.mark.django_db -def test_restricted_action_error( +@pytest.mark.parametrize( + "reason,slack_error", + [ + (reason, slack_error) + for reason, slack_error in AlertGroup.REASONS_TO_SKIP_ESCALATIONS + if reason != AlertGroup.NO_REASON + ], +) +def test_skip_escalations_error( make_organization_and_user_with_slack_identities, make_alert_receive_channel, make_alert_group, make_alert, + reason, + slack_error, ): SlackAlertShootingStep = ScenarioStep.get_step("distribute_alerts", "AlertShootingStep") organization, _, slack_team_identity, _ = make_organization_and_user_with_slack_identities() @@ -26,14 +36,17 @@ def test_restricted_action_error( step = SlackAlertShootingStep(slack_team_identity) with patch.object(step._slack_client, "api_call") as mock_slack_api_call: - mock_slack_api_call.side_effect = SlackAPIRestrictedActionError( - response=build_slack_response({"error": "restricted_action"}) - ) - step._post_alert_group_to_slack(slack_team_identity, alert_group, alert, None, "channel-id", []) + error_response = build_slack_response({"error": slack_error}) + error_class = get_error_class(error_response) + mock_slack_api_call.side_effect = error_class(error_response) + channel_id = "channel-id" + if reason == AlertGroup.CHANNEL_NOT_SPECIFIED: + channel_id = None + step._post_alert_group_to_slack(slack_team_identity, alert_group, alert, None, channel_id, []) alert_group.refresh_from_db() alert.refresh_from_db() - assert alert_group.reason_to_skip_escalation == AlertGroup.RESTRICTED_ACTION + assert alert_group.reason_to_skip_escalation == reason assert alert_group.slack_message is None assert SlackMessage.objects.count() == 0 assert not alert.delivered diff --git a/engine/apps/telegram/client.py b/engine/apps/telegram/client.py index 4271ae5f32..4108fc58e2 100644 --- a/engine/apps/telegram/client.py +++ b/engine/apps/telegram/client.py @@ -186,4 +186,4 @@ def _get_message_and_keyboard( @staticmethod def error_message_is(error: TelegramError, messages: list[str]) -> bool: - return error.message in messages + return error.message.lower() in (m.lower() for m in messages)