Search code examples
terraformterraform-provider-aws

Referencing an element while using count in terraform resource and handling the case when count is 0


I have an AWS WAFv2 Web ACL Logging configuration declared like this

resource "aws_wafv2_web_acl_logging_configuration" "logging_configuration" {
  count = var.enable_logging && var.waf_s3_log_bucket_id != "" ? 1 : 0

  log_destination_configs = [aws_kinesis_firehose_delivery_stream.waf_log_stream.*.arn[0]]
  resource_arn            = aws_wafv2_web_acl.waf.arn

  depends_on = [aws_kinesis_firehose_delivery_stream.waf_log_stream]
}

This code works, but the linter gave me a warning to not use the deprecated * notation when referencing an item that is in a list and to use square bracket notation instead. so I changed it

log_destination_configs = [aws_kinesis_firehose_delivery_stream.waf_log_stream[count.index].arn[0]]

When I do terraform plan it now runs, but then gives me this error

Error: Invalid index

aws_kinesis_firehose_delivery_stream.waf_log_stream is tuple with 1 element

count.index is 0

This value does not have any indices.

I understand the error, but there are 2 things that confuse me

  1. If the count is 0, this resource should not even be created. Why would it be flagged by Terraform if that's the case?

  2. If count is not 0, then the error that I'm getting should not exist. Why is Terraform CLI giving me this error?

Can someone tell me what the issue is here and how I can resolve this?


Solution

  • I've been poking around to try to get it working to understand what is happening and made some discoveries.

    TLDR: Solution

    The correct solution to my problem is to change log_destination_configs parameter to log_destination_configs = [aws_kinesis_firehose_delivery_stream.waf_log_stream[count.index].arn]

    Explanation

    Unfortunately, the error message from Terraform was not clear on which index caused the offending error. It wasn't referring to the [count.index] portion, but the arn[0] at the end.

    The issue stemmed from my lack of understanding of the dot notation syntax used to reference instances of objects that use count.

    To understand this better, let's use a more simple example:

    Suppose I have an aws_instance resource using count and I had set count to 2. The first instance of aws_instance would be aws_instance.server[0] and the second instance would be aws_instance.server[1].

    The square bracket makes it really clear that it is trying to access a particular element in the list based on the index number.

    In my case, the "*" represents a list of all elements of that property. You can see this based on Terraform's example in v0.11 documentation.

    So what I got was essentially the entire list of all the firehose delivery streams that the script will generate (which in my case is a max of 1). If this value was any higher, you would see how the second square bracket will be required to reference the exact instance of the firehose delivery stream ARN I am referring to.

    Since I've changed the syntax to use [count.index], the element returned is no longer a list of all the firehose delivery streams but each instance of the firehose delivery stream; In this case, the square bracket next to "arn" would no longer make sense since ARN is a string and not a list.