config/module: Validate
This commit is contained in:
parent
30b76ef820
commit
c9fd910c41
|
@ -0,0 +1,3 @@
|
|||
# Duplicate resources
|
||||
resource "aws_instance" "foo" {}
|
||||
resource "aws_instance" "foo" {}
|
|
@ -0,0 +1,3 @@
|
|||
module "foo" {
|
||||
source = "./child"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
# Good
|
|
@ -0,0 +1,3 @@
|
|||
module "child" {
|
||||
source = "./child"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# Duplicate resources
|
||||
resource "aws_instance" "foo" {}
|
||||
resource "aws_instance" "foo" {}
|
|
@ -67,6 +67,13 @@ func (t *Tree) Flatten() (*config.Config, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Loaded says whether or not this tree has been loaded or not yet.
|
||||
func (t *Tree) Loaded() bool {
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
return t.children != nil
|
||||
}
|
||||
|
||||
// Modules returns the list of modules that this tree imports.
|
||||
//
|
||||
// This is only the imports of _this_ level of the tree. To retrieve the
|
||||
|
@ -191,6 +198,58 @@ func (t *Tree) String() string {
|
|||
//
|
||||
// This will call the respective config.Config.Validate() functions as well
|
||||
// as verifying things such as parameters/outputs between the various modules.
|
||||
//
|
||||
// Load must be called prior to calling Validate or an error will be returned.
|
||||
func (t *Tree) Validate() error {
|
||||
if !t.Loaded() {
|
||||
return fmt.Errorf("tree must be loaded before calling Validate")
|
||||
}
|
||||
|
||||
// Validate our configuration first.
|
||||
if err := t.config.Validate(); err != nil {
|
||||
return &ValidateError{
|
||||
Name: []string{t.Name()},
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate all our children
|
||||
for _, c := range t.Children() {
|
||||
err := c.Validate()
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
verr, ok := err.(*ValidateError)
|
||||
if !ok {
|
||||
// Unknown error, just return...
|
||||
return err
|
||||
}
|
||||
|
||||
// Append ourselves to the error and then return
|
||||
verr.Name = append(verr.Name, t.Name())
|
||||
return verr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateError is an error returned by Tree.Validate if an error occurs
|
||||
// with validation.
|
||||
type ValidateError struct {
|
||||
Name []string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *ValidateError) Error() string {
|
||||
// Build up the name
|
||||
var buf bytes.Buffer
|
||||
for _, n := range e.Name {
|
||||
buf.WriteString(n)
|
||||
buf.WriteString(".")
|
||||
}
|
||||
buf.Truncate(buf.Len()-1)
|
||||
|
||||
// Format the value
|
||||
return fmt.Sprintf("module %s: %s", buf.String(), e.Err)
|
||||
}
|
||||
|
|
|
@ -6,20 +6,32 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestTree_Load(t *testing.T) {
|
||||
func TestTreeLoad(t *testing.T) {
|
||||
storage := testStorage(t)
|
||||
tree := NewTree(testConfig(t, "basic"))
|
||||
|
||||
if tree.Loaded() {
|
||||
t.Fatal("should not be loaded")
|
||||
}
|
||||
|
||||
// This should error because we haven't gotten things yet
|
||||
if err := tree.Load(storage, GetModeNone); err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
|
||||
if tree.Loaded() {
|
||||
t.Fatal("should not be loaded")
|
||||
}
|
||||
|
||||
// This should get things
|
||||
if err := tree.Load(storage, GetModeGet); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !tree.Loaded() {
|
||||
t.Fatal("should be loaded")
|
||||
}
|
||||
|
||||
// This should no longer error
|
||||
if err := tree.Load(storage, GetModeNone); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -32,7 +44,7 @@ func TestTree_Load(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTree_Modules(t *testing.T) {
|
||||
func TestTreeModules(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "basic"))
|
||||
actual := tree.Modules()
|
||||
|
||||
|
@ -45,7 +57,7 @@ func TestTree_Modules(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTree_Name(t *testing.T) {
|
||||
func TestTreeName(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "basic"))
|
||||
actual := tree.Name()
|
||||
|
||||
|
@ -54,6 +66,50 @@ func TestTree_Name(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTreeValidate_badChild(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "validate-child-bad"))
|
||||
|
||||
if err := tree.Load(testStorage(t), GetModeGet); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if err := tree.Validate(); err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeValidate_badRoot(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "validate-root-bad"))
|
||||
|
||||
if err := tree.Load(testStorage(t), GetModeGet); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if err := tree.Validate(); err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeValidate_good(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "validate-child-good"))
|
||||
|
||||
if err := tree.Load(testStorage(t), GetModeGet); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if err := tree.Validate(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeValidate_notLoaded(t *testing.T) {
|
||||
tree := NewTree(testConfig(t, "basic"))
|
||||
|
||||
if err := tree.Validate(); err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
}
|
||||
|
||||
const treeLoadStr = `
|
||||
<root>
|
||||
foo
|
||||
|
|
Loading…
Reference in New Issue