github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  }