oncall-engine/engine/apps/public_api/tests/test_alert_groups.py
Ildar Iskhakov 784b7e5344
Add latest alert to public api alert groups endpoint (#5059)
# What this PR does

Added last alert information 
and optimized the API call so it makes 10x less queries by:
* prefetching chatops messages (based on @vadimkerr 's
https://github.com/grafana/oncall/pull/4738)
* using `enrich` from private api

Previously: 
<img width="1102" alt="Screenshot 2024-09-24 at 4 47 00 PM"
src="https://github.com/user-attachments/assets/84edb78e-257a-49cd-bc94-083dd8d043d7">
Now:
<img width="1066" alt="Screenshot 2024-09-24 at 4 44 56 PM"
src="https://github.com/user-attachments/assets/e7dfcc40-dce6-4a0d-9677-910aab2b4f17">



## Which issue(s) this PR closes

Related to [issue link here]

<!--
*Note*: If you want the issue to be auto-closed once the PR is merged,
change "Related to" to "Closes" in the line above.
If you have more than one GitHub issue that this PR closes, be sure to
preface
each issue link with a [closing
keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue).
This ensures that the issue(s) are auto-closed once the PR has been
merged.
-->

## Checklist

- [ ] Unit, integration, and e2e (if applicable) tests updated
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required)
- [ ] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.

---------

Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com>
2024-10-02 17:09:50 +00:00

738 lines
28 KiB
Python

from unittest.mock import patch
import pytest
from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from rest_framework.test import APIClient
from apps.alerts.constants import ActionSource
from apps.alerts.models import AlertGroup, AlertReceiveChannel
from apps.alerts.tasks import delete_alert_group, wipe
def construct_expected_response_from_alert_groups(alert_groups):
results = []
for alert_group in alert_groups:
# convert datetimes to serializers.DateTimeField
created_at = None
if alert_group.started_at:
created_at = alert_group.started_at.isoformat()
created_at = created_at[:-6] + "Z"
resolved_at = None
if alert_group.resolved_at:
resolved_at = alert_group.resolved_at.isoformat()
resolved_at = resolved_at[:-6] + "Z"
acknowledged_at = None
if alert_group.acknowledged_at:
acknowledged_at = alert_group.acknowledged_at.isoformat()
acknowledged_at = acknowledged_at[:-6] + "Z"
silenced_at = None
if alert_group.silenced_at:
silenced_at = alert_group.silenced_at.isoformat()
silenced_at = silenced_at[:-6] + "Z"
def user_pk_or_none(alert_group, user_field):
u = getattr(alert_group, user_field)
if u is not None:
return u.public_primary_key
labels = []
for label in alert_group.labels.all():
labels.append(
{
"key": {"id": label.key_name, "name": label.key_name},
"value": {"id": label.value_name, "name": label.value_name},
}
)
results.append(
{
"id": alert_group.public_primary_key,
"integration_id": alert_group.channel.public_primary_key,
"team_id": alert_group.channel.team.public_primary_key if alert_group.channel.team else None,
"route_id": alert_group.channel_filter.public_primary_key,
"alerts_count": alert_group.alerts.count(),
"state": alert_group.state,
"created_at": created_at,
"resolved_at": resolved_at,
"acknowledged_at": acknowledged_at,
"acknowledged_by": user_pk_or_none(alert_group, "acknowledged_by_user"),
"resolved_by": user_pk_or_none(alert_group, "resolved_by_user"),
"title": None,
"labels": labels,
"permalinks": {
"slack": None,
"slack_app": None,
"telegram": None,
"web": alert_group.web_link,
},
"silenced_at": silenced_at,
"last_alert": {
"id": alert_group.alerts.last().public_primary_key,
"alert_group_id": alert_group.public_primary_key,
"created_at": alert_group.alerts.last().created_at.isoformat().replace("+00:00", "Z"),
"payload": alert_group.channel.config.example_payload,
},
}
)
return {
"count": len(alert_groups),
"next": None,
"previous": None,
"results": results,
"current_page_number": 1,
"page_size": 50,
"total_pages": 1,
}
@pytest.fixture()
def alert_group_public_api_setup(
make_organization_and_user_with_token,
make_team,
make_alert_receive_channel,
make_channel_filter,
make_alert_group,
make_alert,
):
organization, user, token = make_organization_and_user_with_token()
team = make_team(organization)
grafana = make_alert_receive_channel(organization, integration=AlertReceiveChannel.INTEGRATION_GRAFANA)
formatted_webhook = make_alert_receive_channel(
organization, integration=AlertReceiveChannel.INTEGRATION_FORMATTED_WEBHOOK, team=team
)
grafana_default_route = make_channel_filter(grafana, is_default=True)
grafana_non_default_route = make_channel_filter(grafana, filtering_term="us-east")
formatted_webhook_default_route = make_channel_filter(formatted_webhook, is_default=True)
grafana_alert_group_default_route = make_alert_group(grafana, channel_filter=grafana_default_route)
grafana_alert_group_non_default_route = make_alert_group(grafana, channel_filter=grafana_non_default_route)
formatted_webhook_alert_group = make_alert_group(formatted_webhook, channel_filter=formatted_webhook_default_route)
make_alert(alert_group=grafana_alert_group_default_route, raw_request_data=grafana.config.example_payload)
make_alert(alert_group=grafana_alert_group_non_default_route, raw_request_data=grafana.config.example_payload)
make_alert(alert_group=formatted_webhook_alert_group, raw_request_data=formatted_webhook.config.example_payload)
integrations = grafana, formatted_webhook
alert_groups = (
grafana_alert_group_default_route,
grafana_alert_group_non_default_route,
formatted_webhook_alert_group,
)
routes = grafana_default_route, grafana_non_default_route, formatted_webhook_default_route
return token, alert_groups, integrations, routes
@pytest.mark.django_db
def test_get_alert_group(alert_group_public_api_setup):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.all().order_by("-started_at")
client = APIClient()
list_response = construct_expected_response_from_alert_groups(alert_groups)
expected_response = list_response["results"][0]
url = reverse("api-public:alert_groups-detail", kwargs={"pk": expected_response["id"]})
response = client.get(url, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_group_slack_links(
alert_group_public_api_setup, make_slack_team_identity, make_slack_channel, make_slack_message
):
token, _, _, _ = alert_group_public_api_setup
alert_group = AlertGroup.objects.all().order_by("-started_at").first()
organization = alert_group.channel.organization
client = APIClient()
list_response = construct_expected_response_from_alert_groups(AlertGroup.objects.filter(pk=alert_group.pk))
expected_response = list_response["results"][0]
slack_team_identity = make_slack_team_identity()
organization.slack_team_identity = slack_team_identity
organization.save()
slack_channel = make_slack_channel(slack_team_identity)
slack_message = make_slack_message(
alert_group=alert_group, channel_id=slack_channel.slack_id, cached_permalink="the-link"
)
url = reverse("api-public:alert_groups-detail", kwargs={"pk": expected_response["id"]})
response = client.get(url, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
expected_response["permalinks"]["slack"] = slack_message.permalink
expected_response["permalinks"]["slack_app"] = slack_message.deep_link
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups(alert_group_public_api_setup):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.all().order_by("-started_at")
client = APIClient()
expected_response = construct_expected_response_from_alert_groups(alert_groups)
url = reverse("api-public:alert_groups-list")
response = client.get(url, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_inactive_user(make_organization_and_user_with_token):
_, user, token = make_organization_and_user_with_token()
# user is set to inactive if deleted via queryset (ie. during sync)
user.is_active = False
user.save()
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.django_db
def test_get_alert_groups_include_labels(alert_group_public_api_setup, make_alert_group_label_association):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.all().order_by("-started_at")
alert_group_0 = alert_groups[0]
organization = alert_group_0.channel.organization
# set labels for the first alert group
make_alert_group_label_association(organization, alert_group_0, key_name="a", value_name="b")
client = APIClient()
expected_response = construct_expected_response_from_alert_groups(alert_groups)
url = reverse("api-public:alert_groups-list")
response = client.get(url, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_integration(
alert_group_public_api_setup,
):
token, alert_groups, integrations, _ = alert_group_public_api_setup
formatted_webhook = integrations[1]
alert_groups = AlertGroup.objects.filter(channel=formatted_webhook).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(
url + f"?integration_id={formatted_webhook.public_primary_key}", format="json", HTTP_AUTHORIZATION=token
)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_team(alert_group_public_api_setup):
token, alert_groups, integrations, _ = alert_group_public_api_setup
for integration in integrations:
team_id = integration.team.public_primary_key if integration.team else "null"
alert_groups = AlertGroup.objects.filter(channel=integration).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + f"?team_id={team_id}", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_started_at(alert_group_public_api_setup):
token, alert_groups, _, _ = alert_group_public_api_setup
now = timezone.now()
# set custom started_at dates
for i, alert_group in enumerate(alert_groups):
# alert groups starting every 10 days going back
alert_group.started_at = now - timezone.timedelta(days=10 * i + 1)
alert_group.save(update_fields=["started_at"])
client = APIClient()
url = reverse("api-public:alert_groups-list")
ranges = (
# start, end, expected
(now - timezone.timedelta(days=1), now, [alert_groups[0]]),
(now - timezone.timedelta(days=12), now, [alert_groups[0], alert_groups[1]]),
(now - timezone.timedelta(days=12), now - timezone.timedelta(days=5), [alert_groups[1]]),
(now - timezone.timedelta(days=32), now, alert_groups),
)
for range_start, range_end, expected_alert_groups in ranges:
started_at_q = "?started_at={}_{}".format(
range_start.strftime("%Y-%m-%dT%H:%M:%S"), range_end.strftime("%Y-%m-%dT%H:%M:%S")
)
response = client.get(url + started_at_q, format="json", HTTP_AUTHORIZATION=token)
expected_response = construct_expected_response_from_alert_groups(expected_alert_groups)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_state_new(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.filter(AlertGroup.get_new_state_filter()).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?state=new", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_state_acknowledged(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.filter(AlertGroup.get_acknowledged_state_filter()).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?state=acknowledged", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_state_silenced(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.filter(AlertGroup.get_silenced_state_filter()).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?state=silenced", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_state_resolved(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
alert_groups = AlertGroup.objects.filter(AlertGroup.get_resolved_state_filter()).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?state=resolved", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_state_unknown(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?state=unknown", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_get_alert_groups_filter_by_integration_no_result(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?integration_id=impossible_integration", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json()["results"] == []
@pytest.mark.django_db
def test_get_alert_groups_filter_by_route(
alert_group_public_api_setup,
):
token, alert_groups, integrations, routes = alert_group_public_api_setup
grafana_non_default_route = routes[1]
alert_groups = AlertGroup.objects.filter(channel_filter=grafana_non_default_route).order_by("-started_at")
expected_response = construct_expected_response_from_alert_groups(alert_groups)
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(
url + f"?route_id={grafana_non_default_route.public_primary_key}", format="json", HTTP_AUTHORIZATION=token
)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.django_db
def test_get_alert_groups_filter_by_route_no_result(
alert_group_public_api_setup,
):
token, _, _, _ = alert_group_public_api_setup
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?route_id=impossible_route_ir", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json()["results"] == []
@pytest.mark.django_db
def test_get_alert_groups_filter_by_labels(
alert_group_public_api_setup,
make_alert_group_label_association,
):
token, alert_groups, _, _ = alert_group_public_api_setup
organization = alert_groups[0].channel.organization
make_alert_group_label_association(organization, alert_groups[0], key_name="a", value_name="b")
make_alert_group_label_association(organization, alert_groups[0], key_name="c", value_name="d")
make_alert_group_label_association(organization, alert_groups[1], key_name="a", value_name="b")
make_alert_group_label_association(organization, alert_groups[2], key_name="c", value_name="d")
expected_response = construct_expected_response_from_alert_groups([alert_groups[0]])
client = APIClient()
url = reverse("api-public:alert_groups-list")
response = client.get(url + "?label=a:b&label=c:d", format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
assert response.json() == expected_response
@pytest.mark.parametrize(
"data,task,status_code",
[
(None, wipe, status.HTTP_204_NO_CONTENT),
({"mode": "wipe"}, wipe, status.HTTP_204_NO_CONTENT),
({"mode": "delete"}, delete_alert_group, status.HTTP_204_NO_CONTENT),
({"mode": "random"}, None, status.HTTP_400_BAD_REQUEST),
("delete", None, status.HTTP_400_BAD_REQUEST),
],
)
@pytest.mark.django_db
def test_delete_alert_group(alert_group_public_api_setup, data, task, status_code):
token, alert_groups, _, _ = alert_group_public_api_setup
alert_group = alert_groups[0]
client = APIClient()
url = reverse("api-public:alert_groups-detail", kwargs={"pk": alert_group.public_primary_key})
if task:
with patch.object(task, "apply_async") as mock_task:
response = client.delete(url, data=data, format="json", HTTP_AUTHORIZATION=token)
mock_task.assert_called_once()
else:
response = client.delete(url, data=data, format="json", HTTP_AUTHORIZATION=token)
assert response.status_code == status_code
@pytest.mark.django_db
def test_pagination(settings, alert_group_public_api_setup):
settings.BASE_URL = "https://test.com/test/prefixed/urls"
token, alert_groups, _, _ = alert_group_public_api_setup
client = APIClient()
url = "{}?perpage=1".format(reverse("api-public:alert_groups-list"))
response = client.get(url, HTTP_AUTHORIZATION=token)
assert response.status_code == status.HTTP_200_OK
result = response.json()
assert result["next"].startswith("https://test.com/test/prefixed/urls")
@pytest.mark.parametrize(
"acknowledged,resolved,attached,maintenance,status_code",
[
(False, False, False, False, status.HTTP_200_OK),
(True, False, False, False, status.HTTP_400_BAD_REQUEST),
(False, True, False, False, status.HTTP_400_BAD_REQUEST),
(False, False, True, False, status.HTTP_400_BAD_REQUEST),
(False, False, False, True, status.HTTP_400_BAD_REQUEST),
],
)
@pytest.mark.django_db
def test_alert_group_acknowledge(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
acknowledged,
resolved,
attached,
maintenance,
status_code,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
maintenance_uuid="test_maintenance_uuid" if maintenance else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-acknowledge", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)
assert response.status_code == status_code
if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.acknowledged is True
assert alert_group.log_records.last().action_source == ActionSource.API
@pytest.mark.parametrize(
"acknowledged,resolved,attached,maintenance,status_code",
[
(True, False, False, False, status.HTTP_200_OK),
(True, True, False, False, status.HTTP_400_BAD_REQUEST),
(True, False, True, False, status.HTTP_400_BAD_REQUEST),
(True, False, False, True, status.HTTP_400_BAD_REQUEST),
(False, False, False, False, status.HTTP_400_BAD_REQUEST),
],
)
@pytest.mark.django_db
def test_alert_group_unacknowledge(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
acknowledged,
resolved,
attached,
maintenance,
status_code,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
maintenance_uuid="test_maintenance_uuid" if maintenance else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-unacknowledge", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)
assert response.status_code == status_code
if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.acknowledged is False
assert alert_group.log_records.last().action_source == ActionSource.API
@pytest.mark.parametrize(
"resolved,attached,maintenance,status_code",
[
(False, False, False, status.HTTP_200_OK),
(False, False, True, status.HTTP_200_OK),
(True, False, False, status.HTTP_400_BAD_REQUEST),
(False, True, False, status.HTTP_400_BAD_REQUEST),
],
)
@pytest.mark.django_db
def test_alert_group_resolve(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
resolved,
attached,
maintenance,
status_code,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
maintenance_uuid="test_maintenance_uuid" if maintenance else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-resolve", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)
assert response.status_code == status_code
if status_code == status.HTTP_200_OK and not maintenance:
alert_group.refresh_from_db()
assert alert_group.resolved is True
assert alert_group.log_records.last().action_source == ActionSource.API
@pytest.mark.parametrize(
"resolved,attached,maintenance,status_code",
[
(True, False, False, status.HTTP_200_OK),
(True, True, False, status.HTTP_400_BAD_REQUEST),
(True, False, True, status.HTTP_400_BAD_REQUEST),
(False, False, False, status.HTTP_400_BAD_REQUEST),
],
)
@pytest.mark.django_db
def test_alert_group_unresolve(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
resolved,
attached,
maintenance,
status_code,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
maintenance_uuid="test_maintenance_uuid" if maintenance else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-unresolve", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)
assert response.status_code == status_code
if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.resolved is False
assert alert_group.log_records.last().action_source == ActionSource.API
@pytest.mark.parametrize(
"acknowledged,resolved,attached,status_code,data,response_msg",
[
(False, False, False, status.HTTP_200_OK, {"delay": 60}, None),
(False, False, False, status.HTTP_400_BAD_REQUEST, {"delay": -2}, "invalid delay value"),
(False, False, False, status.HTTP_400_BAD_REQUEST, {"delay": "fuzz"}, "invalid delay value"),
(False, False, False, status.HTTP_400_BAD_REQUEST, {}, "delay is required"),
(True, False, False, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence an acknowledged alert group"),
(False, True, False, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence a resolved alert group"),
(False, False, True, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence an attached alert group"),
],
)
@pytest.mark.django_db
def test_alert_group_silence(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
acknowledged,
resolved,
attached,
status_code,
data,
response_msg,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-silence", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, data=data, HTTP_AUTHORIZATION=token)
if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.silenced is True
assert alert_group.log_records.last().action_source == ActionSource.API
else:
assert alert_group.silenced is False
assert response.status_code == status_code
assert response_msg == response.json()["detail"]
@pytest.mark.parametrize(
"silenced,resolved,acknowledged,attached,status_code,response_msg",
[
(True, False, False, False, status.HTTP_200_OK, None),
(False, False, False, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence an unsilenced alert group"),
(True, True, False, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence a resolved alert group"),
(True, False, True, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence an acknowledged alert group"),
(True, False, False, True, status.HTTP_400_BAD_REQUEST, "Can't unsilence an attached alert group"),
],
)
@pytest.mark.django_db
def test_alert_group_unsilence(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
silenced,
resolved,
acknowledged,
attached,
status_code,
response_msg,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
silenced=silenced,
root_alert_group=root_alert_group if attached else None,
)
client = APIClient()
url = reverse("api-public:alert_groups-unsilence", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)
if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.silenced is False
assert alert_group.log_records.last().action_source == ActionSource.API
else:
assert alert_group.silenced == silenced
assert response.status_code == status_code
assert response_msg == response.json()["detail"]