terraform: missing provider transform

This commit is contained in:
Mitchell Hashimoto 2015-01-27 22:14:01 -08:00
parent c0695b0657
commit 254689389a
2 changed files with 102 additions and 18 deletions

View File

@ -7,22 +7,29 @@ import (
"github.com/hashicorp/terraform/dag"
)
// 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
}
// 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 {
// First, build a map of the providers
m := make(map[string]dag.Vertex)
for _, v := range g.Vertices() {
if pv, ok := v.(GraphNodeProvider); ok {
m[pv.ProviderName()] = v
}
}
// Go through the other nodes and match them to providers they need
var err error
m := providerVertexMap(g)
for _, v := range g.Vertices() {
if pv, ok := v.(GraphNodeProviderConsumer); ok {
target := m[pv.ProvidedBy()]
@ -40,16 +47,49 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
return err
}
// 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
// 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
}
// 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
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
}

View File

@ -3,6 +3,8 @@ package terraform
import (
"strings"
"testing"
"github.com/hashicorp/terraform/dag"
)
func TestProviderTransformer(t *testing.T) {
@ -28,8 +30,50 @@ func TestProviderTransformer(t *testing.T) {
}
}
func TestMissingProviderTransformer(t *testing.T) {
mod := testModule(t, "transform-provider-basic")
g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
transform := &MissingProviderTransformer{Providers: []string{"foo"}}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformMissingProviderBasicStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestGraphNodeMissingProvider_impl(t *testing.T) {
var _ dag.Vertex = new(graphNodeMissingProvider)
var _ dag.NamedVertex = new(graphNodeMissingProvider)
var _ GraphNodeProvider = new(graphNodeMissingProvider)
}
func TestGraphNodeMissingProvider_ProviderName(t *testing.T) {
n := &graphNodeMissingProvider{ProviderNameValue: "foo"}
if v := n.ProviderName(); v != "foo" {
t.Fatalf("bad: %#v", v)
}
}
const testTransformProviderBasicStr = `
aws_instance.web
provider.aws
provider.aws
`
const testTransformMissingProviderBasicStr = `
aws_instance.web
provider.aws
provider.foo
`