Had a short discussion with my copilot about it
Don’t you just love those new reasoning models 
So based on the discussion below my literal question would be:
- Can Terraform be modified to perform a
ValidateProviderConfig
RPC before a CallFunction
RPC?
So basically implement the same validation for functions
regarding the invocation of ValidateProviderConfig
as with datasources
?
Copilot discussion
Would it be possible for me to simply just invoke the ValidateConfig method myself when a CallFunction is being done?
You’re observing a known characteristic of how Terraform interacts with providers, especially concerning provider-defined functions in scenarios like terraform validate
where no resources or data sources explicitly invoke the provider’s configuration lifecycle.
While you could technically call the ValidateConfig
method from your GenerateResourceNameFunction.Run
method (if the function had a reference to the provider instance), it wouldn’t work as intended for the purpose of processing the provider’s HCL configuration.
Here’s why:
- Missing Configuration Input: The
ValidateConfig
method has the signature: func (p *resourcenamingtoolFunctionsProvider) ValidateConfig(ctx context.Context, req provider.ValidateConfigRequest, resp *provider.ValidateConfigResponse)
The crucial part here is req.Config
. This field in provider.ValidateConfigRequest
is how Terraform provides the actual HCL configuration block of your provider to the method.
- Function’s
Run
Method Signature: Your function’s Run
method (e.g., in GenerateResourceNameFunction
) receives function.RunRequest
. This request contains the arguments passed to the function in the Terraform configuration, but it does not contain the provider’s own HCL configuration block.
Therefore, even if you called p.ValidateConfig
from your function’s Run
method, you would not have the necessary provider.ValidateConfigRequest
(specifically, the req.Config
part) to pass to it. You cannot reconstruct the provider’s configuration block from within the function’s execution context.]
Your current approach of using ValidateConfig
to process and cache the configuration to a file (and then having Configure
and the function potentially read from this file) is a workaround for the lifecycle behavior you’ve encountered. The resourcenamingtool_status
data source helps ensure that ValidateConfig
is triggered.
If the Terraform Plugin Framework guaranteed that Configure
(which could get configuration from req.Config
was always called before any function invocation, even in “offline” states, your file-based workaround might be less necessary. However, given the current behavior you’re working around, directly calling ValidateConfig
from the function’s Run
method isn’t a viable alternative due to the missing provider configuration input.
And would it be possible by implementing a custom provider server somehow and changing the behaviour, so that when a function gets called the ValidateConfig req.Config is made available.
You’re delving into the fundamental architecture of Terraform plugins and their communication with Terraform Core.
The short answer is that implementing a custom provider server to directly make the req.Config
from ValidateConfig
(which is provider.ValidateConfigRequest.Config
) available at the moment a function is called (i.e., within the CallFunction
RPC handler, using its function.RunRequest
) is not feasible in a way that would simplify your current model or bypass the existing lifecycle.
Here’s why:
- gRPC Protocol Definition: The communication between Terraform Core and your plugin is defined by a gRPC protocol (e.g.,
tfplugin6
).
- The
ValidateProviderConfig
RPC (which maps to your ValidateConfig
method) is how Terraform Core sends the provider’s HCL configuration to the plugin. The request for this RPC (ValidateProviderConfigRequest
) contains the Config
field.
- The
CallFunction
RPC is separate. Its request (CallFunctionRequest
) contains the function name and its arguments. It does not include the provider’s HCL configuration.
- Provider Server Role: The provider server (which
terraform-plugin-go
helps you run) is an implementation of this gRPC service. It responds to RPCs sent by Terraform Core.
- When Terraform Core invokes a function, it sends a
CallFunctionRequest
. The server code handling this request (ultimately leading to your function’s Run
method) only receives the data present in CallFunctionRequest
.
- The server cannot compel Terraform Core to send the provider’s HCL configuration as part of a
CallFunctionRequest
, nor can it initiate an RPC back to Core to ask for it during a function call.
- Data Flow: The provider’s HCL configuration and the function’s arguments flow to the plugin through different, distinct RPCs at different times, as determined by Terraform Core’s execution plan.
What a Custom Server Could and Couldn’t Do:
- Could Cache: If you were to customize the server, you could theoretically cache the
req.Config
DynamicValue
(or the parsed resourcenamingtoolProviderModel
) when the ValidateConfig
RPC is handled.
- Couldn’t Change RPC Payload: You couldn’t change the fundamental behavior that the
CallFunctionRequest
itself doesn’t contain this provider configuration.
- Dependency on Lifecycle: Your custom server would still depend on Terraform Core actually calling
ValidateConfig
(or Configure
) for the relevant provider instance before the function call, so that the data could be cached.
Your Current Approach: Your current method—using ValidateConfig
to process the configuration and save it to a file, and using a data source to help ensure ValidateConfig
is triggered—is a pragmatic workaround for the fact that the provider’s Configure
method might not be called before a function invocation in “offline” scenarios like terraform validate
. The function then reads this cached configuration.
Essentially, you’re already implementing a form of caching. The p.config
] field in your provider, when populated by ValidateConfig
or Configure
, is an in-memory cache. If the NewGenerateResourceNameFunction
constructor is called after p.config
is populated by ValidateConfig
, then f.config
in your function instance would hold this data. The file-based sharing handles cases where p.config
might not be directly available or consistent across different operations or if Configure
isn’t run.
Modifying the gRPC server itself wouldn’t change the information Terraform Core sends with each specific type of request. The challenge lies in Terraform Core’s lifecycle for provider configuration in relation to function calls, especially in validate-only scenarios.