Files
getDomain/domain-api/tests/test_ops_service_contract_registry.py
2026-04-18 23:52:51 +08:00

296 lines
13 KiB
Python

import unittest
from unittest.mock import patch
from app.services.ops_service import (
get_ops_blueprint,
get_ops_capabilities,
get_ops_contract_detail,
get_ops_contract_registry,
get_ops_runbook,
)
class OpsServiceContractRegistryTests(unittest.TestCase):
def test_contract_registry_lists_all_frozen_ops_contracts(self) -> None:
payload = get_ops_contract_registry()
self.assertEqual("2026-04-18", payload["registry_version"])
self.assertEqual("v1", payload["schema_version"])
self.assertEqual(11, payload["contracts_total"])
self.assertEqual(
[
"ops_job_contract",
"ops_agent_protocol",
"release_hub_contract",
"ops_driver_contract",
"ops_playbook_contract",
"ops_observability_contract",
"ops_stack_diagnosis_contract",
"ops_doctor_decision_contract",
"ops_go_live_signoff_contract",
"ops_go_live_bundle_contract",
"ops_go_live_review_contract",
],
[item["key"] for item in payload["contracts"]],
)
self.assertIn("/api/v1/ops/contracts/{contract_key}", payload["discovery_entrypoints"])
self.assertEqual(
"docs/schemas/ops_job_contract.md",
payload["contracts_by_key"]["ops_job_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/jobs/{job_id}/dispatch",
payload["contracts_by_key"]["ops_job_contract"]["discovery_endpoints"],
)
self.assertEqual(
"docs/schemas/ops_agent_protocol.md",
payload["contracts_by_key"]["ops_agent_protocol"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/agent/bootstrap-plan",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue/records",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue/flush",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue/replay",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/replay",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/delivery-queue/records/{record_id}/discard",
payload["contracts_by_key"]["ops_agent_protocol"]["discovery_endpoints"],
)
self.assertEqual(
"/api/v1/ops/releases/launchpad",
payload["contracts_by_key"]["release_hub_contract"]["primary_endpoint"],
)
self.assertIn(
"/api/v1/ops/codex-brief",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/driver-actions/preview",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/driver-actions/resolve",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/driver-actions/execute-resolved",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/codex-actions/resolve",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/codex-actions/execute",
payload["contracts_by_key"]["ops_driver_contract"]["discovery_endpoints"],
)
self.assertEqual(
"docs/schemas/ops_playbook_contract.md",
payload["contracts_by_key"]["ops_playbook_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/playbooks/execute",
payload["contracts_by_key"]["ops_playbook_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/playbook-runs/{run_code}/events",
payload["contracts_by_key"]["ops_playbook_contract"]["discovery_endpoints"],
)
self.assertEqual(
"docs/schemas/ops_observability_contract.md",
payload["contracts_by_key"]["ops_observability_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/inspection-overview",
payload["contracts_by_key"]["ops_observability_contract"]["discovery_endpoints"],
)
self.assertIn(
"/api/v1/ops/nodes/{node_code}/scene-log",
payload["contracts_by_key"]["ops_observability_contract"]["discovery_endpoints"],
)
self.assertEqual(
"docs/schemas/ops_stack_diagnosis_contract.md",
payload["contracts_by_key"]["ops_stack_diagnosis_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/stack-diagnosis",
payload["contracts_by_key"]["ops_stack_diagnosis_contract"]["discovery_endpoints"],
)
self.assertIn(
"ops_driver_contract",
payload["contracts_by_key"]["ops_stack_diagnosis_contract"]["related_contract_keys"],
)
self.assertEqual(
"docs/schemas/ops_doctor_decision_contract.md",
payload["contracts_by_key"]["ops_doctor_decision_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/doctor-decision",
payload["contracts_by_key"]["ops_doctor_decision_contract"]["discovery_endpoints"],
)
self.assertIn(
"ops_stack_diagnosis_contract",
payload["contracts_by_key"]["ops_doctor_decision_contract"]["related_contract_keys"],
)
self.assertEqual(
"docs/schemas/ops_go_live_signoff_contract.md",
payload["contracts_by_key"]["ops_go_live_signoff_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/go-live-signoff",
payload["contracts_by_key"]["ops_go_live_signoff_contract"]["discovery_endpoints"],
)
self.assertIn(
"ops_stack_diagnosis_contract",
payload["contracts_by_key"]["ops_go_live_signoff_contract"]["related_contract_keys"],
)
self.assertEqual(
"docs/schemas/ops_go_live_bundle_contract.md",
payload["contracts_by_key"]["ops_go_live_bundle_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/go-live-bundle",
payload["contracts_by_key"]["ops_go_live_bundle_contract"]["discovery_endpoints"],
)
self.assertIn(
"ops_go_live_signoff_contract",
payload["contracts_by_key"]["ops_go_live_bundle_contract"]["related_contract_keys"],
)
self.assertEqual(
"docs/schemas/ops_go_live_review_contract.md",
payload["contracts_by_key"]["ops_go_live_review_contract"]["schema_doc_path"],
)
self.assertIn(
"/api/v1/ops/go-live-review",
payload["contracts_by_key"]["ops_go_live_review_contract"]["discovery_endpoints"],
)
self.assertIn(
"ops_go_live_bundle_contract",
payload["contracts_by_key"]["ops_go_live_review_contract"]["related_contract_keys"],
)
self.assertIn(
"ops_doctor_decision_contract",
payload["contracts_by_key"]["ops_go_live_review_contract"]["related_contract_keys"],
)
def test_contract_detail_exposes_related_contracts(self) -> None:
payload = get_ops_contract_detail("ops_stack_diagnosis_contract")
self.assertEqual("2026-04-18", payload["registry_version"])
self.assertEqual("/api/v1/ops/contracts/ops_stack_diagnosis_contract", payload["detail_endpoint"])
self.assertEqual("ops_stack_diagnosis_contract", payload["contract"]["key"])
self.assertIn("ops_driver_contract", payload["related_contract_keys"])
self.assertIn("release_hub_contract", payload["related_contract_keys"])
self.assertEqual(
"docs/schemas/ops_driver_contract.md",
next(
item["schema_doc_path"]
for item in payload["related_contracts"]
if item["key"] == "ops_driver_contract"
),
)
self.assertEqual({}, get_ops_contract_detail("missing-contract"))
def test_capabilities_blueprint_and_runbook_expose_contract_registry(self) -> None:
capabilities = get_ops_capabilities()
contract_registry = capabilities["contract_registry"]
self.assertEqual("/api/v1/ops/contracts", contract_registry["endpoint"])
self.assertEqual("/api/v1/ops/contracts/{contract_key}", contract_registry["detail_endpoint_pattern"])
self.assertEqual(11, contract_registry["contracts_total"])
self.assertIn("ops_job_contract", contract_registry["contract_keys"])
self.assertIn("ops_driver_contract", contract_registry["contract_keys"])
self.assertIn("ops_playbook_contract", contract_registry["contract_keys"])
self.assertIn("ops_observability_contract", contract_registry["contract_keys"])
self.assertIn("ops_stack_diagnosis_contract", contract_registry["contract_keys"])
self.assertIn("ops_doctor_decision_contract", contract_registry["contract_keys"])
self.assertIn("ops_go_live_signoff_contract", contract_registry["contract_keys"])
self.assertIn("ops_go_live_bundle_contract", contract_registry["contract_keys"])
self.assertIn("ops_go_live_review_contract", contract_registry["contract_keys"])
remote_log_capability = next(
item for item in capabilities["capabilities"] if item["key"] == "remote_log_sync"
)
self.assertEqual("ready", remote_log_capability["current_state"])
self.assertEqual(
"docs/schemas/release_hub_contract.md",
contract_registry["schema_docs"]["release_hub_contract"],
)
self.assertEqual(
"docs/schemas/ops_playbook_contract.md",
contract_registry["schema_docs"]["ops_playbook_contract"],
)
self.assertEqual(
"docs/schemas/ops_job_contract.md",
contract_registry["schema_docs"]["ops_job_contract"],
)
self.assertEqual(
"docs/schemas/ops_observability_contract.md",
contract_registry["schema_docs"]["ops_observability_contract"],
)
self.assertEqual(
"docs/schemas/ops_stack_diagnosis_contract.md",
contract_registry["schema_docs"]["ops_stack_diagnosis_contract"],
)
self.assertEqual(
"docs/schemas/ops_doctor_decision_contract.md",
contract_registry["schema_docs"]["ops_doctor_decision_contract"],
)
self.assertEqual(
"docs/schemas/ops_go_live_signoff_contract.md",
contract_registry["schema_docs"]["ops_go_live_signoff_contract"],
)
self.assertEqual(
"docs/schemas/ops_go_live_bundle_contract.md",
contract_registry["schema_docs"]["ops_go_live_bundle_contract"],
)
self.assertEqual(
"docs/schemas/ops_go_live_review_contract.md",
contract_registry["schema_docs"]["ops_go_live_review_contract"],
)
blueprint = get_ops_blueprint()
self.assertEqual("2026-04-18", blueprint["contract_registry"]["registry_version"])
self.assertEqual(11, blueprint["contract_registry"]["contracts_total"])
with patch("app.services.ops_service.get_runtime_status") as mock_runtime_status, patch(
"app.services.ops_service.list_managed_nodes_with_agent_state"
) as mock_list_managed_nodes_with_agent_state, patch(
"app.services.ops_service.get_release_launchpad"
) as mock_get_release_launchpad, patch(
"app.services.ops_service._attach_ops_runbook_sequence_resolutions"
) as mock_attach_sequences:
mock_runtime_status.return_value = {
"readiness": {"status": "ready", "summary": "ok"},
"worker": {"running": True},
"sync_agent": {"running": True},
"detect": {},
}
mock_list_managed_nodes_with_agent_state.return_value = {"nodes": [], "summary": {}}
mock_get_release_launchpad.return_value = {}
mock_attach_sequences.return_value = []
runbook = get_ops_runbook()
self.assertIn("GET /api/v1/ops/contracts", runbook["fast_checks"])
if __name__ == "__main__":
unittest.main()