Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing Resource's List Attributes #7906

Closed
DustinChaloupka opened this issue Aug 1, 2016 · 9 comments
Closed

Accessing Resource's List Attributes #7906

DustinChaloupka opened this issue Aug 1, 2016 · 9 comments

Comments

@DustinChaloupka
Copy link

DustinChaloupka commented Aug 1, 2016

Terraform Version

0.7.0-rc4

Affected Resource(s)

This would be something related to the core

Terraform Configuration Files

// Really any resource that has a list for an attribute
resource "aws_network_interface" "foo" {
  count = "${var.aws_network_interface_count}"
  subnet_id = "some-subnet-id"
  attachment {
    instance = "a-running-machines-instance-id"
    device_index = 1
  }

  // The attribute wanting to be accessed
  private_ips = ["10.10.1.1"]
}

resource "aws_route53_record" "aws_dns" {
  name = "test.com"

  count = "${var.aws_count}"

  zone_id = "zone-id"
  type = "CNAME"
  records = ["${element(aws_network_interface.foo.*.private_ips, count.index)}"]
}

Debug Output

An error like the following would happen:

Error running plan: 1 error(s) occurred:

* element: element() may only be used with flat lists, this list contains elements of type list in:

${element(aws_network_interface.foo.*.private_ips, count.index)}

Panic Output

N/A

Expected Behavior

The list to be accessed and used

Actual Behavior

An error about it needing to be a flat list

Steps to Reproduce

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

  1. terraform plan when terraform knows that the attribute being accessed is a list (the resource the attribute is in would need to have been created already I think)

Important Factoids

N/A

References

#7834

After some digging I found that the above PR appeared to change what types of elements could be accessed from lists, however, there was no reference in the PR or the changelog about the change in the element() function (or it appears any of the functions that take a list type) only working with flat lists. Was this intended? I tried to do some workarounds, but it appeared that anything that I tried to use that took a type of list did not like the fact that it was not a flat list.

@stack72
Copy link
Contributor

stack72 commented Aug 2, 2016

Hi @DustinChaloupka

Apologies for the error here. I have been able to recreate this, we are currently looking into it now to see what we can do

Please bear with us

Paul

@phinze
Copy link
Contributor

phinze commented Aug 2, 2016

Hey @DustinChaloupka - apologies for the confusion here.

Prior versions of Terraform actually had some quite surprising behavior in this scenario - a splat reference to an attribute of list type would concatenate all the lists in the result.

This happens to work if your list attributes happen to only have one element, but it causes some very unexpected behavior in most other cases.

With 0.7's native list support, the splat reference properly returns a list of lists, so in your example aws_network_interface.foo.*.private_ips yields [["10.10.1.1"]].

The type system within HashiCorp's interpolation language has not yet been enhanced to support functions with multiple possible return types, which is why interpolation functions like element() and lookup() carry with them a limitation that they must return a string.

The new square bracket indexing syntax does not have this limitation, so that's the way you can properly express this scenario in your config:

resource "aws_network_interface" "foo" {
  count = "3"
  subnet_id = "some-subnet-id"
  attachment {
    instance = "a-running-machines-instance-id"
    device_index = 1
  }

  // The attribute wanting to be accessed
  private_ips = ["10.10.1.${count.index+1}"]
}

resource "aws_route53_record" "aws_dns" {
  name = "test.com"

  count = "3"

  zone_id = "zone-id"
  type = "CNAME"
  records = ["${aws_network_interface.foo.*.private_ips[count.index]}"]
}

I hope this helps! Let me know if you have any further questions.

@phinze phinze closed this as completed Aug 2, 2016
@DustinChaloupka
Copy link
Author

@phinze thanks for the help!

That did work under two scenarios, the first being the configuration used as an example on this issue (where the private_ips, in this case, was defined in the resource explicitly). The second scenario that works is when the resource does not explicitly define the list attribute (private_ips in this case) and the resource has already been created.

The scenario that does not work, however, is when the resource has not yet been created and the list attribute has not been explicitly defined:

resource "aws_network_interface" "foo" {
  count = "3"
  subnet_id = "some-subnet-id"
  attachment {
    instance = "a-running-machines-instance-id"
    device_index = 1
  }
}

resource "aws_route53_record" "aws_dns" {
  name = "test.com"

  count = "3"

  zone_id = "zone-id"
  type = "CNAME"
  records = ["${aws_network_interface.foo.*.private_ips[count.index]}"]
}

When doing a terraform plan here an error is presented:

* At column 3, line 1: invalid index operation into non-indexable type: TypeString in:

${aws_network_interface.foo.*.private_ips[count.index]}

I'm going to guess that this is because schema types are not necessarily easily mappable to an ast version or it is not known that that is what it should map to?

@wr0ngway
Copy link

I am also seeing this issue described in #7906 (comment)

@jszwedko
Copy link
Contributor

jszwedko commented Sep 6, 2016

We are also seeing this issue 0.7.3 (in the manner described in #7906 (comment)) -- could this be reopened to track that issue @phinze ? Or would you prefer a separate tracking issue?

Thank you!

@jszwedko
Copy link
Contributor

jszwedko commented Sep 6, 2016

Note that "this isn't currently supported" is fine since it seems like the previous behavior was not explicitly supported (at which point this could be a feature rather than a bug). We have basically the same use case described here (using the outputs of a aws_network_interface to create a aws_route53_record.

@apparentlymart
Copy link
Contributor

I believe what you're seeing here is a bug resulting from how Terraform represents "computed" values -- that is, values that won't be known until something is created -- where internally it's represented as a magic sentinel string value that the index operator then can't index.

I think a separate issue tracking the specific case of indexing computed lists would be a good idea, since this is legitimately a separate concern from what was originally described in this bug (that element was only able to return strings.)

@jszwedko
Copy link
Contributor

jszwedko commented Sep 6, 2016

@apparentlymart 👍 thank you for the clarification, I will open a new issue.

@ghost
Copy link

ghost commented Apr 22, 2020

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.

@ghost ghost locked and limited conversation to collaborators Apr 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants