diff --git a/src/servala/core/migrations/0010_service_instance.py b/src/servala/core/migrations/0010_service_instance.py new file mode 100644 index 0000000..9989650 --- /dev/null +++ b/src/servala/core/migrations/0010_service_instance.py @@ -0,0 +1,117 @@ +# Generated by Django 5.2b1 on 2025-03-28 10:29 + +import django.core.validators +import django.db.models.deletion +import rules.contrib.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0009_organization_namespace"), + ] + + operations = [ + migrations.AlterField( + model_name="organization", + name="namespace", + field=models.CharField( + help_text="This namespace will be used for all Kubernetes resources. Cannot be changed after creation.", + max_length=63, + unique=True, + validators=[ + django.core.validators.RegexValidator( + code="invalid_kubernetes_name", + message='Name must consist of lowercase alphanumeric characters or "-", must start and end with an alphanumeric character.', + regex="^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", + ) + ], + verbose_name="Kubernetes Namespace", + ), + ), + migrations.AlterField( + model_name="servicecategory", + name="name", + field=models.CharField( + max_length=100, + validators=[ + django.core.validators.RegexValidator( + code="invalid_kubernetes_name", + message='Name must consist of lowercase alphanumeric characters or "-", must start and end with an alphanumeric character.', + regex="^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", + ) + ], + verbose_name="Name", + ), + ), + migrations.CreateModel( + name="ServiceInstance", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created_at", + models.DateTimeField(auto_now_add=True, verbose_name="Created"), + ), + ( + "updated_at", + models.DateTimeField(auto_now=True, verbose_name="Last updated"), + ), + ("name", models.CharField(max_length=100, verbose_name="Name")), + ("is_deleted", models.BooleanField(default=False)), + ("deleted_at", models.DateTimeField(blank=True, null=True)), + ( + "context", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="service_instances", + to="core.serviceofferingcontrolplane", + ), + ), + ( + "created_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "deleted_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "organization", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="service_instances", + to="core.organization", + verbose_name="Organization", + ), + ), + ], + options={ + "verbose_name": "Service instance", + "verbose_name_plural": "Service instances", + "unique_together": {("name", "organization", "context")}, + }, + bases=(rules.contrib.models.RulesModelMixin, models.Model), + ), + ] diff --git a/src/servala/core/models/__init__.py b/src/servala/core/models/__init__.py index 6d5b24d..722aabd 100644 --- a/src/servala/core/models/__init__.py +++ b/src/servala/core/models/__init__.py @@ -12,6 +12,7 @@ from .service import ( Service, ServiceCategory, ServiceDefinition, + ServiceInstance, ServiceOffering, ServiceOfferingControlPlane, ) @@ -28,6 +29,7 @@ __all__ = [ "Plan", "Service", "ServiceCategory", + "ServiceInstance", "ServiceDefinition", "ServiceOffering", "ServiceOfferingControlPlane",