test_deployment_contract.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import json
  2. import subprocess
  3. from pathlib import Path
  4. ROOT = Path(__file__).resolve().parents[2]
  5. COMPOSE = ROOT / "deploy/docker/docker-compose.yml"
  6. DOCKERFILE = ROOT / "deploy/docker/mcp.Dockerfile"
  7. ENV_EXAMPLE = ROOT / "deploy/docker/.env.example"
  8. def test_dataops_mcp_image_is_python_311_and_runs_without_root():
  9. source = DOCKERFILE.read_text(encoding="utf-8")
  10. assert source.startswith("FROM python:3.11-slim")
  11. assert "mcp-servers/requirements.txt" in source
  12. assert "mcp-servers/dataops_mcp_stdio.py" in source
  13. assert "USER dataops" in source
  14. def test_compose_exposes_only_profiled_stdio_dataops_mcp_processes():
  15. compose = json.loads(
  16. subprocess.run(
  17. [
  18. "docker",
  19. "compose",
  20. "-f",
  21. str(COMPOSE),
  22. "--profile",
  23. "dataops-mcp",
  24. "config",
  25. "--format",
  26. "json",
  27. ],
  28. cwd=ROOT,
  29. capture_output=True,
  30. text=True,
  31. check=True,
  32. ).stdout
  33. )
  34. services = compose["services"]
  35. scheduling = services["dataops-scheduling-mcp"]
  36. context = services["dataops-context-mcp"]
  37. for service in (scheduling, context):
  38. assert service["profiles"] == ["dataops-mcp"]
  39. assert service["stdin_open"] is True
  40. assert "ports" not in service
  41. assert service["read_only"] is True
  42. assert service["environment"]["DATAOPS_MCP_DATABASE_URL"].startswith(
  43. "postgresql://"
  44. )
  45. assert (
  46. scheduling["environment"]["RUNNER_TASK_TOKEN_SECRET"]
  47. == (services["runner"]["environment"]["RUNNER_TASK_TOKEN_SECRET"])
  48. )
  49. assert scheduling["environment"]["KESTRA_BASE_URL"] == ("http://kestra:8080/api/v1")
  50. assert "app.core.mcp.bootstrap:build_scheduling_gateway" in scheduling["command"]
  51. assert "app.core.mcp.bootstrap:build_context_service" in context["command"]
  52. def test_mcp_identity_scope_is_explicit_in_environment_template():
  53. source = ENV_EXAMPLE.read_text(encoding="utf-8")
  54. for name in (
  55. "DATAOPS_MCP_SUBJECT",
  56. "DATAOPS_MCP_ROLES",
  57. "DATAOPS_MCP_BUSINESS_DOMAINS",
  58. "DATAOPS_MCP_ENVIRONMENTS",
  59. ):
  60. assert f"{name}=" in source