from __future__ import annotations from unittest.mock import patch import pytest from django.contrib import admin from django.contrib.auth import get_user_model from django.test import RequestFactory 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 RuntimeServiceStatus from control_plane.models import Tenant @pytest.mark.django_db def test_admin_can_view_runtime_service_changelist() -> None: """Superusers should see runtime service records in Django admin.""" user_model = get_user_model() admin_user = user_model.objects.create_superuser( username="admin", email="admin@example.com", password="admin-password", ) 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-admin-001", source_sha256="c" * 64, ) RuntimeService.objects.create( deployment=deployment, kind=RuntimeServiceKind.POSTGRESQL, status=RuntimeServiceStatus.READY, 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", ) request = RequestFactory().get("/admin/control_plane/runtimeservice/") request.user = admin_user model_admin = admin.site._registry[RuntimeService] queryset = model_admin.get_queryset(request) runtime_service = queryset.get() assert model_admin.has_module_permission(request) is True assert model_admin.has_view_permission(request) is True assert runtime_service.container_name == "postgres-acme-portal" assert model_admin.tenant_slug(runtime_service) == "acme" assert model_admin.site_slug(runtime_service) == "portal" @pytest.mark.django_db def test_admin_registers_control_plane_models() -> None: """Admin should expose full control-plane graph for smoke data creation.""" assert Tenant in admin.site._registry assert HostedSite in admin.site._registry assert Deployment in admin.site._registry assert RuntimeService in admin.site._registry @pytest.mark.django_db def test_deployment_admin_action_queues_test_container_provisioning() -> None: """Deployment admin action should queue Celery-backed test container provisioning.""" user_model = get_user_model() admin_user = user_model.objects.create_superuser( username="admin-action", email="admin-action@example.com", password="admin-password", ) 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-admin-002", source_sha256="e" * 64, ) request = RequestFactory().post("/admin/control_plane/deployment/") request.user = admin_user model_admin = admin.site._registry[Deployment] deployment_queryset = Deployment.objects.filter(pk=deployment.pk) with ( patch("control_plane.admin.provision_test_runtime_services.delay") as mock_delay, patch.object(model_admin, "message_user") as mock_message_user, ): model_admin.create_test_containers(request, deployment_queryset) mock_delay.assert_called_once_with(str(deployment.id)) mock_message_user.assert_called_once()