From bf025d4f9c3889d8b03750b9299aee06283bbdfb Mon Sep 17 00:00:00 2001 From: xcwang <1366993017@qq.com> Date: Wed, 18 Oct 2023 15:17:02 +0800 Subject: [PATCH] =?UTF-8?q?feature:=20=20=E8=AE=A2=E9=98=85=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=B8=9A=E5=8A=A1=E9=9B=86=20(closed=20#1724)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend/tests/subscription/test_scope.py | 168 ++++++++++++++++++ apps/backend/tests/subscription/test_views.py | 30 ++-- apps/backend/tests/subscription/utils.py | 76 ++++++++ apps/node_man/handlers/cmdb.py | 34 ++-- 4 files changed, 283 insertions(+), 25 deletions(-) create mode 100644 apps/backend/tests/subscription/test_scope.py diff --git a/apps/backend/tests/subscription/test_scope.py b/apps/backend/tests/subscription/test_scope.py new file mode 100644 index 0000000000..ee04763f5a --- /dev/null +++ b/apps/backend/tests/subscription/test_scope.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-节点管理(BlueKing-BK-NODEMAN) available. +Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import typing + +import mock +from django.test import TestCase + +from apps.backend.subscription.tools import covert_biz_set_scope_to_scope +from apps.backend.tests.subscription import utils +from apps.node_man.handlers.cmdb import CmdbHandler +from apps.node_man.models import Subscription + + +class TestSubscrptionByScope(TestCase): + SCOPE_TYPE = Subscription.ScopeType.BIZ_SET + maxDiff = None + + def setUp(self): + mock.patch.stopall() + self.query_limit = mock.patch("apps.node_man.constants.QUERY_CMDB_LIMIT", 10) + self.handlers_client = mock.patch("apps.node_man.handlers.cmdb.client_v2", utils.BizSetCmdbClient) + self.handlers_client.start() + self.query_limit.start() + + def topo__host_scope_with_other_biz(self, bk_biz_ids: typing.List[int]): + scope = { + "node_type": Subscription.NodeType.TOPO, + "object_type": Subscription.ObjectType.HOST, + "scope_type": self.SCOPE_TYPE, + "scope_id": utils.SCOPE_ID, + } + scope["nodes"] = [ + {"bk_obj_id": "biz", "bk_inst_id": bk_biz_id, "bk_biz_id": bk_biz_id} for bk_biz_id in bk_biz_ids + ] + return scope + + def topo__host_scope_with_biz_set(self): + scope = { + "node_type": Subscription.NodeType.TOPO, + "object_type": Subscription.ObjectType.HOST, + "scope_type": self.SCOPE_TYPE, + "scope_id": utils.SCOPE_ID, + } + scope["nodes"] = [{"bk_obj_id": "biz_set", "bk_inst_id": utils.SCOPE_ID}] + return scope + + def instance__host_scope(self, bk_biz_ids: typing.List[int]): + scope = { + "node_type": Subscription.NodeType.INSTANCE, + "object_type": Subscription.ObjectType.HOST, + "scope_type": self.SCOPE_TYPE, + "scope_id": utils.SCOPE_ID, + } + scope["nodes"] = [ + { + "bk_host_id": bk_biz_id, + "bk_biz_id": bk_biz_id, + } + for bk_biz_id in bk_biz_ids + ] + return scope + + def topo__host_scope_with_set(self, bk_biz_ids: typing.List[int]): + scope = { + "node_type": Subscription.NodeType.TOPO, + "object_type": Subscription.ObjectType.HOST, + "scope_type": self.SCOPE_TYPE, + "scope_id": utils.SCOPE_ID, + } + scope["nodes"] = [ + { + "bk_obj_id": "set", + "bk_inst_id": bk_biz_id, + "bk_biz_id": bk_biz_id, + } + for bk_biz_id in bk_biz_ids + ] + return scope + + def set_template__service_scope(self, bk_biz_ids: typing.List[int]): + scope = { + "node_type": Subscription.NodeType.SET_TEMPLATE, + "object_type": Subscription.ObjectType.SERVICE, + "scope_type": self.SCOPE_TYPE, + "scope_id": utils.SCOPE_ID, + } + scope["nodes"] = [ + { + "bk_obj_id": Subscription.NodeType.SET_TEMPLATE, + "bk_inst_id": bk_biz_id, + "bk_biz_id": bk_biz_id, + } + for bk_biz_id in bk_biz_ids + ] + return scope + + def test_covert_biz_set_scope_to_scope(self): + total_biz_ids = list(set(utils.BIZ_SET_COVERATE_BIZ_IDS + utils.BIZ_SET_NOT_COVERATE_BIZ_IDS)) + # biz_set_scope 过滤后只包括业务集内的 node + biz_set_scope = self.topo__host_scope_with_other_biz(total_biz_ids) + covert_biz_set_scope_to_scope(biz_set_scope=biz_set_scope, biz_set_id=utils.SCOPE_ID) + self.assertEqual(biz_set_scope, self.topo__host_scope_with_other_biz(utils.BIZ_SET_COVERATE_BIZ_IDS)) + + # 业务集转换为多业务 + biz_set_node_scope = self.topo__host_scope_with_biz_set() + covert_biz_set_scope_to_scope(biz_set_scope=biz_set_node_scope, biz_set_id=utils.SCOPE_ID) + self.assertEqual(biz_set_node_scope, self.topo__host_scope_with_other_biz(utils.BIZ_SET_COVERATE_BIZ_IDS)) + + # 主机范围过滤 + instance__host_scope = self.instance__host_scope(bk_biz_ids=total_biz_ids) + covert_biz_set_scope_to_scope(biz_set_scope=instance__host_scope, biz_set_id=utils.SCOPE_ID) + self.assertEqual(instance__host_scope, self.instance__host_scope(utils.BIZ_SET_COVERATE_BIZ_IDS)) + + # 集群范围过滤 + topo__host_with_set_scope = self.topo__host_scope_with_set(bk_biz_ids=total_biz_ids) + covert_biz_set_scope_to_scope(biz_set_scope=topo__host_with_set_scope, biz_set_id=utils.SCOPE_ID) + self.assertEqual(topo__host_with_set_scope, self.topo__host_scope_with_set(utils.BIZ_SET_COVERATE_BIZ_IDS)) + + # 集群模版过滤 + set_template__service_scope = self.set_template__service_scope(bk_biz_ids=total_biz_ids) + covert_biz_set_scope_to_scope(biz_set_scope=set_template__service_scope, biz_set_id=utils.SCOPE_ID) + self.assertEqual(set_template__service_scope, self.set_template__service_scope(utils.BIZ_SET_COVERATE_BIZ_IDS)) + + def test_list_business_in_business_set(self): + # 测试分批查询业务集场景下参数拼接 + params_list = [ + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": utils.SCOPE_ID, + "page": {"start": 0, "limit": 10, "enable_count": False, "sort": "bk_biz_id"}, + }, + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": utils.SCOPE_ID, + "page": {"start": 10, "limit": 10, "enable_count": False, "sort": "bk_biz_id"}, + }, + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": utils.SCOPE_ID, + "page": {"start": 20, "limit": 10, "enable_count": False, "sort": "bk_biz_id"}, + }, + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": utils.SCOPE_ID, + "page": {"start": 30, "limit": 10, "enable_count": False, "sort": "bk_biz_id"}, + }, + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": utils.SCOPE_ID, + "page": {"start": 40, "limit": 9, "enable_count": False, "sort": "bk_biz_id"}, + }, + ] + + self.assertEqual( + params_list, + CmdbHandler.splice_business_set_query( + biz_count=len(utils.BIZ_SET_COVERATE_BIZ_IDS), biz_set_id=utils.SCOPE_ID + ), + ) diff --git a/apps/backend/tests/subscription/test_views.py b/apps/backend/tests/subscription/test_views.py index 95ef378611..abbd1112b5 100644 --- a/apps/backend/tests/subscription/test_views.py +++ b/apps/backend/tests/subscription/test_views.py @@ -92,7 +92,14 @@ def _test_create_subscription(self): { "bk_username": "admin", "bk_app_code": "blueking", - "scope": {"bk_biz_id": 2, "node_type": "TOPO", "object_type": "SERVICE", "nodes": [{"id": 123}]}, + "run_immediately": True, + "scope": { + "scope_type": "BIZ_SET", + "scope_id": "10000002", + "node_type": "INSTANCE", + "object_type": "SERVICE", + "nodes": [{"id": 123, "bk_biz_id": 2}], + }, "steps": [ { "id": "my_first", @@ -147,8 +154,14 @@ def _test_update_subscription(self, subscription_id): { "bk_username": "admin", "bk_app_code": "blueking", + "run_immediately": True, "subscription_id": subscription_id, - "scope": {"node_type": "INSTANCE", "nodes": [{"bk_host_id": 100}]}, + "scope": { + "scope_type": "BIZ_SET", + "scope_id": "10000002", + "node_type": "INSTANCE", + "nodes": [{"bk_host_id": 100, "bk_biz_id": 100}], + }, "steps": [ { "id": "my_first", @@ -379,16 +392,11 @@ def _test_run_subscription(self): "bk_username": "admin", "bk_app_code": "blueking", "scope": { + "object_type": "HOST", "node_type": "INSTANCE", - "nodes": [ - { - "ip": "127.0.0.1", - "bk_cloud_id": "0", - "bk_supplier_id": "0", - "bk_obj_id": "biz", - "bk_inst_id": 32, - } - ], + "scope_type": "BIZ_SET", + "scope_id": "10000002", + "nodes": [{"ip": "127.0.0.1", "bk_cloud_id": "0", "bk_supplier_id": "0", "bk_biz_id": 2}], }, "actions": {"my_first": "INSTALL"}, "subscription_id": subscription_id, diff --git a/apps/backend/tests/subscription/utils.py b/apps/backend/tests/subscription/utils.py index 8ee6285b91..004b48171c 100644 --- a/apps/backend/tests/subscription/utils.py +++ b/apps/backend/tests/subscription/utils.py @@ -16,6 +16,20 @@ def set_username(cls, *args, **kwargs): return class cc(object): + @classmethod + def list_business_set(cls, *args, **kwargs): + return {"count": 1, "info": []} + + @classmethod + def list_business_in_business_set(cls, *args, **kwargs): + return { + "count": 2, + "info": [ + {"bk_biz_id": 2, "bk_biz_name": "TEST_BIZ", "default": 0}, + {"bk_biz_id": 5, "bk_biz_name": "TEST_BIZ_1", "default": 0}, + ], + } + @classmethod def list_biz_hosts(cls, *args, **kwargs): return { @@ -3346,6 +3360,25 @@ def list_biz_hosts_without_info_client(*args, **kwargs): return LIST_BIZ_HOSTS_WITHOUT_INFO +def list_biz_set_hosts_without_info_client(*args, **kwargs): + return [ + { + "bk_os_name": "linux centos", + "bk_host_id": bk_biz_id, + "operator": "", + "bk_host_name": f"VM_{index}_10_centos", + "bk_host_innerip": "127.0.0.{index}", + "bk_os_bit": "64-bit", + "bk_cloud_id": 0, + "bk_host_outerip": "", + "bk_os_type": "1", + "bk_bak_operator": "", + "bk_cpu_module": "AMD EPYC Processor", + } + for index, bk_biz_id in enumerate(BIZ_SET_COVERATE_BIZ_IDS) + ] + + LIST_BIZ_HOSTS_WITHOUT_INFO = [ { "bk_os_name": "linux centos", @@ -3362,3 +3395,46 @@ def list_biz_hosts_without_info_client(*args, **kwargs): } ] LIST_BIZ_HOSTS = FIND_HOST_BY_TOPO = {"count": 4, "info": LIST_BIZ_HOSTS_WITHOUT_INFO} + + +SCOPE_ID = 10000002 + +BIZ_SET_COVERATE_BIZ_IDS = [i for i in range(1, 50)] +BIZ_SET_NOT_COVERATE_BIZ_IDS = [i for i in range(51, 100)] + + +class BizSetCmdbClient(object): + class cc(object): + @classmethod + def list_business_set(cls, *args, **kwargs): + return {"count": 1, "info": []} + + @classmethod + def list_business_in_business_set(cls, *args, **kwargs): + info = [ + {"bk_biz_id": bk_biz_id, "bk_biz_name": f"test_biz_name_{index}", "default": 0} + for index, bk_biz_id in enumerate(BIZ_SET_COVERATE_BIZ_IDS) + ] + return {"count": len(BIZ_SET_COVERATE_BIZ_IDS), "info": info} + + @classmethod + def list_hosts_without_biz(cls, *args, **kwargs): + return { + "count": 1, + "info": [ + { + "bk_os_name": "linux centos", + "bk_host_id": 1, + "bk_os_version": "7.4.1708", + "operator": "", + "bk_host_name": "VM_1_10_centos", + "bk_host_innerip": "127.0.0.1", + "bk_os_bit": "64-bit", + "bk_cloud_id": 0, + "bk_host_outerip": "", + "bk_os_type": "1", + "bk_bak_operator": "", + "bk_cpu_module": "AMD EPYC Processor", + } + ], + } diff --git a/apps/node_man/handlers/cmdb.py b/apps/node_man/handlers/cmdb.py index 01a90eb27d..fa5e568896 100644 --- a/apps/node_man/handlers/cmdb.py +++ b/apps/node_man/handlers/cmdb.py @@ -584,6 +584,23 @@ def find_host_service_template(bk_host_ids: List[int]) -> List[Dict]: def get_biz_service_template(bk_biz_id: int) -> List[Dict]: return batch_request(client_v2.cc.list_service_template, {"bk_biz_id": bk_biz_id}) + @staticmethod + def splice_business_set_query(biz_count: int, biz_set_id: int): + prams_list = [ + { + "fields": ["bk_biz_id"], + "bk_biz_set_id": biz_set_id, + "page": { + "start": index * constants.QUERY_CMDB_LIMIT, + "limit": count, + "enable_count": False, + "sort": "bk_biz_id", + }, + } + for index, count in enumerate(basic.number_slice(biz_count, constants.QUERY_CMDB_LIMIT)) + ] + return prams_list + @staticmethod def list_biz_ids_in_biz_set(biz_set_ids: List[int]): group_bk_biz_ids: List[int] = [] @@ -606,21 +623,10 @@ def list_biz_ids_in_biz_set(biz_set_ids: List[int]): {"bk_biz_set_id": biz_set_id, "page": {"enable_count": True}} )["count"] ) - prams_list = [ - { - "fields": ["bk_biz_id"], - "bk_biz_set_id": biz_set_id, - "page": { - "start": index * constants.QUERY_CMDB_LIMIT, - "limit": count, - "enable_count": False, - "sort": "bk_biz_id", - }, - } - for index, count in enumerate(basic.number_slice(biz_count, constants.QUERY_CMDB_LIMIT)) - ] set__biz_info = request_multi_thread( - client_v2.cc.list_business_in_business_set, prams_list, get_data=lambda x: x["info"] + client_v2.cc.list_business_in_business_set, + CmdbHandler.splice_business_set_query(biz_count=biz_count, biz_set_id=biz_set_id), + get_data=lambda x: x["info"], ) group_bk_biz_ids.extend([x["bk_biz_id"] for x in set__biz_info]) return list(set(group_bk_biz_ids))