Terraform: Accessing attributes from resources with count = 0 errors out since version 0.11

Created on 7 Nov 2017  ยท  5Comments  ยท  Source: hashicorp/terraform

Hi,

consider a configuration where specific resources should only be applied for specific environments. This is accomplished by conditionally set the count argument of a resource to 0 or 1 respectively:

resource "aws_s3_bucket" "b" {
  count = "${terraform.workspace == "production" ? 0 : 1}"
  bucket = "my-tf-test-bucket"
  acl    = "private"

  tags {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

Since terraform 0.11, testing on a resource with count = 0 errors out with Resource 'aws_s3_bucket.b' not found for variable 'aws_s3_bucket.b.bucket'

Is this the expected behavior? From my point of view, the resource should exist and a test on the resources count attribute should be possible.

Terraform Version

Terraform v0.11.0-dev

Terraform Configuration Files

resource "aws_s3_bucket" "b" {
  count = 0
  bucket = "my-tf-test-bucket"
  acl    = "private"

  tags {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

output "testbucket" {
  value = "${aws_s3_bucket.b.count > 0 ? aws_s3_bucket.b.bucket : ""}"
}

Expected Behavior

Output testbucket should be empty string w/o error

Actual Behavior

Plan reports the following error:

* output.testbucket: Resource 'aws_s3_bucket.b' not found for variable 'aws_s3_bucket.b.bucket'

Steps to Reproduce

Please list the full steps required to reproduce the issue, for example:

  1. terraform plan
bug config

Most helpful comment

Hi @janschumann! Sorry for this annoying behavior.

I'm surprised to hear that this behavior feels new on 0.11.0 since it's actually a known bug that has existed ever since the conditional expression was implemented, due to some limitations of the interpolation language. (See hashicorp/hil#50 for more details.)

The common workaround today is to exploit the fact that the "splat syntax" can return an empty list when count = 0 and handle this via list operations:

output "testbucket" {
  value = "${element(concat(aws_s3_bucket.b.*.bucket, list("")), 0)}"
}

The additional single-item list here is to ensure that there's always at least one item in this list so that element will work.

The plan is to address this as part of implementing the new version of HCL which incorporates the HIL (interpolation language) functionality while addressing many of the limitations of HIL's type system and evaluator that lead to issues like this. We'll have an opt-in preview version of this soon to gather feedback and find bugs before making Terraform use it by default.

All 5 comments

Hi @janschumann! Sorry for this annoying behavior.

I'm surprised to hear that this behavior feels new on 0.11.0 since it's actually a known bug that has existed ever since the conditional expression was implemented, due to some limitations of the interpolation language. (See hashicorp/hil#50 for more details.)

The common workaround today is to exploit the fact that the "splat syntax" can return an empty list when count = 0 and handle this via list operations:

output "testbucket" {
  value = "${element(concat(aws_s3_bucket.b.*.bucket, list("")), 0)}"
}

The additional single-item list here is to ensure that there's always at least one item in this list so that element will work.

The plan is to address this as part of implementing the new version of HCL which incorporates the HIL (interpolation language) functionality while addressing many of the limitations of HIL's type system and evaluator that lead to issues like this. We'll have an opt-in preview version of this soon to gather feedback and find bugs before making Terraform use it by default.

Thanks @apparentlymart. Sorry for bringing this up again! I never came across this, as I in my case everything worked correctly < 0.11! Thanks for the workaround. I will close this issue.

If you use list() rather than list("") you will get an empty list rather than a list with an empty string. This is useful for an example like this: -

output "static_ip_addresses" {
  value = "${concat(azurerm_public_ip.static.*.ip_address, list())}"
}

You will get output like this: static_ip_addresses = [].

If you use list("") you will get output like this:

static_ip_addresses = [

]

Or like this: -

static_ip_addresses = [
    8.8.8.8,
    4.4.4.4,

]

This is still an issue in 0.12.18. It would be best if contact just always returns [] regardless of its argument.

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

darron picture darron  ยท  3Comments

rjinski picture rjinski  ยท  3Comments

larstobi picture larstobi  ยท  3Comments

shanmugakarna picture shanmugakarna  ยท  3Comments

franklinwise picture franklinwise  ยท  3Comments