Purity verification for builtin functions #37001
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Terraform expects that function calls always return consistent known results, because those functions may be called multiple times to reevaluate the same logical blocks of configuration. The group of functions which read from the filesystem however can't maintain this contract on their own, because changes in the filesystem will inevitably alter their results. This can pose a serious problem when the environment around Terraform changes between plan and apply, and parts of the configuration which Terraform must assume are static evaluate to different values. Changes in the values returned by filesystem functions result in apply-time errors ranging from incorrect data being stored, unexpected errors from resources blaming the provider for inconsistent values, or an outright crash when the internal state of Terraform is corrupted.
Provider defined functions always had this inherent possibility too, because they are executed outside of the control of the Terraform runtime. We developed a method for comparing the function results to ensure they are always consistent between calls, and between plan and and apply, but that was tied directly to the provider function calls. This PR adapts the functionality developed for provider functions to be used more generically for any function call (a lot of the changes here are just removing "Provider" from the data structure names to indicate that they are no longer provider-specific).
Because the function results data already needed to be stored in the plan, and passed around to where functions are instantiated throughout the code, it wasn't much of a stretch to hook that into the
Scopecall which builds out the builtin functions as well. The wrappers are a bit ugly, becausecty.Functionis not an interface, and the function implementations are hidden within a private struct field, so we have to pass along multiple layers of closures to get the wrapper to where it can actually be called.Fixes #36184
Target Release
1.13.x