Rewire closing providers directly instead of in EvalContext

Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
Christian Mesh 2026-01-06 10:07:44 -05:00
parent d59a32b3d7
commit ca5b1ca650
6 changed files with 27 additions and 46 deletions

View file

@ -56,12 +56,6 @@ type EvalContext interface {
// resources in one module are able to use providers from other modules.
ProviderSchema(context.Context, addrs.AbsProviderConfig) (providers.ProviderSchema, error)
// CloseProvider closes provider connections that aren't needed anymore.
//
// This method will panic if the module instance address of the given
// provider configuration does not match the Path() of the EvalContext.
CloseProvider(context.Context, addrs.AbsProviderConfig) error
// ProviderInput and SetProviderInput are used to configure providers
// from user input.
//

View file

@ -157,30 +157,6 @@ func (c *BuiltinEvalContext) ProviderSchema(ctx context.Context, addr addrs.AbsP
return c.Plugins.ProviderSchema(ctx, addr.Provider)
}
func (c *BuiltinEvalContext) CloseProvider(ctx context.Context, addr addrs.AbsProviderConfig) error {
c.ProviderLock.Lock()
defer c.ProviderLock.Unlock()
var diags tfdiags.Diagnostics
providerAddrKey := addr.String()
providerMap := c.ProviderCache[providerAddrKey]
if providerMap != nil {
for _, provider := range providerMap {
err := provider.Close(ctx)
if err != nil {
diags = diags.Append(err)
}
}
delete(c.ProviderCache, providerAddrKey)
}
if diags.HasErrors() {
return diags.Err()
}
return nil
}
func (c *BuiltinEvalContext) ProviderInput(_ context.Context, pc addrs.AbsProviderConfig) map[string]cty.Value {
c.ProviderLock.Lock()
defer c.ProviderLock.Unlock()

View file

@ -51,10 +51,6 @@ type MockEvalContext struct {
ProviderSchemaSchema providers.ProviderSchema
ProviderSchemaError error
CloseProviderCalled bool
CloseProviderAddr addrs.AbsProviderConfig
CloseProviderProvider providers.Interface
ProviderInputCalled bool
ProviderInputAddr addrs.AbsProviderConfig
ProviderInputValues map[string]cty.Value
@ -187,12 +183,6 @@ func (c *MockEvalContext) ProviderSchema(_ context.Context, addr addrs.AbsProvid
return c.ProviderSchemaSchema, c.ProviderSchemaError
}
func (c *MockEvalContext) CloseProvider(_ context.Context, addr addrs.AbsProviderConfig) error {
c.CloseProviderCalled = true
c.CloseProviderAddr = addr
return nil
}
func (c *MockEvalContext) ProviderInput(_ context.Context, addr addrs.AbsProviderConfig) map[string]cty.Value {
c.ProviderInputCalled = true
c.ProviderInputAddr = addr

View file

@ -7,6 +7,7 @@ package tofu
import (
"context"
"errors"
"fmt"
"log"
@ -64,6 +65,15 @@ func (n *NodeApplyableProvider) Instance(key addrs.InstanceKey) providers.Config
return n.instances[key]
}
// GraphNodeProvider
func (n *NodeApplyableProvider) Close(ctx context.Context) error {
var errs []error
for _, instance := range n.instances {
errs = append(errs, instance.Close(ctx))
}
return errors.Join(errs...)
}
// GraphNodeExecutable
func (n *NodeApplyableProvider) Execute(ctx context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
instances, diags := n.initInstances(ctx, evalCtx, op)

View file

@ -31,6 +31,11 @@ func (n *NodeEvalableProvider) Instance(key addrs.InstanceKey) providers.Configu
return n.instance
}
// GraphNodeProvider
func (n *NodeEvalableProvider) Close(ctx context.Context) error {
return n.instance.Close(ctx)
}
// GraphNodeExecutable
func (n *NodeEvalableProvider) Execute(ctx context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
var err error

View file

@ -55,6 +55,7 @@ type GraphNodeProvider interface {
ProviderAddr() addrs.AbsProviderConfig
Name() string
Instance(addrs.InstanceKey) providers.Configured
Close(ctx context.Context) error
// For test framework
MocksAndOverrides() (IsMocked bool, MockResources []*configs.MockResource, OverrideResources []*configs.OverrideResource)
}
@ -497,7 +498,7 @@ func (t *CloseProviderTransformer) Transform(_ context.Context, g *Graph) error
if closer == nil {
// create a closer for this provider type
closer = &graphNodeCloseProvider{Addr: p.ProviderAddr()}
closer = &graphNodeCloseProvider{Provider: p}
g.Add(closer)
cpm[key] = closer
}
@ -638,7 +639,7 @@ func providerVertexMap(g *Graph) map[string]GraphNodeProvider {
}
type graphNodeCloseProvider struct {
Addr addrs.AbsProviderConfig
Provider GraphNodeProvider
}
var (
@ -647,21 +648,21 @@ var (
)
func (n *graphNodeCloseProvider) Name() string {
return n.Addr.String() + " (close)"
return n.Provider.ProviderAddr().String() + " (close)"
}
// GraphNodeModulePath
func (n *graphNodeCloseProvider) ModulePath() addrs.Module {
return n.Addr.Module
return n.Provider.ProviderAddr().Module
}
// GraphNodeExecutable impl.
func (n *graphNodeCloseProvider) Execute(ctx context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
return diags.Append(evalCtx.CloseProvider(ctx, n.Addr))
return diags.Append(n.Provider.Close(ctx))
}
func (n *graphNodeCloseProvider) CloseProviderAddr() addrs.AbsProviderConfig {
return n.Addr
return n.Provider.ProviderAddr()
}
// GraphNodeDotter impl.
@ -724,6 +725,11 @@ func (n *graphNodeProxyProvider) Instance(key addrs.InstanceKey) providers.Confi
return n.Target().Instance(key)
}
func (n *graphNodeProxyProvider) Close(ctx context.Context) error {
// NOP, close handled by the proxied instance
return nil
}
// Find the *single* keyExpression that is used in the provider
// chain. This is not ideal, but it works with current constraints on this feature
func (n *graphNodeProxyProvider) TargetExpr() (hcl.Expression, addrs.Module) {