Terraform: Apply the value only to first resource

Hello, I’m trying to use a value to the first element, however the value associating with other elements as well.

My resource is aws_vpc_endpoint it has been created with for_each expression, one of attributes is private_dns_enabled which is bool, and it must be applied only to the first element, others must be false

How can I associate the value only to the first element, maybe there is a function or patters.

sqs.tf

... truncated ...

private_dns_enabled = lookup(var.parameters[0].sqs[0], "private_dns", false)

... truncated ...

Hi @unity-unity,
it would be helpful if you could share a code base to test with. I’m wondering why it’s important to only apply it to the first resource. Which is your variable for for_each ?

You might use two different aws_vpc_endpoint resource definitions.

1 Like

When you’re creating 3 different same vpc endpoints in my case is sqs the private_dns_enabled should be applied only once, otherwise it, will gave an error

Error creating VPC Endpoint: InvalidParameter: private-dns-enabled cannot be set because there is already a conflicting DNS domain for sqs.eu-west-1.amazonaws.com in the VPC

Which is your parameter to for_each? Should this be set to a different value or should this one be extended with an if statement instead of mangling around with the private_dns_enbled setting?

1 Like

My for_each

   for_each   = { for id, subnet in local.subnet.public.self : id => subnet if local.target.init.sqs == true }
   depends_on = [ data.aws_vpc_endpoint_service.sqs ]

Locals

   subnet  = {
     public  = {
       ipv4  = lookup(var.parameters[0], "public_ipv4",   [])
       ipv6  = lookup(var.parameters[0], "public_ipv6",   [])
       self  = lookup(var.parameters[0], "public_subnet", [])
     }
   }

   target  = {
     init  = {
       sqs  = lookup(var.init[0], "sqs", "") == true && lookup(var.init[0], "sqs", "") != null
       ecr  = lookup(var.init[0], "ecr", "") == true && lookup(var.init[0], "ecr", "") != null
     }
   }

Where:

public_subnet is a list of strings (3 Subnets in Total)

Now as a workaround I’ve used a following combination:

element(lookup(var.parameters[0].sqs[0], "private_dns", false), each.key)

And determination is:

...
private_dns = [ true, false, false ]
...

Maps have no concept of ordering, so “first” or “last” isn’t a thing. Only lists have an order.

The two ways you could handle this are either an option in the map that should be set to true for only one entry (maybe with validation rules to ensure that), or use a list instead of a map for your local - then create a map from that list, setting the private dns setting to true only for the first entry.

1 Like

I’m wondering if the for_each couldn’t just iterate on the vpc instead of the subnets.

1 Like

Yes, it could, but I need endpoints per each subnet

Thank you, for the idea, unfortunately my knowledge is limited, therefore I’ve posted my question, can you show an example?

IMHO, the primary iterator should be the VPCids and subnets get built. Having such the resource has to be created only once anyway.

1 Like