mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Enable scheduling_enabled parameter for reports
This commit is contained in:
committed by
Jeremy Stretch
parent
197c6a1cbf
commit
b167153186
@ -91,6 +91,10 @@ As you can see, reports are completely customizable. Validation logic can be as
|
||||
|
||||
A human-friendly description of what your report does.
|
||||
|
||||
### `scheduling_enabled`
|
||||
|
||||
By default, a report can be scheduled for execution at a later time. Setting `scheduling_enabled` to False disables this ability: Only immediate execution will be possible. (This also disables the ability to set a recurring execution interval.)
|
||||
|
||||
### `job_timeout`
|
||||
|
||||
Set the maximum allowed runtime for the report. If not set, `RQ_DEFAULT_TIMEOUT` will be used.
|
||||
|
@ -57,6 +57,7 @@ Two new webhook trigger events have been introduced: `job_start` and `job_end`.
|
||||
* [#10729](https://github.com/netbox-community/netbox/issues/10729) - Add date & time custom field type
|
||||
* [#11029](https://github.com/netbox-community/netbox/issues/11029) - Enable change logging for cable terminations
|
||||
* [#11254](https://github.com/netbox-community/netbox/issues/11254) - Introduce the `X-Request-ID` HTTP header to annotate the unique ID of each request for change logging
|
||||
* [#11255](https://github.com/netbox-community/netbox/issues/11255) - Introduce the `scheduling_enabled` settings for reports & scripts
|
||||
* [#11291](https://github.com/netbox-community/netbox/issues/11291) - Optimized GraphQL API request handling
|
||||
* [#11440](https://github.com/netbox-community/netbox/issues/11440) - Add an `enabled` field for device type interfaces
|
||||
* [#11494](https://github.com/netbox-community/netbox/issues/11494) - Enable filtering objects by create/update request IDs
|
||||
|
@ -443,6 +443,16 @@ class ReportInputSerializer(serializers.Serializer):
|
||||
schedule_at = serializers.DateTimeField(required=False, allow_null=True)
|
||||
interval = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
def validate_schedule_at(self, value):
|
||||
if value and not self.context['report'].scheduling_enabled:
|
||||
raise serializers.ValidationError("Scheduling is not enabled for this report.")
|
||||
return value
|
||||
|
||||
def validate_interval(self, value):
|
||||
if value and not self.context['report'].scheduling_enabled:
|
||||
raise serializers.ValidationError("Scheduling is not enabled for this report.")
|
||||
return value
|
||||
|
||||
|
||||
#
|
||||
# Scripts
|
||||
|
@ -244,8 +244,12 @@ class ReportViewSet(ViewSet):
|
||||
raise RQWorkerNotRunningException()
|
||||
|
||||
# Retrieve and run the Report. This will create a new Job.
|
||||
module, report = self._get_report(pk)
|
||||
input_serializer = serializers.ReportInputSerializer(data=request.data)
|
||||
module, report_cls = self._get_report(pk)
|
||||
report = report_cls()
|
||||
input_serializer = serializers.ReportInputSerializer(
|
||||
data=request.data,
|
||||
context={'report': report}
|
||||
)
|
||||
|
||||
if input_serializer.is_valid():
|
||||
report.result = Job.enqueue(
|
||||
|
@ -25,20 +25,25 @@ class ReportForm(BootstrapMixin, forms.Form):
|
||||
help_text=_("Interval at which this report is re-run (in minutes)")
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
scheduled_time = self.cleaned_data['schedule_at']
|
||||
if scheduled_time and scheduled_time < local_now():
|
||||
raise forms.ValidationError(_('Scheduled time must be in the future.'))
|
||||
|
||||
# When interval is used without schedule at, raise an exception
|
||||
if self.cleaned_data['interval'] and not scheduled_time:
|
||||
self.cleaned_data['schedule_at'] = local_now()
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, *args, scheduling_enabled=True, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Annotate the current system time for reference
|
||||
now = local_now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
self.fields['schedule_at'].help_text += f' (current time: <strong>{now}</strong>)'
|
||||
|
||||
# Remove scheduling fields if scheduling is disabled
|
||||
if not scheduling_enabled:
|
||||
self.fields.pop('schedule_at')
|
||||
self.fields.pop('interval')
|
||||
|
||||
def clean(self):
|
||||
scheduled_time = self.cleaned_data.get('schedule_at')
|
||||
if scheduled_time and scheduled_time < local_now():
|
||||
raise forms.ValidationError(_('Scheduled time must be in the future.'))
|
||||
|
||||
# When interval is used without schedule at, schedule for the current time
|
||||
if self.cleaned_data.get('interval') and not scheduled_time:
|
||||
self.cleaned_data['schedule_at'] = local_now()
|
||||
|
||||
return self.cleaned_data
|
||||
|
@ -44,12 +44,12 @@ class ScriptForm(BootstrapMixin, forms.Form):
|
||||
self.fields.pop('_interval')
|
||||
|
||||
def clean(self):
|
||||
scheduled_time = self.cleaned_data['_schedule_at']
|
||||
scheduled_time = self.cleaned_data.get('_schedule_at')
|
||||
if scheduled_time and scheduled_time < local_now():
|
||||
raise forms.ValidationError(_('Scheduled time must be in the future.'))
|
||||
|
||||
# When interval is used without schedule at, schedule for the current time
|
||||
if self.cleaned_data['_interval'] and not scheduled_time:
|
||||
if self.cleaned_data.get('_interval') and not scheduled_time:
|
||||
self.cleaned_data['_schedule_at'] = local_now()
|
||||
|
||||
return self.cleaned_data
|
||||
|
@ -83,6 +83,7 @@ class Report(object):
|
||||
}
|
||||
"""
|
||||
description = None
|
||||
scheduling_enabled = True
|
||||
job_timeout = None
|
||||
|
||||
def __init__(self):
|
||||
|
@ -876,7 +876,7 @@ class ReportView(ContentTypePermissionRequiredMixin, View):
|
||||
return render(request, 'extras/report.html', {
|
||||
'module': module,
|
||||
'report': report,
|
||||
'form': ReportForm(),
|
||||
'form': ReportForm(scheduling_enabled=report.scheduling_enabled),
|
||||
})
|
||||
|
||||
def post(self, request, module, name):
|
||||
@ -885,7 +885,7 @@ class ReportView(ContentTypePermissionRequiredMixin, View):
|
||||
|
||||
module = get_object_or_404(ReportModule.objects.restrict(request.user), file_path__startswith=module)
|
||||
report = module.reports[name]()
|
||||
form = ReportForm(request.POST)
|
||||
form = ReportForm(request.POST, scheduling_enabled=report.scheduling_enabled)
|
||||
|
||||
if form.is_valid():
|
||||
|
||||
|
Reference in New Issue
Block a user