mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Cleaned up the API quite a bit
This commit is contained in:
@ -95,74 +95,69 @@ class ReportViewSet(ViewSet):
|
|||||||
exclude_from_schema = True
|
exclude_from_schema = True
|
||||||
lookup_value_regex = '[^/]+' # Allow dots
|
lookup_value_regex = '[^/]+' # Allow dots
|
||||||
|
|
||||||
|
def _retrieve_report(self, pk):
|
||||||
|
|
||||||
|
# Read the PK as "<module>.<report>"
|
||||||
|
if '.' not in pk:
|
||||||
|
raise Http404
|
||||||
|
module_name, report_name = pk.split('.', 1)
|
||||||
|
|
||||||
|
# Raise a 404 on an invalid Report module/name
|
||||||
|
report = get_report(module_name, report_name)
|
||||||
|
if report is None:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
return report
|
||||||
|
|
||||||
def list(self, request):
|
def list(self, request):
|
||||||
|
"""
|
||||||
# Compile all reports
|
Compile all reports and their related results (if any). Result data is deferred in the list view.
|
||||||
|
"""
|
||||||
report_list = []
|
report_list = []
|
||||||
for module_name, reports in get_reports():
|
|
||||||
for report_name, report_cls in reports:
|
|
||||||
data = {
|
|
||||||
'module': module_name,
|
|
||||||
'name': report_name,
|
|
||||||
'description': report_cls.description,
|
|
||||||
'test_methods': report_cls().test_methods,
|
|
||||||
'result': None,
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
result = ReportResult.objects.defer('data').get(report='{}.{}'.format(module_name, report_name))
|
|
||||||
data['result'] = result
|
|
||||||
except ReportResult.DoesNotExist:
|
|
||||||
pass
|
|
||||||
report_list.append(data)
|
|
||||||
|
|
||||||
serializer = serializers.ReportSerializer(report_list, many=True, context={'request': request})
|
# Iterate through all available Reports.
|
||||||
|
for module_name, reports in get_reports():
|
||||||
|
for report in reports:
|
||||||
|
|
||||||
|
# Attach the relevant ReportResult (if any) to each Report.
|
||||||
|
report.result = ReportResult.objects.filter(report=report.full_name).defer('data').first()
|
||||||
|
report_list.append(report)
|
||||||
|
|
||||||
|
serializer = serializers.ReportSerializer(report_list, many=True)
|
||||||
|
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
def retrieve(self, request, pk):
|
def retrieve(self, request, pk):
|
||||||
|
"""
|
||||||
|
Retrieve a single Report identified as "<module>.<report>".
|
||||||
|
"""
|
||||||
|
|
||||||
# Retrieve report by <module>.<report>
|
# Retrieve the Report and ReportResult, if any.
|
||||||
if '.' not in pk:
|
report = self._retrieve_report(pk)
|
||||||
raise Http404
|
report.result = ReportResult.objects.filter(report=report.full_name).first()
|
||||||
module_name, report_name = pk.split('.', 1)
|
|
||||||
report_cls = get_report(module_name, report_name)
|
|
||||||
data = {
|
|
||||||
'module': module_name,
|
|
||||||
'name': report_name,
|
|
||||||
'description': report_cls.description,
|
|
||||||
'test_methods': report_cls().test_methods,
|
|
||||||
'result': None,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Attach report result
|
serializer = serializers.ReportDetailSerializer(report)
|
||||||
try:
|
|
||||||
result = ReportResult.objects.get(report='{}.{}'.format(module_name, report_name))
|
|
||||||
data['result'] = result
|
|
||||||
except ReportResult.DoesNotExist:
|
|
||||||
pass
|
|
||||||
|
|
||||||
serializer = serializers.ReportDetailSerializer(data)
|
|
||||||
|
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
@detail_route()
|
@detail_route()
|
||||||
def run(self, request, pk):
|
def run(self, request, pk):
|
||||||
|
"""
|
||||||
|
Run a Report and create a new ReportResult, overwriting any previous result for the Report.
|
||||||
|
"""
|
||||||
|
|
||||||
# Retrieve report by <module>.<report>
|
# Retrieve and run the Report.
|
||||||
if '.' not in pk:
|
report = self._retrieve_report(pk)
|
||||||
raise Http404
|
|
||||||
module_name, report_name = pk.split('.', 1)
|
|
||||||
report_cls = get_report(module_name, report_name)
|
|
||||||
|
|
||||||
# Run the report
|
|
||||||
report = report_cls()
|
|
||||||
result = report.run()
|
result = report.run()
|
||||||
|
|
||||||
# Save the ReportResult
|
# Delete the old ReportResult (if any) and save the new one.
|
||||||
ReportResult.objects.filter(report=pk).delete()
|
ReportResult.objects.filter(report=pk).delete()
|
||||||
ReportResult(report=pk, failed=report.failed, data=result).save()
|
report.result = ReportResult(report=pk, failed=report.failed, data=result)
|
||||||
|
report.result.save()
|
||||||
|
|
||||||
return Response('Report completed.')
|
serializer = serializers.ReportDetailSerializer(report)
|
||||||
|
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
class RecentActivityViewSet(ReadOnlyModelViewSet):
|
class RecentActivityViewSet(ReadOnlyModelViewSet):
|
||||||
|
@ -6,7 +6,7 @@ import pkgutil
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_LEVEL_CODES, LOG_SUCCESS, LOG_WARNING
|
from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_LEVEL_CODES, LOG_SUCCESS, LOG_WARNING
|
||||||
import reports as user_reports
|
import reports as custom_reports
|
||||||
|
|
||||||
|
|
||||||
def is_report(obj):
|
def is_report(obj):
|
||||||
@ -23,7 +23,8 @@ def get_report(module_name, report_name):
|
|||||||
Return a specific report from within a module.
|
Return a specific report from within a module.
|
||||||
"""
|
"""
|
||||||
module = importlib.import_module('reports.{}'.format(module_name))
|
module = importlib.import_module('reports.{}'.format(module_name))
|
||||||
return getattr(module, report_name)
|
report = getattr(module, report_name, None)
|
||||||
|
return report()
|
||||||
|
|
||||||
|
|
||||||
def get_reports():
|
def get_reports():
|
||||||
@ -31,27 +32,18 @@ def get_reports():
|
|||||||
Compile a list of all reports available across all modules in the reports path. Returns a list of tuples:
|
Compile a list of all reports available across all modules in the reports path. Returns a list of tuples:
|
||||||
|
|
||||||
[
|
[
|
||||||
(module_name, (
|
(module_name, (report_class, report_class, report_class, ...)),
|
||||||
(report_name, report_class),
|
(module_name, (report_class, report_class, report_class, ...)),
|
||||||
(report_name, report_class)
|
...
|
||||||
),
|
|
||||||
(module_name, (
|
|
||||||
(report_name, report_class),
|
|
||||||
(report_name, report_class)
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
module_list = []
|
module_list = []
|
||||||
|
|
||||||
# Iterate through all modules within the reports path
|
# Iterate through all modules within the reports path. These are the user-defined files in which reports are
|
||||||
for importer, module_name, is_pkg in pkgutil.walk_packages(user_reports.__path__):
|
# defined.
|
||||||
|
for importer, module_name, is_pkg in pkgutil.walk_packages(custom_reports.__path__):
|
||||||
module = importlib.import_module('reports.{}'.format(module_name))
|
module = importlib.import_module('reports.{}'.format(module_name))
|
||||||
report_list = []
|
report_list = [cls() for _, cls in inspect.getmembers(module, is_report)]
|
||||||
|
|
||||||
# Iterate through all Report classes within the module
|
|
||||||
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))
|
module_list.append((module_name, report_list))
|
||||||
|
|
||||||
return module_list
|
return module_list
|
||||||
@ -105,6 +97,18 @@ class Report(object):
|
|||||||
raise Exception("A report must contain at least one test method.")
|
raise Exception("A report must contain at least one test method.")
|
||||||
self.test_methods = test_methods
|
self.test_methods = test_methods
|
||||||
|
|
||||||
|
@property
|
||||||
|
def module(self):
|
||||||
|
return self.__module__.rsplit('.', 1)[1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_name(self):
|
||||||
|
return '.'.join([self.module, self.name])
|
||||||
|
|
||||||
def _log(self, obj, message, level=LOG_DEFAULT):
|
def _log(self, obj, message, level=LOG_DEFAULT):
|
||||||
"""
|
"""
|
||||||
Log a message from a test method. Do not call this method directly; use one of the log_* wrappers below.
|
Log a message from a test method. Do not call this method directly; use one of the log_* wrappers below.
|
||||||
|
@ -58,11 +58,11 @@ class ReportListView(View):
|
|||||||
foo = []
|
foo = []
|
||||||
for module, report_list in reports:
|
for module, report_list in reports:
|
||||||
module_reports = []
|
module_reports = []
|
||||||
for report_name, report_class in report_list:
|
for report in report_list:
|
||||||
module_reports.append({
|
module_reports.append({
|
||||||
'name': report_name,
|
'name': report.name,
|
||||||
'description': report_class.description,
|
'description': report.description,
|
||||||
'results': results.get('{}.{}'.format(module, report_name), None)
|
'results': results.get(report.full_name, None)
|
||||||
})
|
})
|
||||||
foo.append((module, module_reports))
|
foo.append((module, module_reports))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user