hashicorp / hashicorp/terraform-plugin-framework
Consider Object Nested Attribute Default Implementation
- Dominant language
- Go
- Stars
- 384
- Forks
- 107
- Avg merge
- 3m
- Merged PRs (30d)
- 1
Description
### Module version
```
v1.3.1
```
### Use-cases
When working with nested attributes, it may be desirable to automatically have an object default based on all the nested attribute default values for when the object is null. Today, this is a manual process to re-create the object default value based on the nested attribute defaults.
```go
schema.SingleNestedAttribute{
// ... other fields ...
Attributes: map[string]schema.Attribute{
"attribute_one": schema.StringAttribute{
// ... other fields ...
Default: stringdefault.StaticString("one"),
}
"attribute_two": schema.StringAttribute{
// ... other fields ...
Default: stringdefault.StaticString("two"),
}
},
Default: objectdefault.StaticValue(
map[string]attr.Type{
"attribute_one": types.StringType,
"attribute_two": types.StringType,
},
map[string]attr.Value{
"attribute_one": types.StringValue("one"),
"attribute_two": types.StringValue("two"),
},
)
}
```
### Proposal
_NOTE: `NestedAttributes` is not possible at the moment due to import cycle._
Add an `AttributeTypes` field and `NestedAttributes` field to `defaults.ObjectRequest`:
```go
type ObjectRequest struct {
// AttributeTypes returns the mapping of nested attribute
// names to attribute types.
AttributeTypes map[string]attr.Type
// NestedAttributes is populated with the schema's nested
// attributes for this object, if the object itself was a
// NestedAttributeObject.
NestedAttributes map[string]fwschema.Attribute
// Path contains the path of the attribute for setting the
// default value. Use this path for any response diagnostics.
Path path.Path
}
```
In `internal/fwschemadata`, update the object handling to something like:
```go
case fwschema.AttributeWithObjectDefaultValue:
defaultValue := a.ObjectDefaultValue()
if defaultValue != nil {
req := defaults.ObjectRequest{
AttributeTypes: a.GetType(), // real implementation is more complicated
Path: fwPath,
}
if na, ok := a.(fwschema.NestedAttribute); ok {
req.NestedAttributes = na.GetNestedObject().GetAttributes()
}
resp := defaults.ObjectResponse{}
defaultValue.DefaultObject(ctx, req, &resp)
logging.FrameworkTrace(ctx, fmt.Sprintf("setting attribute %s to default value: %s", fwPath, resp.PlanValue))
return resp.PlanValue.ToTerraformValue(ctx)
}
```
Create a new `resource/schema/objectdefault` implementation for instantiating the object using all the nested attribute defaults, e.g.
```go
func NestedAttributeDefaults() defaults.Object {/* ... */}
```
It may also be worth considering whether there should be a simplified object value default function that only takes in the `map[string]attr.Value`, since we can theoretically have the `map[string]attr.Type` already available.
### References
- https://github.com/hashicorp/terraform-plugin-framework/issues/726#issuecomment-1593693448
Contributor guide
Assessment
This issue has not been assessed yet.