Disk size SI units #302
3 changed files with 67 additions and 37 deletions
|
|
@ -239,9 +239,9 @@ The Servala Team"""
|
|||
service_offering = ServiceOffering.objects.get(
|
||||
osb_plan_id=plan_id, service=service
|
||||
)
|
||||
except Service.DoesNotExist:
|
||||
except Service.DoesNotExist: # pragma: no-cover
|
||||
return self._error(f"Unknown service_id: {service_id}")
|
||||
except ServiceOffering.DoesNotExist:
|
||||
except ServiceOffering.DoesNotExist: # pragma: no-cover
|
||||
return self._error(
|
||||
f"Unknown plan_id: {plan_id} for service_id: {service_id}"
|
||||
)
|
||||
|
|
@ -284,7 +284,7 @@ The Servala Team"""
|
|||
|
||||
if service_instance:
|
||||
organization = service_instance.organization
|
||||
except Exception:
|
||||
except Exception: # pragma: no cover
|
||||
pass
|
||||
|
||||
description_parts = [f"Action: {action}", f"Service: {service.name}"]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from contextlib import suppress
|
||||
|
||||
from django import forms
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.forms.models import ModelForm, ModelFormMetaclass
|
||||
|
|
@ -335,6 +337,19 @@ class CustomFormMixin(FormGeneratorMixin):
|
|||
if field_type == "number":
|
||||
min_val = field_config.get("min_value")
|
||||
max_val = field_config.get("max_value")
|
||||
unit = field_config.get("addon_text")
|
||||
|
||||
if unit:
|
||||
field.widget = NumberInputWithAddon(addon_text=unit)
|
||||
field.addon_text = unit
|
||||
value = self.initial.get(field_name)
|
||||
if value and isinstance(value, str) and value.endswith(unit):
|
||||
numeric_value = value[: -len(unit)]
|
||||
with suppress(ValueError):
|
||||
if "." in numeric_value:
|
||||
self.initial[field_name] = float(numeric_value)
|
||||
else:
|
||||
self.initial[field_name] = int(numeric_value)
|
||||
|
||||
validators = []
|
||||
if min_val is not None:
|
||||
|
|
@ -406,6 +421,11 @@ class CustomFormMixin(FormGeneratorMixin):
|
|||
|
||||
mapping = field_name
|
||||
value = self.cleaned_data.get(field_name)
|
||||
field = self.fields[field_name]
|
||||
|
||||
if addon_text := getattr(field, "addon_text", None):
|
||||
value = f"{value}{addon_text}"
|
||||
|
||||
parts = mapping.split(".")
|
||||
current = nested
|
||||
for part in parts[:-1]:
|
||||
|
|
|
|||
|
|
@ -8,28 +8,7 @@ from servala.core.crd import generate_custom_form_class
|
|||
from servala.core.crd.forms import DEFAULT_FIELD_CONFIGS, MANDATORY_FIELDS
|
||||
from servala.core.forms import ServiceDefinitionAdminForm
|
||||
from servala.core.models import ControlPlaneCRD
|
||||
|
||||
|
||||
def test_custom_model_form_class_is_none_when_no_form_config():
|
||||
crd = Mock(spec=ControlPlaneCRD)
|
||||
service_def = Mock()
|
||||
service_def.form_config = None
|
||||
crd.service_definition = service_def
|
||||
crd.django_model = Mock()
|
||||
|
||||
if not (
|
||||
crd.django_model
|
||||
and crd.service_definition
|
||||
and crd.service_definition.form_config
|
||||
and crd.service_definition.form_config.get("fieldsets")
|
||||
):
|
||||
result = None
|
||||
else:
|
||||
result = generate_custom_form_class(
|
||||
crd.service_definition.form_config, crd.django_model
|
||||
)
|
||||
|
||||
assert result is None
|
||||
from servala.frontend.forms.widgets import NumberInputWithAddon
|
||||
|
||||
|
||||
def test_custom_model_form_class_returns_class_when_form_config_exists():
|
||||
|
|
@ -60,15 +39,6 @@ def test_custom_model_form_class_returns_class_when_form_config_exists():
|
|||
app_label = "test"
|
||||
|
||||
crd.django_model = TestModel
|
||||
|
||||
if not (
|
||||
crd.django_model
|
||||
and crd.service_definition
|
||||
and crd.service_definition.form_config
|
||||
and crd.service_definition.form_config.get("fieldsets")
|
||||
):
|
||||
result = None
|
||||
else:
|
||||
result = generate_custom_form_class(
|
||||
crd.service_definition.form_config, crd.django_model
|
||||
)
|
||||
|
|
@ -1084,3 +1054,43 @@ def test_empty_values_dont_override_default_configs():
|
|||
assert name_field.max_length == DEFAULT_FIELD_CONFIGS["name"]["max_length"]
|
||||
|
||||
assert name_field.required is False # Was overridden by explicit False
|
||||
|
||||
|
||||
def test_number_field_with_addon_text_roundtrip():
|
||||
class TestModel(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
disk_size = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
app_label = "test"
|
||||
|
||||
form_config = {
|
||||
"fieldsets": [
|
||||
{
|
||||
"fields": [
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Name",
|
||||
"controlplane_field_mapping": "name",
|
||||
"required": True,
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"label": "Disk Size",
|
||||
"controlplane_field_mapping": "disk_size",
|
||||
"addon_text": "Gi",
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
form_class = generate_custom_form_class(form_config, TestModel)
|
||||
form = form_class(initial={"name": "test-instance", "disk_size": "25Gi"})
|
||||
|
||||
assert form.initial["disk_size"] == 25
|
||||
form = form_class(data={"name": "test-instance", "disk_size": "25"})
|
||||
form.fields["context"].required = False
|
||||
assert form.is_valid(), f"Form should be valid but has errors: {form.errors}"
|
||||
nested_data = form.get_nested_data()
|
||||
assert nested_data["disk_size"] == "25Gi"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue