How to Output an Object

Hi there,

I’m going nuts trying to do what I think is a simple thing.
I am creating two VMs. I would like to output an object that contains two maps or sets containing the name and IP of each VM.

This is what I have to try and accomplish this:

output "vms_and_ips" {
  value = tomap({
    "name" = google_compute_instance_from_template.firewall.*.name
    "ip"   = google_compute_instance_from_template.firewall.*.network_interface.0.access_config.0.nat_ip
  })
}

This is how I am trying to access this output:

%{for vm in module.firewall.vms_and_ips}
tf_${vm.name}_management_untrusted_ip: ${vm.ip}
%{endfor}

However, this does not work, and I do not understand why. Where am I going wrong?

Thanks

Hi @DapperDeer

I can only suggest that you use the Terraform console to “navigate” and test the outputs, it’s a great way to accomplish complex variable access.

For example, I have a module that creates EC2 instances and returns the ids.

In terraform console I can understand the module output and test different expressions:

> module.aws_ec2_pro_pub_web_01.id
[
  [
    "i-09eeb888936e8961c",
  ],
]
> module.aws_ec2_pro_pub_web_01.id[0]
[
  "i-09eeb888936e8961c",
]
> module.aws_ec2_pro_pub_web_01.id[0][0]
"i-09eeb888936e8961c"

Hi @DapperDeer,

To give a more direct result it would be helpful to see exactly what error message Terraform returned here.

However, one error I notice in your template is that you’re repeating over module.firewall.vms_and_ips, which is a map from string to list and therefore vm in each case will be one of those lists, not an object you can access .name or .ip on.

I assume you’re trying to build a map where each element is one of the instances of google_compute_instance_from_template.firewall, but in order to do that you’d need to decide on a scheme for assigning each one a unique map key.

If you can say a little more about what your ultimate goal is then I’d be happy to try to give a more complete suggestion on how to address it.

Hi there!

Thanks for your response and sorry for such a long delay. Been dealing with a surgery, but all is well.

At the moment, my ultimate goal will be to create Palo Alto firewalls in Terraform, output any required variables (such as the external, management, and internal IPs) in a file that I can then access from my Ansible script to configure the firewalls.

In regards to the error you noticed, I’ve tried without the tomap() function as that seemed most likely to output what I wanted, but that never worked either. Could a “unique map key” be as simple as the name of each firewall instance?

Thanks

EDIT:

I was finally able to get it thanks to this StackOverflow answer.

I am curious though, is zipmap the optimal way to do this?

For reference:

output "vms_and_ips" {
  value = "${zipmap(google_compute_instance_from_template.firewall.*.name,google_compute_instance_from_template.firewall.*.network_interface.0.access_config.0.nat_ip)}"
}

%{for name, ip in module.firewall.vms_and_ips}
tf_${name}_management_untrusted_ip: ${ip}
%{endfor}