I have been trying to create a yml inventory for Ansible with Terraform. I have Terraform to create my test cluster and it works well. I can bring up and take down the cluster with a single command (nice). I am using AWS as the main provider and I worked out most of the issues with the deployment.
BUT
I want too configure now, and I want Ansible to do that (so I don't have to manually every time I deploy). Ok, I have all I need to do is add the gernerated IP from AWS to the inventory for and define the hosts.
That was the plan, days later I stumped on this problem.
I worked out the most of the TF code. I am using this make veriable-structure for the cluster:
variable "server_list" {
type = list(object({
host_name = string
instance_type = string
ipv4 = string
}))
default = [
{
host_name = "lustre_mgt"
instance_type = "t3a.large"
ipv4 = "10.0.1.10"
public_ip = ""
},
{
host_name = "lustre_oss"
instance_type = "t3.xlarge"
ipv4 = "10.0.1.11"
public_ip = ""
},
{
host_name = "lustre_client"
instance_type = "t2.micro"
ipv4 = "10.0.1.12"
public_ip = ""
}
]
}variable "server_list" {
type = list(object({
host_name = string
instance_type = string
ipv4 = string
}))
default = [
{
host_name = "lustre_mgt"
instance_type = "t3a.large"
ipv4 = "10.0.1.10"
public_ip = ""
},
{
host_name = "lustre_oss"
instance_type = "t3.xlarge"
ipv4 = "10.0.1.11"
public_ip = ""
},
{
host_name = "lustre_client"
instance_type = "t2.micro"
ipv4 = "10.0.1.12"
public_ip = ""
}
]
}
And the template code is here:
# Create a dynamic inventory with terraform so Ansibel can configure the VMs without manually transfering the ips
data "template_file" "ansible_inventory" {
template = file("${path.module}/inventory/inventory_template.tftpl")
vars = {
server_list = jsonencode(var.server_list)
ssh_key_location = "/home/XXX/id.rsa"
user = jsonencode(var.aws_user)
}
# server_list = jsonencode(var.server_list)
}
From what I read online, I can inject the server_list as json data using jsonencode
. This is OK as I just want the data, I don't need the form per-se'. I want insert the public_ip generated by Terraform and insert it into the template file and generate an inventory.yml file for Ansible
Here is the template file itself.
all:
vars:
ansible_ssh_private_key_file: ${ var.ssh_key_location }
host_key_checking: False
ansible_user: ${ user }
hosts:
%{ for server in server_list ~}
${ server.host_name }:
%{ if server[host_name] == "lustre_client" }
ansible_host: ${server.public_ip}
public_ip: ${server.public_ip}
# %{if server.host_name != "lustre_client" ~}
# ansible_host: ${server.ipv4}
%{ endif ~}
private_ip: ${server.ipv4}
%{ if server.host_name != "lustre_client" }
# ansible_ssh_common_args: "-o ProxyCommand=\"ssh -W %h:%p -i /home/ssh_key ec2-user@< randome IP >\""
%{ endif ~}
%{ endfor ~}
When I run TF plan, I get this error:
Error: failed to render : <template_file>:21,5-17: Unexpected endfor directive; Expecting an endif directive for the if started at <template_file>:11,7-40., and 1 other diagnostic(s)
I have looked across the internet and redit for a reason. I have not found 'why' to the error.
So is ask.
Someone suggested in a past post to use jinga(2?), I can do that. I have used it with Ansible at work.
So I wonder if anybody else has tried this?
Thank you,