Terraform中如何使用动态变量指定属性引用中的数据源别名
为什么原写法无法生效
Terraform 的资源、数据源属性引用路径是编译期静态解析的,不支持在路径片段位置插入变量做动态拼接,data.aws_ami.${var.os_name}.image_id 这类写法不符合HCL语法规范,无法通过配置校验。
适配需求的实现方案
方案1:基于现有count逻辑做列表拼接取值
你目前已经给每个OS对应的AMI数据源加了按os_name判断的count规则(匹配目标OS时count=1,否则count=0),可以沿用现有结构,把所有数据源的返回结果汇总为列表后取值,不需要改动原有数据源逻辑。
以你写的suse数据源为例,其他操作系统(ubuntu、centos等)的数据源都按照相同的count判断逻辑编写:
# suse数据源,沿用原有配置 data "aws_ami" "suse" { count = var.os_name == "suse" ? 1 : 0 owners = ["amazon"] most_recent = true filter { name = "name" values = ["suse-sles-${var.os_version}-sp*-v????????-hvm-ssd-x86_64"] } } # ubuntu数据源示例 data "aws_ami" "ubuntu" { count = var.os_name == "ubuntu" ? 1 : 0 owners = ["amazon"] most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-${var.os_version}-*-amd64-server-*"] } }
在EC2实例资源中取AMI值时,把所有数据源的返回结果拼接成长度为1的列表,取首个元素即可:
resource "aws_instance" "workerNode" { # 其他实例配置项... ami = concat( length(data.aws_ami.ubuntu) > 0 ? data.aws_ami.ubuntu[*].image_id : [], length(data.aws_ami.suse) > 0 ? data.aws_ami.suse[*].image_id : [], # 其他操作系统的数据源结果按相同规则追加 )[0] # 其他实例配置项... }
方案2:通过本地值做静态映射
如果不想编写大段concat逻辑,可以用本地值(local)提前建立os_name和对应AMI ID的关联关系,运行时根据变量值匹配取值,写法更简洁。
首先定义本地映射规则,每个映射项增加空列表判断,避免索引越界错误:
locals { os_ami_map = { ubuntu = length(data.aws_ami.ubuntu) > 0 ? data.aws_ami.ubuntu[0].image_id : null suse = length(data.aws_ami.suse) > 0 ? data.aws_ami.suse[0].image_id : null centos = length(data.aws_ami.centos) > 0 ? data.aws_ami.centos[0].image_id : null debian = length(data.aws_ami.debian) > 0 ? data.aws_ami.debian[0].image_id : null } }
在EC2实例资源中取AMI值时,直接按变量索引本地映射即可:
resource "aws_instance" "workerNode" { # 其他实例配置项... ami = local.os_ami_map[var.os_name] # 其他实例配置项... }
注意:只有和当前os_name匹配的数据源会被设置count=1,对应映射项会返回真实的AMI ID,其余不匹配的数据源映射项值为null,不会触发配置错误。
内容的提问来源于stack exchange,提问作者arif
相关产品推荐
相关产品推荐

