From 3c270d9c121dff55ca505f4b63aa4dda6ad78eb9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 10 Jul 2025 16:11:30 +0200 Subject: [PATCH] refactor into a shared function --- src/servala/core/models/organization.py | 7 +++ src/servala/core/models/service.py | 71 ++++++------------------- src/servala/frontend/views/mixins.py | 24 --------- src/servala/frontend/views/service.py | 16 +++--- 4 files changed, 30 insertions(+), 88 deletions(-) diff --git a/src/servala/core/models/organization.py b/src/servala/core/models/organization.py index a9dcd4e..da8c11b 100644 --- a/src/servala/core/models/organization.py +++ b/src/servala/core/models/organization.py @@ -4,6 +4,7 @@ from django.conf import settings from django.db import models, transaction from django.utils.functional import cached_property from django.utils.text import slugify +from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from django_scopes import ScopedManager, scopes_disabled @@ -74,6 +75,12 @@ class Organization(ServalaModelMixin, models.Model): user=user, organization=self, role=OrganizationRole.OWNER ) + def add_support_message(self, message): + support_message = _( + "Need help? We're happy to help via the support form." + ).format(support_url=self.urls.support) + return mark_safe(f"{message} {support_message}") + @classmethod @transaction.atomic def create_organization(cls, instance, owner): diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index ebc2878..365fcce 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -20,10 +20,6 @@ from servala.core import rules as perms from servala.core.models.mixins import ServalaModelMixin from servala.core.validators import kubernetes_name_validator -SUPPORT_MESSAGE_TEMPLATE = _( - "Need help? We're happy to help via the support form." -) - class ServiceCategory(ServalaModelMixin, models.Model): """ @@ -620,10 +616,8 @@ class ServiceInstance(ServalaModelMixin, models.Model): context=context, ) except IntegrityError: - raise cls._format_error_with_support( - "An instance with this name already exists in this organization. Please choose a different name.", - organization, - ) + message = "An instance with this name already exists in this organization. Please choose a different name." + raise ValidationError(organization.add_support_message(message)) try: spec_data = cls._prepare_spec_data(spec_data) @@ -661,16 +655,13 @@ class ServiceInstance(ServalaModelMixin, models.Model): try: error_body = json.loads(e.body) reason = error_body.get("message", str(e)) - raise cls._format_error_with_support( - "Kubernetes API error: {error}.", organization, error=reason - ) + message = f"Kubernetes API error: {reason}." + raise ValidationError(organization.add_support_message(message)) except (ValueError, TypeError): - raise cls._format_error_with_support( - "Kubernetes API error: {error}.", organization, error=str(e) - ) - raise cls._format_error_with_support( - "Error creating instance: {error}.", organization, error=str(e) - ) + message = f"Kubernetes API error: {str(e)}." + raise ValidationError(organization.add_support_message(message)) + message = f"Error creating instance: {str(e)}." + raise ValidationError(organization.add_support_message(message)) return instance def update_spec(self, spec_data, updated_by): @@ -691,28 +682,19 @@ class ServiceInstance(ServalaModelMixin, models.Model): self.save() # Updates updated_at timestamp except ApiException as e: if e.status == 404: - raise self._format_error_with_support( - "Service instance not found in Kubernetes. It may have been deleted externally.", - self.organization, - ) + message = "Service instance not found in Kubernetes. It may have been deleted externally." + raise ValidationError(self.organization.add_support_message(message)) try: error_body = json.loads(e.body) reason = error_body.get("message", str(e)) - raise self._format_error_with_support( - "Kubernetes API error updating instance: {error}.", - self.organization, - error=reason, - ) + message = f"Kubernetes API error updating instance: {reason}." + raise ValidationError(self.organization.add_support_message(message)) except (ValueError, TypeError): - raise self._format_error_with_support( - "Kubernetes API error updating instance: {error}.", - self.organization, - error=str(e), - ) + message = f"Kubernetes API error updating instance: {str(e)}." + raise ValidationError(self.organization.add_support_message(message)) except Exception as e: - raise self._format_error_with_support( - "Error updating instance: {error}.", self.organization, error=str(e) - ) + message = f"Error updating instance: {str(e)}." + raise ValidationError(self.organization.add_support_message(message)) @transaction.atomic def delete_instance(self, user): @@ -863,24 +845,3 @@ class ServiceInstance(ServalaModelMixin, models.Model): return {"error": str(e)} except Exception as 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)) diff --git a/src/servala/frontend/views/mixins.py b/src/servala/frontend/views/mixins.py index 7e7b453..fd5a494 100644 --- a/src/servala/frontend/views/mixins.py +++ b/src/servala/frontend/views/mixins.py @@ -1,14 +1,9 @@ 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 rules.contrib.views import AutoPermissionRequiredMixin, PermissionRequiredMixin 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: fragments = [] @@ -95,22 +90,3 @@ class OrganizationViewMixin(PermissionRequiredMixin): def has_permission(self): 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) diff --git a/src/servala/frontend/views/service.py b/src/servala/frontend/views/service.py index 49ac683..be1b80c 100644 --- a/src/servala/frontend/views/service.py +++ b/src/servala/frontend/views/service.py @@ -146,7 +146,7 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView if not form: # Should not happen if context_object is valid, but as a safeguard messages.error( 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) @@ -165,8 +165,8 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView except Exception as e: messages.error( self.request, - self.format_error_with_support( - "Error creating instance: {error}.", error=str(e) + self.organization.add_support_message( + f"Error creating instance: {str(e)}." ), ) @@ -373,8 +373,8 @@ class ServiceInstanceUpdateView( except Exception as e: messages.error( self.request, - self.format_error_with_support( - "Error updating instance: {error}.", error=str(e) + self.organization.add_support_message( + f"Error updating instance: {str(e)}." ), ) return self.form_invalid(form) @@ -444,10 +444,8 @@ class ServiceInstanceDeleteView( except Exception as e: messages.error( self.request, - self.format_error_with_support( - "An error occurred while trying to delete instance '{name}': {error}.", - name=self.object.name, - error=str(e), + self.organization.add_support_message( + f"An error occurred while trying to delete instance '{self.object.name}': {str(e)}." ), ) response = HttpResponse()