-
Notifications
You must be signed in to change notification settings - Fork 97
Set, Map, and Object TF framework types throw errors when used #700
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
Comments
Hi @mschuchard 👋 Thank you for raising this and sorry you ran into trouble here. Terraform and the framework type system both delineate between "primitive" and "collection" types. Primitive types do not require anything additional to be functional, while collection types must denote the underlying attribute or element types. More specifically with the framework type system implementation, originally everything was implemented within a single You can see the current quirks in the
For most providers developers, working with the Ideally, it should not be possible for provider developers to incorrectly create types in the first place. This could be achieved, for example, by breaking the As for what to do now given the current situation, I think there might be some hesitation with pointing provider developers directly at the Over in #695 we are exploring the option of expanding all the attribute/block/type documentation into separate, more manageable pages. With those extra pages, we could further get into more code examples and potentially provide a "Troubleshooting" section with the Go compiler error you mention. Do you think that might be reasonable from a documentation standpoint? |
Thanks for the information. It is a bit unclear to me if this is pertaining to this issue, #699, or both in combination.
Great! Where in the documentation can I find information about that? I was taking shots in the dark around how to specify the collection type fully in the schema, and could not arrive at any positive results. I also did try to workaround this with a dummy I do also feel like I understand your concern over encouraging the use of
I am familiar with that one as I commented already about my struggles with the typing and my appreciation for documentation expansion. I am unsure about others' experiences thus far, but I am not finding examples to cross-reference in the major providers where code is attempting to achieve the same kind of results that I am working towards. I code in many languages for multiple bindings/integrations/APIs and the |
Thank you for the additional information. It's the end of my day, but I do want to provide you a quick answer here:
In your schema, I would anticipate something like the below for "list_of_map_attribute": schema.ListAttribute{
ElementType: types.Map{
ElemType: /* ... types.String, etc. */, // ElemType inside a Map is required (old naming convention)
},
// ... other attribute configuration ...
}, For the "set_nested_attribute": schema.SetNestedAttribute{
NestedObject: schema.NestedAttributeObject{
// ... nested object configuration ...
},
// ... other attribute configuration ...
}, In your data models: type ExampleResourceModel struct {
ListOfMapAttribute types.List `tfsdk:"list_of_map_attribute"`
SetNestedAttribute types.Set `tfsdk:"set_nested_attribute"`
}
type SetNestedAttributeModel struct {
// ... underlying attributes ...
} And converting out (assuming a list of map of strings): var config ExampleResourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}
// generally good to check config.ListOfMapAttribute.IsNull() or IsUnknown() before doing the below
// similarly with config.SetNestedAttribute.IsNull()/IsUnknown()
var listOfMaps []types.Map
resp.Diagnostics.Append(config.ElementsAs(ctx, &listOfMaps))
if resp.Diagnostics.HasError() {
return
}
for _, listMap := range listOfMaps {
var mapOfStrings map[string]types.String
resp.Diagnostics.Append(listMap.ElementsAs(ctx, &mapOfStrings)...)
if resp.Diagnostics.HasError() {
return
}
// hopefully you're good from here :)
}
var []setNestedAttribute SetNestedAttributeModel
resp.Diagnostics.Append(config.SetNestedAttribute.ElementsAs(ctx, &setNestedAttribute)...)
if resp.Diagnostics.HasError() {
return
}
// hopefully you're good from here :) Complex attributes are tricky to talk about and write out code-wise, since there are multiple potential ways you can write the Go code or use the type system, but hopefully this extra context/example code is helpful. I apologize if any of the code is buggy above, I was trying to hastily write this before heading out. If you have further questions about this over the weekend, you may have good luck raising a topic on HashiCorp Discuss. I'll try to provide a better response to the rest next week. |
Ok yes wow: that first block of code is exactly what I needed. I had no idea from the For the second and third blocks of code: I actually do not want nested attributes, but now I am curious because I would have thought the
Good point.
Anyway: thanks so much for all of this, and expanded documentation for the Also on an interesting note: someone on StackOverflow earlier today asked almost literally the same question as this issue's topic, but that person seemed to be using SDKv2. I informed the person I felt fairly certain an upgrade to the plugin framework was necessary because schema for I will take another shot at this in a couple days, but I would expect this to move me forward. I also think this issue's root cause is a subset of the expanded documentation discussed in #695 because I was misusing the |
My apologies: I thought your reply above was functional for the current 1.2.0 version of this Go module. However, I understand now that your first example of: "list_of_map_attribute": schema.ListAttribute{
ElementType: types.Map{
ElemType: /* ... types.String, etc. */, // ElemType inside a Map is required (old naming convention)
},
// ... other attribute configuration ...
}, is a proposal for a future version since it throws the exact same multiple errors as my attempt. I will eagerly await the implementation of that functionality in the |
@mschuchard can you please show all of your code and the errors you are seeing? I do see that I typo'd a few things in my quick writing last week (e.g.
I would recommend reading about variadic functions in the Go programming language here: https://www.digitalocean.com/community/tutorials/how-to-use-variadic-functions-in-go And peeking at the Go package documentation for each call:
One way to break it down is: diags := listMap.ElementsAs(ctx, &mapOfStrings)
// diags is a diag.Diagnostics (which itself is a type alias for []diag.Diagnostics)
resp.Diagnostics.Append(diags...) Its a coding style to remove the intermediate variable (
The terraform-plugin-framework Go module and its underlying |
That was it right there. I have egg on my face for just blindly following that snippet of the schema and not even attempting to modify it with something I should have known. After updating to: ElementType: types.MapType{
ElemType: types.StringType,
}, I was "off to the races", and only needed one more update to pass acceptance testing. Speaking of which...
So I really appreciate this level of example, but sadly all I actually needed was That totally makes sense, and I appreciate the link to that because I could not find it. I think really the problem for me is the pointers/reference implementation aspect because it is my bane in C++/Go/Rust, and I think I only somewhat understand it even now thanks to Rust's memory safety aspects.
I think I was being kind of hopeful and facetious. In the Packer SDK currently we have something similar to the Model type Config struct {
InstallCmd []string `mapstructure:"install_cmd"`
Keyword string `mapstructure:"keyword"`
Local bool `mapstructure:"local"`
ctx interpolate.Context
} and the type conversion fails when generating HCL2 compatibility for reasons explained to me by Martin. I was wondering if swapping Anyway, thanks again for this truly. |
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
Relevant provider source code
Expected Behavior
According to the documentation, these are the associated framework types, so they should function as expected.
Actual Behavior
Additional Information
I cynically worked around the errors by importing the
basetypes
package, and then:ElementType: basetypes.MapType{},
However, I am unsure if this is a true fix for the issue, and would not feel confident proposing a PR with that as the fix for this issue. This is especially because this workaround then causes a segfault analogous to #699.
The text was updated successfully, but these errors were encountered: