terraform: missing provider transform
This commit is contained in:
parent
c0695b0657
commit
254689389a
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue