I am developing a provider using the OpenAPI spec of our cloud service’s HTTP API.
I’ve successfully migrated one of our resources to the plugin framework. However, after migrating the other, the acceptance test gives the error “refresh plan was not empty” with all computed attributes indicating “known after apply”.
From my understanding, this means that after refresh, the values for these attributes are no longer known by the provider. However, I have verified that my HTTP API returns the exact same responses for GET (read) and POST (create). And that the state is being set properly in both read and create. It seems as though the provider is trying to reset the state back to the configuration file (?). Could someone help point me in the right direction of what could be causing this issue? Thank you!
Here is a PR of the migration Migration in progress by kenny-statsig · Pull Request #5 · statsig-io/terraform-provider-statsig · GitHub.
I’ve also included relevant outputs like the API responses and the post/pre refresh plans.
1 Like
What you’re observing is default plan behavior that the framework uses for Computed
attributes, where if there is no config value, it marks it as unknown if the plan indicates there will be an update:
Typically, you can prevent this during “expected updates” by using the UseStateForUnknown
plan modifier, which just takes the prior state value during update: stringplanmodifier package - github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier - Go Packages
As for your specific problem, a high-level guess just looking at your PR, is that this is likely related to the possible generator bug mentioned over here (just being observed from a different angle):
Here, I’m guessing the PlannedState
and PriorState
are being incorrectly determined to be different because of the custom type implementation being generated by terraform-plugin-codegen-framework
.
Thanks for the response @austin.valle.
I was able to dig a bit further and found that the issue occurs during float value comparison.
It seems that when comparing the planned and prior states, diff.go is comparing float64-type attributes with different precisions
diff, _ := resp.PlannedState.Raw.Diff(req.PriorState.Raw)
fmt.Printf("Diff %+v\n", diff)
...
Diff [AttributeName("groups").ElementKeyInt(0).AttributeName("size"): value1: tftypes.Number<"33.3">, value2: tftypes.Number<"33.3"> AttributeName("groups").ElementKeyInt(1).AttributeName("size"): value1: tftypes.Number<"33.3">, value2: tftypes.Number<"33.3"> AttributeName("groups").ElementKeyInt(2).AttributeName("size"): value1: tftypes.Number<"33.4">, value2: tftypes.Number<"33.4"> AttributeName("allocation"): value1: tftypes.Number<"12.3">, value2: tftypes.Number<"12.3">]
values are not equal 33.3 33.3 1
n1 precision 512
n2 precision 53
values are not equal 33.3 33.3 1
n1 precision 512
n2 precision 53
values are not equal 33.4 33.4 1
n1 precision 512
n2 precision 53
values are not equal 12.3 12.3 -1
n1 precision 512
n2 precision 53
Perhaps Terraform is dropping precision at some point between states?
Ahh I understand, my OpenAPI spec is being schematized to NumberAttribute
which has a different precision than Float64Attribute
since it stores the value as a big.Float under the hood. Hence why the prior state precision is always lower than the planned state.
I suppose I’ll need to find a way to update my OAS to generate Float64Attribute
or handle 512-bit precision when json parsing the API response.