- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing 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。核心参数如下:
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
page | dict | 是 | 分页查询条件 |
host_property_filter | object | 否 | 主机属性组合查询条件 |
fields | array | 是 | 需要返回的主机属性字段列表,按需填写 |
对应的请求体结构定义在 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:分页控制
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
start | int | 是 | 记录起始位置(从 0 开始) |
limit | int | 是 | 每页记录数,最大值为 500 |
sort | string | 否 | 排序字段 |
分页结构对应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 三元组加组合节点)。
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
condition | string | 否 | 组合查询条件:AND或OR |
rules | array | 否 | 过滤规则列表 |
rules中的每条规则:
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
field | string | 是 | 字段名称 |
operator | string | 是 | 操作符,可选值: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)。
响应结构与返回参数
通用响应封装
| 名称 | 类型 | 说明 |
|---|---|---|
result | bool | 请求是否成功:true成功;false失败 |
code | int | 错误码:0表示成功,>0表示失败 |
message | string | 失败时返回的错误信息 |
permission | object | 权限信息 |
data | object | 请求返回的数据 |
data 结构
| 名称 | 类型 | 说明 |
|---|---|---|
count | int | 记录总数 |
info | array | 主机数据与拓扑信息列表 |
其中info数组的每个元素包含:
| 名称 | 类型 | 说明 |
|---|---|---|
host | dict | 主机实际数据 |
topo | array | 主机拓扑信息 |
响应示例(原文档完整示例)
{ "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_name | string | 主机名 |
bk_host_innerip | string | 主机内网 IP |
bk_host_id | int | 主机 ID |
bk_cloud_id | int | 管控区域 |
import_from | string | 主机导入来源,3表示 API 导入 |
bk_asset_id | string | 固定资产编号 |
bk_cloud_inst_id | string | 云主机实例 ID |
bk_cloud_vendor | string | 云厂商 |
bk_cloud_host_status | string | 云主机状态 |
bk_comment | string | 备注 |
bk_cpu | int | CPU 逻辑核数 |
bk_cpu_architecture | string | CPU 架构 |
bk_cpu_module | string | CPU 型号 |
bk_disk | int | 磁盘容量(GB) |
bk_host_outerip | string | 主机外网 IP |
bk_host_innerip_v6 | string | 主机内网 IPv6 |
bk_host_outerip_v6 | string | 主机外网 IPv6 |
bk_isp_name | string | 运营商名称 |
bk_mac | string | 主机内网 MAC 地址 |
bk_mem | int | 主机内存容量(MB) |
bk_os_bit | string | 操作系统位数 |
bk_os_name | string | 操作系统名称 |
bk_os_type | string | 操作系统类型 |
bk_os_version | string | 操作系统版本 |
bk_outer_mac | string | 主机外网 MAC 地址 |
bk_province_name | string | 主机所在省份 |
bk_service_term | int | 保修年限 |
bk_sla | string | SLA 级别 |
bk_sn | string | 设备序列号 |
bk_state | string | 当前状态 |
bk_state_name | string | 主机所在国家 |
operator | string | 主要维护人 |
bk_bak_operator | string | 备份维护人 |
topo 节点结构
data.info.topo是递归的树形结构,节点定义如下:
| 名称 | 类型 | 说明 |
|---|---|---|
inst | object | 节点实例详情 |
inst.obj | string | 节点的模型类型,如set、module及自定义层级模型类型 |
inst.name | string | 节点实例名称 |
inst.id | int | 节点实例 ID |
children | object array | 当前实例的子节点详情,可能有多条 |
children.inst | object | 子节点的实例详情 |
children.children | string | 当前实例的子节点详情(递归结构) |
该结构与源码中的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,其执行流程分为四步:
- 参数校验:
ListHostsDetailAndTopoOption.Validate()校验page、过滤规则深度与fields非空; - 查询主机:调用
CoreService().Host().ListHosts(),并把bk_host_id追加到fields后查询;查询读取策略设置为SecondaryPreferredMode(优先从 MongoDB 从节点读取,降低主库压力); - 编排拓扑:调用
Logic.ArrangeHostDetailAndTopology()组装每台主机的拓扑树; - 可选鉴权与响应:若
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(模块)这类内置模型,也允许用户自定义中间层级模型(如国家、省份),主机通过这些层级挂载到业务拓扑上。
使用建议与注意事项
- 过滤条件优先缩小范围:
host_property_filter支持两层嵌套,建议把筛选性强的条件(如bk_host_innerip)放在最外层 AND 中,缩小主机集后再用 OR 扩展条件,减少全量扫描。 - 分页取数要排序:
limit最大 500,遍历大批量主机时应固定sort(如bk_host_id),避免翻页数据错乱或重复。 - 返回字段按需裁剪:
fields只声明业务侧真正需要的字段(如bk_host_id、bk_host_innerip、bk_host_name),可显著降低响应体与网络开销;服务端会自行追加bk_host_id用于拓扑关联,无需调用方传入。 - 拓扑树的业务范围:接口不通过 URL 指定业务,返回的
topo是主机实际归属的拓扑链路;同一主机可能出现多个顶层父节点(如同时位于不同自定义层级下),因此topo是数组而非单一节点。 - 权限要求:调用方需具备主机池主机查看权限;若开启
with_biz,还会对涉及业务进行查看级实例鉴权,未授权时会返回权限错误。 - 操作符兼容性:文档中列出的
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)
相关推荐
蓝鲸配置平台(bk-cmdb)get_biz_brief_cache_topo 接口详解:查询业务简要拓扑树缓存
蓝鲸配置平台(bk cmdb)get_biz_brief_cache_topo 接口详解:查询业务简要拓扑树缓存 导读 本文围绕蓝鲸智云配置平台(BlueKin
后端企业应用运维蓝鲸 CMDB(bk-cmdb)查询业务拓扑树简要信息接口 find_biz_tree_brief_info 实战指南
蓝鲸 CMDB(bk cmdb)查询业务拓扑树简要信息接口 find_biz_tree_brief_info 实战指南 本文深入讲解蓝鲸智云配置平台(BlueK
后端企业应用运维蓝鲸配置平台(bk-cmdb)按审计 ID 查询操作审计详情接口实战指南
蓝鲸配置平台(bk cmdb)按审计 ID 查询操作审计详情接口实战指南 导读 本文围绕蓝鲸智云配置平台(bk cmdb)开放 API 网关后端接口 find_
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考