This object does not have an attribute named "network_interface_ids"

Hello, I’ve created an Endpoint, and I would like to add a tag to created ENI device
The Endpoint have been created with for_each block (if it is important)
However I get an error:
Error: Unsupported attribute

  on Modules/Network/Endpoints/tags.tf line 14, in resource "aws_ec2_tag" "def_eni_sqs":
  14:    resource_id                     = flatten(aws_vpc_endpoint.sqs.*.network_interface_ids)

This object does not have an attribute named "network_interface_ids".

Here is the Endpoint and Tag resources

resource "aws_vpc_endpoint" "sqs"      {
   for_each                        = { for subnet in local.endpoints.sqs : subnet.name => subnet }
   depends_on                      = [ data.aws_vpc_endpoint_service.sqs ]
 
   vpc_id                          = var.network_ids
   auto_accept                     = var.endpoint_sqs_auto_accept
   service_name                    = data.aws_vpc_endpoint_service.sqs[0].service_name
   vpc_endpoint_type               = "Interface"
   
   policy                          = data.template_file.policy_sqs.rendered
   subnet_ids                      = lookup(each.value, "subnet",  null)
   security_group_ids              = lookup(each.value, "groups",  null)
   private_dns_enabled             = lookup(each.value, "prefix",  null)

   tags = var.tags
}


resource "aws_ec2_tag" "def_eni_sqs" {
   # ^ Default Tags: Unmanaged Interfaces (SQS ENI)
   count                           = length(data.aws_availability_zones.network_zones.names)
   resource_id                     = flatten(aws_vpc_endpoint.sqs.*.network_interface_ids)
   key                             = "Name"
   value                           = join(" | ", [ local.tag_sqs_enis, upper(element(var.availability_zones, count.index)) ])
}

Hi @unity-unity,
it would be easier to replay if all code could be shared.
Anyway, I think the definition of resource_id is a single item which should be referenced using e.g. element(flatten(...),count.index)

1 Like

Hello, @tbugfinder

I’ve found a solution/workaround however I faced a new issue.
Here is my code, for sqs endpoint:

resource "aws_vpc_endpoint" "sqs_private"      {
   count               = length(data.aws_vpc_endpoint_service.sqs) > 0 && var.create_endpoint_sqs ? 1 : 0
   depends_on          = [ data.aws_vpc_endpoint_service.sqs ]
 
   vpc_id              = var.network_ids
   auto_accept         = var.endpoint_sqs_auto_accept
   service_name        = data.aws_vpc_endpoint_service.sqs[0].service_name
   vpc_endpoint_type   = "Interface"
   
   policy              = data.template_file.policy_sqs.rendered
   subnet_ids          = var.private_subnet_ids
   security_group_ids  = local.security.groups
   private_dns_enabled = var.endpoint_sqs_private_dns

   tags = var.tags
}

However, I found that I can tag a network interface, through only the aws_ec2_tag
And here comes a new issue, not an issue but logical mistake

nInNx

As you can see when I’m tagging a network interface to it’s availability zone, it is tagging but tagging wrongly, can you help me to resolve this logic?

Here is the code of aws_ec2_tag

resource "aws_ec2_tag" "def_eni_sqs_private"     {
   count         = length(data.aws_vpc_endpoint_service.sqs) > 0 && var.create_endpoint_sqs ? length(var.availability_zones) : 0
   depends_on    = [ aws_vpc_endpoint.sqs_private ] 
   resource_id   = element(flatten([for interface in aws_vpc_endpoint.sqs_private: interface.network_interface_ids]), count.index)
   key           = "Name"
   value         = join(" | ", [ local.tag_sqs_private_enis, upper(element(var.availability_zones, count.index)) ])
}

IMHO, this is too much - the key here is that count.index is being used compared to the initial post.

On the other hand I’m wondering about what you’re trying to do with the AZ tag finally as there are two resources (aws_vpc_endpoint and was_ec2_tag) managing the same tags.

1 Like

@tbugfinder

Thank you, for your response!

Basically when the sqs endpoint creates, it is also creates a network interface(s), per subnets, in my case there are 3 subnets for each AZ, so I’m trying to tag them, through aws_ec2_tag (There no other option to tag the network interface created by sqs)

I meant what’s the benefit of this tag as it’s a property of the ENI itself, which action or decision will be made of it?

The order of the elements processed within resource aws_ec2_tag isn’t based on the order of var.availability_zones, so those might not match. So the question would be how to get the availability zone of those ENIs as an input instead of using var.availability_zones.

Starting off with the result list of https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/network_interfaces the property availability_zone is available.

Another option might be using a lambda function and tag those ENIs periodically or based on the create event.

1 Like

@tbugfinder

Again, thank you very much for your clue!
For question why we need those tags: - Our policy does not allows resources without tags, everything must be tagged either manually either auto.

I’ve completely forgot about, data statements
With https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/network_interfaces I do not need any more aws_ec2_tag, I can tag inside of data itself.

I’m just wondering why the AZ should be part of the tag values as it is difficult to access and seems to be redundant. I haven’t looked into it specifically however does a VPC endpoint definition propagate tags also to those ENIs?
Would it make sense to tag the ENIs maybe with the VPC endpoint name/ID instead of the AZ?

Data sources only read resource properties, those do not change these.

Yes, for sure it later will be tagged with Endpoint names like:
sqs-endpoint-private-eu-west-1a-unmanaged
sqs-endpoint-private-eu-west-1b-unmanaged
sqs-endpoint-private-eu-west-1c-unmanaged


But as I mentioned before, no issue with endpoints no issue with tags of endpoints, only issue is when the ENI creates a tags it is not mapping to appropriate AZ.

Like in picture above:
sqs-endpoint-private-eu-west-1a-unmanaged — eu-west-1c
sqs-endpoint-private-eu-west-1b-unmanaged — eu-west-1a
sqs-endpoint-private-eu-west-1c-unmanaged — eu-west-1b

As I feel not well understood, I try it again :slight_smile:
Please note - this is pseudo, not tested code but it should show what I’m thinking off.
Basically query the details of each network interface created within the VPC endpoint using a data source and then use this data source and the details within the aws_ec2_tag resource.

It would be easier if you could share a ready to use repo and apply changes there.


data "aws_network_interface" "sqs" {
  count = length(aws_vpc_endpoint.sqs_private[0].network_interface_ids)
  id = aws_vpc_endpoint.sqs_private[0].network_interface_ids[count.index]
}

resource "aws_ec2_tag" "def_eni_sqs_private"     {
   count         = length(data.aws_vpc_endpoint_service.sqs) > 0 && var.create_endpoint_sqs ? length(var.availability_zones) : 0
#   depends_on    = [ aws_vpc_endpoint.sqs_private ]
   ##resource_id   = element(flatten([for interface in aws_vpc_endpoint.sqs_private: interface.network_interface_ids]), count.index)
   resource_id   = data.aws_network_interface.sqs[count.index].id
   key           = "Name"
   ##value         = join(" | ", [ local.tag_sqs_private_enis, upper(element(var.availability_zones, count.index)) ])
   value         = join(" | ", [ local.tag_sqs_private_enis, upper(data.aws_network_interface.sqs[count.index].availability_zone) ])
}

1 Like

@tbugfinder

It worked actually as expected, thank you very much

Solved thanks to @tbugfinder