diff --git a/gcloud/tests/utils/cmdb/test_business_host_topo.py b/gcloud/tests/utils/cmdb/test_business_host_topo.py index 444797d17..6fde2641d 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.bk_host_id = "225" + self.bk_host_ids = "225,286" self.list_biz_hosts_topo_return = [ { "host": { @@ -179,7 +181,6 @@ 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) @@ -229,8 +230,8 @@ def test__get_contains_with_ip_list(self): self.bk_biz_id, self.supplier_account, self.host_fields, - start=0, - limit=10, + start="0", + limit="10", ip_str=self.ip_str, ) @@ -255,8 +256,8 @@ def test__get_many_contains_with_ip_list(self): self.bk_biz_id, self.supplier_account, self.host_fields, - start=0, - limit=10, + start="0", + limit="10", ip_str=self.ip_strs, ) @@ -280,7 +281,7 @@ def test__get_many_contains_with_ip_list(self): 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.username, self.bk_biz_id, self.supplier_account, self.host_fields, start="0", limit="10" ) self.assertEqual(hosts_topo, self.get_filter_business_host_topo_expect_return) @@ -290,5 +291,60 @@ def test__get_with_page_list(self): "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", + bk_host_id=self.bk_host_id, + ) + + 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": "equal", "value": int(self.bk_host_id)}], + }, + "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", + bk_host_id=self.bk_host_ids, + ) + + 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": "equal", "value": int(host_id)} + for host_id in self.bk_host_ids.split(",") + ], + }, + "page": {"start": 0, "limit": 10}, + } ) diff --git a/gcloud/utils/cmdb.py b/gcloud/utils/cmdb.py index ebfac5804..4e4a30ec9 100644 --- a/gcloud/utils/cmdb.py +++ b/gcloud/utils/cmdb.py @@ -19,6 +19,7 @@ from gcloud.conf import settings from gcloud.core.models import StaffGroupSet from gcloud.utils.handlers import handle_api_error +from gcloud.utils.ip import ipv6_pattern logger = logging.getLogger("root") logger_celery = logging.getLogger("celery") @@ -93,7 +94,9 @@ 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, bk_host_id=None +): """获取业务下所有主机信息 :param username: 请求用户名 :type username: str @@ -104,11 +107,13 @@ def get_filter_business_host_topo(username, bk_biz_id, supplier_account, host_fi :param host_fields: 主机过滤字段 :type host_fields: list :param start: 起始页数 - :type start: int + :type start: str :param limit: 每页数量,最大数量限制为 500 - :type limit: int + :type limit: str :param ip_str: 主机内网 IP :type ip_str: str + :param bk_host_id: 主机 id + :type bk_host_id: str :return: [ { "host": { @@ -137,16 +142,36 @@ 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 = [] + if bk_host_id: + rules.extend( + [{"field": "bk_host_id", "operator": "equal", "value": int(host_id)} for host_id in bk_host_id.split(",")] + ) + elif ip_str: + rules.extend( + [ + { + "field": "bk_host_innerip_v6" if ipv6_pattern.match(ip) else "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 and limit is not None: + params["page"] = {"start": int(start), "limit": int(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 +185,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, data["data"]["count"] + 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 990adcadd..e893512bb 100644 --- a/pipeline_plugins/cmdb_ip_picker/query.py +++ b/pipeline_plugins/cmdb_ip_picker/query.py @@ -88,6 +88,7 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= ip_str = request.GET.get("ip_str", "") start = request.GET.get("start", None) limit = request.GET.get("limit", None) + bk_host_id = request.GET.get("bk_host_id", None) # get filter module id if request.GET.get("topo", None): @@ -112,13 +113,10 @@ def cmdb_search_host(request, bk_biz_id, bk_supplier_account="", bk_supplier_id= message = handle_api_error(_("配置平台(CMDB)"), "cc.search_cloud_area", {}, cloud_area_result) result = {"result": False, "code": ERROR_CODES.API_GSE_ERROR, "message": message} return JsonResponse(result) - count = None - if start and limit: - 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 - ) - 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, start, limit, ip_str, bk_host_id + ) # map cloud_area_id to cloud_area cloud_area_dict = {} @@ -219,6 +217,7 @@ 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 + if count: result = {"result": True, "code": NO_ERROR, "data": {"data": data, "count": count}} else: