From ef4f76b2907c4f4da81b9a9d4c95d5cd1eb38681 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Tue, 2 Dec 2025 16:11:51 +0100 Subject: [PATCH] Implement form changes for plan integration --- src/servala/core/crd/forms.py | 19 +++++++++++++++--- src/servala/frontend/forms/service.py | 29 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/servala/core/crd/forms.py b/src/servala/core/crd/forms.py index 659684e..b88f2db 100644 --- a/src/servala/core/crd/forms.py +++ b/src/servala/core/crd/forms.py @@ -69,13 +69,17 @@ class CrdModelFormMixin(FormGeneratorMixin): "spec.parameters.network.serviceType", "spec.parameters.scheduling", "spec.parameters.security", + "spec.publishConnectionDetailsTo", + "spec.resourceRef", + "spec.writeConnectionSecretToRef", + ] + + # Fields populated from compute plan + READONLY_FIELDS = [ "spec.parameters.size.cpu", "spec.parameters.size.memory", "spec.parameters.size.requests.cpu", "spec.parameters.size.requests.memory", - "spec.publishConnectionDetailsTo", - "spec.resourceRef", - "spec.writeConnectionSecretToRef", ] def __init__(self, *args, **kwargs): @@ -88,6 +92,15 @@ class CrdModelFormMixin(FormGeneratorMixin): ): field.widget = forms.HiddenInput() field.required = False + elif name in self.READONLY_FIELDS or any( + name.startswith(f) for f in self.READONLY_FIELDS + ): + field.disabled = True + field.required = False + field.widget.attrs["readonly"] = "readonly" + field.widget.attrs["class"] = ( + field.widget.attrs.get("class", "") + " form-control-plaintext" + ) def strip_title(self, field_name, label): field = self.fields[field_name] diff --git a/src/servala/frontend/forms/service.py b/src/servala/frontend/forms/service.py index 23325f3..169d6ea 100644 --- a/src/servala/frontend/forms/service.py +++ b/src/servala/frontend/forms/service.py @@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _ from servala.core.models import ( CloudProvider, + ComputePlanAssignment, ControlPlane, Service, ServiceCategory, @@ -56,6 +57,34 @@ class ControlPlaneSelectForm(forms.Form): self.fields["control_plane"].initial = planes.first() +class ComputePlanSelectionForm(forms.Form): + compute_plan_assignment = forms.ModelChoiceField( + queryset=ComputePlanAssignment.objects.none(), + widget=forms.RadioSelect, + required=True, + label=_("Compute Plan"), + empty_label=None, + ) + + def __init__(self, *args, control_plane_crd=None, **kwargs): + super().__init__(*args, **kwargs) + if control_plane_crd: + self.fields["compute_plan_assignment"].queryset = ( + ComputePlanAssignment.objects.filter( + control_plane_crd=control_plane_crd, is_active=True + ) + .select_related("compute_plan") + .order_by("sort_order", "compute_plan__name", "sla") + ) + if ( + not self.is_bound + and self.fields["compute_plan_assignment"].queryset.exists() + ): + self.fields["compute_plan_assignment"].initial = self.fields[ + "compute_plan_assignment" + ].queryset.first() + + class ServiceInstanceFilterForm(forms.Form): name = forms.CharField(required=False, label=_("Name")) service = forms.ModelChoiceField(