From 4692f9809f1cffaef77c8d0cc421880bd3e4952a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 7 Feb 2015 16:19:08 -0800 Subject: [PATCH] terraform: module nodes expand --- terraform/graph_builder.go | 37 ++++++++++++------ terraform/graph_config_node.go | 6 +++ terraform/graph_config_node_test.go | 39 +++++++++++++++++++ .../graph-node-module-expand/child/main.tf | 4 ++ .../graph-node-module-expand/main.tf | 3 ++ terraform/transform_config.go | 5 +++ 6 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 terraform/test-fixtures/graph-node-module-expand/child/main.tf create mode 100644 terraform/test-fixtures/graph-node-module-expand/main.tf diff --git a/terraform/graph_builder.go b/terraform/graph_builder.go index 40baa54914..e946e152e6 100644 --- a/terraform/graph_builder.go +++ b/terraform/graph_builder.go @@ -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 diff --git a/terraform/graph_config_node.go b/terraform/graph_config_node.go index ae248e3e3c..f5de5833e0 100644 --- a/terraform/graph_config_node.go +++ b/terraform/graph_config_node.go @@ -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. diff --git a/terraform/graph_config_node_test.go b/terraform/graph_config_node_test.go index 40894f5da8..1476c97e02 100644 --- a/terraform/graph_config_node_test.go +++ b/terraform/graph_config_node_test.go @@ -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 +` diff --git a/terraform/test-fixtures/graph-node-module-expand/child/main.tf b/terraform/test-fixtures/graph-node-module-expand/child/main.tf new file mode 100644 index 0000000000..f14f189b0c --- /dev/null +++ b/terraform/test-fixtures/graph-node-module-expand/child/main.tf @@ -0,0 +1,4 @@ +resource "aws_instance" "foo" {} +resource "aws_instance" "bar" { + var = "${aws_instance.foo.whatever}" +} diff --git a/terraform/test-fixtures/graph-node-module-expand/main.tf b/terraform/test-fixtures/graph-node-module-expand/main.tf new file mode 100644 index 0000000000..0f6991c536 --- /dev/null +++ b/terraform/test-fixtures/graph-node-module-expand/main.tf @@ -0,0 +1,3 @@ +module "child" { + source = "./child" +} diff --git a/terraform/transform_config.go b/terraform/transform_config.go index f92c97dca0..21e08930dd 100644 --- a/terraform/transform_config.go +++ b/terraform/transform_config.go @@ -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], })