Terraform AWS Provider 数据源 aws_cloudfront_distribution_tenant 完全指南:按 ID 或域名检索 CloudFront 多租户分布
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
本文以terraform-provider-aws仓库中的 website/docs/d/cloudfront_distribution_tenant.html.markdown 文档为骨架,结合仓库内 distribution_tenant_data_source.go、distribution_tenant.go 等源码实现,系统讲解aws_cloudfront_distribution_tenant数据源的参数、导出属性、底层调用链与实战用法。读完本文,你将掌握如何通过分布租户 ID、域名、ARN 或名称从 CloudFront 多租户分布中查询租户信息,并能在 Terraform 配置中直接引用其 ARN、域名列表、状态等属性完成基础设施编排。
背景:什么是 CloudFront Distribution Tenant
在深入了解数据源之前,需要先明确"分布租户(Distribution Tenant)"这一概念。根据仓库中资源文档 website/docs/r/cloudfront_distribution_tenant.html.markdown 的说明:
Distribution tenants allow you to create isolated configurations within a multi-tenant CloudFront distribution. Each tenant can have its own domains, customizations, and parameters while sharing the underlying distribution infrastructure.
即:分布租户允许你在一个多租户 CloudFront 分布(multi-tenant distribution)内创建彼此隔离的配置。每个租户可以拥有自己独立的域名(domains)、自定义配置(customizations,如证书、地域限制、Web ACL)和参数(parameters),同时共享底层分布基础设施。这非常适合 SaaS 类场景中"一套边缘基础设施、多客户隔离配置"的诉求。
aws_cloudfront_distribution_tenant数据源正是用于读取这类租户的当前状态信息,而对应的资源aws_cloudfront_distribution_tenant则用于创建和管理租户。二者配合使用,是"先管理、后查询引用"的标准 Terraform 模式。
数据源概览与适用场景
数据源的核心作用(见文档首句):
Use this data source to retrieve information about a CloudFront distribution tenant.
适用场景包括:
- 在配置中引用某个已存在租户的ARN(如用于 IAM 策略、标签集成或依赖其他资源);
- 查询租户的域名列表(domains)以动态生成 DNS 记录或证书校验记录;
- 判断租户当前的部署状态(status),确认其信息是否已全量传播到 CloudFront 边缘网络;
- 读取租户的etag、distribution_id、enabled、connection_group_id等元数据,用于构建跨资源依赖。
参数参考(Argument Reference)
文档明确规定数据源支持以下参数:
| 参数 | 类型 | 说明 |
|---|---|---|
id | 可选(String) | 分布租户的标识符,例如EDFDVBD632BHDS5。id与domain必须且只能指定其一。 |
domain | 可选(String) | 分布租户的关联域名。id与domain必须且只能指定其一。 |
从源码看:实际支持的查询键更多
虽然原文档只列出id与domain两个查询键,但从仓库源码可以确认,数据源的实际查询能力更强。在 distribution_tenant_data_source.go 中,Read方法定义了一个"查找策略表(lookup strategies)":
lookupStrategies := []struct { value types.String fn func(context.Context, *cloudfront.Client, string) (any, error) }{ {data.ID, ...}, // 按 ID 查询 {data.ARN, ...}, // 按 ARN 查询 {data.Name, ...}, // 按 Name 查询 {data.Domain, ...},// 按 Domain 查询(走 GetDistributionTenantByDomain API) }也就是说,从源码结构看,id、arn、name、domain四个字段都可以作为查询键,其中前三个最终都调用findDistributionTenantByIdentifier(即 CloudFront 的GetDistributionTenantAPI,入参为Identifier),而domain走的是findDistributionTenantByDomain(即GetDistributionTenantByDomainAPI,入参为Domain)。
同时,ConfigValidators 使用 Terraform Plugin Framework 的datasourcevalidator.ExactlyOneOf对id、arn、name、domain四个根级路径做互斥校验:
datasourcevalidator.ExactlyOneOf( path.MatchRoot(names.AttrID), path.MatchRoot(names.AttrARN), path.MatchRoot(names.AttrName), path.MatchRoot(names.AttrDomain), )这意味着四个查询键中必须且只能指定一个,否则 Terraform 会在规划阶段直接报错。在编写配置时,可依据手头掌握的信息灵活选择最合适的查询键。
Read方法还会依次遍历查找策略,只使用第一个非空(IsNull/IsUnknown均为 false)的字段发起查询(见 distribution_tenant_data_source.go),因此即使同时配置多个键,也只会按顺序命中第一个。
属性参考(Attribute Reference)
文档列出数据源除参数外导出的属性如下:
| 属性 | 类型 | 说明 |
|---|---|---|
domains | List | 分布租户的域名列表。 |
arn | String | 分布租户的 ARN。 |
status | String | 分布租户的当前状态。若为Deployed,表示租户信息已完全传播到整个 CloudFront 系统。 |
distribution_id | String | 租户所关联的 CloudFront 分布 ID。 |
etag | String | 租户信息的当前版本号,例如E2QWRUHAPOMQZL。 |
enabled | Bool | 分布租户是否已启用。 |
connection_group_id | String | 租户关联的 CloudFront connection group 的 ID。 |
从源码看:Schema 中的完整属性集
数据源在 Schema 定义 中实际注册的属性比文档列出的更多,除上述 7 个外还包括:
customizations:租户的自定义配置(证书、地域限制、Web ACL);managed_certificate_request:CloudFront 托管 ACM 证书的请求信息;name:租户名称(同时可作查询键);parameters:租户参数列表;tags:租户标签(ComputedOnly)。
其中arn、id、domain均被声明为Optional + Computed,即既可以作为查询键传入,也会在查询成功后回填。数据源模型distributionTenantDataSourceModel(见 distribution_tenant_data_source.go)中,domains由domainResultModel组成,每个元素包含domain与status两个字段——这意味着domains列表中每个域名都带有独立的传播状态。
status 与 etag 的语义
status与etag的取值语义可在资源源码中找到印证。consts.go 定义了两种租户状态:
distributionTenantStatusDeployed = "Deployed" distributionTenantStatusInProgress = "InProgress"资源在 waitDistributionTenantDeployed 中会轮询等待租户从InProgress变为Deployed。因此数据源读取到的status字段,Deployed即代表租户信息已全量传播到 CloudFront 系统,可安全对外提供流量;etag则是租户信息的版本标识,资源在更新/删除操作中会将其作为IfMatch条件使用(见 distribution_tenant.go),数据源返回同一字段可帮助你在外部实现乐观并发控制。
使用示例
按租户 ID 查询(文档标准示例)
data "aws_cloudfront_distribution_tenant" "test" { id = "EDFDVBD632BHDS5" }按关联域名查询
data "aws_cloudfront_distribution_tenant" "by_domain" { domain = "tenant.example.com" }与资源联用:创建后立即查询
更常见的做法是与aws_cloudfront_distribution_tenant资源、aws_cloudfront_multitenant_distribution资源组合,直接引用资源的输出来查询并导出属性:
resource "aws_cloudfront_multitenant_distribution" "example" { # 多租户分布定义,例如 primary_domain 等 } resource "aws_cloudfront_distribution_tenant" "example" { name = "example-tenant" distribution_id = aws_cloudfront_multitenant_distribution.example.id enabled = true domain { domain = "tenant.example.com" } } # 通过资源 ID 查询租户详情 data "aws_cloudfront_distribution_tenant" "test" { id = aws_cloudfront_distribution_tenant.example.id } output "tenant_arn" { value = data.aws_cloudfront_distribution_tenant.test.arn } output "tenant_status" { value = data.aws_cloudfront_distribution_tenant.test.status }源码实现深度解析
查询流程
数据源的Read生命周期方法(见 distribution_tenant_data_source.go)执行步骤如下:
- 从配置中读取模型数据;
- 通过
d.Meta().CloudFrontClient(ctx)获取 CloudFront 客户端; - 按顺序遍历查找策略表,命中第一个非空查询键;
- 调用对应查找函数发起 AWS API 请求;
- 对返回结果做类型断言,兼容
GetDistributionTenantOutput与GetDistributionTenantByDomainOutput两种响应结构(二者都携带DistributionTenant与ETag字段); - 使用
fwflex.Flatten将 API 响应扁平化写入模型; - 手动回填
id与etag两个需要特殊处理的计算字段; - 写入 State。
底层 API 调用与错误处理
按域名查询的底层实现findDistributionTenantByDomain(见 distribution_tenant_data_source.go)直接调用 CloudFront 的GetDistributionTenantByDomainAPI:
input := cloudfront.GetDistributionTenantByDomainInput{ Domain: aws.String(domain), } output, err := conn.GetDistributionTenantByDomain(ctx, &input)错误处理遵循仓库统一的tfresource/retry约定:
- 遇到
awstypes.EntityNotFound(AWS 侧"实体不存在")时,包装为retry.NotFoundError,供上层用retry.NotFound(err)判断"未找到"语义; - 响应为 nil 或响应中
DistributionTenant为 nil 时,返回tfresource.NewEmptyResultError()(空结果错误); - 其余错误原样向上传递,最终由
Read方法以response.Diagnostics.AddError形式暴露给用户。
按 ID/ARN/Name 查询走findDistributionTenantByIdentifier(见 distribution_tenant.go),其内部同样调用GetDistributionTenant,并额外校验Domains与DistributionId不为空,避免返回不完整的租户数据。
测试验证:四种查询路径均有覆盖
仓库提供了完整的接受性测试(Acceptance Test)来验证数据源各查询路径,见 distribution_tenant_data_source_test.go:
TestAccCloudFrontDistributionTenantDataSource_basic:按id查询;TestAccCloudFrontDistributionTenantDataSource_byARN:按arn查询;TestAccCloudFrontDistributionTenantDataSource_byName:按name查询;TestAccCloudFrontDistributionTenantDataSource_byDomain:按domain查询(该用例通过depends_on显式等待租户资源创建完成)。
测试使用resource.TestCheckResourceAttrPair逐项比对数据源与资源输出的arn、connection_group_id、distribution_id、enabled、etag、name、status等字段的一致性,并通过statecheck.CompareValuePairs验证数据源id与资源id相同、tags与资源tags_all相同。这些断言从侧面印证了数据源与资源在字段语义上完全对齐。
每个测试用例都通过acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID)做分区服务预检,并设置ProtoV5ProviderFactories,说明该数据源基于 Terraform Plugin Framework(Protocol v5)实现。若需在本地运行,可参考仓库 docs/running-and-writing-acceptance-tests.md 配置 AWS 凭据后执行make testacc TESTS=TestAccCloudFrontDistributionTenantDataSource_basic。
使用注意事项
- 查询键互斥:
id、arn、name、domain四者必须且只能指定一个,违反ExactlyOneOf约束会在规划阶段报错。原文档仅描述id/domain两个键,arn与name属于源码已实现、文档尚未同步的能力,使用前请先在本仓库对应版本的 provider 上验证。 domain的语义:传入的域名必须是该租户的关联域名,查询由 CloudFrontGetDistributionTenantByDomainAPI 完成;若租户不存在,数据源会返回"未找到"类错误,可通过data.aws_cloudfront_distribution_tenant.xxx的读取结果判断资源是否存在。status字段:只有Deployed才表示租户配置已全量传播到 CloudFront 边缘系统;InProgress表示仍在部署中,此时引用租户对外提供流量的能力可能尚未就绪。etag的并发语义:etag是租户配置的版本标识。若你同时通过其他工具(如 AWS CLI、SDK)修改租户,数据源每次读取都会返回最新版本,可作为检测配置漂移的依据。- 数据源本身无实际变更能力:数据源只读,不创建、不修改、不删除任何 CloudFront 资源;租户的完整生命周期管理请使用 aws_cloudfront_distribution_tenant 资源。
【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考