蓝鲸配置平台 ESB 接口实战:transfer_host_to_resourcemodule 上交主机至资源池
蓝鲸配置平台 ESB 接口实战:transfer_host_to_resourcemodule 上交主机至资源池
本篇技术指南聚焦蓝鲸智云配置平台(BlueKing CMDB)ESB 组件 transfer_host_to_resourcemodule 接口的完整用法:如何将业务空闲机池下的主机上交(回收)至资源池,包括请求参数语义、默认转移目录规则、返回结构、权限模型,以及从 ESB 网关到 coreservice 底层的完整调用链与关键校验逻辑。读完本文,你将能够准确构造请求、解读响应与错误码,并理解该操作在"业务主机池 → 资源池"生命周期管理中的位置与限制。
该接口属于早期由 ESB 维护并封装的 CMDB 组件文档(见 docs/apidoc/esb-cc/README.md,该目录内容需保留、不新增接口),文档同时提供英文版本(docs/apidoc/esb-cc/en/transfer_host_to_resourcemodule.md)。
接口概览:功能与适用场景
功能描述:上交主机至资源池,操作权限为"主机归还主机池"权限。
在 CMDB 的资源管理中,主机在"业务"与"资源池(主机池)"之间流转是常见的生命周期操作:
- 业务侧维护的待分配主机通常存放在业务的空闲机池(内置模块)中;
- 当主机不再属于任何业务时,需要将其上交/回收至资源池,由资源池统一纳管,后续可再分配到其他业务。
transfer_host_to_resourcemodule 正是完成"业务主机 → 资源池"这一方向转移的 ESB 接口。仓库中与之对应的前端行为描述为"主机回收至主机池"(见 src/ui/src/store/modules/api/host-relation.js)。
接口有一个重要使用前提(原文档强调的注意项):
只能上交业务空闲机池下的主机
也就是说,并非业务中的任意主机都可以上交;只有位于业务空闲机池(广义上还包括故障机、待回收等内置模块)中的主机才满足上交条件。
请求参数详解
接口公共参数({{ common_args_desc }} 模板展开)与接口参数如下。
公共参数
原文档通过 {{ common_args_desc }} 引用 ESB 公共参数模板,从请求示例可以还原出实际调用时必须携带的网关公共参数:
| 字段 | 类型 | 必选 | 描述 |
|---|---|---|---|
| bk_app_code | string | 是 | 应用标识(应用 ID) |
| bk_app_secret | string | 是 | 应用密钥 |
| bk_username | string | 是 | 操作用户名 |
| bk_token | string | 是 | 登录态 Token |
接口参数
| 字段 | 类型 | 必选 | 描述 |
|---|---|---|---|
| bk_supplier_account | string | 否 | 开发商账号 |
| bk_biz_id | int | 是 | 业务ID |
| bk_module_id | int | 否 | 转移到的主机池目录ID,默认转移到主机池的空闲机目录 |
| bk_host_id | array | 是 | 主机ID |
参数说明与源码对应关系如下:
- bk_biz_id:必填,指主机当前所属的业务 ID。在 CMDB 内部统一使用字段常量
BKAppIDField = "bk_biz_id"(见 src/common/definitions.go); - bk_host_id:必填的数组类型,即待上交主机的 ID 列表。源码中对应的请求结构体为
DefaultModuleHostConfigParams,字段为HostIDs <a href="https://link.gitcode.com/i/134bc2ab6e172999e864ec50197bd708" target="_blank">]int64 \json:"bk_host_id"`(见 [src/common/metadata/common.go</a>),内部常量同样定义为BKHostIDField = "bk_host_id"`(见 src/common/definitions.go); - bk_module_id:选填,指定上交到资源池中的具体目录 ID;不传时默认转移到主机池的空闲机目录。从实现看,当
ModuleID == 0时,会按资源池业务中DefaultResModuleFlag(值为 1,见 src/common/definitions.go)标记查找默认资源目录,即"主机池的空闲机目录"(见 src/scene_server/host_server/logics/module.go); - bk_supplier_account:开发商账号,蓝鲸多租户(开发商)体系下的账号标识。
请求参数示例
原文档给出的完整 Python 格式请求示例(含公共参数):
{
"bk_app_code": "esb_test",
"bk_app_secret": "xxx",
"bk_username": "xxx",
"bk_token": "xxx",
"bk_supplier_account": "123456789",
"bk_biz_id": 1,
"bk_module_id": 3,
"bk_host_id": [
9,
10
]
}
该示例表示:将业务 bk_biz_id=1 下的主机 9、10 上交至资源池目录 bk_module_id=3。若省略 bk_module_id,则主机将默认进入资源池的空闲机目录。
返回结果示例
{
"result": true,
"code": 0,
"message": "success",
"permission": null,
"request_id": "e43da4ef221746868dc4c837d36f3807",
"data": null
}
返回结果参数说明
response
| 名称 | 类型 | 描述 |
|---|---|---|
| result | bool | 请求成功与否。true:请求成功;false请求失败 |
| code | int | 错误编码。 0表示success,>0表示失败错误 |
| message | string | 请求失败返回的错误信息 |
| data | object | 请求返回的数据 |
| permission | object | 权限信息 |
| request_id | string | 请求链id |
其中 code=0 表示成功;request_id 为请求链 ID,用于全链路日志追踪;permission 在无权限校验问题时为 null,当用户缺少"主机归还主机池"权限时会返回相应的权限申请信息。
底层实现原理:从 ESB 到 coreservice 的调用链
该 ESB 组件最终会调用 host_server 的 /hosts/modules/resource 接口,完整调用链可以从仓库源码逐层还原。
1. 路由注册
host_server 服务初始化时注册了该路由(见 src/scene_server/host_server/service/service_initfunc.go):
utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/hosts/modules/resource",
Handler: s.MoveHostToResourcePool})
与之相邻的路由还包括:转移到空闲机 MoveHost2IdleModule、故障机 MoveHost2FaultModule、待回收 MoveHost2RecycleModule 以及资源池主机分配到业务空闲机(/hosts/modules/resource/idle)等,共同构成主机在业务与资源池之间双向流转的接口族。
2. 服务层 Handler
MoveHostToResourcePool 处理器解析请求体为 DefaultModuleHostConfigParams(见 src/scene_server/host_server/service/module.go):
- 若
bk_host_id列表为空,直接返回成功(空操作不报错); - 在事务(
AutoRunTxn)内调用Logic.MoveHostToResourcePool执行实际转移; - 转移失败时返回异常明细
ExceptionResult列表,成功则返回空 data。
3. 核心业务逻辑
Logics.MoveHostToResourcePool 是上交操作的核心实现(见 src/scene_server/host_server/logics/module.go),其关键步骤为:
- 获取资源池业务 ID(
GetDefaultAppID),资源池本身也是一个特殊业务; - 校验业务合法性与归属:
ApplicationID == 0时返回资源池不存在错误;若ownerAppID == conf.ApplicationID,说明主机已在资源池中,直接返回"主机已在主机池"错误; - 解析目标目录:
bk_module_id为 0 时按默认资源目录(空闲机目录)查找,否则按指定目录 ID 查找资源池模块; - 校验主机来源(对应文档的"只能上交业务空闲机池下的主机"):通过条件
bk_default != 普通模块(0) 且 bk_biz_id = 业务ID查询该业务下的内置模块(空闲机/故障机/待回收),再调用notExistAppModuleHost逐一确认待上交主机确实属于这些模块(见 src/scene_server/host_server/logics/module.go)。若有主机不在其中,返回"主机不属于空闲机模块"错误; - 构造跨业务转移参数并执行:将主机从原业务转移到资源池业务的目标目录,参数为
TransferHostsCrossBusinessRequest(源业务、目标业务、目标模块、主机 ID 列表); - 写入操作审计日志(
auditlog.NewHostModuleLog+SaveAudit),保证主机模块关系变更可追溯。
4. coreservice 底层转移
跨业务转移最终落到 coreservice 的 TransferToAnotherBusiness(见 src/source_controller/coreservice/core/host/transfer/manager.go)。从源码结构看,该实现的核心是:
- 构建跨业务主机模块转移器(
SetCrossBusiness标记源业务列表); - 校验参数后,清理主机在原业务下的业务私有字段(
clearLegacyPrivateField,将私有属性置空并更新cc_HostBase表),随后通过 MongoDB 的unset更新移除遗留数据,确保主机上交后不带原业务的私有属性进入资源池。
5. 客户端封装
若在 Go 服务间直接调用,可复用 apimachinery 封装的客户端方法 hostServer.MoveHostToResourcePool(见 src/apimachinery/hostserver/apis.go),它向 /hosts/modules/resource 发起 POST 请求,请求体为 DefaultModuleHostConfigParams。
权限控制:主机归还主机池
接口要求调用者具备"主机归还主机池"权限,该权限在权限中心(IAM)的初始动作定义中明确注册:
BusinessHostTransferToResourcePool: "主机归还主机池",
(见 src/ac/iam/initial_actions.go)
从权限解析器(src/ac/parser/host.go)可以还原权限判定逻辑:
- 命中模式
"/api/v3/hosts/modules/resource"(POST)后,解析bk_biz_id与请求体中的bk_module_id; - 若未指定目录 ID,则自动换算为资源池默认目录 ID 用于授权;
- 最终构造的资源为"业务实例 + 资源池目录实例"两级授权对象,动作类型为
MoveBizHostFromModuleToResPool(主机归还主机池)。
因此,即使 bk_module_id 省略,鉴权时也会基于默认空闲机目录进行,权限模型与实际转移目标保持一致。
常见错误码与排查
接口失败时通过 code(>0)返回错误编码,结合错误码定义(见 src/common/errInfo.go)可快速定位问题:
| 错误码 | 常量名 | 含义与排查方向 |
|---|---|---|
| 1110051 | CCErrHostNotResourceFail | 资源池不存在:检查资源池业务是否初始化 |
| 1110052 | CCErrHostBelongResourceFail | 主机已在资源池中:所选主机本身已归属资源池业务,无需再次上交 |
| 1110056 | CCErrHostModuleConfigNotMatch | 主机不属于业务空闲机模块:违反"只能上交业务空闲机池下的主机"前提,需先把主机移入业务空闲机池再执行上交 |
| 1108044 | CCErrHostTransferFinalModuleConflict | 转移后模块互斥冲突:目标模块与主机现有模块归属存在冲突(该错误同时用于带服务实例自动清除的通用转移接口) |
仓库中的接口测试用例覆盖了上述典型异常场景(见 src/test/host_server/host_abnormal_test.go):转移不存在的主机、不存在的业务主机、非空闲机主机等均返回 result=false,与本文描述的校验逻辑一一对应。
前端调用场景(可选佐证)
Web 端"主机池"转移菜单也复用同一接口(见 src/ui/src/views/resource/transfer/transfer-menu.vue 与 src/ui/src/views/resource/transfer/transfer-menu.vue):
await this.$store.dispatch('hostRelation/transferHostToResourceModule', {
params: {
bk_biz_id: HostStore.uniqueBusiness.bk_biz_id,
bk_host_id: HostStore.getSelected().map(item => item.host.bk_host_id),
bk_module_id: directoryId
},
...
})
前端在发起前同样会校验"仅支持对空闲机池下的主机进行操作",与接口后端的模块归属校验形成双重保障;所选主机已在主机池中时会直接拦截提示,对应后端错误码 1110052 的场景。
综上,transfer_host_to_resourcemodule 是 CMDB 主机从业务归还至资源池的标准通道:请求参数少、语义清晰,但背后包含业务校验、空闲机归属校验、跨业务转移与私有字段清理、权限鉴权、审计日志等多个环节。开发者在集成时重点把握三点即可:主机必须处于业务空闲机池、bk_module_id 缺省即落到资源池空闲机目录、权限需开通"主机归还主机池",其余行为均由平台保证一致性。