]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/terraform/eval_provider.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / eval_provider.go
index 092fd18d838579a97ce377a40a0d7d8c8826feba..7df6584a1e56aac4a23f66672cb2d47ed0c49b62 100644 (file)
@@ -2,162 +2,145 @@ package terraform
 
 import (
        "fmt"
+       "log"
 
-       "github.com/hashicorp/terraform/config"
-)
-
-// EvalSetProviderConfig sets the parent configuration for a provider
-// without configuring that provider, validating it, etc.
-type EvalSetProviderConfig struct {
-       Provider string
-       Config   **ResourceConfig
-}
-
-func (n *EvalSetProviderConfig) Eval(ctx EvalContext) (interface{}, error) {
-       return nil, ctx.SetProviderConfig(n.Provider, *n.Config)
-}
+       "github.com/hashicorp/hcl2/hcl"
 
-// EvalBuildProviderConfig outputs a *ResourceConfig that is properly
-// merged with parents and inputs on top of what is configured in the file.
-type EvalBuildProviderConfig struct {
-       Provider string
-       Config   **ResourceConfig
-       Output   **ResourceConfig
-}
+       "github.com/hashicorp/terraform/addrs"
+       "github.com/hashicorp/terraform/configs"
+       "github.com/hashicorp/terraform/providers"
+       "github.com/hashicorp/terraform/tfdiags"
+)
 
-func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) {
-       cfg := *n.Config
-
-       // If we have a configuration set, then merge that in
-       if input := ctx.ProviderInput(n.Provider); 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; those appear *only* in
-               // "cfg" here.
-               rc, err := config.NewRawConfig(input)
-               if err != nil {
-                       return nil, err
-               }
-
-               merged := cfg.raw.Merge(rc)
-               cfg = NewResourceConfig(merged)
+func buildProviderConfig(ctx EvalContext, addr addrs.ProviderConfig, config *configs.Provider) hcl.Body {
+       var configBody hcl.Body
+       if config != nil {
+               configBody = config.Config
        }
 
-       // Get the parent configuration if there is one
-       if parent := ctx.ParentProviderConfig(n.Provider); parent != nil {
-               merged := cfg.raw.Merge(parent.raw)
-               cfg = NewResourceConfig(merged)
+       var inputBody hcl.Body
+       inputConfig := ctx.ProviderInput(addr)
+       if len(inputConfig) > 0 {
+               inputBody = configs.SynthBody("<input-prompt>", inputConfig)
        }
 
-       *n.Output = cfg
-       return nil, nil
+       switch {
+       case configBody != nil && inputBody != nil:
+               log.Printf("[TRACE] buildProviderConfig for %s: merging explicit config and input", addr)
+               // Note that the inputBody is the _base_ here, because configs.MergeBodies
+               // expects the base have all of the required fields, while these are
+               // forced to be optional for the override. The input process should
+               // guarantee that we have a value for each of the required arguments and
+               // that in practice the sets of attributes in each body will be
+               // disjoint.
+               return configs.MergeBodies(inputBody, configBody)
+       case configBody != nil:
+               log.Printf("[TRACE] buildProviderConfig for %s: using explicit config only", addr)
+               return configBody
+       case inputBody != nil:
+               log.Printf("[TRACE] buildProviderConfig for %s: using input only", addr)
+               return inputBody
+       default:
+               log.Printf("[TRACE] buildProviderConfig for %s: no configuration at all", addr)
+               return hcl.EmptyBody()
+       }
 }
 
 // EvalConfigProvider is an EvalNode implementation that configures
 // a provider that is already initialized and retrieved.
 type EvalConfigProvider struct {
-       Provider string
-       Config   **ResourceConfig
+       Addr     addrs.ProviderConfig
+       Provider *providers.Interface
+       Config   *configs.Provider
 }
 
 func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
-       return nil, ctx.ConfigureProvider(n.Provider, *n.Config)
+       if n.Provider == nil {
+               return nil, fmt.Errorf("EvalConfigProvider Provider is nil")
+       }
+
+       var diags tfdiags.Diagnostics
+       provider := *n.Provider
+       config := n.Config
+
+       configBody := buildProviderConfig(ctx, n.Addr, config)
+
+       resp := provider.GetSchema()
+       diags = diags.Append(resp.Diagnostics)
+       if diags.HasErrors() {
+               return nil, diags.NonFatalErr()
+       }
+
+       configSchema := resp.Provider.Block
+       configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey)
+       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 {
-       Name string
+       TypeName string
+       Addr     addrs.ProviderConfig
 }
 
 func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) {
-       return ctx.InitProvider(n.Name)
+       return ctx.InitProvider(n.TypeName, n.Addr)
 }
 
 // EvalCloseProvider is an EvalNode implementation that closes provider
 // connections that aren't needed anymore.
 type EvalCloseProvider struct {
-       Name string
+       Addr addrs.ProviderConfig
 }
 
 func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) {
-       ctx.CloseProvider(n.Name)
+       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 {
-       Name   string
-       Output *ResourceProvider
+       Addr   addrs.AbsProviderConfig
+       Output *providers.Interface
+
+       // 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.Name)
+       if n.Addr.ProviderConfig.Type == "" {
+               // Should never happen
+               panic("EvalGetProvider used with uninitialized provider configuration address")
+       }
+
+       result := ctx.Provider(n.Addr)
        if result == nil {
-               return nil, fmt.Errorf("provider %s not initialized", n.Name)
+               return nil, fmt.Errorf("provider %s not initialized", n.Addr)
        }
 
        if n.Output != nil {
                *n.Output = result
        }
 
-       return nil, nil
-}
-
-// EvalInputProvider is an EvalNode implementation that asks for input
-// for the given provider configurations.
-type EvalInputProvider struct {
-       Name     string
-       Provider *ResourceProvider
-       Config   **ResourceConfig
-}
-
-func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) {
-       // If we already configured this provider, then don't do this again
-       if v := ctx.ProviderInput(n.Name); v != nil {
-               return nil, nil
-       }
-
-       rc := *n.Config
-
-       // Wrap the input into a namespace
-       input := &PrefixUIInput{
-               IdPrefix:    fmt.Sprintf("provider.%s", n.Name),
-               QueryPrefix: fmt.Sprintf("provider.%s.", n.Name),
-               UIInput:     ctx.Input(),
-       }
-
-       // Go through each provider and capture the input necessary
-       // to satisfy it.
-       config, err := (*n.Provider).Input(input, rc)
-       if err != nil {
-               return nil, fmt.Errorf(
-                       "Error configuring %s: %s", n.Name, err)
-       }
-
-       // Set the input that we received so that child modules don't attempt
-       // to ask for input again.
-       if config != nil && len(config.Config) > 0 {
-               // This repository of provider input results on the context doesn't
-               // retain config.ComputedKeys, so we need to filter those out here
-               // in order that later users of this data won't try to use the unknown
-               // value placeholder as if it were a literal value. This map is just
-               // of known values we've been able to complete so far; dynamic stuff
-               // will be merged in by EvalBuildProviderConfig on subsequent
-               // (post-input) walks.
-               confMap := config.Config
-               if config.ComputedKeys != nil {
-                       for _, key := range config.ComputedKeys {
-                               delete(confMap, key)
-                       }
-               }
-
-               ctx.SetProviderInput(n.Name, confMap)
-       } else {
-               ctx.SetProviderInput(n.Name, map[string]interface{}{})
+       if n.Schema != nil {
+               *n.Schema = ctx.ProviderSchema(n.Addr)
        }
 
        return nil, nil