1
0
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:
Arthur
2024-03-14 15:06:26 -07:00
parent 9062d99bfa
commit 80802a4357
4 changed files with 74 additions and 38 deletions

View File

@ -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

View File

@ -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):

View File

@ -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 %}

View File

@ -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 %}