I'm beginning by creating a few machines:
resource "aws_instance" "servers" {
count = 20
instance_type = "t2.micro"
...........................
}
and then, I want to create a "master machine", like this:
resource "aws_instance" "master" {
instance_type = "t2.micro"
.................................
user_data = <<-EOF
#!/bin/bash
yum -y install python-pip
mkdir /ansible
cd /ansible
touch inventory
echo "${aws_instance.servers[*].public_ip}" > inventory
echo "server_hostname" >> inventory
pip install ansible
EOF
}
Basically I want the IPs of the machines to be in my Ansible inventory on the master machine. My issue however is that when I try to apply the terraform, I run into this:
aws_instance.servers is tuple with 2 elements
│ Cannot include the given value in a string template: string required.
How can I solve this?
Tried to get a list of the IPs of some EC2 machines in order to have it in a file on a master EC2, via user_data script. However, the issue is that I can't convert it from tuple.
Since you have more than one IP address to include, you will need to explain to Terraform how you want to format those multiple IP addresses into a single string to include into the template result.
For example, you could tell Terraform to produce a space-separated sequence of IP addresses:
resource "aws_instance" "master" {
instance_type = "t2.micro"
.................................
user_data = <<-EOF
#!/bin/bash
yum -y install python-pip
mkdir /ansible
cd /ansible
touch inventory
echo "${join(" ", aws_instance.servers[*].public_ip)}" > inventory
echo "server_hostname" >> inventory
pip install ansible
EOF
}
This example uses the join
function to concatenate the IP addresses together with spaces.
If you need something more specialized and would benefit from writing an entire template block per element then you can alternatively use template directives. For example, if you want to run a separate command for each IP address:
resource "aws_instance" "master" {
instance_type = "t2.micro"
.................................
user_data = <<-EOF
#!/bin/bash
yum -y install python-pip
mkdir /ansible
cd /ansible
touch inventory
%{ for ip in aws_instance.servers[*].public_ip ~}
echo "${ip}" >> inventory
%{ endfor ~}
echo "server_hostname" >> inventory
pip install ansible
EOF
}
(Note that the above will generate a concatenation >>
for even the first IP address, which is different from what you originally shared but I decided to keep it simple since the point of this example is only to show the template for
syntax. Adjust as needed!)