Add alert groups external URLs information to details API (#4226)

Alert groups connected to an external source will return external URLs
information, eg.

```
{
  "external_urls": [
    {
      "integration": "C2IFSTV93NQUW",
      "integration_type": "servicenow",
      "external_id": "4c686e1e83d1021075feb3a6feaad3a8",
      "url": "https://some.service-now.com/incident.do?sys_id=4c686e1e83d1021075feb3a6feaad3a8"
    }
  ]
}

```
Related to https://github.com/grafana/oncall-private/issues/2615
This commit is contained in:
Matias Bordese 2024-04-15 14:49:51 -03:00 committed by GitHub
parent 14f9677082
commit 0989c40abb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 2 deletions

View file

@ -22,6 +22,13 @@ logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
class ExternalURL(typing.TypedDict):
integration: str
integration_type: str
external_id: str
url: str
class RenderForWeb(typing.TypedDict):
title: str
message: str
@ -213,6 +220,7 @@ class AlertGroupSerializer(AlertGroupListSerializer):
alerts = serializers.SerializerMethodField("get_limited_alerts")
last_alert_at = serializers.SerializerMethodField()
paged_users = serializers.SerializerMethodField()
external_urls = serializers.SerializerMethodField()
class Meta(AlertGroupListSerializer.Meta):
fields = AlertGroupListSerializer.Meta.fields + [
@ -221,6 +229,7 @@ class AlertGroupSerializer(AlertGroupListSerializer):
"slack_permalink", # TODO: make plugin frontend use "permalinks" field to get Slack link
"last_alert_at",
"paged_users",
"external_urls",
]
def get_last_alert_at(self, obj: "AlertGroup") -> datetime.datetime:
@ -242,3 +251,21 @@ class AlertGroupSerializer(AlertGroupListSerializer):
def get_paged_users(self, obj: "AlertGroup") -> typing.List[PagedUser]:
return obj.get_paged_users()
def get_external_urls(self, obj: "AlertGroup") -> typing.List[ExternalURL]:
external_urls = []
external_ids = obj.external_ids.all()
for external_id in external_ids:
source_integration = external_id.source_alert_receive_channel
get_url = getattr(source_integration.config, "get_url", None)
if get_url:
url = source_integration.config.get_url(source_integration, external_id.value)
external_urls.append(
{
"integration": source_integration.public_primary_key,
"integration_type": source_integration.integration,
"external_id": external_id.value,
"url": url,
}
)
return external_urls

View file

@ -1,5 +1,5 @@
import datetime
from unittest.mock import patch
from unittest.mock import Mock, patch
import pytest
from django.core.cache import cache
@ -10,7 +10,13 @@ from rest_framework.response import Response
from rest_framework.test import APIClient
from apps.alerts.constants import ActionSource
from apps.alerts.models import AlertGroup, AlertGroupLogRecord, ResolutionNote
from apps.alerts.models import (
AlertGroup,
AlertGroupExternalID,
AlertGroupLogRecord,
AlertReceiveChannel,
ResolutionNote,
)
from apps.alerts.paging import direct_paging
from apps.alerts.tasks import wipe
from apps.api.errors import AlertGroupAPIError
@ -2243,3 +2249,42 @@ def test_alert_group_list_labels(
assert response.json()["results"][-1]["labels"] == [
{"key": {"id": "a", "name": "a"}, "value": {"id": "b", "name": "b"}}
]
@pytest.mark.django_db
def test_alert_group_external_urls(
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
make_alert_receive_channel,
make_alert_receive_channel_connection,
make_alert_group,
):
client = APIClient()
integration_config = AlertReceiveChannel._config[0]
integration_config.get_url = Mock(return_value="https://some-url")
organization, user, token = make_organization_and_user_with_plugin_token()
source_alert_receive_channel = make_alert_receive_channel(organization, integration=integration_config.slug)
alert_receive_channel = make_alert_receive_channel(organization)
make_alert_receive_channel_connection(source_alert_receive_channel, alert_receive_channel)
alert_group = make_alert_group(alert_receive_channel)
url = reverse("api-internal:alertgroup-detail", kwargs={"pk": alert_group.public_primary_key})
response = client.get(url, format="json", **make_user_auth_headers(user, token))
assert response.json()["external_urls"] == []
# create external IDs
external_id = AlertGroupExternalID.objects.create(
source_alert_receive_channel=source_alert_receive_channel, alert_group=alert_group, value="test123"
)
url = reverse("api-internal:alertgroup-detail", kwargs={"pk": alert_group.public_primary_key})
response = client.get(url, format="json", **make_user_auth_headers(user, token))
expected = {
"integration": source_alert_receive_channel.public_primary_key,
"integration_type": source_alert_receive_channel.integration,
"external_id": external_id.value,
"url": "https://some-url",
}
assert response.json()["external_urls"] == [expected]

View file

@ -1411,6 +1411,12 @@ export interface components {
avatar_full: string;
important: boolean;
}[];
readonly external_urls: {
integration: string;
integration_type: string;
external_id: string;
url: string;
}[];
};
AlertGroupAttach: {
root_alert_group_pk: string;