蓝鲸配置平台 bk-cmdb delete_inst 接口详解:删除对象实例的请求参数、返回结果与底层实现

原创2026-10-13 13:52:21522 阅读
文章标签:后端企业应用微服务

蓝鲸配置平台 bk-cmdb delete_inst 接口详解:删除对象实例的请求参数、返回结果与底层实现

本文以蓝鲸智云配置平台(bk-cmdb)开放接口文档中的 delete_inst(删除实例)接口为核心,讲解如何通过指定模型 ID 与实例 ID 删除自定义层级模型和通用模型下的对象实例,覆盖接口适用边界、请求参数、请求/响应示例、权限要求,并结合 src/source_controller/coreservice 与 src/ac/parser 的源码剖析其删除校验、级联清理与鉴权实现的底层逻辑。读完本文,你可以独立完成该接口的调用与排障,并理解它与批量删除、级联删除等同类接口的差异。

功能概述与适用场景

delete_inst 接口用于指定模型 ID(bk_obj_id)和实例 ID(bk_inst_id)删除该模型下的对象实例,其权限要求为模型实例删除权限(在权限中心的动作类型为 delete 实例)。

使用前必须明确该接口的适用范围,这是最容易踩坑的一点:

  • 适用:自定义层级模型(自定义主线模型)实例、通用模型实例。
  • 不适用:业务、集群、模块、主机等平台内置模型实例。这些内置模型实例拥有专属的管理接口(例如主机的迁移、业务拓扑管理等),不能通过本接口直接删除。

若需要批量删除模型实例,请使用同一文档体系中的 batch_delete_inst 接口;若需要连同实例的关联关系一并删除,可关注本文后面介绍的级联删除实现(CascadeDeleteModelInstance)。

接口信息总览

根据 docs/apidoc/cc/cc.yaml 中 delete_inst 的网关定义,该接口的完整映射关系如下:

项目 值
网关路径(建议方式) /v2/cc/delete_inst/
网关 HTTP 方法 POST(suggest_method)
内部目标路径 /api/v3/delete/instance/object/{bk_obj_id}/inst/{bk_inst_id}
内部目标 HTTP 方法 DELETE
API 类型 operate(操作类接口)
权限点 模型实例删除权限(meta.Delete)

也就是说,请求经过 API 网关(ESB)时使用 POST + 网关路径;网关将请求转换为对 CMDB 内部服务的 DELETE /api/v3/delete/instance/object/{bk_obj_id}/inst/{bk_inst_id} 调用。权限中心在内部路径上完成实例级鉴权(详见下文"权限鉴权链路")。

请求参数详解

公共参数

接口文档中以 {{ common_args_desc }} 占位符表示的公共参数(通用请求头/公共鉴权参数)在真实调用中必须携带,从文档给出的请求示例可以看到通常包含:

字段 类型 说明
bk_app_code string 应用标识,ESB 网关鉴权用
bk_app_secret string 应用密钥,ESB 网关鉴权用
bk_username string 用户名,标识操作者
bk_token string 用户登录态 Token(与 bk_username 二选一或按网关要求组合)

接口参数

字段 类型 必选 描述
bk_obj_id string 是 模型 ID
bk_inst_id int 是 实例 ID
bk_biz_id int 否 业务 ID,当删除的是自定义主线层级模型实例时则必传

关于 metadata 的特殊注意事项

文档明确提示一个兼容性坑点:当操作的是自定义主线层级模型实例,且同时接入了权限中心时,对于 CMDB 小于 3.9 的版本,还需要额外传入包含实例所在业务 ID 的 metadata 参数,否则会导致权限中心鉴权失败。格式如下:

"metadata": {
    "label": {
        "bk_biz_id": "64"
    }
}

这是为了让旧版本 CMDB 在鉴权时能够定位实例所属的业务范围。从源码看,权限解析逻辑在从请求 body 中读取业务 ID(见 src/ac/parser/topolatest.go 中的 getBizIDFromBody),因此传入 metadata.label.bk_biz_id 可以保证实例级鉴权正确命中。

请求参数示例

以下是文档给出的完整请求示例(通过网关发起):

{
    "bk_app_code": "esb_test",
    "bk_app_secret": "xxx",
    "bk_username": "xxx",
    "bk_token": "xxx",
    "bk_obj_id": "test",
    "bk_inst_id": 44
}

其中 bk_obj_id 为 test 的模型下、bk_inst_id 为 44 的实例将被删除。若该模型是自定义主线层级模型且版本小于 3.9、接入了权限中心,则还需要按上一节格式补充 metadata 字段。

返回结果解析

返回结果示例

{
    "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 请求失败返回的错误信息
permission object 权限信息(鉴权失败或需要额外授权时返回)
request_id string 请求链 ID,用于全链路追踪
data object 请求返回的数据(删除成功时为空)

底层实现:删除一条实例的完整调用链

理解底层实现有助于在调用失败时快速定位问题。删除实例的内部调用链在 src/source_controller/coreservice 模块中可以分为三层:

1. 路由注册(service 层入口)

在 src/source_controller/coreservice/service/service_initfunc.go 中注册了两个删除实例的路由:

  • DELETE /delete/model/{bk_obj_id}/instance → s.DeleteModelInstances(普通删除)
  • DELETE /delete/model/{bk_obj_id}/instance/cascade → s.CascadeDeleteModelInstances(级联删除)

对应 HTTP 处理器定义在 src/source_controller/coreservice/service/instances.go:

func (s *coreService) DeleteModelInstances(ctx *rest.Contexts) {
    inputData := metadata.DeleteOption{}
    if err := ctx.DecodeInto(&inputData); nil != err {
        ctx.RespAutoError(err)
        return
    }
    ctx.RespEntityWithError(s.core.InstanceOperation().DeleteModelInstance(
        ctx.Kit, ctx.Request.PathParameter("bk_obj_id"), inputData))
}

请求体被解码为 metadata.DeleteOption 结构体,其定义在 src/common/metadata/delete.go:

type DeleteOption struct {
    Condition mapstr.MapStr `json:"condition"`
}

注意:删除接口的请求体本质上是一个**条件(condition)**结构,从 bk_inst_id 会被转换为 Condition 中实例 ID 字段的等值条件。

2. 核心删除逻辑(core 层)

核心实现在 src/source_controller/coreservice/core/instances/instance.go 的 DeleteModelInstance 函数中,大致分五步:

  1. 确定数据表与实例 ID 字段:通过 common.GetInstTableName(objID, kit.SupplierAccount) 获取模型对应的实例表名,通过 common.GetInstIDField(objID) 获取实例 ID 字段名(通用模型为 bk_inst_id,主线模型为对应主线字段)。
  2. 注入数据归属条件:将 bk_supplier_account(供应商账号)写入查询条件,保证只操作本供应商范围内的数据。
  3. 查询并逐一校验关联关系:先按条件查询出全部待删除实例,随后对每个实例调用 IsInstAsstExist 检查是否存在实例关联关系;一旦发现仍有关联,立即返回错误码 CCErrorInstHasAsst(对应 src/common/errInfo.go 中定义的 1101075),并拒绝删除。这也是调用该接口最常见的失败原因之一。
  4. 删除实例数据:调用 mongodb.Client().Table(tableName).Delete(...) 从 Mongo 表中物理删除满足条件的数据;若模型是通用模型(metadata.IsCommon(objID),判断逻辑见 src/common/metadata/object.go),还会同步清理实例 ID 与实例的映射数据(instancemapping.Delete)。
  5. 清理被引用实例:调用 DeleteQuotedInst 删除这些实例对应的"被引用实例"(quoted inst)数据,避免留下脏数据。

最终返回被删除的实例数量 DeletedCount。

3. 级联删除的差异

同文件中的 CascadeDeleteModelInstance 与普通删除唯一的区别在于第 3 步:普通删除在发现实例有关联关系时会报错中止,而级联删除会先调用 DeleteInstAsst 把实例的所有关联关系一并删除,然后再删除实例本身,从而实现"连坐"式清理。如果你希望删除一个仍存在关联关系的实例,应使用级联删除路径 /api/v3/delete/model/{bk_obj_id}/instance/cascade(对应批量/级联场景),而不是普通删除。

权限鉴权链路

该接口的鉴权在 API 网关转发到内部服务后由权限解析器处理。在 src/ac/parser/topolatest.go 中,删除实例的请求会命中正则 ^/api/v3/delete/instance/object/[^\s/]+/inst/[0-9]+/?$(对应变量 deleteObjectInstanceLatestRegexp),解析流程为:

  1. 从 URL 中解析出模型 ID(objID)与实例 ID(instID);
  2. 根据模型 ID 查询模型,确定实例类型(getInstanceTypeByObject);
  3. 从请求 body 中读取业务 ID(getBizIDFromBody,即前文 metadata 参数被使用的位置);
  4. 组装 ResourceAttribute,其中 Action: meta.Delete,InstanceID: instID,交给权限中心完成实例级删除授权。

这也解释了文档中"权限:模型实例删除权限"的落点:权限中心需要用户对该模型实例具备 delete 动作,且能定位到实例所属业务,否则返回 permission 相关信息。

常见失败场景与排查建议

  • 实例仍存在关联关系:返回错误码 1101075(CCErrorInstHasAsst)。请先调用删除实例关联接口清理关联,或改用级联删除路径。
  • 鉴权失败:确认用户具备模型实例删除权限;删除自定义主线层级模型实例且 CMDB 版本小于 3.9 时,务必携带 metadata.label.bk_biz_id。
  • 尝试删除内置模型实例(如 bk_host、业务、集群、模块):接口不适用,请改用对应业务/拓扑/主机管理接口。
  • 实例不存在:删除操作按条件执行,条件不匹配时不会报"实例不存在",返回 data 为空或删除数量为 0,需要结合返回的 DeletedCount 或前置查询接口(如 search_inst)确认实例 ID 正确。

相关接口与资源

登录后查看全文
bk-cmdb