2015-01-27 23:48:46 -06:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
"github.com/hashicorp/terraform/dag"
|
|
|
|
)
|
|
|
|
|
2015-01-28 00:14:01 -06:00
|
|
|
// GraphNodeProvider is an interface that nodes that can be a provider
|
|
|
|
// must implement. The ProviderName returned is the name of the provider
|
|
|
|
// they satisfy.
|
|
|
|
type GraphNodeProvider interface {
|
|
|
|
ProviderName() string
|
|
|
|
}
|
|
|
|
|
|
|
|
// GraphNodeProviderConsumer is an interface that nodes that require
|
|
|
|
// a provider must implement. ProvidedBy must return the name of the provider
|
|
|
|
// to use.
|
|
|
|
type GraphNodeProviderConsumer interface {
|
|
|
|
ProvidedBy() string
|
|
|
|
}
|
|
|
|
|
2015-01-27 23:48:46 -06:00
|
|
|
// 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{}
|
|
|
|
|
|
|
|
func (t *ProviderTransformer) Transform(g *Graph) error {
|
|
|
|
// Go through the other nodes and match them to providers they need
|
|
|
|
var err error
|
2015-01-28 00:14:01 -06:00
|
|
|
m := providerVertexMap(g)
|
2015-01-27 23:48:46 -06:00
|
|
|
for _, v := range g.Vertices() {
|
|
|
|
if pv, ok := v.(GraphNodeProviderConsumer); ok {
|
|
|
|
target := m[pv.ProvidedBy()]
|
|
|
|
if target == nil {
|
|
|
|
err = multierror.Append(err, fmt.Errorf(
|
|
|
|
"%s: provider %s couldn't be found",
|
|
|
|
dag.VertexName(v), pv.ProvidedBy()))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
g.Connect(dag.BasicEdge(v, target))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-01-28 00:14:01 -06:00
|
|
|
// MissingProviderTransformer is a GraphTransformer that adds nodes
|
|
|
|
// for missing 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.
|
|
|
|
type MissingProviderTransformer struct {
|
|
|
|
// Providers is the list of providers we support.
|
|
|
|
Providers []string
|
2015-01-27 23:48:46 -06:00
|
|
|
}
|
|
|
|
|
2015-01-28 00:14:01 -06:00
|
|
|
func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
|
|
|
m := providerVertexMap(g)
|
|
|
|
for _, p := range t.Providers {
|
|
|
|
if _, ok := m[p]; ok {
|
|
|
|
// This provider already exists as a configured node
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add our own missing provider node to the graph
|
|
|
|
g.Add(&graphNodeMissingProvider{ProviderNameValue: p})
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type graphNodeMissingProvider struct {
|
|
|
|
ProviderNameValue string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *graphNodeMissingProvider) Name() string {
|
|
|
|
return fmt.Sprintf("provider.%s", n.ProviderNameValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *graphNodeMissingProvider) ProviderName() string {
|
|
|
|
return n.ProviderNameValue
|
|
|
|
}
|
|
|
|
|
|
|
|
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.ProviderName()] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m
|
2015-01-27 23:48:46 -06:00
|
|
|
}
|