diff --git a/engine/apps/api/serializers/alert_receive_channel.py b/engine/apps/api/serializers/alert_receive_channel.py index 6d15085e..abeb687b 100644 --- a/engine/apps/api/serializers/alert_receive_channel.py +++ b/engine/apps/api/serializers/alert_receive_channel.py @@ -227,7 +227,7 @@ class FilterAlertReceiveChannelSerializer(serializers.ModelSerializer): class Meta: model = AlertReceiveChannel - fields = ["value", "display_name"] + fields = ["value", "display_name", "integration_url"] def get_value(self, obj): return obj.public_primary_key diff --git a/engine/apps/api/views/alert_receive_channel.py b/engine/apps/api/views/alert_receive_channel.py index 2be1cb24..8c1ecc29 100644 --- a/engine/apps/api/views/alert_receive_channel.py +++ b/engine/apps/api/views/alert_receive_channel.py @@ -38,7 +38,7 @@ class AlertReceiveChannelFilter(ByTeamModelFieldFilterMixin, filters.FilterSet): maintenance_mode = filters.MultipleChoiceFilter( choices=AlertReceiveChannel.MAINTENANCE_MODE_CHOICES, method="filter_maintenance_mode" ) - integration = filters.ChoiceFilter(choices=AlertReceiveChannel.INTEGRATION_CHOICES) + integration = filters.MultipleChoiceFilter(choices=AlertReceiveChannel.INTEGRATION_CHOICES) team = TeamModelMultipleChoiceFilter() class Meta: @@ -80,7 +80,7 @@ class AlertReceiveChannelView( update_serializer_class = AlertReceiveChannelUpdateSerializer filter_backends = [SearchFilter, DjangoFilterBackend] - search_fields = ("verbal_name", "integration") + search_fields = ("verbal_name",) filterset_class = AlertReceiveChannelFilter pagination_class = FifteenPageSizePaginator @@ -102,6 +102,7 @@ class AlertReceiveChannelView( "filters": [RBACPermission.Permissions.INTEGRATIONS_READ], "start_maintenance": [RBACPermission.Permissions.INTEGRATIONS_WRITE], "stop_maintenance": [RBACPermission.Permissions.INTEGRATIONS_WRITE], + "validate_name": [RBACPermission.Permissions.INTEGRATIONS_WRITE], "migrate": [RBACPermission.Permissions.INTEGRATIONS_WRITE], } @@ -144,6 +145,16 @@ class AlertReceiveChannelView( return queryset + def paginate_queryset(self, queryset): + """ + Override to apply pagination only if ?page= is present in query params + Required for Grafana Alerting. + """ + page_number = self.request.query_params.get("page", None) + if not page_number: + return None + return super().paginate_queryset(queryset) + @action(detail=True, methods=["post"], throttle_classes=[DemoAlertThrottler]) def send_demo_alert(self, request, pk): instance = self.get_object() @@ -333,3 +344,21 @@ class AlertReceiveChannelView( instance.save() return Response(status=status.HTTP_200_OK) + + @action(detail=False, methods=["get"]) + def validate_name(self, request): + """ + Checks if verbal_name is available. + It is needed for OnCall <-> Alerting integration. + """ + verbal_name = self.request.query_params.get("verbal_name") + if verbal_name is None: + raise BadRequest("verbal_name is required") + organization = self.request.auth.organization + name_used = AlertReceiveChannel.objects.filter(organization=organization, verbal_name=verbal_name).exists() + if name_used: + r = Response(status=status.HTTP_409_CONFLICT) + else: + r = Response(status=status.HTTP_200_OK) + + return r diff --git a/engine/apps/api/views/features.py b/engine/apps/api/views/features.py index 4d46e5d2..1efa086d 100644 --- a/engine/apps/api/views/features.py +++ b/engine/apps/api/views/features.py @@ -12,6 +12,7 @@ FEATURE_GRAFANA_CLOUD_NOTIFICATIONS = "grafana_cloud_notifications" FEATURE_GRAFANA_CLOUD_CONNECTION = "grafana_cloud_connection" FEATURE_WEB_SCHEDULES = "web_schedules" FEATURE_WEBHOOKS2 = "webhooks2" +FEATURE_GRAFANA_ALERTING_V2 = "grafana_alerting_v2" class FeaturesAPIView(APIView): @@ -62,4 +63,6 @@ class FeaturesAPIView(APIView): if settings.FEATURE_WEBHOOKS_2_ENABLED: enabled_features.append(FEATURE_WEBHOOKS2) + if settings.FEATURE_GRAFANA_ALERTING_V2_ENABLED: + enabled_features.append(FEATURE_GRAFANA_ALERTING_V2) return enabled_features diff --git a/engine/settings/base.py b/engine/settings/base.py index 8b881d2c..9807d0bb 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -66,6 +66,7 @@ FEATURE_INBOUND_EMAIL_ENABLED = getenv_boolean("FEATURE_INBOUND_EMAIL_ENABLED", FEATURE_PROMETHEUS_EXPORTER_ENABLED = getenv_boolean("FEATURE_PROMETHEUS_EXPORTER_ENABLED", default=False) FEATURE_WEBHOOKS_2_ENABLED = getenv_boolean("FEATURE_WEBHOOKS_2_ENABLED", default=True) FEATURE_SHIFT_SWAPS_ENABLED = getenv_boolean("FEATURE_SHIFT_SWAPS_ENABLED", default=False) +FEATURE_GRAFANA_ALERTING_V2_ENABLED = getenv_boolean("FEATURE_GRAFANA_ALERTING_V2_ENABLED", default=False) GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED = getenv_boolean("GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED", default=True) GRAFANA_CLOUD_NOTIFICATIONS_ENABLED = getenv_boolean("GRAFANA_CLOUD_NOTIFICATIONS_ENABLED", default=True)