config/module: tree.String()

This commit is contained in:
Mitchell Hashimoto 2014-09-14 20:14:37 -07:00
parent 85d1e40644
commit 30b76ef820
2 changed files with 79 additions and 3 deletions

View File

@ -1,7 +1,10 @@
package module
import (
"bufio"
"bytes"
"fmt"
"strings"
"sync"
"github.com/hashicorp/terraform/config"
@ -13,9 +16,10 @@ import (
// all the modules without getting, flatten the tree into something
// Terraform can use, etc.
type Tree struct {
name string
config *config.Config
children []*Tree
lock sync.Mutex
lock sync.RWMutex
}
// GetMode is an enum that describes how modules are loaded.
@ -47,7 +51,9 @@ func NewTree(c *config.Config) *Tree {
//
// This will only return a non-nil value after Load is called.
func (t *Tree) Children() []*Tree {
return nil
t.lock.RLock()
defer t.lock.RUnlock()
return t.children
}
// Flatten takes the entire module tree and flattens it into a single
@ -77,6 +83,16 @@ func (t *Tree) Modules() []*Module {
return result
}
// Name returns the name of the tree. This will be "<root>" for the root
// tree and then the module name given for any children.
func (t *Tree) Name() string {
if t.name == "" {
return "<root>"
}
return t.name
}
// Load loads the configuration of the entire tree.
//
// The parameters are used to tell the tree where to find modules and
@ -130,6 +146,7 @@ func (t *Tree) Load(s Storage, mode GetMode) error {
"module %s: %s", m.Name, err)
}
children[i] = NewTree(c)
children[i].name = m.Name
}
// Go through all the children and load them.
@ -145,6 +162,31 @@ func (t *Tree) Load(s Storage, mode GetMode) error {
return nil
}
// String gives a nice output to describe the tree.
func (t *Tree) String() string {
var result bytes.Buffer
result.WriteString(t.Name() + "\n")
cs := t.Children()
if cs == nil {
result.WriteString(" not loaded")
} else {
// Go through each child and get its string value, then indent it
// by two.
for _, c := range cs {
r := strings.NewReader(c.String())
scanner := bufio.NewScanner(r)
for scanner.Scan() {
result.WriteString(" ")
result.WriteString(scanner.Text())
result.WriteString("\n")
}
}
}
return result.String()
}
// Validate does semantic checks on the entire tree of configurations.
//
// This will call the respective config.Config.Validate() functions as well

View File

@ -2,14 +2,34 @@ package module
import (
"reflect"
"strings"
"testing"
)
func TestTree_Load(t *testing.T) {
storage := testStorage(t)
tree := NewTree(testConfig(t, "basic"))
if err := tree.Load(testStorage(t), GetModeGet); err != nil {
// This should error because we haven't gotten things yet
if err := tree.Load(storage, GetModeNone); err == nil {
t.Fatal("should error")
}
// This should get things
if err := tree.Load(storage, GetModeGet); err != nil {
t.Fatalf("err: %s", err)
}
// This should no longer error
if err := tree.Load(storage, GetModeNone); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(tree.String())
expected := strings.TrimSpace(treeLoadStr)
if actual != expected {
t.Fatalf("bad: \n\n%s", actual)
}
}
func TestTree_Modules(t *testing.T) {
@ -24,3 +44,17 @@ func TestTree_Modules(t *testing.T) {
t.Fatalf("bad: %#v", actual)
}
}
func TestTree_Name(t *testing.T) {
tree := NewTree(testConfig(t, "basic"))
actual := tree.Name()
if actual != "<root>" {
t.Fatalf("bad: %#v", actual)
}
}
const treeLoadStr = `
<root>
foo
`