opentofu/terraform/evaltree_provider.go
Alisdair McDiarmid ac99a3b916 terraform: Relax provider config ref constraints
When configuring providers, it is normally valid to refer to any value
which is known at apply time. This can include resource instance
attributes, variables, locals, and so on.

The import command has a simpler graph evaluation, which means that
many of these values are unknown. We previously prevented this from
happening by restricting provider configuration references to input
variables (#22862), but this was more restrictive than is necessary.

This commit changes how we verify provider configuration for import.
We no longer inspect the configuration references during graph building,
because this is too early to determine if these values will become known
or not.

Instead, when the provider is configured during evaluation, we
check if the configuration value is wholly known. If not, we fail with a
diagnostic error.

Includes a test case which verifies that providers can now be configured
using locals as well as vars, and an updated test case which verifies
that providers cannot be configured with references to resources.
2020-06-29 10:58:20 -04:00

86 lines
1.9 KiB
Go

package terraform
import (
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/providers"
)
// ProviderEvalTree returns the evaluation tree for initializing and
// configuring providers.
func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNode {
var provider providers.Interface
addr := n.Addr
seq := make([]EvalNode, 0, 5)
seq = append(seq, &EvalInitProvider{
Addr: addr,
})
seq = append(seq, &EvalOpFilter{
Ops: []walkOperation{walkValidate},
Node: &EvalSequence{
Nodes: []EvalNode{
&EvalGetProvider{
Addr: addr,
Output: &provider,
},
&EvalValidateProvider{
Addr: addr,
Provider: &provider,
Config: config,
},
},
},
})
seq = append(seq, &EvalOpFilter{
Ops: []walkOperation{walkRefresh, walkPlan, walkApply, walkDestroy, walkImport},
Node: &EvalSequence{
Nodes: []EvalNode{
&EvalGetProvider{
Addr: addr,
Output: &provider,
},
},
},
})
// We configure on everything but validate, since validate may
// not have access to all the variables.
seq = append(seq, &EvalOpFilter{
Ops: []walkOperation{walkRefresh, walkPlan, walkApply, walkDestroy},
Node: &EvalSequence{
Nodes: []EvalNode{
&EvalConfigProvider{
Addr: addr,
Provider: &provider,
Config: config,
},
},
},
})
seq = append(seq, &EvalOpFilter{
Ops: []walkOperation{walkImport},
Node: &EvalSequence{
Nodes: []EvalNode{
&EvalConfigProvider{
Addr: addr,
Provider: &provider,
Config: config,
VerifyConfigIsKnown: true,
},
},
},
})
return &EvalSequence{Nodes: seq}
}
// CloseProviderEvalTree returns the evaluation tree for closing
// provider connections that aren't needed anymore.
func CloseProviderEvalTree(addr addrs.AbsProviderConfig) EvalNode {
return &EvalCloseProvider{Addr: addr}
}