-
Notifications
You must be signed in to change notification settings - Fork 94
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
attr: Consider Adding IsNull() and IsUnknown() methods to Value #193
Comments
Another use case is attempting to write a generic state -> plan attribute plan modifier for Computed attributes: type computedValueDoesNotChangeModifier struct {}
func (m computedValueDoesNotChangeModifier) Description(ctx context.Context) string {
return "Value does not change after creation."
}
func (m computedValueDoesNotChangeModifier) MarkdownDescription(ctx context.Context) string {
return m.Description()
}
func (m computedValueDoesNotChangeModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) {
// Do nothing for Create
if req.AttributeState == nil || req.AttributeState.IsNull() {
return
}
resp.AttributePlan = req.AttributeState
} |
I think we talked about this previously, and discarded the idea because it opened the door for inconsistent implementations (i.e., Does a |
What if we recommend the
Likely, since I presume the implementation would be something like the following: func ValueIsNull(ctx context.Context, val attr.Value) (bool, error) {
tfValRaw, err := val.ToTerraformValue(ctx)
return tfValRaw == nil, err
} That implementation does require more gymnastics though since you either have to pass back the error, making it not a simple conditional helper, or as a cursed implementation, swallow the error. How discoverable are these |
I also think that encouraging or requiring custom implementations to explicitly think about null and unknown values, e.g. by introducing these methods, might make for overall less problematic implementations such as those only backed by built-in, non-pointer Go types since a developer would need to 🤔 whether what they are doing might be problematic. I guess I lean towards prioritizing ease of use, since this is likely a common use case, over potential risks with inconsistent custom implementations. |
I'm debating the merits of refining that method's interface to remove the error, and having types panic if there's an error. How can that error be handled, really? What's can be done with it by returning it? Is it a better provider developer experience to panic and see exactly where the error is, rather than returning it and potentially having to trace it back through? Given we're talking about changing Does that change any of the calculus on this?
This is a solid point and I'm inclined to agree, but I think we're due a refactoring of our package hierarchy anyways. There are some odd dependency paths here that just need mapped out so we can figure out what we can safely split out.
I think we're talking about what use is going to suffer, here. On one hand, we can make checking values easier. But doing so makes implementing types correctly more difficult and leaves more opportunities for errors. I don't know that I disagree with you that "making types" is the right place to locate this difficulty--I've definitely sided with that being the more advanced use case and therefore making it responsible for more complexity in the past--I think I'm just 🤔 about whether we need to make either of these harder, or if we can find a solution that is easy to use without making implementations more difficult. I'm suspicious we can, but I do think it would require some (light) refactoring. But yes, ideally these would end up in the |
After #231, the |
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. |
Module version
Use-cases
When writing attribute plan modifiers, it can be necessary to check if the configuration or state
attr.Value
are null or unknown. It feels a little tedious to have to know the underlying value type for comparison and how to properly create the conditional.Attempted Solutions
Proposal
For any
attr.Value
that potentially do not understand null/unknown, they can always return false for both methods. The implementation above then becomes:The text was updated successfully, but these errors were encountered: