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

Show which input values are unknown when for_each fails due to being unknown #26747

Merged
merged 3 commits into from
Oct 29, 2020

Conversation

apparentlymart
Copy link
Contributor

@apparentlymart apparentlymart commented Oct 29, 2020

(This is another installment of "I had a little time to kill and this has been annoying me.")

When writing complex for_each expressions that collect values from various other places in the configuration, the error message about the value being invalid due to being unknown is particularly frustrating because it has historically not given any guidance as to what might be contributing to the value being unknown.

We typically annotate expression evaluation errors with information about the values that might have contributed to them, but we've not been doing that for the for_each expressions because our evaluation codepath was using a sort of "all in one" shortcut method to evaluate the expression and thus didn't have enough information (the hcl.EvalContext, to be specific) to properly annotate the errors.

Questions of the form "why is my for_each not known during plan?" come up pretty often, so I think it's worth some slight additional complexity of hopping down to the layer below so we can get hold of the hcl.EvalContext and improve these error messages, and so that's what this PR does. My focus was on the specific example I've described above, but this actually generalizes to any error message involving an expression making use of unknown values from elsewhere, and may therefore prove useful in some other cases by at least letting the user know what the type of each unknown value is.

While I was in the neighborhood I also noticed that in the case of sensitive values this would potentially disclose that the value is unknown or null, which might (in rare cases) inadvertently indirectly disclose something important in the logs. For that reason, I added an extra check right up front to disable all further presentation for any value that is sensitive. Finally, I realized that we didn't actually have any tests for this formatting codepath (a result of it starting its life as a "shipped prototype", I guess) and so I took this opportunity to write out some basic test cases too, along with verifying the new behaviors I introduced here.

(There's probably some opportunities to do something similar for the corresponding message for unknown count values, but I've run out of time to work on this today and so I'd like to save that for another time; my sense is that for_each expressions tend to be the more complicated ones, while count expressions are often simpler and thus less likely to raise questions about what exactly is unknown in the inputs.)

Our diagnostics model allows for optionally annotating an error or warning
with information about the expression and eval context it was generated
from, which the diagnostic renderer for the UI will then use to give the
user some additional hints about what values may have contributed to the
error.

We previously didn't have those annotations on the results of evaluating
for_each expressions though, because in that case we were using the helper
function to evaluate an expression in one shot and thus we didn't ever
have a reference to the EvalContext in order to include it in the
diagnostic values.

Now, at the expense of having to handle the evaluation at a slightly lower
level of abstraction, we'll annotate all of the for_each error messages
with source expression information. This is valuable because we see users
often confused as to how their complex for_each expressions ended up being
invalid, and hopefully giving some information about what the inputs were
will allow more users to self-solve.
Previously when printing the relevant variables involved in a failed
expression evaluation we would just skip over unknown values entirely.

There are some errors, though, which are _caused by_ a value being
unknown, in which case it's helpful to show which of the inputs to that
expression were known vs. unknown so that the user can limit their further
investigation only to the unknown ones.

While here I also added a special case for sensitive values that overrides
all other display, because we don't know what about a value is sensitive
and so better to give nothing away at the expense of a slightly less
helpful error message.
@codecov
Copy link

codecov bot commented Oct 29, 2020

Codecov Report

Merging #26747 into master will increase coverage by 0.08%.
The diff coverage is 80.00%.

Impacted Files Coverage Δ
lang/eval.go 59.16% <0.00%> (-0.63%) ⬇️
terraform/eval_validate.go 64.58% <0.00%> (ø)
terraform/eval_for_each.go 87.25% <86.88%> (+0.11%) ⬆️
command/format/diagnostic.go 64.39% <100.00%> (+19.77%) ⬆️
terraform/node_module_expand.go 84.41% <100.00%> (ø)
terraform/node_resource_plan.go 95.28% <0.00%> (-1.89%) ⬇️

Copy link
Contributor

@mildwonkey mildwonkey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Copy link
Contributor

@alisdair alisdair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very helpful improvement!

terraform/eval_for_each.go Outdated Show resolved Hide resolved
@apparentlymart apparentlymart merged commit d03a774 into master Oct 29, 2020
@apparentlymart apparentlymart deleted the f-diags-unknown-values branch October 29, 2020 16:07
@ghost
Copy link

ghost commented Nov 29, 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 as resolved and limited conversation to collaborators Nov 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants