Skip to content

Commit

Permalink
Merge pull request #352 from stveit/event_type_stateless
Browse files Browse the repository at this point in the history
Add new Event type stateless
  • Loading branch information
stveit authored Mar 4, 2022
2 parents 077e6a8 + d6c404a commit ce63cb6
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/argus/incident/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ class IncidentConfig(AppConfig):
label = "argus_incident"

def ready(self):
from .signals import delete_associated_user, delete_associated_event, create_start_event, send_notification
from .signals import delete_associated_user, delete_associated_event, create_first_event, send_notification

post_delete.connect(delete_associated_user, "argus_incident.SourceSystem")
post_delete.connect(delete_associated_event, "argus_incident.Acknowledgement")
post_save.connect(create_start_event, "argus_incident.Incident")
post_save.connect(create_first_event, "argus_incident.Incident")
post_save.connect(send_notification, "argus_incident.Event", dispatch_uid="send_notification")
35 changes: 35 additions & 0 deletions src/argus/incident/migrations/0005_alter_event_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 3.2.11 on 2022-03-01 12:34

from django.db import migrations, models


def add_stateless_event_type(apps, schema_editor):
# Change INCIDENT_START events for stateless incidents to STATELESS
Event = apps.get_model('argus_incident', 'Event')
for event in Event.objects.all():
if event.type == "STA" and event.incident.end_time == None:
event.type="LES"
event.save()

def remove_stateless_event_type(apps, schema_editor):
# undo changes made by add_stateless_event_type
Event = apps.get_model('argus_incident', 'Event')
for event in Event.objects.all():
if event.type == "LES":
event.type = "STA"
event.save()

class Migration(migrations.Migration):

dependencies = [
('argus_incident', '0004_add_ChangeEvent_proxy'),
]

operations = [
migrations.AlterField(
model_name='event',
name='type',
field=models.CharField(choices=[('STA', 'Incident start'), ('END', 'Incident end'), ('CHI', 'Incident change'), ('CLO', 'Close'), ('REO', 'Reopen'), ('ACK', 'Acknowledge'), ('OTH', 'Other'), ('LES', 'Stateless')], max_length=3),
),
migrations.RunPython(add_stateless_event_type, remove_stateless_event_type),
]
7 changes: 6 additions & 1 deletion src/argus/incident/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ def last_close_or_end_event(self):
def latest_change_event(self):
return self.events.filter(type=Event.Type.INCIDENT_CHANGE).order_by("timestamp").last()

@property
def stateless_event(self):
return self.events.filter(type=Event.Type.STATELESS).order_by("timestamp").first()

@property
def acks(self):
return Acknowledgement.objects.filter(event__incident=self)
Expand Down Expand Up @@ -386,8 +390,9 @@ class Type(models.TextChoices):
REOPEN = "REO", "Reopen"
ACKNOWLEDGE = "ACK", "Acknowledge"
OTHER = "OTH", "Other"
STATELESS = "LES", "Stateless"

ALLOWED_TYPES_FOR_SOURCE_SYSTEMS = {Type.INCIDENT_START, Type.INCIDENT_END, Type.OTHER, Type.INCIDENT_CHANGE}
ALLOWED_TYPES_FOR_SOURCE_SYSTEMS = {Type.INCIDENT_START, Type.INCIDENT_END, Type.OTHER, Type.INCIDENT_CHANGE, Type.STATELESS}
ALLOWED_TYPES_FOR_END_USERS = {Type.CLOSE, Type.REOPEN, Type.ACKNOWLEDGE, Type.OTHER}

incident = models.ForeignKey(to=Incident, on_delete=models.PROTECT, related_name="events")
Expand Down
9 changes: 5 additions & 4 deletions src/argus/incident/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

__all__ = [
"delete_associated_user",
"create_start_event",
"create_first_event",
"send_notification",
"delete_associated_event",
]
Expand All @@ -15,15 +15,16 @@ def delete_associated_user(sender, instance: SourceSystem, *args, **kwargs):
instance.user.delete()


def create_start_event(sender, instance: Incident, created, raw, *args, **kwargs):
def create_first_event(sender, instance: Incident, created, raw, *args, **kwargs):
if raw or not created:
return
if not instance.start_event:
if not instance.start_event and not instance.stateless_event:
event_type = Event.Type.INCIDENT_START if instance.stateful else Event.Type.STATELESS
Event.objects.create(
incident=instance,
actor=instance.source.user,
timestamp=instance.start_time,
type=Event.Type.INCIDENT_START,
type=event_type,
description=instance.description,
)

Expand Down
4 changes: 3 additions & 1 deletion src/argus/incident/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,10 @@ def validate_incident_has_no_relation_to_event_type():
elif event_type == Event.Type.REOPEN and incident.open:
self._raise_type_validation_error("The incident is already open.")
else:
if event_type == Event.Type.INCIDENT_START:
if event_type == Event.Type.STATELESS:
validate_incident_has_no_relation_to_event_type()
elif event_type == Event.Type.INCIDENT_START:
self._raise_type_validation_error("Stateless incident cannot have an INCIDENT_START event.")
elif event_type in {Event.Type.INCIDENT_END, Event.Type.CLOSE, Event.Type.REOPEN}:
self._raise_type_validation_error("Cannot change the state of a stateless incident.")

Expand Down
21 changes: 21 additions & 0 deletions tests/incident/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from django.utils.timezone import make_aware
from django.test import TestCase
from rest_framework import status
from rest_framework.test import APITestCase

Expand Down Expand Up @@ -195,3 +196,23 @@ def test_event_has_description(self):

self.assertTrue(event_start)
self.assertEqual(incident.description, incident.events.get(type="STA").description)


class StatelessEventTests(TestCase):
def setUp(self):
disconnect_signals()

def tearDown(self):
connect_signals()

def test_new_stateless_incident_has_stateless_event(self):
source_incident_id = "abcknekkebrod"
incident = Incident.objects.create(
start_time=timezone.now(),
end_time=None,
source_incident_id=source_incident_id,
source=SourceSystemFactory(),
description=f"Incident #{source_incident_id} created for testing",
)
event_stateless = incident.events.filter(type=Event.Type.STATELESS)
self.assertEqual(1, event_stateless.count())

0 comments on commit ce63cb6

Please sign in to comment.