refactor into a shared function
All checks were successful
Tests / test (push) Successful in 27s

This commit is contained in:
Tobias Brunner 2025-07-10 16:11:30 +02:00
parent 5fa3d32c57
commit 3c270d9c12
No known key found for this signature in database
4 changed files with 30 additions and 88 deletions

View file

@ -4,6 +4,7 @@ from django.conf import settings
from django.db import models, transaction from django.db import models, transaction
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_scopes import ScopedManager, scopes_disabled from django_scopes import ScopedManager, scopes_disabled
@ -74,6 +75,12 @@ class Organization(ServalaModelMixin, models.Model):
user=user, organization=self, role=OrganizationRole.OWNER user=user, organization=self, role=OrganizationRole.OWNER
) )
def add_support_message(self, message):
support_message = _(
"Need help? We're happy to help via the <a href='{support_url}'>support form</a>."
).format(support_url=self.urls.support)
return mark_safe(f"{message} {support_message}")
@classmethod @classmethod
@transaction.atomic @transaction.atomic
def create_organization(cls, instance, owner): def create_organization(cls, instance, owner):

View file

@ -20,10 +20,6 @@ from servala.core import rules as perms
from servala.core.models.mixins import ServalaModelMixin from servala.core.models.mixins import ServalaModelMixin
from servala.core.validators import kubernetes_name_validator from servala.core.validators import kubernetes_name_validator
SUPPORT_MESSAGE_TEMPLATE = _(
"Need help? We're happy to help via the <a href='{support_url}'>support form</a>."
)
class ServiceCategory(ServalaModelMixin, models.Model): class ServiceCategory(ServalaModelMixin, models.Model):
""" """
@ -620,10 +616,8 @@ class ServiceInstance(ServalaModelMixin, models.Model):
context=context, context=context,
) )
except IntegrityError: except IntegrityError:
raise cls._format_error_with_support( message = "An instance with this name already exists in this organization. Please choose a different name."
"An instance with this name already exists in this organization. Please choose a different name.", raise ValidationError(organization.add_support_message(message))
organization,
)
try: try:
spec_data = cls._prepare_spec_data(spec_data) spec_data = cls._prepare_spec_data(spec_data)
@ -661,16 +655,13 @@ class ServiceInstance(ServalaModelMixin, models.Model):
try: try:
error_body = json.loads(e.body) error_body = json.loads(e.body)
reason = error_body.get("message", str(e)) reason = error_body.get("message", str(e))
raise cls._format_error_with_support( message = f"Kubernetes API error: {reason}."
"Kubernetes API error: {error}.", organization, error=reason raise ValidationError(organization.add_support_message(message))
)
except (ValueError, TypeError): except (ValueError, TypeError):
raise cls._format_error_with_support( message = f"Kubernetes API error: {str(e)}."
"Kubernetes API error: {error}.", organization, error=str(e) raise ValidationError(organization.add_support_message(message))
) message = f"Error creating instance: {str(e)}."
raise cls._format_error_with_support( raise ValidationError(organization.add_support_message(message))
"Error creating instance: {error}.", organization, error=str(e)
)
return instance return instance
def update_spec(self, spec_data, updated_by): def update_spec(self, spec_data, updated_by):
@ -691,28 +682,19 @@ class ServiceInstance(ServalaModelMixin, models.Model):
self.save() # Updates updated_at timestamp self.save() # Updates updated_at timestamp
except ApiException as e: except ApiException as e:
if e.status == 404: if e.status == 404:
raise self._format_error_with_support( message = "Service instance not found in Kubernetes. It may have been deleted externally."
"Service instance not found in Kubernetes. It may have been deleted externally.", raise ValidationError(self.organization.add_support_message(message))
self.organization,
)
try: try:
error_body = json.loads(e.body) error_body = json.loads(e.body)
reason = error_body.get("message", str(e)) reason = error_body.get("message", str(e))
raise self._format_error_with_support( message = f"Kubernetes API error updating instance: {reason}."
"Kubernetes API error updating instance: {error}.", raise ValidationError(self.organization.add_support_message(message))
self.organization,
error=reason,
)
except (ValueError, TypeError): except (ValueError, TypeError):
raise self._format_error_with_support( message = f"Kubernetes API error updating instance: {str(e)}."
"Kubernetes API error updating instance: {error}.", raise ValidationError(self.organization.add_support_message(message))
self.organization,
error=str(e),
)
except Exception as e: except Exception as e:
raise self._format_error_with_support( message = f"Error updating instance: {str(e)}."
"Error updating instance: {error}.", self.organization, error=str(e) raise ValidationError(self.organization.add_support_message(message))
)
@transaction.atomic @transaction.atomic
def delete_instance(self, user): def delete_instance(self, user):
@ -863,24 +845,3 @@ class ServiceInstance(ServalaModelMixin, models.Model):
return {"error": str(e)} return {"error": str(e)}
except Exception as e: except Exception as e:
return {"error": str(e)} return {"error": str(e)}
@classmethod
def _format_error_with_support(cls, message, organization, **kwargs):
"""
Helper method to format error messages with support links.
Args:
message: The error message template (without support text)
organization: The organization object to get the support URL
**kwargs: Additional format parameters for the message
Returns:
A ValidationError with the formatted message including support link
"""
support_url = organization.urls.support
# Combine the main message with the support message template
full_message = _("{message} {support_message}").format(
message=_(message).format(**kwargs),
support_message=SUPPORT_MESSAGE_TEMPLATE.format(support_url=support_url),
)
return ValidationError(mark_safe(full_message))

