diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 5789dc7c2..4999f6fab 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -200,6 +200,36 @@ class ReportDetailSerializer(ReportSerializer): result = ReportResultSerializer() +# +# Scripts +# + +class ScriptSerializer(serializers.Serializer): + id = serializers.SerializerMethodField(read_only=True) + name = serializers.SerializerMethodField(read_only=True) + description = serializers.SerializerMethodField(read_only=True) + vars = serializers.SerializerMethodField(read_only=True) + + 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() + } + + +class ScriptInputSerializer(serializers.Serializer): + data = serializers.JSONField() + commit = serializers.BooleanField() + + # # Change logging # diff --git a/netbox/extras/api/urls.py b/netbox/extras/api/urls.py index ddfe2107c..3215439c2 100644 --- a/netbox/extras/api/urls.py +++ b/netbox/extras/api/urls.py @@ -38,6 +38,9 @@ router.register(r'config-contexts', views.ConfigContextViewSet) # Reports router.register(r'reports', views.ReportViewSet, basename='report') +# Scripts +router.register(r'scripts', views.ScriptViewSet, basename='script') + # Change logging router.register(r'object-changes', views.ObjectChangeViewSet) diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index a6b678522..8c8b5de87 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -3,6 +3,7 @@ from collections import OrderedDict from django.contrib.contenttypes.models import ContentType from django.db.models import Count from django.http import Http404 +from rest_framework import status from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response @@ -13,6 +14,7 @@ from extras.models import ( ConfigContext, CustomFieldChoice, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, Tag, ) from extras.reports import get_report, get_reports +from extras.scripts import get_script, get_scripts from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet from . import serializers @@ -222,6 +224,53 @@ class ReportViewSet(ViewSet): return Response(serializer.data) +# +# Scripts +# + +class ScriptViewSet(ViewSet): + permission_classes = [IsAuthenticatedOrLoginNotRequired] + _ignore_model_permissions = True + exclude_from_schema = True + lookup_value_regex = '[^/]+' # Allow dots + + def _get_script(self, pk): + module_name, script_name = pk.split('.') + script = get_script(module_name, script_name) + if script is None: + raise Http404 + return script + + def list(self, request): + + flat_list = [] + for script_list in get_scripts().values(): + flat_list.extend(script_list.values()) + + serializer = serializers.ScriptSerializer(flat_list, many=True, context={'request': request}) + + return Response(serializer.data) + + def retrieve(self, request, pk): + script = self._get_script(pk) + serializer = serializers.ScriptSerializer(script, context={'request': request}) + + return Response(serializer.data) + + def post(self, request, pk): + """ + Run a Script identified as ".