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() == ()