mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-18 05:28:16 -06:00
Misc cleanup
This commit is contained in:
parent
78c2dba68f
commit
c45bdf4884
@ -15,7 +15,7 @@ __all__ = [
|
|||||||
'NestedImageAttachmentSerializer',
|
'NestedImageAttachmentSerializer',
|
||||||
'NestedJournalEntrySerializer',
|
'NestedJournalEntrySerializer',
|
||||||
'NestedSavedFilterSerializer',
|
'NestedSavedFilterSerializer',
|
||||||
'NestedScriptModuleSerializer',
|
'NestedScriptSerializer',
|
||||||
'NestedTagSerializer', # Defined in netbox.api.serializers
|
'NestedTagSerializer', # Defined in netbox.api.serializers
|
||||||
'NestedWebhookSerializer',
|
'NestedWebhookSerializer',
|
||||||
]
|
]
|
||||||
@ -117,7 +117,7 @@ class NestedJournalEntrySerializer(WritableNestedSerializer):
|
|||||||
fields = ['id', 'url', 'display', 'created']
|
fields = ['id', 'url', 'display', 'created']
|
||||||
|
|
||||||
|
|
||||||
class NestedScriptModuleSerializer(WritableNestedSerializer):
|
class NestedScriptSerializer(WritableNestedSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(
|
url = serializers.HyperlinkedIdentityField(
|
||||||
view_name='extras-api:script-detail',
|
view_name='extras-api:script-detail',
|
||||||
lookup_field='full_name',
|
lookup_field='full_name',
|
||||||
@ -127,7 +127,7 @@ class NestedScriptModuleSerializer(WritableNestedSerializer):
|
|||||||
display = serializers.SerializerMethodField(read_only=True)
|
display = serializers.SerializerMethodField(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.ScriptModule
|
model = models.Script
|
||||||
fields = ['id', 'url', 'display', 'name']
|
fields = ['id', 'url', 'display', 'name']
|
||||||
|
|
||||||
def get_display(self, obj):
|
def get_display(self, obj):
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from drf_spectacular.types import OpenApiTypes
|
||||||
|
from drf_spectacular.utils import extend_schema_field
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from core.api.serializers import JobSerializer
|
|
||||||
from core.api.nested_serializers import NestedDataSourceSerializer, NestedDataFileSerializer, NestedJobSerializer
|
from core.api.nested_serializers import NestedDataSourceSerializer, NestedDataFileSerializer, NestedJobSerializer
|
||||||
|
from core.api.serializers import JobSerializer
|
||||||
from core.models import ContentType
|
from core.models import ContentType
|
||||||
from dcim.api.nested_serializers import (
|
from dcim.api.nested_serializers import (
|
||||||
NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedLocationSerializer, NestedPlatformSerializer,
|
NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedLocationSerializer, NestedPlatformSerializer,
|
||||||
NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer,
|
NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer,
|
||||||
)
|
)
|
||||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||||
from drf_spectacular.utils import extend_schema_field
|
|
||||||
from drf_spectacular.types import OpenApiTypes
|
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.models import *
|
from extras.models import *
|
||||||
from netbox.api.exceptions import SerializerNotFound
|
from netbox.api.exceptions import SerializerNotFound
|
||||||
@ -84,17 +84,17 @@ class EventRuleSerializer(NetBoxModelSerializer):
|
|||||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||||
def get_action_object(self, instance):
|
def get_action_object(self, instance):
|
||||||
context = {'request': self.context['request']}
|
context = {'request': self.context['request']}
|
||||||
if instance.action_type == EventRuleActionChoices.WEBHOOK:
|
# We need to manually instantiate the serializer for scripts
|
||||||
|
if instance.action_type == EventRuleActionChoices.SCRIPT:
|
||||||
|
module_id, script_name = instance.action_parameters['script_choice'].split(":", maxsplit=1)
|
||||||
|
script = instance.action_object.scripts[script_name]()
|
||||||
|
return NestedScriptSerializer(script, context=context).data
|
||||||
|
else:
|
||||||
serializer = get_serializer_for_model(
|
serializer = get_serializer_for_model(
|
||||||
model=instance.action_object_type.model_class(),
|
model=instance.action_object_type.model_class(),
|
||||||
prefix=NESTED_SERIALIZER_PREFIX
|
prefix=NESTED_SERIALIZER_PREFIX
|
||||||
)
|
)
|
||||||
return serializer(instance.action_object, context=context).data
|
return serializer(instance.action_object, context=context).data
|
||||||
elif instance.action_type == EventRuleActionChoices.SCRIPT:
|
|
||||||
from extras.api.nested_serializers import NestedScriptModuleSerializer
|
|
||||||
module_id, script_name = instance.action_parameters['script_choice'].split(":", maxsplit=1)
|
|
||||||
script = instance.action_object.scripts[script_name]()
|
|
||||||
return NestedScriptModuleSerializer(script, context=context).data
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django_rq import get_queue
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
from django_rq import get_queue
|
||||||
|
|
||||||
from netbox.config import get_config
|
from netbox.config import get_config
|
||||||
from netbox.constants import RQ_QUEUE_DEFAULT
|
from netbox.constants import RQ_QUEUE_DEFAULT
|
||||||
|
@ -250,7 +250,7 @@ class EventRuleForm(NetBoxModelForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(_('EventRule'), ('name', 'description', 'content_types', 'enabled', 'tags')),
|
(_('Event Rule'), ('name', 'description', 'content_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'), (
|
||||||
|
@ -73,10 +73,12 @@ class EventRuleTest(APITestCase):
|
|||||||
Tag(name='Baz', slug='baz'),
|
Tag(name='Baz', slug='baz'),
|
||||||
))
|
))
|
||||||
|
|
||||||
def test_event_rule_conditions(self):
|
def test_eventrule_conditions(self):
|
||||||
# Create a conditional Webhook
|
"""
|
||||||
|
Test evaluation of EventRule conditions.
|
||||||
|
"""
|
||||||
event_rule = EventRule(
|
event_rule = EventRule(
|
||||||
name='Conditional Webhook',
|
name='Event Rule 1',
|
||||||
type_create=True,
|
type_create=True,
|
||||||
type_update=True,
|
type_update=True,
|
||||||
conditions={
|
conditions={
|
||||||
@ -103,7 +105,10 @@ class EventRuleTest(APITestCase):
|
|||||||
# Evaluate the conditions (status='active')
|
# Evaluate the conditions (status='active')
|
||||||
self.assertTrue(event_rule.eval_conditions(data))
|
self.assertTrue(event_rule.eval_conditions(data))
|
||||||
|
|
||||||
def test_enqueue_webhook_create(self):
|
def test_single_create_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that creating an object with an applicable EventRule queues a background task for the rule's action.
|
||||||
|
"""
|
||||||
# Create an object via the REST API
|
# Create an object via the REST API
|
||||||
data = {
|
data = {
|
||||||
'name': 'Site 1',
|
'name': 'Site 1',
|
||||||
@ -120,7 +125,7 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(Site.objects.count(), 1)
|
self.assertEqual(Site.objects.count(), 1)
|
||||||
self.assertEqual(Site.objects.first().tags.count(), 2)
|
self.assertEqual(Site.objects.first().tags.count(), 2)
|
||||||
|
|
||||||
# Verify that a job was queued for the object creation webhook
|
# Verify that a background task was queued for the new object
|
||||||
self.assertEqual(self.queue.count, 1)
|
self.assertEqual(self.queue.count, 1)
|
||||||
job = self.queue.jobs[0]
|
job = self.queue.jobs[0]
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_create=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_create=True))
|
||||||
@ -131,7 +136,11 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], 'Site 1')
|
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], 'Site 1')
|
||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo'])
|
||||||
|
|
||||||
def test_enqueue_webhook_bulk_create(self):
|
def test_bulk_create_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that bulk creating multiple objects with an applicable EventRule queues a background task for each
|
||||||
|
new object.
|
||||||
|
"""
|
||||||
# Create multiple objects via the REST API
|
# Create multiple objects via the REST API
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
@ -166,7 +175,7 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(Site.objects.count(), 3)
|
self.assertEqual(Site.objects.count(), 3)
|
||||||
self.assertEqual(Site.objects.first().tags.count(), 2)
|
self.assertEqual(Site.objects.first().tags.count(), 2)
|
||||||
|
|
||||||
# Verify that a webhook was queued for each object
|
# Verify that a background task was queued for each new object
|
||||||
self.assertEqual(self.queue.count, 3)
|
self.assertEqual(self.queue.count, 3)
|
||||||
for i, job in enumerate(self.queue.jobs):
|
for i, job in enumerate(self.queue.jobs):
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_create=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_create=True))
|
||||||
@ -177,7 +186,10 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], response.data[i]['name'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], response.data[i]['name'])
|
||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo'])
|
||||||
|
|
||||||
def test_enqueue_webhook_update(self):
|
def test_single_update_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that updating an object with an applicable EventRule queues a background task for the rule's action.
|
||||||
|
"""
|
||||||
site = Site.objects.create(name='Site 1', slug='site-1')
|
site = Site.objects.create(name='Site 1', slug='site-1')
|
||||||
site.tags.set(Tag.objects.filter(name__in=['Foo', 'Bar']))
|
site.tags.set(Tag.objects.filter(name__in=['Foo', 'Bar']))
|
||||||
|
|
||||||
@ -194,7 +206,7 @@ class EventRuleTest(APITestCase):
|
|||||||
response = self.client.patch(url, data, format='json', **self.header)
|
response = self.client.patch(url, data, format='json', **self.header)
|
||||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||||
|
|
||||||
# Verify that a job was queued for the object update webhook
|
# Verify that a background task was queued for the updated object
|
||||||
self.assertEqual(self.queue.count, 1)
|
self.assertEqual(self.queue.count, 1)
|
||||||
job = self.queue.jobs[0]
|
job = self.queue.jobs[0]
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_update=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_update=True))
|
||||||
@ -207,7 +219,11 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], 'Site X')
|
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], 'Site X')
|
||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Baz'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Baz'])
|
||||||
|
|
||||||
def test_enqueue_webhook_bulk_update(self):
|
def test_bulk_update_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that bulk updating multiple objects with an applicable EventRule queues a background task for each
|
||||||
|
updated object.
|
||||||
|
"""
|
||||||
sites = (
|
sites = (
|
||||||
Site(name='Site 1', slug='site-1'),
|
Site(name='Site 1', slug='site-1'),
|
||||||
Site(name='Site 2', slug='site-2'),
|
Site(name='Site 2', slug='site-2'),
|
||||||
@ -246,7 +262,7 @@ class EventRuleTest(APITestCase):
|
|||||||
response = self.client.patch(url, data, format='json', **self.header)
|
response = self.client.patch(url, data, format='json', **self.header)
|
||||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||||
|
|
||||||
# Verify that a job was queued for the object update webhook
|
# Verify that a background task was queued for each updated object
|
||||||
self.assertEqual(self.queue.count, 3)
|
self.assertEqual(self.queue.count, 3)
|
||||||
for i, job in enumerate(self.queue.jobs):
|
for i, job in enumerate(self.queue.jobs):
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_update=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_update=True))
|
||||||
@ -259,7 +275,10 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], response.data[i]['name'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['name'], response.data[i]['name'])
|
||||||
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Baz'])
|
self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Baz'])
|
||||||
|
|
||||||
def test_enqueue_webhook_delete(self):
|
def test_single_delete_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that deleting an object with an applicable EventRule queues a background task for the rule's action.
|
||||||
|
"""
|
||||||
site = Site.objects.create(name='Site 1', slug='site-1')
|
site = Site.objects.create(name='Site 1', slug='site-1')
|
||||||
site.tags.set(Tag.objects.filter(name__in=['Foo', 'Bar']))
|
site.tags.set(Tag.objects.filter(name__in=['Foo', 'Bar']))
|
||||||
|
|
||||||
@ -269,7 +288,7 @@ class EventRuleTest(APITestCase):
|
|||||||
response = self.client.delete(url, **self.header)
|
response = self.client.delete(url, **self.header)
|
||||||
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
# Verify that a job was queued for the object update webhook
|
# Verify that a task was queued for the deleted object
|
||||||
self.assertEqual(self.queue.count, 1)
|
self.assertEqual(self.queue.count, 1)
|
||||||
job = self.queue.jobs[0]
|
job = self.queue.jobs[0]
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_delete=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_delete=True))
|
||||||
@ -279,7 +298,11 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['prechange']['name'], 'Site 1')
|
self.assertEqual(job.kwargs['snapshots']['prechange']['name'], 'Site 1')
|
||||||
self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo'])
|
self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo'])
|
||||||
|
|
||||||
def test_enqueue_webhook_bulk_delete(self):
|
def test_bulk_delete_process_eventrule(self):
|
||||||
|
"""
|
||||||
|
Check that bulk deleting multiple objects with an applicable EventRule queues a background task for each
|
||||||
|
deleted object.
|
||||||
|
"""
|
||||||
sites = (
|
sites = (
|
||||||
Site(name='Site 1', slug='site-1'),
|
Site(name='Site 1', slug='site-1'),
|
||||||
Site(name='Site 2', slug='site-2'),
|
Site(name='Site 2', slug='site-2'),
|
||||||
@ -298,7 +321,7 @@ class EventRuleTest(APITestCase):
|
|||||||
response = self.client.delete(url, data, format='json', **self.header)
|
response = self.client.delete(url, data, format='json', **self.header)
|
||||||
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
# Verify that a job was queued for the object update webhook
|
# Verify that a background task was queued for each deleted object
|
||||||
self.assertEqual(self.queue.count, 3)
|
self.assertEqual(self.queue.count, 3)
|
||||||
for i, job in enumerate(self.queue.jobs):
|
for i, job in enumerate(self.queue.jobs):
|
||||||
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_delete=True))
|
self.assertEqual(job.kwargs['event_rule'], EventRule.objects.get(type_delete=True))
|
||||||
@ -309,7 +332,6 @@ class EventRuleTest(APITestCase):
|
|||||||
self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo'])
|
self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo'])
|
||||||
|
|
||||||
def test_webhooks_worker(self):
|
def test_webhooks_worker(self):
|
||||||
|
|
||||||
request_id = uuid.uuid4()
|
request_id = uuid.uuid4()
|
||||||
|
|
||||||
def dummy_send(_, request, **kwargs):
|
def dummy_send(_, request, **kwargs):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import json
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ from extras.choices import *
|
|||||||
from extras.models import *
|
from extras.models import *
|
||||||
from utilities.testing import ViewTestCases, TestCase
|
from utilities.testing import ViewTestCases, TestCase
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user