feat: add ops center and node onboarding flow
This commit is contained in:
177
domain-api/tests/test_ops_template_service.py
Normal file
177
domain-api/tests/test_ops_template_service.py
Normal file
@@ -0,0 +1,177 @@
|
||||
import unittest
|
||||
|
||||
from app.services.ops_template_service import build_ops_template_payload, get_ops_action_template
|
||||
|
||||
|
||||
class OpsTemplateServiceTests(unittest.TestCase):
|
||||
def test_node_bootstrap_defaults_and_clamps_number(self) -> None:
|
||||
ok, message, data = build_ops_template_payload(
|
||||
"node.bootstrap",
|
||||
{
|
||||
"expires_in_hours": 9999,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(ok, message)
|
||||
self.assertEqual("ok", message)
|
||||
self.assertEqual("", data["control_plane_base_url"])
|
||||
self.assertEqual("/opt/domaincheck", data["root_dir"])
|
||||
self.assertEqual(720, data["expires_in_hours"])
|
||||
self.assertEqual("", data["node_region"])
|
||||
self.assertEqual("", data["node_role"])
|
||||
|
||||
def test_deploy_release_custom_normalizes_lists_and_booleans(self) -> None:
|
||||
ok, message, data = build_ops_template_payload(
|
||||
"deploy.release.custom",
|
||||
{
|
||||
"release_version": "2026.04.18-rc1",
|
||||
"artifact_url": "https://example.com/release.tar.gz",
|
||||
"restart_services": "domaincheck-api\ndomaincheck-worker",
|
||||
"health_check_urls": "",
|
||||
"health_check_services": "",
|
||||
"rollback_on_failure": "false",
|
||||
"switch_current": "true",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(ok, message)
|
||||
self.assertEqual("ok", message)
|
||||
self.assertEqual(["domaincheck-api", "domaincheck-worker"], data["restart_services"])
|
||||
self.assertEqual([], data["health_check_urls"])
|
||||
self.assertEqual([], data["health_check_services"])
|
||||
self.assertFalse(data["rollback_on_failure"])
|
||||
self.assertTrue(data["switch_current"])
|
||||
self.assertEqual("/opt/domaincheck", data["install_root"])
|
||||
|
||||
def test_deploy_release_control_applies_defaults(self) -> None:
|
||||
ok, message, data = build_ops_template_payload(
|
||||
"deploy.release.control",
|
||||
{
|
||||
"release_version": "2026.04.18-rc1",
|
||||
"artifact_url": "https://example.com/release.tar.gz",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(ok, message)
|
||||
self.assertEqual(
|
||||
["domaincheck-api", "domaincheck-worker", "domaincheck-sync-agent"],
|
||||
data["restart_services"],
|
||||
)
|
||||
self.assertEqual(["http://127.0.0.1:8100/health"], data["health_check_urls"])
|
||||
self.assertEqual(
|
||||
["domaincheck-api", "domaincheck-worker", "domaincheck-sync-agent"],
|
||||
data["health_check_services"],
|
||||
)
|
||||
self.assertTrue(data["rollback_on_failure"])
|
||||
self.assertTrue(data["switch_current"])
|
||||
|
||||
def test_deploy_release_missing_required_field_fails(self) -> None:
|
||||
ok, message, data = build_ops_template_payload(
|
||||
"deploy.release.custom",
|
||||
{
|
||||
"release_version": "2026.04.18-rc1",
|
||||
"artifact_url": "",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertFalse(ok)
|
||||
self.assertEqual("artifact_url 不能为空", message)
|
||||
self.assertEqual({}, data)
|
||||
|
||||
def test_logs_collect_lines_are_clamped(self) -> None:
|
||||
ok, message, data = build_ops_template_payload(
|
||||
"logs.collect",
|
||||
{
|
||||
"service_name": "domaincheck-worker",
|
||||
"lines": 9999,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(ok, message)
|
||||
self.assertEqual(500, data["lines"])
|
||||
|
||||
def test_delivery_queue_templates_normalize_and_require_expected_fields(self) -> None:
|
||||
replay_ok, replay_message, replay_data = build_ops_template_payload(
|
||||
"delivery.queue.replay",
|
||||
{
|
||||
"record_id": "evt-001",
|
||||
"limit": 999,
|
||||
"flush_after_replay": "false",
|
||||
"reason": "确认状态已修复",
|
||||
},
|
||||
)
|
||||
discard_ok, discard_message, discard_data = build_ops_template_payload(
|
||||
"delivery.queue.discard",
|
||||
{
|
||||
"record_id": "evt-002",
|
||||
"limit": 0,
|
||||
"reason": "确认这条死信不再需要补发",
|
||||
},
|
||||
)
|
||||
flush_ok, flush_message, flush_data = build_ops_template_payload(
|
||||
"delivery.queue.flush",
|
||||
{
|
||||
"limit": 999,
|
||||
},
|
||||
)
|
||||
discard_fail_ok, discard_fail_message, discard_fail_data = build_ops_template_payload(
|
||||
"delivery.queue.discard",
|
||||
{
|
||||
"record_id": "evt-003",
|
||||
"reason": "",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(replay_ok, replay_message)
|
||||
self.assertEqual(200, replay_data["limit"])
|
||||
self.assertFalse(replay_data["flush_after_replay"])
|
||||
self.assertEqual("evt-001", replay_data["record_id"])
|
||||
|
||||
self.assertTrue(discard_ok, discard_message)
|
||||
self.assertEqual(1, discard_data["limit"])
|
||||
self.assertEqual("确认这条死信不再需要补发", discard_data["reason"])
|
||||
|
||||
self.assertTrue(flush_ok, flush_message)
|
||||
self.assertEqual(200, flush_data["limit"])
|
||||
|
||||
self.assertFalse(discard_fail_ok)
|
||||
self.assertEqual("reason 不能为空", discard_fail_message)
|
||||
self.assertEqual({}, discard_fail_data)
|
||||
|
||||
def test_diagnostics_and_service_control_templates_expose_ssh(self) -> None:
|
||||
health_template = get_ops_action_template("health.snapshot")
|
||||
logs_template = get_ops_action_template("logs.collect")
|
||||
diagnostics_template = get_ops_action_template("diagnostics.collect")
|
||||
service_status_template = get_ops_action_template("service.status")
|
||||
restart_template = get_ops_action_template("service.restart")
|
||||
restart_api_template = get_ops_action_template("runtime.restart_api")
|
||||
stop_worker_template = get_ops_action_template("runtime.stop_worker")
|
||||
deploy_control_template = get_ops_action_template("deploy.release.control")
|
||||
deploy_worker_template = get_ops_action_template("deploy.release.worker")
|
||||
deploy_custom_template = get_ops_action_template("deploy.release.custom")
|
||||
queue_flush_template = get_ops_action_template("delivery.queue.flush")
|
||||
queue_replay_template = get_ops_action_template("delivery.queue.replay")
|
||||
queue_discard_template = get_ops_action_template("delivery.queue.discard")
|
||||
|
||||
self.assertIn("ssh", health_template["execution_modes"])
|
||||
self.assertEqual("远端 Agent", health_template["default_execution_mode_label"])
|
||||
self.assertEqual("SSH", next(item["label"] for item in health_template["execution_mode_options"] if item["value"] == "ssh"))
|
||||
self.assertIn("ssh", logs_template["execution_modes"])
|
||||
self.assertIn("ssh", diagnostics_template["execution_modes"])
|
||||
self.assertIn("ssh", service_status_template["execution_modes"])
|
||||
self.assertIn("ssh", restart_template["execution_modes"])
|
||||
self.assertIn("ssh", restart_api_template["execution_modes"])
|
||||
self.assertIn("ssh", stop_worker_template["execution_modes"])
|
||||
self.assertEqual("控制面", get_ops_action_template("node.bootstrap")["default_execution_mode_label"])
|
||||
self.assertIn("ssh", deploy_control_template["execution_modes"])
|
||||
self.assertIn("ssh", deploy_worker_template["execution_modes"])
|
||||
self.assertIn("ssh", deploy_custom_template["execution_modes"])
|
||||
self.assertEqual(["remote-agent"], queue_flush_template["execution_modes"])
|
||||
self.assertEqual(["remote-agent"], queue_replay_template["execution_modes"])
|
||||
self.assertEqual(["remote-agent"], queue_discard_template["execution_modes"])
|
||||
self.assertEqual("远端 Agent", queue_flush_template["default_execution_mode_label"])
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user