terraform-provider-aws 数据源 aws_eks_clusters:全量枚举一个 AWS 区域的 EKS 集群名称
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
本篇技术文章围绕 Terraform AWS Provider 的数据源aws_eks_clusters展开:介绍它的适用场景、完整的 HCL 用法、参数与属性定义,并结合internal/service/eks包下的源码与验收测试,深入讲解它如何通过 AWS SDK for Go v2 的分页器(Paginator)遍历整个区域的 EKS 集群。读完后,你将能够用该数据源在 Terraform 配置中动态发现区域内的所有 EKS 集群,并理解其背后的分页迭代实现与测试验证方式。
数据源定位:从“名称列表”到“集群详情”
aws_eks_clusters是一个列表型数据源(list-type data source),其官方描述为 “Retrieve EKS Clusters list”(检索 EKS 集群列表)。它解决的问题是:当你不知道当前区域里存在多少个 EKS 集群、或不想手工维护集群名称清单时,可以用一条data块直接枚举出区域内全部集群的名称集合,再基于这些名称驱动其他资源或数据源(for_each)逐个获取详情。
与之对应的单集群数据源是aws_eks_cluster(需要预先指定name)。官方文档给出的典型用法正是两者的组合:先用aws_eks_clusters拿到名称集合,再用for_each对每个名称实例化aws_eks_cluster拉取完整详情。
示例用法
官方文档(website/docs/d/eks_clusters.html.markdown)给出的完整示例如下,可直接复制使用:
data "aws_eks_clusters" "example" {} data "aws_eks_cluster" "example" { for_each = toset(data.aws_eks_clusters.example.names) name = each.value }要点说明:
data "aws_eks_clusters" "example" {}不需要任何必填参数,空块即表示“列出当前 provider 配置区域下的全部集群”;names的类型是Set(无序集合),因此在 HCL 中先经toset(...)显式转换为 set 类型,再传给for_each,保证每个集群只实例化一次;- 内层
data.aws_eks_cluster.example会为集合中的每个名称创建一个实例,最终data.aws_eks_cluster.example[<name>]即对应单个集群的完整属性(状态、Kubernetes 版本、vpc_config 等,详见aws_eks_cluster数据源文档)。
这一“列表数据源 + for_each 详情数据源”的模式,是该仓库所有列表型数据源的通用消费方式。
参数参考(Argument Reference)
该数据源支持的参数很少,官方文档只列出:
| 参数 | 必填 | 说明 |
|---|---|---|
region | 否(Optional) | 查询的 AWS 区域。缺省时使用 provider 配置中设置的 Region。 |
从源码看(clusters_data_source.go),dataSourceClusters()的 schema 中只显式声明了一个属性names(names.AttrNames,TypeSet、Computed,元素为字符串),没有任何可配置的过滤参数(如名称前缀、标签过滤都不支持)。region参数由 provider 层面的区域解析机制统一处理,Read函数通过c.Region(ctx)读取当前生效区域——这正是文档中“Defaults to the Region set in the provider configuration”的实现来源。因此:
- 想查询其他区域的集群,需要在
data块上显式写region = "eu-west-1"(由 provider 的 region 逻辑注入到客户端); - 若需要按标签、名称前缀等条件筛选,只能在拿到
names之后,在 HCL 层用setintersect、setintersection等集合函数自行过滤,数据源本身不提供服务端过滤。
属性参考(Attribute Reference)
官方文档列出了除参数之外导出的两个属性:
| 属性 | 说明 |
|---|---|
id | AWS Region(即当前 provider 配置的 AWS 区域名称,例如us-east-1)。 |
names | Set,区域内所有 EKS 集群的名称集合。 |
关于id的取值逻辑可以直接在源码中确认:clusters_data_source.go 中执行d.SetId(c.Region(ctx)),即把区域字符串作为 Terraform state 中该数据源的id。这是一种刻意的设计:数据源没有任何服务端资源 ID 可用,用区域标识 id 可以让同一区域多次 plan 之间保持 id 稳定(只要区域不变,state 就不会出现无意义的 diff)。
names的写入则在同文件第 49 行d.Set(names.AttrNames, clusters),其中clusters是经过分页收集后的[]string切片,最终在 state 中表现为无序字符串集合。
源码实现:分页迭代与错误传播
核心 Read 函数
dataSourceClustersRead(clusters_data_source.go)的完整流程只有三步:
- 从 provider 元数据取得 EKS 客户端:
c.EKSClient(ctx); - 调用
tfslices.CollectWithError(listClusters(ctx, conn, &input))一次性收集所有分页的集群名称;出错则通过sdkdiag.AppendFromErr转为 Terraform Diagnostics; - 设置
id与names。
这里有两个值得注意的实现细节:
- 传入的
input是一个空的eks.ListClustersInput——再次印证该 API 调用不带任何过滤条件,返回的是区域内的全量集群名称; - 数据源文件头部的
@SDKDataSource("aws_eks_clusters", name="Clusters")注解用于代码生成(见 service_package_gen.go 中的Factory: dataSourceClusters注册项),保证数据源名称、常量与生成代码保持同步。
分页收集器:listClusters 迭代器
真正调用 AWS API 的是listClusters函数(cluster_list.go),它返回一个 Go 1.23 风格的iter.Seq2[string, error]迭代器序列:
func listClusters(ctx context.Context, conn *eks.Client, input *eks.ListClustersInput) iter.Seq2[string, error] { return func(yield func(string, error) bool) { pages := eks.NewListClustersPaginator(conn, input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { yield(inttypes.Zero[string](), fmt.Errorf("listing EKS Clusters: %w", err)) return } for _, item := range page.Clusters { if !yield(item, nil) { return } } } } }关键点:
- 自动分页:
eks.NewListClustersPaginator是 AWS SDK for Go v2 的分页器,ListClustersAPI 单页最多返回 100 个结果,当区域内集群超过单页容量时,该循环会透明地跟随NextToken取完所有页。对用户而言names永远是完整的; - 错误包装:分页失败时错误被包装为
listing EKS Clusters: <原始错误>并经由yield的 error 通道传出,由CollectWithError接收后变成 Terraform 诊断信息,便于排障; - 提前终止支持:
if !yield(item, nil) { return }让调用方可以中途停止消费,不过数据源场景下CollectWithError会消费到底,收集全部名称。
CollectWithError定义在 internal/slices/slices.go,它把iter.Seq2[E, error]序列物化为切片,是仓库中“迭代器 → 集合”的通用转换工具。
与新版 list resource 的共享实现
值得注意的是,listClusters同时被两处复用:
- 本数据源
aws_eks_clusters(SDKv2 风格,只导出名称集合); - 框架层的list resource
aws_eks_cluster(cluster_list.go 中@SDKListResource("aws_eks_cluster")),它通过yield逐条产出集群,并在request.IncludeResource时进一步调用findClusterByName拉取完整集群属性做展平(flatten)。
也就是说,仓库内部“只列名称”和“列出带详情资源”两条路径共用同一个分页迭代器,避免了重复实现分页逻辑。对于希望以 Terraform 框架原生的 list resource 方式消费集群列表的场景,可以参考仓库文档 docs/list-resources.md。
验收测试如何验证该数据源
验收测试TestAccEKSClustersDataSource_basic位于 clusters_data_source_test.go,其验证逻辑简洁但有代表性:
func TestAccEKSClustersDataSource_basic(t *testing.T) { ctx := acctest.Context(t) rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) dataSourceResourceName := "data.aws_eks_clusters.test" acctest.ParallelTest(ctx, t, resource.TestCase{ // ... Steps: []resource.TestStep{ { Config: testAccClustersDataSourceConfig_basic(rName), Check: resource.ComposeTestCheckFunc( acctest.CheckResourceAttrGreaterThanValue(dataSourceResourceName, "names.#", 0), ), }, }, }) }测试配置(同文件第 35–41 行)先用testAccClusterConfig_basic创建了一个真实集群,再声明:
data "aws_eks_clusters" "test" { depends_on = [aws_eks_cluster.test] }这里depends_on保证数据源读取发生在集群创建之后,随后用CheckResourceAttrGreaterThanValue(..., "names.#", 0)断言集合非空——即“刚创建的集群一定出现在names里”。names.#正是 Set 类型的元素个数属性。该测试运行需要真实的 AWS 凭据与区域环境,可参阅仓库文档 docs/running-and-writing-acceptance-tests.md 了解验收测试的执行方式。
适用前提与使用限制
基于仓库当前实现,使用该数据源时需注意:
- 区域粒度:它枚举的是 provider 当前(或显式指定的)单个区域内全部 EKS 集群,不会跨区域;查询多区域需为每个区域声明 provider 别名或显式
region; - 无过滤能力:不支持名称前缀、状态、标签等任何服务端过滤条件,筛选只能在 HCL 层对
names做集合运算; - 只含名称:本数据源只返回集群名称,不包含状态、版本、endpoint 等字段;获取详情请配合
aws_eks_cluster数据源,或采用框架 list resourceaws_eks_cluster; - 权限要求:执行该读取需要调用者具备
eks:ListClusters权限。
关键文件索引
| 文件 | 作用 |
|---|---|
| website/docs/d/eks_clusters.html.markdown | aws_eks_clusters数据源官方文档(本文主体来源) |
| internal/service/eks/clusters_data_source.go | 数据源 schema 定义与 Read 实现 |
| internal/service/eks/cluster_list.go | 分页迭代器listClusters与 list resource 实现 |
| internal/service/eks/clusters_data_source_test.go | 验收测试 |
| internal/service/eks/service_package_gen.go | 数据源在 service package 中的工厂注册 |
| internal/slices/slices.go | 迭代器切片收集器CollectWithError |
| docs/list-resources.md | 框架 list resource 设计与使用文档 |
| docs/add-a-new-datasource.md | 新增数据源的开发指南 |
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考