mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-17 21:18:16 -06:00
14438 script job mapping
This commit is contained in:
parent
fc890e36af
commit
6930e441ae
@ -8,14 +8,19 @@ def update_scripts(apps, schema_editor):
|
||||
from extras.models import ScriptModule
|
||||
ScriptModuleNew = apps.get_model('extras', 'ScriptModule')
|
||||
Script = apps.get_model('extras', 'Script')
|
||||
ContentType = apps.get_model('contenttypes', 'ContentType')
|
||||
ct = ContentType.objects.get(app_label='extras', model='script')
|
||||
|
||||
for module in ScriptModule.objects.all():
|
||||
for script in module.get_module_scripts.keys():
|
||||
Script.objects.create(
|
||||
obj = Script.objects.create(
|
||||
name=script,
|
||||
module=ScriptModuleNew.objects.get(file_root=module.file_root, file_path=module.file_path),
|
||||
)
|
||||
|
||||
# update all jobs associated with this module/name to point to the new script obj
|
||||
module.jobs.filter(name=name).update(object_type=ct, object_id=obj.id)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@ -35,6 +40,10 @@ class Migration(migrations.Migration):
|
||||
'ordering': ('name', 'pk'),
|
||||
},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='script',
|
||||
constraint=models.UniqueConstraint(fields=('name', 'module'), name='extras_script_unique_name_module'),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=update_scripts,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
|
@ -21,7 +21,7 @@ __all__ = (
|
||||
logger = logging.getLogger('netbox.data_backends')
|
||||
|
||||
|
||||
class Script(EventRulesMixin, models.Model):
|
||||
class Script(EventRulesMixin, JobsMixin, models.Model):
|
||||
name = models.CharField(
|
||||
verbose_name=_('name'),
|
||||
max_length=79,
|
||||
@ -37,11 +37,24 @@ class Script(EventRulesMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', 'pk')
|
||||
constraints = (
|
||||
models.UniqueConstraint(
|
||||
fields=('name', 'module'),
|
||||
name='%(app_label)s_%(class)s_unique_name_module'
|
||||
),
|
||||
)
|
||||
verbose_name = _('script')
|
||||
verbose_name_plural = _('scripts')
|
||||
|
||||
@cached_property
|
||||
def python_class(self):
|
||||
return self.module.get_module_scripts.get(self.name)
|
||||
|
||||
def get_jobs(self):
|
||||
return self.module.jobs.filter(
|
||||
name=self.name
|
||||
)
|
||||
|
||||
|
||||
class ScriptModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
||||
|
||||
|
@ -130,9 +130,9 @@ urlpatterns = [
|
||||
path('scripts/add/', views.ScriptModuleCreateView.as_view(), name='scriptmodule_add'),
|
||||
path('scripts/results/<int:job_pk>/', views.ScriptResultView.as_view(), name='script_result'),
|
||||
path('scripts/<int:pk>/', include(get_model_urls('extras', 'scriptmodule'))),
|
||||
path('scripts/<str:module>/<str:name>/', views.ScriptView.as_view(), name='script'),
|
||||
path('scripts/<str:module>/<str:name>/source/', views.ScriptSourceView.as_view(), name='script_source'),
|
||||
path('scripts/<str:module>/<str:name>/jobs/', views.ScriptJobsView.as_view(), name='script_jobs'),
|
||||
path('scripts/class/<int:pk>/', views.ScriptView.as_view(), name='script'),
|
||||
path('scripts/class/<int:pk>/source/', views.ScriptSourceView.as_view(), name='script_source'),
|
||||
path('scripts/class/<int:pk>/jobs/', views.ScriptJobsView.as_view(), name='script_jobs'),
|
||||
|
||||
# Markdown
|
||||
path('render/markdown/', views.RenderMarkdownView.as_view(), name="render_markdown"),
|
||||
|
@ -1226,27 +1226,28 @@ class ScriptView(ContentTypePermissionRequiredMixin, View):
|
||||
def get_required_permission(self):
|
||||
return 'extras.view_script'
|
||||
|
||||
def get(self, request, module, name):
|
||||
module = get_script_module(module, request)
|
||||
script = module.scripts[name]()
|
||||
jobs = module.get_jobs(script.class_name)
|
||||
form = script.as_form(initial=normalize_querydict(request.GET))
|
||||
def get(self, request, pk):
|
||||
script = Script.objects.get(pk=pk)
|
||||
script_class = script.python_class()
|
||||
jobs = script.get_jobs()
|
||||
form = script_class.as_form(initial=normalize_querydict(request.GET))
|
||||
|
||||
return render(request, 'extras/script.html', {
|
||||
'job_count': jobs.count(),
|
||||
'module': module,
|
||||
'module': script.module,
|
||||
'script': script,
|
||||
'script_class': script_class,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
def post(self, request, module, name):
|
||||
def post(self, request, pk):
|
||||
if not request.user.has_perm('extras.run_script'):
|
||||
return HttpResponseForbidden()
|
||||
|
||||
module = get_script_module(module, request)
|
||||
script = module.scripts[name]()
|
||||
jobs = module.get_jobs(script.class_name)
|
||||
form = script.as_form(request.POST, request.FILES)
|
||||
script = Script.objects.get(pk=pk)
|
||||
script_class = script.python_class()
|
||||
jobs = script.get_jobs()
|
||||
form = script_class.as_form(request.POST, request.FILES)
|
||||
|
||||
# Allow execution only if RQ worker process is running
|
||||
if not get_workers_for_queue('default'):
|
||||
@ -1255,8 +1256,8 @@ class ScriptView(ContentTypePermissionRequiredMixin, View):
|
||||
elif form.is_valid():
|
||||
job = Job.enqueue(
|
||||
run_script,
|
||||
instance=module,
|
||||
name=script.class_name,
|
||||
instance=script.module,
|
||||
name=script_class.class_name,
|
||||
user=request.user,
|
||||
schedule_at=form.cleaned_data.pop('_schedule_at'),
|
||||
interval=form.cleaned_data.pop('_interval'),
|
||||
@ -1270,8 +1271,9 @@ class ScriptView(ContentTypePermissionRequiredMixin, View):
|
||||
|
||||
return render(request, 'extras/script.html', {
|
||||
'job_count': jobs.count(),
|
||||
'module': module,
|
||||
'module': script.module,
|
||||
'script': script,
|
||||
'script_class': script_class,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
@ -1281,15 +1283,16 @@ class ScriptSourceView(ContentTypePermissionRequiredMixin, View):
|
||||
def get_required_permission(self):
|
||||
return 'extras.view_script'
|
||||
|
||||
def get(self, request, module, name):
|
||||
module = get_script_module(module, request)
|
||||
script = module.scripts[name]()
|
||||
jobs = module.get_jobs(script.class_name)
|
||||
def get(self, request, pk):
|
||||
script = Script.objects.get(pk=pk)
|
||||
script_class = script.python_class()
|
||||
jobs = script.get_jobs()
|
||||
|
||||
return render(request, 'extras/script/source.html', {
|
||||
'job_count': jobs.count(),
|
||||
'module': module,
|
||||
'module': script.module,
|
||||
'script': script,
|
||||
'script_class': script_class,
|
||||
'tab': 'source',
|
||||
})
|
||||
|
||||
@ -1299,10 +1302,10 @@ class ScriptJobsView(ContentTypePermissionRequiredMixin, View):
|
||||
def get_required_permission(self):
|
||||
return 'extras.view_script'
|
||||
|
||||
def get(self, request, module, name):
|
||||
module = get_script_module(module, request)
|
||||
script = module.scripts[name]()
|
||||
jobs = module.get_jobs(script.class_name)
|
||||
def get(self, request, pk):
|
||||
script = Script.objects.get(pk=pk)
|
||||
script_class = script.python_class()
|
||||
jobs = script.get_jobs()
|
||||
|
||||
jobs_table = JobTable(
|
||||
data=jobs,
|
||||
@ -1313,7 +1316,7 @@ class ScriptJobsView(ContentTypePermissionRequiredMixin, View):
|
||||
|
||||
return render(request, 'extras/script/jobs.html', {
|
||||
'job_count': jobs.count(),
|
||||
'module': module,
|
||||
'module': script.module,
|
||||
'script': script,
|
||||
'table': jobs_table,
|
||||
'tab': 'jobs',
|
||||
|
@ -17,7 +17,7 @@
|
||||
{% csrf_token %}
|
||||
<div class="field-group my-4">
|
||||
{# Render grouped fields according to declared fieldsets #}
|
||||
{% for group, fields in script.get_fieldsets %}
|
||||
{% for group, fields in script_class.get_fieldsets %}
|
||||
{% if fields %}
|
||||
<div class="field-group mb-5">
|
||||
<div class="row">
|
||||
|
@ -26,13 +26,13 @@
|
||||
{% block tabs %}
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if not tab %} active{% endif %}" href="{% url 'extras:script' module=script.module name=script.class_name %}">{% trans "Script" %}</a>
|
||||
<a class="nav-link{% if not tab %} active{% endif %}" href="{% url 'extras:script' script.id %}">{% trans "Script" %}</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if tab == 'source' %} active{% endif %}" href="{% url 'extras:script_source' module=script.module name=script.class_name %}">{% trans "Source" %}</a>
|
||||
<a class="nav-link{% if tab == 'source' %} active{% endif %}" href="{% url 'extras:script_source' script.id %}">{% trans "Source" %}</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if tab == 'jobs' %} active{% endif %}" href="{% url 'extras:script_jobs' module=script.module name=script.class_name %}">
|
||||
<a class="nav-link{% if tab == 'jobs' %} active{% endif %}" href="{% url 'extras:script_jobs' script.id %}">
|
||||
{% trans "Jobs" %} {% badge job_count %}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% extends 'extras/script/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<code class="h6 my-3 d-block">{{ script.filename }}</code>
|
||||
<pre class="block">{{ script.source }}</pre>
|
||||
<code class="h6 my-3 d-block">{{ script_class.filename }}</code>
|
||||
<pre class="block">{{ script_class.source }}</pre>
|
||||
{% endblock %}
|
||||
|
@ -56,7 +56,7 @@
|
||||
{% for script in module.scripts.all %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'extras:script' module=module.python_name name=script.name %}" name="script.{{ script.name }}">{{ script.python_class.name }}</a>
|
||||
<a href="{% url 'extras:script' script.id %}" name="script.{{ script.name }}">{{ script.python_class.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ script.python_class.Meta.description|markdown|placeholder }}
|
||||
|
Loading…
Reference in New Issue
Block a user