github.com/ljosa/terraform@v0.7.0-rc2.0.20160617205345-fe540b408f59/terraform/eval.go (about) 1 package terraform 2 3 import ( 4 "log" 5 "strings" 6 ) 7 8 // EvalNode is the interface that must be implemented by graph nodes to 9 // evaluate/execute. 10 type EvalNode interface { 11 // Eval evaluates this node with the given context. The second parameter 12 // are the argument values. These will match in order and 1-1 with the 13 // results of the Args() return value. 14 Eval(EvalContext) (interface{}, error) 15 } 16 17 // GraphNodeEvalable is the interface that graph nodes must implement 18 // to enable valuation. 19 type GraphNodeEvalable interface { 20 EvalTree() EvalNode 21 } 22 23 // EvalEarlyExitError is a special error return value that can be returned 24 // by eval nodes that does an early exit. 25 type EvalEarlyExitError struct{} 26 27 func (EvalEarlyExitError) Error() string { return "early exit" } 28 29 // Eval evaluates the given EvalNode with the given context, properly 30 // evaluating all args in the correct order. 31 func Eval(n EvalNode, ctx EvalContext) (interface{}, error) { 32 // Call the lower level eval which doesn't understand early exit, 33 // and if we early exit, it isn't an error. 34 result, err := EvalRaw(n, ctx) 35 if err != nil { 36 if _, ok := err.(EvalEarlyExitError); ok { 37 return nil, nil 38 } 39 } 40 41 return result, err 42 } 43 44 // EvalRaw is like Eval except that it returns all errors, even if they 45 // signal something normal such as EvalEarlyExitError. 46 func EvalRaw(n EvalNode, ctx EvalContext) (interface{}, error) { 47 path := "unknown" 48 if ctx != nil { 49 path = strings.Join(ctx.Path(), ".") 50 } 51 52 log.Printf("[DEBUG] %s: eval: %T", path, n) 53 output, err := n.Eval(ctx) 54 if err != nil { 55 if _, ok := err.(EvalEarlyExitError); ok { 56 log.Printf("[DEBUG] %s: eval: %T, err: %s", path, n, err) 57 } else { 58 log.Printf("[ERROR] %s: eval: %T, err: %s", path, n, err) 59 } 60 } 61 62 return output, err 63 }