]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/transform_provider.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / transform_provider.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "fmt"
5 "log"
bae9f6d2 6
107c1cdb
ND
7 "github.com/hashicorp/hcl2/hcl"
8 "github.com/hashicorp/terraform/addrs"
9 "github.com/hashicorp/terraform/configs"
bae9f6d2 10 "github.com/hashicorp/terraform/dag"
107c1cdb 11 "github.com/hashicorp/terraform/tfdiags"
bae9f6d2
JC
12)
13
107c1cdb 14func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, config *configs.Config) GraphTransformer {
15c0b25d
AP
15 return GraphTransformMulti(
16 // Add providers from the config
17 &ProviderConfigTransformer{
107c1cdb 18 Config: config,
15c0b25d
AP
19 Providers: providers,
20 Concrete: concrete,
21 },
22 // Add any remaining missing providers
23 &MissingProviderTransformer{
24 Providers: providers,
25 Concrete: concrete,
26 },
27 // Connect the providers
107c1cdb
ND
28 &ProviderTransformer{
29 Config: config,
30 },
15c0b25d
AP
31 // Remove unused providers and proxies
32 &PruneProviderTransformer{},
33 // Connect provider to their parent provider nodes
34 &ParentProviderTransformer{},
35 )
36}
37
bae9f6d2 38// GraphNodeProvider is an interface that nodes that can be a provider
15c0b25d 39// must implement.
107c1cdb
ND
40//
41// ProviderAddr returns the address of the provider configuration this
42// satisfies, which is relative to the path returned by method Path().
43//
15c0b25d 44// Name returns the full name of the provider in the config.
bae9f6d2 45type GraphNodeProvider interface {
107c1cdb
ND
46 GraphNodeSubPath
47 ProviderAddr() addrs.AbsProviderConfig
15c0b25d 48 Name() string
bae9f6d2
JC
49}
50
51// GraphNodeCloseProvider is an interface that nodes that can be a close
52// provider must implement. The CloseProviderName returned is the name of
53// the provider they satisfy.
54type GraphNodeCloseProvider interface {
107c1cdb
ND
55 GraphNodeSubPath
56 CloseProviderAddr() addrs.AbsProviderConfig
bae9f6d2
JC
57}
58
59// GraphNodeProviderConsumer is an interface that nodes that require
107c1cdb
ND
60// a provider must implement. ProvidedBy must return the address of the provider
61// to use, which will be resolved to a configuration either in the same module
62// or in an ancestor module, with the resulting absolute address passed to
63// SetProvider.
bae9f6d2 64type GraphNodeProviderConsumer interface {
107c1cdb
ND
65 // ProvidedBy returns the address of the provider configuration the node
66 // refers to. If the returned "exact" value is true, this address will
67 // be taken exactly. If "exact" is false, a provider configuration from
68 // an ancestor module may be selected instead.
69 ProvidedBy() (addr addrs.AbsProviderConfig, exact bool)
15c0b25d 70 // Set the resolved provider address for this resource.
107c1cdb 71 SetProvider(addrs.AbsProviderConfig)
bae9f6d2
JC
72}
73
74// ProviderTransformer is a GraphTransformer that maps resources to
75// providers within the graph. This will error if there are any resources
76// that don't map to proper resources.
107c1cdb
ND
77type ProviderTransformer struct {
78 Config *configs.Config
79}
bae9f6d2
JC
80
81func (t *ProviderTransformer) Transform(g *Graph) error {
107c1cdb
ND
82 // We need to find a provider configuration address for each resource
83 // either directly represented by a node or referenced by a node in
84 // the graph, and then create graph edges from provider to provider user
85 // so that the providers will get initialized first.
86
87 var diags tfdiags.Diagnostics
88
89 // To start, we'll collect the _requested_ provider addresses for each
90 // node, which we'll then resolve (handling provider inheritence, etc) in
91 // the next step.
92 // Our "requested" map is from graph vertices to string representations of
93 // provider config addresses (for deduping) to requests.
94 type ProviderRequest struct {
95 Addr addrs.AbsProviderConfig
96 Exact bool // If true, inheritence from parent modules is not attempted
97 }
98 requested := map[dag.Vertex]map[string]ProviderRequest{}
99 needConfigured := map[string]addrs.AbsProviderConfig{}
bae9f6d2 100 for _, v := range g.Vertices() {
107c1cdb
ND
101
102 // Does the vertex _directly_ use a provider?
bae9f6d2 103 if pv, ok := v.(GraphNodeProviderConsumer); ok {
107c1cdb 104 requested[v] = make(map[string]ProviderRequest)
15c0b25d 105
107c1cdb
ND
106 p, exact := pv.ProvidedBy()
107 if exact {
108 log.Printf("[TRACE] ProviderTransformer: %s is provided by %s exactly", dag.VertexName(v), p)
109 } else {
110 log.Printf("[TRACE] ProviderTransformer: %s is provided by %s or inherited equivalent", dag.VertexName(v), p)
111 }
112
113 requested[v][p.String()] = ProviderRequest{
114 Addr: p,
115 Exact: exact,
116 }
117
118 // Direct references need the provider configured as well as initialized
119 needConfigured[p.String()] = p
120 }
121 }
122
123 // Now we'll go through all the requested addresses we just collected and
124 // figure out which _actual_ config address each belongs to, after resolving
125 // for provider inheritance and passing.
126 m := providerVertexMap(g)
127 for v, reqs := range requested {
128 for key, req := range reqs {
129 p := req.Addr
15c0b25d
AP
130 target := m[key]
131
107c1cdb 132 _, ok := v.(GraphNodeSubPath)
15c0b25d 133 if !ok && target == nil {
107c1cdb
ND
134 // No target and no path to traverse up from
135 diags = diags.Append(fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p))
136 continue
137 }
138
139 if target != nil {
140 log.Printf("[TRACE] ProviderTransformer: exact match for %s serving %s", p, dag.VertexName(v))
15c0b25d
AP
141 }
142
107c1cdb
ND
143 // if we don't have a provider at this level, walk up the path looking for one,
144 // unless we were told to be exact.
145 if target == nil && !req.Exact {
146 for pp, ok := p.Inherited(); ok; pp, ok = pp.Inherited() {
147 key := pp.String()
148 target = m[key]
149 if target != nil {
150 log.Printf("[TRACE] ProviderTransformer: %s uses inherited configuration %s", dag.VertexName(v), pp)
151 break
152 }
153 log.Printf("[TRACE] ProviderTransformer: looking for %s to serve %s", pp, dag.VertexName(v))
15c0b25d 154 }
107c1cdb 155 }
15c0b25d 156
107c1cdb
ND
157 // If this provider doesn't need to be configured then we can just
158 // stub it out with an init-only provider node, which will just
159 // start up the provider and fetch its schema.
160 if _, exists := needConfigured[key]; target == nil && !exists {
161 stubAddr := p.ProviderConfig.Absolute(addrs.RootModuleInstance)
162 stub := &NodeEvalableProvider{
163 &NodeAbstractProvider{
164 Addr: stubAddr,
165 },
bae9f6d2 166 }
107c1cdb
ND
167 m[stubAddr.String()] = stub
168 log.Printf("[TRACE] ProviderTransformer: creating init-only node for %s", stubAddr)
169 target = stub
170 g.Add(target)
15c0b25d
AP
171 }
172
173 if target == nil {
107c1cdb
ND
174 diags = diags.Append(tfdiags.Sourceless(
175 tfdiags.Error,
176 "Provider configuration not present",
177 fmt.Sprintf(
178 "To work with %s its original provider configuration at %s is required, but it has been removed. This occurs when a provider configuration is removed while objects created by that provider still exist in the state. Re-add the provider configuration to destroy %s, after which you can remove the provider configuration again.",
179 dag.VertexName(v), p, dag.VertexName(v),
180 ),
15c0b25d
AP
181 ))
182 break
183 }
bae9f6d2 184
15c0b25d
AP
185 // see if this in an inherited provider
186 if p, ok := target.(*graphNodeProxyProvider); ok {
187 g.Remove(p)
188 target = p.Target()
107c1cdb 189 key = target.(GraphNodeProvider).ProviderAddr().String()
bae9f6d2 190 }
15c0b25d 191
107c1cdb
ND
192 log.Printf("[DEBUG] ProviderTransformer: %q (%T) needs %s", dag.VertexName(v), v, dag.VertexName(target))
193 if pv, ok := v.(GraphNodeProviderConsumer); ok {
194 pv.SetProvider(target.ProviderAddr())
195 }
15c0b25d 196 g.Connect(dag.BasicEdge(v, target))
bae9f6d2
JC
197 }
198 }
199
107c1cdb 200 return diags.Err()
bae9f6d2
JC
201}
202
203// CloseProviderTransformer is a GraphTransformer that adds nodes to the
204// graph that will close open provider connections that aren't needed anymore.
205// A provider connection is not needed anymore once all depended resources
206// in the graph are evaluated.
207type CloseProviderTransformer struct{}
208
209func (t *CloseProviderTransformer) Transform(g *Graph) error {
210 pm := providerVertexMap(g)
15c0b25d 211 cpm := make(map[string]*graphNodeCloseProvider)
bae9f6d2 212 var err error
bae9f6d2 213
15c0b25d
AP
214 for _, v := range pm {
215 p := v.(GraphNodeProvider)
107c1cdb 216 key := p.ProviderAddr().String()
15c0b25d
AP
217
218 // get the close provider of this type if we alread created it
107c1cdb 219 closer := cpm[key]
15c0b25d
AP
220
221 if closer == nil {
222 // create a closer for this provider type
107c1cdb 223 closer = &graphNodeCloseProvider{Addr: p.ProviderAddr()}
15c0b25d 224 g.Add(closer)
107c1cdb 225 cpm[key] = closer
15c0b25d
AP
226 }
227
228 // Close node depends on the provider itself
229 // this is added unconditionally, so it will connect to all instances
230 // of the provider. Extra edges will be removed by transitive
231 // reduction.
232 g.Connect(dag.BasicEdge(closer, p))
233
234 // connect all the provider's resources to the close node
235 for _, s := range g.UpEdges(p).List() {
236 if _, ok := s.(GraphNodeProviderConsumer); ok {
237 g.Connect(dag.BasicEdge(closer, s))
bae9f6d2
JC
238 }
239 }
240 }
241
242 return err
243}
244
107c1cdb
ND
245// MissingProviderTransformer is a GraphTransformer that adds to the graph
246// a node for each default provider configuration that is referenced by another
247// node but not already present in the graph.
248//
249// These "default" nodes are always added to the root module, regardless of
250// where they are requested. This is important because our inheritance
251// resolution behavior in ProviderTransformer will then treat these as a
252// last-ditch fallback after walking up the tree, rather than preferring them
253// as it would if they were placed in the same module as the requester.
254//
255// This transformer may create extra nodes that are not needed in practice,
256// due to overriding provider configurations in child modules.
257// PruneProviderTransformer can then remove these once ProviderTransformer
258// has resolved all of the inheritence, etc.
bae9f6d2
JC
259type MissingProviderTransformer struct {
260 // Providers is the list of providers we support.
261 Providers []string
262
bae9f6d2
JC
263 // Concrete, if set, overrides how the providers are made.
264 Concrete ConcreteProviderNodeFunc
265}
266
267func (t *MissingProviderTransformer) Transform(g *Graph) error {
268 // Initialize factory
269 if t.Concrete == nil {
270 t.Concrete = func(a *NodeAbstractProvider) dag.Vertex {
271 return a
272 }
273 }
274
15c0b25d 275 var err error
bae9f6d2 276 m := providerVertexMap(g)
15c0b25d 277 for _, v := range g.Vertices() {
bae9f6d2
JC
278 pv, ok := v.(GraphNodeProviderConsumer)
279 if !ok {
280 continue
281 }
282
107c1cdb
ND
283 // For our work here we actually care only about the provider type and
284 // we plan to place all default providers in the root module, and so
285 // it's safe for us to rely on ProvidedBy here rather than waiting for
286 // the later proper resolution of provider inheritance done by
287 // ProviderTransformer.
288 p, _ := pv.ProvidedBy()
289 if p.ProviderConfig.Alias != "" {
290 // We do not create default aliased configurations.
291 log.Println("[TRACE] MissingProviderTransformer: skipping implication of aliased config", p)
292 continue
293 }
bae9f6d2 294
107c1cdb
ND
295 // We're going to create an implicit _default_ configuration for the
296 // referenced provider type in the _root_ module, ignoring all other
297 // aspects of the resource's declared provider address.
298 defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(p.ProviderConfig.Type)
299 key := defaultAddr.String()
15c0b25d 300 provider := m[key]
bae9f6d2 301
15c0b25d 302 if provider != nil {
107c1cdb
ND
303 // There's already an explicit default configuration for this
304 // provider type in the root module, so we have nothing to do.
15c0b25d
AP
305 continue
306 }
bae9f6d2 307
107c1cdb 308 log.Printf("[DEBUG] adding implicit provider configuration %s, implied first by %s", defaultAddr, dag.VertexName(v))
bae9f6d2 309
107c1cdb 310 // create the missing top-level provider
15c0b25d 311 provider = t.Concrete(&NodeAbstractProvider{
107c1cdb
ND
312 Addr: defaultAddr,
313 }).(GraphNodeProvider)
15c0b25d 314
107c1cdb
ND
315 g.Add(provider)
316 m[key] = provider
bae9f6d2
JC
317 }
318
15c0b25d 319 return err
bae9f6d2
JC
320}
321
322// ParentProviderTransformer connects provider nodes to their parents.
323//
324// This works by finding nodes that are both GraphNodeProviders and
325// GraphNodeSubPath. It then connects the providers to their parent
15c0b25d 326// path. The parent provider is always at the root level.
bae9f6d2
JC
327type ParentProviderTransformer struct{}
328
329func (t *ParentProviderTransformer) Transform(g *Graph) error {
15c0b25d
AP
330 pm := providerVertexMap(g)
331 for _, v := range g.Vertices() {
bae9f6d2
JC
332 // Only care about providers
333 pn, ok := v.(GraphNodeProvider)
107c1cdb 334 if !ok {
bae9f6d2
JC
335 continue
336 }
337
107c1cdb
ND
338 // Also require non-empty path, since otherwise we're in the root
339 // module and so cannot have a parent.
340 if len(pn.Path()) <= 1 {
341 continue
bae9f6d2 342 }
bae9f6d2 343
15c0b25d
AP
344 // this provider may be disabled, but we can only get it's name from
345 // the ProviderName string
107c1cdb
ND
346 addr := pn.ProviderAddr()
347 parentAddr, ok := addr.Inherited()
348 if ok {
349 parent := pm[parentAddr.String()]
350 if parent != nil {
351 g.Connect(dag.BasicEdge(v, parent))
352 }
bae9f6d2 353 }
15c0b25d 354 }
bae9f6d2
JC
355 return nil
356}
357
15c0b25d
AP
358// PruneProviderTransformer removes any providers that are not actually used by
359// anything, and provider proxies. This avoids the provider being initialized
360// and configured. This both saves resources but also avoids errors since
361// configuration may imply initialization which may require auth.
bae9f6d2
JC
362type PruneProviderTransformer struct{}
363
364func (t *PruneProviderTransformer) Transform(g *Graph) error {
365 for _, v := range g.Vertices() {
15c0b25d 366 // We only care about providers
107c1cdb
ND
367 _, ok := v.(GraphNodeProvider)
368 if !ok {
bae9f6d2
JC
369 continue
370 }
15c0b25d
AP
371
372 // ProxyProviders will have up edges, but we're now done with them in the graph
373 if _, ok := v.(*graphNodeProxyProvider); ok {
107c1cdb 374 log.Printf("[DEBUG] pruning proxy %s", dag.VertexName(v))
15c0b25d
AP
375 g.Remove(v)
376 }
377
378 // Remove providers with no dependencies.
379 if g.UpEdges(v).Len() == 0 {
107c1cdb 380 log.Printf("[DEBUG] pruning unused %s", dag.VertexName(v))
bae9f6d2
JC
381 g.Remove(v)
382 }
383 }
384
385 return nil
386}
387
107c1cdb
ND
388func providerVertexMap(g *Graph) map[string]GraphNodeProvider {
389 m := make(map[string]GraphNodeProvider)
bae9f6d2
JC
390 for _, v := range g.Vertices() {
391 if pv, ok := v.(GraphNodeProvider); ok {
107c1cdb
ND
392 addr := pv.ProviderAddr()
393 m[addr.String()] = pv
bae9f6d2
JC
394 }
395 }
396
397 return m
398}
399
107c1cdb
ND
400func closeProviderVertexMap(g *Graph) map[string]GraphNodeCloseProvider {
401 m := make(map[string]GraphNodeCloseProvider)
bae9f6d2
JC
402 for _, v := range g.Vertices() {
403 if pv, ok := v.(GraphNodeCloseProvider); ok {
107c1cdb
ND
404 addr := pv.CloseProviderAddr()
405 m[addr.String()] = pv
bae9f6d2
JC
406 }
407 }
408
409 return m
410}
411
412type graphNodeCloseProvider struct {
107c1cdb 413 Addr addrs.AbsProviderConfig
bae9f6d2
JC
414}
415
107c1cdb
ND
416var (
417 _ GraphNodeCloseProvider = (*graphNodeCloseProvider)(nil)
418)
419
bae9f6d2 420func (n *graphNodeCloseProvider) Name() string {
107c1cdb
ND
421 return n.Addr.String() + " (close)"
422}
423
424// GraphNodeSubPath impl.
425func (n *graphNodeCloseProvider) Path() addrs.ModuleInstance {
426 return n.Addr.Module
bae9f6d2
JC
427}
428
429// GraphNodeEvalable impl.
430func (n *graphNodeCloseProvider) EvalTree() EvalNode {
107c1cdb 431 return CloseProviderEvalTree(n.Addr)
bae9f6d2
JC
432}
433
434// GraphNodeDependable impl.
435func (n *graphNodeCloseProvider) DependableName() []string {
436 return []string{n.Name()}
437}
438
107c1cdb
ND
439func (n *graphNodeCloseProvider) CloseProviderAddr() addrs.AbsProviderConfig {
440 return n.Addr
bae9f6d2
JC
441}
442
443// GraphNodeDotter impl.
444func (n *graphNodeCloseProvider) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
445 if !opts.Verbose {
446 return nil
447 }
448 return &dag.DotNode{
449 Name: name,
450 Attrs: map[string]string{
451 "label": n.Name(),
452 "shape": "diamond",
453 },
454 }
455}
456
457// RemovableIfNotTargeted
458func (n *graphNodeCloseProvider) RemoveIfNotTargeted() bool {
459 // We need to add this so that this node will be removed if
460 // it isn't targeted or a dependency of a target.
461 return true
462}
463
15c0b25d
AP
464// graphNodeProxyProvider is a GraphNodeProvider implementation that is used to
465// store the name and value of a provider node for inheritance between modules.
466// These nodes are only used to store the data while loading the provider
467// configurations, and are removed after all the resources have been connected
468// to their providers.
469type graphNodeProxyProvider struct {
107c1cdb
ND
470 addr addrs.AbsProviderConfig
471 target GraphNodeProvider
472}
473
474var (
475 _ GraphNodeProvider = (*graphNodeProxyProvider)(nil)
476)
477
478func (n *graphNodeProxyProvider) ProviderAddr() addrs.AbsProviderConfig {
479 return n.addr
15c0b25d
AP
480}
481
107c1cdb
ND
482func (n *graphNodeProxyProvider) Path() addrs.ModuleInstance {
483 return n.addr.Module
15c0b25d
AP
484}
485
486func (n *graphNodeProxyProvider) Name() string {
107c1cdb 487 return n.addr.String() + " (proxy)"
15c0b25d
AP
488}
489
490// find the concrete provider instance
491func (n *graphNodeProxyProvider) Target() GraphNodeProvider {
492 switch t := n.target.(type) {
493 case *graphNodeProxyProvider:
494 return t.Target()
495 default:
496 return n.target
497 }
498}
499
500// ProviderConfigTransformer adds all provider nodes from the configuration and
501// attaches the configs.
502type ProviderConfigTransformer struct {
503 Providers []string
504 Concrete ConcreteProviderNodeFunc
505
506 // each provider node is stored here so that the proxy nodes can look up
507 // their targets by name.
508 providers map[string]GraphNodeProvider
509 // record providers that can be overriden with a proxy
510 proxiable map[string]bool
511
107c1cdb
ND
512 // Config is the root node of the configuration tree to add providers from.
513 Config *configs.Config
bae9f6d2
JC
514}
515
15c0b25d 516func (t *ProviderConfigTransformer) Transform(g *Graph) error {
107c1cdb
ND
517 // If no configuration is given, we don't do anything
518 if t.Config == nil {
15c0b25d
AP
519 return nil
520 }
521
15c0b25d
AP
522 t.providers = make(map[string]GraphNodeProvider)
523 t.proxiable = make(map[string]bool)
524
525 // Start the transformation process
107c1cdb 526 if err := t.transform(g, t.Config); err != nil {
15c0b25d
AP
527 return err
528 }
529
530 // finally attach the configs to the new nodes
531 return t.attachProviderConfigs(g)
bae9f6d2
JC
532}
533
107c1cdb 534func (t *ProviderConfigTransformer) transform(g *Graph, c *configs.Config) error {
15c0b25d 535 // If no config, do nothing
107c1cdb 536 if c == nil {
15c0b25d
AP
537 return nil
538 }
539
540 // Add our resources
107c1cdb 541 if err := t.transformSingle(g, c); err != nil {
15c0b25d
AP
542 return err
543 }
544
545 // Transform all the children.
107c1cdb
ND
546 for _, cc := range c.Children {
547 if err := t.transform(g, cc); err != nil {
15c0b25d
AP
548 return err
549 }
550 }
551 return nil
552}
553
107c1cdb
ND
554func (t *ProviderConfigTransformer) transformSingle(g *Graph, c *configs.Config) error {
555 // Get the module associated with this configuration tree node
556 mod := c.Module
557 staticPath := c.Path
558
559 // We actually need a dynamic module path here, but we've not yet updated
560 // our graph builders enough to support expansion of module calls with
561 // "count" and "for_each" set, so for now we'll shim this by converting to
562 // a dynamic path with no keys. At the time of writing this is the only
563 // possible kind of dynamic path anyway.
564 path := make(addrs.ModuleInstance, len(staticPath))
565 for i, name := range staticPath {
566 path[i] = addrs.ModuleInstanceStep{
567 Name: name,
568 }
15c0b25d
AP
569 }
570
571 // add all providers from the configuration
107c1cdb
ND
572 for _, p := range mod.ProviderConfigs {
573 relAddr := p.Addr()
574 addr := relAddr.Absolute(path)
15c0b25d 575
107c1cdb
ND
576 abstract := &NodeAbstractProvider{
577 Addr: addr,
578 }
579 var v dag.Vertex
580 if t.Concrete != nil {
581 v = t.Concrete(abstract)
582 } else {
583 v = abstract
584 }
15c0b25d
AP
585
586 // Add it to the graph
587 g.Add(v)
107c1cdb
ND
588 key := addr.String()
589 t.providers[key] = v.(GraphNodeProvider)
590
591 // A provider configuration is "proxyable" if its configuration is
592 // entirely empty. This means it's standing in for a provider
593 // configuration that must be passed in from the parent module.
594 // We decide this by evaluating the config with an empty schema;
595 // if this succeeds, then we know there's nothing in the body.
596 _, diags := p.Config.Content(&hcl.BodySchema{})
597 t.proxiable[key] = !diags.HasErrors()
15c0b25d
AP
598 }
599
600 // Now replace the provider nodes with proxy nodes if a provider was being
601 // passed in, and create implicit proxies if there was no config. Any extra
602 // proxies will be removed in the prune step.
107c1cdb 603 return t.addProxyProviders(g, c)
15c0b25d
AP
604}
605
107c1cdb
ND
606func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, c *configs.Config) error {
607 path := c.Path
15c0b25d
AP
608
609 // can't add proxies at the root
610 if len(path) == 0 {
611 return nil
612 }
613
107c1cdb
ND
614 parentPath, callAddr := path.Call()
615 parent := c.Parent
15c0b25d
AP
616 if parent == nil {
617 return nil
618 }
619
107c1cdb
ND
620 callName := callAddr.Name
621 var parentCfg *configs.ModuleCall
622 for name, mod := range parent.Module.ModuleCalls {
623 if name == callName {
15c0b25d
AP
624 parentCfg = mod
625 break
626 }
627 }
628
107c1cdb
ND
629 // We currently don't support count/for_each for modules and so we must
630 // shim our path and parentPath into module instances here so that the
631 // rest of Terraform can behave as if we do. This shimming should be
632 // removed later as part of implementing count/for_each for modules.
633 instPath := make(addrs.ModuleInstance, len(path))
634 for i, name := range path {
635 instPath[i] = addrs.ModuleInstanceStep{Name: name}
636 }
637 parentInstPath := make(addrs.ModuleInstance, len(parentPath))
638 for i, name := range parentPath {
639 parentInstPath[i] = addrs.ModuleInstanceStep{Name: name}
640 }
641
15c0b25d
AP
642 if parentCfg == nil {
643 // this can't really happen during normal execution.
107c1cdb 644 return fmt.Errorf("parent module config not found for %s", c.Path.String())
15c0b25d
AP
645 }
646
647 // Go through all the providers the parent is passing in, and add proxies to
648 // the parent provider nodes.
107c1cdb
ND
649 for _, pair := range parentCfg.Providers {
650 fullAddr := pair.InChild.Addr().Absolute(instPath)
651 fullParentAddr := pair.InParent.Addr().Absolute(parentInstPath)
652 fullName := fullAddr.String()
653 fullParentName := fullParentAddr.String()
15c0b25d
AP
654
655 parentProvider := t.providers[fullParentName]
656
657 if parentProvider == nil {
658 return fmt.Errorf("missing provider %s", fullParentName)
659 }
660
661 proxy := &graphNodeProxyProvider{
107c1cdb
ND
662 addr: fullAddr,
663 target: parentProvider,
15c0b25d
AP
664 }
665
666 concreteProvider := t.providers[fullName]
667
668 // replace the concrete node with the provider passed in
669 if concreteProvider != nil && t.proxiable[fullName] {
670 g.Replace(concreteProvider, proxy)
671 t.providers[fullName] = proxy
672 continue
673 }
674
107c1cdb
ND
675 // aliased configurations can't be implicitly passed in
676 if fullAddr.ProviderConfig.Alias != "" {
15c0b25d
AP
677 continue
678 }
679
680 // There was no concrete provider, so add this as an implicit provider.
681 // The extra proxy will be pruned later if it's unused.
682 g.Add(proxy)
683 t.providers[fullName] = proxy
684 }
685 return nil
686}
687
688func (t *ProviderConfigTransformer) attachProviderConfigs(g *Graph) error {
689 for _, v := range g.Vertices() {
690 // Only care about GraphNodeAttachProvider implementations
691 apn, ok := v.(GraphNodeAttachProvider)
692 if !ok {
693 continue
694 }
695
696 // Determine what we're looking for
107c1cdb 697 addr := apn.ProviderAddr()
15c0b25d
AP
698
699 // Get the configuration.
107c1cdb
ND
700 mc := t.Config.DescendentForInstance(addr.Module)
701 if mc == nil {
702 log.Printf("[TRACE] ProviderConfigTransformer: no configuration available for %s", addr.String())
15c0b25d
AP
703 continue
704 }
705
706 // Go through the provider configs to find the matching config
107c1cdb
ND
707 for _, p := range mc.Module.ProviderConfigs {
708 if p.Name == addr.ProviderConfig.Type && p.Alias == addr.ProviderConfig.Alias {
709 log.Printf("[TRACE] ProviderConfigTransformer: attaching to %q provider configuration from %s", dag.VertexName(v), p.DeclRange)
15c0b25d
AP
710 apn.AttachProvider(p)
711 break
712 }
713 }
714 }
715
716 return nil
bae9f6d2 717}