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
for_each and splat #22476
for_each and splat #22476
Comments
Hi @omeid! As you've figured out here, a resource with You didn't show the source code for |
Hello @teamterraform
This is somewhat unexpected, they should work.
Yes. It is pretty much a standard
I believe it is not directly related and the issue happens on the master still. |
update, I was not able to reproduce the same problem using a minimal version, and the problem went away once I recreated the subnets. I suppose the problem may be related to moving from |
While I am unable to create a small code to reproduce this, it is happening on a large deployment randomly. Run |
Still unable to replicate this, what is even bizarre is that changing unrelated resources makes the error go away. |
Randomly sounds a lot like #22407 -- this will go out in the next release of Terraform (which is soon). Does the randomness happen on master? Or we leave this open until 0.12.7 is out, and then validate that it's not happening anymore. |
Okay, I figured out, the error happens when |
That is NOT the only way this happens! I'm getting this when using a plain simple module that has nothing but subnets. No transitioning from something else, no |
I am hitting this same issue when I am trying to get output
|
Hi all! Just wanted to clarify that it is by design that the splat operators don't work with maps. Splat operators are for lists only, as described in the documentation. Note in particular the paragraph describing their other "useful effect":
So, the reason applying Aside from that special behavior (which isn't useful when using value = { for k, v in aws_eip.this : k => v.id } or, if you want the result to be a list (in lexical order by the keys, discarding the keys themselves): value = [for v in aws_eip.this : v.id] or, if you want the result to be a set of strings, reflecting that the ids are not ordered and more convenient to use with value = toset([for v in aws_eip.this : v.id]) As mentioned above, we cannot and do not intend to change this behavior to make splat expressions work with maps because that is incompatible with existing configurations. Based on the comments so far it's not clear to us whether everyone is just reporting that splat expressions don't work with |
Thanks for the explanation. What is the expected way to access a list of property from a resource created using
Edit: I suppose I could also do this: |
@joshuaspence thanks |
@teamterraform thanks for the explanation! An explicit hint about maps in the documentation would be a big help here, to counteract the strong visual intuition that Splat expressions are not directly applicable to maps (including
or use an equivalent for expression
Incidentally, is If yes, then the equivalent for expression above could instead be
which is shorter, though also potentially even more counterintuitive since that's literally the same equivalent for expression you would get from |
Thank you for the suggestions @dmrzzz, I've looked in the docs and found we have docs regarding for_each and splat in https://www.terraform.io/docs/configuration/expressions.html#splat-expressions, but I've added one to https://www.terraform.io/docs/configuration/expressions.html#references-to-resource-attributes as well. As to your question about I'd also note that this is valid in the same way that if you wanted to use the index values of a list, you could use I'm closing this issue as we've clarified that the splat operator with |
I understand that the documentation is correct, but is there any reason to not change the language so that the splat operator can be used with maps or introducing an equivalent syntax for maps? |
@pselle thanks for the doc updates, and sorry I didn't see the very useful "Splat expressions are for lists only..." that you had already added in 67e314d prior to my earlier comment; my browser must still have had the old page cached. Regarding If only one temporary variable is provided for an object or map source ( |
@joshuaspence We can consider this for future language design, around the issue of "I want all map'd instances", but personal opinion is splat is not a great fit for this without guards, as it is ambiguous as to if you will get the values or keys of a map (since both may be meaningful data, whereas indicies less so). "Get all the instances" for resources represented by a map returns two values, the keys and the values, and so using @dmrzzz Thanks for the suggestion! I'll ponder this a little more, because I want to make sure we're providing useful data in the docs/not handing people lines that might confuse them ("why do I need the index?"). I might also float this up to our documentation lead to see if he has some more suggestions on clarifying |
@pselle While it is true that both the key and value of a map has meaning, generally the key is a meaningful-reference (opposite to merely sequential reference in case of lists) and the value is well, the value. So treating Of course, if someone wants the keys, they can always still do that with |
As we noted in the longer comment above, the splat operator in its current form cannot be changed to work directly with maps because the splat operator already has a defined meaning for working with non-list/non-set values: it wraps the value in a single-element list, or produces an empty list if the value is null. Existing configurations are relying on this behavior because in Terraform 0.11 it was somewhat common to use the For the foreseeable future, [ for v in aws_instance.example : v.id ] Since it's likely that when { for k, v in aws_instance.example : k => v.id } Since all three of these results would be reasonable things to compute in different situations, we think it's important that it's clear to a reader which of these forms is the result of a particular expression. The Terraform language generally prioritizes being explicit over being terse. |
Thanks for the explanation @apparentlymart. I think it is worth documenting the backwards compatibility issue to help users understand the rationale for the somewhat surprising behaviour. |
I'm going to lock this issue because it has been closed for 30 days 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. |
Using for_each with a map in resources results in a weird behaviour:
Input:
Output:
Using
values(aws_eip.this).*.id
works withaws_eip
, however, withaws_subnet
, I get the following:Output:
Happens on terraform 0.12.6 as well as master.
The text was updated successfully, but these errors were encountered: