mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
3ebbeede6c
These changes modify topdown evaluation to use a binding list that namespaces variables. This allows topdown to propagate partially ground ref operands into child query evaluation. These changes also prepare topdown evaluation to support a partial evaluation mode. With these changes, evaluation is no longer performed in two steps (i.e., first pass of evaluating individual terms, second pass of evaluating built-in expressions.) Instead, evaluation assumes queries have been rewritten to eagerly evaluate refs and comprehension. This way, ref and comprehension bindings do not have to be maintained separately: they are handled by the normal variable binding list. This commit contains some breaking changes to the topdown APIs, namely... 1. Truth explanation has been removed. This feature was not used and the tracing changes broke it. We can revisit in future if necessary. 2. Data indexing has been removed. Data indexing can be re-added in future if necessary however it should be handled outside of topdown to avoid potential memory leaks. 3. Built-in functions produce at-most-one output now. Functions that used to produce multiple outputs (e.g., io.jwt.decode) can produce a composite value if they need to. Fixes #131
96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
// Copyright 2017 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package topdown
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/open-policy-agent/opa/ast"
|
|
)
|
|
|
|
// Error is the error type returned by the Eval and Query functions when
|
|
// an evaluation error occurs.
|
|
type Error struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
Location *ast.Location `json:"location,omitempty"`
|
|
}
|
|
|
|
const (
|
|
|
|
// InternalErr represents an unknown evaluation error.
|
|
InternalErr string = "eval_internal_error"
|
|
|
|
// CancelErr indicates the evaluation process was cancelled.
|
|
CancelErr string = "eval_cancel_error"
|
|
|
|
// ConflictErr indicates a conflict was encountered during evaluation. For
|
|
// instance, a conflict occurs if a rule produces multiple, differing values
|
|
// for the same key in an object. Conflict errors indicate the policy does
|
|
// not account for the data loaded into the policy engine.
|
|
ConflictErr string = "eval_conflict_error"
|
|
|
|
// TypeErr indicates evaluation stopped because an expression was applied to
|
|
// a value of an inappropriate type.
|
|
TypeErr string = "eval_type_error"
|
|
)
|
|
|
|
// IsError returns true if the err is an Error.
|
|
func IsError(err error) bool {
|
|
_, ok := err.(*Error)
|
|
return ok
|
|
}
|
|
|
|
// IsCancel returns true if err was caused by cancellation.
|
|
func IsCancel(err error) bool {
|
|
if e, ok := err.(*Error); ok {
|
|
return e.Code == CancelErr
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (e *Error) Error() string {
|
|
|
|
msg := fmt.Sprintf("%v: %v", e.Code, e.Message)
|
|
|
|
if e.Location != nil {
|
|
msg = e.Location.String() + ": " + msg
|
|
}
|
|
|
|
return msg
|
|
}
|
|
|
|
func functionConflictErr(loc *ast.Location) error {
|
|
return &Error{
|
|
Code: ConflictErr,
|
|
Location: loc,
|
|
Message: "functions must not produce multiple outputs for same inputs",
|
|
}
|
|
}
|
|
|
|
func completeDocConflictErr(loc *ast.Location) error {
|
|
return &Error{
|
|
Code: ConflictErr,
|
|
Location: loc,
|
|
Message: "complete rules must not produce multiple outputs",
|
|
}
|
|
}
|
|
|
|
func objectDocKeyConflictErr(loc *ast.Location) error {
|
|
return &Error{
|
|
Code: ConflictErr,
|
|
Location: loc,
|
|
Message: "object keys must be unique",
|
|
}
|
|
}
|
|
|
|
func unsupportedBuiltinErr(loc *ast.Location) error {
|
|
return &Error{
|
|
Code: InternalErr,
|
|
Location: loc,
|
|
Message: "unsupported built-in",
|
|
}
|
|
}
|