github.com/rajeev159/opa@v0.45.0/topdown/errors.go (about) 1 // Copyright 2017 The OPA Authors. All rights reserved. 2 // Use of this source code is governed by an Apache2 3 // license that can be found in the LICENSE file. 4 5 package topdown 6 7 import ( 8 "errors" 9 "fmt" 10 11 "github.com/open-policy-agent/opa/ast" 12 ) 13 14 // Halt is a special error type that built-in function implementations return to indicate 15 // that policy evaluation should stop immediately. 16 type Halt struct { 17 Err error 18 } 19 20 func (h Halt) Error() string { 21 return h.Err.Error() 22 } 23 24 func (h Halt) Unwrap() error { return h.Err } 25 26 // Error is the error type returned by the Eval and Query functions when 27 // an evaluation error occurs. 28 type Error struct { 29 Code string `json:"code"` 30 Message string `json:"message"` 31 Location *ast.Location `json:"location,omitempty"` 32 } 33 34 const ( 35 36 // InternalErr represents an unknown evaluation error. 37 InternalErr string = "eval_internal_error" 38 39 // CancelErr indicates the evaluation process was cancelled. 40 CancelErr string = "eval_cancel_error" 41 42 // ConflictErr indicates a conflict was encountered during evaluation. For 43 // instance, a conflict occurs if a rule produces multiple, differing values 44 // for the same key in an object. Conflict errors indicate the policy does 45 // not account for the data loaded into the policy engine. 46 ConflictErr string = "eval_conflict_error" 47 48 // TypeErr indicates evaluation stopped because an expression was applied to 49 // a value of an inappropriate type. 50 TypeErr string = "eval_type_error" 51 52 // BuiltinErr indicates a built-in function received a semantically invalid 53 // input or encountered some kind of runtime error, e.g., connection 54 // timeout, connection refused, etc. 55 BuiltinErr string = "eval_builtin_error" 56 57 // WithMergeErr indicates that the real and replacement data could not be merged. 58 WithMergeErr string = "eval_with_merge_error" 59 ) 60 61 // IsError returns true if the err is an Error. 62 func IsError(err error) bool { 63 var e *Error 64 return errors.As(err, &e) 65 } 66 67 // IsCancel returns true if err was caused by cancellation. 68 func IsCancel(err error) bool { 69 return errors.Is(err, &Error{Code: CancelErr}) 70 } 71 72 // Is allows matching topdown errors using errors.Is (see IsCancel). 73 func (e *Error) Is(target error) bool { 74 var t *Error 75 if errors.As(target, &t) { 76 return (t.Code == "" || e.Code == t.Code) && 77 (t.Message == "" || e.Message == t.Message) && 78 (t.Location == nil || t.Location.Compare(e.Location) == 0) 79 } 80 return false 81 } 82 83 func (e *Error) Error() string { 84 msg := fmt.Sprintf("%v: %v", e.Code, e.Message) 85 86 if e.Location != nil { 87 msg = e.Location.String() + ": " + msg 88 } 89 90 return msg 91 } 92 93 func functionConflictErr(loc *ast.Location) error { 94 return &Error{ 95 Code: ConflictErr, 96 Location: loc, 97 Message: "functions must not produce multiple outputs for same inputs", 98 } 99 } 100 101 func completeDocConflictErr(loc *ast.Location) error { 102 return &Error{ 103 Code: ConflictErr, 104 Location: loc, 105 Message: "complete rules must not produce multiple outputs", 106 } 107 } 108 109 func objectDocKeyConflictErr(loc *ast.Location) error { 110 return &Error{ 111 Code: ConflictErr, 112 Location: loc, 113 Message: "object keys must be unique", 114 } 115 } 116 117 func unsupportedBuiltinErr(loc *ast.Location) error { 118 return &Error{ 119 Code: InternalErr, 120 Location: loc, 121 Message: "unsupported built-in", 122 } 123 } 124 125 func mergeConflictErr(loc *ast.Location) error { 126 return &Error{ 127 Code: WithMergeErr, 128 Location: loc, 129 Message: "real and replacement data could not be merged", 130 } 131 } 132 133 func internalErr(loc *ast.Location, msg string) error { 134 return &Error{ 135 Code: InternalErr, 136 Location: loc, 137 Message: msg, 138 } 139 }