Stefan
Stefan

Reputation: 1553

Get resources based on a value created using count

I am using Terraform v12.19 with the aws provider v2.34.0. Imagine, I have a resource generated with a count value:

resource "aws_iam_role" "role" {
  count = length(var.somevariable)
  name = var.somevariable[count.index]
}

Later on, I want to reference one specific resource instance in that way, e. g.:

resource "aws_iam_role_policy_attachment" "polatt" {
  role       = aws_iam_role.role["TheRoleNameIWant"].id
  policy_arn = "arn:aws:iam::aws:policy/..."
}

I don't know the index, I can just rely on the name, provided by the variable. Thats because the values of the variable are provided by an external source and the order could change...

Any ideas how to do this?

Upvotes: 0

Views: 2064

Answers (1)

mjgpy3
mjgpy3

Reputation: 8957

You should be able to accomplish this using the index terraform function.

Here's a minimal example using null_resources to test it out

locals {
  role_names = [
    "role-a",
    "role-b",
    "role-c",
    "role-d",
  ]

  target_role_name = "role-c"
}

resource "null_resource" "hi" {
  count = length(local.role_names)
}

output "target_resource" {
  value = null_resource.hi[index(local.role_names, local.target_role_name)].id
}

output "all_resources" {
  value = [for r in null_resource.hi : r.id]
}

This outputs, for example

all_resources = [
  "4350570701002192774",
  "9173388682753384584",
  "1634695740603384613",
  "2098863759573339880",
]
target_resource = 1634695740603384613

So your example, I suppose, would look like

resource "aws_iam_role_policy_attachment" "polatt" {
  role       = aws_iam_role.role[index(var.somevariable, "TheRoleNameIWant")].id
  policy_arn = "arn:aws:iam::aws:policy/..."
}

Update

Your comment below mentions that you actually have a more complicated data structure than just a list of names. I just wanted to mention that you can derive names from your JSON structure.

Assuming you have something like the following

variable "role_values" {
  value = [
    {
      name = "foo",
      other = "details",
      fields = 3
    },
    {
      name = "bar",
      other = "yet more details",
      fields = 3
    }
  ]
}

you could derive just the names by using a local and the newer for loops TF 0.12 offers

locals {
  role_names = [for role in var.role_values: role.name]
}

That way you don't have to store the names twice.

Upvotes: 1

Related Questions