Compare commits

...

20 Commits

Author SHA1 Message Date
Idris Foughali
acef50a693 Merge cf16a29ad3 into 77b389f105 2025-12-09 22:06:34 -06:00
Arthur Hanson
77b389f105 Fixes #20873: fix webhooks with image fields (#20955) 2025-12-09 22:06:11 -06:00
ifoughali
cf16a29ad3 Style: removed comment 2025-12-05 15:24:35 +01:00
ifoughali
544c97d923 XMerge branch 'closes-20817-Fix-datasource-sync-broken-when-cron-is-set' of https://github.com/ifoughal/netbox into closes-20817-Fix-datasource-sync-broken-when-cron-is-set 2025-12-05 15:23:43 +01:00
ifoughali
77ee6baa23 refactor: moved status update logic from clean() to save() method 2025-12-05 15:23:38 +01:00
Idris Foughali
09d1049267 Merge branch 'netbox-community:main' into closes-20817-Fix-datasource-sync-broken-when-cron-is-set 2025-12-05 14:51:56 +01:00
Idris Foughali
93e5f919ba Merge branch 'netbox-community:main' into closes-20817-Fix-datasource-sync-broken-when-cron-is-set 2025-12-01 10:07:15 +01:00
ifoughali
929d024003 Merge branch 'closes-20817-Fix-datasource-sync-broken-when-cron-is-set' of https://github.com/ifoughal/netbox into closes-20817-Fix-datasource-sync-broken-when-cron-is-set 2025-11-26 09:00:22 +01:00
ifoughali
e4b614038e revert: re-added queued status set for datasource object 2025-11-26 09:00:17 +01:00
Idris Foughali
3016b1d90b Merge branch 'netbox-community:main' into closes-20817-Fix-datasource-sync-broken-when-cron-is-set 2025-11-26 08:55:12 +01:00
ifoughali
57b47dc1ea style: use != instead of not in for single SYNCING check 2025-11-26 08:05:20 +01:00
ifoughali
da4c669312 Feat: reworked status update logic 2025-11-20 11:27:39 +01:00
ifoughali
71f707b7ac Feat: removed SCHEDULED choice due to redundency with sync interval 2025-11-20 11:26:43 +01:00
ifoughali
e11508dd6c Fix: removed status update from the enqueue method 2025-11-20 10:50:35 +01:00
ifoughali
5b5b5c8909 Revert "Feat: set status as editable field"
This reverts commit b4160ad59b.
2025-11-19 20:18:59 +01:00
Idris Foughali
a49869af42 Feat: removed QUEUED from ready for sync condition 2025-11-19 19:01:01 +00:00
Idris Foughali
2e0ff04f84 Feat: added 2 states for DataSourceStatusChoices 2025-11-19 18:52:27 +00:00
Idris Foughali
bfeba36514 Feat: added status update during save method of DataSourceForm 2025-11-19 18:51:25 +00:00
Idris Foughali
111aca115b Feat: added clean method to set data-source state to Ready or scheduled 2025-11-19 18:51:01 +00:00
Idris Foughali
b4160ad59b Feat: set status as editable field 2025-11-19 18:49:47 +00:00
5 changed files with 33 additions and 10 deletions

View File

@@ -13,6 +13,7 @@ class DataSourceStatusChoices(ChoiceSet):
SYNCING = 'syncing' SYNCING = 'syncing'
COMPLETED = 'completed' COMPLETED = 'completed'
FAILED = 'failed' FAILED = 'failed'
READY = 'ready'
CHOICES = ( CHOICES = (
(NEW, _('New'), 'blue'), (NEW, _('New'), 'blue'),
@@ -20,6 +21,7 @@ class DataSourceStatusChoices(ChoiceSet):
(SYNCING, _('Syncing'), 'cyan'), (SYNCING, _('Syncing'), 'cyan'),
(COMPLETED, _('Completed'), 'green'), (COMPLETED, _('Completed'), 'green'),
(FAILED, _('Failed'), 'red'), (FAILED, _('Failed'), 'red'),
(READY, _('Ready'), 'green'),
) )

View File

@@ -16,6 +16,7 @@ from utilities.forms import get_field_value
from utilities.forms.fields import CommentField, JSONField from utilities.forms.fields import CommentField, JSONField
from utilities.forms.rendering import FieldSet from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import HTMXSelect from utilities.forms.widgets import HTMXSelect
from core.choices import DataSourceStatusChoices
__all__ = ( __all__ = (
'ConfigRevisionForm', 'ConfigRevisionForm',
@@ -79,14 +80,28 @@ class DataSourceForm(NetBoxModelForm):
if self.instance and self.instance.parameters: if self.instance and self.instance.parameters:
self.fields[field_name].initial = self.instance.parameters.get(name) self.fields[field_name].initial = self.instance.parameters.get(name)
def save(self, *args, **kwargs):
def save(self, *args, **kwargs):
parameters = {} parameters = {}
for name in self.fields: for name in self.fields:
if name.startswith('backend_'): if name.startswith('backend_'):
parameters[name[8:]] = self.cleaned_data[name] parameters[name[8:]] = self.cleaned_data[name]
self.instance.parameters = parameters self.instance.parameters = parameters
# Determine initial status based on new/existing instance
if not self.instance.pk:
# New instance
object_status = DataSourceStatusChoices.NEW
else:
# Existing instance
if not self.cleaned_data.get("sync_interval"):
object_status = DataSourceStatusChoices.READY
else:
object_status = self.instance.status
# # Final override only if the user explicitly provided a status
self.instance.status = object_status
return super().save(*args, **kwargs) return super().save(*args, **kwargs)

View File

@@ -111,10 +111,7 @@ class DataSource(JobsMixin, PrimaryModel):
@property @property
def ready_for_sync(self): def ready_for_sync(self):
return self.enabled and self.status not in ( return self.enabled and self.status != DataSourceStatusChoices.SYNCING
DataSourceStatusChoices.QUEUED,
DataSourceStatusChoices.SYNCING
)
def clean(self): def clean(self):
super().clean() super().clean()

View File

@@ -119,7 +119,9 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non
if snapshots: if snapshots:
params["snapshots"] = snapshots params["snapshots"] = snapshots
if request: if request:
params["request"] = copy_safe_request(request) # Exclude FILES - webhooks don't need uploaded files,
# which can cause pickle errors with Pillow.
params["request"] = copy_safe_request(request, include_files=False)
# Enqueue the task # Enqueue the task
rq_queue.enqueue( rq_queue.enqueue(

View File

@@ -35,27 +35,34 @@ class NetBoxFakeRequest:
# Utility functions # Utility functions
# #
def copy_safe_request(request): def copy_safe_request(request, include_files=True):
""" """
Copy selected attributes from a request object into a new fake request object. This is needed in places where Copy selected attributes from a request object into a new fake request object. This is needed in places where
thread safe pickling of the useful request data is needed. thread safe pickling of the useful request data is needed.
Args:
request: The original request object
include_files: Whether to include request.FILES.
""" """
meta = { meta = {
k: request.META[k] k: request.META[k]
for k in HTTP_REQUEST_META_SAFE_COPY for k in HTTP_REQUEST_META_SAFE_COPY
if k in request.META and isinstance(request.META[k], str) if k in request.META and isinstance(request.META[k], str)
} }
return NetBoxFakeRequest({ data = {
'META': meta, 'META': meta,
'COOKIES': request.COOKIES, 'COOKIES': request.COOKIES,
'POST': request.POST, 'POST': request.POST,
'GET': request.GET, 'GET': request.GET,
'FILES': request.FILES,
'user': request.user, 'user': request.user,
'method': request.method, 'method': request.method,
'path': request.path, 'path': request.path,
'id': getattr(request, 'id', None), # UUID assigned by middleware 'id': getattr(request, 'id', None), # UUID assigned by middleware
}) }
if include_files:
data['FILES'] = request.FILES
return NetBoxFakeRequest(data)
def get_client_ip(request, additional_headers=()): def get_client_ip(request, additional_headers=()):