commit
2715670656
4 changed files with 116 additions and 13 deletions
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## v1.3.57 (2023-11-10)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix AmazonSNS integration to handle exceptions the same as other integrations @mderynck ([#3315](https://github.com/grafana/oncall/pull/3315))
|
||||
|
||||
## v1.3.56 (2023-11-10)
|
||||
|
||||
## v1.3.55 (2023-11-07)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from apps.integrations.mixins import (
|
|||
is_ratelimit_ignored,
|
||||
)
|
||||
from apps.integrations.tasks import create_alert, create_alertmanager_alerts
|
||||
from apps.user_management.exceptions import OrganizationDeletedException, OrganizationMovedException
|
||||
from common.api_helpers.utils import create_engine_url
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -31,8 +32,10 @@ class AmazonSNS(BrowsableInstructionMixin, AlertChannelDefiningMixin, Integratio
|
|||
def dispatch(self, *args, **kwargs):
|
||||
try:
|
||||
return super().dispatch(*args, **kwargs)
|
||||
except (OrganizationMovedException, OrganizationDeletedException, PermissionDenied) as oe:
|
||||
raise oe
|
||||
except Exception as e:
|
||||
print(e)
|
||||
logger.error(f"AmazonSNS - Bad Request (400) {str(e)}")
|
||||
return JsonResponse(status=400, data={})
|
||||
|
||||
def handle_message(self, message, payload):
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from rest_framework.test import APIClient
|
|||
from apps.alerts.models import AlertReceiveChannel
|
||||
from apps.auth_token.auth import ApiTokenAuthentication, ScheduleExportAuthentication, UserScheduleExportAuthentication
|
||||
from apps.auth_token.models import ScheduleExportAuthToken, UserScheduleExportAuthToken
|
||||
from apps.integrations.views import AlertManagerAPIView
|
||||
from apps.integrations.views import AlertManagerAPIView, AmazonSNS
|
||||
from apps.schedules.models import OnCallScheduleWeb
|
||||
from apps.user_management.exceptions import OrganizationMovedException
|
||||
|
||||
|
|
@ -30,19 +30,27 @@ def test_organization_region_delete(
|
|||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
"integration_type,integration_view",
|
||||
[
|
||||
(AlertReceiveChannel.INTEGRATION_ALERTMANAGER, AlertManagerAPIView()),
|
||||
("amazon_sns", AmazonSNS()),
|
||||
],
|
||||
)
|
||||
def test_integration_does_not_raise_exception_organization_moved(
|
||||
make_organization,
|
||||
make_alert_receive_channel,
|
||||
integration_type,
|
||||
integration_view,
|
||||
):
|
||||
organization = make_organization()
|
||||
alert_receive_channel = make_alert_receive_channel(
|
||||
organization=organization,
|
||||
integration=AlertReceiveChannel.INTEGRATION_ALERTMANAGER,
|
||||
integration=integration_type,
|
||||
)
|
||||
|
||||
try:
|
||||
am = AlertManagerAPIView()
|
||||
am.dispatch(alert_channel_key=alert_receive_channel.token)
|
||||
integration_view.dispatch(alert_channel_key=alert_receive_channel.token)
|
||||
assert False
|
||||
except OrganizationMovedException:
|
||||
assert False
|
||||
|
|
@ -51,21 +59,29 @@ def test_integration_does_not_raise_exception_organization_moved(
|
|||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
"integration_type,integration_view",
|
||||
[
|
||||
(AlertReceiveChannel.INTEGRATION_ALERTMANAGER, AlertManagerAPIView()),
|
||||
("amazon_sns", AmazonSNS()),
|
||||
],
|
||||
)
|
||||
def test_integration_raises_exception_organization_moved(
|
||||
make_organization_and_region,
|
||||
make_alert_receive_channel,
|
||||
integration_type,
|
||||
integration_view,
|
||||
):
|
||||
organization, region = make_organization_and_region()
|
||||
organization.save()
|
||||
|
||||
alert_receive_channel = make_alert_receive_channel(
|
||||
organization=organization,
|
||||
integration=AlertReceiveChannel.INTEGRATION_ALERTMANAGER,
|
||||
integration=integration_type,
|
||||
)
|
||||
|
||||
try:
|
||||
am = AlertManagerAPIView()
|
||||
am.dispatch(alert_channel_key=alert_receive_channel.token)
|
||||
integration_view.dispatch(alert_channel_key=alert_receive_channel.token)
|
||||
assert False
|
||||
except OrganizationMovedException as e:
|
||||
assert e.organization == organization
|
||||
|
|
@ -73,24 +89,29 @@ def test_integration_raises_exception_organization_moved(
|
|||
|
||||
@patch("apps.user_management.middlewares.OrganizationMovedMiddleware.make_request")
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
"integration_type",
|
||||
[
|
||||
AlertReceiveChannel.INTEGRATION_ALERTMANAGER,
|
||||
"amazon_sns",
|
||||
],
|
||||
)
|
||||
def test_organization_moved_middleware(
|
||||
mocked_make_request,
|
||||
make_organization_and_region,
|
||||
make_alert_receive_channel,
|
||||
mocked_make_request, make_organization_and_region, make_alert_receive_channel, integration_type
|
||||
):
|
||||
organization, region = make_organization_and_region()
|
||||
organization.save()
|
||||
|
||||
alert_receive_channel = make_alert_receive_channel(
|
||||
organization=organization,
|
||||
integration=AlertReceiveChannel.INTEGRATION_ALERTMANAGER,
|
||||
integration=integration_type,
|
||||
)
|
||||
|
||||
expected_message = bytes(f"Redirected to {region.oncall_backend_url}", "utf-8")
|
||||
mocked_make_request.return_value = HttpResponse(expected_message, status=status.HTTP_200_OK)
|
||||
|
||||
client = APIClient()
|
||||
url = reverse("integrations:alertmanager", kwargs={"alert_channel_key": alert_receive_channel.token})
|
||||
url = reverse(f"integrations:{integration_type}", kwargs={"alert_channel_key": alert_receive_channel.token})
|
||||
|
||||
data = {"value": "test"}
|
||||
response = client.post(url, data, format="json")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
from celery import uuid as celery_uuid
|
||||
from django.core.management import BaseCommand
|
||||
|
||||
from apps.alerts.models import AlertGroup
|
||||
from apps.alerts.tasks import acknowledge_reminder_task
|
||||
from apps.user_management.models import Organization
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
Restart acknowledge_reminder_task for organization. Used for migrated organizations.
|
||||
|
||||
Usage example:
|
||||
`python manage.py restart_acknowledge_reminder -ppk "organization ppk"` - restart task for alert groups from
|
||||
organizations with this public pk
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
|
||||
group.add_argument(
|
||||
"-ppk", "--organization_ppk", type=str, help="Organization public pks to restart reminder for."
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
organization_ppk = options["organization_ppk"]
|
||||
organization = Organization.objects.get(public_primary_key=organization_ppk)
|
||||
self.stdout.write(
|
||||
f"Processing restart acknowledge reminder for alert groups from organization "
|
||||
f"(id: {organization.id}, ppk: {organization.public_primary_key})..."
|
||||
)
|
||||
if organization.acknowledge_remind_timeout == 0:
|
||||
self.stdout.write("Organization doesn't have acknowledge reminder setting set")
|
||||
return
|
||||
|
||||
alert_groups = AlertGroup.objects.filter(
|
||||
acknowledged=True,
|
||||
resolved=False,
|
||||
silenced=False,
|
||||
maintenance_uuid__isnull=True,
|
||||
root_alert_group=None,
|
||||
channel__organization=organization,
|
||||
)
|
||||
if not alert_groups:
|
||||
self.stdout.write("No affected alert groups.")
|
||||
return
|
||||
|
||||
self.stdout.write(f"Affected alert groups count: {alert_groups.count()}.")
|
||||
|
||||
tasks = []
|
||||
alert_groups_to_update = []
|
||||
|
||||
for alert_group in alert_groups:
|
||||
task_id = celery_uuid()
|
||||
countdown = Organization.ACKNOWLEDGE_REMIND_DELAY[organization.acknowledge_remind_timeout]
|
||||
alert_group.last_unique_unacknowledge_process_id = task_id
|
||||
alert_groups_to_update.append(alert_group)
|
||||
tasks.append(
|
||||
acknowledge_reminder_task.signature(
|
||||
args=(alert_group.pk, task_id), immutable=True, task_id=task_id, countdown=countdown
|
||||
)
|
||||
)
|
||||
|
||||
AlertGroup.objects.bulk_update(
|
||||
alert_groups_to_update,
|
||||
["last_unique_unacknowledge_process_id"],
|
||||
batch_size=5000,
|
||||
)
|
||||
|
||||
for task in tasks:
|
||||
task.apply_async()
|
||||
|
||||
self.stdout.write("Acknowledge reminder has been restarted for affected alert groups")
|
||||
Loading…
Add table
Reference in a new issue