oncall-engine/engine/apps/api/views/maintenance.py

161 lines
6.2 KiB
Python

from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from apps.alerts.models import AlertReceiveChannel
from apps.alerts.models.maintainable_object import MaintainableObject
from apps.api.permissions import RBACPermission
from apps.auth_token.auth import PluginAuthentication
from common.api_helpers.exceptions import BadRequest
from common.api_helpers.mixins import TeamFilteringMixin
from common.exceptions import MaintenanceCouldNotBeStartedError
class GetObjectMixin:
def get_object(self, request):
organization = request.auth.organization
type = request.data.get("type", None)
if type == "organization":
instance = organization
elif type == "alert_receive_channel":
pk = request.data.get("alert_receive_channel_id", None)
if pk is not None:
try:
instance = AlertReceiveChannel.objects.get(
public_primary_key=pk,
organization=organization,
)
if instance.team is not None and instance.team not in self.request.user.teams.all():
raise BadRequest(detail={"alert_receive_channel_id": ["unknown id"]})
except AlertReceiveChannel.DoesNotExist:
raise BadRequest(detail={"alert_receive_channel_id": ["unknown id"]})
else:
raise BadRequest(detail={"alert_receive_channel_id": ["id is required"]})
else:
raise BadRequest(detail={"type": ["Unknown type"]})
return instance
class MaintenanceAPIView(APIView, TeamFilteringMixin):
"""Deprecated. Maintenance management is now performed on integrations page (alert_receive_channel/ endpoint))"""
authentication_classes = (PluginAuthentication,)
permission_classes = (IsAuthenticated, RBACPermission)
rbac_permissions = {
"get": [RBACPermission.Permissions.MAINTENANCE_READ],
"filters": [RBACPermission.Permissions.MAINTENANCE_READ],
}
def get(self, request):
organization = self.request.auth.organization
response = []
integrations_under_maintenance = (
AlertReceiveChannel.objects.filter(
maintenance_mode__isnull=False, organization=organization, *self.available_teams_lookup_args
)
.distinct()
.order_by("maintenance_started_at")
)
if organization.maintenance_mode is not None:
response.append(
{
"organization_id": organization.public_primary_key,
"type": "organization",
"maintenance_mode": organization.maintenance_mode,
"maintenance_till_timestamp": organization.till_maintenance_timestamp,
"started_at_timestamp": organization.started_at_timestamp,
}
)
for i in integrations_under_maintenance:
response.append(
{
"alert_receive_channel_id": i.public_primary_key,
"type": "alert_receive_channel",
"maintenance_mode": i.maintenance_mode,
"maintenance_till_timestamp": i.till_maintenance_timestamp,
"started_at_timestamp": i.started_at_timestamp,
}
)
return Response(response, status=200)
@action(methods=["get"], detail=False)
def filters(self, request):
filter_name = request.query_params.get("search", None)
api_root = "/api/internal/v1/"
filter_options = [
{
"name": "team",
"type": "team_select",
"href": api_root + "teams/",
"global": True,
},
]
if filter_name is not None:
filter_options = list(filter(lambda f: filter_name in f["name"], filter_options))
return Response(filter_options)
class MaintenanceStartAPIView(GetObjectMixin, APIView):
"""Deprecated. Maintenance management is now performed on integrations page (alert_receive_channel/ endpoint))"""
authentication_classes = (PluginAuthentication,)
permission_classes = (IsAuthenticated, RBACPermission)
rbac_permissions = {
"post": [RBACPermission.Permissions.MAINTENANCE_WRITE],
}
def post(self, request):
mode = request.data.get("mode", None)
duration = request.data.get("duration", None)
try:
mode = int(mode)
except (ValueError, TypeError):
raise BadRequest(detail={"mode": ["Invalid mode"]})
if mode not in [MaintainableObject.DEBUG_MAINTENANCE, MaintainableObject.MAINTENANCE]:
raise BadRequest(detail={"mode": ["Unknown mode"]})
try:
duration = int(duration)
except (ValueError, TypeError):
raise BadRequest(detail={"duration": ["Invalid duration"]})
if duration not in MaintainableObject.maintenance_duration_options_in_seconds():
raise BadRequest(detail={"mode": ["Unknown duration"]})
instance = self.get_object(request)
try:
instance.start_maintenance(mode, duration, request.user)
except MaintenanceCouldNotBeStartedError as e:
if type(instance) == AlertReceiveChannel:
detail = {"alert_receive_channel_id": ["Already on maintenance"]}
else:
detail = str(e)
raise BadRequest(detail=detail)
return Response(status=status.HTTP_200_OK)
class MaintenanceStopAPIView(GetObjectMixin, APIView):
"""Deprecated. Maintenance management is now performed on integrations page (alert_receive_channel/ endpoint))"""
authentication_classes = (PluginAuthentication,)
permission_classes = (IsAuthenticated, RBACPermission)
rbac_permissions = {
"post": [RBACPermission.Permissions.MAINTENANCE_WRITE],
}
def post(self, request):
instance = self.get_object(request)
user = request.user
instance.force_disable_maintenance(user)
return Response(status=status.HTTP_200_OK)