Explicit hash function for SetNestedAttribute

I’ve got a use-case where an attribute is a SetNestedAttribute, but I want to compute the hash for each element based on only a subset of the attributes in the NestedObject. How can I do this? The AWS provider does something similar using SDKv2; https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/service/ec2/ec2_ami.go#L153-L159. I haven’t been able to find the equivalent in the Plugin Framework.

My reason for doing this is some of the values in the element are optional and computed (which is making Terraform think the changes were not applied correctly, and on running a plan, that there are new changes).

@bflad (Hi Brian) once told me that SetNested objects containing both configured and computed objects were bad news.

You might find that thread (and the linked response in particular) helpful.

I don’t understand the hash thing you’re pointing out in the AWS provider, but I’ve really been wishing for a way to declare a “key” attribute in a SetNested attribute. Maybe that’s what you’re getting at?

Thanks for the response. I tried changing up the schema so that it’s not a SetNestedAttribute, but a ListNestedAttribute. That works fine, except the API may return a different order. So I deal with that by updating values in the state in-place (to retain order), and append if new values are returned. The problem is if the user changes the order in their configuration, that is picked up as a change. I tried following the recommendation in Custom sort for ListNestedAttributes · Issue #305 · hashicorp/terraform-plugin-framework · GitHub, but it’s not very helpful (especially without an example). I tried doing what I understood from it myself: adding a ModifyPlan function and re-ordering the elements in the plan to match what is in the state, but that fails during a terraform plan (planned value does not match config value). Obviously I’m misunderstanding this, but I’m not sure how to fix this.

And yes, a “key” attribute would solve this instantly. Composite keys, even better.

I don’t claim to have anywhere near a complete understanding of this topic, but from what I’ve managed to learn so far, it looks like the ability to set a custom hash function in SDKv2 was an unwise decision that necessarily could never be completely implemented, because some of the comparison occurs in Terraform itself, not the provider - so you end up with a set that is treated with different concepts of identity in Terraform vs. the provider.

I suspect part of why this works at all, is the legacy exemption that lets SDK trample over all the modern rules for good provider behaviour that Terraform enforces on non-SDK providers.

In the particular example you cite, I think the aws_ami resource is avoiding all the issues by making any change to an existing set item require recreation of the entire resource anyway, meaning it effectively doesn’t care if Terraform itself would have come up with a misleading plan diff, because it has already overridden the operation to be a full replace of the containing resource.

If you want to explain your own use-case in more detail - and without assuming use of SetNestedAttribute - people here can probably give better guidance on how best to represent it.

Funnily enough my use-case falls under the same umbrella. If any attribute in my set changes value, the whole resource must be replaced.