LiteLLM Terraform Provider 实战:litellm_unified_access_group 数据源使用与源码解析
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
本文围绕 LiteLLM 仓库中 Terraform Provider 的litellm_unified_access_group数据源(Data Source)展开,说明如何通过 IaC 方式按 ID 查询一个已存在的 LiteLLM 统一访问组(Unified Access Group)及其授予的模型、MCP 服务器、Agent,以及其绑定的团队与 Key。读完本文,你将掌握该数据源的完整字段语义、Terraform 声明式用法,并理解其背后的 HTTP 调用链与 Go SDK 实现,从而把"访问权限查询"可靠地纳入你的基础设施编排流程。
Unified Access Group:一次授权、多处生效
在 LiteLLM Proxy 的权限模型里,"统一访问组"是一组访问权限的聚合体。一个访问组可以把"能调哪些模型(access_model_names)、能连哪些 MCP 服务器(access_mcp_server_ids)、能使用哪些 Agent(access_agent_ids)"打包在一起,再整体分配给团队(team)和虚拟 Key(key)。这种设计避免了在 Team 或 Key 上重复维护一长串模型清单,让权限在 Proxy 侧集中定义、批量复用。
Proxy 侧对访问组的管理集中在一组管理端点上,仓库中对应的实现在 访问组管理端点。围绕访问组,仓库还提供了三套独立的"同步器",分别负责把访问组绑定同步到模型、团队和 Key:
- access_group_model_sync.py
- access_group_team_sync.py
- access_group_key_sync.py
从这些源码结构可以看出,访问组不仅是"静态标签",其与 Team/Key 的绑定变更会被幂等地同步(_sync_add_access_group_to_teams、_sync_remove_access_group_from_teams、_sync_add_access_group_to_keys等均以"如果尚未包含则追加/删除"的方式实现幂等)。这也解释了为什么在 Terraform 里查询一个访问组时,会同时看到assigned_team_ids、assigned_key_ids这类"反向关联"字段:它们来自 Proxy 返回的实时数据,而非 HCL 中的静态声明。
Terraform Provider 正是在 Proxy 的这些管理端点之上封装了 Resource(管理生命周期)与 Data Source(只读查询)两类访问组抽象。本文聚焦 Data Source 形态的文档 unified_access_group.md。
数据源定位:只读查询单个访问组
litellm_unified_access_group数据源用于"按 ID 获取一个已存在的统一访问组"并暴露其全部属性,供 HCL 中其他资源引用。它不创建、不修改任何东西,属于纯只读的查询抽象。
Example Usage(完整示例)
原文档给出了最小可运行示例——按access_group_id查询一个名为 engineering 的访问组,并把其可访问模型列表输出为output:
data "litellm_unified_access_group" "engineering" { access_group_id = "b6e5f9d0-..." } output "engineering_models" { value = data.litellm_unified_access_group.engineering.access_model_names }在此基础上,数据源的返回属性可被任意 Terraform 表达式引用,例如把访问组的 MCP 服务器 ID 传给下游资源、根据归属团队做条件渲染等:
# 访问组授予了哪些 MCP 服务器,可用于与 litellm_mcp_server 资源对照审计 output "engineering_mcp_servers" { value = data.litellm_unified_access_group.engineering.access_mcp_server_ids } # 该访问组当前被分配给了哪些团队,便于校验权限漂移 output "engineering_teams" { value = data.litellm_unified_access_group.engineering.assigned_team_ids }Argument Reference(入参)
| 参数 | 必需 | 类型 | 说明 |
|---|---|---|---|
access_group_id | ✅ Required | string | 要查询的统一访问组 ID。该 ID 与 Terraform 资源/数据源的id、access_group_id属性同源,均对应 Proxy 侧访问组记录的主键 |
注意:该数据源只接收这一个入参,其余字段全部由服务端返回并写入 Terraform State。
Attribute Reference(导出属性)
数据源按 ID 命中后会导出以下全部属性:
| 属性 | 类型 | 语义 |
|---|---|---|
id | string | 统一访问组 ID |
access_group_id | string | 统一访问组 ID(与id等价) |
access_group_name | string | 访问组的显示名称 |
description | string | 访问组描述(若存在) |
access_model_names | list(string) | 该访问组授予访问权限的模型名列表 |
access_mcp_server_ids | list(string) | 该访问组授予访问权限的 MCP 服务器 ID 列表 |
access_agent_ids | list(string) | 该访问组授予访问权限的 Agent ID 列表 |
assigned_team_ids | list(string) | 被分配了该访问组的团队 ID 列表 |
assigned_key_ids | list(string) | 被分配了该访问组的 Key(token 哈希)ID 列表 |
created_at | string | 访问组的创建时间戳 |
created_by | string | 创建该访问组的用户 |
updated_at | string | 访问组最近一次更新时间戳 |
updated_by | string | 最近一次更新该访问组的用户 |
前置条件与适用范围
使用该数据源之前,需要满足以下条件:
- 已运行 LiteLLM Proxy 服务,并启用访问组相关的管理能力;
- 已配置 Terraform Provider 与 Proxy 的连接(Base URL 与访问凭证),Provider 侧连接初始化逻辑位于 provider.go;
- 待查询的访问组已在 Proxy 侧通过管理端 API、管理 UI 或 unified_access_group 资源 创建完成。
数据源的适用场景是"读取存量配置并与期望状态对比",例如在terraform plan前审计某访问组当前授予了哪些模型、是否还绑定了已下线的团队。若你需要的是创建/修改/删除访问组,则应使用对应的 unified_access_group Resource,而非本数据源。
从源码看数据源的真实调用链
理解了"查什么"之后,再看"怎么查"。数据源的完整 Go 实现在 data_source_unified_access_group.go。
Schema 定义:Computed 化 + 单一必填入参
dataSourceLiteLLMUnifiedAccessGroup()的 Schema 由两部分组成(源码 L67-L79):
- 复用
unifiedAccessGroupComputedSchema():把access_group_name、description、access_model_names、access_mcp_server_ids、access_agent_ids、assigned_team_ids、assigned_key_ids、created_at、created_by、updated_at、updated_by全部声明为Computed: true,即这些值只能由服务端响应写入,不允许用户在 HCL 里覆盖; - 追加
access_group_id,类型为TypeString、Required: true,作为查询的唯一定位键。
这种"1 个 Required + 11 个 Computed"的 Schema 组合是 Terraform Data Source 的典型形态:用户只负责描述"要查哪个",其余字段全部由 Provider 的 Read 函数回填。
Read 函数:一次只读 GET 请求
dataSourceLiteLLMUnifiedAccessGroupRead(源码 L81-L108)的实现非常直观:
- 从
ResourceData取出用户声明的access_group_id; - 通过客户端
MakeRequest发起GET /v1/unified_access_group/{groupID}; - 若 HTTP 返回
404,则直接以错误结束:"unified access group '{id}' not found"; - 其余非 2xx 响应交由
handleResponse统一处理; - 把响应体
JSON解码到unifiedAccessGroupResponse结构体; d.SetId(...)写入资源 ID,随后调用setUnifiedAccessGroupFields把响应字段逐一写回ResourceData。
unifiedAccessGroupResponse结构体(定义在 resource_unified_access_group.go)通过 JSON tag 映射了 Proxy 返回的全部字段,其中Description、CreatedBy、UpdatedBy是指针类型(*string),表示这些字段在服务端可能是缺失的;对应的回填逻辑setUnifiedAccessGroupFields(L123-L142)在写回前都做了nil判断,避免把空指针写进 State。这是 Go 侧对"可空响应字段"的标准防御式处理,也解释了为何description/created_by/updated_by在 Attribute 表中标注为"若存在"。
端点与数据结构小结
- HTTP 方法/路径:
GET /v1/unified_access_group/{access_group_id}(单查),GET /v1/unified_access_group(列表查询); - 请求/响应均为 JSON,字段名与 Terraform 属性名一一对应(下划线命名);
- 数据源是只读的,永远不发起 POST / PUT / DELETE。
错误处理与可用性语义
该数据源对"查不到"的处理是直接报错(区别于资源读取时"404 则从 State 中摘除"的收敛语义)。测试用例对这一点做了明确的断言:
- data_source_unified_access_group_test.go 中
TestUnifiedAccessGroupDataSourceReadNotFound用httptest返回404,随后断言 Read 必须返回错误(L49-L63); - 与之对照,resource_unified_access_group_test.go 中的
TestUnifiedAccessGroupReadNotFound断言资源在 404 时清空 ID 且不报错(L126-L142)。
这种差异是刻意的:数据源代表"被引用的存量事实",目标对象不存在时,下游引用它的资源应当 fail fast 而非静默拿到空数据;而资源代表"期望状态",目标被外部删除时收敛为空 State 并等待下次 apply 重建是更稳妥的选择。
组合使用:单查 + 列表 + 资源
如果不知道确切的访问组 ID,可以先使用列表数据源litellm_unified_access_groups一次性拉取全部访问组(文档见 unified_access_groups.md),其导出access_groups(数组,每项字段与本数据源一致)和ids(所有访问组 ID 列表):
data "litellm_unified_access_groups" "all" {} output "unified_access_group_ids" { value = data.litellm_unified_access_groups.all.ids }而需要管理访问组生命周期(创建、改名、增减绑定、删除)时,则使用管理资源。资源侧同时支持terraform import将存量访问组纳入管理(资源文档):
terraform import litellm_unified_access_group.engineering <access-group-id>一个常见的端到端模式是:先用资源声明访问组的期望权限,再用数据源在plan/apply之间校验实际生效值:
resource "litellm_unified_access_group" "engineering" { access_group_name = "engineering-access" description = "Models and tools for the engineering org" access_model_names = ["gpt-4", "claude-3-sonnet"] access_mcp_server_ids = [litellm_mcp_server.github.id] assigned_team_ids = [litellm_team.engineering.id] } data "litellm_unified_access_group" "engineering_check" { access_group_id = litellm_unified_access_group.engineering.id } output "audited_model_access" { value = data.litellm_unified_access_group.engineering_check.access_model_names }测试与验证方式
Provider 为访问组数据源提供了基于net/http/httptest的单元测试,不依赖真实 Proxy 即可验证 HTTP 契约:
TestUnifiedAccessGroupDataSourceRead:mockGET /v1/unified_access_group/uag-123,断言id、access_group_name、description、access_model_names、assigned_team_ids等字段被正确写入(测试源码 L12-L47);TestUnifiedAccessGroupsDataSourceRead:mock 列表端点返回两条访问组记录,断言access_groups数量、嵌套字段及ids汇总正确(L65-L112)。
测试夹具unifiedAccessGroupJSON产出的响应 JSON 覆盖了全部字段(含access_mcp_server_ids、access_agent_ids、assigned_key_ids等列表字段与时间戳),可在编写本地 Provider 用例时作为响应格式参考。
小结
litellm_unified_access_group是访问组场景里"读"的那一半:只接收access_group_id一个必填参数,返回模型、MCP 服务器、Agent、团队、Key 授权及审计时间戳等全部只读属性。它的底层不过是对 Proxy 管理端点GET /v1/unified_access_group/{id}的封装,但 Data Source 的 Schema(全 Computed)与错误语义(404 即报错)让它天然适合作为 IaC 状态校验与审计引用的可靠来源。需要完整管理访问组时,请搭配 litellm_unified_access_group 资源 使用。
相关源码与文档索引
- 本文主文档:terraform/provider/docs/data-sources/unified_access_group.md
- 数据源 Go 实现:data_source_unified_access_group.go
- 资源与响应结构体实现:resource_unified_access_group.go
- 数据源测试:data_source_unified_access_group_test.go
- 资源测试:resource_unified_access_group_test.go
- 列表数据源文档:terraform/provider/docs/data-sources/unified_access_groups.md
- 资源文档:terraform/provider/docs/resources/unified_access_group.md
- Proxy 侧访问组管理端点:access_group_endpoints.py
- 访问组与团队/Key 同步逻辑:access_group_team_sync.py、access_group_key_sync.py
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考