mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
15353 add better script error message
This commit is contained in:
@ -96,6 +96,7 @@ class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile):
|
|||||||
Proxy model for script module files.
|
Proxy model for script module files.
|
||||||
"""
|
"""
|
||||||
objects = ScriptModuleManager()
|
objects = ScriptModuleManager()
|
||||||
|
error = None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
@ -118,6 +119,7 @@ class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile):
|
|||||||
try:
|
try:
|
||||||
module = self.get_module()
|
module = self.get_module()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
self.error = e
|
||||||
logger.debug(f"Failed to load script: {self.python_name} error: {e}")
|
logger.debug(f"Failed to load script: {self.python_name} error: {e}")
|
||||||
module = None
|
module = None
|
||||||
|
|
||||||
|
@ -1040,12 +1040,27 @@ class ScriptListView(ContentTypePermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ScriptView(generic.ObjectView):
|
class BaseScriptView(generic.ObjectView):
|
||||||
queryset = Script.objects.all()
|
queryset = Script.objects.all()
|
||||||
|
|
||||||
|
def _get_script_class(self, script):
|
||||||
|
script_class = script.python_class
|
||||||
|
if script_class:
|
||||||
|
script_class = script_class()
|
||||||
|
|
||||||
|
return script_class
|
||||||
|
|
||||||
|
|
||||||
|
class ScriptView(BaseScriptView):
|
||||||
|
|
||||||
def get(self, request, **kwargs):
|
def get(self, request, **kwargs):
|
||||||
script = self.get_object(**kwargs)
|
script = self.get_object(**kwargs)
|
||||||
script_class = script.python_class()
|
script_class = self._get_script_class(script)
|
||||||
|
if not script_class:
|
||||||
|
return render(request, 'extras/script.html', {
|
||||||
|
'script': script,
|
||||||
|
})
|
||||||
|
|
||||||
form = script_class.as_form(initial=normalize_querydict(request.GET))
|
form = script_class.as_form(initial=normalize_querydict(request.GET))
|
||||||
|
|
||||||
return render(request, 'extras/script.html', {
|
return render(request, 'extras/script.html', {
|
||||||
@ -1057,11 +1072,16 @@ class ScriptView(generic.ObjectView):
|
|||||||
|
|
||||||
def post(self, request, **kwargs):
|
def post(self, request, **kwargs):
|
||||||
script = self.get_object(**kwargs)
|
script = self.get_object(**kwargs)
|
||||||
script_class = script.python_class()
|
|
||||||
|
|
||||||
if not request.user.has_perm('extras.run_script', obj=script):
|
if not request.user.has_perm('extras.run_script', obj=script):
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
script_class = self._get_script_class(script)
|
||||||
|
if not script_class:
|
||||||
|
return render(request, 'extras/script.html', {
|
||||||
|
'script': script,
|
||||||
|
})
|
||||||
|
|
||||||
form = script_class.as_form(request.POST, request.FILES)
|
form = script_class.as_form(request.POST, request.FILES)
|
||||||
|
|
||||||
# Allow execution only if RQ worker process is running
|
# Allow execution only if RQ worker process is running
|
||||||
@ -1091,21 +1111,22 @@ class ScriptView(generic.ObjectView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ScriptSourceView(generic.ObjectView):
|
class ScriptSourceView(BaseScriptView):
|
||||||
queryset = Script.objects.all()
|
queryset = Script.objects.all()
|
||||||
|
|
||||||
def get(self, request, **kwargs):
|
def get(self, request, **kwargs):
|
||||||
script = self.get_object(**kwargs)
|
script = self.get_object(**kwargs)
|
||||||
|
script_class = self._get_script_class(script)
|
||||||
|
|
||||||
return render(request, 'extras/script/source.html', {
|
return render(request, 'extras/script/source.html', {
|
||||||
'script': script,
|
'script': script,
|
||||||
'script_class': script.python_class(),
|
'script_class': script_class,
|
||||||
'job_count': script.jobs.count(),
|
'job_count': script.jobs.count(),
|
||||||
'tab': 'source',
|
'tab': 'source',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ScriptJobsView(generic.ObjectView):
|
class ScriptJobsView(BaseScriptView):
|
||||||
queryset = Script.objects.all()
|
queryset = Script.objects.all()
|
||||||
|
|
||||||
def get(self, request, **kwargs):
|
def get(self, request, **kwargs):
|
||||||
|
@ -14,38 +14,43 @@
|
|||||||
{% trans "You do not have permission to run scripts" %}.
|
{% trans "You do not have permission to run scripts" %}.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form action="" method="post" enctype="multipart/form-data" class="object-edit">
|
{% if form %}
|
||||||
{% csrf_token %}
|
<form action="" method="post" enctype="multipart/form-data" class="object-edit">
|
||||||
<div class="field-group my-4">
|
{% csrf_token %}
|
||||||
{# Render grouped fields according to declared fieldsets #}
|
<div class="field-group my-4">
|
||||||
{% for group, fields in script_class.get_fieldsets %}
|
{# Render grouped fields according to declared fieldsets #}
|
||||||
{% if fields %}
|
{% for group, fields in script_class.get_fieldsets %}
|
||||||
<div class="field-group mb-5">
|
{% if fields %}
|
||||||
<div class="row">
|
<div class="field-group mb-5">
|
||||||
<h5 class="col-9 offset-3">{{ group }}</h5>
|
<div class="row">
|
||||||
|
<h5 class="col-9 offset-3">{{ group }}</h5>
|
||||||
|
</div>
|
||||||
|
{% for name in fields %}
|
||||||
|
{% with field=form|getfield:name %}
|
||||||
|
{% render_field field %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% for name in fields %}
|
{% endif %}
|
||||||
{% with field=form|getfield:name %}
|
{% endfor %}
|
||||||
{% render_field field %}
|
</div>
|
||||||
{% endwith %}
|
<div class="text-end">
|
||||||
{% endfor %}
|
<a href="{% url 'extras:script_list' %}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
|
||||||
</div>
|
{% if not request.user|can_run:script or not script.is_executable %}
|
||||||
|
<button class="btn btn-primary" disabled>
|
||||||
|
<i class="mdi mdi-play"></i> {% trans "Run Script" %}
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" name="_run" class="btn btn-primary">
|
||||||
|
<i class="mdi mdi-play"></i> {% trans "Run Script" %}
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
</div>
|
||||||
</div>
|
</form>
|
||||||
<div class="text-end">
|
{% else %}
|
||||||
<a href="{% url 'extras:script_list' %}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
|
<p>{% trans "Error loading script" %}.</p>
|
||||||
{% if not request.user|can_run:script or not script.is_executable %}
|
<pre class="block">{{ script.module.error }}</pre>
|
||||||
<button class="btn btn-primary" disabled>
|
{% endif %}
|
||||||
<i class="mdi mdi-play"></i> {% trans "Run Script" %}
|
|
||||||
</button>
|
|
||||||
{% else %}
|
|
||||||
<button type="submit" name="_run" class="btn btn-primary">
|
|
||||||
<i class="mdi mdi-play"></i> {% trans "Run Script" %}
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
{% extends 'extras/script/base.html' %}
|
{% extends 'extras/script/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<code class="h6 my-3 d-block">{{ script_class.filename }}</code>
|
|
||||||
<pre class="block">{{ script_class.source }}</pre>
|
{% if script_class %}
|
||||||
|
<code class="h6 my-3 d-block">{{ script_class.filename }}</code>
|
||||||
|
<pre class="block">{{ script_class.source }}</pre>
|
||||||
|
{% else %}
|
||||||
|
<p>{% trans "Error loading script" %}.</p>
|
||||||
|
<pre class="block">{{ script.module.error }}</pre>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Reference in New Issue
Block a user