Compare commits

...

2 commits

Author SHA1 Message Date
4d13d71953 Improve display of kubernetes errors
All checks were successful
Tests / test (push) Successful in 23s
2025-04-03 18:01:15 +02:00
fb5a6e9a42 Improve name uniqueness feedback 2025-04-03 17:54:31 +02:00
2 changed files with 60 additions and 35 deletions

View file

@ -1,9 +1,11 @@
import json
import kubernetes import kubernetes
import urlman import urlman
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import IntegrityError, models
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from encrypted_fields.fields import EncryptedJSONField from encrypted_fields.fields import EncryptedJSONField
@ -492,39 +494,59 @@ class ServiceInstance(ServalaModelMixin, models.Model):
def create_instance(cls, name, organization, context, created_by, spec_data): def create_instance(cls, name, organization, context, created_by, spec_data):
# Ensure the namespace exists # Ensure the namespace exists
context.control_plane.get_or_create_namespace(organization.namespace) context.control_plane.get_or_create_namespace(organization.namespace)
try:
instance = cls.objects.create(
name=name,
organization=organization,
created_by=created_by,
context=context,
)
except IntegrityError:
raise ValidationError(
_(
"An instance with this name already exists in this organization. Please choose a different name."
)
)
group = context.service_definition.api_definition["group"] try:
version = context.service_definition.api_definition["version"] group = context.service_definition.api_definition["group"]
kind = context.service_definition.api_definition["kind"] version = context.service_definition.api_definition["version"]
create_data = { kind = context.service_definition.api_definition["kind"]
"apiVersion": f"{group}/{version}", create_data = {
"kind": kind, "apiVersion": f"{group}/{version}",
"metadata": { "kind": kind,
"name": name, "metadata": {
"namespace": organization.namespace, "name": name,
}, "namespace": organization.namespace,
"spec": spec_data or {}, },
} "spec": spec_data or {},
if label := context.control_plane.required_label: }
create_data["metadata"]["labels"] = {settings.DEFAULT_LABEL_KEY: label} if label := context.control_plane.required_label:
api_instance = client.CustomObjectsApi( create_data["metadata"]["labels"] = [
context.control_plane.get_kubernetes_client() {settings.DEFAULT_LABEL_KEY: label}
) ]
plural = kind.lower() api_instance = client.CustomObjectsApi(
if not plural.endswith("s"): context.control_plane.get_kubernetes_client()
plural = f"{plural}s" )
plural = kind.lower()
if not plural.endswith("s"):
plural = f"{plural}s"
api_instance.create_namespaced_custom_object( api_instance.create_namespaced_custom_object(
group=group, group=group,
version=version, version=version,
namespace=organization.namespace, namespace=organization.namespace,
plural=plural, plural=plural,
body=create_data, body=create_data,
) )
except Exception as e:
return cls.objects.create( instance.delete()
name=name, if isinstance(e, ApiException):
organization=organization, try:
created_by=created_by, error_body = json.loads(e.body)
context=context, reason = error_body.get("message", str(e))
) raise ValidationError(_("Kubernetes API error: {}").format(reason))
except (ValueError, TypeError):
raise ValidationError(_("Kubernetes API error: {}").format(str(e)))
raise ValidationError(_("Error creating instance: {}").format(str(e)))
return instance

View file

@ -1,4 +1,5 @@
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import ValidationError
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
@ -134,6 +135,8 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView
spec_data=form.get_nested_data().get("spec"), spec_data=form.get_nested_data().get("spec"),
) )
return redirect(service_instance.urls.base) return redirect(service_instance.urls.base)
except ValidationError as e:
messages.error(self.request, e.message or str(e))
except Exception as e: except Exception as e:
messages.error(self.request, str(e)) messages.error(self.request, str(e))