Initial commit
This commit is contained in:
commit
4ff9eac274
45 files changed
+2911
No files matched your search
@@ -0,0 +1,193 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.views import generic
|
||||
from utilities.views import register_model_view
|
||||
|
||||
from .engine.resolver import Resolver
|
||||
from .filtersets import ServiceFilterSet, ServiceTemplateFilterSet
|
||||
from .forms import (
|
||||
ResolveForm,
|
||||
ServiceBulkEditForm,
|
||||
ServiceFilterSetForm,
|
||||
ServiceForm,
|
||||
ServiceTemplateBulkEditForm,
|
||||
ServiceTemplateFilterSetForm,
|
||||
ServiceTemplateForm,
|
||||
ServiceTemplateImportForm,
|
||||
)
|
||||
from .models import Service, ServiceTemplate
|
||||
from .tables import ServiceTable, ServiceTemplateTable
|
||||
|
||||
|
||||
def _build_preview(result):
|
||||
"""Transform result.planned_objects into a list of dicts with pre-computed action."""
|
||||
preview = []
|
||||
for node_name, obj in result.planned_objects:
|
||||
ct = ContentType.objects.get_for_model(obj.__class__)
|
||||
key = (ct.id, obj.pk)
|
||||
action = "add" if key in result.to_add else "keep"
|
||||
preview.append({"node": node_name, "object": obj, "action": action})
|
||||
return preview
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════
|
||||
# Service Template
|
||||
# ════════════════════════════════════════════════════════════════════
|
||||
|
||||
@register_model_view(ServiceTemplate, "list", path="", detail=False)
|
||||
class ServiceTemplateListView(generic.ObjectListView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
table = ServiceTemplateTable
|
||||
filterset = ServiceTemplateFilterSet
|
||||
filterset_form = ServiceTemplateFilterSetForm
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate, "add", path="add", detail=False)
|
||||
@register_model_view(ServiceTemplate, "edit")
|
||||
class ServiceTemplateEditView(generic.ObjectEditView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
form = ServiceTemplateForm
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate, "delete")
|
||||
class ServiceTemplateDeleteView(generic.ObjectDeleteView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate, "bulk_edit", path="edit", detail=False)
|
||||
class ServiceTemplateBulkEditView(generic.BulkEditView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
table = ServiceTemplateTable
|
||||
form = ServiceTemplateBulkEditForm
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate, "bulk_delete", path="delete", detail=False)
|
||||
class ServiceTemplateBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
table = ServiceTemplateTable
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate, "bulk_import", path="import", detail=False)
|
||||
class ServiceTemplateBulkImportView(generic.BulkImportView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
model_form = ServiceTemplateImportForm
|
||||
table = ServiceTemplateTable
|
||||
|
||||
|
||||
@register_model_view(ServiceTemplate)
|
||||
class ServiceTemplateView(generic.ObjectView):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
context = super().get_extra_context(request, instance)
|
||||
context["is_locked"] = instance.is_locked
|
||||
return context
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════
|
||||
# Service
|
||||
# ════════════════════════════════════════════════════════════════════
|
||||
|
||||
@register_model_view(Service, "list", path="", detail=False)
|
||||
class ServiceListView(generic.ObjectListView):
|
||||
queryset = Service.objects.all()
|
||||
table = ServiceTable
|
||||
filterset = ServiceFilterSet
|
||||
filterset_form = ServiceFilterSetForm
|
||||
|
||||
|
||||
@register_model_view(Service, "add", path="add", detail=False)
|
||||
@register_model_view(Service, "edit")
|
||||
class ServiceEditView(generic.ObjectEditView):
|
||||
queryset = Service.objects.all()
|
||||
form = ServiceForm
|
||||
|
||||
|
||||
@register_model_view(Service, "delete")
|
||||
class ServiceDeleteView(generic.ObjectDeleteView):
|
||||
queryset = Service.objects.all()
|
||||
|
||||
|
||||
@register_model_view(Service, "bulk_edit", path="edit", detail=False)
|
||||
class ServiceBulkEditView(generic.BulkEditView):
|
||||
queryset = Service.objects.all()
|
||||
table = ServiceTable
|
||||
form = ServiceBulkEditForm
|
||||
|
||||
|
||||
@register_model_view(Service, "bulk_delete", path="delete", detail=False)
|
||||
class ServiceBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = Service.objects.all()
|
||||
table = ServiceTable
|
||||
|
||||
|
||||
@register_model_view(Service)
|
||||
class ServiceView(generic.ObjectView):
|
||||
queryset = Service.objects.all()
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
context = super().get_extra_context(request, instance)
|
||||
context["bindings"] = instance.bindings.select_related(
|
||||
"content_type",
|
||||
).all()
|
||||
return context
|
||||
|
||||
|
||||
@register_model_view(Service, "resolve", path="resolve")
|
||||
class ServiceResolveView(generic.ObjectView):
|
||||
"""Dry-run preview (GET) and commit (POST) for service resolution."""
|
||||
|
||||
queryset = Service.objects.all()
|
||||
|
||||
def get(self, request, pk):
|
||||
service = get_object_or_404(self.queryset, pk=pk)
|
||||
resolver = Resolver()
|
||||
try:
|
||||
result = resolver.resolve(service, mode="dry_run", user=request.user)
|
||||
except Exception as exc:
|
||||
messages.error(request, f"Resolution failed: {exc}")
|
||||
return redirect("plugins:netbox_services:service", pk=service.pk)
|
||||
|
||||
return render(request, "netbox_services/service_resolve.html", {
|
||||
"object": service,
|
||||
"service": service,
|
||||
"result": result,
|
||||
"planned_preview": _build_preview(result),
|
||||
"form": ResolveForm(initial={"mode": "commit"}),
|
||||
"active_tab": "resolve",
|
||||
})
|
||||
|
||||
def post(self, request, pk):
|
||||
service = get_object_or_404(self.queryset, pk=pk)
|
||||
form = ResolveForm(request.POST)
|
||||
mode = form.cleaned_data.get("mode", "dry_run") if form.is_valid() else "dry_run"
|
||||
|
||||
resolver = Resolver()
|
||||
try:
|
||||
result = resolver.resolve(service, mode=mode, user=request.user)
|
||||
except Exception as exc:
|
||||
messages.error(request, f"Resolution failed: {exc}")
|
||||
return redirect("plugins:netbox_services:service", pk=service.pk)
|
||||
|
||||
if mode == "commit":
|
||||
messages.success(
|
||||
request,
|
||||
_("Resolution committed: {added} added, {removed} removed, {kept} unchanged.").format(
|
||||
added=len(result.to_add),
|
||||
removed=len(result.to_remove),
|
||||
kept=result.total_planned - len(result.to_add),
|
||||
),
|
||||
)
|
||||
return redirect("plugins:netbox_services:service", pk=service.pk)
|
||||
|
||||
return render(request, "netbox_services/service_resolve.html", {
|
||||
"object": service,
|
||||
"service": service,
|
||||
"result": result,
|
||||
"planned_preview": _build_preview(result),
|
||||
"form": ResolveForm(initial={"mode": "commit"}),
|
||||
"active_tab": "resolve",
|
||||
})
|
||||
Reference in new issue
Block a user