terraform: start FlattenGraph impl.
This commit is contained in:
parent
5e767f63b9
commit
12c30feb0f
|
@ -2,6 +2,7 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
|
@ -152,7 +153,75 @@ func (n *graphNodeModuleExpanded) EvalTree() EvalNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GraphNodeFlattenable impl.
|
||||||
|
func (n *graphNodeModuleExpanded) FlattenGraph() *Graph {
|
||||||
|
graph := n.Subgraph()
|
||||||
|
|
||||||
|
// Build the string that represents the path. We do this once here
|
||||||
|
// so that we only have to compute it once. The block below is in {}
|
||||||
|
// so that parts drops out of scope immediately.
|
||||||
|
var pathStr string
|
||||||
|
{
|
||||||
|
parts := make([]string, 0, len(graph.Path)*2)
|
||||||
|
for _, p := range graph.Path[1:] {
|
||||||
|
parts = append(parts, "module", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
pathStr = strings.Join(parts, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go over each vertex in the graph and wrap the configuration
|
||||||
|
// items so that the dependencies properly map to the modules.
|
||||||
|
// See the docs for graphNodeModuleWrappable for more info.
|
||||||
|
for _, v := range graph.Vertices() {
|
||||||
|
if sn, ok := v.(graphNodeModuleSkippable); ok && sn.FlattenSkip() {
|
||||||
|
graph.Remove(v)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wn, ok := v.(graphNodeModuleWrappable)
|
||||||
|
if !ok {
|
||||||
|
panic("unwrappable node: " + dag.VertexName(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.Replace(v, &graphNodeModuleFlatWrap{
|
||||||
|
graphNodeModuleWrappable: wn,
|
||||||
|
|
||||||
|
Path: graph.Path,
|
||||||
|
PathString: pathStr,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeSubgraph impl.
|
// GraphNodeSubgraph impl.
|
||||||
func (n *graphNodeModuleExpanded) Subgraph() *Graph {
|
func (n *graphNodeModuleExpanded) Subgraph() *Graph {
|
||||||
return n.Graph
|
return n.Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This interface can be implemented to be skipped/ignored when
|
||||||
|
// flattening the module graph.
|
||||||
|
type graphNodeModuleSkippable interface {
|
||||||
|
FlattenSkip() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the interface that all nodes within a module graph must
|
||||||
|
// implement to be wrapped for flattening.
|
||||||
|
type graphNodeModuleWrappable interface {
|
||||||
|
graphNodeConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// graphNodeModuleFlatWrap wraps elements of the module graph
|
||||||
|
// when they are flattened so that the dependency information is
|
||||||
|
// correct.
|
||||||
|
type graphNodeModuleFlatWrap struct {
|
||||||
|
graphNodeModuleWrappable
|
||||||
|
|
||||||
|
Path []string
|
||||||
|
PathString string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *graphNodeModuleFlatWrap) Name() string {
|
||||||
|
return fmt.Sprintf("%s.%s", n.PathString, n.graphNodeModuleWrappable.Name())
|
||||||
|
}
|
||||||
|
|
|
@ -39,3 +39,42 @@ func TestGraphNodeConfigModuleExpand(t *testing.T) {
|
||||||
t.Fatalf("bad:\n\n%s", actual)
|
t.Fatalf("bad:\n\n%s", actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGraphNodeConfigModuleExpandFlatten(t *testing.T) {
|
||||||
|
mod := testModule(t, "graph-node-module-flatten")
|
||||||
|
|
||||||
|
node := &GraphNodeConfigModule{
|
||||||
|
Path: []string{RootModuleName, "child"},
|
||||||
|
Module: &config.Module{},
|
||||||
|
Tree: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
g, err := node.Expand(&BasicGraphBuilder{
|
||||||
|
Steps: []GraphTransformer{
|
||||||
|
&ConfigTransformer{Module: mod},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fg := g.(GraphNodeFlattenable)
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(fg.FlattenGraph().String())
|
||||||
|
expected := strings.TrimSpace(testGraphNodeModuleExpandFlattenStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad:\n\n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testGraphNodeModuleExpandStr = `
|
||||||
|
aws_instance.bar
|
||||||
|
aws_instance.foo
|
||||||
|
aws_instance.foo
|
||||||
|
module inputs
|
||||||
|
module inputs
|
||||||
|
`
|
||||||
|
|
||||||
|
const testGraphNodeModuleExpandFlattenStr = `
|
||||||
|
module.child.aws_instance.foo
|
||||||
|
`
|
||||||
|
|
|
@ -113,11 +113,3 @@ func TestGraphNodeConfigVariable_impl(t *testing.T) {
|
||||||
var _ dag.NamedVertex = new(GraphNodeConfigVariable)
|
var _ dag.NamedVertex = new(GraphNodeConfigVariable)
|
||||||
var _ graphNodeConfig = new(GraphNodeConfigVariable)
|
var _ graphNodeConfig = new(GraphNodeConfigVariable)
|
||||||
}
|
}
|
||||||
|
|
||||||
const testGraphNodeModuleExpandStr = `
|
|
||||||
aws_instance.bar
|
|
||||||
aws_instance.foo
|
|
||||||
aws_instance.foo
|
|
||||||
module inputs
|
|
||||||
module inputs
|
|
||||||
`
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
resource "aws_instance" "foo" {}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module "child" {
|
||||||
|
source = "./child"
|
||||||
|
}
|
|
@ -45,3 +45,8 @@ func (n *graphNodeModuleInput) Name() string {
|
||||||
func (n *graphNodeModuleInput) EvalTree() EvalNode {
|
func (n *graphNodeModuleInput) EvalTree() EvalNode {
|
||||||
return &EvalSetVariables{Variables: n.Variables}
|
return &EvalSetVariables{Variables: n.Variables}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// graphNodeModuleSkippable impl.
|
||||||
|
func (n *graphNodeModuleInput) FlattenSkip() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue