diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 58de803a5..fcd60462c 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -917,6 +917,10 @@ class ReportModule(JobResultsMixin, WebhooksMixin, PythonModuleMixin, ManagedFil def get_absolute_url(self): return reverse('extras:report_list') + @property + def name(self): + return self.file_path + @cached_property def reports(self): module = self.get_module() diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 969fb3369..cedc1491f 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -3,6 +3,7 @@ import traceback from datetime import timedelta from django.utils import timezone +from django.utils.functional import classproperty from django_rq import job from .choices import JobResultStatusChoices, LogLevelChoices @@ -26,7 +27,7 @@ def run_report(job_result, *args, **kwargs): method for queueing into the background processor. """ module_name, report_name = job_result.name.split('.', 1) - report = get_report(module_name, report_name) + report = get_report(module_name, report_name)() try: job_result.start() @@ -83,7 +84,7 @@ class Report(object): self.active_test = None self.failed = False - self.logger = logging.getLogger(f"netbox.reports.{self.full_name}") + self.logger = logging.getLogger(f"netbox.reports.{self.__module__}.{self.__class__.__name__}") # Compile test methods and initialize results skeleton test_methods = [] @@ -101,13 +102,17 @@ class Report(object): raise Exception("A report must contain at least one test method.") self.test_methods = test_methods - @property + @classproperty def module(self): return self.__module__ - @property + @classproperty def class_name(self): - return self.__class__.__name__ + return self.__name__ + + @classproperty + def full_name(self): + return f'{self.module}.{self.class_name}' @property def name(self): @@ -116,9 +121,9 @@ class Report(object): """ return self.class_name - @property - def full_name(self): - return f'{self.module}.{self.class_name}' + # + # Logging methods + # def _log(self, obj, message, level=LogLevelChoices.LOG_DEFAULT): """ @@ -175,6 +180,10 @@ class Report(object): self.logger.info(f"Failure | {obj}: {message}") self.failed = True + # + # Run methods + # + def run(self, job_result): """ Run the report and save its results. Each test method will be executed in order. diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index eb73f8b51..23a9f9f73 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -267,7 +267,7 @@ class BaseScript: def __init__(self): # Initiate the log - self.logger = logging.getLogger(f"netbox.scripts.{self.module()}.{self.__class__.__name__}") + self.logger = logging.getLogger(f"netbox.scripts.{self.__module__}.{self.__class__.__name__}") self.log = [] # Declare the placeholder for the current request @@ -280,22 +280,26 @@ class BaseScript: def __str__(self): return self.name + @classproperty + def module(self): + return self.__module__ + + @classproperty + def class_name(self): + return self.__name__ + + @classproperty + def full_name(self): + return f'{self.module}.{self.class_name}' + @classproperty def name(self): return getattr(self.Meta, 'name', self.__name__) - @classproperty - def full_name(self): - return '.'.join([self.__module__, self.__name__]) - @classproperty def description(self): return getattr(self.Meta, 'description', '') - @classmethod - def module(cls): - return cls.__module__ - @classmethod def root_module(cls): return cls.__module__.split(".")[0] diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 3d9419263..0a441b6fd 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -852,20 +852,17 @@ class ReportView(ContentTypePermissionRequiredMixin, View): ).first() return render(request, 'extras/report.html', { + 'module': module, 'report': report, 'form': ReportForm(), }) def post(self, request, module, name): - - # Permissions check if not request.user.has_perm('extras.run_report'): return HttpResponseForbidden() - report = get_report(module, name) - if report is None: - raise Http404 - + module = get_object_or_404(ReportModule.objects.restrict(request.user), file_path=f'{module}.py') + report = module.reports[name]() form = ReportForm(request.POST) if form.is_valid(): @@ -891,6 +888,7 @@ class ReportView(ContentTypePermissionRequiredMixin, View): return redirect('extras:report_result', job_result_pk=job_result.pk) return render(request, 'extras/report.html', { + 'module': module, 'report': report, 'form': form, }) diff --git a/netbox/templates/extras/report.html b/netbox/templates/extras/report.html index a3876d319..382c0669f 100644 --- a/netbox/templates/extras/report.html +++ b/netbox/templates/extras/report.html @@ -10,7 +10,7 @@ {% block breadcrumbs %} - + {% endblock breadcrumbs %} {% block subtitle %} diff --git a/netbox/templates/extras/report_list.html b/netbox/templates/extras/report_list.html index e919d93d2..19fc96fc6 100644 --- a/netbox/templates/extras/report_list.html +++ b/netbox/templates/extras/report_list.html @@ -26,7 +26,7 @@
{% for module in report_modules %}
-
+
{% if perms.extras.delete_reportmodule %} {% endif %} - {{ module.name|bettertitle }}
@@ -51,15 +50,15 @@ {% for report_name, report in module.reports.items %} - - - {{ report.name }} - - - {% include 'extras/inc/job_label.html' with result=report.result %} - - {{ report.description|markdown|placeholder }} - {% with last_result=job_results|get_key:report.full_name %} + {% with last_result=job_results|get_key:report.full_name %} + + + {{ report.name }} + + + {% include 'extras/inc/job_label.html' with result=report.result %} + + {{ report.description|markdown|placeholder }} {% if last_result %} {{ last_result.created|annotated_date }} @@ -87,21 +86,21 @@
{% endif %} - {% endwith %} - - {% for method, stats in report.result.data.items %} - - - {{ method }} - - - {{ stats.success }} - {{ stats.info }} - {{ stats.warning }} - {{ stats.failure }} - - {% endfor %} + {% for method, stats in last_result.data.items %} + + + {{ method }} + + + {{ stats.success }} + {{ stats.info }} + {{ stats.warning }} + {{ stats.failure }} + + + {% endfor %} + {% endwith %} {% endfor %} diff --git a/netbox/templates/extras/script.html b/netbox/templates/extras/script.html index a7093ec15..cc12d5a7c 100644 --- a/netbox/templates/extras/script.html +++ b/netbox/templates/extras/script.html @@ -11,7 +11,7 @@ {% block breadcrumbs %} - + {% endblock breadcrumbs %} {% block subtitle %} diff --git a/netbox/templates/extras/script_list.html b/netbox/templates/extras/script_list.html index 9d5771cff..a4d6908f6 100644 --- a/netbox/templates/extras/script_list.html +++ b/netbox/templates/extras/script_list.html @@ -25,7 +25,7 @@
{% for module in script_modules %}
-
+
{% if perms.extras.delete_scriptmodule %} {% endif %} - {{ module.name|bettertitle }}
@@ -49,17 +48,17 @@ {% for script_name, script_class in module.scripts.items %} - - - {{ script_class.name }} - - - {% include 'extras/inc/job_label.html' with result=script_class.result %} - - - {{ script_class.Meta.description|markdown|placeholder }} - - {% with last_result=job_results|get_key:script_class.full_name %} + {% with last_result=job_results|get_key:script_class.full_name %} + + + {{ script_class.name }} + + + {% include 'extras/inc/job_label.html' with result=script_class.result %} + + + {{ script_class.Meta.description|markdown|placeholder }} + {% if last_result %} {{ last_result.created|annotated_date }} @@ -71,8 +70,8 @@ Never {{ ''|placeholder }} {% endif %} - {% endwith %} - + + {% endwith %} {% endfor %}