Rename model, reset migrations
This commit is contained in:
parent
94713a3100
commit
67f4b3ba12
15 changed files with 462 additions and 767 deletions
|
@ -6,6 +6,7 @@ from servala.core.models import (
|
||||||
BillingEntity,
|
BillingEntity,
|
||||||
CloudProvider,
|
CloudProvider,
|
||||||
ControlPlane,
|
ControlPlane,
|
||||||
|
ControlPlaneCRD,
|
||||||
Organization,
|
Organization,
|
||||||
OrganizationMembership,
|
OrganizationMembership,
|
||||||
OrganizationOrigin,
|
OrganizationOrigin,
|
||||||
|
@ -15,7 +16,6 @@ from servala.core.models import (
|
||||||
ServiceDefinition,
|
ServiceDefinition,
|
||||||
ServiceInstance,
|
ServiceInstance,
|
||||||
ServiceOffering,
|
ServiceOffering,
|
||||||
ServiceOfferingControlPlane,
|
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -207,14 +207,14 @@ class ServiceDefinitionAdmin(admin.ModelAdmin):
|
||||||
return ["api_definition"]
|
return ["api_definition"]
|
||||||
|
|
||||||
|
|
||||||
class ServiceOfferingControlPlaneInline(admin.TabularInline):
|
class ControlPlaneCRDInline(admin.TabularInline):
|
||||||
model = ServiceOfferingControlPlane
|
model = ControlPlaneCRD
|
||||||
extra = 1
|
extra = 1
|
||||||
autocomplete_fields = ("control_plane", "service_definition")
|
autocomplete_fields = ("control_plane", "service_definition")
|
||||||
|
|
||||||
|
|
||||||
@admin.register(ServiceOfferingControlPlane)
|
@admin.register(ControlPlaneCRD)
|
||||||
class ServiceOfferingControlPlaneAdmin(admin.ModelAdmin):
|
class ControlPlaneCRDAdmin(admin.ModelAdmin):
|
||||||
list_display = ("service_offering", "control_plane", "service_definition")
|
list_display = ("service_offering", "control_plane", "service_definition")
|
||||||
list_filter = ("service_offering", "control_plane", "service_definition")
|
list_filter = ("service_offering", "control_plane", "service_definition")
|
||||||
search_fields = ("service_offering__service__name", "control_plane__name")
|
search_fields = ("service_offering__service__name", "control_plane__name")
|
||||||
|
@ -263,6 +263,6 @@ class ServiceOfferingAdmin(admin.ModelAdmin):
|
||||||
search_fields = ("description",)
|
search_fields = ("description",)
|
||||||
autocomplete_fields = ("service", "provider")
|
autocomplete_fields = ("service", "provider")
|
||||||
inlines = (
|
inlines = (
|
||||||
ServiceOfferingControlPlaneInline,
|
ControlPlaneCRDInline,
|
||||||
PlanInline,
|
PlanInline,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-16 08:44
|
# Generated by Django 5.2b1 on 2025-03-31 09:20
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
import encrypted_fields.fields
|
||||||
|
import rules.contrib.models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import servala.core.models.service
|
||||||
import servala.core.models.user
|
import servala.core.models.user
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,9 +15,128 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = []
|
dependencies = [
|
||||||
|
("auth", "0012_alter_user_first_name_max_length"),
|
||||||
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="BillingEntity",
|
||||||
|
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")),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"erp_reference",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=100, verbose_name="ERP reference"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Billing entity",
|
||||||
|
"verbose_name_plural": "Billing entities",
|
||||||
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="CloudProvider",
|
||||||
|
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")),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"logo",
|
||||||
|
models.ImageField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
upload_to="public/service_providers",
|
||||||
|
verbose_name="Logo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"external_links",
|
||||||
|
models.JSONField(
|
||||||
|
blank=True, null=True, verbose_name="External links"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Cloud provider",
|
||||||
|
"verbose_name_plural": "Cloud providers",
|
||||||
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="OrganizationOrigin",
|
||||||
|
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")),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Organization origin",
|
||||||
|
"verbose_name_plural": "Organization origins",
|
||||||
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="User",
|
name="User",
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -33,6 +156,14 @@ class Migration(migrations.Migration):
|
||||||
blank=True, null=True, verbose_name="last login"
|
blank=True, null=True, verbose_name="last login"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"created_at",
|
||||||
|
models.DateTimeField(auto_now_add=True, verbose_name="Created"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"updated_at",
|
||||||
|
models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"email",
|
"email",
|
||||||
models.EmailField(
|
models.EmailField(
|
||||||
|
@ -73,105 +204,38 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="Is superuser",
|
verbose_name="Is superuser",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"groups",
|
||||||
|
models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
||||||
|
related_name="user_set",
|
||||||
|
related_query_name="user",
|
||||||
|
to="auth.group",
|
||||||
|
verbose_name="groups",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user_permissions",
|
||||||
|
models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Specific permissions for this user.",
|
||||||
|
related_name="user_set",
|
||||||
|
related_query_name="user",
|
||||||
|
to="auth.permission",
|
||||||
|
verbose_name="user permissions",
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
"verbose_name": "User",
|
"verbose_name": "User",
|
||||||
"verbose_name_plural": "Users",
|
"verbose_name_plural": "Users",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
managers=[
|
managers=[
|
||||||
("objects", servala.core.models.user.UserManager()),
|
("objects", servala.core.models.user.UserManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
|
||||||
name="BillingEntity",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=100, verbose_name="Name")),
|
|
||||||
(
|
|
||||||
"description",
|
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"erp_reference",
|
|
||||||
models.CharField(
|
|
||||||
blank=True, max_length=100, verbose_name="ERP reference"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Billing entity",
|
|
||||||
"verbose_name_plural": "Billing entities",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="CloudProvider",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=100, verbose_name="Name")),
|
|
||||||
(
|
|
||||||
"description",
|
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"logo",
|
|
||||||
models.ImageField(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
upload_to="public/service_providers",
|
|
||||||
verbose_name="Logo",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"external_links",
|
|
||||||
models.JSONField(
|
|
||||||
blank=True, null=True, verbose_name="External links"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Cloud provider",
|
|
||||||
"verbose_name_plural": "Cloud providers",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="OrganizationOrigin",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=100, verbose_name="Name")),
|
|
||||||
(
|
|
||||||
"description",
|
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Organization origin",
|
|
||||||
"verbose_name_plural": "Organization origins",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="ControlPlane",
|
name="ControlPlane",
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -184,16 +248,29 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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")),
|
("name", models.CharField(max_length=100, verbose_name="Name")),
|
||||||
(
|
(
|
||||||
"description",
|
"description",
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"k8s_api_endpoint",
|
"api_credentials",
|
||||||
models.URLField(verbose_name="Kubernetes API endpoint"),
|
encrypted_fields.fields.EncryptedJSONField(
|
||||||
|
help_text="Required fields: certificate-authority-data, server (URL), token",
|
||||||
|
validators=[
|
||||||
|
servala.core.models.service.validate_api_credentials
|
||||||
|
],
|
||||||
|
verbose_name="API credentials",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
("api_credentials", models.JSONField(verbose_name="API credentials")),
|
|
||||||
(
|
(
|
||||||
"cloud_provider",
|
"cloud_provider",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
@ -208,6 +285,7 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Control plane",
|
"verbose_name": "Control plane",
|
||||||
"verbose_name_plural": "Control planes",
|
"verbose_name_plural": "Control planes",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Organization",
|
name="Organization",
|
||||||
|
@ -221,10 +299,35 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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")),
|
("name", models.CharField(max_length=100, verbose_name="Name")),
|
||||||
|
(
|
||||||
|
"namespace",
|
||||||
|
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",
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"billing_entity",
|
"billing_entity",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
on_delete=django.db.models.deletion.PROTECT,
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
related_name="organizations",
|
related_name="organizations",
|
||||||
to="core.billingentity",
|
to="core.billingentity",
|
||||||
|
@ -236,6 +339,7 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Organization",
|
"verbose_name": "Organization",
|
||||||
"verbose_name_plural": "Organizations",
|
"verbose_name_plural": "Organizations",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="OrganizationMembership",
|
name="OrganizationMembership",
|
||||||
|
@ -249,6 +353,14 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"date_joined",
|
"date_joined",
|
||||||
models.DateTimeField(auto_now_add=True, verbose_name="Date joined"),
|
models.DateTimeField(auto_now_add=True, verbose_name="Date joined"),
|
||||||
|
@ -289,6 +401,7 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Organization membership",
|
"verbose_name": "Organization membership",
|
||||||
"verbose_name_plural": "Organization memberships",
|
"verbose_name_plural": "Organization memberships",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="organization",
|
model_name="organization",
|
||||||
|
@ -322,6 +435,14 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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")),
|
("name", models.CharField(max_length=100, verbose_name="Name")),
|
||||||
(
|
(
|
||||||
"description",
|
"description",
|
||||||
|
@ -352,6 +473,7 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Service category",
|
"verbose_name": "Service category",
|
||||||
"verbose_name_plural": "Service categories",
|
"verbose_name_plural": "Service categories",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Service",
|
name="Service",
|
||||||
|
@ -365,7 +487,21 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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")),
|
("name", models.CharField(max_length=100, verbose_name="Name")),
|
||||||
|
(
|
||||||
|
"slug",
|
||||||
|
models.SlugField(
|
||||||
|
max_length=100, unique=True, verbose_name="URL slug"
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"description",
|
"description",
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
|
@ -399,6 +535,57 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Service",
|
"verbose_name": "Service",
|
||||||
"verbose_name_plural": "Services",
|
"verbose_name_plural": "Services",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ServiceDefinition",
|
||||||
|
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")),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"api_definition",
|
||||||
|
models.JSONField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Contains group, version, and kind information",
|
||||||
|
null=True,
|
||||||
|
verbose_name="API Definition",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"service",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="service_definitions",
|
||||||
|
to="core.service",
|
||||||
|
verbose_name="Service",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Service definition",
|
||||||
|
"verbose_name_plural": "Service definitions",
|
||||||
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="ServiceOffering",
|
name="ServiceOffering",
|
||||||
|
@ -413,16 +600,16 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"description",
|
"created_at",
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
models.DateTimeField(auto_now_add=True, verbose_name="Created"),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"control_plane",
|
"updated_at",
|
||||||
models.ManyToManyField(
|
models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
||||||
related_name="offerings",
|
),
|
||||||
to="core.controlplane",
|
(
|
||||||
verbose_name="Control planes",
|
"description",
|
||||||
),
|
models.TextField(blank=True, verbose_name="Description"),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"provider",
|
"provider",
|
||||||
|
@ -447,6 +634,7 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Service offering",
|
"verbose_name": "Service offering",
|
||||||
"verbose_name_plural": "Service offerings",
|
"verbose_name_plural": "Service offerings",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Plan",
|
name="Plan",
|
||||||
|
@ -460,6 +648,14 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
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")),
|
("name", models.CharField(max_length=100, verbose_name="Name")),
|
||||||
(
|
(
|
||||||
"description",
|
"description",
|
||||||
|
@ -493,5 +689,142 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name": "Plan",
|
"verbose_name": "Plan",
|
||||||
"verbose_name_plural": "Plans",
|
"verbose_name_plural": "Plans",
|
||||||
},
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ControlPlaneCRD",
|
||||||
|
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"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"control_plane",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="offering_connections",
|
||||||
|
to="core.controlplane",
|
||||||
|
verbose_name="Control plane",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"service_definition",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
|
related_name="offering_control_planes",
|
||||||
|
to="core.servicedefinition",
|
||||||
|
verbose_name="Service definition",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"service_offering",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="control_plane_connections",
|
||||||
|
to="core.serviceoffering",
|
||||||
|
verbose_name="Service offering",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Service offering control plane connection",
|
||||||
|
"verbose_name_plural": "Service offering control planes connections",
|
||||||
|
"unique_together": {("service_offering", "control_plane")},
|
||||||
|
},
|
||||||
|
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
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=63,
|
||||||
|
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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("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.controlplanecrd",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"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),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-17 06:19
|
|
||||||
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0001_initial"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="billingentity",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="billingentity",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organization",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organization",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organizationmembership",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organizationmembership",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organizationorigin",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organizationorigin",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="user",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="user",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,25 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-20 08:12
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0002_billingentity_created_at_billingentity_updated_at_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="organization",
|
|
||||||
name="billing_entity",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.PROTECT,
|
|
||||||
related_name="organizations",
|
|
||||||
to="core.billingentity",
|
|
||||||
verbose_name="Billing entity",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,46 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-24 06:33
|
|
||||||
|
|
||||||
import encrypted_fields.fields
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("auth", "0012_alter_user_first_name_max_length"),
|
|
||||||
("core", "0003_billing_entity_nullable"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="user",
|
|
||||||
name="groups",
|
|
||||||
field=models.ManyToManyField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
|
||||||
related_name="user_set",
|
|
||||||
related_query_name="user",
|
|
||||||
to="auth.group",
|
|
||||||
verbose_name="groups",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="user",
|
|
||||||
name="user_permissions",
|
|
||||||
field=models.ManyToManyField(
|
|
||||||
blank=True,
|
|
||||||
help_text="Specific permissions for this user.",
|
|
||||||
related_name="user_set",
|
|
||||||
related_query_name="user",
|
|
||||||
to="auth.permission",
|
|
||||||
verbose_name="user permissions",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="controlplane",
|
|
||||||
name="api_credentials",
|
|
||||||
field=encrypted_fields.fields.EncryptedJSONField(
|
|
||||||
verbose_name="API credentials"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,29 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-24 10:27
|
|
||||||
|
|
||||||
import encrypted_fields.fields
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
import servala.core.models.service
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0004_encrypt_api_credentials"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name="controlplane",
|
|
||||||
name="k8s_api_endpoint",
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="controlplane",
|
|
||||||
name="api_credentials",
|
|
||||||
field=encrypted_fields.fields.EncryptedJSONField(
|
|
||||||
help_text="Required fields: certificate-authority-data, server (URL), token",
|
|
||||||
validators=[servala.core.models.service.validate_api_credentials],
|
|
||||||
verbose_name="API credentials",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-24 14:29
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0005_remove_controlplane_k8s_api_endpoint"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="service",
|
|
||||||
name="slug",
|
|
||||||
field=models.SlugField(
|
|
||||||
default="slug", max_length=100, unique=True, verbose_name="URL slug"
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,115 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-25 11:02
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0006_service_slug"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name="serviceoffering",
|
|
||||||
name="control_plane",
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="ServiceDefinition",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=100, verbose_name="Name")),
|
|
||||||
(
|
|
||||||
"description",
|
|
||||||
models.TextField(blank=True, verbose_name="Description"),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"api_definition",
|
|
||||||
models.JSONField(
|
|
||||||
blank=True,
|
|
||||||
help_text="Contains group, version, and kind information",
|
|
||||||
null=True,
|
|
||||||
verbose_name="API Definition",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"service",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="service_definitions",
|
|
||||||
to="core.service",
|
|
||||||
verbose_name="Service",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Service definition",
|
|
||||||
"verbose_name_plural": "Service definitions",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="ServiceOfferingControlPlane",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"control_plane",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="offering_connections",
|
|
||||||
to="core.controlplane",
|
|
||||||
verbose_name="Control plane",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"service_definition",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.PROTECT,
|
|
||||||
related_name="offering_control_planes",
|
|
||||||
to="core.servicedefinition",
|
|
||||||
verbose_name="Service definition",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"service_offering",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="control_plane_connections",
|
|
||||||
to="core.serviceoffering",
|
|
||||||
verbose_name="Service offering",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Service offering control plane connection",
|
|
||||||
"verbose_name_plural": "Service offering control planes connections",
|
|
||||||
"unique_together": {("service_offering", "control_plane")},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="serviceoffering",
|
|
||||||
name="control_planes",
|
|
||||||
field=models.ManyToManyField(
|
|
||||||
related_name="offerings",
|
|
||||||
through="core.ServiceOfferingControlPlane",
|
|
||||||
to="core.controlplane",
|
|
||||||
verbose_name="Control planes",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,134 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-26 14:54
|
|
||||||
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0007_service_definition"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="cloudprovider",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="cloudprovider",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="controlplane",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="controlplane",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="plan",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="plan",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="service",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="service",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="servicecategory",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="servicecategory",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="servicedefinition",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="servicedefinition",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="serviceoffering",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="serviceoffering",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="serviceofferingcontrolplane",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
verbose_name="Created",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="serviceofferingcontrolplane",
|
|
||||||
name="updated_at",
|
|
||||||
field=models.DateTimeField(auto_now=True, verbose_name="Last updated"),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,34 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-28 09:39
|
|
||||||
|
|
||||||
import django.core.validators
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0008_created_and_updated"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="organization",
|
|
||||||
name="namespace",
|
|
||||||
field=models.CharField(
|
|
||||||
default="namespace",
|
|
||||||
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_namespace",
|
|
||||||
message='Namespace 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",
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,117 +0,0 @@
|
||||||
# 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),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,34 +0,0 @@
|
||||||
# Generated by Django 5.2b1 on 2025-03-28 11:51
|
|
||||||
|
|
||||||
import django.core.validators
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("core", "0010_service_instance"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="servicecategory",
|
|
||||||
name="name",
|
|
||||||
field=models.CharField(max_length=100, verbose_name="Name"),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="serviceinstance",
|
|
||||||
name="name",
|
|
||||||
field=models.CharField(
|
|
||||||
max_length=63,
|
|
||||||
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",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -8,13 +8,13 @@ from .organization import (
|
||||||
from .service import (
|
from .service import (
|
||||||
CloudProvider,
|
CloudProvider,
|
||||||
ControlPlane,
|
ControlPlane,
|
||||||
|
ControlPlaneCRD,
|
||||||
Plan,
|
Plan,
|
||||||
Service,
|
Service,
|
||||||
ServiceCategory,
|
ServiceCategory,
|
||||||
ServiceDefinition,
|
ServiceDefinition,
|
||||||
ServiceInstance,
|
ServiceInstance,
|
||||||
ServiceOffering,
|
ServiceOffering,
|
||||||
ServiceOfferingControlPlane,
|
|
||||||
)
|
)
|
||||||
from .user import User
|
from .user import User
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ __all__ = [
|
||||||
"BillingEntity",
|
"BillingEntity",
|
||||||
"CloudProvider",
|
"CloudProvider",
|
||||||
"ControlPlane",
|
"ControlPlane",
|
||||||
|
"ControlPlaneCRD",
|
||||||
"Organization",
|
"Organization",
|
||||||
"OrganizationMembership",
|
"OrganizationMembership",
|
||||||
"OrganizationOrigin",
|
"OrganizationOrigin",
|
||||||
|
@ -32,6 +33,5 @@ __all__ = [
|
||||||
"ServiceInstance",
|
"ServiceInstance",
|
||||||
"ServiceDefinition",
|
"ServiceDefinition",
|
||||||
"ServiceOffering",
|
"ServiceOffering",
|
||||||
"ServiceOfferingControlPlane",
|
|
||||||
"User",
|
"User",
|
||||||
]
|
]
|
||||||
|
|
|
@ -121,6 +121,12 @@ class ControlPlane(ServalaModelMixin, models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_definitions(self):
|
||||||
|
return ServiceDefinition.objects.filter(
|
||||||
|
offering_control_planes__control_plane=self
|
||||||
|
).distinct()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def kubernetes_config(self):
|
def kubernetes_config(self):
|
||||||
conf = kubernetes.client.Configuration()
|
conf = kubernetes.client.Configuration()
|
||||||
|
@ -288,10 +294,10 @@ class ServiceDefinition(ServalaModelMixin, models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class ServiceOfferingControlPlane(ServalaModelMixin, models.Model):
|
class ControlPlaneCRD(ServalaModelMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
Each combination of ServiceOffering and ControlPlane can have a different
|
Each combination of ServiceOffering and ControlPlane can have a different
|
||||||
ServiceDefinition, which is here modeled as the "through" model.
|
ServiceDefinition, which is here modeled as basically a "through" model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
service_offering = models.ForeignKey(
|
service_offering = models.ForeignKey(
|
||||||
|
@ -391,12 +397,6 @@ class ServiceOffering(ServalaModelMixin, models.Model):
|
||||||
related_name="offerings",
|
related_name="offerings",
|
||||||
verbose_name=_("Provider"),
|
verbose_name=_("Provider"),
|
||||||
)
|
)
|
||||||
control_planes = models.ManyToManyField(
|
|
||||||
to="ControlPlane",
|
|
||||||
through="ServiceOfferingControlPlane",
|
|
||||||
related_name="offerings",
|
|
||||||
verbose_name=_("Control planes"),
|
|
||||||
)
|
|
||||||
description = models.TextField(blank=True, verbose_name=_("Description"))
|
description = models.TextField(blank=True, verbose_name=_("Description"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -408,6 +408,12 @@ class ServiceOffering(ServalaModelMixin, models.Model):
|
||||||
service_name=self.service.name, provider_name=self.provider.name
|
service_name=self.service.name, provider_name=self.provider.name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def control_planes(self):
|
||||||
|
return ControlPlane.objects.filter(
|
||||||
|
offering_connections__service_offering=self
|
||||||
|
).distinct()
|
||||||
|
|
||||||
|
|
||||||
class ServiceInstance(ServalaModelMixin, models.Model):
|
class ServiceInstance(ServalaModelMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -433,7 +439,7 @@ class ServiceInstance(ServalaModelMixin, models.Model):
|
||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
context = models.ForeignKey(
|
context = models.ForeignKey(
|
||||||
to="core.ServiceOfferingControlPlane",
|
to="core.ControlPlaneCRD",
|
||||||
related_name="service_instances",
|
related_name="service_instances",
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,10 +4,10 @@ from django.utils.functional import cached_property
|
||||||
from django.views.generic import DetailView, ListView
|
from django.views.generic import DetailView, ListView
|
||||||
|
|
||||||
from servala.core.models import (
|
from servala.core.models import (
|
||||||
|
ControlPlaneCRD,
|
||||||
Service,
|
Service,
|
||||||
ServiceInstance,
|
ServiceInstance,
|
||||||
ServiceOffering,
|
ServiceOffering,
|
||||||
ServiceOfferingControlPlane,
|
|
||||||
)
|
)
|
||||||
from servala.frontend.forms.service import ControlPlaneSelectForm, ServiceFilterForm
|
from servala.frontend.forms.service import ControlPlaneSelectForm, ServiceFilterForm
|
||||||
from servala.frontend.views.mixins import HtmxViewMixin, OrganizationViewMixin
|
from servala.frontend.views.mixins import HtmxViewMixin, OrganizationViewMixin
|
||||||
|
@ -89,12 +89,12 @@ class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView
|
||||||
@cached_property
|
@cached_property
|
||||||
def context_object(self):
|
def context_object(self):
|
||||||
if self.request.method == "POST":
|
if self.request.method == "POST":
|
||||||
return ServiceOfferingControlPlane.objects.filter(
|
return ControlPlaneCRD.objects.filter(
|
||||||
pk=self.request.POST.get("context"),
|
pk=self.request.POST.get("context"),
|
||||||
# Make sure we don’t use a malicious ID
|
# Make sure we don’t use a malicious ID
|
||||||
control_plane__in=self.planes,
|
control_plane__in=self.planes,
|
||||||
).first()
|
).first()
|
||||||
return ServiceOfferingControlPlane.objects.filter(
|
return ControlPlaneCRD.objects.filter(
|
||||||
control_plane=self.selected_plane, service_offering=self.object
|
control_plane=self.selected_plane, service_offering=self.object
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue