☰
蓝鲸配置平台 bk-cmdb:主机详情与拓扑树查询接口(findmany/hosts/detail_topo)实战指南
2026/10/12 1:49:54 网站建设 项目流程
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

蓝鲸智云配置平台(BlueKing CMDB)

项目地址:https://gitcode.com/gh_mirrors/bk/bk-cmdb
点击查看免费下载

本文基于蓝鲸智云配置平台(BlueKing CMDB,即 bk-cmdb)的 OpenAPI 文档,深入讲解POST /api/v3/findmany/hosts/detail_topo接口:它允许调用方基于主机属性条件一次查询出主机详情与主机在业务拓扑树中的完整位置(国家/省份/集群/模块等多层级节点)。读完本文,你将掌握该接口的请求参数结构、host_property_filter组合过滤规则的完整语法、分页控制方式、返回数据的拓扑树组装规则,以及它在 host_server 服务中的底层实现原理。

接口概述

detail_topo(即ListHostDetailAndTopology)是 bk-cmdb 面向 API 网关(APIGW)开放的主机查询接口,对应调用权限为主机池主机查看权限(Host pool host view permission)。它的核心能力是:根据主机条件信息查询主机详情及其拓扑信息。

从源码结构看,该接口在 host_server 路由注册 中注册为:

utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/findmany/hosts/detail_topo", Handler: s.ListHostDetailAndTopology})

对应处理器实现在 findhost.go。在权限解析层面,ac/parser/host.go 将其匹配为meta.HostInstance类型的FindMany动作,即按主机实例的批量查看权限进行鉴权。

该接口与按业务查询主机的list_hosts_topo(/hosts/app/{bk_biz_id}/list_hosts_topo)不同:detail_topo不要求调用方在 URL 中携带业务 ID,而是完全依靠主机属性过滤条件(host_property_filter)圈定主机范围,并返回每台主机在拓扑中的多级父节点链路,适合主机池(资源池)场景下的主机检索与定位。

请求参数详解

接口为POST,请求体为 JSON。核心参数如下:

名称类型必填说明
pagedict是分页查询条件
host_property_filterobject否主机属性组合查询条件
fieldsarray是需要返回的主机属性字段列表,按需填写

对应的请求体结构定义在 metadata/hostserver.go 中:

type ListHostsDetailAndTopoOption struct { WithBiz bool `json:"with_biz"` HostPropertyFilter *querybuilder.QueryFilter `json:"host_property_filter"` Fields []string `json:"fields"` Page BasePage `json:"page"` }

其中with_biz是一个可选增强字段(文档未列出但在源码中已支持):置为true时返回的拓扑树会带上业务节点,同时服务端会对涉及的业务做ViewBusinessResource级别的实例鉴权(见 findhost.go)。

fields:按需裁剪返回字段

fields用于控制响应中主机属性部分返回哪些字段。服务端在实现中会把bk_host_id强制追加进查询字段(见 findhost.go),因为后续拓扑编排依赖主机 ID 关联主机与模块关系:

option := &meta.ListHosts{ HostPropertyFilter: options.HostPropertyFilter, Fields: append(options.Fields, common.BKHostIDField), Page: options.Page, }

若fields为空,参数校验会直接返回参数错误(见 metadata/hostserver.go),因此fields是必填项。

page:分页控制

名称类型必填说明
startint是记录起始位置(从 0 开始)
limitint是每页记录数,最大值为 500
sortstring否排序字段

分页结构对应metadata.BasePage(page.go)。在ListHostsDetailAndTopoOption.Validate()中,limit上限被进一步约束为common.BKMaxInstanceLimit(即 500),start不允许为负数(见 metadata/hostserver.go)。建议显式指定sort(例如bk_host_id),保证多次分页取数时结果顺序稳定。

host_property_filter:主机属性组合过滤

该参数用于基于主机属性字段搜索主机,组合支持AND 与 OR,最多可嵌套两层(即查询条件最大深度为 3)。过滤规则是field、operator、value四元组(实际是 field/operator/value 三元组加组合节点)。

名称类型必填说明
conditionstring否组合查询条件:AND或OR
rulesarray否过滤规则列表

rules中的每条规则:

名称类型必填说明
fieldstring是字段名称
operatorstring是操作符,可选值:equal、not_equal、in、not_in、less、less_or_equal、greater、greater_or_equal、between、not_between
value-否操作数,不同操作符对应不同取值格式

说明:文档所列操作符与 querybuilder 模块当前实现存在差异——between/not_between目前不在 types.go 的SupportOperators集合中,README也明确说明不支持between/not_between,此类区间比较可基于greater_or_equal与less_or_equal组合实现。当前完整支持的操作符包括:equal、not_equal、in、not_in、less、less_or_equal、greater、greater_or_equal,以及时间比较类datetime_less、datetime_less_or_equal、datetime_greater、datetime_greater_or_equal、字符串类begins_with、not_begins_with、contains、not_contains、ends_with、not_ends_with、数组类is_empty、is_not_empty、空值类is_null、is_not_null、字段存在类exist、not_exist。

各操作符的 value 格式要求(详见 types.go 与 validate.go):

操作符类别操作符value 格式
通用比较equal/not_equal基本类型:数值、布尔、字符串
集合比较in/not_in基本类型数组,元素类型需一致(NeedSameSliceElementType)
数值比较less/less_or_equal/greater/greater_or_equal数值
时间比较datetime_*系列RFC3339 时间字符串或日期字符串
字符串匹配begins_with/contains/ends_with及其not_变体非空字符串
数组空值is_empty/is_not_empty不接受参数
空值判断is_null/is_not_null不接受参数
字段存在exist/not_exist不接受参数

组合规则深度的限制:querybuilder.MaxDeep = 3(types.go),即最外层的 AND/OR 组合节点算第 1 层,最多嵌套两层子组合,最内层为原子规则。超出深度上限会在 Validate 中被拦截,返回host_property_filter exceeded max allowed deep。

过滤规则的底层转换:host_property_filter在 metadata/hostserver.go 中被校验后,会通过QueryFilter.ToMgo()转换为 MongoDB 查询条件(见 types.go),例如equal转为$eq、in转为$in、contains转为大小写不敏感的$regex等,随后由 coreservice 的Host().ListHosts()在 MongoDB 中执行(调用链见 findhost.go 与 apimachinery/coreservice/host/api.go)。

请求示例

以下请求示例综合演示了page、fields与双层嵌套的host_property_filter(原文档示例):

{ "page": { "start": 0, "limit": 10, "sort": "bk_host_id" }, "fields": [ "bk_host_id", "bk_host_innerip" ], "host_property_filter": { "condition": "AND", "rules": [ { "field": "bk_host_innerip", "operator": "equal", "value": "192.168.1.1" }, { "condition": "OR", "rules": [ { "field": "bk_os_type", "operator": "not_in", "value": [ "3" ] }, { "field": "bk_cloud_id", "operator": "equal", "value": 0 } ] } ] } }

该请求的语义为:查询内网 IP 为192.168.1.1,并且(操作系统类型不在["3"]中或管控区域 ID 等于 0)的主机,每页取 10 条,按bk_host_id升序,返回字段仅含bk_host_id与bk_host_innerip。

注意in/not_in的 value 必须是数组(如上例["3"]),equal的 value 可直接为标量;数组元素类型需一致,且数组长度默认上限为 500(DefaultMaxSliceElementsCount,见 types.go)。

响应结构与返回参数

通用响应封装

名称类型说明
resultbool请求是否成功:true成功;false失败
codeint错误码:0表示成功,>0表示失败
messagestring失败时返回的错误信息
permissionobject权限信息
dataobject请求返回的数据

data 结构

名称类型说明
countint记录总数
infoarray主机数据与拓扑信息列表

其中info数组的每个元素包含:

名称类型说明
hostdict主机实际数据
topoarray主机拓扑信息

响应示例(原文档完整示例)

{ "result": true, "code": 0, "message": "success", "permission": null, "data": { "count": 2, "info": [ { "host": { "bk_host_id": 2, "bk_host_innerip": "192.168.1.1" }, "topo": [ { "inst": { "obj": "nation", "name": "中国", "id": 30 }, "children": [ { "inst": { "obj": "province", "name": "prov-xxx", "id": 31 }, "children": [ { "inst": { "obj": "set", "name": "set-xxx", "id": 20 }, "children": [ { "inst": { "obj": "module", "name": "mod-xxx", "id": 52 }, "children": null }, { "inst": { "obj": "module", "name": "mod-yy", "id": 53 }, "children": null } ] } ] } ] }, { "inst": { "obj": "nation", "name": "国家", "id": 29 }, "children": [ { "inst": { "obj": "province", "name": "prv1", "id": 26 }, "children": [ { "inst": { "obj": "set", "name": "set11", "id": 19 }, "children": [ { "inst": { "obj": "module", "name": "m22", "id": 51 }, "children": null } ] } ] } ] } ] }, { "host": { "bk_host_id": 4, "bk_host_innerip": "192.168.1.2" }, "topo": [ { "inst": { "obj": "set", "name": "空闲机池", "id": 2 }, "children": [ { "inst": { "obj": "module", "name": "故障机", "id": 4 }, "children": null } ] } ] } ] } }

从示例可以看到拓扑树的两种形态:业务自定义层级的主机返回从自定义模型(如nation、province)到set、module的多级父节点链;位于空闲机池的主机则直接返回set(空闲机池)→module(故障机/空闲机)的两级结构。

host 字段说明

data.info.host中返回的字段由请求fields决定。以下为系统内置主机属性字段说明(其余返回值取决于用户自定义属性字段):

字段类型说明
bk_host_namestring主机名
bk_host_inneripstring主机内网 IP
bk_host_idint主机 ID
bk_cloud_idint管控区域
import_fromstring主机导入来源,3表示 API 导入
bk_asset_idstring固定资产编号
bk_cloud_inst_idstring云主机实例 ID
bk_cloud_vendorstring云厂商
bk_cloud_host_statusstring云主机状态
bk_commentstring备注
bk_cpuintCPU 逻辑核数
bk_cpu_architecturestringCPU 架构
bk_cpu_modulestringCPU 型号
bk_diskint磁盘容量(GB)
bk_host_outeripstring主机外网 IP
bk_host_innerip_v6string主机内网 IPv6
bk_host_outerip_v6string主机外网 IPv6
bk_isp_namestring运营商名称
bk_macstring主机内网 MAC 地址
bk_memint主机内存容量(MB)
bk_os_bitstring操作系统位数
bk_os_namestring操作系统名称
bk_os_typestring操作系统类型
bk_os_versionstring操作系统版本
bk_outer_macstring主机外网 MAC 地址
bk_province_namestring主机所在省份
bk_service_termint保修年限
bk_slastringSLA 级别
bk_snstring设备序列号
bk_statestring当前状态
bk_state_namestring主机所在国家
operatorstring主要维护人
bk_bak_operatorstring备份维护人

topo 节点结构

data.info.topo是递归的树形结构,节点定义如下:

名称类型说明
instobject节点实例详情
inst.objstring节点的模型类型,如set、module及自定义层级模型类型
inst.namestring节点实例名称
inst.idint节点实例 ID
childrenobject array当前实例的子节点详情,可能有多条
children.instobject子节点的实例详情
children.childrenstring当前实例的子节点详情(递归结构)

该结构与源码中的HostDetailWithTopo/HostTopoNode/NodeInstance一一对应(metadata/hostserver.go):

type HostDetailWithTopo struct { Host map[string]interface{} `json:"host"` Topo []*HostTopoNode `json:"topo"` } type HostTopoNode struct { Instance *NodeInstance `json:"inst"` Children []*HostTopoNode `json:"children"` } type NodeInstance struct { Object string `json:"obj"` InstName interface{} `json:"name"` InstID interface{} `json:"id"` }

底层实现原理:拓扑树是如何组装出来的

