from __future__ import annotations import unittest from unittest.mock import patch from monitors.yumi.tencent_clb import ( collect_internal_bindings, collect_internal_health_states, prepare_internal_clb_snapshot, ) APP1_OTHER = { "host": "app-1", "service": "other", "ip": "10.2.11.3", "instanceId": "ins-n566mmeg", "port": 2400, } L4_LISTENERS = [ { "ListenerId": "lbl-other", "Protocol": "TCP", "Port": 2400, "Targets": [ {"InstanceId": "ins-n566mmeg", "Port": 2400, "Weight": 10, "PrivateIpAddresses": ["10.2.11.3"]}, {"InstanceId": "ins-kauk17la", "Port": 2400, "Weight": 10, "PrivateIpAddresses": ["10.2.12.6"]}, ], }, { "ListenerId": "lbl-live", "Protocol": "TCP", "Port": 2500, "Targets": [ {"InstanceId": "ins-n566mmeg", "Port": 2500, "Weight": 10, "PrivateIpAddresses": ["10.2.11.3"]}, ], }, ] class InternalClbBindingTests(unittest.TestCase): def test_collect_internal_bindings_matches_only_service_port_and_host(self) -> None: # 同一台宿主机同时挂 other-2400 / live-2500,只允许命中当前服务自己的监听器。 bindings = collect_internal_bindings(L4_LISTENERS, APP1_OTHER) self.assertEqual(len(bindings), 1) self.assertEqual(bindings[0]["listenerId"], "lbl-other") self.assertEqual(bindings[0]["port"], 2400) self.assertEqual(bindings[0]["weight"], 10) self.assertEqual(bindings[0]["instanceId"], "ins-n566mmeg") @patch("monitors.yumi.tencent_clb.INTERNAL_CLB_IDS", ()) def test_prepare_snapshot_disabled_without_config(self) -> None: # 未配置 INTERNAL_CLB_IDS 时必须整体跳过,保持历史行为。 self.assertIsNone(prepare_internal_clb_snapshot(APP1_OTHER)) @patch("monitors.yumi.tencent_clb.call_clb_api") @patch("monitors.yumi.tencent_clb.INTERNAL_CLB_IDS", ("lb-app", "lb-pay")) def test_prepare_snapshot_collects_matching_clbs_only(self, call_clb_api_mock) -> None: def fake_describe(method: str, payload: dict) -> dict: self.assertEqual(method, "DescribeTargets") if payload["LoadBalancerId"] == "lb-app": return {"Listeners": L4_LISTENERS} return {"Listeners": []} call_clb_api_mock.side_effect = fake_describe snapshot = prepare_internal_clb_snapshot(APP1_OTHER) self.assertIsNotNone(snapshot) self.assertEqual(len(snapshot["groups"]), 1) group = snapshot["groups"][0] self.assertEqual(group["loadBalancerId"], "lb-app") self.assertEqual(group["listenerIds"], ["lbl-other"]) self.assertEqual(len(group["bindings"]), 1) self.assertEqual(int(group["bindings"][0]["weight"]), 10) @patch("monitors.yumi.tencent_clb.call_clb_api") @patch("monitors.yumi.tencent_clb.INTERNAL_CLB_IDS", ("lb-app",)) def test_prepare_snapshot_none_when_service_not_behind_clb(self, call_clb_api_mock) -> None: call_clb_api_mock.return_value = {"Listeners": []} self.assertIsNone(prepare_internal_clb_snapshot(APP1_OTHER)) class InternalClbHealthTests(unittest.TestCase): def test_collect_internal_health_states_flattens_l4_rules(self) -> None: load_balancers = [ { "LoadBalancerId": "lb-app", "Listeners": [ { "ListenerId": "lbl-other", "Rules": [ { "Targets": [ { "TargetId": "ins-n566mmeg", "Port": 2400, "HealthStatus": True, "HealthStatusDetail": "Alive", }, { "TargetId": "ins-kauk17la", "Port": 2400, "HealthStatus": False, "HealthStatusDetail": "Dead", }, ] } ], } ], } ] snapshot = {"service": APP1_OTHER} states = collect_internal_health_states(load_balancers, snapshot) self.assertEqual(len(states), 1) self.assertEqual(states[0]["targetId"], "ins-n566mmeg") self.assertTrue(states[0]["healthStatus"]) if __name__ == "__main__": unittest.main()