From ee8fba07efe3774376c6d2af84900312c8c27f84 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Tue, 25 Mar 2025 18:30:08 +0100 Subject: [PATCH] Use serialized data for schema --- src/servala/core/crd.py | 95 ++++++++++++++++++++---------- src/servala/core/models/service.py | 30 +++++++++- 2 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/servala/core/crd.py b/src/servala/core/crd.py index 5a3803c..bf22bcc 100644 --- a/src/servala/core/crd.py +++ b/src/servala/core/crd.py @@ -1,52 +1,80 @@ +import re + from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator from django.db import models from django.forms.models import ModelForm, ModelFormMetaclass +from django.utils.translation import gettext_lazy as _ -def generate_django_model(crd, group, version, kind): +def generate_django_model(schema, group, version, kind): """ Generates a virtual Django model from a Kubernetes CRD's OpenAPI v3 schema. """ - schema = crd.spec.versions[0].schema.open_apiv3_schema - properties = schema.properties - required_fields = schema.required + spec = schema["properties"].get("spec") or {} + # defaults = {"apiVersion": f"{group}/{version}", "kind": kind} + model_fields = {"__module__": "crd_models"} - - defaults = {"apiVersion": f"{group}/{version}", "kind": kind} - - for prop_name, prop_schema in properties.items(): - is_required = prop_name in required_fields - field = get_django_field( - prop_schema, is_required, default=defaults.get(prop_name) - ) - model_fields[prop_name] = field + model_fields.update(build_object_fields(spec, "spec")) meta_class = type("Meta", (), {"app_label": "crd_models"}) model_fields["Meta"] = meta_class # create the model class - model_name = crd.spec.names.kind + model_name = kind model_class = type(model_name, (models.Model,), model_fields) return model_class -def get_django_field(prop_schema, is_required=False, default=None): - field_type = prop_schema.type or "string" - format = prop_schema.format +def build_object_fields(schema, name, verbose_name_prefix=None): + required_fields = schema.get("required", []) + properties = schema.get("properties", {}) + fields = {} + + for field_name, field_schema in properties.items(): + is_required = field_name in required_fields + full_name = f"{name}.{field_name}" + result = get_django_field( + field_schema, + is_required, + field_name, + full_name, + verbose_name_prefix=verbose_name_prefix, + ) + if isinstance(result, dict): + fields.update(result) + else: + fields[full_name] = result + return fields + + +def deslugify(title): + if "_" in title: + title.replace("_", " ") + return title.title() + return re.sub(r"(?