aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/transform_provider.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_provider.go574
1 files changed, 400 insertions, 174 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go b/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go
index b9695d5..c4772b4 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go
@@ -1,19 +1,46 @@
1package terraform 1package terraform
2 2
3import ( 3import (
4 "errors"
4 "fmt" 5 "fmt"
5 "log" 6 "log"
6 "strings" 7 "strings"
7 8
8 "github.com/hashicorp/go-multierror" 9 "github.com/hashicorp/go-multierror"
10 "github.com/hashicorp/terraform/config"
11 "github.com/hashicorp/terraform/config/module"
9 "github.com/hashicorp/terraform/dag" 12 "github.com/hashicorp/terraform/dag"
10) 13)
11 14
15func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, mod *module.Tree) GraphTransformer {
16 return GraphTransformMulti(
17 // Add providers from the config
18 &ProviderConfigTransformer{
19 Module: mod,
20 Providers: providers,
21 Concrete: concrete,
22 },
23 // Add any remaining missing providers
24 &MissingProviderTransformer{
25 Providers: providers,
26 Concrete: concrete,
27 },
28 // Connect the providers
29 &ProviderTransformer{},
30 // Remove unused providers and proxies
31 &PruneProviderTransformer{},
32 // Connect provider to their parent provider nodes
33 &ParentProviderTransformer{},
34 )
35}
36
12// GraphNodeProvider is an interface that nodes that can be a provider 37// GraphNodeProvider is an interface that nodes that can be a provider
13// must implement. The ProviderName returned is the name of the provider 38// must implement.
14// they satisfy. 39// ProviderName returns the name of the provider this satisfies.
40// Name returns the full name of the provider in the config.
15type GraphNodeProvider interface { 41type GraphNodeProvider interface {
16 ProviderName() string 42 ProviderName() string
43 Name() string
17} 44}
18 45
19// GraphNodeCloseProvider is an interface that nodes that can be a close 46// GraphNodeCloseProvider is an interface that nodes that can be a close
@@ -25,9 +52,12 @@ type GraphNodeCloseProvider interface {
25 52
26// GraphNodeProviderConsumer is an interface that nodes that require 53// GraphNodeProviderConsumer is an interface that nodes that require
27// a provider must implement. ProvidedBy must return the name of the provider 54// a provider must implement. ProvidedBy must return the name of the provider
28// to use. 55// to use. This may be a provider by type, type.alias or a fully resolved
56// provider name
29type GraphNodeProviderConsumer interface { 57type GraphNodeProviderConsumer interface {
30 ProvidedBy() []string 58 ProvidedBy() string
59 // Set the resolved provider address for this resource.
60 SetProvider(string)
31} 61}
32 62
33// ProviderTransformer is a GraphTransformer that maps resources to 63// ProviderTransformer is a GraphTransformer that maps resources to
@@ -41,18 +71,52 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
41 m := providerVertexMap(g) 71 m := providerVertexMap(g)
42 for _, v := range g.Vertices() { 72 for _, v := range g.Vertices() {
43 if pv, ok := v.(GraphNodeProviderConsumer); ok { 73 if pv, ok := v.(GraphNodeProviderConsumer); ok {
44 for _, p := range pv.ProvidedBy() { 74 p := pv.ProvidedBy()
45 target := m[providerMapKey(p, pv)] 75
46 if target == nil { 76 key := providerMapKey(p, pv)
47 println(fmt.Sprintf("%#v\n\n%#v", m, providerMapKey(p, pv))) 77 target := m[key]
48 err = multierror.Append(err, fmt.Errorf( 78
49 "%s: provider %s couldn't be found", 79 sp, ok := pv.(GraphNodeSubPath)
50 dag.VertexName(v), p)) 80 if !ok && target == nil {
51 continue 81 // no target, and no path to walk up
82 err = multierror.Append(err, fmt.Errorf(
83 "%s: provider %s couldn't be found",
84 dag.VertexName(v), p))
85 break
86 }
87
88 // if we don't have a provider at this level, walk up the path looking for one
89 for i := 1; target == nil; i++ {
90 path := normalizeModulePath(sp.Path())
91 if len(path) < i {
92 break
93 }
94
95 key = ResolveProviderName(p, path[:len(path)-i])
96 target = m[key]
97 if target != nil {
98 break
52 } 99 }
100 }
101
102 if target == nil {
103 err = multierror.Append(err, fmt.Errorf(
104 "%s: configuration for %s is not present; a provider configuration block is required for all operations",
105 dag.VertexName(v), p,
106 ))
107 break
108 }
53 109
54 g.Connect(dag.BasicEdge(v, target)) 110 // see if this in an inherited provider
111 if p, ok := target.(*graphNodeProxyProvider); ok {
112 g.Remove(p)
113 target = p.Target()
114 key = target.(GraphNodeProvider).Name()
55 } 115 }
116
117 log.Printf("[DEBUG] resource %s using provider %s", dag.VertexName(pv), key)
118 pv.SetProvider(key)
119 g.Connect(dag.BasicEdge(v, target))
56 } 120 }
57 } 121 }
58 122
@@ -67,36 +131,32 @@ type CloseProviderTransformer struct{}
67 131
68func (t *CloseProviderTransformer) Transform(g *Graph) error { 132func (t *CloseProviderTransformer) Transform(g *Graph) error {
69 pm := providerVertexMap(g) 133 pm := providerVertexMap(g)
70 cpm := closeProviderVertexMap(g) 134 cpm := make(map[string]*graphNodeCloseProvider)
71 var err error 135 var err error
72 for _, v := range g.Vertices() {
73 if pv, ok := v.(GraphNodeProviderConsumer); ok {
74 for _, p := range pv.ProvidedBy() {
75 key := p
76 source := cpm[key]
77
78 if source == nil {
79 // Create a new graphNodeCloseProvider and add it to the graph
80 source = &graphNodeCloseProvider{ProviderNameValue: p}
81 g.Add(source)
82
83 // Close node needs to depend on provider
84 provider, ok := pm[key]
85 if !ok {
86 err = multierror.Append(err, fmt.Errorf(
87 "%s: provider %s couldn't be found for closing",
88 dag.VertexName(v), p))
89 continue
90 }
91 g.Connect(dag.BasicEdge(source, provider))
92
93 // Make sure we also add the new graphNodeCloseProvider to the map
94 // so we don't create and add any duplicate graphNodeCloseProviders.
95 cpm[key] = source
96 }
97 136
98 // Close node depends on all nodes provided by the provider 137 for _, v := range pm {
99 g.Connect(dag.BasicEdge(source, v)) 138 p := v.(GraphNodeProvider)
139
140 // get the close provider of this type if we alread created it
141 closer := cpm[p.Name()]
142
143 if closer == nil {
144 // create a closer for this provider type
145 closer = &graphNodeCloseProvider{ProviderNameValue: p.Name()}
146 g.Add(closer)
147 cpm[p.Name()] = closer
148 }
149
150 // Close node depends on the provider itself
151 // this is added unconditionally, so it will connect to all instances
152 // of the provider. Extra edges will be removed by transitive
153 // reduction.
154 g.Connect(dag.BasicEdge(closer, p))
155
156 // connect all the provider's resources to the close node
157 for _, s := range g.UpEdges(p).List() {
158 if _, ok := s.(GraphNodeProviderConsumer); ok {
159 g.Connect(dag.BasicEdge(closer, s))
100 } 160 }
101 } 161 }
102 } 162 }
@@ -104,18 +164,14 @@ func (t *CloseProviderTransformer) Transform(g *Graph) error {
104 return err 164 return err
105} 165}
106 166
107// MissingProviderTransformer is a GraphTransformer that adds nodes 167// MissingProviderTransformer is a GraphTransformer that adds nodes for all
108// for missing providers into the graph. Specifically, it creates provider 168// required providers into the graph. Specifically, it creates provider
109// configuration nodes for all the providers that we support. These are 169// configuration nodes for all the providers that we support. These are pruned
110// pruned later during an optimization pass. 170// later during an optimization pass.
111type MissingProviderTransformer struct { 171type MissingProviderTransformer struct {
112 // Providers is the list of providers we support. 172 // Providers is the list of providers we support.
113 Providers []string 173 Providers []string
114 174
115 // AllowAny will not check that a provider is supported before adding
116 // it to the graph.
117 AllowAny bool
118
119 // Concrete, if set, overrides how the providers are made. 175 // Concrete, if set, overrides how the providers are made.
120 Concrete ConcreteProviderNodeFunc 176 Concrete ConcreteProviderNodeFunc
121} 177}
@@ -128,99 +184,57 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
128 } 184 }
129 } 185 }
130 186
131 // Create a set of our supported providers 187 var err error
132 supported := make(map[string]struct{}, len(t.Providers))
133 for _, v := range t.Providers {
134 supported[v] = struct{}{}
135 }
136
137 // Get the map of providers we already have in our graph
138 m := providerVertexMap(g) 188 m := providerVertexMap(g)
139 189 for _, v := range g.Vertices() {
140 // Go through all the provider consumers and make sure we add
141 // that provider if it is missing. We use a for loop here instead
142 // of "range" since we'll modify check as we go to add more to check.
143 check := g.Vertices()
144 for i := 0; i < len(check); i++ {
145 v := check[i]
146
147 pv, ok := v.(GraphNodeProviderConsumer) 190 pv, ok := v.(GraphNodeProviderConsumer)
148 if !ok { 191 if !ok {
149 continue 192 continue
150 } 193 }
151 194
152 // If this node has a subpath, then we use that as a prefix 195 p := pv.ProvidedBy()
153 // into our map to check for an existing provider. 196 // this may be the resolved provider from the state, so we need to get
154 var path []string 197 // the base provider name.
155 if sp, ok := pv.(GraphNodeSubPath); ok { 198 parts := strings.SplitAfter(p, "provider.")
156 raw := normalizeModulePath(sp.Path()) 199 p = parts[len(parts)-1]
157 if len(raw) > len(rootModulePath) {
158 path = raw
159 }
160 }
161 200
162 for _, p := range pv.ProvidedBy() { 201 key := ResolveProviderName(p, nil)
163 key := providerMapKey(p, pv) 202 provider := m[key]
164 if _, ok := m[key]; ok {
165 // This provider already exists as a configure node
166 continue
167 }
168 203
169 // If the provider has an alias in it, we just want the type 204 // we already have it
170 ptype := p 205 if provider != nil {
171 if idx := strings.IndexRune(p, '.'); idx != -1 { 206 continue
172 ptype = p[:idx] 207 }
173 }
174 208
175 if !t.AllowAny { 209 // we don't implicitly create aliased providers
176 if _, ok := supported[ptype]; !ok { 210 if strings.Contains(p, ".") {
177 // If we don't support the provider type, skip it. 211 log.Println("[DEBUG] not adding missing provider alias:", p)
178 // Validation later will catch this as an error. 212 continue
179 continue 213 }
180 }
181 }
182 214
183 // Add the missing provider node to the graph 215 log.Println("[DEBUG] adding missing provider:", p)
184 v := t.Concrete(&NodeAbstractProvider{
185 NameValue: p,
186 PathValue: path,
187 }).(dag.Vertex)
188 if len(path) > 0 {
189 // We'll need the parent provider as well, so let's
190 // add a dummy node to check to make sure that we add
191 // that parent provider.
192 check = append(check, &graphNodeProviderConsumerDummy{
193 ProviderValue: p,
194 PathValue: path[:len(path)-1],
195 })
196 }
197 216
198 m[key] = g.Add(v) 217 // create the misisng top-level provider
199 } 218 provider = t.Concrete(&NodeAbstractProvider{
219 NameValue: p,
220 }).(dag.Vertex)
221
222 m[key] = g.Add(provider)
200 } 223 }
201 224
202 return nil 225 return err
203} 226}
204 227
205// ParentProviderTransformer connects provider nodes to their parents. 228// ParentProviderTransformer connects provider nodes to their parents.
206// 229//
207// This works by finding nodes that are both GraphNodeProviders and 230// This works by finding nodes that are both GraphNodeProviders and
208// GraphNodeSubPath. It then connects the providers to their parent 231// GraphNodeSubPath. It then connects the providers to their parent
209// path. 232// path. The parent provider is always at the root level.
210type ParentProviderTransformer struct{} 233type ParentProviderTransformer struct{}
211 234
212func (t *ParentProviderTransformer) Transform(g *Graph) error { 235func (t *ParentProviderTransformer) Transform(g *Graph) error {
213 // Make a mapping of path to dag.Vertex, where path is: "path.name" 236 pm := providerVertexMap(g)
214 m := make(map[string]dag.Vertex) 237 for _, v := range g.Vertices() {
215
216 // Also create a map that maps a provider to its parent
217 parentMap := make(map[dag.Vertex]string)
218 for _, raw := range g.Vertices() {
219 // If it is the flat version, then make it the non-flat version.
220 // We eventually want to get rid of the flat version entirely so
221 // this is a stop-gap while it still exists.
222 var v dag.Vertex = raw
223
224 // Only care about providers 238 // Only care about providers
225 pn, ok := v.(GraphNodeProvider) 239 pn, ok := v.(GraphNodeProvider)
226 if !ok || pn.ProviderName() == "" { 240 if !ok || pn.ProviderName() == "" {
@@ -228,53 +242,48 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error {
228 } 242 }
229 243
230 // Also require a subpath, if there is no subpath then we 244 // Also require a subpath, if there is no subpath then we
231 // just totally ignore it. The expectation of this transform is 245 // can't have a parent.
232 // that it is used with a graph builder that is already flattened. 246 if pn, ok := v.(GraphNodeSubPath); ok {
233 var path []string 247 if len(normalizeModulePath(pn.Path())) <= 1 {
234 if pn, ok := raw.(GraphNodeSubPath); ok { 248 continue
235 path = pn.Path() 249 }
236 }
237 path = normalizeModulePath(path)
238
239 // Build the key with path.name i.e. "child.subchild.aws"
240 key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
241 m[key] = raw
242
243 // Determine the parent if we're non-root. This is length 1 since
244 // the 0 index should be "root" since we normalize above.
245 if len(path) > 1 {
246 path = path[:len(path)-1]
247 key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
248 parentMap[raw] = key
249 } 250 }
250 }
251 251
252 // Connect! 252 // this provider may be disabled, but we can only get it's name from
253 for v, key := range parentMap { 253 // the ProviderName string
254 if parent, ok := m[key]; ok { 254 name := ResolveProviderName(strings.SplitN(pn.ProviderName(), " ", 2)[0], nil)
255 parent := pm[name]
256 if parent != nil {
255 g.Connect(dag.BasicEdge(v, parent)) 257 g.Connect(dag.BasicEdge(v, parent))
256 } 258 }
257 }
258 259
260 }
259 return nil 261 return nil
260} 262}
261 263
262// PruneProviderTransformer is a GraphTransformer that prunes all the 264// PruneProviderTransformer removes any providers that are not actually used by
263// providers that aren't needed from the graph. A provider is unneeded if 265// anything, and provider proxies. This avoids the provider being initialized
264// no resource or module is using that provider. 266// and configured. This both saves resources but also avoids errors since
267// configuration may imply initialization which may require auth.
265type PruneProviderTransformer struct{} 268type PruneProviderTransformer struct{}
266 269
267func (t *PruneProviderTransformer) Transform(g *Graph) error { 270func (t *PruneProviderTransformer) Transform(g *Graph) error {
268 for _, v := range g.Vertices() { 271 for _, v := range g.Vertices() {
269 // We only care about the providers 272 // We only care about providers
270 if pn, ok := v.(GraphNodeProvider); !ok || pn.ProviderName() == "" { 273 pn, ok := v.(GraphNodeProvider)
274 if !ok || pn.ProviderName() == "" {
271 continue 275 continue
272 } 276 }
273 // Does anything depend on this? If not, then prune it. 277
274 if s := g.UpEdges(v); s.Len() == 0 { 278 // ProxyProviders will have up edges, but we're now done with them in the graph
275 if nv, ok := v.(dag.NamedVertex); ok { 279 if _, ok := v.(*graphNodeProxyProvider); ok {
276 log.Printf("[DEBUG] Pruning provider with no dependencies: %s", nv.Name()) 280 log.Printf("[DEBUG] pruning proxy provider %s", dag.VertexName(v))
277 } 281 g.Remove(v)
282 }
283
284 // Remove providers with no dependencies.
285 if g.UpEdges(v).Len() == 0 {
286 log.Printf("[DEBUG] pruning unused provider %s", dag.VertexName(v))
278 g.Remove(v) 287 g.Remove(v)
279 } 288 }
280 } 289 }
@@ -285,23 +294,26 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error {
285// providerMapKey is a helper that gives us the key to use for the 294// providerMapKey is a helper that gives us the key to use for the
286// maps returned by things such as providerVertexMap. 295// maps returned by things such as providerVertexMap.
287func providerMapKey(k string, v dag.Vertex) string { 296func providerMapKey(k string, v dag.Vertex) string {
288 pathPrefix := "" 297 if strings.Contains(k, "provider.") {
289 if sp, ok := v.(GraphNodeSubPath); ok { 298 // this is already resolved
290 raw := normalizeModulePath(sp.Path()) 299 return k
291 if len(raw) > len(rootModulePath) {
292 pathPrefix = modulePrefixStr(raw) + "."
293 }
294 } 300 }
295 301
296 return pathPrefix + k 302 // we create a dummy provider to
303 var path []string
304 if sp, ok := v.(GraphNodeSubPath); ok {
305 path = normalizeModulePath(sp.Path())
306 }
307 return ResolveProviderName(k, path)
297} 308}
298 309
299func providerVertexMap(g *Graph) map[string]dag.Vertex { 310func providerVertexMap(g *Graph) map[string]dag.Vertex {
300 m := make(map[string]dag.Vertex) 311 m := make(map[string]dag.Vertex)
301 for _, v := range g.Vertices() { 312 for _, v := range g.Vertices() {
302 if pv, ok := v.(GraphNodeProvider); ok { 313 if pv, ok := v.(GraphNodeProvider); ok {
303 key := providerMapKey(pv.ProviderName(), v) 314 // TODO: The Name may have meta info, like " (disabled)"
304 m[key] = v 315 name := strings.SplitN(pv.Name(), " ", 2)[0]
316 m[name] = v
305 } 317 }
306 } 318 }
307 319
@@ -324,7 +336,7 @@ type graphNodeCloseProvider struct {
324} 336}
325 337
326func (n *graphNodeCloseProvider) Name() string { 338func (n *graphNodeCloseProvider) Name() string {
327 return fmt.Sprintf("provider.%s (close)", n.ProviderNameValue) 339 return n.ProviderNameValue + " (close)"
328} 340}
329 341
330// GraphNodeEvalable impl. 342// GraphNodeEvalable impl.
@@ -362,19 +374,233 @@ func (n *graphNodeCloseProvider) RemoveIfNotTargeted() bool {
362 return true 374 return true
363} 375}
364 376
365// graphNodeProviderConsumerDummy is a struct that never enters the real 377// graphNodeProxyProvider is a GraphNodeProvider implementation that is used to
366// graph (though it could to no ill effect). It implements 378// store the name and value of a provider node for inheritance between modules.
367// GraphNodeProviderConsumer and GraphNodeSubpath as a way to force 379// These nodes are only used to store the data while loading the provider
368// certain transformations. 380// configurations, and are removed after all the resources have been connected
369type graphNodeProviderConsumerDummy struct { 381// to their providers.
370 ProviderValue string 382type graphNodeProxyProvider struct {
371 PathValue []string 383 nameValue string
384 path []string
385 target GraphNodeProvider
386}
387
388func (n *graphNodeProxyProvider) ProviderName() string {
389 return n.Target().ProviderName()
390}
391
392func (n *graphNodeProxyProvider) Name() string {
393 return ResolveProviderName(n.nameValue, n.path)
394}
395
396// find the concrete provider instance
397func (n *graphNodeProxyProvider) Target() GraphNodeProvider {
398 switch t := n.target.(type) {
399 case *graphNodeProxyProvider:
400 return t.Target()
401 default:
402 return n.target
403 }
404}
405
406// ProviderConfigTransformer adds all provider nodes from the configuration and
407// attaches the configs.
408type ProviderConfigTransformer struct {
409 Providers []string
410 Concrete ConcreteProviderNodeFunc
411
412 // each provider node is stored here so that the proxy nodes can look up
413 // their targets by name.
414 providers map[string]GraphNodeProvider
415 // record providers that can be overriden with a proxy
416 proxiable map[string]bool
417
418 // Module is the module to add resources from.
419 Module *module.Tree
372} 420}
373 421
374func (n *graphNodeProviderConsumerDummy) Path() []string { 422func (t *ProviderConfigTransformer) Transform(g *Graph) error {
375 return n.PathValue 423 // If no module is given, we don't do anything
424 if t.Module == nil {
425 return nil
426 }
427
428 // If the module isn't loaded, that is simply an error
429 if !t.Module.Loaded() {
430 return errors.New("module must be loaded for ProviderConfigTransformer")
431 }
432
433 t.providers = make(map[string]GraphNodeProvider)
434 t.proxiable = make(map[string]bool)
435
436 // Start the transformation process
437 if err := t.transform(g, t.Module); err != nil {
438 return err
439 }
440
441 // finally attach the configs to the new nodes
442 return t.attachProviderConfigs(g)
376} 443}
377 444
378func (n *graphNodeProviderConsumerDummy) ProvidedBy() []string { 445func (t *ProviderConfigTransformer) transform(g *Graph, m *module.Tree) error {
379 return []string{n.ProviderValue} 446 // If no config, do nothing
447 if m == nil {
448 return nil
449 }
450
451 // Add our resources
452 if err := t.transformSingle(g, m); err != nil {
453 return err
454 }
455
456 // Transform all the children.
457 for _, c := range m.Children() {
458 if err := t.transform(g, c); err != nil {
459 return err
460 }
461 }
462 return nil
463}
464
465func (t *ProviderConfigTransformer) transformSingle(g *Graph, m *module.Tree) error {
466 log.Printf("[TRACE] ProviderConfigTransformer: Starting for path: %v", m.Path())
467
468 // Get the configuration for this module
469 conf := m.Config()
470
471 // Build the path we're at
472 path := m.Path()
473 if len(path) > 0 {
474 path = append([]string{RootModuleName}, path...)
475 }
476
477 // add all providers from the configuration
478 for _, p := range conf.ProviderConfigs {
479 name := p.Name
480 if p.Alias != "" {
481 name += "." + p.Alias
482 }
483
484 v := t.Concrete(&NodeAbstractProvider{
485 NameValue: name,
486 PathValue: path,
487 })
488
489 // Add it to the graph
490 g.Add(v)
491 fullName := ResolveProviderName(name, path)
492 t.providers[fullName] = v.(GraphNodeProvider)
493 t.proxiable[fullName] = len(p.RawConfig.RawMap()) == 0
494 }
495
496 // Now replace the provider nodes with proxy nodes if a provider was being
497 // passed in, and create implicit proxies if there was no config. Any extra
498 // proxies will be removed in the prune step.
499 return t.addProxyProviders(g, m)
500}
501
502func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, m *module.Tree) error {
503 path := m.Path()
504
505 // can't add proxies at the root
506 if len(path) == 0 {
507 return nil
508 }
509
510 parentPath := path[:len(path)-1]
511 parent := t.Module.Child(parentPath)
512 if parent == nil {
513 return nil
514 }
515
516 var parentCfg *config.Module
517 for _, mod := range parent.Config().Modules {
518 if mod.Name == m.Name() {
519 parentCfg = mod
520 break
521 }
522 }
523
524 if parentCfg == nil {
525 // this can't really happen during normal execution.
526 return fmt.Errorf("parent module config not found for %s", m.Name())
527 }
528
529 // Go through all the providers the parent is passing in, and add proxies to
530 // the parent provider nodes.
531 for name, parentName := range parentCfg.Providers {
532 fullName := ResolveProviderName(name, path)
533 fullParentName := ResolveProviderName(parentName, parentPath)
534
535 parentProvider := t.providers[fullParentName]
536
537 if parentProvider == nil {
538 return fmt.Errorf("missing provider %s", fullParentName)
539 }
540
541 proxy := &graphNodeProxyProvider{
542 nameValue: name,
543 path: path,
544 target: parentProvider,
545 }
546
547 concreteProvider := t.providers[fullName]
548
549 // replace the concrete node with the provider passed in
550 if concreteProvider != nil && t.proxiable[fullName] {
551 g.Replace(concreteProvider, proxy)
552 t.providers[fullName] = proxy
553 continue
554 }
555
556 // aliased providers can't be implicitly passed in
557 if strings.Contains(name, ".") {
558 continue
559 }
560
561 // There was no concrete provider, so add this as an implicit provider.
562 // The extra proxy will be pruned later if it's unused.
563 g.Add(proxy)
564 t.providers[fullName] = proxy
565 }
566 return nil
567}
568
569func (t *ProviderConfigTransformer) attachProviderConfigs(g *Graph) error {
570 for _, v := range g.Vertices() {
571 // Only care about GraphNodeAttachProvider implementations
572 apn, ok := v.(GraphNodeAttachProvider)
573 if !ok {
574 continue
575 }
576
577 // Determine what we're looking for
578 path := normalizeModulePath(apn.Path())[1:]
579 name := apn.ProviderName()
580 log.Printf("[TRACE] Attach provider request: %#v %s", path, name)
581
582 // Get the configuration.
583 tree := t.Module.Child(path)
584 if tree == nil {
585 continue
586 }
587
588 // Go through the provider configs to find the matching config
589 for _, p := range tree.Config().ProviderConfigs {
590 // Build the name, which is "name.alias" if an alias exists
591 current := p.Name
592 if p.Alias != "" {
593 current += "." + p.Alias
594 }
595
596 // If the configs match then attach!
597 if current == name {
598 log.Printf("[TRACE] Attaching provider config: %#v", p)
599 apn.AttachProvider(p)
600 break
601 }
602 }
603 }
604
605 return nil
380} 606}