Terraform创建EC2生成Ansible清单时报字符串模板错误求助
问题排查:Terraform生成Ansible清单时的字符串模板错误
问题场景
通过Terraform创建AWS EC2实例,同时利用null_resource的local-exec生成Ansible清单文件,核心代码及错误如下:
核心代码片段
resource "aws_instance" "myec2instace" { ami = data.aws_ami.ubuntu.id #instance_type = var.instance_type_list[1] instance_type = var.ispto_service_ec2_inst_type["test"] key_name = var.is_pto_service_key_pair vpc_security_group_ids = [aws_security_group.pto-ssh.id] count = 1 tags = { "Name" : "PTO-EC2ins-${count.index}" } } resource "null_resource" "localinventory01" { triggers = { mytest = timestamp() } provisioner "local-exec" { command = "echo ${aws_instance.myec2instace.*.tags.Name} ansible_host=${aws_instance.myec2instace.*.public_ip} ansible_user=ubuntu ansible_ssh_private_key_file=/home/nelbo/Downloads/xxxservice.pem ansible_connection=ssh ansible_port=22 >> inventory" } }
错误信息
terraform validate和terraform plan执行正常,但terraform apply时触发错误:
│ aws_instance.myec2instace is tuple with 1 element │ │ Cannot include the given value in a string template: string required.
问题原因
当使用count = 1时,aws_instance.myec2instace会被Terraform识别为包含1个元素的元组(tuple),而aws_instance.myec2instace.*.tags.Name这种splat表达式返回的同样是元组类型,并非单个字符串。Terraform的字符串模板要求插入值必须是单个字符串,直接将元组代入模板会触发类型不匹配错误。
修复方案
方案1:直接通过索引取值(适合count=1场景)
利用索引[0]提取元组中的唯一元素,将其转为字符串后代入模板:
resource "null_resource" "localinventory01" { triggers = { mytest = timestamp() } provisioner "local-exec" { command = "echo ${aws_instance.myec2instace[0].tags.Name} ansible_host=${aws_instance.myec2instace[0].public_ip} ansible_user=ubuntu ansible_ssh_private_key_file=/home/nelbo/Downloads/xxxservice.pem ansible_connection=ssh ansible_port=22 >> inventory" } }
方案2:遍历生成多行清单(适合count>1场景)
如果后续可能调整实例数量,可通过Terraform的循环语法遍历所有实例,为每个实例生成一行清单内容:
resource "null_resource" "localinventory01" { triggers = { mytest = timestamp() } provisioner "local-exec" { command = <<EOT %{ for inst in aws_instance.myec2instace ~} echo "${inst.tags.Name} ansible_host=${inst.public_ip} ansible_user=ubuntu ansible_ssh_private_key_file=/home/nelbo/Downloads/xxxservice.pem ansible_connection=ssh ansible_port=22" >> inventory %{ endfor ~} EOT } }
内容的提问来源于stack exchange,提问作者NelabhotlaR
相关产品推荐
相关产品推荐

