☰
蓝鲸配置平台(bk-cmdb)更新服务分类接口实战:API 参数、权限与底层实现解析
2026/10/13 6:49:55 网站建设 项目流程
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

导读

服务分类(Service Category)是蓝鲸配置平台(bk-cmdb)业务拓扑中用于组织服务模板与模块的逻辑分组,其结构直接影响业务拓扑树中"服务"层级的展示与维护。本文围绕开放 API 网关(APIGW)提供的"更新服务分类"接口(update_service_category),完整讲解其请求参数、调用示例、响应结构,并结合仓库源码深入解析从网关到数据层的完整调用链、名称校验规则、内置分类保护机制与错误码含义,帮助你在业务中安全、正确地维护服务分类名称。

接口概述

"更新服务分类"是 bk-cmdb 通过 APIGW 对外开放的 API 之一,对应开放 API 资源定义文件 bk_apigw_resources_bk-cmdb.yaml 中的/api/v3/update/proc/service_category资源:

项目值
请求方式PUT
请求路径/api/v3/update/proc/service_category
operationIdupdate_service_category
功能描述更新服务分类(目前仅名称字段可更新)
权限要求服务分类编辑权限(IAM 动作edit_biz_service_category)
网关可见性isPublic: false,需申请权限后才可调用(allowApplyPermission: true)

从网关资源定义可以看到,该接口经过 APIGW 的限流插件(bk-rate-limit,默认每秒 100 个令牌)后,以PUT方式转发至后端/api/v3/update/proc/service_category。由于userVerifiedRequired: false,该接口通过蓝鲸 API 网关的统一鉴权(应用凭据 + 用户身份)完成认证,而非要求用户在请求头中额外携带登录态。

输入参数说明

更新服务分类接口共接收三个必选参数,完整参数表如下:

参数名称参数类型必选描述
idint是服务分类 ID
namestring是服务分类名称
bk_biz_idint是业务 ID

参数含义详解:

  • id:待更新服务分类的唯一标识。该 ID 是服务分类在bk_cmdb集合(表名见下文)中的主键,可通过"查询服务分类"(list_service_category)接口或业务拓扑页面获取。
  • name:更新后的服务分类名称。当前版本仅支持更新名称字段;服务分类的层级关系(bk_parent_id)、归属业务(bk_biz_id)等字段不可通过本接口修改。
  • bk_biz_id:服务分类所属业务 ID,用于限定操作范围,保证更新操作只作用于指定业务下的分类。

调用示例

请求体以 JSON 形式提交,以下为文档给出的调用示例:

{ "bk_biz_id": 1, "id": 3, "name": "222" }

以curl方式调用该接口(配合蓝鲸 API 网关的应用鉴权信息)可写作:

curl -X PUT 'https://{APIGW_HOST}/api/v3/update/proc/service_category' \ -H 'Content-Type: application/json' \ -H 'X-Bk-App-Code: {APP_CODE}' \ -H 'X-Bk-App-Secret: {APP_SECRET}' \ -H 'X-Bk-User-Name: {USERNAME}' \ -d '{ "bk_biz_id": 1, "id": 3, "name": "222" }'

其中{APIGW_HOST}为蓝鲸 APIGW 网关地址,X-Bk-App-Code/X-Bk-App-Secret为应用凭据,X-Bk-User-Name为发起操作的用户名(用于 IAM 权限校验)。

响应示例与参数说明

响应示例

{ "result": true, "code": 0, "message": "success", "permission": null, "data": { "bk_biz_id": 3, "id": 22, "name": "api", "bk_root_id": 21, "bk_parent_id": 21, "bk_supplier_account": "0", "is_built_in": false } }

说明:响应示例中data展示的是更新后服务分类的完整信息,示例中的字段取值(如id: 22、bk_biz_id: 3)为演示数据,与上方请求示例中的输入值无严格对应关系。

响应参数说明

参数名称参数类型描述
resultbool请求成功与否。true表示请求成功,false表示请求失败
codeint错误编码。0表示 success,>0表示失败错误
messagestring请求失败时返回的错误信息
permissionobject权限信息(通常为null)
dataobject更新后的服务分类信息

data字段说明

data对象完整对应源码中 ServiceCategory 结构体 的字段定义:

参数名称参数类型描述
bk_biz_idint业务 ID
idint服务分类 ID
namestring服务分类名称
bk_root_idint根服务分类 ID
bk_parent_idint父服务分类 ID
bk_supplier_accountstring运营商账号
is_built_inbool是否是内置服务分类

其中:

  • bk_parent_id为0表示该分类是一级(顶层)分类,否则为二级分类;
  • bk_root_id记录该分类所属的根分类 ID。由 CreateServiceCategory 源码 可见,一级分类创建后其bk_root_id等于自身id,二级分类则继承父分类的bk_root_id;
  • is_built_in为true时表示系统内置分类(如默认的Default分类,见 definitions.go),此类分类受保护,不允许修改。

底层调用链:从网关到 MongoDB

"更新服务分类"并非单模块实现,而是贯穿 APIGW → proc_server → coreservice → MongoDB 的多层调用。完整链路如下:

APIGW (/api/v3/update/proc/service_category, PUT) │ 转发 ▼ proc_server 路由: PUT /update/proc/service_category │ [service.go](https://link.gitcode.com/i/e06321bb91a4cbb1c04a822acc15411c) 注册路由 ▼ ProcServer.UpdateServiceCategory 处理器 │ [servicecategory.go](https://link.gitcode.com/i/9d7ea26bf860220a09ed73b242d0c826) ▼ apimachinery 客户端: PUT /update/proc/service_category │ [category.go](https://link.gitcode.com/i/d936811216f9d1a6c220b9a4f8585f71) ▼ coreservice 路由: PUT /update/process/service_category/{service_category_id} │ [service_process_initfunc.go](https://link.gitcode.com/i/18bed2bbd8a20d93c18a442f9c903e8b) ▼ coreService.UpdateServiceCategory 处理器 │ [service_category.go](https://link.gitcode.com/i/39bf798615146dd7eb366a2489f9ef42) ▼ processOperation.UpdateServiceCategory(业务逻辑 + MongoDB 写入) [service_category.go](https://link.gitcode.com/i/33a2b33e162813ea8ad68c7f83c0090c)

各层职责:

  1. proc_server 层:UpdateServiceCategory处理器先通过ctx.DecodeInto(input)解析请求体为 ServiceCategory 结构体,随后使用Engine.CoreAPI.CoreService().Txn().AutoRunTxn开启事务,在事务内调用 coreservice 的更新接口。数据持久化到 MongoDB 的操作与事务提交保持一致性(源码见 servicecategory.go)。
  2. apimachinery 客户端层:封装对 coreservice 的 HTTP 调用,构造PUT /update/proc/service_category请求(源码见 category.go),为上层各服务模块提供统一的 SDK 入口。
  3. coreservice 接口层:从 URL 路径参数中解析service_category_id(ctx.Request.PathParameter(common.BKServiceCategoryIDField)),并通过ctx.DecodeInto解析请求体,然后调用数据层(源码见 service_category.go)。
  4. coreservice 数据层:执行最终的校验与写库操作,详见下一节。

核心业务逻辑:名称校验、内置分类保护与唯一性检查

更新操作的真正核心位于数据层 processOperation.UpdateServiceCategory,其执行流程可以概括为四步:

1. 加载原分类并更新名称

先通过GetServiceCategory(kit, categoryID)按id从bk_cmdb集合(表常量BKTableNameServiceCategory)加载目标分类;加载成功后,仅将请求中的Name覆盖到本地对象:

category, err := p.GetServiceCategory(kit, categoryID) ... category.Name = input.Name

这一步印证了文档中"目前仅名称字段可更新"的描述:请求体中即使携带其他字段,最终也只会被用于名称更新。

2. 名称合法性校验

更新后的对象调用ServiceCategory.Validate()进行校验(源码见 process.go),校验规则包括:

校验项规则依据
非空名称不能为空字符串process.go
最大长度按 UTF-8 字符数(utf8.RuneCountInString)计算,不得超过 128 个字符常量ServiceCategoryMaxLength,见 definitions.go
字符格式必须匹配正则^([\w\p{Han}]|[:\-\(\)])+$,即允许字母、数字、下划线、中文及: - ( )字符常量FieldTypeServiceCategoryRegexp,见 definitions.go

校验失败时接口返回参数非法错误(CCErrCommParamsInvalid),并在message中指明具体字段与原因。

3. 内置分类保护

若目标分类的IsBuiltIn为true,更新操作会被直接拒绝,返回错误码CCErrCommOperateBuiltInItemForbidden(错误码值 1199054,见 errInfo.go):

if category.IsBuiltIn { return nil, kit.CCError.CCError(common.CCErrCommOperateBuiltInItemForbidden) }

这意味着系统内置服务分类(如默认的Default分类)只读,无法通过本接口改名。

4. 名称唯一性检查

更新前会在业务范围内校验新名称是否与其他分类冲突,构造的查询条件为:

  • name等于新名称;
  • 排除当前分类自身(id != categoryID);
  • bk_biz_id属于[0, 业务ID](即全局默认分类与当前业务分类均参与查重);
  • 同时匹配bk_parent_id(同层级内互斥)。

若已存在同名分类,返回错误码CCErrCoreServiceServiceCategoryNameDuplicated(错误码值 1113017,见 errInfo.go)。

5. 执行更新并返回最新数据

以上校验全部通过后,按id为过滤条件执行 MongoDB 的Update,并将更新后的完整分类对象作为data返回给调用方。

权限控制:IAM 服务分类编辑权限

文档明确指出该接口需要"服务分类编辑权限"。在 bk-cmdb 的权限中心(IAM)适配中:

  • 资源类型biz_process_service_category(服务分类)与动作edit_biz_service_category(服务分类编辑)的定义见 types.go;
  • 动作展示名为"服务分类编辑",见 initial_actions.go;
  • 在 adaptor.go 中,meta.Update操作被映射到EditBusinessServiceCategory动作,即更新服务分类对应"服务分类编辑"权限。

调用方(即X-Bk-User-Name指定的用户)若未获授权,网关或 CMDB 会返回权限不足相关错误,响应中的permission字段可用于向权限中心申请权限。

错误排查指引

结合错误码定义,更新服务分类时常见失败场景如下:

场景错误码含义与处理建议
id不存在CCErrCommNotFound目标分类不存在,请先通过查询接口确认id
名称为空 / 超长 / 含非法字符CCErrCommParamsInvalid按上文校验规则修正name(非空、≤128 字符、符合正则)
目标为内置分类CCErrCommOperateBuiltInItemForbidden(1199054)内置分类不可更新,请更换目标分类
同层级已存在同名分类CCErrCoreServiceServiceCategoryNameDuplicated(1113017)更换为业务内不重复的名称
无权限IAM 权限不足使用具有"服务分类编辑"权限的用户调用

在仓库的集成测试中,更新服务分类的行为由 no_service_template_test.go 覆盖——测试通过serviceClient.UpdateServiceCategory修改服务分类名称后,再校验查询结果中分类名称是否同步更新,可用于验证接口在完整环境下的正确性。

小结

"更新服务分类"接口是 bk-cmdb 业务拓扑维护中的重要写操作。使用时需重点把握三点:仅名称可更新、内置分类受保护、业务内同名互斥。通过本文梳理的调用链与校验逻辑,你可以准确构造请求、预判失败场景,并理解名称变更在 CMDB 多模块架构中的流转过程。更完整的开放 API 定义可参考 bk_apigw_resources_bk-cmdb.yaml,接口文档原文见 update_service_category.md。

  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

相关推荐

上一篇:LanceDB Python 从同步 API 迁移到异步 API 完整指南:connect_async 与 AsyncConnection/AsyncTable 实战
下一篇:Sliver Pivots 完整实战指南:用 C2 流量链式代理穿越受限网络(TCP / Named Pipe)

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

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

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

立即咨询