Search code examples
terraformopenstack

Map value in module with for-each to output


I have a module that creates multiple resources for a list of names. So for each name supplied in a variable called instances, a set of resources (vm, ports, volumes) is created.
In the output of that module I want to have a map, that maps the instance (each value in instances) to the IP of an associated port.

This is the definition of the port

resource "openstack_networking_port_v2" "this" {
  for_each = var.instances

  name               = "port-${each.key}"
  network_id         = var.network_id
  admin_state_up     = true
  security_group_ids = var.security_group_ids
  fixed_ip {
    subnet_id = var.subnet_id
  }
}

Until now, I had this in the output of the module

output "int-port" {
  value     = openstack_networking_port_v2.this
}

and this where I used it

int-ip : module.my-instance.int-port["${var.deployment}-my-01"].all_fixed_ips[0]

After upgrading terraform, I need to add sensitive = true to the output, as the openstack provider has marked something as sensitive, which will lead to the output not being printed. (I know I can get it with terraform output -json)
So I want to just return the IPs I need in the output instead of the whole object, but I can't figure out how.

I tried the following things:

output "int-ip" {
  value = openstack_networking_port_v2.this.*.all_fixed_ips[0]
}

and

output "int-ip" {
  value = openstack_networking_port_v2.this[*].all_fixed_ips[0]
}

which gives me

│ Error: Unsupported attribute
│
│   on ../../modules/ext-instance-v2/outputs.tf line 24, in output "int-port":
│   24:   value = openstack_networking_port_v2.this.*.all_fixed_ips[0]
│
│ This object does not have an attribute named "all_fixed_ips".

I also tried

output "int-ip" {
  value = {
    for instance in var.instances:
    instance => openstack_networking_port_v2.this["${instance}"].all_fixed_ips[0]
  }
}

and

output "int-ip" {
  value = {
    for instance in var.instances:
    instance => openstack_networking_port_v2.this[instance].all_fixed_ips[0]
  }
}

which leads to that error

│ Error: Invalid index
│ 
│   on ../../modules/ext-instance-v2/outputs.tf line 19, in output "int-ip":
│   19:     instance => openstack_networking_port_v2.this["${instance}"].all_fixed_ips[0]
│     ├────────────────
│     │ openstack_networking_port_v2.this is object with 9 attributes
│ 
│ The given key does not identify an element in this collection value.

It feels like I'm very close, but just out of reach.
I'm not only interested in the solution, but also in an explanation why the things I tried, did not work out.


Solution

  • Since your openstack_networking_port_v2.this is map due to for_each, it should be:

    output "int-ip" {
      value = values(openstack_networking_port_v2.this)[*].all_fixed_ips[0]
    }
    

    Update

    Based on the comments. The correct way is for the last attempt is:

    output "int-ip" {
      value = {
        for instance in keys(var.instances):
          instance => openstack_networking_port_v2.this[instance].all_fixed_ips[0]
      }
    }
    

    This is required, as instances is a map, but you need a list. In this case, you want to use the list of keys in the for-each.