WIP
This commit is contained in:
parent
e70a0584c9
commit
a7a5b5c8ea
43 changed files with 5531 additions and 9 deletions
133
tests/test_control_plane_models.py
Normal file
133
tests/test_control_plane_models.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from django.db import IntegrityError
|
||||
|
||||
from control_plane.models import Deployment
|
||||
from control_plane.models import HostedSite
|
||||
from control_plane.models import RuntimeService
|
||||
from control_plane.models import RuntimeServiceKind
|
||||
from control_plane.models import Tenant
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_deployment_builds_uv_gunicorn_command() -> None:
|
||||
"""Deployment model should expose a reusable Django launch command."""
|
||||
tenant = Tenant.objects.create(slug="acme", display_name="Acme")
|
||||
hosted_site = HostedSite.objects.create(
|
||||
tenant=tenant,
|
||||
slug="portal",
|
||||
display_name="Portal",
|
||||
wsgi_module="portal.wsgi:application",
|
||||
)
|
||||
deployment = Deployment.objects.create(
|
||||
hosted_site=hosted_site,
|
||||
idempotency_key="deploy-001",
|
||||
source_sha256="a" * 64,
|
||||
guest_port=8010,
|
||||
)
|
||||
|
||||
assert deployment.build_django_launch_command() == (
|
||||
"uv",
|
||||
"run",
|
||||
"gunicorn",
|
||||
"--bind",
|
||||
"0.0.0.0:8010",
|
||||
"--workers",
|
||||
"2",
|
||||
"--access-logfile",
|
||||
"-",
|
||||
"--error-logfile",
|
||||
"-",
|
||||
"--capture-output",
|
||||
"--graceful-timeout",
|
||||
"30",
|
||||
"--timeout",
|
||||
"60",
|
||||
"portal.wsgi:application",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_runtime_service_enforces_one_service_kind_per_deployment() -> None:
|
||||
"""A deployment should not create duplicate PostgreSQL or Redis resources."""
|
||||
tenant = Tenant.objects.create(slug="acme", display_name="Acme")
|
||||
hosted_site = HostedSite.objects.create(
|
||||
tenant=tenant,
|
||||
slug="portal",
|
||||
display_name="Portal",
|
||||
wsgi_module="portal.wsgi:application",
|
||||
)
|
||||
deployment = Deployment.objects.create(
|
||||
hosted_site=hosted_site,
|
||||
idempotency_key="deploy-002",
|
||||
source_sha256="b" * 64,
|
||||
)
|
||||
RuntimeService.objects.create(
|
||||
deployment=deployment,
|
||||
kind=RuntimeServiceKind.POSTGRESQL,
|
||||
container_name="postgres-acme-portal",
|
||||
network_name="net-acme-portal",
|
||||
hostname="postgres.internal",
|
||||
image_reference="docker.io/library/postgres:17-alpine",
|
||||
internal_port=5432,
|
||||
connection_username="portal",
|
||||
connection_database="portal",
|
||||
connection_secret_ref="secret://postgres/acme/portal",
|
||||
)
|
||||
|
||||
with pytest.raises(IntegrityError):
|
||||
RuntimeService.objects.create(
|
||||
deployment=deployment,
|
||||
kind=RuntimeServiceKind.POSTGRESQL,
|
||||
container_name="postgres-acme-portal-2",
|
||||
network_name="net-acme-portal",
|
||||
hostname="postgres-2.internal",
|
||||
image_reference="docker.io/library/postgres:17-alpine",
|
||||
internal_port=5432,
|
||||
connection_username="portal",
|
||||
connection_database="portal",
|
||||
connection_secret_ref="secret://postgres/acme/portal-2",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_deployment_can_seed_missing_test_runtime_services() -> None:
|
||||
"""Deployment should create one PostgreSQL and one Redis runtime service idempotently."""
|
||||
tenant = Tenant.objects.create(slug="acme", display_name="Acme")
|
||||
hosted_site = HostedSite.objects.create(
|
||||
tenant=tenant,
|
||||
slug="portal",
|
||||
display_name="Portal",
|
||||
wsgi_module="portal.wsgi:application",
|
||||
)
|
||||
deployment = Deployment.objects.create(
|
||||
hosted_site=hosted_site,
|
||||
idempotency_key="deploy-003",
|
||||
source_sha256="d" * 64,
|
||||
)
|
||||
|
||||
created_services = deployment.ensure_test_runtime_services()
|
||||
|
||||
assert {runtime_service.kind for runtime_service in created_services} == {
|
||||
RuntimeServiceKind.POSTGRESQL.value,
|
||||
RuntimeServiceKind.REDIS.value,
|
||||
}
|
||||
assert RuntimeService.objects.filter(deployment=deployment).count() == 2
|
||||
|
||||
postgres_service = RuntimeService.objects.get(
|
||||
deployment=deployment,
|
||||
kind=RuntimeServiceKind.POSTGRESQL,
|
||||
)
|
||||
redis_service = RuntimeService.objects.get(
|
||||
deployment=deployment,
|
||||
kind=RuntimeServiceKind.REDIS,
|
||||
)
|
||||
|
||||
assert postgres_service.connection_username
|
||||
assert postgres_service.connection_database == postgres_service.connection_username
|
||||
assert postgres_service.internal_port == 5432
|
||||
assert not redis_service.connection_username
|
||||
assert not redis_service.connection_database
|
||||
assert redis_service.internal_port == 6379
|
||||
assert deployment.ensure_test_runtime_services() == ()
|
||||
Loading…
Add table
Add a link
Reference in a new issue