- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing 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 |
| operationId | update_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 网关的统一鉴权(应用凭据 + 用户身份)完成认证,而非要求用户在请求头中额外携带登录态。
输入参数说明
更新服务分类接口共接收三个必选参数,完整参数表如下:
| 参数名称 | 参数类型 | 必选 | 描述 |
|---|---|---|---|
id | int | 是 | 服务分类 ID |
name | string | 是 | 服务分类名称 |
bk_biz_id | int | 是 | 业务 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)为演示数据,与上方请求示例中的输入值无严格对应关系。
响应参数说明
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
result | bool | 请求成功与否。true表示请求成功,false表示请求失败 |
code | int | 错误编码。0表示 success,>0表示失败错误 |
message | string | 请求失败时返回的错误信息 |
permission | object | 权限信息(通常为null) |
data | object | 更新后的服务分类信息 |
data字段说明
data对象完整对应源码中 ServiceCategory 结构体 的字段定义:
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
bk_biz_id | int | 业务 ID |
id | int | 服务分类 ID |
name | string | 服务分类名称 |
bk_root_id | int | 根服务分类 ID |
bk_parent_id | int | 父服务分类 ID |
bk_supplier_account | string | 运营商账号 |
is_built_in | bool | 是否是内置服务分类 |
其中:
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)各层职责:
- proc_server 层:
UpdateServiceCategory处理器先通过ctx.DecodeInto(input)解析请求体为 ServiceCategory 结构体,随后使用Engine.CoreAPI.CoreService().Txn().AutoRunTxn开启事务,在事务内调用 coreservice 的更新接口。数据持久化到 MongoDB 的操作与事务提交保持一致性(源码见 servicecategory.go)。 - apimachinery 客户端层:封装对 coreservice 的 HTTP 调用,构造
PUT /update/proc/service_category请求(源码见 category.go),为上层各服务模块提供统一的 SDK 入口。 - coreservice 接口层:从 URL 路径参数中解析
service_category_id(ctx.Request.PathParameter(common.BKServiceCategoryIDField)),并通过ctx.DecodeInto解析请求体,然后调用数据层(源码见 service_category.go)。 - 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)
相关推荐
蓝鲸配置平台 bk-cmdb 主机锁定接口 add_host_lock 实战指南:参数、幂等语义与底层实现
蓝鲸配置平台 bk cmdb 主机锁定接口 add_host_lock 实战指南:参数、幂等语义与底层实现 本文以蓝鲸智云配置平台(BlueKing CMDB,
后端企业应用运维蓝鲸配置平台(bk-cmdb)批量更新 Kubernetes Workload 接口实战指南
蓝鲸配置平台(bk cmdb)批量更新 Kubernetes Workload 接口实战指南 导读 本文围绕 bk cmdb(蓝鲸智云配置平台)API 网关提供
后端企业应用运维蓝鲸配置平台 bk-cmdb 新建服务分类接口(create_service_category)实战指南:参数详解、源码原理与测试验证
蓝鲸配置平台 bk cmdb 新建服务分类接口(create_service_category)实战指南:参数详解、源码原理与测试验证 本指南以蓝鲸智云配置平台
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考