simplify MissingProvider and ParentProvider transf

Simplify the MissingProviderTransformer so that it only adds missing
providers at the root level. There's no need for the multitple providers
added at every level of the path

ParentProviderTransformer then only needs to connect providers with the
equivalent type at the root level.
This commit is contained in:
James Bardin 2017-11-02 14:55:11 -04:00
parent 341ec39174
commit a782568645
1 changed files with 40 additions and 81 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform/dag"
)
// TODO: return the transformers and append them to the list, so we don't lose the log steps
func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, mod *module.Tree) GraphTransformer {
// If we have no providers, let the MissingProviderTransformer add anything required.
// This is used by the destroy edge transformer's internal dependency graph.
@ -127,6 +128,7 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
// in the graph are evaluated.
type CloseProviderTransformer struct{}
// FIXME: this doesn't close providers if the root provider is disabled
func (t *CloseProviderTransformer) Transform(g *Graph) error {
pm := providerVertexMap(g)
cpm := make(map[string]*graphNodeCloseProvider)
@ -192,96 +194,62 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
supported[v] = struct{}{}
}
// Get the map of providers we already have in our graph
var err error
m := providerVertexMap(g)
// Go through all the provider consumers and make sure we add
// that provider if it is missing. We use a for loop here instead
// of "range" since we'll modify check as we go to add more to check.
check := g.Vertices()
for i := 0; i < len(check); i++ {
v := check[i]
for _, v := range g.Vertices() {
pv, ok := v.(GraphNodeProviderConsumer)
if !ok {
continue
}
// If this node has a subpath, then we use that as a prefix
// into our map to check for an existing provider.
p := pv.ProvidedBy()[0]
var path []string
if sp, ok := pv.(GraphNodeSubPath); ok {
raw := normalizeModulePath(sp.Path())
if len(raw) > len(rootModulePath) {
path = raw
}
}
p := pv.ProvidedBy()[0]
// always add the parent nodes to check, since configured providers
// may have already been added for modules.
if len(path) > 0 {
// We'll need the parent provider as well, so let's
// add a dummy node to check to make sure that we add
// that parent provider.
check = append(check, &graphNodeProviderConsumerDummy{
ProviderValue: p,
PathValue: path[:len(path)-1],
})
path = sp.Path()
}
key := providerMapKey(p, pv)
if _, ok := m[key]; ok {
// This provider already exists as a configure node
continue
provider := m[key]
// if we don't have a provider at this level, walk up the path looking for one
for i := 1; provider == nil && len(path) >= i; i++ {
key = ResolveProviderName(p, normalizeModulePath(path[:len(path)-i]))
provider = m[key]
}
// If the provider has an alias in it, we just want the type
// TODO: jbardin -- stop adding aliased providers altogether
ptype := p
if idx := strings.IndexRune(p, '.'); idx != -1 {
ptype = p[:idx]
}
if !t.AllowAny {
if _, ok := supported[ptype]; !ok {
// If we don't support the provider type, skip it.
// Validation later will catch this as an error.
if provider != nil {
// we found a provider, but make sure there's a top-level provider too
if _, ok := m[ResolveProviderName(p, nil)]; ok {
continue
}
}
// Add the missing provider node to the graph
provider := t.Concrete(&NodeAbstractProvider{
// always add a new top level provider
provider = t.Concrete(&NodeAbstractProvider{
NameValue: p,
PathValue: path,
}).(dag.Vertex)
key = ResolveProviderName(p, nil)
m[key] = g.Add(provider)
pv.SetProvider(key)
}
return nil
return err
}
// ParentProviderTransformer connects provider nodes to their parents.
//
// This works by finding nodes that are both GraphNodeProviders and
// GraphNodeSubPath. It then connects the providers to their parent
// path.
// path. The parent provider is always at the root level.
type ParentProviderTransformer struct{}
func (t *ParentProviderTransformer) Transform(g *Graph) error {
// Make a mapping of path to dag.Vertex, where path is: "path.name"
m := make(map[string]dag.Vertex)
// Also create a map that maps a provider to its parent
parentMap := make(map[dag.Vertex]string)
for _, raw := range g.Vertices() {
// If it is the flat version, then make it the non-flat version.
// We eventually want to get rid of the flat version entirely so
// this is a stop-gap while it still exists.
var v dag.Vertex = raw
pm := providerVertexMap(g)
for _, v := range g.Vertices() {
// Only care about providers
pn, ok := v.(GraphNodeProvider)
if !ok || pn.ProviderName() == "" {
@ -289,33 +257,22 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error {
}
// Also require a subpath, if there is no subpath then we
// just totally ignore it. The expectation of this transform is
// that it is used with a graph builder that is already flattened.
var path []string
if pn, ok := raw.(GraphNodeSubPath); ok {
path = pn.Path()
// can't have a parent.
if pn, ok := v.(GraphNodeSubPath); ok {
if len(normalizeModulePath(pn.Path())) <= 1 {
continue
}
}
path = normalizeModulePath(path)
key := ResolveProviderName(pn.ProviderName(), path)
m[key] = raw
// Determine the parent if we're non-root. This is length 1 since
// the 0 index should be "root" since we normalize above.
if len(path) > 1 {
path = path[:len(path)-1]
key := ResolveProviderName(pn.ProviderName(), path)
parentMap[raw] = key
}
}
// Connect!
for v, key := range parentMap {
if parent, ok := m[key]; ok {
// 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))
}
}
}
return nil
}
@ -357,7 +314,9 @@ func providerVertexMap(g *Graph) map[string]dag.Vertex {
m := make(map[string]dag.Vertex)
for _, v := range g.Vertices() {
if pv, ok := v.(GraphNodeProvider); ok {
m[pv.Name()] = v
// TODO: The Name may have meta info, like " (disabled)"
name := strings.SplitN(pv.Name(), " ", 2)[0]
m[name] = v
}
}