I’d like to write a resource which looks like this:
resource "thing" "x" {
two_dimensional_map = {
A = { // A is an arbitrary map key
a = { // a is an arbitrary map key
object_val_1 = ""
object_val_2 = ""
}
b = { // b is an arbitrary map key
object_val_1 = ""
object_val_2 = ""
}
}
B = { // B is an arbitrary map key
a = { // a is an arbitrary map key
object_val_1 = ""
object_val_2 = ""
}
b = { // b is an arbitrary map key
object_val_1 = ""
object_val_2 = ""
}
}
}
}
I guess this would be a two-dimensional MapNestedObject
?
The following resource schema mostly gets me there:
func (o *thing) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"two_dimensional_map": schema.MapAttribute{
ElementType: types.MapType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"object_val_1": types.StringType,
"object_val_2": types.StringType,
},
},
},
},
},
}
}
The problem is that the innermost object is expressed merely as a types.ObjectType{}
. There’s no way to describe it as a map[string]schema.Attribute
.
The result is the object’s attributes don’t support Validators
, can’t be marked as Optional
, and won’t have documentation rendered by tfplugindocs
via MarkdownDescription
.
Is there a way to express a schema which includes a Map
of MapNested
attributes?
Hey there @hQnVyLRx ,
Is there a way to express a schema which includes a Map
of MapNested
attributes?
Short answer to your question is no, there’s no way to describe a two-dimensional map where an underlying object can define Computed
/Optional
/Required
fields, validators, descriptions, etc.
The schema you provided is the closest you can get to a multi-dimensional map.
Deeper dive, in case future readers are interested
It’s not actually a terraform-plugin-framework
implementation detail, but a Terraform plugin protocol detail that restricts what we can do here. Schema attributes in the protocol can be defined with either type
(MapAttribute
, StringAttribute
) or nested_type
(SingleNested
, MapNested
). A nested type comprises of a NestingMode
and attributes of an object (NestedObject.), so the only representation you can have for nested attributes are:
- List of objects
- Map of object
- Set of object
- Object
That’s to say if we wanted to fully model a multi-dimensional map, we’d need to make changes to both Terraform core, the plugin protocol, and the SDKs to support a new NestingMode
.
A partial solution to your problem that is a limitation of terraform-plugin-framework
today could be to add support for optional
object attributes, which would eventually be defined in the type
field. It’s actually already supported in our lower-level SDK terraform-plugin-go
, we would just need to expose that in terraform-plugin-framework
. This wouldn’t expose the object in the schema, but would allow defining a two-dimensional map’s object attributes as optional
in type itself.
A similar request was made in reference to provider functions, which is particularly interesting because there are no attribute/nested attribute concepts with functions, so optional
object attributes would potentially help there as well.
1 Like
Thanks very much for the thorough explanation, @austin.valle.
1 Like