Move config rendering logic to new RenderConfigMixin

This commit is contained in:
Jeremy Stretch 2023-11-16 13:39:35 -05:00
parent 2b49d2ba60
commit 18597510cb
3 changed files with 38 additions and 47 deletions

View File

@ -3,10 +3,8 @@ from django.shortcuts import get_object_or_404
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, OpenApiParameter
from rest_framework.decorators import action
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.status import HTTP_400_BAD_REQUEST
from rest_framework.viewsets import ViewSet
from circuits.models import Circuit
@ -14,12 +12,11 @@ from dcim import filtersets
from dcim.constants import CABLE_TRACE_SVG_DEFAULT_WIDTH
from dcim.models import *
from dcim.svg import CableTraceSVG
from extras.api.mixins import ConfigContextQuerySetMixin, ConfigTemplateRenderMixin
from extras.api.mixins import ConfigContextQuerySetMixin, RenderConfigMixin
from ipam.models import Prefix, VLAN
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
from netbox.api.metadata import ContentTypeMetadata
from netbox.api.pagination import StripCountAnnotationsPaginator
from netbox.api.renderers import TextRenderer
from netbox.api.viewsets import NetBoxModelViewSet, MPTTLockedMixin
from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
from netbox.constants import NESTED_SERIALIZER_PREFIX
@ -389,7 +386,7 @@ class PlatformViewSet(NetBoxModelViewSet):
class DeviceViewSet(
SequentialBulkCreatesMixin,
ConfigContextQuerySetMixin,
ConfigTemplateRenderMixin,
RenderConfigMixin,
NetBoxModelViewSet
):
queryset = Device.objects.prefetch_related(
@ -419,23 +416,6 @@ class DeviceViewSet(
return serializers.DeviceWithConfigContextSerializer
@action(detail=True, methods=['post'], url_path='render-config', renderer_classes=[JSONRenderer, TextRenderer])
def render_config(self, request, pk):
"""
Resolve and render the preferred ConfigTemplate for this Device.
"""
device = self.get_object()
configtemplate = device.get_config_template()
if not configtemplate:
return Response({'error': 'No config template found for this device.'}, status=HTTP_400_BAD_REQUEST)
# Compile context data
context_data = device.get_config_context()
context_data.update(request.data)
context_data.update({'device': device})
return self.render_configtemplate(request, configtemplate, context_data)
class VirtualDeviceContextViewSet(NetBoxModelViewSet):
queryset = VirtualDeviceContext.objects.prefetch_related(

View File

@ -1,10 +1,16 @@
from jinja2.exceptions import TemplateError
from rest_framework.decorators import action
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST
from netbox.api.renderers import TextRenderer
from .nested_serializers import NestedConfigTemplateSerializer
__all__ = (
'ConfigContextQuerySetMixin',
'ConfigTemplateRenderMixin',
'RenderConfigMixin',
)
@ -31,7 +37,9 @@ class ConfigContextQuerySetMixin:
class ConfigTemplateRenderMixin:
"""
Provides a method to return a rendered ConfigTemplate as REST API data.
"""
def render_configtemplate(self, request, configtemplate, context):
try:
output = configtemplate.render(context=context)
@ -50,3 +58,28 @@ class ConfigTemplateRenderMixin:
'configtemplate': template_serializer.data,
'content': output
})
class RenderConfigMixin(ConfigTemplateRenderMixin):
"""
Provides a /render-config/ endpoint for REST API views whose model may have a ConfigTemplate assigned.
"""
@action(detail=True, methods=['post'], url_path='render-config', renderer_classes=[JSONRenderer, TextRenderer])
def render_config(self, request, pk):
"""
Resolve and render the preferred ConfigTemplate for this Device.
"""
instance = self.get_object()
object_type = instance._meta._model_name
configtemplate = instance.get_config_template()
if not configtemplate:
return Response({
'error': f'No config template found for this {object_type}.'
}, status=HTTP_400_BAD_REQUEST)
# Compile context data
context_data = instance.get_config_context()
context_data.update(request.data)
context_data.update({object_type: instance})
return self.render_configtemplate(request, configtemplate, context_data)

View File

@ -1,12 +1,7 @@
from rest_framework.decorators import action
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.status import HTTP_400_BAD_REQUEST
from dcim.models import Device
from extras.api.mixins import ConfigContextQuerySetMixin, ConfigTemplateRenderMixin
from netbox.api.renderers import TextRenderer
from extras.api.mixins import ConfigContextQuerySetMixin, RenderConfigMixin
from netbox.api.viewsets import NetBoxModelViewSet
from utilities.utils import count_related
from virtualization import filtersets
@ -57,7 +52,7 @@ class ClusterViewSet(NetBoxModelViewSet):
# Virtual machines
#
class VirtualMachineViewSet(ConfigContextQuerySetMixin, ConfigTemplateRenderMixin, NetBoxModelViewSet):
class VirtualMachineViewSet(ConfigContextQuerySetMixin, RenderConfigMixin, NetBoxModelViewSet):
queryset = VirtualMachine.objects.prefetch_related(
'site', 'cluster', 'device', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'config_template', 'tags'
)
@ -83,23 +78,6 @@ class VirtualMachineViewSet(ConfigContextQuerySetMixin, ConfigTemplateRenderMixi
return serializers.VirtualMachineWithConfigContextSerializer
@action(detail=True, methods=['post'], url_path='render-config', renderer_classes=[JSONRenderer, TextRenderer])
def render_config(self, request, pk):
"""
Resolve and render the preferred ConfigTemplate for this Virtual Machine.
"""
instance = self.get_object()
configtemplate = instance.get_config_template()
if not configtemplate:
return Response({'error': 'No config template found for this virtual machine.'}, status=HTTP_400_BAD_REQUEST)
# Compile context data
context_data = instance.get_config_context()
context_data.update(request.data)
context_data.update({'virtualmachine': instance})
return self.render_configtemplate(request, configtemplate, context_data)
class VMInterfaceViewSet(NetBoxModelViewSet):
queryset = VMInterface.objects.prefetch_related(