diff --git a/netbox/extras/management/commands/runreport.py b/netbox/extras/management/commands/runreport.py index 6c63eed40..acffdc54d 100644 --- a/netbox/extras/management/commands/runreport.py +++ b/netbox/extras/management/commands/runreport.py @@ -32,6 +32,10 @@ class Command(BaseCommand): report = report_cls() results = report.run() + # Record the results + ReportResult.objects.filter(report=report_name_full).delete() + ReportResult(report=report_name_full, failed=report.failed, data=results).save() + # Report on success/failure status = self.style.ERROR('FAILED') if report.failed else self.style.SUCCESS('SUCCESS') for test_name, attrs in results.items(): diff --git a/netbox/extras/migrations/0008_reports.py b/netbox/extras/migrations/0008_reports.py index 77f4c6501..0cfe48ba5 100644 --- a/netbox/extras/migrations/0008_reports.py +++ b/netbox/extras/migrations/0008_reports.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.4 on 2017-09-21 20:31 +# Generated by Django 1.11.4 on 2017-09-22 15:21 from __future__ import unicode_literals from django.conf import settings @@ -20,8 +20,9 @@ class Migration(migrations.Migration): name='ReportResult', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', models.DateTimeField(auto_created=True)), ('report', models.CharField(max_length=255, unique=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('failed', models.BooleanField()), ('data', django.contrib.postgres.fields.jsonb.JSONField()), ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), ], diff --git a/netbox/extras/models.py b/netbox/extras/models.py index 413f9994d..d1eee12cb 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -398,8 +398,9 @@ class ReportResult(models.Model): This model stores the results from running a user-defined report. """ report = models.CharField(max_length=255, unique=True) - created = models.DateTimeField(auto_created=True) + created = models.DateTimeField(auto_now_add=True) user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='+', blank=True, null=True) + failed = models.BooleanField() data = JSONField() class Meta: diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 1f91930a6..99f42d9b8 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -20,7 +20,18 @@ def is_report(obj): def get_reports(): """ - Compile a list of all reports available across all modules in the reports path. + Compile a list of all reports available across all modules in the reports path. Returns a list of tuples: + + [ + (module_name, ( + (report_name, report_class), + (report_name, report_class) + ), + (module_name, ( + (report_name, report_class), + (report_name, report_class) + ) + ] """ module_list = [] @@ -30,8 +41,8 @@ def get_reports(): report_list = [] # Iterate through all Report classes within the module - for report_name, report_cls in inspect.getmembers(module, is_report): - report_list.append((report_name, report_cls)) + for report_name, report_class in inspect.getmembers(module, is_report): + report_list.append((report_name, report_class)) module_list.append((module_name, report_list)) @@ -92,7 +103,7 @@ class Report(object): """ if level not in LOG_LEVEL_CODES: raise Exception("Unknown logging level: {}".format(level)) - logline = [timezone.now(), level, obj, message] + logline = [timezone.now().isoformat(), level, str(obj), message] self.results[self.active_test]['log'].append(logline) def log_success(self, obj, message=None): diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 4692482ee..d39d8c17c 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals +from collections import OrderedDict from django.contrib.auth.mixins import PermissionRequiredMixin -from django.shortcuts import get_object_or_404, redirect, render +from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views.generic import View @@ -52,9 +53,19 @@ class ReportListView(View): def get(self, request): reports = get_reports() - results = {r.name: r for r in ReportResult.objects.all()} + results = {r.report: r for r in ReportResult.objects.all()} + + foo = [] + for module, report_list in reports: + module_reports = [] + for report_name, report_class in report_list: + module_reports.append({ + 'name': report_name, + 'description': report_class.description, + 'results': results.get('{}.{}'.format(module, report_name), None) + }) + foo.append((module, module_reports)) return render(request, 'extras/report_list.html', { - 'reports': reports, - 'results': results, + 'reports': foo, }) diff --git a/netbox/templates/extras/report_list.html b/netbox/templates/extras/report_list.html index 04602869f..1b987c520 100644 --- a/netbox/templates/extras/report_list.html +++ b/netbox/templates/extras/report_list.html @@ -5,13 +5,52 @@
Name | +Description | +Last Run | +Status | +||
---|---|---|---|---|---|
{{ report.name }} | +{{ report.description|default:"" }} | + {% if report.results %} +{{ report.results.created }} | ++ {% if report.results.failed %} + + {% else %} + + {% endif %} + | + {% else %} +Never | +— | + {% endif %} +
+
+
+
+
+
+
+ {{ method }}
+ |
+