terraform-provider-aws 中 aws_ami_ids 数据源详解:AMI 批量检索的参数、实现与测试验证

发布时间:2026/9/17 19:07:29
terraform-provider-aws 中 aws_ami_ids 数据源详解:AMI 批量检索的参数、实现与测试验证 terraform-provider-aws 中 aws_ami_ids 数据源详解AMI 批量检索的参数、实现与测试验证【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws本篇围绕 Terraform AWS Provider 的aws_ami_ids数据源展开它会按owners、filter等条件调用 EC2DescribeImagesAPI 批量查找 AMI并将匹配到的镜像 ID 列表以ids属性输出。读完本文你将掌握该数据源全部参数含name_regex本地正则过滤、sort_ascending排序、include_deprecated等的正确用法并能从源码层面理解其分页查询、错误处理与 ID 排序的完整链路。典型用法按属主与名称模式筛选 AMIaws_ami_ids的定位是“获取一组 AMI ID 列表”官方文档见 website/docs/d/ami_ids.html.markdown。最典型的场景是只查某一个属主如 Ubuntu 官方账户099720109477名下符合名称模式的全部镜像data aws_ami_ids ubuntu { owners [099720109477] filter { name name values [ubuntu/images/ubuntu-*-*-amd64-server-*] } }此时data.aws_ami_ids.ubuntu.ids即返回所有匹配的 AMI ID 列表。需要强调的是owners是必填项且至少提供一个值——源码中该属性声明为Required: true, MinItems: 1并对每个元素附加了validation.NoZeroValues校验不允许空字符串定义位于 ec2_ami_ids_data_source.go。参数参考Argument Reference结合官方文档与源码 schema 定义dataSourceAMIIDs该数据源支持以下参数参数必填类型/默认值说明region否字符串查询所在区域。默认使用 provider 配置中的 Region与其他 provider 资源的 region 语义一致owners是字符串列表至少 1 项限定搜索范围的 AMI 属主列表。合法取值为AWS 账户 ID、self当前账户、AWS 属主别名如amazon、aws-marketplace、microsoft。元素禁止为空值NoZeroValues校验executable_users否字符串列表仅保留对镜像具有显式启动权限的用户可见的镜像。取值为数值的账户 ID 或selffilter否filter块可多个名称/取值对的过滤条件完整可用过滤器名称以 EC2 APIDescribeImages的 Filters 参考为准include_deprecated否布尔默认false为true时返回结果包含已弃用deprecated的 AMI为false或未指定时不包含name_regex否正则字符串对 AWS 返回的 AMI 名称做本地正则匹配可实现 AWS API 过滤器不支持的更复杂模式因过滤在本地执行结果集过大时有性能影响建议配合其他参数缩小返回范围sort_ascending否布尔默认false按创建时间排序方向。默认降序最新的在前设为true则升序几点源码级的补充细节name_regex在 schema 层通过validation.StringIsValidRegExp校验保证配置的字符串是合法正则源码非法正则在 plan 阶段即报错而不是等到 read 时才失败。include_deprecated与sort_ascending均使用Default: false声明默认值与文档描述一致源码。filter块filter块包含两个字段name— 过滤器名称必填。合法名称即 EC2 APIDescribeImages所接受的所有 Filter 名称例如name、creation-date、architecture、virtualization-type、state、image-type等。values— 该过滤器接受的取值集合必填字符串集合。从源码看filter属性复用了 EC2 服务包统一的customFiltersSchemaTypeSetname/values两个 Required 字段定义在 filters.goread 时经 newCustomFilterList 转换为 EC2 API 的Filters结构。这意味着aws_ami_ids的过滤语义与 AWS CLI/API 完全对齐多个 filter 之间是 AND 关系同一 filter 的多个 values 之间是 OR 关系。输出属性与 ID 生成机制除上述参数外数据源额外导出ids— AMI ID 列表按创建时间排序方向由sort_ascending决定。源码中该属性为TypeList、Computed源码元素顺序稳定可靠。关于 Terraform 状态中的id属性值得说明数据源 read 完成后会执行d.SetId(strconv.Itoa(create.StringHashcode(fmt.Sprintf(%#v, input))))源码。从这段实现看id是对最终DescribeImagesInput结构体格式化的字符串做 hash 得到的整数。其直接效果是相同查询条件复用已有状态条件变化时状态自动刷新——这在数据源场景下是常见的稳定标识做法ids本身才是用户真正消费的输出。源码实现一次 read 的完整调用链read 入口为 dataSourceAMIIDsRead整个流程可拆为四步。1. 组装 DescribeImagesInputinput : ec2.DescribeImagesInput{ IncludeDeprecated: aws.Bool(d.Get(include_deprecated).(bool)), Owners: flex.ExpandStringValueList(d.Get(owners).([]any)), } if v, ok : d.GetOk(executable_users); ok { input.ExecutableUsers flex.ExpandStringValueList(v.([]any)) } if v, ok : d.GetOk(names.AttrFilter); ok { input.Filters newCustomFilterList(v.(*schema.Set)) }owners无条件放入输入executable_users与filter仅在配置了值时才设置到输入中GetOk语义避免向 API 传递空参数。2. 分页拉取全部镜像查询通过 findImages 执行该函数封装了分页与错误处理pages : ec2.NewDescribeImagesPaginator(conn, input) for pages.HasMorePages() { page, err : pages.NextPage(ctx) if tfawserr.ErrCodeEquals(err, errCodeInvalidAMIIDNotFound) { return nil, retry.NotFoundError{ LastError: err, } } if err ! nil { return nil, err } output append(output, page.Images...) }从源码结构看有两个要点使用 SDK v2 的DescribeImagesPaginator自动翻页保证结果集不受单页大小限制当 API 返回InvalidAMIID.NotFound错误码时转换为retry.NotFoundError错误码常量定义于 errors.go。对于数据源而言这意味着若按 ID 条件查询不到任何镜像Terraform 会得到一个明确的“未找到”错误而不是静默返回空列表。3. name_regex 本地过滤if v, ok : d.GetOk(name_regex); ok { r : regexache.MustCompile(v.(string)) for _, image : range images { name : aws.ToString(image.Name) // Check for a very rare case where the response would include no // image name. No name means nothing to attempt a match against, // therefore we are skipping such image. if name { continue } if r.MatchString(name) { filteredImages append(filteredImages, image) } } } else { filteredImages images[:] }这印证了文档中“该过滤在本地对 AWS 返回结果执行”的描述正则只匹配镜像的Name字段MatchString为部分匹配而非全匹配且对极少数无名称的镜像直接跳过。正则使用regexache.MustCompile预编译编译失败会在 plan/validate 阶段被拦截配合前述StringIsValidRegExp校验。4. 按创建时间排序并输出slices.SortFunc(filteredImages, func(a, b awstypes.Image) int { atime, _ : time.Parse(time.RFC3339, aws.ToString(a.CreationDate)) btime, _ : time.Parse(time.RFC3339, aws.ToString(b.CreationDate)) compare : atime.Compare(btime) if d.Get(sort_ascending).(bool) { return compare } return -compare }) for _, image : range filteredImages { imageIDs append(imageIDs, aws.ToString(image.ImageId)) }排序依据是 API 返回的CreationDate字段RFC3339 格式sort_ascending true时正序旧 → 新默认false时取-compare反转为倒序新 → 旧。因此ids[0]在默认配置下就是创建时间最新的镜像 ID这是“取属主下最新一批镜像批量部署”类场景的关键保证。验收测试对行为的实证验证配套的验收测试位于 ec2_ami_ids_data_source_test.go覆盖了文档声明的三条核心行为基础查询TestAccEC2AMIIDsDataSource_basic用owners [099720109477]加name过滤ubuntu/images/hvm-instance/ubuntu-*断言ids.# 0排序方向TestAccEC2AMIIDsDataSource_sorted构造两个aws_ami数据源取得两张已知镜像再用aws_ami_ids的name过滤同时命中它们分别以sort_ascending false/true各跑一步断言ids.0/ids.1的相对顺序正好相反include_deprecatedTestAccEC2AMIIDsDataSource_includeDeprecated以include_deprecated true查询 Ubuntu 镜像并断言结果非空。其中排序测试的配置值得注意它对第二张镜像额外叠加了creation-date过滤限定到某个月份使两张镜像的创建时间明确不同从而让升/降序断言具有确定性。Timeouts 与使用建议该数据源声明了 read 超时默认为 20 分钟对应 Terraform 的超时配置项read默认20m。源码中通过schema.ResourceTimeout{Read: schema.DefaultTimeout(20 * time.Minute)}实现源码。对结果集很大的属主如amazon这一宽松默认值给了分页拉取充分时间但如果配置了过宽的过滤器导致单次查询超过 20 分钟仍会因超时失败。基于以上实现细节实践上建议务必提供owners并尽量收窄owners必填本身就是防止全库扫描的设计查询公开镜像时用属主别名amazon查询发行方镜像时用具体账户 ID。优先用 API 侧filter其次才是name_regexname_regex在本地对全量返回结果做匹配文档已明确提示“结果集大时可能有性能影响”正确做法是先靠ownersfilter如creation-date、architecture、state available把 API 返回集压小再用正则做精细模式匹配。利用排序方向取最新镜像默认降序下ids[0]即最新镜像可与slice(data.aws_ami_ids.x.ids, 0, 1)等写法配合实现“取最新一个 AMI”的模式需要稳定旧版本审计时再显式开启sort_ascending。注意 deprecated 语义include_deprecated默认false若属主已弃用某些镜像而你希望它们仍出现在列表中例如做清理盘点需显式置为true。该数据源在 provider 中的注册信息可见 service_package_gen.goTypeName: aws_ami_ids与同服务包内的 aws_ami 单镜像数据源文档 构成互补查单张镜像用aws_ami查一组 ID 用aws_ami_ids。【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考