Misc cleanup

This commit is contained in:
Jeremy Stretch 2023-11-15 16:54:19 -05:00
parent 12b4bf80bc
commit 58136deeaf
6 changed files with 25 additions and 35 deletions

View File

@ -292,6 +292,6 @@ class EventRuleActionChoices(ChoiceSet):
SCRIPT = 'script' SCRIPT = 'script'
CHOICES = ( CHOICES = (
(WEBHOOK, _('Webhook'), 'webhook'), (WEBHOOK, _('Webhook')),
(SCRIPT, _('Script'), 'script'), (SCRIPT, _('Script')),
) )

View File

@ -136,10 +136,3 @@ DEFAULT_DASHBOARD = [
} }
}, },
] ]
EVENT_TYPE_MODELS = Q(
app_label='extras',
model__in=(
'webhook',
'script',
))

View File

@ -1,5 +1,3 @@
import hashlib
import hmac
import logging import logging
import sys import sys
@ -15,14 +13,14 @@ from utilities.api import get_serializer_for_model
from utilities.rqworker import get_rq_retry from utilities.rqworker import get_rq_retry
from utilities.utils import serialize_object from utilities.utils import serialize_object
from .choices import * from .choices import *
from .models import EventRule, Webhook from .models import EventRule
logger = logging.getLogger('netbox.events_processor') logger = logging.getLogger('netbox.events_processor')
def serialize_for_event(instance): def serialize_for_event(instance):
""" """
Return a serialized representation of the given instance suitable for use in a webhook. Return a serialized representation of the given instance suitable for use in a queued event.
""" """
serializer_class = get_serializer_for_model(instance.__class__) serializer_class = get_serializer_for_model(instance.__class__)
serializer_context = { serializer_context = {
@ -51,9 +49,9 @@ def get_snapshots(instance, action):
def enqueue_object(queue, instance, user, request_id, action): def enqueue_object(queue, instance, user, request_id, action):
""" """
Enqueue a serialized representation of a created/updated/deleted object for the processing of Enqueue a serialized representation of a created/updated/deleted object for the processing of
webhooks once the request has completed. events once the request has completed.
""" """
# Determine whether this type of object supports webhooks # Determine whether this type of object supports event rules
app_label = instance._meta.app_label app_label = instance._meta.app_label
model_name = instance._meta.model_name model_name = instance._meta.model_name
if model_name not in registry['model_features']['webhooks'].get(app_label, []): if model_name not in registry['model_features']['webhooks'].get(app_label, []):
@ -72,7 +70,7 @@ def enqueue_object(queue, instance, user, request_id, action):
def process_event_rules(queue): def process_event_rules(queue):
""" """
Flush a list of object representation to RQ for webhook processing. Flush a list of object representation to RQ for EventRule processing.
""" """
rq_queue_name = get_config().QUEUE_MAPPINGS.get('webhook', RQ_QUEUE_DEFAULT) rq_queue_name = get_config().QUEUE_MAPPINGS.get('webhook', RQ_QUEUE_DEFAULT)
rq_queue = get_queue(rq_queue_name) rq_queue = get_queue(rq_queue_name)
@ -138,7 +136,7 @@ def flush_events(queue):
Flush a list of object representation to RQ for webhook processing. Flush a list of object representation to RQ for webhook processing.
""" """
if queue: if queue:
for name in settings.NETBOX_EVENTS_PIPELINE: for name in settings.EVENTS_PIPELINE:
try: try:
func = module_member(name) func = module_member(name)
func(queue) func(queue)

View File

@ -47,8 +47,8 @@ class WebhookFilterSet(NetBoxModelFilterSet):
class Meta: class Meta:
model = Webhook model = Webhook
fields = [ fields = [
'id', 'name', 'payload_url', 'id', 'name', 'payload_url', 'http_method', 'http_content_type', 'secret', 'ssl_verification',
'http_method', 'http_content_type', 'secret', 'ssl_verification', 'ca_file_path', 'ca_file_path',
] ]
def search(self, queryset, name, value): def search(self, queryset, name, value):
@ -73,8 +73,7 @@ class EventRuleFilterSet(NetBoxModelFilterSet):
class Meta: class Meta:
model = EventRule model = EventRule
fields = [ fields = [
'id', 'name', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'id', 'name', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'enabled',
'enabled',
] ]
def search(self, queryset, name, value): def search(self, queryset, name, value):

View File

@ -41,14 +41,15 @@ __all__ = (
class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel): class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
""" """
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or An EventRule defines an action to be taken automatically in response to a specific set of events, such as when a
delete in NetBox. The request will contain a representation of the object, which the remote application can act on. specific type of object is created, modified, or deleted. The action to be taken might entail transmitting a
Each Webhook can be limited to firing only on certain actions or certain object types. webhook or executing a custom script.
""" """
content_types = models.ManyToManyField( content_types = models.ManyToManyField(
to=ContentType, to=ContentType,
related_name='eventrules', related_name='eventrules',
verbose_name=_('object types'), verbose_name=_('object types'),
# TODO: FeatureQuery is being removed under #14153
limit_choices_to=FeatureQuery('eventrules'), limit_choices_to=FeatureQuery('eventrules'),
help_text=_("The object(s) to which this Event applies.") help_text=_("The object(s) to which this Event applies.")
) )
@ -98,12 +99,12 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
max_length=30, max_length=30,
choices=EventRuleActionChoices, choices=EventRuleActionChoices,
default=EventRuleActionChoices.WEBHOOK, default=EventRuleActionChoices.WEBHOOK,
verbose_name=_('event type') verbose_name=_('action type')
) )
action_object_type = models.ForeignKey( action_object_type = models.ForeignKey(
to=ContentType, to=ContentType,
related_name='eventrule_actions', related_name='eventrule_actions',
on_delete=models.CASCADE, on_delete=models.CASCADE
) )
action_object_id = models.PositiveBigIntegerField( action_object_id = models.PositiveBigIntegerField(
blank=True, blank=True,
@ -111,9 +112,8 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
) )
action_object = GenericForeignKey( action_object = GenericForeignKey(
ct_field='action_object_type', ct_field='action_object_type',
fk_field='action_object_id', fk_field='action_object_id'
) )
# internal (not show in UI) - used by scripts to store function name # internal (not show in UI) - used by scripts to store function name
action_object_identifier = models.CharField( action_object_identifier = models.CharField(
max_length=80, max_length=80,
@ -128,8 +128,8 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
verbose_name = _('eventrule') verbose_name = _('event rule')
verbose_name_plural = _('eventrules') verbose_name_plural = _('event rules')
def __str__(self): def __str__(self):
return self.name return self.name
@ -149,9 +149,10 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
self.type_create, self.type_update, self.type_delete, self.type_job_start, self.type_job_end self.type_create, self.type_update, self.type_delete, self.type_job_start, self.type_job_end
]): ]):
raise ValidationError( raise ValidationError(
_("At least one event type must be selected: create, update, delete, job_start, and/or job_end.") _("At least one event type must be selected: create, update, delete, job start, and/or job end.")
) )
# Validate that any conditions are in the correct format
if self.conditions: if self.conditions:
try: try:
ConditionSet(self.conditions) ConditionSet(self.conditions)
@ -170,7 +171,6 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
content_type_field='action_object_type', content_type_field='action_object_type',
object_id_field='action_object_id' object_id_field='action_object_id'
) )
name = models.CharField( name = models.CharField(
verbose_name=_('name'), verbose_name=_('name'),
max_length=150, max_length=150,

View File

@ -115,6 +115,9 @@ DEFAULT_PERMISSIONS = getattr(configuration, 'DEFAULT_PERMISSIONS', {
DEVELOPER = getattr(configuration, 'DEVELOPER', False) DEVELOPER = getattr(configuration, 'DEVELOPER', False)
DOCS_ROOT = getattr(configuration, 'DOCS_ROOT', os.path.join(os.path.dirname(BASE_DIR), 'docs')) DOCS_ROOT = getattr(configuration, 'DOCS_ROOT', os.path.join(os.path.dirname(BASE_DIR), 'docs'))
EMAIL = getattr(configuration, 'EMAIL', {}) EMAIL = getattr(configuration, 'EMAIL', {})
EVENTS_PIPELINE = getattr(configuration, 'EVENTS_PIPELINE', (
'extras.events.process_event_rules',
))
EXEMPT_VIEW_PERMISSIONS = getattr(configuration, 'EXEMPT_VIEW_PERMISSIONS', []) EXEMPT_VIEW_PERMISSIONS = getattr(configuration, 'EXEMPT_VIEW_PERMISSIONS', [])
FIELD_CHOICES = getattr(configuration, 'FIELD_CHOICES', {}) FIELD_CHOICES = getattr(configuration, 'FIELD_CHOICES', {})
FILE_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'FILE_UPLOAD_MAX_MEMORY_SIZE', 2621440) FILE_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'FILE_UPLOAD_MAX_MEMORY_SIZE', 2621440)
@ -174,9 +177,6 @@ STORAGE_CONFIG = getattr(configuration, 'STORAGE_CONFIG', {})
TIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a') TIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a')
TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC') TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')
ENABLE_LOCALIZATION = getattr(configuration, 'ENABLE_LOCALIZATION', False) ENABLE_LOCALIZATION = getattr(configuration, 'ENABLE_LOCALIZATION', False)
NETBOX_EVENTS_PIPELINE = getattr(configuration, 'NETBOX_EVENTS_PIPELINE', (
'extras.events.process_event_rules',
))
# Check for hard-coded dynamic config parameters # Check for hard-coded dynamic config parameters