TF12 - muliple outputs for resources created options with for_each

I’m creating resources with the following for_each format:

  for_each    = var.aws_accounts
  account_id  = each.key
  host_tags   = each.value

The resource creates an additional “external_id” field that.
I’d like to capture the account_id and external_id in such a way that I can write out to SSM or Vault in a single line … like to use account_id in the path & external_id as the value.

The current output I’m using with:

output "dd_aws_full_ids" {
  value = [
    values(..my.resource..)[*].account_id,
    values(..my.resource..)[*].external_id,
  ]
}

generates output like:

Outputs:

external_ids = [
  [
    "account1",
    "account2",
    "account3",
  ],
  [
    "id1",
    "id2",
    "id3",
  ],
]

Is there a way to get these outputs on a single line? Something along the lines of:

Outputs:

external_ids = [
   ["account1", "id1"]
   ["account2", "id2"]
   ["account3", "id3"]
]

thanks!

I think you can get the result you were hoping for here with a for expression:

output "dd_aws_full_ids" {
  value = [
    for r in ..my.resource.. : [r.account_id, r.external_id]
  ]
}

The result won’t be in any particular order (since it’s derived from a map) so it might be worth making that explicit by converting the result to a set to prevent the caller from inadvertently depending on the order:

output "dd_aws_full_ids" {
  value = toset([
    for r in ..my.resource.. : [r.account_id, r.external_id]
  ])
}

Alternatively, it might be more convenient for the caller if it were presented as a mapping from account id to external id:

output "dd_aws_full_ids" {
  value = {
    for r in ..my.resource.. : r.account_id => r.external_id
  }
}

Thanks! That works! It’s all about the syntax… :slight_smile:
The last option you gave generates output like:

dd_aws_full_ids = {
  "<account1>" = "<external_id>"
  "<account2>" = "<external_id>"
}

But how to use that as a value in a depndant resource? Llike if I want to write that value to SSM or Vault. Using aws_ssm_parameter I’m trying things like:

resource "aws_ssm_parameter" "dd_external_id" {
  for acc in datadog_integration_aws.full_integration:

  name     = "/dd_external_ids/${acc.account_id}"
  type     = "String"
  value    = acc.external_id
}

Using content {} block or working with for_each… can’t seem to get the syntax here. Is it possible?

I think this will do what you wanted, if I understood correctly:

resource "aws_ssm_parameter" "dd_external_id" {
  for_each = datadog_integration_aws.full_integration

  name  = "/dd_external_ids/${each.key}"
  type  = "String"
  value = each.value.external_id
}

This is resource for_each.

1 Like

Thanks again! I tried similar with for_each but didn’t get the value right. I used value = each.external_id rather than value = each.value.external_id