diff --git a/src/servala/core/crd.py b/src/servala/core/crd.py index 2c2b9fb..2793d75 100644 --- a/src/servala/core/crd.py +++ b/src/servala/core/crd.py @@ -5,6 +5,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator, RegexVa from django.db import models from django.forms.models import ModelForm, ModelFormMetaclass from django.utils.translation import gettext_lazy as _ +from jsonschema import validate from servala.core.models import ServiceInstance @@ -253,14 +254,10 @@ class CrdModelFormMixin: def validate_nested_data(self, data, schema): """Validate data against the provided OpenAPI v3 schema""" - # TODO: actually validate the nested data. - # TODO: get jsonschema to give us a path to the failing field rather than just an error message, - # then add the validation error to that field (self.add_error()) - # try: - # validate(instance=data, schema=schema) - # except Exception as e: - # raise forms.ValidationError(f"Validation error: {e.message}") - pass + try: + validate(instance=data, schema=schema) + except Exception as e: + raise forms.ValidationError(f"Validation error: {e.message}") def generate_model_form_class(model): diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index 9e282a6..5d34d80 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -191,21 +191,6 @@ class ControlPlane(ServalaModelMixin, models.Model): except Exception as e: return False, _("Connection error: {}").format(str(e)) - def get_or_create_namespace(self, name): - api_instance = kubernetes.client.CoreV1Api(self.get_kubernetes_client()) - try: - api_instance.read_namespace(name=name) - except kubernetes.client.ApiException as e: - if e.status == 404: - # Namespace does not exist, create it - body = kubernetes.client.V1Namespace( - metadata=kubernetes.client.V1ObjectMeta(name=name) - ) - api_instance.create_namespace(body=body) - else: - # If there's another error, raise it - raise - class CloudProvider(ServalaModelMixin, models.Model): """ @@ -480,9 +465,27 @@ class ServiceInstance(ServalaModelMixin, models.Model): base = "{self.organization.urls.instances}{self.name}/" @classmethod - def create_instance(cls, name, organization, context, created_by, spec_data): + def create_instance(cls, organization, context, created_by, spec_data): + name = spec_data.get("spec.name") + # Ensure the namespace exists - context.control_plane.get_or_create_namespace(organization.namespace) + namespace_name = organization.namespace + api_instance = kubernetes.client.CoreV1Api( + context.control_plane.get_kubernetes_client() + ) + + try: + api_instance.read_namespace(name=namespace_name) + except kubernetes.client.ApiException as e: + if e.status == 404: + # Namespace does not exist, create it + body = kubernetes.client.V1Namespace( + metadata=kubernetes.client.V1ObjectMeta(name=namespace_name) + ) + api_instance.create_namespace(body=body) + else: + # If there's another error, raise it + raise return cls.objects.create( name=name, diff --git a/src/servala/frontend/views/service.py b/src/servala/frontend/views/service.py index 1803dd0..cfb1ff8 100644 --- a/src/servala/frontend/views/service.py +++ b/src/servala/frontend/views/service.py @@ -128,7 +128,6 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView try: service_instance = ServiceInstance.create_instance( organization=self.organization, - name=form.cleaned_data["name"], context=self.context_object, created_by=request.user, spec_data=form.get_nested_data(),