From d0c7abd950ed211d2c6bc9207824bc32edb61b83 Mon Sep 17 00:00:00 2001 From: guohelu <141622458+guohelu@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:56:48 +0800 Subject: [PATCH] Hotfix release master (#7594) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 新增IP选择器后端搜索和分页 #7550 * fix: 修复返回数据格式错误 #7550 * fix: 修复前后端联调BUG #7550 * fix: 修复代码逻辑问题 #7550 * fix: 修复请求为POST请求 #7550 * fix: 修复模糊匹配规则问题 #7550 * fix: 修复数据类型错误 #7550 --- .../utils/cmdb/test_business_host_topo.py | 114 ++++++++++++++++-- gcloud/utils/cmdb.py | 39 ++++-- pipeline_plugins/cmdb_ip_picker/query.py | 29 +++-- 3 files changed, 151 insertions(+), 31 deletions(-) diff --git a/gcloud/tests/utils/cmdb/test_business_host_topo.py b/gcloud/tests/utils/cmdb/test_business_host_topo.py index d6043d00c..be787da2c 100644 --- a/gcloud/tests/utils/cmdb/test_business_host_topo.py +++ b/gcloud/tests/utils/cmdb/test_business_host_topo.py @@ -33,6 +33,8 @@ def setUp(self): self.ip_list = "ip_list_token" self.ip_str = "ip_str_token" self.ip_strs = "ip1_str_token, ip2_str_token" + self.host_id_str = "225" + self.host_id_strs = "225,286" self.list_biz_hosts_topo_return = [ { "host": { @@ -111,7 +113,8 @@ def setUp(self): }, ], }, - ] + ], + "count": 2, }, } self.get_business_host_topo_expect_return = [ @@ -142,12 +145,42 @@ def setUp(self): ], }, ] + self.get_filter_business_host_topo_expect_return = ( + [ + { + "host": { + "bk_cloud_id": 0, + "bk_host_id": 1, + "bk_host_innerip": "127.0.0.1", + "bk_mac": "", + "bk_os_type": None, + }, + "set": [{"bk_set_id": 11, "bk_set_name": "set1"}], + "module": [{"bk_module_id": 56, "bk_module_name": "m1"}], + }, + { + "host": { + "bk_cloud_id": 0, + "bk_host_id": 3, + "bk_host_innerip": "127.0.0.3", + "bk_mac": "", + "bk_os_type": None, + }, + "set": [{"bk_set_id": 10, "bk_set_name": "空闲机池"}, {"bk_set_id": 11, "bk_set_name": "set1"}], + "module": [ + {"bk_module_id": 54, "bk_module_name": "空闲机"}, + {"bk_module_id": 55, "bk_module_name": "空闲机1"}, + {"bk_module_id": 56, "bk_module_name": "m1"}, + ], + }, + ], + 2, + ) def tearDown(self): self.get_client_by_user_patcher.stop() def test__list_biz_hosts_topo_return_empty(self): - mock_batch_request = MagicMock(return_value=[]) with patch("gcloud.utils.cmdb.batch_request", mock_batch_request): hosts_topo = get_business_host_topo(self.username, self.bk_biz_id, self.supplier_account, self.host_fields) @@ -202,7 +235,7 @@ def test__get_contains_with_ip_list(self): ip_str=self.ip_str, ) - self.assertEqual(hosts_topo, self.get_business_host_topo_expect_return) + self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) self.mock_client.cc.list_biz_hosts_topo.assert_called_once_with( { "bk_biz_id": self.bk_biz_id, @@ -210,7 +243,8 @@ def test__get_contains_with_ip_list(self): "fields": self.host_fields, "host_property_filter": { "condition": "OR", - "rules": [{"field": "bk_host_innerip", "operator": "contains", "value": self.ip_str}], + "rules": [{"field": "bk_host_innerip_v6", "operator": "contains", "value": self.ip_str}] + + [{"field": "bk_host_innerip", "operator": "contains", "value": self.ip_str}], }, "page": {"start": 0, "limit": 10}, }, @@ -228,7 +262,7 @@ def test__get_many_contains_with_ip_list(self): ip_str=self.ip_strs, ) - self.assertEqual(hosts_topo, self.get_business_host_topo_expect_return) + self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) self.mock_client.cc.list_biz_hosts_topo.assert_called_once_with( { "bk_biz_id": self.bk_biz_id, @@ -237,8 +271,12 @@ def test__get_many_contains_with_ip_list(self): "host_property_filter": { "condition": "OR", "rules": [ - {"field": "bk_host_innerip", "operator": "contains", "value": self.ip_str} - for self.ip_str in self.ip_strs.split(",") + {"field": "bk_host_innerip_v6", "operator": "contains", "value": ip_str} + for ip_str in self.ip_strs.split(",") + ] + + [ + {"field": "bk_host_innerip", "operator": "contains", "value": ip_str} + for ip_str in self.ip_strs.split(",") ], }, "page": {"start": 0, "limit": 10}, @@ -251,12 +289,70 @@ def test__get_with_page_list(self): self.username, self.bk_biz_id, self.supplier_account, self.host_fields, start=0, limit=10 ) - self.assertEqual(hosts_topo, self.get_business_host_topo_expect_return) + self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) self.mock_client.cc.list_biz_hosts_topo.assert_called_once_with( { "bk_biz_id": self.bk_biz_id, "bk_supplier_account": self.supplier_account, "fields": self.host_fields, "page": {"start": 0, "limit": 10}, - }, + } + ) + + def test_get_equal_host_list(self): + self.mock_client.cc.list_biz_hosts_topo = MagicMock(return_value=self.list_biz_hosts_page_topo_return) + hosts_topo = get_filter_business_host_topo( + self.username, + self.bk_biz_id, + self.supplier_account, + self.host_fields, + start=0, + limit=10, + host_id_str=self.host_id_str, + ) + + self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) + self.mock_client.cc.list_biz_hosts_topo.assert_called_once_with( + { + "bk_biz_id": self.bk_biz_id, + "bk_supplier_account": self.supplier_account, + "fields": self.host_fields, + "host_property_filter": { + "condition": "OR", + "rules": [{"field": "bk_host_id", "operator": "in", "value": [int(self.host_id_str)]}], + }, + "page": {"start": 0, "limit": 10}, + } + ) + + def test_get_many_equal_host_list(self): + self.mock_client.cc.list_biz_hosts_topo = MagicMock(return_value=self.list_biz_hosts_page_topo_return) + hosts_topo = get_filter_business_host_topo( + self.username, + self.bk_biz_id, + self.supplier_account, + self.host_fields, + start=0, + limit=10, + host_id_str=self.host_id_strs, + ) + + self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) + self.mock_client.cc.list_biz_hosts_topo.assert_called_once_with( + { + "bk_biz_id": self.bk_biz_id, + "bk_supplier_account": self.supplier_account, + "fields": self.host_fields, + "host_property_filter": { + "condition": "OR", + "rules": [ + { + "field": "bk_host_id", + "operator": "in", + "value": [int(host_id) for host_id in self.host_id_strs.split(",")], + } + ], + }, + "page": {"start": 0, "limit": 10}, + } ) diff --git a/gcloud/utils/cmdb.py b/gcloud/utils/cmdb.py index 82953e236..58796e5ec 100644 --- a/gcloud/utils/cmdb.py +++ b/gcloud/utils/cmdb.py @@ -93,8 +93,10 @@ def get_business_host_topo(username, bk_biz_id, supplier_account, host_fields, i return host_info_list -def get_filter_business_host_topo(username, bk_biz_id, supplier_account, host_fields, start, limit, ip_str=None): - """获取业务下所有主机信息 +def get_filter_business_host_topo( + username, bk_biz_id, supplier_account, host_fields, start=None, limit=None, ip_str=None, host_id_str=None +): + """获取业务下所有符合条件的主机信息 :param username: 请求用户名 :type username: str :param bk_biz_id: 业务 CC ID @@ -109,6 +111,8 @@ def get_filter_business_host_topo(username, bk_biz_id, supplier_account, host_fi :type limit: int :param ip_str: 主机内网 IP :type ip_str: str + :param host_id_str: 主机 id + :type host_id_str: str :return: [ { "host": { @@ -137,16 +141,29 @@ def get_filter_business_host_topo(username, bk_biz_id, supplier_account, host_fi """ client = get_client_by_user(username) params = {"bk_biz_id": bk_biz_id, "bk_supplier_account": supplier_account, "fields": list(host_fields or [])} - if ip_str: - rules = [{"field": "bk_host_innerip", "operator": "contains", "value": ip} for ip in ip_str.split(",")] - params["host_property_filter"] = {"condition": "OR", "rules": rules} - params["page"] = {"start": start, "limit": limit} - data = client.cc.list_biz_hosts_topo(params) - if not data["result"]: - raise Exception(_("查询主机列表失败, 请确认业务[{}]是否存在!".format(bk_biz_id))) + rules = [] + # 根据host_id_str进行精准匹配 + if host_id_str: + host_id_list = [int(host_id) for host_id in host_id_str.split(",")] + rules.extend([{"field": "bk_host_id", "operator": "in", "value": host_id_list}]) + # 根据ip_str进行模糊匹配 + elif ip_str: + rules.extend([{"field": "bk_host_innerip_v6", "operator": "contains", "value": ip} for ip in ip_str.split(",")]) + rules.extend([{"field": "bk_host_innerip", "operator": "contains", "value": ip} for ip in ip_str.split(",")]) + if rules: + params["host_property_filter"] = {"condition": "OR", "rules": rules} - result = data["data"]["info"] + count = None + if start is not None and limit is not None: + params["page"] = {"start": start, "limit": limit} + data = client.cc.list_biz_hosts_topo(params) + if not data["result"]: + raise Exception(_("查询主机列表失败, 请确认业务[{}]是否存在!".format(bk_biz_id))) + count = data["data"]["count"] + result = data["data"]["info"] + else: + result = batch_request(client.cc.list_biz_hosts_topo, params) host_info_list = [] for host_topo in result: @@ -160,7 +177,7 @@ def get_filter_business_host_topo(username, bk_biz_id, supplier_account, host_fi host_info_list.append(host_info) - return host_info_list + return host_info_list, count def get_business_host(username, bk_biz_id, supplier_account, host_fields, ip_list=None, bk_cloud_id=None): diff --git a/pipeline_plugins/cmdb_ip_picker/query.py b/pipeline_plugins/cmdb_ip_picker/query.py index e9ef30e85..629dff201 100644 --- a/pipeline_plugins/cmdb_ip_picker/query.py +++ b/pipeline_plugins/cmdb_ip_picker/query.py @@ -80,18 +80,19 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= if settings.ENABLE_IPV6 or settings.ENABLE_GSE_V2: # IPV6环境下或者开启了GSE 2.0 版本 default_host_fields.append("bk_agent_id") - fields = set(default_host_fields + json.loads(request.GET.get("fields", "[]"))) + fields = set(default_host_fields + json.loads(request.POST.get("fields", "[]"))) client = get_client_by_user(request.user.username) topo_modules_id = set() - ip_str = request.GET.get("ip_str", "") - start = request.GET.get("start", None) - limit = request.GET.get("limit", None) + start = request.POST.get("start", None) + limit = request.POST.get("limit", None) + ip_str = request.POST.get("ip_str", "") + host_id_str = request.POST.get("host_id_str", None) # get filter module id - if request.GET.get("topo", None): - topo = json.loads(request.GET.get("topo")) + if request.POST.get("topo", None): + topo = json.loads(request.POST.get("topo")) topo_result = get_cmdb_topo_tree(request.user.username, bk_biz_id, bk_supplier_account) if not topo_result["result"]: return JsonResponse(topo_result) @@ -114,11 +115,13 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= return JsonResponse(result) if start and limit: - raw_host_info_list = cmdb.get_filter_business_host_topo( - request.user.username, bk_biz_id, bk_supplier_account, fields, int(start), int(limit), ip_str + raw_host_info_list, count = cmdb.get_filter_business_host_topo( + request.user.username, bk_biz_id, bk_supplier_account, fields, int(start), int(limit), ip_str, host_id_str ) else: - raw_host_info_list = cmdb.get_business_host_topo(request.user.username, bk_biz_id, bk_supplier_account, fields) + raw_host_info_list, count = cmdb.get_filter_business_host_topo( + request.user.username, bk_biz_id, bk_supplier_account, fields, ip_str=ip_str, host_id_str=host_id_str + ) # map cloud_area_id to cloud_area cloud_area_dict = {} @@ -207,7 +210,7 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= host["agent"] = agent_info.get("bk_agent_alive", -1) # search host lock status - if request.GET.get("search_host_lock", None): + if request.POST.get("search_host_lock", None): bk_host_id_list = [host_detail["bk_host_id"] for host_detail in data] host_lock_status_result = client.cc.search_host_lock({"id_list": bk_host_id_list}) if not host_lock_status_result["result"]: @@ -219,7 +222,11 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= host_lock_status = host_lock_status_data.get(host_detail["bk_host_id"]) if host_lock_status is not None: host_detail["bk_host_lock_status"] = host_lock_status - result = {"result": True, "code": NO_ERROR, "data": data} + + if count: + result = {"result": True, "code": NO_ERROR, "data": {"data": data, "count": count}} + else: + result = {"result": True, "code": NO_ERROR, "data": data} return JsonResponse(result)