John Anderson 5 лет назад
Родитель
Сommit
f48a079ae6

+ 3 - 12
netbox/extras/api/serializers.py

@@ -284,21 +284,12 @@ class ScriptSerializer(serializers.Serializer):
         lookup_field='full_name',
         lookup_field='full_name',
         lookup_url_kwarg='pk'
         lookup_url_kwarg='pk'
     )
     )
-    id = serializers.SerializerMethodField(read_only=True)
-    name = serializers.SerializerMethodField(read_only=True)
-    description = serializers.SerializerMethodField(read_only=True)
+    id = serializers.CharField(read_only=True, source="full_name")
+    name = serializers.CharField(read_only=True)
+    description = serializers.CharField(read_only=True)
     vars = serializers.SerializerMethodField(read_only=True)
     vars = serializers.SerializerMethodField(read_only=True)
     result = NestedJobResultSerializer()
     result = NestedJobResultSerializer()
 
 
-    def get_id(self, instance):
-        return '{}.{}'.format(instance.__module__, instance.__name__)
-
-    def get_name(self, instance):
-        return getattr(instance.Meta, 'name', instance.__name__)
-
-    def get_description(self, instance):
-        return getattr(instance.Meta, 'description', '')
-
     def get_vars(self, instance):
     def get_vars(self, instance):
         return {
         return {
             k: v.__class__.__name__ for k, v in instance._get_vars().items()
             k: v.__class__.__name__ for k, v in instance._get_vars().items()

+ 3 - 2
netbox/extras/api/views.py

@@ -17,6 +17,7 @@ from extras.models import (
 from extras.reports import get_report, get_reports
 from extras.reports import get_report, get_reports
 from extras.scripts import get_script, get_scripts, run_script
 from extras.scripts import get_script, get_scripts, run_script
 from utilities.api import IsAuthenticatedOrLoginNotRequired, ModelViewSet
 from utilities.api import IsAuthenticatedOrLoginNotRequired, ModelViewSet
+from utilities.utils import copy_safe_request
 from . import serializers
 from . import serializers
 
 
 
 
@@ -304,12 +305,12 @@ class ScriptViewSet(ViewSet):
                 script.full_name,
                 script.full_name,
                 script_content_type,
                 script_content_type,
                 request.user,
                 request.user,
-                data=form.cleaned_data,
+                data=data,
                 request=copy_safe_request(request),
                 request=copy_safe_request(request),
                 commit=commit
                 commit=commit
             )
             )
             script.result = job_result
             script.result = job_result
-            serializer = serializers.ScriptDetailSerializer(script)
+            serializer = serializers.ScriptDetailSerializer(script, context={'request': request})
 
 
             return Response(serializer.data)
             return Response(serializer.data)
 
 

+ 0 - 43
netbox/extras/models/models.py

@@ -573,25 +573,6 @@ class Script(models.Model):
     class Meta:
     class Meta:
         managed = False
         managed = False
 
 
-    @classmethod
-    def get_absolute_url_from_job_result(cls, job_result):
-        """
-        Given a JobResult that links to this content type, return URL to an instance which corresponds to that job
-        result, i.e. for historical records
-        """
-        if job_result.obj_type.model_class() != cls:
-            return None
-
-        module, script_name = job_result.name.split('.')
-        return reverse(
-            'extras:script_history_detail',
-            kwargs={
-                'module': module,
-                'script_name': script_name,
-                'job_id': job_result.job_id
-            }
-        )
-
 
 
 #
 #
 # Reports
 # Reports
@@ -606,23 +587,6 @@ class Report(models.Model):
     class Meta:
     class Meta:
         managed = False
         managed = False
 
 
-    @classmethod
-    def get_absolute_url_from_job_result(cls, job_result):
-        """
-        Given a JobResult that links to this content type, return URL to an instance which corresponds to that job
-        result, i.e. for historical records
-        """
-        if job_result.obj_type.model_class() != cls:
-            return None
-
-        return reverse(
-            'extras:report_history_detail',
-            kwargs={
-                'name': job_result.name,
-                'job_id': job_result.job_id
-            }
-        )
-
 
 
 #
 #
 # Job results
 # Job results
@@ -676,12 +640,6 @@ class JobResult(models.Model):
     def __str__(self):
     def __str__(self):
         return str(self.job_id)
         return str(self.job_id)
 
 
-    def get_absolute_url(self):
-        """
-        Job results are accessed only under the context of the content type they link to
-        """
-        return self.obj_type.model_class().get_absolute_url_from_job_result(self)
-
     @property
     @property
     def duration(self):
     def duration(self):
         if not self.completed:
         if not self.completed:
@@ -692,7 +650,6 @@ class JobResult(models.Model):
 
 
         return f"{int(minutes)} minutes, {seconds:.2f} seconds"
         return f"{int(minutes)} minutes, {seconds:.2f} seconds"
 
 
-
     @classmethod
     @classmethod
     def enqueue_job(cls, func, name, obj_type, user, *args, **kwargs):
     def enqueue_job(cls, func, name, obj_type, user, *args, **kwargs):
         """
         """

+ 8 - 0
netbox/extras/scripts.py

@@ -273,12 +273,20 @@ class BaseScript:
         self.source = inspect.getsource(self.__class__)
         self.source = inspect.getsource(self.__class__)
 
 
     def __str__(self):
     def __str__(self):
+        return self.name
+
+    @classproperty
+    def name(self):
         return getattr(self.Meta, 'name', self.__class__.__name__)
         return getattr(self.Meta, 'name', self.__class__.__name__)
 
 
     @classproperty
     @classproperty
     def full_name(self):
     def full_name(self):
         return '.'.join([self.__module__, self.__name__])
         return '.'.join([self.__module__, self.__name__])
 
 
+    @classproperty
+    def description(self):
+        return getattr(self.Meta, 'description', '')
+
     @classmethod
     @classmethod
     def module(cls):
     def module(cls):
         return cls.__module__
         return cls.__module__

+ 0 - 40
netbox/extras/tables.py

@@ -61,28 +61,6 @@ OBJECTCHANGE_REQUEST_ID = """
 <a href="{% url 'extras:objectchange_list' %}?request_id={{ value }}">{{ value }}</a>
 <a href="{% url 'extras:objectchange_list' %}?request_id={{ value }}">{{ value }}</a>
 """
 """
 
 
-JOB_RESULT_CREATED = """
-<a href="{{ record.get_absolute_url }}">{{ value|date:"SHORT_DATETIME_FORMAT" }}</a>
-"""
-
-JOB_RESULT_COMPLETED = """
-<span>{% if value %}{{ value|date:"SHORT_DATETIME_FORMAT" }}{% else %}—{% endif %}</span>
-"""
-
-JOB_RESULT_STATUS = """
-{% if record.status == 'failed' %}
-    <label class="label label-danger">Failed</label>
-{% elif record.status == 'pending' %}
-    <label class="label label-default">Pending</label>
-{% elif record.status == 'running' %}
-    <label class="label label-warning">Running</label>
-{% elif record.status == 'completed' %}
-    <label class="label label-success">Passed</label>
-{% else %}
-    <label class="label label-default">N/A</label>
-{% endif %}
-"""
-
 
 
 class TagTable(BaseTable):
 class TagTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
@@ -155,21 +133,3 @@ class ObjectChangeTable(BaseTable):
     class Meta(BaseTable.Meta):
     class Meta(BaseTable.Meta):
         model = ObjectChange
         model = ObjectChange
         fields = ('time', 'user_name', 'action', 'changed_object_type', 'object_repr', 'request_id')
         fields = ('time', 'user_name', 'action', 'changed_object_type', 'object_repr', 'request_id')
-
-
-class JobResultHistoryTable(BaseTable):
-    created = tables.TemplateColumn(
-        template_code=JOB_RESULT_CREATED,
-        verbose_name='Run'
-    )
-    completed = tables.TemplateColumn(
-        template_code=JOB_RESULT_COMPLETED
-    )
-    status = tables.TemplateColumn(
-        template_code=JOB_RESULT_STATUS
-    )
-
-    class Meta(BaseTable.Meta):
-        model = JobResult
-        fields = ('created', 'completed', 'status')
-

+ 2 - 7
netbox/extras/tests/test_api.py

@@ -10,6 +10,7 @@ from extras.api.views import ScriptViewSet
 from extras.models import ConfigContext, Graph, ExportTemplate, Tag
 from extras.models import ConfigContext, Graph, ExportTemplate, Tag
 from extras.scripts import BooleanVar, IntegerVar, Script, StringVar
 from extras.scripts import BooleanVar, IntegerVar, Script, StringVar
 from utilities.testing import APITestCase, APIViewTestCases
 from utilities.testing import APITestCase, APIViewTestCases
+from utilities.utils import copy_safe_request
 
 
 
 
 class AppTest(APITestCase):
 class AppTest(APITestCase):
@@ -263,13 +264,7 @@ class ScriptTest(APITestCase):
         response = self.client.post(url, data, format='json', **self.header)
         response = self.client.post(url, data, format='json', **self.header)
         self.assertHttpStatus(response, status.HTTP_200_OK)
         self.assertHttpStatus(response, status.HTTP_200_OK)
 
 
-        self.assertEqual(response.data['log'][0]['status'], 'info')
-        self.assertEqual(response.data['log'][0]['message'], script_data['var1'])
-        self.assertEqual(response.data['log'][1]['status'], 'success')
-        self.assertEqual(response.data['log'][1]['message'], script_data['var2'])
-        self.assertEqual(response.data['log'][2]['status'], 'failure')
-        self.assertEqual(response.data['log'][2]['message'], script_data['var3'])
-        self.assertEqual(response.data['output'], 'Script complete')
+        self.assertEqual(response.data['result']['status']['value'], 'pending')
 
 
 
 
 class CreatedUpdatedFilterTest(APITestCase):
 class CreatedUpdatedFilterTest(APITestCase):

+ 0 - 1
netbox/extras/views.py

@@ -501,7 +501,6 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View):
 
 
         if form.is_valid():
         if form.is_valid():
             commit = form.cleaned_data.pop('_commit')
             commit = form.cleaned_data.pop('_commit')
-            #output, execution_time = run_script(script, form.cleaned_data, request, commit)
 
 
             script_content_type = ContentType.objects.get(app_label='extras', model='script')
             script_content_type = ContentType.objects.get(app_label='extras', model='script')
             job_result = JobResult.enqueue_job(
             job_result = JobResult.enqueue_job(

+ 10 - 1
netbox/netbox/views.py

@@ -1,6 +1,7 @@
 from collections import OrderedDict
 from collections import OrderedDict
 
 
 from django.conf import settings
 from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
 from django.db.models import Count, F
 from django.db.models import Count, F
 from django.shortcuts import render
 from django.shortcuts import render
 from django.views.generic import View
 from django.views.generic import View
@@ -24,6 +25,7 @@ from dcim.tables import (
     CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable,
     CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable,
     VirtualChassisTable,
     VirtualChassisTable,
 )
 )
+from extras.choices import JobResultStatusChoices
 from extras.models import ObjectChange, JobResult
 from extras.models import ObjectChange, JobResult
 from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet
 from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet
 from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
 from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
@@ -187,6 +189,13 @@ class HomeView(View):
             pk__lt=F('_connected_interface')
             pk__lt=F('_connected_interface')
         )
         )
 
 
+        # Report Results
+        report_content_type = ContentType.objects.get(app_label='extras', model='report')
+        report_results = JobResult.objects.filter(
+            obj_type=report_content_type,
+            status__in=JobResultStatusChoices.TERMINAL_STATE_CHOICES
+        ).defer('data')[:10]
+
         stats = {
         stats = {
 
 
             # Organization
             # Organization
@@ -241,7 +250,7 @@ class HomeView(View):
         return render(request, self.template_name, {
         return render(request, self.template_name, {
             'search_form': SearchForm(),
             'search_form': SearchForm(),
             'stats': stats,
             'stats': stats,
-            'report_results': [],#ReportResult.objects.order_by('-created')[:10],
+            'report_results': report_results,
             'changelog': changelog[:15],
             'changelog': changelog[:15],
             'new_release': new_release,
             'new_release': new_release,
         })
         })

+ 0 - 3
netbox/project-static/js/job_result.js

@@ -30,9 +30,6 @@ $(document).ready(function(){
                 url: url + pending_result_id + '/',
                 url: url + pending_result_id + '/',
                 method: 'GET',
                 method: 'GET',
                 dataType: 'json',
                 dataType: 'json',
-                beforeSend: function(xhr, settings) {
-                    xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
-                },
                 context: this,
                 context: this,
                 success: function(data) {
                 success: function(data) {
                     updatePendingStatusLabel(data.status);
                     updatePendingStatusLabel(data.status);

+ 2 - 2
netbox/templates/home.html

@@ -280,8 +280,8 @@
                 <table class="table table-hover panel-body">
                 <table class="table table-hover panel-body">
                     {% for result in report_results %}
                     {% for result in report_results %}
                         <tr>
                         <tr>
-                            <td><a href="{% url 'extras:report' name=result.report %}">{{ result.report }}</a></td>
-                            <td class="text-right"><span title="{{ result.created }}">{% include 'extras/inc/report_label.html' %}</span></td>
+                            <td><a href="{% url 'extras:report' name=result.name %}">{{ result.name }}</a></td>
+                            <td class="text-right"><span title="{{ result.created }}">{% include 'extras/inc/job_label.html' %}</span></td>
                         </tr>
                         </tr>
                     {% endfor %}
                     {% endfor %}
                 </table>
                 </table>

+ 1 - 0
netbox/utilities/utils.py

@@ -12,6 +12,7 @@ from dcim.choices import CableLengthUnitChoices
 from extras.utils import is_taggable
 from extras.utils import is_taggable
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 
 
+
 def csv_format(data):
 def csv_format(data):
     """
     """
     Encapsulate any data which contains a comma within double quotes.
     Encapsulate any data which contains a comma within double quotes.