-
Notifications
You must be signed in to change notification settings - Fork 36
Description
ResourceRouter and DataSourceRouter make it easy to split requests out to be handled by resource or data source specific types. This is helpful, for example, for something like this:
type resource struct {}
func (r resource) ApplyResourceChange(ctx context, req *tfprotov5.ApplyResourceChangeRequest) (*tfprotov5.ApplyResourceChangeResponse, error) {
// only requests for foo_resource will be handled here
// other resources will get routed to different functions
}
router := tfprotov5.ResourceRouter{
"foo_resource": resource{},
}This makes it so provider developers don't need to handle all resources in the same function, or write their own routing code based on req.TypeName.
But it has a fundamental problem: the provider configuration has no way to get into that method. Or if there is a way, it's convoluted and not intuitive.
We could solve this by having the ResourceRouter change:
type ResourceRouter map[string]func(tfprotov5.ProviderServer) (tfprotov5.ResourceServer, error)Then provider developers could do something like this:
// myProvider holds provider configuration and fills the tfprotov5.ProviderServer interface
type myProvider struct{}
type resource struct {
provider myProvider
}
func (r resource) ApplyResourceChange(ctx context, req *tfprotov5.ApplyResourceChangeRequest) (*tfprotov5.ApplyResourceChangeResponse, error) {
// only requests for foo_resource will be handled here
// other resources will get routed to different functions
}
// assume the other ResourceServer methods are defined on resource
func newResource(provider tfprotov5.ProviderServer) (tfprotov5.ResourceServer, error) {
prov, ok := provider.(myProvider)
if !ok {
return nil, errors.New("provider is of wrong type, something went wrong")
}
return resource{provider: prov}, nil
}
router := tfprotov5.ResourceRouter{
"foo_resource": newResource,
}ResourceRouter would then instantiate the instance of the resource, passing in the provider, completing the chain.
But this begs the question: how sure are we that this is the right abstraction? Does this need to live in this module? Could we move it to plugin-sdk or another module that's easier to bump the major version on without losing much, or even anything?
Should we bother reworking it, or just remove it outright and put it somewhere else?
Regardless, I think we're going to want to make the provider available, as it's going to be what has the Terraform version and any information passed in the ConfigureProvider RPC.