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