diff --git a/gcloud/tests/utils/cmdb/test_business_host_topo.py b/gcloud/tests/utils/cmdb/test_business_host_topo.py index 2b81ed35d5..d6043d00c5 100644 --- a/gcloud/tests/utils/cmdb/test_business_host_topo.py +++ b/gcloud/tests/utils/cmdb/test_business_host_topo.py @@ -14,15 +14,15 @@ from django.test import TestCase -from gcloud.utils.cmdb import get_business_host_topo +from gcloud.utils.cmdb import get_business_host_topo, get_filter_business_host_topo class GetBusinessHostTopoTestCase(TestCase): def setUp(self): - mock_client = MagicMock() - mock_client.cc.list_biz_hosts_topo = "list_biz_hosts_topo" + self.mock_client = MagicMock() + self.mock_client.cc.list_biz_hosts_topo = "list_biz_hosts_topo" self.get_client_by_user_patcher = patch( - "gcloud.utils.cmdb.get_client_by_user", MagicMock(return_value=mock_client) + "gcloud.utils.cmdb.get_client_by_user", MagicMock(return_value=self.mock_client) ) self.get_client_by_user_patcher.start() @@ -31,6 +31,8 @@ def setUp(self): self.supplier_account = "supplier_account_token" self.host_fields = ["host_fields_token"] self.ip_list = "ip_list_token" + self.ip_str = "ip_str_token" + self.ip_strs = "ip1_str_token, ip2_str_token" self.list_biz_hosts_topo_return = [ { "host": { @@ -65,6 +67,53 @@ def setUp(self): ], }, ] + self.list_biz_hosts_page_topo_return = { + "result": True, + "data": { + "info": [ + { + "host": { + "bk_cloud_id": 0, + "bk_host_id": 1, + "bk_host_innerip": "127.0.0.1", + "bk_mac": "", + "bk_os_type": None, + }, + "topo": [ + { + "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, + }, + "topo": [ + { + "bk_set_id": 10, + "bk_set_name": "空闲机池", + "module": [ + {"bk_module_id": 54, "bk_module_name": "空闲机"}, + {"bk_module_id": 55, "bk_module_name": "空闲机1"}, + ], + }, + { + "bk_set_id": 11, + "bk_set_name": "set1", + "module": [{"bk_module_id": 56, "bk_module_name": "m1"}], + }, + ], + }, + ] + }, + } self.get_business_host_topo_expect_return = [ { "host": { @@ -140,3 +189,74 @@ def test__get_without_ip_list(self): "list_biz_hosts_topo", {"bk_biz_id": self.bk_biz_id, "bk_supplier_account": self.supplier_account, "fields": self.host_fields}, ) + + def test__get_contains_with_ip_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, + ip_str=self.ip_str, + ) + + self.assertEqual(hosts_topo, self.get_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_innerip", "operator": "contains", "value": self.ip_str}], + }, + "page": {"start": 0, "limit": 10}, + }, + ) + + def test__get_many_contains_with_ip_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, + ip_str=self.ip_strs, + ) + + self.assertEqual(hosts_topo, self.get_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_innerip", "operator": "contains", "value": self.ip_str} + for self.ip_str in self.ip_strs.split(",") + ], + }, + "page": {"start": 0, "limit": 10}, + }, + ) + + def test__get_with_page_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 + ) + + self.assertEqual(hosts_topo, self.get_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}, + }, + ) diff --git a/gcloud/utils/cmdb.py b/gcloud/utils/cmdb.py index 4d54bb2194..82953e236f 100644 --- a/gcloud/utils/cmdb.py +++ b/gcloud/utils/cmdb.py @@ -93,6 +93,76 @@ 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): + """获取业务下所有主机信息 + :param username: 请求用户名 + :type username: str + :param bk_biz_id: 业务 CC ID + :type bk_biz_id: int + :param supplier_account: 开发商账号, defaults to 0 + :type supplier_account: int + :param host_fields: 主机过滤字段 + :type host_fields: list + :param start: 起始页数 + :type start: int + :param limit: 每页数量,最大数量限制为 500 + :type limit: int + :param ip_str: 主机内网 IP + :type ip_str: str + :return: [ + { + "host": { + "bk_host_id": 4, + "bk_host_innerip": "127.0.0.1", + "bk_cloud_id": 0, + ... + }, + "module": [ + { + "bk_module_id": 2, + "bk_module_name": "module_name" + }, + ... + ], + "set": [ + { + "bk_set_name": "set_name", + "bk_set_id": 1 + }, + ... + ] + } + ] + :rtype: list + """ + 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))) + + result = data["data"]["info"] + + host_info_list = [] + for host_topo in result: + host_info = {"host": host_topo["host"], "module": [], "set": []} + for parent_set in host_topo["topo"]: + host_info["set"].append({"bk_set_id": parent_set["bk_set_id"], "bk_set_name": parent_set["bk_set_name"]}) + for parent_module in parent_set["module"]: + host_info["module"].append( + {"bk_module_id": parent_module["bk_module_id"], "bk_module_name": parent_module["bk_module_name"]} + ) + + host_info_list.append(host_info) + + return host_info_list + + def get_business_host(username, bk_biz_id, supplier_account, host_fields, ip_list=None, bk_cloud_id=None): """根据主机内网 IP 过滤业务下的主机 :param username: 请求用户名 diff --git a/pipeline_plugins/cmdb_ip_picker/query.py b/pipeline_plugins/cmdb_ip_picker/query.py index a09275b650..e9ef30e850 100644 --- a/pipeline_plugins/cmdb_ip_picker/query.py +++ b/pipeline_plugins/cmdb_ip_picker/query.py @@ -85,6 +85,10 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= topo_modules_id = set() + ip_str = request.GET.get("ip_str", "") + start = request.GET.get("start", None) + limit = request.GET.get("limit", None) + # get filter module id if request.GET.get("topo", None): topo = json.loads(request.GET.get("topo")) @@ -109,7 +113,12 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= result = {"result": False, "code": ERROR_CODES.API_GSE_ERROR, "message": message} return JsonResponse(result) - raw_host_info_list = cmdb.get_business_host_topo(request.user.username, bk_biz_id, bk_supplier_account, fields) + 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 + ) + else: + raw_host_info_list = cmdb.get_business_host_topo(request.user.username, bk_biz_id, bk_supplier_account, fields) # map cloud_area_id to cloud_area cloud_area_dict = {}