# 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>
738 lines
28 KiB
Python
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"]
|