detail_topo的处理器实现位于 findhost.go,其执行流程分为四步:

  1. 参数校验:ListHostsDetailAndTopoOption.Validate()校验page、过滤规则深度与fields非空;
  2. 查询主机:调用CoreService().Host().ListHosts(),并把bk_host_id追加到fields后查询;查询读取策略设置为SecondaryPreferredMode(优先从 MongoDB 从节点读取,降低主库压力);
  3. 编排拓扑:调用Logic.ArrangeHostDetailAndTopology()组装每台主机的拓扑树;
  4. 可选鉴权与响应:若with_biz=true且开启了权限中心(AuthManager),对涉及的业务执行ViewBusinessResource鉴权,最终以count + info形式返回。

ArrangeHostDetailAndTopology的编排过程(logics/host.go)是理解返回结果的关键:

  • 获取主模型链(mainline)排序:通过getTopologyRank()读取模型关联中的主模型关联(AssociationKindMainline),构建从biz → ... → set → module的模型层级顺序(logics/host.go);
  • 读取主机-模块关系:批量查询主机归属的bk_app_id、bk_set_id、bk_module_id,建立host → module映射;
  • 获取内置对象详情:批量拉取涉及的业务、集群、模块的实例信息(getInnerObjectDetails);
  • 获取自定义模型实例:基于主模型链,自下而上地以集群的父实例 ID 逐层查出业务下自定义模型(如nation、province)的实例(getCustomTopoInfo);
  • 组装树:按从顶层到module的层级逆序(rank反转),把每个节点的obj、name、id以及children递归拼装成树形结构(rearrangeHostDetailAndTopo)。

这一设计与 CMDB 的“主线模型”(mainline)概念强相关:业务下既存在set(集群)、module(模块)这类内置模型,也允许用户自定义中间层级模型(如国家、省份),主机通过这些层级挂载到业务拓扑上。

使用建议与注意事项

  1. 过滤条件优先缩小范围:host_property_filter支持两层嵌套,建议把筛选性强的条件(如bk_host_innerip)放在最外层 AND 中,缩小主机集后再用 OR 扩展条件,减少全量扫描。
  2. 分页取数要排序:limit最大 500,遍历大批量主机时应固定sort(如bk_host_id),避免翻页数据错乱或重复。
  3. 返回字段按需裁剪:fields只声明业务侧真正需要的字段(如bk_host_id、bk_host_innerip、bk_host_name),可显著降低响应体与网络开销;服务端会自行追加bk_host_id用于拓扑关联,无需调用方传入。
  4. 拓扑树的业务范围:接口不通过 URL 指定业务,返回的topo是主机实际归属的拓扑链路;同一主机可能出现多个顶层父节点(如同时位于不同自定义层级下),因此topo是数组而非单一节点。
  5. 权限要求:调用方需具备主机池主机查看权限;若开启with_biz,还会对涉及业务进行查看级实例鉴权,未授权时会返回权限错误。
  6. 操作符兼容性:文档中列出的between/not_between在当前版本 querybuilder 中未实现,请改用greater_or_equal+less_or_equal组合表达区间条件;in/not_in数组元素必须类型一致。

参考资料

  • 关联 API 文档:list_host_detail_topology.md
  • 接口实现:findhost.go
  • 路由注册:service_initfunc.go
  • 请求/响应结构定义:metadata/hostserver.go、metadata/hostserver.go
  • 拓扑编排逻辑:logics/host.go、logics/host.go
  • 组合过滤规则引擎:querybuilder 说明文档、types.go、validate.go
  • 权限解析:ac/parser/host.go
  • 主机列表查询封装:apimachinery/coreservice/host/api.go
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

蓝鲸智云配置平台(BlueKing CMDB)

项目地址:https://gitcode.com/gh_mirrors/bk/bk-cmdb
点击查看免费下载

相关推荐

上一篇:en_PP-OCRv5_mobile_rec_safetensors核心技术解析:轻量化MobileNet架构深度剖析 🚀
下一篇:无需Steam也能玩转创意工坊?5个跨平台解决方案实测

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询