mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
39a83b2fd1
This was incorrectly comparing a cty.Value to an hcl.Body. Now we decode the body first so we can compare two of cty.Value. Also includes a fix to a stale comment in buildProviderConfig that was no longer accurate.
154 lines
4.6 KiB
Go
154 lines
4.6 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/configs"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
func buildProviderConfig(ctx EvalContext, addr addrs.ProviderConfig, body hcl.Body) hcl.Body {
|
|
// If we have an Input configuration set, then merge that in
|
|
if input := ctx.ProviderInput(addr); input != nil {
|
|
// "input" is a map of the subset of config values that were known
|
|
// during the input walk, set by EvalInputProvider. Note that
|
|
// in particular it does *not* include attributes that had
|
|
// computed values at input time.
|
|
|
|
inputBody := configs.SynthBody("<input prompt>", input)
|
|
body = configs.MergeBodies(body, inputBody)
|
|
}
|
|
|
|
return body
|
|
}
|
|
|
|
// EvalConfigProvider is an EvalNode implementation that configures
|
|
// a provider that is already initialized and retrieved.
|
|
type EvalConfigProvider struct {
|
|
Addr addrs.ProviderConfig
|
|
Provider *ResourceProvider
|
|
Config *configs.Provider
|
|
}
|
|
|
|
func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|
if n.Provider == nil {
|
|
return nil, fmt.Errorf("EvalConfigProvider Provider is nil")
|
|
}
|
|
if n.Config == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var diags tfdiags.Diagnostics
|
|
provider := *n.Provider
|
|
config := n.Config
|
|
|
|
if config == nil {
|
|
// If we have no explicit configuration, just write an empty
|
|
// configuration into the provider.
|
|
configDiags := ctx.ConfigureProvider(n.Addr, cty.EmptyObjectVal)
|
|
return nil, configDiags.ErrWithWarnings()
|
|
}
|
|
|
|
schema, err := provider.GetSchema(&ProviderSchemaRequest{})
|
|
if err != nil {
|
|
diags = diags.Append(err)
|
|
return nil, diags.NonFatalErr()
|
|
}
|
|
if schema == nil {
|
|
return nil, fmt.Errorf("schema not available for %s", n.Addr)
|
|
}
|
|
|
|
configSchema := schema.Provider
|
|
configBody := buildProviderConfig(ctx, n.Addr, config.Config)
|
|
configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, addrs.NoKey)
|
|
diags = diags.Append(evalDiags)
|
|
if evalDiags.HasErrors() {
|
|
return nil, diags.NonFatalErr()
|
|
}
|
|
|
|
configDiags := ctx.ConfigureProvider(n.Addr, configVal)
|
|
configDiags = configDiags.InConfigBody(configBody)
|
|
|
|
return nil, configDiags.ErrWithWarnings()
|
|
}
|
|
|
|
// EvalInitProvider is an EvalNode implementation that initializes a provider
|
|
// and returns nothing. The provider can be retrieved again with the
|
|
// EvalGetProvider node.
|
|
type EvalInitProvider struct {
|
|
TypeName string
|
|
Addr addrs.ProviderConfig
|
|
}
|
|
|
|
func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|
return ctx.InitProvider(n.TypeName, n.Addr)
|
|
}
|
|
|
|
// EvalCloseProvider is an EvalNode implementation that closes provider
|
|
// connections that aren't needed anymore.
|
|
type EvalCloseProvider struct {
|
|
Addr addrs.ProviderConfig
|
|
}
|
|
|
|
func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|
ctx.CloseProvider(n.Addr)
|
|
return nil, nil
|
|
}
|
|
|
|
// EvalGetProvider is an EvalNode implementation that retrieves an already
|
|
// initialized provider instance for the given name.
|
|
//
|
|
// Unlike most eval nodes, this takes an _absolute_ provider configuration,
|
|
// because providers can be passed into and inherited between modules.
|
|
// Resource nodes must therefore know the absolute path of the provider they
|
|
// will use, which is usually accomplished by implementing
|
|
// interface GraphNodeProviderConsumer.
|
|
type EvalGetProvider struct {
|
|
Addr addrs.AbsProviderConfig
|
|
Output *ResourceProvider
|
|
|
|
// If non-nil, Schema will be updated after eval to refer to the
|
|
// schema of the provider.
|
|
Schema **ProviderSchema
|
|
}
|
|
|
|
func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|
result := ctx.Provider(n.Addr)
|
|
if result == nil {
|
|
return nil, fmt.Errorf("provider %s not initialized", n.Addr)
|
|
}
|
|
|
|
if n.Output != nil {
|
|
*n.Output = result
|
|
}
|
|
|
|
if n.Schema != nil {
|
|
*n.Schema = ctx.ProviderSchema(n.Addr)
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
// EvalInputProvider is an EvalNode implementation that asks for input
|
|
// for the given provider configurations.
|
|
type EvalInputProvider struct {
|
|
Addr addrs.ProviderConfig
|
|
Provider *ResourceProvider
|
|
Config *configs.Provider
|
|
}
|
|
|
|
func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|
// This is currently disabled. It used to interact with a provider method
|
|
// called Input, allowing the provider to capture input interactively
|
|
// itself, but once re-implemented we'll have this instead use the
|
|
// provider's configuration schema to automatically infer what we need
|
|
// to prompt for.
|
|
var diags tfdiags.Diagnostics
|
|
diags = diags.Append(tfdiags.SimpleWarning(fmt.Sprintf("%s: provider input is temporarily disabled", n.Addr)))
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|