Open pksunkara opened 1 year ago
@bflad I would really appreciate it if I can get any pointers here.
We've been playing with Default: objectdefault.StaticValue(..)
on the schema.SingleNestedAttribute
to achieve this. Would be interested to hear your experience with this as for us I'm hearing there are cases where this default overrides the declared values in the nested object
Hi folks 👋 Sorry for the delayed response here.
The behavior of schema-based Default
value handling occurs when the "object layer" containing the attribute is known (not null or unknown). All root attributes are automatically invoked, however when nested attributes and blocks come into play, it is important to note that behavior versus your desired implementation when a higher "layer" may be null in a configuration. If setting default values in an underlying attribute within a single nested attribute (object) when that object is null is desired, then the single nested attribute itself must declare a default (potentially in addition to having a default on the underlying attribute for when the single nested attribute is not null, but the underlying attribute is still null). The reason for this is because it leaves the choice up to provider developers when they may or may not want objects instantiated, since that behavior is not always desirable.
To summarize this particular case with a single nested attribute with one underlying attribute:
Default on Single Nested Attribute | Default on Underlying Attribute | Configuration | Framework Behavior |
---|---|---|---|
No | No | Null single nested attribute | Passthrough (null single nested attribute and implicitly null underlying attribute) |
No | No | Known single nested attribute, but null underlying attribute | Passthrough (known single nested attribute, but null underlying attribute) |
No | No | Known single nested attribute and known underlying attribute | Passthrough (known single nested attribute and known underlying attribute) |
No | Yes | Null single nested attribute | Passthrough (null single nested attribute and implicitly null underlying attribute) |
No | Yes | Known single nested attribute, but null underlying attribute | Known single nested attribute with underlying attribute default |
No | Yes | Known single nested attribute and known underlying attribute | Passthrough (known single nested attribute and known underlying attribute) |
Yes | No | Null single nested attribute | Single nested attribute default |
Yes | No | Known single nested attribute, but null underlying attribute | Passthrough (Known single nested attribute with null underlying attribute) |
Yes | No | Known single nested attribute and known underlying attribute | Passthrough (known single nested attribute and known underlying attribute) |
Yes | Yes | Null single nested attribute | Single nested attribute default |
Yes | Yes | Known single nested attribute, but null underlying attribute | Known single nested attribute with underlying attribute default |
Yes | Yes | Known single nested attribute and known underlying attribute | Passthrough (known single nested attribute and known underlying attribute) |
Hopefully this clarifies some of the behaviors here and please reach out if the functionality is not working as I'm describing. It does not appear that the website documentation walks through this level of detail, so will take this issue to adjust that particular documentation.
No Yes Null single nested attribute Passthrough (null single nested attribute and implicitly null underlying attribute)
This is the issue I am running into. Right now, if I want this scenario to not trigger, I need to duplicate the defaults on the object level too.
Default: objectdefault.StaticValue(
types.ObjectValueMust(
cyclesAttrTypes,
map[string]attr.Value{
"enabled": types.BoolValue(false),
"start_day": types.Float64Value(0),
"duration": types.Float64Value(1),
"cooldown": types.Float64Value(0),
"upcoming": types.Float64Value(2),
"auto_add_started": types.BoolValue(true),
"auto_add_completed": types.BoolValue(true),
"need_for_active": types.BoolValue(false),
},
),
),
Is there a way I can prevent this duplication and let the underlying attribute get set to the specified default?
@pksunkara I'm not aware of a way to do that today with existing framework functions/methods, but it may be possible to enhance the framework so that:
defaults.ObjectRequest
typeobjectdefault
function is created that instantiates a known object using those types will either all null underlying values (and somehow triggering those underlying defaults to be called) or instantiating a known object using the attribute defaults directlyI'll create a feature request issue for tracking that proposal.
Created https://github.com/hashicorp/terraform-plugin-framework/issues/777 with above. The proposal details are a little hazy/unclear since we'd need to avoid an import cycle, but I'm hopeful that it might be possible to work around that issue.
Module version
v1.2.0
Relevant provider source code
Terraform Configuration Files
Debug Output
Expected Behavior
The Graphql Request sent to the server contains
triage_enabled
astrue
(read from the default)Actual Behavior
The Graphql Request sent to the server contains
triage_enabled
asfalse
Steps to Reproduce
References
I suspect this is caused by
modifiers.UnknownAttributesOnUnknown
, but it is recommended by @bflad at https://github.com/hashicorp/terraform-plugin-framework/issues/489#issuecomment-1255548450