-
Notifications
You must be signed in to change notification settings - Fork 92
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
AttributePlanModifier for default value #285
Comments
Moreover there is another problem appeared regarding default values complexity after 88f0847. The default value of the "complex" attributes (e.g. lists, maps etc) cannot be just an empty list/map but the element type should be define too. To explain better, previously the default value could be something like So the way to overcome that problem, is to define more complicated default values which define their element types too:
|
It seems adding a default plan modifier like proposed above seems extends the scope of plan modifier to non-computed attributes? terraform-plugin-framework/tfsdk/attribute.go Line 101 in 52f814f
|
How so? You would still need to have |
@tmccombs In SDK v2, setting a default value for optional and non-computed attribute is allowed. It is weired to mark an optional attribute as computed only for being able to use the default plan modifier, which also breaks the assumption for O+C attributes, i.e. if it is unset, keeps using whatever value set remotely (but now it will always use the default value). |
@tmccombs BTW, should the check above be modified to, as otherwise, it will always be resolved to if val.IsKnown() && !val.IsNull() {
return
} |
But the framework doesn't have a native way to set a default value. And iirc that has been discussed on a couple of other issues. The current recommendation is to use a plan modifier to set a default value, this issue is just about making it easier to do that by providing a plan modifier implementation for setting a default value, so that every provider doesn't have to re-invent the wheel.
I'm unfamiliar with that assumption. But if that assukmption is something that should be upheld, then maybe having native support for default values in the framework should be revisited.
|
Drive-by note: Just to provide some context here, the framework should/will supply some standard plan modifiers that can handle at least primitive type default values. It'll be helpful for the maintainers to understand use cases, because as mentioned above, sometimes choosing a desired behavior may require choosing a separate implementation:
terraform-plugin-sdk was allowed to do things that are not allowed in other provider implementations and also performed some very opinionated plan logic. There is no longer forced opinions based on Computed-ness. Computed should always be required for any framework or provider-defined default value implementation outside the old SDK, since it signals to Terraform that a value not in a configuration may come from the provider. There may be consideration in #31 to just always set Computed with Optional, to simplify provider implementations. |
Just implemented this thing myself, really unintuitive to not have a default value modifier in the framework, since its implementation is so generic. Looking forward to see more modifiers 👍 |
It seems the following simple code is enough with v0.10.0. It's just for note. I'm really welcome to see the official version 👍 package modifier
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
)
// DefaultAttributePlanModifier is to set default value for an attribute
// https://github.com/hashicorp/terraform-plugin-framework/issues/285
type DefaultAttributePlanModifier struct {
value attr.Value
}
func DefaultAttribute(value attr.Value) DefaultAttributePlanModifier {
return DefaultAttributePlanModifier{value: value}
}
func (m DefaultAttributePlanModifier) Modify(
ctx context.Context,
req tfsdk.ModifyAttributePlanRequest,
resp *tfsdk.ModifyAttributePlanResponse,
) {
if req.AttributeConfig == nil || resp.AttributePlan == nil {
return
}
// if configuration was provided, then don't use the default
if !req.AttributeConfig.IsNull() {
return
}
// If the plan is known and not null (for example due to another plan modifier),
// don't set the default value
if !resp.AttributePlan.IsUnknown() && !resp.AttributePlan.IsNull() {
return
}
resp.AttributePlan = m.value
}
func (m DefaultAttributePlanModifier) Description(ctx context.Context) string {
return "Use a static default value for an attribute"
}
func (m DefaultAttributePlanModifier) MarkdownDescription(ctx context.Context) string {
return m.Description(ctx)
} And usage is // ...
"kind": {
Optional: true,
Computed: true,
Type: types.StringType,
PlanModifiers: tfsdk.AttributePlanModifiers{
modifier.DefaultAttribute(types.String{Value: "foo"}),
},
}, Note that the terraform-provider-scaffolding-framework use |
FWIW I looked into all the scenarios a field generally behaves like and implemented modifiers for them at https://github.com/terraform-community-providers/terraform-plugin-framework-utils#modifiers.
Turns out that we don't need anything else other than A test provider is implemented at https://github.com/terraform-community-providers/terraform-plugin-framework-utils/tree/master/test/terraform-provider-test along with tests at https://github.com/terraform-community-providers/terraform-plugin-framework-utils/tree/master/test/infra-test/specs. I am also going to use this in https://github.com/terraform-community-providers/terraform-provider-linear. |
This should be covered by #668 which will release with terraform-plugin-framework version 1.2.0 🔜 . If there are further bug reports, feature requests, or documentation suggestions with resource default value handling, please raise 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. |
Module version
Use-cases
It is pretty common use case to have a default value for an attribute. It seems the way to do that in the plugin framework is to define a AttributePlanModifier. However, doing so requires quite a bit of boilerplate, and it probably makes sense to include this in the pre-defined modifiers included in the framework.
Note that this is limited to a static default known at the time of creating the schema, not something that computes a default from the current plan or something like that.
Attempted Solutions
User's can define their own modifies to do this, but doing so requires quite a bit of boilerplate for a very common requirement.
Proposal
Include a
AttributePlanModifier
to support adding a default value. Something like:References
Additional notes.
It's a little unfortunate, that there doesn't seem to be a public interface to convert an
interface{}
to anattr.Value
, like the inverse ofValueAs
, so that the default value has to be anattr.Value
instead of a native go value. At least I couldn't find such an interface.I also don't love that I have to define
Description
andMarkdownDescription
methods even if it is just an internal provider. I'm not even really sure how those are used for validators and plan modifiers.Edit:
Updated code to be more correct.
The text was updated successfully, but these errors were encountered: