Rename EventRule.content_types to object_types & use ObjectType proxy

This commit is contained in:
Jeremy Stretch 2024-03-01 15:31:03 -05:00
parent ba514aceac
commit e51d71d7e6
15 changed files with 71 additions and 58 deletions

View File

@ -59,7 +59,7 @@ __all__ = (
class EventRuleSerializer(NetBoxModelSerializer): class EventRuleSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='extras-api:eventrule-detail') url = serializers.HyperlinkedIdentityField(view_name='extras-api:eventrule-detail')
content_types = ContentTypeField( object_types = ContentTypeField(
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
many=True many=True
) )
@ -72,7 +72,7 @@ class EventRuleSerializer(NetBoxModelSerializer):
class Meta: class Meta:
model = EventRule model = EventRule
fields = [ fields = [
'id', 'url', 'display', 'content_types', 'name', 'type_create', 'type_update', 'type_delete', 'id', 'url', 'display', 'object_types', 'name', 'type_create', 'type_update', 'type_delete',
'type_job_start', 'type_job_end', 'enabled', 'conditions', 'action_type', 'action_object_type', 'type_job_start', 'type_job_end', 'enabled', 'conditions', 'action_type', 'action_object_type',
'action_object_id', 'action_object', 'description', 'custom_fields', 'tags', 'created', 'last_updated', 'action_object_id', 'action_object', 'description', 'custom_fields', 'tags', 'created', 'last_updated',
] ]

View File

@ -155,7 +155,7 @@ def process_event_queue(events):
if content_type not in events_cache[action_flag]: if content_type not in events_cache[action_flag]:
events_cache[action_flag][content_type] = EventRule.objects.filter( events_cache[action_flag][content_type] = EventRule.objects.filter(
**{action_flag: True}, **{action_flag: True},
content_types=content_type, object_types=content_type,
enabled=True enabled=True
) )
event_rules = events_cache[action_flag][content_type] event_rules = events_cache[action_flag][content_type]

View File

@ -89,10 +89,10 @@ class EventRuleFilterSet(NetBoxModelFilterSet):
method='search', method='search',
label=_('Search'), label=_('Search'),
) )
content_type_id = MultiValueNumberFilter( object_types_id = MultiValueNumberFilter(
field_name='content_types__id' field_name='object_types__id'
) )
content_types = ContentTypeFilter() object_types = ContentTypeFilter()
action_type = django_filters.MultipleChoiceFilter( action_type = django_filters.MultipleChoiceFilter(
choices=EventRuleActionChoices choices=EventRuleActionChoices
) )

View File

@ -173,8 +173,8 @@ class WebhookImportForm(NetBoxModelImportForm):
class EventRuleImportForm(NetBoxModelImportForm): class EventRuleImportForm(NetBoxModelImportForm):
content_types = CSVMultipleContentTypeField( object_types = CSVMultipleContentTypeField(
label=_('Content types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
help_text=_("One or more assigned object types") help_text=_("One or more assigned object types")
) )
@ -187,7 +187,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
class Meta: class Meta:
model = EventRule model = EventRule
fields = ( fields = (
'name', 'description', 'enabled', 'conditions', 'content_types', 'type_create', 'type_update', 'name', 'description', 'enabled', 'conditions', 'object_types', 'type_create', 'type_update',
'type_delete', 'type_job_start', 'type_job_end', 'action_type', 'action_object', 'comments', 'tags' 'type_delete', 'type_job_start', 'type_job_end', 'action_type', 'action_object', 'comments', 'tags'
) )

View File

@ -250,10 +250,10 @@ class EventRuleFilterForm(NetBoxModelFilterSetForm):
fieldsets = ( fieldsets = (
(None, ('q', 'filter_id', 'tag')), (None, ('q', 'filter_id', 'tag')),
(_('Attributes'), ('content_type_id', 'action_type', 'enabled')), (_('Attributes'), ('object_types_id', 'action_type', 'enabled')),
(_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')), (_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')),
) )
content_type_id = ContentTypeMultipleChoiceField( object_types_id = ContentTypeMultipleChoiceField(
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
required=False, required=False,
label=_('Object type') label=_('Object type')

View File

@ -248,8 +248,8 @@ class WebhookForm(NetBoxModelForm):
class EventRuleForm(NetBoxModelForm): class EventRuleForm(NetBoxModelForm):
content_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Content types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
) )
action_choice = forms.ChoiceField( action_choice = forms.ChoiceField(
@ -266,7 +266,7 @@ class EventRuleForm(NetBoxModelForm):
) )
fieldsets = ( fieldsets = (
(_('Event Rule'), ('name', 'description', 'content_types', 'enabled', 'tags')), (_('Event Rule'), ('name', 'description', 'object_types', 'enabled', 'tags')),
(_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')), (_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')),
(_('Conditions'), ('conditions',)), (_('Conditions'), ('conditions',)),
(_('Action'), ( (_('Action'), (
@ -277,7 +277,7 @@ class EventRuleForm(NetBoxModelForm):
class Meta: class Meta:
model = EventRule model = EventRule
fields = ( fields = (
'content_types', 'name', 'description', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'object_types', 'name', 'description', 'type_create', 'type_update', 'type_delete', 'type_job_start',
'type_job_end', 'enabled', 'conditions', 'action_type', 'action_object_type', 'action_object_id', 'type_job_end', 'enabled', 'conditions', 'action_type', 'action_object_type', 'action_object_id',
'action_data', 'comments', 'tags' 'action_data', 'comments', 'tags'
) )

View File

@ -59,6 +59,14 @@ class CustomLinkType(ObjectType):
filterset_class = filtersets.CustomLinkFilterSet filterset_class = filtersets.CustomLinkFilterSet
class EventRuleType(OrganizationalObjectType):
class Meta:
model = models.EventRule
exclude = ('object_types',)
filterset_class = filtersets.EventRuleFilterSet
class ExportTemplateType(ObjectType): class ExportTemplateType(ObjectType):
class Meta: class Meta:
@ -112,11 +120,3 @@ class WebhookType(OrganizationalObjectType):
class Meta: class Meta:
model = models.Webhook model = models.Webhook
filterset_class = filtersets.WebhookFilterSet filterset_class = filtersets.WebhookFilterSet
class EventRuleType(OrganizationalObjectType):
class Meta:
model = models.EventRule
exclude = ('content_types', )
filterset_class = filtersets.EventRuleFilterSet

View File

@ -38,4 +38,16 @@ class Migration(migrations.Migration):
name='object_types', name='object_types',
field=models.ManyToManyField(related_name='custom_links', to='core.objecttype'), field=models.ManyToManyField(related_name='custom_links', to='core.objecttype'),
), ),
# Event rules
migrations.RenameField(
model_name='eventrule',
old_name='content_types',
new_name='object_types',
),
migrations.AlterField(
model_name='eventrule',
name='object_types',
field=models.ManyToManyField(related_name='event_rules', to='core.objecttype'),
),
] ]

View File

@ -43,9 +43,9 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
specific type of object is created, modified, or deleted. The action to be taken might entail transmitting a specific type of object is created, modified, or deleted. The action to be taken might entail transmitting a
webhook or executing a custom script. webhook or executing a custom script.
""" """
content_types = models.ManyToManyField( object_types = models.ManyToManyField(
to='contenttypes.ContentType', to='core.ObjectType',
related_name='eventrules', related_name='event_rules',
verbose_name=_('object types'), verbose_name=_('object types'),
help_text=_("The object(s) to which this rule applies.") help_text=_("The object(s) to which this rule applies.")
) )

View File

@ -281,8 +281,8 @@ class EventRuleTable(NetBoxTable):
linkify=True, linkify=True,
verbose_name=_('Object'), verbose_name=_('Object'),
) )
content_types = columns.ContentTypesColumn( object_types = columns.ContentTypesColumn(
verbose_name=_('Content Types'), verbose_name=_('Object Types'),
) )
enabled = columns.BooleanColumn( enabled = columns.BooleanColumn(
verbose_name=_('Enabled'), verbose_name=_('Enabled'),
@ -309,7 +309,7 @@ class EventRuleTable(NetBoxTable):
class Meta(NetBoxTable.Meta): class Meta(NetBoxTable.Meta):
model = EventRule model = EventRule
fields = ( fields = (
'pk', 'id', 'name', 'enabled', 'description', 'action_type', 'action_object', 'content_types', 'pk', 'id', 'name', 'enabled', 'description', 'action_type', 'action_object', 'object_types',
'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'tags', 'created', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'tags', 'created',
'last_updated', 'last_updated',
) )

View File

@ -122,7 +122,7 @@ class EventRuleTest(APIViewTestCases.APIViewTestCase):
cls.create_data = [ cls.create_data = [
{ {
'name': 'EventRule 4', 'name': 'EventRule 4',
'content_types': ['dcim.device', 'dcim.devicetype'], 'object_types': ['dcim.device', 'dcim.devicetype'],
'type_create': True, 'type_create': True,
'action_type': EventRuleActionChoices.WEBHOOK, 'action_type': EventRuleActionChoices.WEBHOOK,
'action_object_type': 'extras.webhook', 'action_object_type': 'extras.webhook',
@ -130,7 +130,7 @@ class EventRuleTest(APIViewTestCases.APIViewTestCase):
}, },
{ {
'name': 'EventRule 5', 'name': 'EventRule 5',
'content_types': ['dcim.device', 'dcim.devicetype'], 'object_types': ['dcim.device', 'dcim.devicetype'],
'type_create': True, 'type_create': True,
'action_type': EventRuleActionChoices.WEBHOOK, 'action_type': EventRuleActionChoices.WEBHOOK,
'action_object_type': 'extras.webhook', 'action_object_type': 'extras.webhook',
@ -138,7 +138,7 @@ class EventRuleTest(APIViewTestCases.APIViewTestCase):
}, },
{ {
'name': 'EventRule 6', 'name': 'EventRule 6',
'content_types': ['dcim.device', 'dcim.devicetype'], 'object_types': ['dcim.device', 'dcim.devicetype'],
'type_create': True, 'type_create': True,
'action_type': EventRuleActionChoices.WEBHOOK, 'action_type': EventRuleActionChoices.WEBHOOK,
'action_object_type': 'extras.webhook', 'action_object_type': 'extras.webhook',

View File

@ -3,17 +3,18 @@ import uuid
from unittest.mock import patch from unittest.mock import patch
import django_rq import django_rq
from dcim.choices import SiteStatusChoices
from dcim.models import Site
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import reverse from django.urls import reverse
from requests import Session
from rest_framework import status
from core.models import ObjectType
from dcim.choices import SiteStatusChoices
from dcim.models import Site
from extras.choices import EventRuleActionChoices, ObjectChangeActionChoices from extras.choices import EventRuleActionChoices, ObjectChangeActionChoices
from extras.events import enqueue_object, flush_events, serialize_for_event from extras.events import enqueue_object, flush_events, serialize_for_event
from extras.models import EventRule, Tag, Webhook from extras.models import EventRule, Tag, Webhook
from extras.webhooks import generate_signature, send_webhook from extras.webhooks import generate_signature, send_webhook
from requests import Session
from rest_framework import status
from utilities.testing import APITestCase from utilities.testing import APITestCase
@ -29,7 +30,7 @@ class EventRuleTest(APITestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
site_ct = ContentType.objects.get_for_model(Site) site_type = ObjectType.objects.get_for_model(Site)
DUMMY_URL = 'http://localhost:9000/' DUMMY_URL = 'http://localhost:9000/'
DUMMY_SECRET = 'LOOKATMEIMASECRETSTRING' DUMMY_SECRET = 'LOOKATMEIMASECRETSTRING'
@ -39,32 +40,32 @@ class EventRuleTest(APITestCase):
Webhook(name='Webhook 3', payload_url=DUMMY_URL, secret=DUMMY_SECRET), Webhook(name='Webhook 3', payload_url=DUMMY_URL, secret=DUMMY_SECRET),
)) ))
ct = ContentType.objects.get(app_label='extras', model='webhook') webhook_type = ObjectType.objects.get(app_label='extras', model='webhook')
event_rules = EventRule.objects.bulk_create(( event_rules = EventRule.objects.bulk_create((
EventRule( EventRule(
name='Webhook Event 1', name='Webhook Event 1',
type_create=True, type_create=True,
action_type=EventRuleActionChoices.WEBHOOK, action_type=EventRuleActionChoices.WEBHOOK,
action_object_type=ct, action_object_type=webhook_type,
action_object_id=webhooks[0].id action_object_id=webhooks[0].id
), ),
EventRule( EventRule(
name='Webhook Event 2', name='Webhook Event 2',
type_update=True, type_update=True,
action_type=EventRuleActionChoices.WEBHOOK, action_type=EventRuleActionChoices.WEBHOOK,
action_object_type=ct, action_object_type=webhook_type,
action_object_id=webhooks[0].id action_object_id=webhooks[0].id
), ),
EventRule( EventRule(
name='Webhook Event 3', name='Webhook Event 3',
type_delete=True, type_delete=True,
action_type=EventRuleActionChoices.WEBHOOK, action_type=EventRuleActionChoices.WEBHOOK,
action_object_type=ct, action_object_type=webhook_type,
action_object_id=webhooks[0].id action_object_id=webhooks[0].id
), ),
)) ))
for event_rule in event_rules: for event_rule in event_rules:
event_rule.content_types.set([site_ct]) event_rule.object_types.set([site_type])
Tag.objects.bulk_create(( Tag.objects.bulk_create((
Tag(name='Foo', slug='foo'), Tag(name='Foo', slug='foo'),

View File

@ -241,7 +241,7 @@ class EventRuleTestCase(TestCase, BaseFilterSetTests):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
content_types = ContentType.objects.filter( object_types = ObjectType.objects.filter(
model__in=['region', 'site', 'rack', 'location', 'device'] model__in=['region', 'site', 'rack', 'location', 'device']
) )
@ -334,11 +334,11 @@ class EventRuleTestCase(TestCase, BaseFilterSetTests):
), ),
) )
EventRule.objects.bulk_create(event_rules) EventRule.objects.bulk_create(event_rules)
event_rules[0].content_types.add(content_types[0]) event_rules[0].object_types.add(object_types[0])
event_rules[1].content_types.add(content_types[1]) event_rules[1].object_types.add(object_types[1])
event_rules[2].content_types.add(content_types[2]) event_rules[2].object_types.add(object_types[2])
event_rules[3].content_types.add(content_types[3]) event_rules[3].object_types.add(object_types[3])
event_rules[4].content_types.add(content_types[4]) event_rules[4].object_types.add(object_types[4])
def test_q(self): def test_q(self):
params = {'q': 'foobar1'} params = {'q': 'foobar1'}
@ -352,10 +352,10 @@ class EventRuleTestCase(TestCase, BaseFilterSetTests):
params = {'description': ['foobar1', 'foobar2']} params = {'description': ['foobar1', 'foobar2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_content_types(self): def test_object_types(self):
params = {'content_types': 'dcim.region'} params = {'object_types': 'dcim.region'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
params = {'content_type_id': [ContentType.objects.get_for_model(Region).pk]} params = {'object_types_id': [ContentType.objects.get_for_model(Region).pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_action_type(self): def test_action_type(self):

View File

@ -397,7 +397,7 @@ class EventRulesTestCase(ViewTestCases.PrimaryObjectViewTestCase):
for webhook in webhooks: for webhook in webhooks:
webhook.save() webhook.save()
site_ct = ContentType.objects.get_for_model(Site) site_type = ObjectType.objects.get_for_model(Site)
event_rules = ( event_rules = (
EventRule(name='EventRule 1', type_create=True, action_object=webhooks[0]), EventRule(name='EventRule 1', type_create=True, action_object=webhooks[0]),
EventRule(name='EventRule 2', type_create=True, action_object=webhooks[1]), EventRule(name='EventRule 2', type_create=True, action_object=webhooks[1]),
@ -405,12 +405,12 @@ class EventRulesTestCase(ViewTestCases.PrimaryObjectViewTestCase):
) )
for event in event_rules: for event in event_rules:
event.save() event.save()
event.content_types.add(site_ct) event.object_types.add(site_type)
webhook_ct = ContentType.objects.get_for_model(Webhook) webhook_ct = ContentType.objects.get_for_model(Webhook)
cls.form_data = { cls.form_data = {
'name': 'Event X', 'name': 'Event X',
'content_types': [site_ct.pk], 'object_types': [site_type.pk],
'type_create': False, 'type_create': False,
'type_update': True, 'type_update': True,
'type_delete': True, 'type_delete': True,
@ -423,7 +423,7 @@ class EventRulesTestCase(ViewTestCases.PrimaryObjectViewTestCase):
} }
cls.csv_data = ( cls.csv_data = (
"name,content_types,type_create,action_type,action_object", "name,object_types,type_create,action_type,action_object",
"Webhook 4,dcim.site,True,webhook,Webhook 1", "Webhook 4,dcim.site,True,webhook,Webhook 1",
) )

View File

@ -26,9 +26,9 @@
<div class="card"> <div class="card">
<h5 class="card-header">{% trans "Object Types" %}</h5> <h5 class="card-header">{% trans "Object Types" %}</h5>
<table class="table table-hover attr-table"> <table class="table table-hover attr-table">
{% for ct in object.content_types.all %} {% for object_type in object.object_types.all %}
<tr> <tr>
<td>{{ ct }}</td> <td>{{ object_type }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>