diff --git a/pyproject.toml b/pyproject.toml index 3cded0f..27d42c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ known_first_party = "servala" [tool.flake8] max-line-length = 160 exclude = ".venv" -ignore = "E203,W503" +ignore = "E203" [tool.djlint] extend_exclude = "src/servala/static/mazer" diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index 2f83d8d..550a489 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -609,34 +609,61 @@ class ServiceInstance(ServalaModelMixin, models.Model): @cached_property def connection_credentials(self): """ - Get connection credentials directly from the resource's writeConnectionSecretToRef - after checking that secret conditions are available. + Get connection credentials via spec.resourceRef. + The resource referenced there has the information which secret + we want in spec.writeConnectionSecretToRef.name and spec.writeConnectionSecretToRef.namespace. """ if not self.kubernetes_object: return {} - - # Check if secrets are available based on conditions - secrets_available = any( - [ - condition.get("type") == "Status" and condition.get("status") == "True" - for condition in self.status_conditions - ] - ) - if not secrets_available: - return {} - - if not (secret_ref := self.spec.get("writeConnectionSecretToRef")): - return {} - if not (secret_name := secret_ref.get("name")): + if not ( + resource_ref := self.kubernetes_object.get("spec", {}).get("resourceRef") + ): return {} try: + group = resource_ref.get("apiVersion", "").split("/")[0] + version = resource_ref.get("apiVersion", "").split("/")[1] + kind = resource_ref.get("kind") + name = resource_ref.get("name") + namespace = resource_ref.get("namespace", self.organization.namespace) + + if not all([group, version, kind, name]): + return {} + + plural = kind.lower() + if not plural.endswith("s"): + plural = f"{plural}s" + + api_instance = client.CustomObjectsApi( + self.context.control_plane.get_kubernetes_client() + ) + + referenced_obj = api_instance.get_namespaced_custom_object( + group=group, + version=version, + namespace=namespace, + plural=plural, + name=name, + ) + + secret_ref = referenced_obj.get("spec", {}).get( + "writeConnectionSecretToRef" + ) + if not secret_ref: + return {} + + secret_name = secret_ref.get("name") + secret_namespace = secret_ref.get("namespace", namespace) + + if not secret_name: + return {} + # Get the secret data v1 = kubernetes.client.CoreV1Api( self.context.control_plane.get_kubernetes_client() ) secret = v1.read_namespaced_secret( - name=secret_name, namespace=secret_ref.get("namespace") + name=secret_name, namespace=secret_namespace ) # Secret data is base64 encoded diff --git a/src/servala/frontend/templates/frontend/organizations/service_instance_detail.html b/src/servala/frontend/templates/frontend/organizations/service_instance_detail.html index b9cf4dc..f83fb84 100644 --- a/src/servala/frontend/templates/frontend/organizations/service_instance_detail.html +++ b/src/servala/frontend/templates/frontend/organizations/service_instance_detail.html @@ -103,58 +103,29 @@

{% translate "Specification" %}

-
-
- -
diff --git a/src/servala/frontend/views/service.py b/src/servala/frontend/views/service.py index b6ecc42..6ee6b1e 100644 --- a/src/servala/frontend/views/service.py +++ b/src/servala/frontend/views/service.py @@ -4,7 +4,6 @@ from django.shortcuts import redirect from django.utils.functional import cached_property from django.views.generic import DetailView, ListView -from servala.core.crd import deslugify from servala.core.models import ( ControlPlaneCRD, Service, @@ -169,116 +168,6 @@ class ServiceInstanceDetailView(OrganizationViewMixin, DetailView): "context__service_definition__service", ) - def get_nested_spec(self): - """ - Organize spec data into fieldsets similar to how the form does it. - """ - spec = self.object.spec or {} - - # Process spec fields - others = [] - nested_fieldsets = {} - - # First pass: organize fields into nested structures - for key, value in spec.items(): - if isinstance(value, dict): - # This is a nested structure - if key not in nested_fieldsets: - nested_fieldsets[key] = { - "title": deslugify(key), - "fields": [], - "fieldsets": {}, - } - - # Process fields in the nested structure - for sub_key, sub_value in value.items(): - if isinstance(sub_value, dict): - # Even deeper nesting - if sub_key not in nested_fieldsets[key]["fieldsets"]: - nested_fieldsets[key]["fieldsets"][sub_key] = { - "title": deslugify(sub_key), - "fields": [], - } - - # Add fields from the deeper level - for leaf_key, leaf_value in sub_value.items(): - nested_fieldsets[key]["fieldsets"][sub_key][ - "fields" - ].append( - { - "key": leaf_key, - "label": deslugify(leaf_key), - "value": leaf_value, - } - ) - else: - # Add field to parent level - nested_fieldsets[key]["fields"].append( - { - "key": sub_key, - "label": deslugify(sub_key), - "value": sub_value, - } - ) - else: - # This is a top-level field - others.append( - { - "key": key, - "label": deslugify(key), - "value": value, - } - ) - - # Second pass: Promote fields based on count - for group_key, group in list(nested_fieldsets.items()): - # Promote single sub-fieldsets to parent - for sub_key, sub_fieldset in list(group["fieldsets"].items()): - if len(sub_fieldset["fields"]) == 1: - field = sub_fieldset["fields"][0] - field["label"] = f"{sub_fieldset['title']}: {field['label']}" - group["fields"].append(field) - del group["fieldsets"][sub_key] - - # Move single-field groups to others - total_fields = len(group["fields"]) - for sub_fieldset in group["fieldsets"].values(): - total_fields += len(sub_fieldset["fields"]) - - if ( - total_fields == 1 - and len(group["fields"]) == 1 - and not group["fieldsets"] - ): - field = group["fields"][0] - field["label"] = f"{group['title']}: {field['label']}" - others.append(field) - del nested_fieldsets[group_key] - elif total_fields == 0: - del nested_fieldsets[group_key] - - fieldsets = [] - if others: - fieldsets.append( - { - "title": "General", - "fields": others, - "fieldsets": {}, - } - ) - # Create fieldsets from the organized data - for group in nested_fieldsets.values(): - fieldsets.append(group) - - return fieldsets - - def get_context_data(self, **kwargs): - """Return service instance for the current organization.""" - context = super().get_context_data(**kwargs) - if self.object.spec: - context["spec_fieldsets"] = self.get_nested_spec() - return context - class ServiceInstanceListView(OrganizationViewMixin, ListView): template_name = "frontend/organizations/service_instances.html"