Compare commits
2 commits
03989d24d4
...
a3d709aa3c
Author | SHA1 | Date | |
---|---|---|---|
a3d709aa3c | |||
e85f1fc5f4 |
6 changed files with 53 additions and 13 deletions
|
@ -50,7 +50,6 @@ erDiagram
|
||||||
ControlPlane {
|
ControlPlane {
|
||||||
string name
|
string name
|
||||||
string description
|
string description
|
||||||
string k8s_api_endpoint
|
|
||||||
json api_credentials
|
json api_credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,16 +112,16 @@ class CloudProviderAdmin(admin.ModelAdmin):
|
||||||
@admin.register(ControlPlane)
|
@admin.register(ControlPlane)
|
||||||
class ControlPlaneAdmin(admin.ModelAdmin):
|
class ControlPlaneAdmin(admin.ModelAdmin):
|
||||||
form = ControlPlaneAdminForm
|
form = ControlPlaneAdminForm
|
||||||
list_display = ("name", "cloud_provider", "k8s_api_endpoint")
|
list_display = ("name", "cloud_provider")
|
||||||
list_filter = ("cloud_provider",)
|
list_filter = ("cloud_provider",)
|
||||||
search_fields = ("name", "description", "k8s_api_endpoint")
|
search_fields = ("name", "description")
|
||||||
autocomplete_fields = ("cloud_provider",)
|
autocomplete_fields = ("cloud_provider",)
|
||||||
actions = ["test_kubernetes_connection"]
|
actions = ["test_kubernetes_connection"]
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
{"fields": ("name", "description", "k8s_api_endpoint", "cloud_provider")},
|
{"fields": ("name", "description", "cloud_provider")},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
_("API Credentials"),
|
_("API Credentials"),
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# 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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -89,7 +89,6 @@ def validate_api_credentials(value):
|
||||||
class ControlPlane(models.Model):
|
class ControlPlane(models.Model):
|
||||||
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
||||||
description = models.TextField(blank=True, verbose_name=_("Description"))
|
description = models.TextField(blank=True, verbose_name=_("Description"))
|
||||||
k8s_api_endpoint = models.URLField(verbose_name=_("Kubernetes API endpoint"))
|
|
||||||
# Either contains the fields "certificate_authority_data", "server" and "token", or is empty
|
# Either contains the fields "certificate_authority_data", "server" and "token", or is empty
|
||||||
api_credentials = EncryptedJSONField(
|
api_credentials = EncryptedJSONField(
|
||||||
verbose_name=_("API credentials"),
|
verbose_name=_("API credentials"),
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
import pytest
|
import pytest
|
||||||
from servala.core.models import Organization, OrganizationMembership, User, OrganizationOrigin
|
|
||||||
|
|
||||||
|
from servala.core.models import (
|
||||||
|
Organization,
|
||||||
|
OrganizationMembership,
|
||||||
|
OrganizationOrigin,
|
||||||
|
User,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def origin():
|
def origin():
|
||||||
return OrganizationOrigin.objects.create(name="TESTORIGIN")
|
return OrganizationOrigin.objects.create(name="TESTORIGIN")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def organization(origin):
|
def organization(origin):
|
||||||
return Organization.objects.create(name="Test Org", origin=origin)
|
return Organization.objects.create(name="Test Org", origin=origin)
|
||||||
|
@ -16,9 +22,11 @@ def organization(origin):
|
||||||
def other_organization(origin):
|
def other_organization(origin):
|
||||||
return Organization.objects.create(name="Test Org Alternate", origin=origin)
|
return Organization.objects.create(name="Test Org Alternate", origin=origin)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def org_owner(organization):
|
def org_owner(organization):
|
||||||
user = User.objects.create(email="user@example.org", password="example")
|
user = User.objects.create(email="user@example.org", password="example")
|
||||||
OrganizationMembership.objects.create(organization=organization, user=user, role="owner")
|
OrganizationMembership.objects.create(
|
||||||
|
organization=organization, user=user, role="owner"
|
||||||
|
)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("url,redirect", (
|
@pytest.mark.parametrize(
|
||||||
("/", "/accounts/login/?next=/"),
|
"url,redirect",
|
||||||
("/accounts/profile/", "/accounts/login/?next=/accounts/profile/")
|
(
|
||||||
))
|
("/", "/accounts/login/?next=/"),
|
||||||
|
("/accounts/profile/", "/accounts/login/?next=/accounts/profile/"),
|
||||||
|
),
|
||||||
|
)
|
||||||
def test_root_view_redirects_valid_urls(client, url, redirect):
|
def test_root_view_redirects_valid_urls(client, url, redirect):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
|
@ -33,7 +36,9 @@ def test_user_cannot_see_other_organization(client, org_owner, other_organizatio
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_organization_linked_in_sidebar(client, org_owner, organization, other_organization):
|
def test_organization_linked_in_sidebar(
|
||||||
|
client, org_owner, organization, other_organization
|
||||||
|
):
|
||||||
client.force_login(org_owner)
|
client.force_login(org_owner)
|
||||||
response = client.get("/", follow=True)
|
response = client.get("/", follow=True)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue