ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

蓝鲸配置平台(bk-cmdb)批量更新被引用模型实例接口实战:batch_update_quoted_inst 全解析

蓝鲸配置平台(bk-cmdb)批量更新被引用模型实例接口实战:batch_update_quoted_inst 全解析
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

导读

在蓝鲸智云配置平台(BlueKing CMDB)中,"模型引用(Model Quote)"机制允许源模型通过表格类型属性引用一张派生子表,例如主机模型通过disk属性引用磁盘表。当需要一次性修改多条被引用实例时,可调用batch_update_quoted_inst接口(v3.10.30+ 引入)。本文以 docs/apidoc/apigw/open/zh/batch_update_quoted_inst.md 为主干,结合仓库源码梳理该接口的请求参数、调用示例、响应结构,以及底层的路由注册、参数校验、权限与审计实现,帮助读者正确、安全地批量更新被引用模型实例。

接口概述

功能定位

batch_update_quoted_inst用于批量更新被引用的模型的实例,即批量修改"源模型通过表格属性引用出的子模型"中的多条实例记录。它需要以下前置条件:

  • 版本要求:v3.10.30 及以上版本;
  • 权限要求:调用者需要具备源模型实例的编辑权限。

从源码结构看,被引用模型的实例管理与普通模型实例走的是独立链路:拓扑服务(topo_server)负责接入层鉴权与审计,核心服务(coreservice)负责真正的数据读写,二者通过ModelQuote()客户端桥接,相关代码位于 src/scene_server/topo_server/service/quoted_instance.go 与 src/source_controller/coreservice/service/model_quote/quoted_inst.go。

模型引用的数据模型

被引用模型与源模型的关联关系记录在ModelQuoteRelation结构中(见 src/common/metadata/model_quote.go):

  • DestModel:派生出的子模型(即被引用模型),例如bk_host_disk;
  • SrcModel:源模型,例如主机模型host;
  • PropertyID:源模型上引用该子模型的属性 ID,例如disk;
  • Type:引用类型(如表格table)。

生成被引用模型对象 ID 的规则为"bk_" + 源模型 + "#" + 属性ID,对应源码函数GenerateModelQuoteObjID(srcModel, propertyID)。这解释了为什么接口入参必须同时提供bk_obj_id与bk_property_id:二者共同定位到唯一的被引用模型及其表。

输入参数详解

接口请求体为 JSON 对象,各参数说明如下(与原文档保持完全一致,并补充源码校验细节):

参数名称参数类型必选描述
bk_obj_idstring是源模型 ID
bk_property_idstring是源模型引用该模型的属性 ID
idsint64 array是需要更新的实例 ID 数组,最多不能超过 500 个
dataobject是需要更新的实例信息

data 字段说明

data为待更新的字段集合,其字段由被引用模型的属性定义决定,并非固定结构。原文档中的name、operator、description仅为示例字段:

参数名称参数类型必选描述
namestringdata 中至少一个字段必填名称,此处仅为示例,实际字段由模型属性决定
operatorstringdata 中至少一个字段必填维护人,此处仅为示例,实际字段由模型属性决定
descriptionstringdata 中至少一个字段必填描述,此处仅为示例,实际字段由模型属性决定

提示:data中的多个字段是批量应用于ids指定的全部实例,即这些实例会统一被设置为相同值。若需要对不同实例设置不同字段值,应拆分为多次调用。

源码层的参数校验逻辑

服务端对入参的校验可在 src/common/metadata/model_quote.go 的BatchUpdateQuotedInstOption.Validate()中看到,它与接口文档互为印证:

  1. bk_obj_id为空 → 报参数缺失;
  2. bk_property_id为空 → 报参数缺失;
  3. ids为空数组 → 报参数缺失;
  4. ids数量超过common.BKMaxWriteOpLimit(200)→ 报参数缺失错误(此处注意:文档上限 500 与常量定义存在差异,源码中BKMaxWriteOpLimit = 200,见 src/common/definitions.go,实际以服务端校验为准);
  5. data为空对象 → 报参数缺失。

此外,拓扑服务层还会做二次校验(src/scene_server/topo_server/service/quoted_instance.go):

  • 通过ModelQuoteOperation().GetQuotedObjID根据bk_obj_id+bk_property_id查询ModelQuoteRelation,定位被引用模型对象 ID(实现见 src/scene_server/topo_server/logics/model_quote/model_quote.go);
  • 用filtertools.GenAtomFilter(common.BKFieldID, filter.In, opt.IDs)构造"ID 属于 ids 集合"的过滤条件,先查出待更新实例的原始快照,用于后续鉴权与审计。

调用示例

以下为原文档提供的完整调用示例:

{ "bk_obj_id": "host", "bk_property_id": "disk", "ids": [ 1, 2 ], "data": { "name": "test", "operator": "user", "description": "test instance" } }

该示例的含义:将主机(host)模型通过disk属性引用的磁盘实例中 ID 为 1、2 的两条记录,统一更新为name=test、operator=user、description=test instance。

响应结构与示例

响应示例

{ "result": true, "code": 0, "message": "success", "permission": null, "data": null }

响应参数说明

参数名称参数类型描述
resultbool请求成功与否。true:请求成功;false:请求失败
codeint错误编码。0 表示 success,>0 表示失败错误
messagestring请求失败返回的错误信息
permissionobject权限信息
dataobject请求返回的数据

更新成功时data返回null,这一点与批量创建接口(batch_create_quoted_inst)不同——创建接口的data.ids会返回新实例 ID 数组,可参见 docs/apidoc/apigw/open/zh/batch_create_quoted_inst.md;而批量删除接口同样返回data: null,见 docs/apidoc/apigw/open/zh/batch_delete_quoted_inst.md。

底层调用链与实现原理

路由注册

该接口的 HTTP 路由在拓扑服务的initModelQuote中注册(src/scene_server/topo_server/service/service_model_quote_initfunc.go):

utility.AddHandler(rest.Action{Verb: http.MethodPut, Path: "/updatemany/quoted/instance", Handler: s.BatchUpdateQuotedInstance})

即完整 API 路径为PUT /api/v3/updatemany/quoted/instance(权限点在 src/ac/parser/model_quote.go 中登记为BatchUpdateQuotedInstance/ "更新引用模型实例")。

服务端处理流程

拓扑服务层的BatchUpdateQuotedInstance(src/scene_server/topo_server/service/quoted_instance.go)执行步骤如下:

  1. 解析并校验请求体:cts.DecodeInto(opt)反序列化为BatchUpdateQuotedInstOption并执行Validate();
  2. 定位被引用模型:调用GetQuotedObjID从关系表取出DestModel;
  3. 查询实例快照:按ids构造filter.In条件查询现有实例(limit 为BKMaxPageSize),用于后续鉴权与审计日志生成;
  4. 鉴权:通过authorizeQuotedInstance调用AuthManager.AuthorizeByInstanceID(..., meta.Update, objID, instIDs...),对被引用实例做更新授权(源码注释表明当前复用了源模型实例的更新动作进行鉴权);
  5. 生成审计日志:使用auditlog.NewQuotedInstAuditLog生成AuditUpdate类型的操作审计(实现见 src/common/auditlog/quoted_inst.go),记录变更前后的字段内容;
  6. 事务内更新:在AutoRunTxn事务中调用CoreService().ModelQuote().BatchUpdateQuotedInstance真正写库,并在同一事务内保存审计日志,保证数据与审计的一致性;
  7. 响应:成功则返回data: null。

核心数据层实现

核心服务层(coreservice)的BatchUpdateQuotedInstance(src/source_controller/coreservice/service/model_quote/quoted_inst.go)完成最终写库:

  • 解析CommonUpdateOption(包含过滤条件与data),执行Validate();
  • 取路径参数bk_obj_id,通过common.GetInstTableName(objID, supplierAccount)计算被引用模型的 MongoDB 表名;
  • 调用validateUpdateQuotedInst逐字段校验(细节见 src/source_controller/coreservice/service/model_quote/quoted_inst_validate.go):
    • 过滤掉bk_inst_id、bk_field_id等主键/关联字段(不允许通过该接口修改);
    • 仅保留被引用模型属性表中真实存在且IsEditable为 true 的字段,其余字段被静默删除;
    • 对字符串值做TrimSpace去空格,并调用属性的Validate做类型/枚举/必填等校验;
  • 将过滤条件SetModOwner加上供应商账号(多租户数据隔离),并把last_time更新为当前时间;
  • 执行mongodb.Client().Table(table).Update(ctx, filter, data)批量更新,若命中唯一键冲突返回重复项错误,否则返回RespEntity(nil)。

客户端调用封装

若通过 Go SDK 调用,可使用 src/apimachinery/apiserver/model_quote/instance.go 中提供的封装:

err := quoteClient.BatchUpdateQuotedInstance(ctx, header, &metadata.BatchUpdateQuotedInstOption{ ObjID: "host", PropertyID: "disk", IDs: []uint64{1, 2}, Data: mapstr.MapStr{"name": "test"}, })

客户端内部以PUT /updatemany/quoted/instance请求并统一解析BaseResp,出错时返回errors.CCHttpError或业务错误码。

测试用例佐证

仓库集成测试 src/test/topo_server/model_quote_test.go 覆盖了更新场景:

  • 正常更新:构造BatchUpdateQuotedInstOption(含ObjID、PropertyID、IDs、Data)调用BatchUpdateQuotedInstance,断言不报错;
  • 异常场景:PropertyID设置为不存在的"prop_no_exist",断言调用报错——对应源码中GetQuotedObjID查询关系表无结果时返回参数非法错误。

这为接口行为提供了可复现的验证路径。

使用注意事项

  1. 权限前置:接口要求源模型实例的编辑权限,权限校验失败时响应中permission字段会携带所需权限信息;
  2. 数量上限:ids数组不能超过文档所述 500 个,且实际服务端校验以BKMaxWriteOpLimit(源码中为 200)为准,批量过大时应分批调用;
  3. 字段白名单:data中非被引用模型属性、或不可编辑(IsEditable=false)的字段会被忽略,bk_inst_id等关联字段不可通过本接口修改;
  4. 整体覆盖语义:data中的所有字段会统一写入ids指定的所有实例,请确认业务上允许这些实例拥有相同的更新值;
  5. 审计可追溯:更新会写入操作审计(QuotedInst 类型,AuditUpdate动作),变更记录可在平台审计中心查询;
  6. 原子性:更新与审计日志在同一事务内提交,任一环节失败都会整体回滚,不会出现"数据已改、审计缺失"的不一致状态。

关联文档

如需了解被引用模型实例的完整操作闭环,可配合阅读同一目录下的关联接口文档:

  • 批量创建:docs/apidoc/apigw/open/zh/batch_create_quoted_inst.md
  • 查询列表:docs/apidoc/apigw/open/zh/list_quoted_inst.md
  • 批量删除:docs/apidoc/apigw/open/zh/batch_delete_quoted_inst.md

结合这三篇文档与上文源码分析,即可完整掌握被引用模型实例从创建、查询、批量更新到删除的整个 API 使用链路。

  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

项目地址:https://gitcode.com/gh_mirrors/bk/bk-cmdb
点击查看免费下载
上一篇:终极指南:3步让你的老款Mac焕发新生,免费安装最新macOS系统
下一篇:深度解析:如何用mootdx构建高效通达信金融数据处理系统

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进