X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=vendor%2Fgithub.com%2Fhashicorp%2Fterraform%2Fterraform%2Ftransform_provider.go;h=6a4fb47c49c86e877b842811f80eaeda24522af1;hb=HEAD;hp=c4772b40193ca4e9d42eee6a95fde75855517600;hpb=15c0b25d011f37e7c20aeca9eaf461f78285b8d9;p=github%2Ffretlink%2Fterraform-provider-statuscake.git diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go b/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go index c4772b4..6a4fb47 100644 --- a/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go +++ b/vendor/github.com/hashicorp/terraform/terraform/transform_provider.go @@ -1,22 +1,21 @@ package terraform import ( - "errors" "fmt" "log" - "strings" - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/config/module" + "github.com/hashicorp/hcl2/hcl" + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/dag" + "github.com/hashicorp/terraform/tfdiags" ) -func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, mod *module.Tree) GraphTransformer { +func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, config *configs.Config) GraphTransformer { return GraphTransformMulti( // Add providers from the config &ProviderConfigTransformer{ - Module: mod, + Config: config, Providers: providers, Concrete: concrete, }, @@ -26,7 +25,9 @@ func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, m Concrete: concrete, }, // Connect the providers - &ProviderTransformer{}, + &ProviderTransformer{ + Config: config, + }, // Remove unused providers and proxies &PruneProviderTransformer{}, // Connect provider to their parent provider nodes @@ -36,10 +37,14 @@ func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, m // GraphNodeProvider is an interface that nodes that can be a provider // must implement. -// ProviderName returns the name of the provider this satisfies. +// +// ProviderAddr returns the address of the provider configuration this +// satisfies, which is relative to the path returned by method Path(). +// // Name returns the full name of the provider in the config. type GraphNodeProvider interface { - ProviderName() string + GraphNodeSubPath + ProviderAddr() addrs.AbsProviderConfig Name() string } @@ -47,62 +52,132 @@ type GraphNodeProvider interface { // provider must implement. The CloseProviderName returned is the name of // the provider they satisfy. type GraphNodeCloseProvider interface { - CloseProviderName() string + GraphNodeSubPath + CloseProviderAddr() addrs.AbsProviderConfig } // GraphNodeProviderConsumer is an interface that nodes that require -// a provider must implement. ProvidedBy must return the name of the provider -// to use. This may be a provider by type, type.alias or a fully resolved -// provider name +// a provider must implement. ProvidedBy must return the address of the provider +// to use, which will be resolved to a configuration either in the same module +// or in an ancestor module, with the resulting absolute address passed to +// SetProvider. type GraphNodeProviderConsumer interface { - ProvidedBy() string + // ProvidedBy returns the address of the provider configuration the node + // refers to. If the returned "exact" value is true, this address will + // be taken exactly. If "exact" is false, a provider configuration from + // an ancestor module may be selected instead. + ProvidedBy() (addr addrs.AbsProviderConfig, exact bool) // Set the resolved provider address for this resource. - SetProvider(string) + SetProvider(addrs.AbsProviderConfig) } // ProviderTransformer is a GraphTransformer that maps resources to // providers within the graph. This will error if there are any resources // that don't map to proper resources. -type ProviderTransformer struct{} +type ProviderTransformer struct { + Config *configs.Config +} func (t *ProviderTransformer) Transform(g *Graph) error { - // Go through the other nodes and match them to providers they need - var err error - m := providerVertexMap(g) + // We need to find a provider configuration address for each resource + // either directly represented by a node or referenced by a node in + // the graph, and then create graph edges from provider to provider user + // so that the providers will get initialized first. + + var diags tfdiags.Diagnostics + + // To start, we'll collect the _requested_ provider addresses for each + // node, which we'll then resolve (handling provider inheritence, etc) in + // the next step. + // Our "requested" map is from graph vertices to string representations of + // provider config addresses (for deduping) to requests. + type ProviderRequest struct { + Addr addrs.AbsProviderConfig + Exact bool // If true, inheritence from parent modules is not attempted + } + requested := map[dag.Vertex]map[string]ProviderRequest{} + needConfigured := map[string]addrs.AbsProviderConfig{} for _, v := range g.Vertices() { + + // Does the vertex _directly_ use a provider? if pv, ok := v.(GraphNodeProviderConsumer); ok { - p := pv.ProvidedBy() + requested[v] = make(map[string]ProviderRequest) - key := providerMapKey(p, pv) + p, exact := pv.ProvidedBy() + if exact { + log.Printf("[TRACE] ProviderTransformer: %s is provided by %s exactly", dag.VertexName(v), p) + } else { + log.Printf("[TRACE] ProviderTransformer: %s is provided by %s or inherited equivalent", dag.VertexName(v), p) + } + + requested[v][p.String()] = ProviderRequest{ + Addr: p, + Exact: exact, + } + + // Direct references need the provider configured as well as initialized + needConfigured[p.String()] = p + } + } + + // Now we'll go through all the requested addresses we just collected and + // figure out which _actual_ config address each belongs to, after resolving + // for provider inheritance and passing. + m := providerVertexMap(g) + for v, reqs := range requested { + for key, req := range reqs { + p := req.Addr target := m[key] - sp, ok := pv.(GraphNodeSubPath) + _, ok := v.(GraphNodeSubPath) if !ok && target == nil { - // no target, and no path to walk up - err = multierror.Append(err, fmt.Errorf( - "%s: provider %s couldn't be found", - dag.VertexName(v), p)) - break + // No target and no path to traverse up from + diags = diags.Append(fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p)) + continue + } + + if target != nil { + log.Printf("[TRACE] ProviderTransformer: exact match for %s serving %s", p, dag.VertexName(v)) } - // if we don't have a provider at this level, walk up the path looking for one - for i := 1; target == nil; i++ { - path := normalizeModulePath(sp.Path()) - if len(path) < i { - break + // if we don't have a provider at this level, walk up the path looking for one, + // unless we were told to be exact. + if target == nil && !req.Exact { + for pp, ok := p.Inherited(); ok; pp, ok = pp.Inherited() { + key := pp.String() + target = m[key] + if target != nil { + log.Printf("[TRACE] ProviderTransformer: %s uses inherited configuration %s", dag.VertexName(v), pp) + break + } + log.Printf("[TRACE] ProviderTransformer: looking for %s to serve %s", pp, dag.VertexName(v)) } + } - key = ResolveProviderName(p, path[:len(path)-i]) - target = m[key] - if target != nil { - break + // If this provider doesn't need to be configured then we can just + // stub it out with an init-only provider node, which will just + // start up the provider and fetch its schema. + if _, exists := needConfigured[key]; target == nil && !exists { + stubAddr := p.ProviderConfig.Absolute(addrs.RootModuleInstance) + stub := &NodeEvalableProvider{ + &NodeAbstractProvider{ + Addr: stubAddr, + }, } + m[stubAddr.String()] = stub + log.Printf("[TRACE] ProviderTransformer: creating init-only node for %s", stubAddr) + target = stub + g.Add(target) } if target == nil { - err = multierror.Append(err, fmt.Errorf( - "%s: configuration for %s is not present; a provider configuration block is required for all operations", - dag.VertexName(v), p, + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Provider configuration not present", + fmt.Sprintf( + "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.", + dag.VertexName(v), p, dag.VertexName(v), + ), )) break } @@ -111,16 +186,18 @@ func (t *ProviderTransformer) Transform(g *Graph) error { if p, ok := target.(*graphNodeProxyProvider); ok { g.Remove(p) target = p.Target() - key = target.(GraphNodeProvider).Name() + key = target.(GraphNodeProvider).ProviderAddr().String() } - log.Printf("[DEBUG] resource %s using provider %s", dag.VertexName(pv), key) - pv.SetProvider(key) + log.Printf("[DEBUG] ProviderTransformer: %q (%T) needs %s", dag.VertexName(v), v, dag.VertexName(target)) + if pv, ok := v.(GraphNodeProviderConsumer); ok { + pv.SetProvider(target.ProviderAddr()) + } g.Connect(dag.BasicEdge(v, target)) } } - return err + return diags.Err() } // CloseProviderTransformer is a GraphTransformer that adds nodes to the @@ -136,15 +213,16 @@ func (t *CloseProviderTransformer) Transform(g *Graph) error { for _, v := range pm { p := v.(GraphNodeProvider) + key := p.ProviderAddr().String() // get the close provider of this type if we alread created it - closer := cpm[p.Name()] + closer := cpm[key] if closer == nil { // create a closer for this provider type - closer = &graphNodeCloseProvider{ProviderNameValue: p.Name()} + closer = &graphNodeCloseProvider{Addr: p.ProviderAddr()} g.Add(closer) - cpm[p.Name()] = closer + cpm[key] = closer } // Close node depends on the provider itself @@ -164,10 +242,20 @@ func (t *CloseProviderTransformer) Transform(g *Graph) error { return err } -// MissingProviderTransformer is a GraphTransformer that adds nodes for all -// required providers into the graph. Specifically, it creates provider -// configuration nodes for all the providers that we support. These are pruned -// later during an optimization pass. +// MissingProviderTransformer is a GraphTransformer that adds to the graph +// a node for each default provider configuration that is referenced by another +// node but not already present in the graph. +// +// These "default" nodes are always added to the root module, regardless of +// where they are requested. This is important because our inheritance +// resolution behavior in ProviderTransformer will then treat these as a +// last-ditch fallback after walking up the tree, rather than preferring them +// as it would if they were placed in the same module as the requester. +// +// This transformer may create extra nodes that are not needed in practice, +// due to overriding provider configurations in child modules. +// PruneProviderTransformer can then remove these once ProviderTransformer +// has resolved all of the inheritence, etc. type MissingProviderTransformer struct { // Providers is the list of providers we support. Providers []string @@ -192,34 +280,40 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error { continue } - p := pv.ProvidedBy() - // this may be the resolved provider from the state, so we need to get - // the base provider name. - parts := strings.SplitAfter(p, "provider.") - p = parts[len(parts)-1] + // For our work here we actually care only about the provider type and + // we plan to place all default providers in the root module, and so + // it's safe for us to rely on ProvidedBy here rather than waiting for + // the later proper resolution of provider inheritance done by + // ProviderTransformer. + p, _ := pv.ProvidedBy() + if p.ProviderConfig.Alias != "" { + // We do not create default aliased configurations. + log.Println("[TRACE] MissingProviderTransformer: skipping implication of aliased config", p) + continue + } - key := ResolveProviderName(p, nil) + // We're going to create an implicit _default_ configuration for the + // referenced provider type in the _root_ module, ignoring all other + // aspects of the resource's declared provider address. + defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(p.ProviderConfig.Type) + key := defaultAddr.String() provider := m[key] - // we already have it if provider != nil { + // There's already an explicit default configuration for this + // provider type in the root module, so we have nothing to do. continue } - // we don't implicitly create aliased providers - if strings.Contains(p, ".") { - log.Println("[DEBUG] not adding missing provider alias:", p) - continue - } - - log.Println("[DEBUG] adding missing provider:", p) + log.Printf("[DEBUG] adding implicit provider configuration %s, implied first by %s", defaultAddr, dag.VertexName(v)) - // create the misisng top-level provider + // create the missing top-level provider provider = t.Concrete(&NodeAbstractProvider{ - NameValue: p, - }).(dag.Vertex) + Addr: defaultAddr, + }).(GraphNodeProvider) - m[key] = g.Add(provider) + g.Add(provider) + m[key] = provider } return err @@ -237,26 +331,26 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error { for _, v := range g.Vertices() { // Only care about providers pn, ok := v.(GraphNodeProvider) - if !ok || pn.ProviderName() == "" { + if !ok { continue } - // Also require a subpath, if there is no subpath then we - // can't have a parent. - if pn, ok := v.(GraphNodeSubPath); ok { - if len(normalizeModulePath(pn.Path())) <= 1 { - continue - } + // Also require non-empty path, since otherwise we're in the root + // module and so cannot have a parent. + if len(pn.Path()) <= 1 { + continue } // this provider may be disabled, but we can only get it's name from // the ProviderName string - name := ResolveProviderName(strings.SplitN(pn.ProviderName(), " ", 2)[0], nil) - parent := pm[name] - if parent != nil { - g.Connect(dag.BasicEdge(v, parent)) + addr := pn.ProviderAddr() + parentAddr, ok := addr.Inherited() + if ok { + parent := pm[parentAddr.String()] + if parent != nil { + g.Connect(dag.BasicEdge(v, parent)) + } } - } return nil } @@ -270,20 +364,20 @@ type PruneProviderTransformer struct{} func (t *PruneProviderTransformer) Transform(g *Graph) error { for _, v := range g.Vertices() { // We only care about providers - pn, ok := v.(GraphNodeProvider) - if !ok || pn.ProviderName() == "" { + _, ok := v.(GraphNodeProvider) + if !ok { continue } // ProxyProviders will have up edges, but we're now done with them in the graph if _, ok := v.(*graphNodeProxyProvider); ok { - log.Printf("[DEBUG] pruning proxy provider %s", dag.VertexName(v)) + log.Printf("[DEBUG] pruning proxy %s", dag.VertexName(v)) g.Remove(v) } // Remove providers with no dependencies. if g.UpEdges(v).Len() == 0 { - log.Printf("[DEBUG] pruning unused provider %s", dag.VertexName(v)) + log.Printf("[DEBUG] pruning unused %s", dag.VertexName(v)) g.Remove(v) } } @@ -291,40 +385,24 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error { return nil } -// providerMapKey is a helper that gives us the key to use for the -// maps returned by things such as providerVertexMap. -func providerMapKey(k string, v dag.Vertex) string { - if strings.Contains(k, "provider.") { - // this is already resolved - return k - } - - // we create a dummy provider to - var path []string - if sp, ok := v.(GraphNodeSubPath); ok { - path = normalizeModulePath(sp.Path()) - } - return ResolveProviderName(k, path) -} - -func providerVertexMap(g *Graph) map[string]dag.Vertex { - m := make(map[string]dag.Vertex) +func providerVertexMap(g *Graph) map[string]GraphNodeProvider { + m := make(map[string]GraphNodeProvider) for _, v := range g.Vertices() { if pv, ok := v.(GraphNodeProvider); ok { - // TODO: The Name may have meta info, like " (disabled)" - name := strings.SplitN(pv.Name(), " ", 2)[0] - m[name] = v + addr := pv.ProviderAddr() + m[addr.String()] = pv } } return m } -func closeProviderVertexMap(g *Graph) map[string]dag.Vertex { - m := make(map[string]dag.Vertex) +func closeProviderVertexMap(g *Graph) map[string]GraphNodeCloseProvider { + m := make(map[string]GraphNodeCloseProvider) for _, v := range g.Vertices() { if pv, ok := v.(GraphNodeCloseProvider); ok { - m[pv.CloseProviderName()] = v + addr := pv.CloseProviderAddr() + m[addr.String()] = pv } } @@ -332,16 +410,25 @@ func closeProviderVertexMap(g *Graph) map[string]dag.Vertex { } type graphNodeCloseProvider struct { - ProviderNameValue string + Addr addrs.AbsProviderConfig } +var ( + _ GraphNodeCloseProvider = (*graphNodeCloseProvider)(nil) +) + func (n *graphNodeCloseProvider) Name() string { - return n.ProviderNameValue + " (close)" + return n.Addr.String() + " (close)" +} + +// GraphNodeSubPath impl. +func (n *graphNodeCloseProvider) Path() addrs.ModuleInstance { + return n.Addr.Module } // GraphNodeEvalable impl. func (n *graphNodeCloseProvider) EvalTree() EvalNode { - return CloseProviderEvalTree(n.ProviderNameValue) + return CloseProviderEvalTree(n.Addr) } // GraphNodeDependable impl. @@ -349,8 +436,8 @@ func (n *graphNodeCloseProvider) DependableName() []string { return []string{n.Name()} } -func (n *graphNodeCloseProvider) CloseProviderName() string { - return n.ProviderNameValue +func (n *graphNodeCloseProvider) CloseProviderAddr() addrs.AbsProviderConfig { + return n.Addr } // GraphNodeDotter impl. @@ -380,17 +467,24 @@ func (n *graphNodeCloseProvider) RemoveIfNotTargeted() bool { // configurations, and are removed after all the resources have been connected // to their providers. type graphNodeProxyProvider struct { - nameValue string - path []string - target GraphNodeProvider + addr addrs.AbsProviderConfig + target GraphNodeProvider +} + +var ( + _ GraphNodeProvider = (*graphNodeProxyProvider)(nil) +) + +func (n *graphNodeProxyProvider) ProviderAddr() addrs.AbsProviderConfig { + return n.addr } -func (n *graphNodeProxyProvider) ProviderName() string { - return n.Target().ProviderName() +func (n *graphNodeProxyProvider) Path() addrs.ModuleInstance { + return n.addr.Module } func (n *graphNodeProxyProvider) Name() string { - return ResolveProviderName(n.nameValue, n.path) + return n.addr.String() + " (proxy)" } // find the concrete provider instance @@ -415,26 +509,21 @@ type ProviderConfigTransformer struct { // record providers that can be overriden with a proxy proxiable map[string]bool - // Module is the module to add resources from. - Module *module.Tree + // Config is the root node of the configuration tree to add providers from. + Config *configs.Config } func (t *ProviderConfigTransformer) Transform(g *Graph) error { - // If no module is given, we don't do anything - if t.Module == nil { + // If no configuration is given, we don't do anything + if t.Config == nil { return nil } - // If the module isn't loaded, that is simply an error - if !t.Module.Loaded() { - return errors.New("module must be loaded for ProviderConfigTransformer") - } - t.providers = make(map[string]GraphNodeProvider) t.proxiable = make(map[string]bool) // Start the transformation process - if err := t.transform(g, t.Module); err != nil { + if err := t.transform(g, t.Config); err != nil { return err } @@ -442,95 +531,126 @@ func (t *ProviderConfigTransformer) Transform(g *Graph) error { return t.attachProviderConfigs(g) } -func (t *ProviderConfigTransformer) transform(g *Graph, m *module.Tree) error { +func (t *ProviderConfigTransformer) transform(g *Graph, c *configs.Config) error { // If no config, do nothing - if m == nil { + if c == nil { return nil } // Add our resources - if err := t.transformSingle(g, m); err != nil { + if err := t.transformSingle(g, c); err != nil { return err } // Transform all the children. - for _, c := range m.Children() { - if err := t.transform(g, c); err != nil { + for _, cc := range c.Children { + if err := t.transform(g, cc); err != nil { return err } } return nil } -func (t *ProviderConfigTransformer) transformSingle(g *Graph, m *module.Tree) error { - log.Printf("[TRACE] ProviderConfigTransformer: Starting for path: %v", m.Path()) - - // Get the configuration for this module - conf := m.Config() - - // Build the path we're at - path := m.Path() - if len(path) > 0 { - path = append([]string{RootModuleName}, path...) +func (t *ProviderConfigTransformer) transformSingle(g *Graph, c *configs.Config) error { + // Get the module associated with this configuration tree node + mod := c.Module + staticPath := c.Path + + // We actually need a dynamic module path here, but we've not yet updated + // our graph builders enough to support expansion of module calls with + // "count" and "for_each" set, so for now we'll shim this by converting to + // a dynamic path with no keys. At the time of writing this is the only + // possible kind of dynamic path anyway. + path := make(addrs.ModuleInstance, len(staticPath)) + for i, name := range staticPath { + path[i] = addrs.ModuleInstanceStep{ + Name: name, + } } // add all providers from the configuration - for _, p := range conf.ProviderConfigs { - name := p.Name - if p.Alias != "" { - name += "." + p.Alias - } + for _, p := range mod.ProviderConfigs { + relAddr := p.Addr() + addr := relAddr.Absolute(path) - v := t.Concrete(&NodeAbstractProvider{ - NameValue: name, - PathValue: path, - }) + abstract := &NodeAbstractProvider{ + Addr: addr, + } + var v dag.Vertex + if t.Concrete != nil { + v = t.Concrete(abstract) + } else { + v = abstract + } // Add it to the graph g.Add(v) - fullName := ResolveProviderName(name, path) - t.providers[fullName] = v.(GraphNodeProvider) - t.proxiable[fullName] = len(p.RawConfig.RawMap()) == 0 + key := addr.String() + t.providers[key] = v.(GraphNodeProvider) + + // A provider configuration is "proxyable" if its configuration is + // entirely empty. This means it's standing in for a provider + // configuration that must be passed in from the parent module. + // We decide this by evaluating the config with an empty schema; + // if this succeeds, then we know there's nothing in the body. + _, diags := p.Config.Content(&hcl.BodySchema{}) + t.proxiable[key] = !diags.HasErrors() } // Now replace the provider nodes with proxy nodes if a provider was being // passed in, and create implicit proxies if there was no config. Any extra // proxies will be removed in the prune step. - return t.addProxyProviders(g, m) + return t.addProxyProviders(g, c) } -func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, m *module.Tree) error { - path := m.Path() +func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, c *configs.Config) error { + path := c.Path // can't add proxies at the root if len(path) == 0 { return nil } - parentPath := path[:len(path)-1] - parent := t.Module.Child(parentPath) + parentPath, callAddr := path.Call() + parent := c.Parent if parent == nil { return nil } - var parentCfg *config.Module - for _, mod := range parent.Config().Modules { - if mod.Name == m.Name() { + callName := callAddr.Name + var parentCfg *configs.ModuleCall + for name, mod := range parent.Module.ModuleCalls { + if name == callName { parentCfg = mod break } } + // We currently don't support count/for_each for modules and so we must + // shim our path and parentPath into module instances here so that the + // rest of Terraform can behave as if we do. This shimming should be + // removed later as part of implementing count/for_each for modules. + instPath := make(addrs.ModuleInstance, len(path)) + for i, name := range path { + instPath[i] = addrs.ModuleInstanceStep{Name: name} + } + parentInstPath := make(addrs.ModuleInstance, len(parentPath)) + for i, name := range parentPath { + parentInstPath[i] = addrs.ModuleInstanceStep{Name: name} + } + if parentCfg == nil { // this can't really happen during normal execution. - return fmt.Errorf("parent module config not found for %s", m.Name()) + return fmt.Errorf("parent module config not found for %s", c.Path.String()) } // Go through all the providers the parent is passing in, and add proxies to // the parent provider nodes. - for name, parentName := range parentCfg.Providers { - fullName := ResolveProviderName(name, path) - fullParentName := ResolveProviderName(parentName, parentPath) + for _, pair := range parentCfg.Providers { + fullAddr := pair.InChild.Addr().Absolute(instPath) + fullParentAddr := pair.InParent.Addr().Absolute(parentInstPath) + fullName := fullAddr.String() + fullParentName := fullParentAddr.String() parentProvider := t.providers[fullParentName] @@ -539,9 +659,8 @@ func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, m *module.Tree) } proxy := &graphNodeProxyProvider{ - nameValue: name, - path: path, - target: parentProvider, + addr: fullAddr, + target: parentProvider, } concreteProvider := t.providers[fullName] @@ -553,8 +672,8 @@ func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, m *module.Tree) continue } - // aliased providers can't be implicitly passed in - if strings.Contains(name, ".") { + // aliased configurations can't be implicitly passed in + if fullAddr.ProviderConfig.Alias != "" { continue } @@ -575,27 +694,19 @@ func (t *ProviderConfigTransformer) attachProviderConfigs(g *Graph) error { } // Determine what we're looking for - path := normalizeModulePath(apn.Path())[1:] - name := apn.ProviderName() - log.Printf("[TRACE] Attach provider request: %#v %s", path, name) + addr := apn.ProviderAddr() // Get the configuration. - tree := t.Module.Child(path) - if tree == nil { + mc := t.Config.DescendentForInstance(addr.Module) + if mc == nil { + log.Printf("[TRACE] ProviderConfigTransformer: no configuration available for %s", addr.String()) continue } // Go through the provider configs to find the matching config - for _, p := range tree.Config().ProviderConfigs { - // Build the name, which is "name.alias" if an alias exists - current := p.Name - if p.Alias != "" { - current += "." + p.Alias - } - - // If the configs match then attach! - if current == name { - log.Printf("[TRACE] Attaching provider config: %#v", p) + for _, p := range mc.Module.ProviderConfigs { + if p.Name == addr.ProviderConfig.Type && p.Alias == addr.ProviderConfig.Alias { + log.Printf("[TRACE] ProviderConfigTransformer: attaching to %q provider configuration from %s", dag.VertexName(v), p.DeclRange) apn.AttachProvider(p) break }