You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform获取AWS AMI报错:values需字符串列表类型的解决咨询

问题描述

我需要用Terraform获取每周创建的特定AMI(ID未知,可通过名称检索)来更新EC2实例,采用了AWS External数据源、bash脚本实现,但遇到了类型错误。

报错信息

Error: Incorrect attribute value type

on main.tf line 20, in data "aws_ami" "get_ami_id":
20: values = "{$data.external.get_ami_name.results}"

Inappropriate value for attribute "values": list of string required.

现有代码

get_ami_name.sh

#!/bin/bash

AMI_NAME=$(aws ec2 describe-images --owners 5555566666 --query 'Images[?Name>=`em`][]'|grep Name|grep -v DeviceName|sort -n|tail -5|sort -t- -nrk5,5|awk '{print $2}'|sed 's/"//g')
jq -n --arg ami_name "$AMI_NAME" '{"ami_name":$ami_name}'

main.tf

# 获取最新AMI名称
data "external" "get_ami_name" {
   program = ["bash", "${path.root}/get_ami_name.sh"]
}

output "ami_name_out" {
   value = ["data.external.get_ami_name.results"]
}

# 根据检索到的名称获取AMI ID
data "aws_ami" "get_ami_id" {
   most_recent = true
   owners = ["555556666"]
   filter {
      name = "name"
          values = "{$data.external.get_ami_name.results}"
   }
}

解决方案

1. 修复现有代码的错误

修正Terraform变量引用错误

values字段要求是字符串列表,你当前的写法有两个问题:

  • 变量引用语法错误:应该用${...}而非{$...}
  • 没有正确提取ami_name字段:data.external.get_ami_name.results是一个map,需要指定键ami_name
  • 要把值包装成列表形式

修改后的data "aws_ami" "get_ami_id"部分:

data "aws_ami" "get_ami_id" {
   most_recent = true
   owners = ["555556666"]
   filter {
      name = "name"
      values = [data.external.get_ami_name.results.ami_name]
   }
}

另外,output部分的写法也有误,应该直接引用map的字段,而非字符串:

output "ami_name_out" {
   value = data.external.get_ami_name.results.ami_name
}

确保bash脚本返回单个AMI名称

你的bash脚本可能返回多个名称(因为用了tail -5),这会导致Terraform的filter匹配多个AMI,建议调整脚本只输出最新的一个名称,比如优化aws cli的query参数直接获取最新的:

#!/bin/bash

# 用aws cli的query直接排序并取最新的AMI名称,避免复杂的文本处理
AMI_NAME=$(aws ec2 describe-images --owners 5555566666 --query 'sort_by(Images[?starts_with(Name, `em`)], &CreationDate)[-1].Name' --output text)
jq -n --arg ami_name "$AMI_NAME" '{"ami_name":$ami_name}'

2. 更优实现:完全用Terraform内置功能(无需外部脚本)

直接使用Terraform的aws_ami数据源结合内置函数,不需要依赖bash脚本和external数据源,更符合Terraform的声明式风格:

data "aws_ami" "latest_target_ami" {
  most_recent = true
  owners      = ["555556666"]

  filter {
    name   = "name"
    values = ["em*"] # 匹配名称以em开头的AMI,可根据实际规则调整
  }

  # 可选:筛选近7天创建的AMI,实现每周更新需求
  filter {
    name   = "creation-date"
    values = ["${formatdate("YYYY-MM-dd", timeadd(timestamp(), "-7d"))}*"]
  }
}

output "latest_ami_id" {
  value = data.aws_ami.latest_target_ami.id
}

output "latest_ami_name" {
  value = data.aws_ami.latest_target_ami.name
}

说明:

  • 用"em*"直接匹配名称符合规则的AMI,替代bash里的文本过滤
  • 可选的creation-date过滤器精准筛选近7天创建的AMI
  • most_recent = true确保获取最新的那个AMI,无需额外排序

内容的提问来源于stack exchange,提问作者MDM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:35:24