def execute(self, data, parent_data): operator = parent_data.get_one_of_inputs("executor") client = get_client_by_user(operator) biz_cc_id = parent_data.get_one_of_inputs("biz_cc_id") sa_ip_list = data.get_one_of_inputs("cc_ip_list") custom_property = data.get_one_of_inputs("cc_custom_property") host_rule = data.get_one_of_inputs("cc_hostname_rule") custom_rule = data.get_one_of_inputs("cc_custom_rule") hostname_rule = [] if host_rule: hostname_rule.extend(host_rule) if custom_rule: hostname_rule.extend(custom_rule) if not hostname_rule: data.set_outputs("ex_data", _("请选择至少一种规则")) return False hostname_rule = sorted(hostname_rule, key=lambda e: str(e.__getitem__("field_order"))) ip_list = cc_get_ips_info_by_str(username=operator, biz_cc_id=biz_cc_id, ip_str=sa_ip_list, use_cache=False) if not ip_list["result"] or not ip_list["ip_count"]: data.outputs.ex_data = _("无法从配置平台(CMDB)查询到对应 IP,请确认输入的 IP 是否合法") return False if ip_list["invalid_ip"]: data.outputs.ex_data = _("无法从配置平台(CMDB)查询到对应 IP,请确认输入的 IP 是否合法") data.outputs.invalid_ip = ",".join(ip_list["invalid_ip"]) return False # 规则中包含的自增变量个数 inc_num = 0 host_rule_list = [] set_rule_list = [] module_rule_list = [] for rule in hostname_rule: if rule["field_rule_code"] == self.FileCode.host_rule and rule[ "field_content"] not in host_rule_list: host_rule_list.append(rule["field_content"]) if rule["field_rule_code"] == self.FileCode.set_rule and rule[ "field_content"] not in set_rule_list: set_rule_list.append(rule["field_content"]) if rule["field_rule_code"] == self.FileCode.module_rule and rule[ "field_content"] not in module_rule_list: module_rule_list.append(rule["field_content"]) if rule["field_rule_code"] == self.FileCode.auto_var_rule: inc_num += 1 # 如果集群规则不为空,拉取集群属性信息 set_property = {} if set_rule_list: # 获取所有的集群id和模型id set_id_list = [] for host_data in ip_list["ip_result"]: id_list = [_set["bk_set_id"] for _set in host_data["Sets"]] set_id_list.extend(id_list) set_rule_list.append("bk_set_id") # 查询集群的属性值 set_kwargs = { "bk_biz_id": biz_cc_id, "bk_ids": list(set(set_id_list)), "fields": set_rule_list } set_result = client.cc.find_set_batch(set_kwargs) if not set_result.get("result"): error_message = handle_api_error("蓝鲸配置平台(CC)", "cc.find_set_batch", set_kwargs, set_result) data.set_outputs("ex_data", error_message) self.logger.error(error_message) return False for set_data in set_result["data"]: set_property[set_data["bk_set_id"]] = set_data # 如果模块规则不为空,拉取模块属性信息 module_property = {} if module_rule_list: module_id_list = [] for host_data in ip_list["ip_result"]: id_list = [ _module["bk_module_id"] for _module in host_data["Modules"] ] module_id_list.extend(id_list) module_rule_list.append("bk_module_id") # 查询模块的属性值 module_kwargs = { "bk_biz_id": biz_cc_id, "bk_ids": list(set(module_id_list)), "fields": module_rule_list } module_result = client.cc.find_module_batch(module_kwargs) if not module_result.get("result"): error_message = handle_api_error("蓝鲸配置平台(CC)", "cc.find_module_batch", module_kwargs, module_result) data.set_outputs("ex_data", error_message) self.logger.error(error_message) return False for module_data in module_result["data"]: module_property[module_data["bk_module_id"]] = module_data # 数据组装,将规则连接起来,并和ip对应 host_list = [] # 自增变量 inc = [-1] * inc_num for host in ip_list["ip_result"]: custom_property_value = "" inc_num_temp = 0 # 主机属性 host_kwargs = {"bk_host_id": host["HostID"]} host_result = client.cc.get_host_base_info(**host_kwargs) if not host_result.get("result"): error_message = handle_api_error("蓝鲸配置平台(CC)", "cc.get_host_base_info", host_kwargs, host_result) data.set_outputs("ex_data", error_message) self.logger.error(error_message) return False host_content = {} for host_prop in host_result["data"]: if host_prop["bk_property_id"] in host_rule_list: host_content[host_prop["bk_property_id"]] = host_prop[ "bk_property_value"] for rule in hostname_rule: if rule["field_rule_code"] == self.FileCode.host_rule and host_content[ rule["field_content"]]: custom_property_value += host_content[ rule["field_content"]] if rule["field_rule_code"] == self.FileCode.set_rule: # 集群属性 set_content_list = [ set_property[_set["bk_set_id"]] for _set in host["Sets"] ] for set_content in set_content_list: if set_content.get(rule["field_content"]): custom_property_value += set_content[ rule["field_content"]] if rule["field_rule_code"] == self.FileCode.module_rule: # 模块属性 module_content_list = [ module_property[_module["bk_module_id"]] for _module in host["Modules"] ] for module_content in module_content_list: if module_content.get(rule["field_content"]): custom_property_value += module_content[ rule["field_content"]] if rule["field_rule_code"] == self.FileCode.ip_type_rule: custom_property_value += host["InnerIP"].replace( ".", rule["field_content"]) # 第一个自增变量 if rule["field_rule_code"] == self.FileCode.auto_var_rule: if inc[inc_num_temp] == -1: inc[inc_num_temp] = int(rule["field_content"]) else: inc[inc_num_temp] += 1 custom_property_value += str(inc[inc_num_temp]) inc_num_temp += 1 # 自定义字符串 if rule["field_rule_code"] == self.FileCode.custom_string: custom_property_value += rule["field_content"] host_list.append({ "bk_host_id": host["HostID"], "properties": { custom_property: custom_property_value } }) kwargs = {"update": host_list} result = client.cc.batch_update_host(kwargs) if not result["result"]: message = cc_handle_api_error("cc.batch_update_host", kwargs, result) self.logger.error(message) data.set_outputs("ex_data", message) return False return True
def test_cloud_ip_format_with_multi_innerip(self): ip_str = "0:1.1.1.1,0:2.2.2.2\n0:3.3.3.3,0:4.4.4.4" get_business_host_topo_return = [ { "host": { "bk_host_id": 1, "bk_host_innerip": "1.2.3.4,1.1.1.1", "bk_cloud_id": 0 }, "module": [{ "bk_module_id": 1, "bk_module_name": "module_1" }], "set": [{ "bk_set_id": 1, "bk_set_name": "set_1" }], }, { "host": { "bk_host_id": 2, "bk_host_innerip": "", "bk_cloud_id": 0 }, "module": [{ "bk_module_id": 2, "bk_module_name": "module_2" }], "set": [{ "bk_set_id": 2, "bk_set_name": "set_2" }], }, { "host": { "bk_host_id": 3, "bk_host_innerip": "3.3.3.3", "bk_cloud_id": 0 }, "module": [{ "bk_module_id": 3, "bk_module_name": "module_3" }], "set": [{ "bk_set_id": 3, "bk_set_name": "set_3" }], }, ] cmdb = MagicMock() cmdb.get_business_host_topo = MagicMock( return_value=get_business_host_topo_return) supplier_account_for_business = MagicMock( return_value=self.supplier_account) with patch( "pipeline_plugins.components.utils.sites.open.utils.supplier_account_for_business", supplier_account_for_business, ): with patch( "pipeline_plugins.components.utils.sites.open.utils.cmdb", cmdb): result = cc_get_ips_info_by_str(username=self.username, biz_cc_id=self.biz_cc_id, ip_str=ip_str) supplier_account_for_business.assert_called_once_with(self.biz_cc_id) cmdb.get_business_host_topo.assert_called_once_with( username=self.username, bk_biz_id=self.biz_cc_id, supplier_account=self.supplier_account, host_fields=["bk_host_innerip", "bk_host_id", "bk_cloud_id"], ip_list=["1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"], ) self.assertEqual(result["result"], True) self.assertEqual( result["ip_result"], [ { "InnerIP": "1.1.1.1", "HostID": 1, "Source": 0, "Sets": [{ "bk_set_id": 1, "bk_set_name": "set_1" }], "Modules": [{ "bk_module_id": 1, "bk_module_name": "module_1" }], }, { "InnerIP": "3.3.3.3", "HostID": 3, "Source": 0, "Sets": [{ "bk_set_id": 3, "bk_set_name": "set_3" }], "Modules": [{ "bk_module_id": 3, "bk_module_name": "module_3" }], }, ], ) self.assertEqual(result["ip_count"], 2) self.assertEqual(set(result["invalid_ip"]), {"2.2.2.2", "4.4.4.4"})
def execute(self, data, parent_data): biz_cc_id = parent_data.get_one_of_inputs("biz_cc_id") executor = parent_data.get_one_of_inputs("executor") client = get_client_by_user(executor) supplier_account = supplier_account_for_business(biz_cc_id) language = parent_data.get_one_of_inputs("language") host_update_method = data.get_one_of_inputs("cc_host_update_method") host_property_custom = data.get_one_of_inputs( "cc_host_property_custom") separator = data.get_one_of_inputs("cc_auto_separator") host_property_custom = convert_num_to_str(host_property_custom) if host_update_method == "auto": host_property_data = [] for column in host_property_custom: column_result = chunk_table_data(column, separator) if not column_result["result"]: message = _("单行扩展失败,请检查输入参数格式是否合法, error={}".format( column_result["message"])) data.outputs.ex_data = message self.logger.error(message) return False host_property_data.extend(column_result["data"]) host_property_custom = host_property_data bk_host_innerip_list = [] for host in host_property_custom: bk_host_innerip_list.append(host["bk_host_innerip"]) ip_str = ",".join(bk_host_innerip_list) ip_list = cc_get_ips_info_by_str(username=executor, biz_cc_id=biz_cc_id, ip_str=ip_str, use_cache=False) if not ip_list["result"] or not ip_list["ip_count"]: data.outputs.ex_data = _("无法从配置平台(CMDB)查询到对应 IP,请确认输入的 IP 是否合法") return False if ip_list["invalid_ip"]: data.outputs.ex_data = _("无法从配置平台(CMDB)查询到对应 IP,请确认输入的 IP 是否合法") data.outputs.invalid_ip = ",".join(ip_list["invalid_ip"]) return False ip_dir = {} for host in ip_list["ip_result"]: ip_dir.update({host["InnerIP"]: host["HostID"]}) # do not operate inputs data directly host_property_copy = deepcopy(host_property_custom) update_host_message = [] for host_property_dir in host_property_copy: inner_host_ip = host_property_dir["bk_host_innerip"] # 兼容填写云区域ID:IP的情况, 只获取对应IP if ":" in inner_host_ip: inner_host_ip = inner_host_ip.split(":")[1] if inner_host_ip not in ip_dir: message = _("innerip【{}】找不到对应的host_id".format(inner_host_ip)) data.outputs.ex_data = message self.logger.error(message) return False host_id = ip_dir[inner_host_ip] host_update = {"bk_host_id": host_id} host_property_dir.pop("bk_host_innerip") properties = {} for cc_host_property, cc_host_prop_value in host_property_dir.items( ): if cc_host_prop_value: is_legal, ex_data = verify_host_property( executor, supplier_account, language, cc_host_property, cc_host_prop_value) if not is_legal: data.outputs.ex_data = ex_data self.logger.error(ex_data) return False properties[cc_host_property] = cc_host_prop_value host_update["properties"] = properties update_host_message.append(host_update) cc_kwargs = { "bk_supplier_account": supplier_account, "update": update_host_message } cc_result = client.cc.batch_update_host(cc_kwargs) if cc_result["result"]: return True else: message = cc_handle_api_error("cc.batch_update_host", cc_kwargs, cc_result) self.logger.error(message) data.set_outputs("ex_data", message) return False
def get_value(self): if "executor" not in self.pipeline_data or "project_id" not in self.pipeline_data: return "ERROR: executor and project_id of pipeline is needed" var_ip_selector = self.value username = self.pipeline_data["executor"] project_id = self.pipeline_data["project_id"] project = Project.objects.get(id=project_id) bk_biz_id = project.bk_biz_id if project.from_cmdb else "" bk_supplier_account = supplier_account_for_project(project_id) # 筛选集群 filter_set = var_ip_selector["var_filter_set"] # 筛选模块 filter_service_template = var_ip_selector["var_filter_module"] # 输入方式 produce_method = var_ip_selector["var_ip_method"] if produce_method == "custom": # 自定义输入ip custom_value = var_ip_selector["var_ip_custom_value"] ip_filter_result = cc_get_ips_info_by_str(username, bk_biz_id, custom_value) # 过滤输入的ip ip_filter_result_list = ",".join( [ip["InnerIP"] for ip in ip_filter_result["ip_result"]]) logger.info( "[SetModuleIpSelector.get_value] ip_filter_result_list: %s" % ip_filter_result_list) # 根据输入获取空闲机module id service_template_list = get_service_template_list( username, bk_biz_id, bk_supplier_account) # 如果勾选的set中有空闲机池,则会将所有空闲机module id添加进去 service_template_list.extend( get_biz_inner_module_list( var_ip_selector, username, bk_biz_id, bk_supplier_account, produce_method, )) # 通过集群模块筛选的ip module_ids = get_module_id_list( bk_biz_id, username, get_set_list(username, bk_biz_id, bk_supplier_account), service_template_list, filter_set, filter_service_template, bk_supplier_account, ) logger.info("[SetModuleIpSelector.get_value] module_ids: %s" % module_ids) set_module_filter_ip_list = get_ip_list_by_module_id( username, bk_biz_id, bk_supplier_account, module_ids) # 获取在集群模块筛选的ip列表中的自定义输入ip data = filter_ip(ip_filter_result_list, set_module_filter_ip_list) elif produce_method == "select": set_input_method = "var_set" module_input_method = "var_module" data = get_ip_result_by_input_method( set_input_method, module_input_method, var_ip_selector, username, bk_biz_id, bk_supplier_account, filter_set, filter_service_template, produce_method, var_module_name=var_ip_selector["var_ip_manual_value"] ["var_module_name"], ) elif produce_method == "manual": set_input_method = "var_manual_set" module_input_method = "var_manual_module" data = get_ip_result_by_input_method( set_input_method, module_input_method, var_ip_selector, username, bk_biz_id, bk_supplier_account, filter_set, filter_service_template, produce_method, var_module_name=var_ip_selector["var_ip_select_value"] ["var_module_name"], ) else: # 输入ip方式不存在 logger.error( "[SetModuleIpSelector.get_value] input ip method: {} not exit". format(produce_method)) data = "" return data