0.7.0-rc4
This would be something related to the core
// 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)}"]
}
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)}
N/A
The list to be accessed and used
An error about it needing to be a flat list
Please list the steps required to reproduce the issue, for example:
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)N/A
https://github.com/hashicorp/terraform/pull/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.
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
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 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?
I am also seeing this issue described in https://github.com/hashicorp/terraform/issues/7906#issuecomment-237266966
We are also seeing this issue 0.7.3 (in the manner described in https://github.com/hashicorp/terraform/issues/7906#issuecomment-237266966) -- could this be reopened to track that issue @phinze ? Or would you prefer a separate tracking issue?
Thank you!
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.
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.)
@apparentlymart 👍 thank you for the clarification, I will open a new issue.
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.
Most helpful comment
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_ipsyields[["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()andlookup()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:
I hope this helps! Let me know if you have any further questions.