107 lines
5.1 KiB
Python
107 lines
5.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from app.services.ops_service import get_ops_go_live_bundle
|
|
|
|
|
|
class OpsServiceGoLiveBundleTests(unittest.TestCase):
|
|
@patch("app.services.ops_service.get_ops_contract_registry")
|
|
def test_go_live_bundle_marks_missing_when_no_manifest_exists(self, mock_get_ops_contract_registry) -> None:
|
|
mock_get_ops_contract_registry.return_value = {
|
|
"contracts_by_key": {
|
|
"ops_go_live_bundle_contract": {"version": "v1"},
|
|
}
|
|
}
|
|
|
|
with patch("app.services.ops_service._find_latest_go_live_bundle_manifest", return_value=(None, Path("/tmp/go-live-bundles"))):
|
|
payload = get_ops_go_live_bundle(base_url="http://127.0.0.1:8100")
|
|
|
|
self.assertEqual("missing", payload["status"])
|
|
self.assertFalse(payload["bundle_available"])
|
|
self.assertEqual("待导出", payload["status_label"])
|
|
self.assertIn("go-live-export", payload["recommended_commands"]["go_live_export"])
|
|
|
|
@patch("app.services.ops_service.get_ops_contract_registry")
|
|
def test_go_live_bundle_reads_manifest_summary_and_review_state(self, mock_get_ops_contract_registry) -> None:
|
|
mock_get_ops_contract_registry.return_value = {
|
|
"contracts_by_key": {
|
|
"ops_go_live_bundle_contract": {"version": "v1"},
|
|
}
|
|
}
|
|
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
report_dir = Path(temp_dir) / "go-live-bundle-001"
|
|
report_dir.mkdir(parents=True, exist_ok=True)
|
|
env_audit_path = report_dir / "00_env_audit.txt"
|
|
env_audit_path.write_text(
|
|
"[8/8] condensed env audit summary\n"
|
|
+ json.dumps(
|
|
{
|
|
"status": "attention",
|
|
"headline": "仍有轻微环境缺口",
|
|
"missing_items": ["missing_tool:jq"],
|
|
"runtime": {"runtime_may_need_restart": True},
|
|
"recommended_actions": ["bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover"],
|
|
},
|
|
ensure_ascii=False,
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
manifest_path = report_dir / "manifest.json"
|
|
manifest_path.write_text(
|
|
json.dumps(
|
|
{
|
|
"report_dir": str(report_dir),
|
|
"artifacts": [
|
|
{"key": "env_audit", "path": str(env_audit_path), "ok": True},
|
|
{"key": "go_live_summary", "path": str(report_dir / "02_go_live_summary.json"), "ok": True},
|
|
],
|
|
"failures": ["doctor_export"],
|
|
"summary": {
|
|
"ok": False,
|
|
"artifact_total": 9,
|
|
"failure_total": 1,
|
|
"review_status_hint": "attention",
|
|
"review_headline": "核心报告已齐,但建议先复核补充缺口。",
|
|
"launchpad_recommended_target_node_code": "mainland-worker-01",
|
|
"launchpad_recommended_recovery_label": "先补接管缺口",
|
|
"launchpad_recommended_recovery_summary": "mainland-worker-01 还缺接入收口。",
|
|
"launchpad_onboarding_bootstrap_pending_nodes": 1,
|
|
"launchpad_onboarding_acceptance_ready_nodes": 0,
|
|
"launchpad_alignment": {"consistent": False, "target_node_code_consistent": False},
|
|
"recommended_reading_order": ["00_env_audit.txt", "02_go_live_summary.json"],
|
|
"contract_surface_gaps": ["ops_go_live_bundle_contract"],
|
|
"discovered_contract_keys": ["ops_go_live_signoff_contract"],
|
|
},
|
|
},
|
|
ensure_ascii=False,
|
|
indent=2,
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with patch(
|
|
"app.services.ops_service._find_latest_go_live_bundle_manifest",
|
|
return_value=(manifest_path, report_dir),
|
|
):
|
|
payload = get_ops_go_live_bundle(base_url="http://127.0.0.1:8100")
|
|
|
|
self.assertEqual("attention", payload["status"])
|
|
self.assertTrue(payload["bundle_available"])
|
|
self.assertEqual(str(manifest_path), payload["manifest_path"])
|
|
self.assertEqual(9, payload["artifact_total"])
|
|
self.assertEqual(["doctor_export"], payload["noncritical_failures"])
|
|
self.assertEqual("attention", payload["env_audit"]["status"])
|
|
self.assertTrue(payload["env_audit"]["runtime_may_need_restart"])
|
|
self.assertFalse(payload["summary"]["launchpad_alignment"]["consistent"])
|
|
self.assertIn(str(manifest_path), payload["recommended_commands"]["go_live_signoff"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|