Schema for `Optional` + `Computed` to support correct removal plan in framework

In a provider I have the situation that a top-level resource attribute is both Optional and Computed with the corresponding API behavior that ff the attribute is not set during create the upstream API will set it to some value, let’s say it’s "default" string. From then on the value is never changed upstream (re-computed), but the user is free to change it to some desired value.

Now, the behavior that I’m looking for is that if the user removes the attribute from the resource entirely a diff in the plan is generated and I’d be able to send a "null" value upstream so that it can reset it to the default. The problem with the SDK is that no plan is generated, because it’s also marked as Computed. I think that’s a limitation with the SDK.

What would be the correct way to handle such a situation with the new framework?

Hi @timofurrer,
If I understand your question correctly, you essentially want the behavior “default” value for an attribute but that value is coming from an API call rather than a static, hardcoded value.

In the Framework, a default value is implemented using plan modification, you can implement a resource plan modifier that will call your API to set the value of your attribute if the value of the attribute in the configuration is Unknown.

For example, in the Local provider, the file_permission attribute is both Optional and Computed and uses an attribute-level plan modifier to set a default string. Please note that this example uses an attribute plan modifier instead of a resource plan modifier, in your case you would use a resource plan modifier as the Framework currently only supports external API calls for plan modifiers at the resource-level, but conceptually they are very similar.

If I understand your question correctly, you essentially want the behavior “default” value for an attribute but that value is coming from an API call rather than a static, hardcoded value.

Not exactly, the API is not known to the provider it all - not statically nor is it able to get it via an API call. What I’m looking for is a way to get a diff in the plan if the attribute is removed from the config entirely - so that the provider can send a null value to the API which resets the attribute to the default only the API backend knows.

I just commented out an Optional + Computed attribute with no PlanModifier from the config for a provider based on very recent main branch, and was surprised to find it did exactly what you’re saying: The previously configured value persisted in the tfstate and no new plan was generated.

I expected that removing the value for this attribute would be enough to generate a new plan, but it wasn’t.

The subject of what goes on behind the scenes of Terraform plan with regards to providers is pretty nuanced. Without going too much into the weeds, the behavior for Terraform for Optional + Computed attributes is to copy the prior state if there is no configuration for it.

To handle your situation in the framework, you can create an attribute or resource plan modifier as detailed in my previous reply except you would set the plan value to unknown if the request state value is not null and the request configuration value is null. This should then give you a diff in the terraform plan.

Alternatively, you can try splitting your attribute into two attributes, an Optional attribute that users can configure and sends the value to the API and a Computed attribute that Terraform would set to unknown if there is no configuration and that would cause a diff in the plan.

Please let me know if you have any other questions or if you need me to clarify.

The approach with the plan modifier sounds good - I’ll look into this once we’ve migrated that particular resource over to the new framework. Thanks.

1 Like