Terraform AWS Provider 数据源 aws_ec2_hosts 完全指南:按条件批量查询 EC2 Dedicated Hosts 📅 发布时间:2026/9/18 18:36:24 👁 浏览次数: Terraform AWS Provider 数据源 aws_ec2_hosts 完全指南按条件批量查询 EC2 Dedicated Hosts【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws本指南围绕 Terraform AWS Provider 提供的aws_ec2_hosts数据源展开讲解如何通过filter、tags、outpost_arn等参数批量查询 EC2 Dedicated Hosts专用主机的 ID 列表并深入源码层面剖析其底层实现原理DescribeHostsAPI 调用、分页逻辑与客户端过滤机制。读完本文你将能够在 Terraform 配置中精准筛选专用主机并理解该数据源在 terraform-provider-aws 仓库中的完整实现链路。数据源概述什么是aws_ec2_hostsaws_ec2_hosts是一个框架Plugin Framework实现的数据源其功能是返回一组与给定过滤器匹配的 EC2 Dedicated Host 的 ID 列表。它与单实例查询的数据源如aws_ec2_host不同专为批量发现场景设计例如你需要获取某个可用区、某个实例类型下所有可用状态的专用主机 ID供后续资源引用或循环创建实例使用。该数据源的官方说明位于 website/docs/d/ec2_hosts.html.markdown其 frontmatter 中的描述为Provides details about multiple EC2 Dedicated Hosts。关于 Dedicated Host 的更多背景可参考 AWS 官方 EC2 User Guide 中的 Dedicated Hosts 章节文档内链接为外部站点此处仅提示语义。示例用法按实例类型过滤最常见的用法是同时传入多个filter块数据源会返回同时满足所有过滤器AND 语义的主机 IDdata aws_ec2_hosts example { filter { name instance-type values [c5.large] } filter { name state values [available] } }这段配置的含义是查询所有实例类型为c5.large且状态为available可用的 Dedicated Host。查询结果会导出到data.aws_ec2_hosts.example.ids供其他资源引用。按 Outpost ARN 过滤outpost_arn参数用于筛选部署在指定 AWS Outpost 上的主机。需要特别注意的是DescribeHostsAPI 并不支持将outpost-arn作为服务端过滤条件因此该参数是在 Provider 内部通过客户端侧过滤实现的data aws_ec2_hosts outpost { outpost_arn data.aws_outposts_outpost.example.arn filter { name state values [available] } }Argument Reference参数参考以下是aws_ec2_hosts支持的参数全部为可选参数是否可选说明filter可选一个或多个配置块用于按名称-值过滤。支持的过滤器名称见 AWS EC2 API 参考中DescribeHosts的 Filter 列表。详细说明见下文outpost_arn可选AWS Outpost 的 ARN。客户端侧过滤仅返回分配在该 Outpost 上的主机region可选该数据源执行查询的 AWS 区域默认使用 Provider 配置中设置的区域tags可选键值对形式的资源标签映射每一对标签都必须与目标 Dedicated Host 上的标签精确匹配filter块每个filter配置块支持以下参数参数是否必填说明name必填过滤器名称对应DescribeHostsAPI 支持的过滤字段values必填一个或多个过滤器值组成的列表从源码看filter块被建模为集合嵌套块SetNestedBlock其中的name为必填字符串属性values为必填字符串集合定义在 internal/service/ec2/filters.go#L136-L152func customFiltersBlock(ctx context.Context) datasourceschema.Block { return datasourceschema.SetNestedBlock{ CustomType: fwtypes.NewSetNestedObjectTypeOfcustomFilterModel, NestedObject: datasourceschema.NestedBlockObject{ Attributes: map[string]datasourceschema.Attribute{ names.AttrName: datasourceschema.StringAttribute{Required: true}, names.AttrValues: datasourceschema.SetAttribute{ CustomType: fwtypes.SetOfStringType, ElementType: types.StringType, Required: true, }, }, }, } }值得注意的一个实现细节values在 schema 中是一个Set无序集合而对应的customFilterModel结构体filters.go#L155-L158使用fwtypes.SetOfString承载值这意味着在配置中多个filter块的顺序不影响查询结果。Attribute Reference属性参考除上述参数外该数据源还会导出以下属性属性说明idsEC2 Dedicated Host 标识符Host ID的列表ids在 schema 中被声明为 Computed计算属性的字符串列表ec2_hosts_data_source.go#L37-L41names.AttrIDs: schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, ElementType: types.StringType, Computed: true, },源码级实现原理数据源的框架化注册该数据源使用 Terraform Plugin Framework 实现通过FrameworkDataSource注解注册对应源码为 internal/service/ec2/ec2_hosts_data_source.go// FrameworkDataSource(aws_ec2_hosts, nameHosts) func newHostsDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { return hostsDataSource{}, nil }数据源的模型结构体hostsDataSourceModel继承自framework.WithRegionModel用于注入region参数并声明了filter、ids、outpost_arn、tags四个字段ec2_hosts_data_source.go#L92-L98。Read 调用链从配置到DescribeHosts数据源的核心逻辑在Read方法ec2_hosts_data_source.go#L53-L90完整流程如下从请求配置中解析出用户定义的过滤器、标签与outpost_arn通过d.Meta().EC2Client(ctx)获取 EC2 客户端构造ec2.DescribeHostsInput将用户过滤器转换为 API Filter 列表input : ec2.DescribeHostsInput{ Filter: append(newCustomFilterListFramework(ctx, data.Filters), newTagFilterList(svcTags(tftags.New(ctx, data.Tags)))...), }这里体现了两个关键转换函数newCustomFilterListFrameworkfilters.go#L209-L236把 Terraform 侧的filter集合逐条转换为awstypes.Filter{Name, Values}跳过未设置或未知的条目newTagFilterListfilters.go#L53-L57把tags映射转换为tag:Key格式的过滤器实现标签必须精确匹配的服务端过滤func newTagFilterList(tags []awstypes.Tag) []awstypes.Filter { return tfslices.ApplyToAll(tags, func(tag awstypes.Tag) awstypes.Filter { return newFilter(tag:aws.ToString(tag.Key), []string{aws.ToString(tag.Value)}) }) }调用findHosts执行查询详见下文分页逻辑客户端侧过滤 Outpost ARN由于 API 不支持outpost-arn服务端过滤代码在拿到全部主机列表后用tfslices.Filter逐条比对Host.OutpostArn与用户传入的outpost_arnif !data.OutpostARN.IsNull() !data.OutpostARN.IsUnknown() { outpostARN : data.OutpostARN.ValueString() output tfslices.Filter(output, func(v awstypes.Host) bool { return aws.ToString(v.OutpostArn) outpostARN }) }最后通过fwflex.FlattenFrameworkStringValueListOfString把每条主机的HostId展平为字符串列表写入ids并保存到状态data.IDs fwflex.FlattenFrameworkStringValueListOfString(ctx, tfslices.ApplyToAll(output, func(v awstypes.Host) string { return aws.ToString(v.HostId) }))分页与错误处理findHosts查询动作最终落到 internal/service/ec2/find.go#L355-L376 的findHosts函数它使用 EC2 SDK 的DescribeHostsPaginator自动分页拉取全部结果避免单次 API 响应大小限制导致数据缺失func findHosts(ctx context.Context, conn *ec2.Client, input *ec2.DescribeHostsInput) ([]awstypes.Host, error) { var output []awstypes.Host pages : ec2.NewDescribeHostsPaginator(conn, input) for pages.HasMorePages() { page, err : pages.NextPage(ctx) if tfawserr.ErrCodeEquals(err, errCodeInvalidHostIDNotFound) { return nil, retry.NotFoundError{LastError: err} } if err ! nil { return nil, err } output append(output, page.Hosts...) } return output, nil }该实现还处理了特殊错误码InvalidHostID.NotFound定义于 internal/service/ec2/errors.go#L51将其归一化为retry.NotFoundError便于上层统一处理查询对象不存在的场景。整体执行流程图Terraform 配置 (filter / tags / outpost_arn) │ ▼ Read() 解析模型 (hostsDataSourceModel) │ ├──► newCustomFilterListFramework ──► []awstypes.Filter用户 filter 块 ├──► newTagFilterList ─────────────► []awstypes.Filtertag:Key 格式 │ ▼ DescribeHostsInput ──► findHosts()DescribeHostsPaginator 分页拉取 │ ▼ 服务端返回全部 Host 列表 │ ▼ outpost_arn 非空──► tfslices.Filter 客户端侧按 OutpostArn 精确匹配 │ ▼ 展平 HostId ──► ids 属性写入 State测试用例佐证仓库为aws_ec2_hosts提供了三组接受测试Acceptance Tests位于 internal/service/ec2/ec2_hosts_data_source_test.go可以作为完整可运行的实战模板TestAccEC2HostsDataSource_filter先创建aws_ec2_host资源实例类型c5.large指定可用区再用instance-typeavailability-zone两个过滤器查询断言ids.#大于 0TestAccEC2HostsDataSource_outpostARN在 Outpost 上创建主机实例族r5d配合aws_outposts_outposts/aws_outposts_outpost数据源获取 Outpost ARN验证outpost_arn客户端过滤后ids.#恰好为 1TestAccEC2HostsDataSource_tags创建带Name标签的主机然后通过tags参数精确匹配断言ids.#为 1。其中 filter 场景的配置片段展示了数据源与资源depends_on的正确配合方式resource aws_ec2_host test { availability_zone data.aws_availability_zones.available.names[0] instance_type c5.large tags { Name tf-acc-test-... } } data aws_ec2_hosts test { filter { name instance-type values [c5.large] } filter { name availability-zone values [aws_ec2_host.test.availability_zone] } }注意测试中使用了acctest.PreCheckOutpostsOutposts做前置检查ec2_hosts_data_source_test.go#L41说明 Outpost 相关用例只有在测试账户具备 Outposts 资源时才可运行——这是实际环境中使用outpost_arn参数前需要确认的前提条件。实践要点与注意事项filter与tags可组合使用两者最终都会转换成DescribeHosts的 Filter 数组合并下发语义为 AND即结果必须同时匹配所有条件。outpost_arn是客户端过滤它发生在 API 返回全部主机之后因此若账户内主机数量巨大该参数无法减少 API 数据传输量仅影响最终返回的ids结果。values支持通配符从测试配置可见values [r5d.*]这类通配符写法ec2_hosts_data_source_test.go#L96-L99这与 EC2 过滤语法保持一致。分页自动处理底层findHosts使用 Paginator无需关心主机数量超过单页上限的问题。结果集为空时的表现当没有任何主机匹配时ids为空列表而非报错除非 API 返回InvalidHostID.NotFound等异常下游引用ids的for_each等表达式会自然得到空集合便于做条件化处理。可用区域region查询默认在 Provider 配置的区域执行跨区域查询需显式设置region参数与 Provider 区域化管理的整体设计一致。【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考