From 6c6fb06a01b41143cb7ed8a7f4bbae4add2ee161 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Thu, 26 Jun 2025 17:28:59 +0200 Subject: [PATCH 1/2] Prune empty values before creating instance --- src/servala/core/models/service.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index e87a972..a35e493 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -305,6 +305,31 @@ def validate_api_definition(value): return validate_dict(value, required_fields) +def prune_empty_data(data): + """ + Recursively remove empty values from dictionaries and lists. + Empty values include: None, empty strings, empty lists, empty dicts. + """ + + def is_empty(value): + return value is None or value == "" or value == [] or value == {} + + if isinstance(data, dict): + return { + key: pruned_value + for key, value in data.items() + if not is_empty(pruned_value := prune_empty_data(value)) + } + elif isinstance(data, list): + return [ + pruned_item + for item in data + if not is_empty(pruned_item := prune_empty_data(item)) + ] + else: + return data + + class ServiceDefinition(ServalaModelMixin, models.Model): """ Configuration/service implementation: contains information on which @@ -588,6 +613,7 @@ class ServiceInstance(ServalaModelMixin, models.Model): try: spec_data = spec_data or {} + spec_data = prune_empty_data(spec_data) if "writeConnectionSecretToRef" not in spec_data: spec_data["writeConnectionSecretToRef"] = {} From 3236fc7b212f78711d83c4884fe2e457a7133282 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Thu, 26 Jun 2025 17:32:56 +0200 Subject: [PATCH 2/2] Prune empty data from instance updates aswell Closes #124 --- src/servala/core/models/service.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index a35e493..362661b 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -593,6 +593,16 @@ class ServiceInstance(ServalaModelMixin, models.Model): if key in attrs: delattr(self, key) + @classmethod + def _prepare_spec_data(cls, spec_data): + """ + Prepare spec data by pruning empty values and ensuring required fields. + This method centralizes spec data processing to ensure consistency. + """ + spec_data = spec_data or {} + spec_data = prune_empty_data(spec_data) + return spec_data + @classmethod def create_instance(cls, name, organization, context, created_by, spec_data): # Ensure the namespace exists @@ -612,8 +622,8 @@ class ServiceInstance(ServalaModelMixin, models.Model): ) try: - spec_data = spec_data or {} - spec_data = prune_empty_data(spec_data) + spec_data = cls._prepare_spec_data(spec_data) + if "writeConnectionSecretToRef" not in spec_data: spec_data["writeConnectionSecretToRef"] = {} @@ -655,6 +665,7 @@ class ServiceInstance(ServalaModelMixin, models.Model): def update_spec(self, spec_data, updated_by): try: + spec_data = self._prepare_spec_data(spec_data) api_instance = self.context.control_plane.custom_objects_api patch_body = {"spec": spec_data}