View file

@ -1,14 +1,9 @@
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView from django.views.generic import UpdateView
from rules.contrib.views import AutoPermissionRequiredMixin, PermissionRequiredMixin from rules.contrib.views import AutoPermissionRequiredMixin, PermissionRequiredMixin
from servala.core.models import Organization from servala.core.models import Organization
# Import the support message template from the service model
from servala.core.models.service import SUPPORT_MESSAGE_TEMPLATE
class HtmxViewMixin: class HtmxViewMixin:
fragments = [] fragments = []
@ -95,22 +90,3 @@ class OrganizationViewMixin(PermissionRequiredMixin):
def has_permission(self): def has_permission(self):
return self.has_organization_permission() and super().has_permission() return self.has_organization_permission() and super().has_permission()
def format_error_with_support(self, message, **kwargs):
"""
Helper method to format error messages with support links for frontend views.
Args:
message: The error message template (without support text)
**kwargs: Additional format parameters for the message
Returns:
A formatted message with support link
"""
support_url = self.organization.urls.support
# Combine the main message with the support message template
full_message = _("{message} {support_message}").format(
message=_(message).format(**kwargs),
support_message=SUPPORT_MESSAGE_TEMPLATE.format(support_url=support_url),
)
return mark_safe(full_message)

View file

@ -146,7 +146,7 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView
if not form: # Should not happen if context_object is valid, but as a safeguard if not form: # Should not happen if context_object is valid, but as a safeguard
messages.error( messages.error(
self.request, self.request,
self.format_error_with_support("Could not initialize service form."), self.organization.add_support_message("Could not initialize service form."),
) )
return self.render_to_response(context) return self.render_to_response(context)
@ -165,8 +165,8 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView
except Exception as e: except Exception as e:
messages.error( messages.error(
self.request, self.request,
self.format_error_with_support( self.organization.add_support_message(
"Error creating instance: {error}.", error=str(e) f"Error creating instance: {str(e)}."
), ),
) )
@ -373,8 +373,8 @@ class ServiceInstanceUpdateView(
except Exception as e: except Exception as e:
messages.error( messages.error(
self.request, self.request,
self.format_error_with_support( self.organization.add_support_message(
"Error updating instance: {error}.", error=str(e) f"Error updating instance: {str(e)}."
), ),
) )
return self.form_invalid(form) return self.form_invalid(form)
@ -444,10 +444,8 @@ class ServiceInstanceDeleteView(
except Exception as e: except Exception as e:
messages.error( messages.error(
self.request, self.request,
self.format_error_with_support( self.organization.add_support_message(
"An error occurred while trying to delete instance '{name}': {error}.", f"An error occurred while trying to delete instance '{self.object.name}': {str(e)}."
name=self.object.name,
error=str(e),
), ),
) )
response = HttpResponse() response = HttpResponse()