terraform: module nodes expand

This commit is contained in:
Mitchell Hashimoto 2015-02-07 16:19:08 -08:00
parent e5fd7c9e84
commit 4692f9809f
6 changed files with 83 additions and 11 deletions

View File

@ -13,6 +13,29 @@ type GraphBuilder interface {
Build(path []string) (*Graph, error)
}
// BasicGraphBuilder is a GraphBuilder that builds a graph out of a
// series of transforms and validates the graph is a valid structure.
type BasicGraphBuilder struct {
Steps []GraphTransformer
}
// TODO(mitchellh): test
func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
g := &Graph{Path: path}
for _, step := range b.Steps {
if err := step.Transform(g); err != nil {
return g, err
}
}
// Validate the graph structure
if err := g.Validate(); err != nil {
return nil, err
}
return g, nil
}
// BuiltinGraphBuilder is responsible for building the complete graph that
// Terraform uses for execution. It is an opinionated builder that defines
// the step order required to build a complete graph as is used and expected
@ -34,19 +57,11 @@ type BuiltinGraphBuilder struct {
// Build builds the graph according to the steps returned by Steps.
func (b *BuiltinGraphBuilder) Build(path []string) (*Graph, error) {
g := &Graph{Path: path}
for _, step := range b.Steps() {
if err := step.Transform(g); err != nil {
return g, err
}
basic := &BasicGraphBuilder{
Steps: b.Steps(),
}
// Validate the graph structure
if err := g.Validate(); err != nil {
return nil, err
}
return g, nil
return basic.Build(path)
}
// Steps returns the ordered list of GraphTransformers that must be executed

View File

@ -22,6 +22,7 @@ type graphNodeConfig interface {
// GraphNodeConfigModule represents a module within the configuration graph.
type GraphNodeConfigModule struct {
Path []string
Module *config.Module
Tree *module.Tree
}
@ -46,6 +47,11 @@ func (n *GraphNodeConfigModule) Name() string {
return fmt.Sprintf("module.%s", n.Module.Name)
}
// GraphNodeExpandable
func (n *GraphNodeConfigModule) Expand(b GraphBuilder) (*Graph, error) {
return b.Build(n.Path)
}
// GraphNodeConfigProvider represents a configured provider within the
// configuration graph. These are only immediately in the graph when an
// explicit `provider` configuration block is in the configuration.

View File

@ -1,12 +1,45 @@
package terraform
import (
"strings"
"testing"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/dag"
)
func TestGraphNodeConfigModule_impl(t *testing.T) {
var _ dag.Vertex = new(GraphNodeConfigModule)
var _ dag.NamedVertex = new(GraphNodeConfigModule)
var _ graphNodeConfig = new(GraphNodeConfigModule)
var _ GraphNodeExpandable = new(GraphNodeConfigModule)
}
func TestGraphNodeConfigModuleExpand(t *testing.T) {
mod := testModule(t, "graph-node-module-expand")
node := &GraphNodeConfigModule{
Path: []string{RootModuleName, "child"},
Module: nil,
Tree: nil,
}
g, err := node.Expand(&BasicGraphBuilder{
Steps: []GraphTransformer{
&ConfigTransformer{Module: mod},
},
})
if err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testGraphNodeModuleExpandStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestGraphNodeConfigProvider_impl(t *testing.T) {
var _ dag.Vertex = new(GraphNodeConfigProvider)
var _ dag.NamedVertex = new(GraphNodeConfigProvider)
@ -40,3 +73,9 @@ func TestGraphNodeConfigResource_ProvidedBy(t *testing.T) {
t.Fatalf("bad: %#v", v)
}
}
const testGraphNodeModuleExpandStr = `
aws_instance.bar
aws_instance.foo
aws_instance.foo
`

View File

@ -0,0 +1,4 @@
resource "aws_instance" "foo" {}
resource "aws_instance" "bar" {
var = "${aws_instance.foo.whatever}"
}

View File

@ -0,0 +1,3 @@
module "child" {
source = "./child"
}

View File

@ -53,7 +53,12 @@ func (t *ConfigTransformer) Transform(g *Graph) error {
// Write all the modules out
children := module.Children()
for _, m := range config.Modules {
path := make([]string, len(g.Path), len(g.Path)+1)
copy(path, g.Path)
path = append(path, m.Name)
nodes = append(nodes, &GraphNodeConfigModule{
Path: path,
Module: m,
Tree: children[m.Name],
})