mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
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 .serializers import ConfigTemplateSerializer
|
|
|
|
__all__ = (
|
|
'ConfigContextQuerySetMixin',
|
|
'ConfigTemplateRenderMixin',
|
|
'RenderConfigMixin',
|
|
)
|
|
|
|
|
|
class ConfigContextQuerySetMixin:
|
|
"""
|
|
Used by views that work with config context models (device and virtual machine).
|
|
Provides a get_queryset() method which deals with adding the config context
|
|
data annotation or not.
|
|
"""
|
|
def get_queryset(self):
|
|
"""
|
|
Build the proper queryset based on the request context
|
|
|
|
If the `brief` query param equates to True or the `exclude` query param
|
|
includes `config_context` as a value, return the base queryset.
|
|
|
|
Else, return the queryset annotated with config context data
|
|
"""
|
|
queryset = super().get_queryset()
|
|
request = self.get_serializer_context()['request']
|
|
if self.brief or 'config_context' in request.query_params.get('exclude', []):
|
|
return queryset
|
|
return queryset.annotate_config_context_data()
|
|
|
|
|
|
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)
|
|
except TemplateError as e:
|
|
return Response({
|
|
'detail': f"An error occurred while rendering the template (line {e.lineno}): {e}"
|
|
}, status=500)
|
|
|
|
# If the client has requested "text/plain", return the raw content.
|
|
if request.accepted_renderer.format == 'txt':
|
|
return Response(output)
|
|
|
|
template_serializer = ConfigTemplateSerializer(configtemplate, nested=True, context={'request': request})
|
|
|
|
return Response({
|
|
'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)
|