133 lines
4.4 KiB
Python
133 lines
4.4 KiB
Python
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() == ()
|