mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 00:41:27 -06:00
3ac6e575f1
To avoid a massively-disruptive change to how EvalNode works, we're now "smuggling" warnings through the error return value for these, but this depends on all of the Eval machinery correctly handling this special case and continuing evaluation when only warnings are returned. Previous changes missed EvalSequence as a place where execution halts on error. Now it will accumulate diagnostics itself, aborting if any of them are error diagnostics, and then wrap its own result up in an error to be returned by the main Eval function, which already treats non-fatal errors as a special case, though now produces an explicit log message about that situation to make it easier to spot in trace logs. This also includes a more detailed warning message for the warning about provider input being disabled. While this warning should be removed before we release anyway, having this additional detail is helpful in debugging tests where it's being returned.
71 lines
1.9 KiB
Go
71 lines
1.9 KiB
Go
package terraform
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// EvalNode is the interface that must be implemented by graph nodes to
|
|
// evaluate/execute.
|
|
type EvalNode interface {
|
|
// Eval evaluates this node with the given context. The second parameter
|
|
// are the argument values. These will match in order and 1-1 with the
|
|
// results of the Args() return value.
|
|
Eval(EvalContext) (interface{}, error)
|
|
}
|
|
|
|
// GraphNodeEvalable is the interface that graph nodes must implement
|
|
// to enable valuation.
|
|
type GraphNodeEvalable interface {
|
|
EvalTree() EvalNode
|
|
}
|
|
|
|
// EvalEarlyExitError is a special error return value that can be returned
|
|
// by eval nodes that does an early exit.
|
|
type EvalEarlyExitError struct{}
|
|
|
|
func (EvalEarlyExitError) Error() string { return "early exit" }
|
|
|
|
// Eval evaluates the given EvalNode with the given context, properly
|
|
// evaluating all args in the correct order.
|
|
func Eval(n EvalNode, ctx EvalContext) (interface{}, error) {
|
|
// Call the lower level eval which doesn't understand early exit,
|
|
// and if we early exit, it isn't an error.
|
|
result, err := EvalRaw(n, ctx)
|
|
if err != nil {
|
|
if _, ok := err.(EvalEarlyExitError); ok {
|
|
return nil, nil
|
|
}
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
// EvalRaw is like Eval except that it returns all errors, even if they
|
|
// signal something normal such as EvalEarlyExitError.
|
|
func EvalRaw(n EvalNode, ctx EvalContext) (interface{}, error) {
|
|
path := "unknown"
|
|
if ctx != nil {
|
|
path = ctx.Path().String()
|
|
}
|
|
if path == "" {
|
|
path = "<root>"
|
|
}
|
|
|
|
log.Printf("[TRACE] %s: eval: %T", path, n)
|
|
output, err := n.Eval(ctx)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case EvalEarlyExitError:
|
|
log.Printf("[TRACE] %s: eval: %T, early exit err: %s", path, n, err)
|
|
case tfdiags.NonFatalError:
|
|
log.Printf("[WARN] %s: eval: %T, non-fatal err: %s", path, n, err)
|
|
default:
|
|
log.Printf("[ERROR] %s: eval: %T, err: %s", path, n, err)
|
|
}
|
|
}
|
|
|
|
return output, err
|
|
}
|