7 "github.com/hashicorp/hcl2/hcl"
9 "github.com/hashicorp/terraform/addrs"
10 "github.com/hashicorp/terraform/configs"
11 "github.com/hashicorp/terraform/providers"
12 "github.com/hashicorp/terraform/tfdiags"
15 func buildProviderConfig(ctx EvalContext, addr addrs.ProviderConfig, config *configs.Provider) hcl.Body {
16 var configBody hcl.Body
18 configBody = config.Config
21 var inputBody hcl.Body
22 inputConfig := ctx.ProviderInput(addr)
23 if len(inputConfig) > 0 {
24 inputBody = configs.SynthBody("<input-prompt>", inputConfig)
28 case configBody != nil && inputBody != nil:
29 log.Printf("[TRACE] buildProviderConfig for %s: merging explicit config and input", addr)
30 // Note that the inputBody is the _base_ here, because configs.MergeBodies
31 // expects the base have all of the required fields, while these are
32 // forced to be optional for the override. The input process should
33 // guarantee that we have a value for each of the required arguments and
34 // that in practice the sets of attributes in each body will be
36 return configs.MergeBodies(inputBody, configBody)
37 case configBody != nil:
38 log.Printf("[TRACE] buildProviderConfig for %s: using explicit config only", addr)
40 case inputBody != nil:
41 log.Printf("[TRACE] buildProviderConfig for %s: using input only", addr)
44 log.Printf("[TRACE] buildProviderConfig for %s: no configuration at all", addr)
45 return hcl.EmptyBody()
49 // EvalConfigProvider is an EvalNode implementation that configures
50 // a provider that is already initialized and retrieved.
51 type EvalConfigProvider struct {
52 Addr addrs.ProviderConfig
53 Provider *providers.Interface
54 Config *configs.Provider
57 func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
58 if n.Provider == nil {
59 return nil, fmt.Errorf("EvalConfigProvider Provider is nil")
62 var diags tfdiags.Diagnostics
63 provider := *n.Provider
66 configBody := buildProviderConfig(ctx, n.Addr, config)
68 resp := provider.GetSchema()
69 diags = diags.Append(resp.Diagnostics)
70 if diags.HasErrors() {
71 return nil, diags.NonFatalErr()
74 configSchema := resp.Provider.Block
75 configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey)
76 diags = diags.Append(evalDiags)
77 if evalDiags.HasErrors() {
78 return nil, diags.NonFatalErr()
81 configDiags := ctx.ConfigureProvider(n.Addr, configVal)
82 configDiags = configDiags.InConfigBody(configBody)
84 return nil, configDiags.ErrWithWarnings()
87 // EvalInitProvider is an EvalNode implementation that initializes a provider
88 // and returns nothing. The provider can be retrieved again with the
89 // EvalGetProvider node.
90 type EvalInitProvider struct {
92 Addr addrs.ProviderConfig
95 func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) {
96 return ctx.InitProvider(n.TypeName, n.Addr)
99 // EvalCloseProvider is an EvalNode implementation that closes provider
100 // connections that aren't needed anymore.
101 type EvalCloseProvider struct {
102 Addr addrs.ProviderConfig
105 func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) {
106 ctx.CloseProvider(n.Addr)
110 // EvalGetProvider is an EvalNode implementation that retrieves an already
111 // initialized provider instance for the given name.
113 // Unlike most eval nodes, this takes an _absolute_ provider configuration,
114 // because providers can be passed into and inherited between modules.
115 // Resource nodes must therefore know the absolute path of the provider they
116 // will use, which is usually accomplished by implementing
117 // interface GraphNodeProviderConsumer.
118 type EvalGetProvider struct {
119 Addr addrs.AbsProviderConfig
120 Output *providers.Interface
122 // If non-nil, Schema will be updated after eval to refer to the
123 // schema of the provider.
124 Schema **ProviderSchema
127 func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) {
128 if n.Addr.ProviderConfig.Type == "" {
129 // Should never happen
130 panic("EvalGetProvider used with uninitialized provider configuration address")
133 result := ctx.Provider(n.Addr)
135 return nil, fmt.Errorf("provider %s not initialized", n.Addr)
143 *n.Schema = ctx.ProviderSchema(n.Addr)