mirror of
				https://github.com/netbox-community/netbox.git
				synced 2024-05-10 07:54:54 +00:00 
			
		
		
		
	fix tests and cleanup
This commit is contained in:
		@@ -284,21 +284,12 @@ class ScriptSerializer(serializers.Serializer):
 | 
			
		||||
        lookup_field='full_name',
 | 
			
		||||
        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)
 | 
			
		||||
    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):
 | 
			
		||||
        return {
 | 
			
		||||
            k: v.__class__.__name__ for k, v in instance._get_vars().items()
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ from extras.models import (
 | 
			
		||||
from extras.reports import get_report, get_reports
 | 
			
		||||
from extras.scripts import get_script, get_scripts, run_script
 | 
			
		||||
from utilities.api import IsAuthenticatedOrLoginNotRequired, ModelViewSet
 | 
			
		||||
from utilities.utils import copy_safe_request
 | 
			
		||||
from . import serializers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -304,12 +305,12 @@ class ScriptViewSet(ViewSet):
 | 
			
		||||
                script.full_name,
 | 
			
		||||
                script_content_type,
 | 
			
		||||
                request.user,
 | 
			
		||||
                data=form.cleaned_data,
 | 
			
		||||
                data=data,
 | 
			
		||||
                request=copy_safe_request(request),
 | 
			
		||||
                commit=commit
 | 
			
		||||
            )
 | 
			
		||||
            script.result = job_result
 | 
			
		||||
            serializer = serializers.ScriptDetailSerializer(script)
 | 
			
		||||
            serializer = serializers.ScriptDetailSerializer(script, context={'request': request})
 | 
			
		||||
 | 
			
		||||
            return Response(serializer.data)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -573,25 +573,6 @@ class Script(models.Model):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        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
 | 
			
		||||
@@ -606,23 +587,6 @@ class Report(models.Model):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        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
 | 
			
		||||
@@ -676,12 +640,6 @@ class JobResult(models.Model):
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        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
 | 
			
		||||
    def duration(self):
 | 
			
		||||
        if not self.completed:
 | 
			
		||||
@@ -692,7 +650,6 @@ class JobResult(models.Model):
 | 
			
		||||
 | 
			
		||||
        return f"{int(minutes)} minutes, {seconds:.2f} seconds"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def enqueue_job(cls, func, name, obj_type, user, *args, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -273,12 +273,20 @@ class BaseScript:
 | 
			
		||||
        self.source = inspect.getsource(self.__class__)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
    @classproperty
 | 
			
		||||
    def name(self):
 | 
			
		||||
        return getattr(self.Meta, 'name', self.__class__.__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__
 | 
			
		||||
 
 | 
			
		||||
@@ -61,28 +61,6 @@ OBJECTCHANGE_REQUEST_ID = """
 | 
			
		||||
<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):
 | 
			
		||||
    pk = ToggleColumn()
 | 
			
		||||
@@ -155,21 +133,3 @@ class ObjectChangeTable(BaseTable):
 | 
			
		||||
    class Meta(BaseTable.Meta):
 | 
			
		||||
        model = ObjectChange
 | 
			
		||||
        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')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ from extras.api.views import ScriptViewSet
 | 
			
		||||
from extras.models import ConfigContext, Graph, ExportTemplate, Tag
 | 
			
		||||
from extras.scripts import BooleanVar, IntegerVar, Script, StringVar
 | 
			
		||||
from utilities.testing import APITestCase, APIViewTestCases
 | 
			
		||||
from utilities.utils import copy_safe_request
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AppTest(APITestCase):
 | 
			
		||||
@@ -263,13 +264,7 @@ class ScriptTest(APITestCase):
 | 
			
		||||
        response = self.client.post(url, data, format='json', **self.header)
 | 
			
		||||
        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):
 | 
			
		||||
 
 | 
			
		||||
@@ -501,7 +501,6 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View):
 | 
			
		||||
 | 
			
		||||
        if form.is_valid():
 | 
			
		||||
            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')
 | 
			
		||||
            job_result = JobResult.enqueue_job(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.db.models import Count, F
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
@@ -24,6 +25,7 @@ from dcim.tables import (
 | 
			
		||||
    CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable,
 | 
			
		||||
    VirtualChassisTable,
 | 
			
		||||
)
 | 
			
		||||
from extras.choices import JobResultStatusChoices
 | 
			
		||||
from extras.models import ObjectChange, JobResult
 | 
			
		||||
from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet
 | 
			
		||||
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
 | 
			
		||||
@@ -187,6 +189,13 @@ class HomeView(View):
 | 
			
		||||
            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 = {
 | 
			
		||||
 | 
			
		||||
            # Organization
 | 
			
		||||
@@ -241,7 +250,7 @@ class HomeView(View):
 | 
			
		||||
        return render(request, self.template_name, {
 | 
			
		||||
            'search_form': SearchForm(),
 | 
			
		||||
            'stats': stats,
 | 
			
		||||
            'report_results': [],#ReportResult.objects.order_by('-created')[:10],
 | 
			
		||||
            'report_results': report_results,
 | 
			
		||||
            'changelog': changelog[:15],
 | 
			
		||||
            'new_release': new_release,
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
@@ -30,9 +30,6 @@ $(document).ready(function(){
 | 
			
		||||
                url: url + pending_result_id + '/',
 | 
			
		||||
                method: 'GET',
 | 
			
		||||
                dataType: 'json',
 | 
			
		||||
                beforeSend: function(xhr, settings) {
 | 
			
		||||
                    xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
 | 
			
		||||
                },
 | 
			
		||||
                context: this,
 | 
			
		||||
                success: function(data) {
 | 
			
		||||
                    updatePendingStatusLabel(data.status);
 | 
			
		||||
 
 | 
			
		||||
@@ -280,8 +280,8 @@
 | 
			
		||||
                <table class="table table-hover panel-body">
 | 
			
		||||
                    {% for result in report_results %}
 | 
			
		||||
                        <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>
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                </table>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ from dcim.choices import CableLengthUnitChoices
 | 
			
		||||
from extras.utils import is_taggable
 | 
			
		||||
from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def csv_format(data):
 | 
			
		||||
    """
 | 
			
		||||
    Encapsulate any data which contains a comma within double quotes.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user