mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-19 22:18:17 -06:00
14132 remove fields from Webhook model, consolidate migrations
This commit is contained in:
parent
1cc8a82921
commit
e6f048b639
@ -40,10 +40,6 @@ class WebhookFilterSet(NetBoxModelFilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label=_('Search'),
|
label=_('Search'),
|
||||||
)
|
)
|
||||||
content_type_id = MultiValueNumberFilter(
|
|
||||||
field_name='content_types__id'
|
|
||||||
)
|
|
||||||
content_types = ContentTypeFilter()
|
|
||||||
http_method = django_filters.MultipleChoiceFilter(
|
http_method = django_filters.MultipleChoiceFilter(
|
||||||
choices=WebhookHttpMethodChoices
|
choices=WebhookHttpMethodChoices
|
||||||
)
|
)
|
||||||
@ -51,8 +47,8 @@ class WebhookFilterSet(NetBoxModelFilterSet):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Webhook
|
model = Webhook
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'payload_url',
|
'id', 'payload_url',
|
||||||
'enabled', 'http_method', 'http_content_type', 'secret', 'ssl_verification', 'ca_file_path',
|
'http_method', 'http_content_type', 'secret', 'ssl_verification', 'ca_file_path',
|
||||||
]
|
]
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
|
@ -152,8 +152,7 @@ class WebhookImportForm(NetBoxModelImportForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Webhook
|
model = Webhook
|
||||||
fields = (
|
fields = (
|
||||||
'name', 'enabled', 'content_types', 'type_create', 'type_update', 'type_delete', 'type_job_start',
|
'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template',
|
||||||
'type_job_end', 'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template',
|
|
||||||
'secret', 'ssl_verification', 'ca_file_path', 'tags'
|
'secret', 'ssl_verification', 'ca_file_path', 'tags'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -226,61 +226,13 @@ class WebhookFilterForm(NetBoxModelFilterSetForm):
|
|||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('q', 'filter_id', 'tag')),
|
(None, ('q', 'filter_id', 'tag')),
|
||||||
(_('Attributes'), ('content_type_id', 'http_method', 'enabled')),
|
(_('Attributes'), ('http_method',)),
|
||||||
(_('Events'), ('type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end')),
|
|
||||||
)
|
|
||||||
content_type_id = ContentTypeMultipleChoiceField(
|
|
||||||
queryset=ContentType.objects.filter(FeatureQuery('webhooks').get_query()),
|
|
||||||
required=False,
|
|
||||||
label=_('Object type')
|
|
||||||
)
|
)
|
||||||
http_method = forms.MultipleChoiceField(
|
http_method = forms.MultipleChoiceField(
|
||||||
choices=WebhookHttpMethodChoices,
|
choices=WebhookHttpMethodChoices,
|
||||||
required=False,
|
required=False,
|
||||||
label=_('HTTP method')
|
label=_('HTTP method')
|
||||||
)
|
)
|
||||||
enabled = forms.NullBooleanField(
|
|
||||||
label=_('Enabled'),
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
)
|
|
||||||
)
|
|
||||||
type_create = forms.NullBooleanField(
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
),
|
|
||||||
label=_('Object creations')
|
|
||||||
)
|
|
||||||
type_update = forms.NullBooleanField(
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
),
|
|
||||||
label=_('Object updates')
|
|
||||||
)
|
|
||||||
type_delete = forms.NullBooleanField(
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
),
|
|
||||||
label=_('Object deletions')
|
|
||||||
)
|
|
||||||
type_job_start = forms.NullBooleanField(
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
),
|
|
||||||
label=_('Job starts')
|
|
||||||
)
|
|
||||||
type_job_end = forms.NullBooleanField(
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
|
||||||
),
|
|
||||||
label=_('Job terminations')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class EventRuleFilterForm(NetBoxModelFilterSetForm):
|
class EventRuleFilterForm(NetBoxModelFilterSetForm):
|
||||||
|
@ -7,6 +7,29 @@ import taggit.managers
|
|||||||
import utilities.json
|
import utilities.json
|
||||||
|
|
||||||
|
|
||||||
|
def move_webhooks(apps, schema_editor):
|
||||||
|
Webhook = apps.get_model("extras", "Webhook")
|
||||||
|
EventRule = apps.get_model("extras", "EventRule")
|
||||||
|
|
||||||
|
for webhook in Webhook.objects.all():
|
||||||
|
event = EventRule()
|
||||||
|
|
||||||
|
event.name = webhook.name
|
||||||
|
event.type_create = webhook.type_create
|
||||||
|
event.type_update = webhook.type_update
|
||||||
|
event.type_delete = webhook.type_delete
|
||||||
|
event.type_job_start = webhook.type_job_start
|
||||||
|
event.type_job_end = webhook.type_job_end
|
||||||
|
event.enabled = webhook.enabled
|
||||||
|
event.conditions = webhook.conditions
|
||||||
|
|
||||||
|
event.event_type = EventRuleTypeChoices.WEBHOOK
|
||||||
|
event.object_type_id = ContentType.objects.get_for_model(webhook).id
|
||||||
|
event.object = webhook
|
||||||
|
event.save()
|
||||||
|
event.content_types.add(*webhook.content_types.all())
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('contenttypes', '0002_remove_content_type_name'),
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
@ -59,4 +82,62 @@ class Migration(migrations.Migration):
|
|||||||
'ordering': ('name',),
|
'ordering': ('name',),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.RunPython(move_webhooks),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='webhook',
|
||||||
|
options={'ordering': ('payload_url',)},
|
||||||
|
),
|
||||||
|
migrations.RemoveConstraint(
|
||||||
|
model_name='webhook',
|
||||||
|
name='extras_webhook_unique_payload_url_types',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='conditions',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='content_types',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='enabled',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='name',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='type_create',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='type_delete',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='type_job_end',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='type_job_start',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='type_update',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='eventrule',
|
||||||
|
name='object_type',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='eventrule_actions',
|
||||||
|
to='contenttypes.contenttype',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='eventrule',
|
||||||
|
unique_together={('object_type', 'object_id')},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -2,7 +2,7 @@ import json
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.validators import ValidationError
|
from django.core.validators import ValidationError
|
||||||
@ -103,7 +103,7 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
|
|||||||
object_type = models.ForeignKey(
|
object_type = models.ForeignKey(
|
||||||
to=ContentType,
|
to=ContentType,
|
||||||
related_name='eventrule_actions',
|
related_name='eventrule_actions',
|
||||||
limit_choices_to=EVENT_TYPE_MODELS,
|
# limit_choices_to=EVENT_TYPE_MODELS,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
object_id = models.PositiveBigIntegerField(
|
object_id = models.PositiveBigIntegerField(
|
||||||
@ -119,6 +119,7 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
|
|||||||
ordering = ('name',)
|
ordering = ('name',)
|
||||||
verbose_name = _('eventrule')
|
verbose_name = _('eventrule')
|
||||||
verbose_name_plural = _('eventrules')
|
verbose_name_plural = _('eventrules')
|
||||||
|
unique_together = ('object_type', 'object_id')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -154,43 +155,8 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
|||||||
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
|
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
|
||||||
Each Webhook can be limited to firing only on certain actions or certain object types.
|
Each Webhook can be limited to firing only on certain actions or certain object types.
|
||||||
"""
|
"""
|
||||||
content_types = models.ManyToManyField(
|
events = GenericRelation(EventRule)
|
||||||
to=ContentType,
|
|
||||||
related_name='webhooks',
|
|
||||||
verbose_name=_('object types'),
|
|
||||||
limit_choices_to=FeatureQuery('webhooks'),
|
|
||||||
help_text=_("The object(s) to which this Webhook applies.")
|
|
||||||
)
|
|
||||||
name = models.CharField(
|
|
||||||
verbose_name=_('name'),
|
|
||||||
max_length=150,
|
|
||||||
unique=True
|
|
||||||
)
|
|
||||||
type_create = models.BooleanField(
|
|
||||||
verbose_name=_('on create'),
|
|
||||||
default=False,
|
|
||||||
help_text=_("Triggers when a matching object is created.")
|
|
||||||
)
|
|
||||||
type_update = models.BooleanField(
|
|
||||||
verbose_name=_('on update'),
|
|
||||||
default=False,
|
|
||||||
help_text=_("Triggers when a matching object is updated.")
|
|
||||||
)
|
|
||||||
type_delete = models.BooleanField(
|
|
||||||
verbose_name=_('on delete'),
|
|
||||||
default=False,
|
|
||||||
help_text=_("Triggers when a matching object is deleted.")
|
|
||||||
)
|
|
||||||
type_job_start = models.BooleanField(
|
|
||||||
verbose_name=_('on job start'),
|
|
||||||
default=False,
|
|
||||||
help_text=_("Triggers when a job for a matching object is started.")
|
|
||||||
)
|
|
||||||
type_job_end = models.BooleanField(
|
|
||||||
verbose_name=_('on job end'),
|
|
||||||
default=False,
|
|
||||||
help_text=_("Triggers when a job for a matching object terminates.")
|
|
||||||
)
|
|
||||||
payload_url = models.CharField(
|
payload_url = models.CharField(
|
||||||
max_length=500,
|
max_length=500,
|
||||||
verbose_name=_('URL'),
|
verbose_name=_('URL'),
|
||||||
@ -199,10 +165,6 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
|||||||
"processing is supported with the same context as the request body."
|
"processing is supported with the same context as the request body."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
enabled = models.BooleanField(
|
|
||||||
verbose_name=_('enabled'),
|
|
||||||
default=True
|
|
||||||
)
|
|
||||||
http_method = models.CharField(
|
http_method = models.CharField(
|
||||||
max_length=30,
|
max_length=30,
|
||||||
choices=WebhookHttpMethodChoices,
|
choices=WebhookHttpMethodChoices,
|
||||||
@ -245,12 +207,6 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
|||||||
"digest of the payload body using the secret as the key. The secret is not transmitted in the request."
|
"digest of the payload body using the secret as the key. The secret is not transmitted in the request."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
conditions = models.JSONField(
|
|
||||||
verbose_name=_('conditions'),
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
help_text=_("A set of conditions which determine whether the webhook will be generated.")
|
|
||||||
)
|
|
||||||
ssl_verification = models.BooleanField(
|
ssl_verification = models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
verbose_name=_('SSL verification'),
|
verbose_name=_('SSL verification'),
|
||||||
@ -267,18 +223,12 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('name',)
|
ordering = ('payload_url',)
|
||||||
constraints = (
|
|
||||||
models.UniqueConstraint(
|
|
||||||
fields=('payload_url', 'type_create', 'type_update', 'type_delete'),
|
|
||||||
name='%(app_label)s_%(class)s_unique_payload_url_types'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
verbose_name = _('webhook')
|
verbose_name = _('webhook')
|
||||||
verbose_name_plural = _('webhooks')
|
verbose_name_plural = _('webhooks')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.payload_url
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('extras:webhook', args=[self.pk])
|
return reverse('extras:webhook', args=[self.pk])
|
||||||
@ -290,20 +240,6 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
|
|||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
# At least one action type must be selected
|
|
||||||
if not any([
|
|
||||||
self.type_create, self.type_update, self.type_delete, self.type_job_start, self.type_job_end
|
|
||||||
]):
|
|
||||||
raise ValidationError(
|
|
||||||
_("At least one event type must be selected: create, update, delete, job_start, and/or job_end.")
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.conditions:
|
|
||||||
try:
|
|
||||||
ConditionSet(self.conditions)
|
|
||||||
except ValueError as e:
|
|
||||||
raise ValidationError({'conditions': e})
|
|
||||||
|
|
||||||
# CA file path requires SSL verification enabled
|
# CA file path requires SSL verification enabled
|
||||||
if not self.ssl_verification and self.ca_file_path:
|
if not self.ssl_verification and self.ca_file_path:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
|
@ -320,6 +320,9 @@ class EventRuleTable(NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
event_type = tables.Column(
|
||||||
|
verbose_name=_('Event Type'),
|
||||||
|
)
|
||||||
content_types = columns.ContentTypesColumn(
|
content_types = columns.ContentTypesColumn(
|
||||||
verbose_name=_('Content Types'),
|
verbose_name=_('Content Types'),
|
||||||
)
|
)
|
||||||
@ -348,11 +351,11 @@ class EventRuleTable(NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = EventRule
|
model = EventRule
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete',
|
'pk', 'id', 'name', 'event_type', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete',
|
||||||
'type_job_start', 'type_job_end', 'tags', 'created', 'last_updated',
|
'type_job_start', 'type_job_end', 'tags', 'created', 'last_updated',
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
'pk', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'type_job_start',
|
'pk', 'name', 'event_type', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'type_job_start',
|
||||||
'type_job_end',
|
'type_job_end',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user