From ff4eb0a9ba1533bf0bf1d189629db66282ba8ebe Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 31 Jan 2025 15:46:22 +0100 Subject: [PATCH] osb catalog --- hub/broker/serializers.py | 68 +++++++++++++++++++++++++++++++++++++++ hub/broker/views.py | 22 ++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/hub/broker/serializers.py b/hub/broker/serializers.py index 6ac63fd..2d1db9d 100644 --- a/hub/broker/serializers.py +++ b/hub/broker/serializers.py @@ -1,5 +1,6 @@ from rest_framework import serializers from hub.services.models import ServiceOffering, Plan +from django.utils.html import strip_tags class ServiceUserSerializer(serializers.Serializer): @@ -47,3 +48,70 @@ class ServiceInstanceProvisioningSerializer(serializers.Serializer): return plan except Plan.DoesNotExist: raise serializers.ValidationError("Invalid plan_id") + + +class CostSerializer(serializers.Serializer): + amount = serializers.DecimalField(max_digits=10, decimal_places=2) + unit = serializers.CharField() + + +class PlanMetadataSerializer(serializers.Serializer): + bullets = serializers.ListField(child=serializers.CharField(), required=False) + costs = CostSerializer(many=True, required=False) + + +class PlanSerializer(serializers.ModelSerializer): + description = serializers.SerializerMethodField() + + def get_description(self, obj): + return strip_tags(obj.description) if obj.description else "" + + class Meta: + model = Plan + fields = ["id", "name", "description"] + + +class ServiceOfferingMetadataSerializer(serializers.Serializer): + displayName = serializers.CharField() + providerDisplayName = serializers.CharField() + longDescription = serializers.SerializerMethodField() + imageUrl = serializers.URLField(required=False) + + def get_longDescription(self, obj): + return strip_tags(obj["longDescription"]) if obj.get("longDescription") else "" + + +class ServiceOfferingSerializer(serializers.ModelSerializer): + id = serializers.SerializerMethodField() + name = serializers.SerializerMethodField() + description = serializers.SerializerMethodField() + plans = PlanSerializer(many=True) + bindable = serializers.BooleanField(default=True) + metadata = serializers.SerializerMethodField() + + class Meta: + model = ServiceOffering + fields = ["id", "name", "description", "plans", "bindable", "metadata"] + + def get_id(self, obj): + return str(obj.pk) + + def get_name(self, obj): + return f"{obj.service.name}-{obj.cloud_provider.name}".lower().replace(" ", "-") + + def get_description(self, obj): + return strip_tags(obj.description) if obj.description else "" + + def get_metadata(self, obj): + return ServiceOfferingMetadataSerializer( + { + "displayName": obj.service.name, + "providerDisplayName": obj.cloud_provider.name, + "longDescription": obj.description, + "imageUrl": obj.service.logo.url if obj.service.logo else None, + } + ).data + + +class CatalogSerializer(serializers.Serializer): + services = ServiceOfferingSerializer(many=True) diff --git a/hub/broker/views.py b/hub/broker/views.py index 718d0bb..dbbb40b 100644 --- a/hub/broker/views.py +++ b/hub/broker/views.py @@ -6,7 +6,7 @@ from django.shortcuts import get_object_or_404 from hub.services.models import ServiceOffering, Lead from hub.services.odoo import OdooAPI from .models import ServiceInstance, ServiceBrokerUser -from .serializers import ServiceInstanceProvisioningSerializer +from .serializers import ServiceInstanceProvisioningSerializer, CatalogSerializer from .authentication import ServiceBrokerAuthentication logger = logging.getLogger(__name__) @@ -15,6 +15,26 @@ logger = logging.getLogger(__name__) class ServiceBrokerViewSet(viewsets.ViewSet): authentication_classes = [ServiceBrokerAuthentication] + @action(detail=False, methods=["get"], url_path="catalog") + def get_catalog(self, request): + """ + Return the catalog of services available to the authenticated user. + """ + # Get broker user and their allowed offerings + broker_user = get_object_or_404(ServiceBrokerUser, user=request.user) + offerings = broker_user.allowed_offerings.prefetch_related( + "plans", + "plans__prices", + "plans__prices__currency", + "plans__prices__term", + "service", + "cloud_provider", + ).all() + + # Serialize the catalog + serializer = CatalogSerializer({"services": offerings}) + return Response(serializer.data) + def _create_lead_from_provision_data(self, offering, plan, parameters, context): """Create a lead in Odoo from provisioning data""" # Get the first user from parameters as the main contact