mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-30 19:35:06 +00:00
fix: error management in jp functions (#6239)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
c3729672f9
commit
dd35ae201b
4 changed files with 51 additions and 42 deletions
|
@ -64,7 +64,7 @@ func ParseArithemticOperands(arguments []interface{}, operator string) (Operand,
|
|||
}
|
||||
|
||||
if op[0] == nil || op[1] == nil || t[0]|t[1] == 3 {
|
||||
return nil, nil, fmt.Errorf(genericError, operator, "invalid operands")
|
||||
return nil, nil, formatError(genericError, operator, "invalid operands")
|
||||
}
|
||||
|
||||
return op[0], op[1], nil
|
||||
|
@ -198,13 +198,13 @@ func (op1 Quantity) Divide(op2 interface{}) (interface{}, error) {
|
|||
case Quantity:
|
||||
divisor := v.AsApproximateFloat64()
|
||||
if divisor == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, divide)
|
||||
return nil, formatError(zeroDivisionError, divide)
|
||||
}
|
||||
dividend := op1.AsApproximateFloat64()
|
||||
return dividend / divisor, nil
|
||||
case Scalar:
|
||||
if v.float64 == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, divide)
|
||||
return nil, formatError(zeroDivisionError, divide)
|
||||
}
|
||||
q, err := resource.ParseQuantity(fmt.Sprintf("%v", v.float64))
|
||||
if err != nil {
|
||||
|
@ -223,12 +223,12 @@ func (op1 Duration) Divide(op2 interface{}) (interface{}, error) {
|
|||
switch v := op2.(type) {
|
||||
case Duration:
|
||||
if v.Seconds() == 0 {
|
||||
return nil, fmt.Errorf(undefinedQuoError, divide)
|
||||
return nil, formatError(zeroDivisionError, divide)
|
||||
}
|
||||
return op1.Seconds() / v.Seconds(), nil
|
||||
case Scalar:
|
||||
if v.float64 == 0 {
|
||||
return nil, fmt.Errorf(undefinedQuoError, divide)
|
||||
return nil, formatError(zeroDivisionError, divide)
|
||||
}
|
||||
seconds := op1.Seconds() / v.float64
|
||||
return time.Duration(seconds * float64(time.Second)).String(), nil
|
||||
|
@ -241,7 +241,7 @@ func (op1 Scalar) Divide(op2 interface{}) (interface{}, error) {
|
|||
switch v := op2.(type) {
|
||||
case Scalar:
|
||||
if v.float64 == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, divide)
|
||||
return nil, formatError(zeroDivisionError, divide)
|
||||
}
|
||||
return op1.float64 / v.float64, nil
|
||||
default:
|
||||
|
@ -266,13 +266,13 @@ func (op1 Quantity) Modulo(op2 interface{}) (interface{}, error) {
|
|||
i1 := int64(f1)
|
||||
i2 := int64(f2)
|
||||
if f1 != float64(i1) {
|
||||
return nil, fmt.Errorf(nonIntModuloError, modulo)
|
||||
return nil, formatError(nonIntModuloError, modulo)
|
||||
}
|
||||
if f2 != float64(i2) {
|
||||
return nil, fmt.Errorf(nonIntModuloError, modulo)
|
||||
return nil, formatError(nonIntModuloError, modulo)
|
||||
}
|
||||
if i2 == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, modulo)
|
||||
return nil, formatError(zeroDivisionError, modulo)
|
||||
}
|
||||
return resource.NewQuantity(i1%i2, op1.Quantity.Format).String(), nil
|
||||
default:
|
||||
|
@ -284,7 +284,7 @@ func (op1 Duration) Modulo(op2 interface{}) (interface{}, error) {
|
|||
switch v := op2.(type) {
|
||||
case Duration:
|
||||
if v.Duration == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, modulo)
|
||||
return nil, formatError(zeroDivisionError, modulo)
|
||||
}
|
||||
return (op1.Duration % v.Duration).String(), nil
|
||||
default:
|
||||
|
@ -298,13 +298,13 @@ func (op1 Scalar) Modulo(op2 interface{}) (interface{}, error) {
|
|||
val1 := int64(op1.float64)
|
||||
val2 := int64(v.float64)
|
||||
if op1.float64 != float64(val1) {
|
||||
return nil, fmt.Errorf(nonIntModuloError, modulo)
|
||||
return nil, formatError(nonIntModuloError, modulo)
|
||||
}
|
||||
if v.float64 != float64(val2) {
|
||||
return nil, fmt.Errorf(nonIntModuloError, modulo)
|
||||
return nil, formatError(nonIntModuloError, modulo)
|
||||
}
|
||||
if val2 == 0 {
|
||||
return nil, fmt.Errorf(zeroDivisionError, modulo)
|
||||
return nil, formatError(zeroDivisionError, modulo)
|
||||
}
|
||||
return float64(val1 % val2), nil
|
||||
default:
|
||||
|
|
20
pkg/engine/jmespath/error.go
Normal file
20
pkg/engine/jmespath/error.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package jmespath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
errorPrefix = "JMESPath function '%s': "
|
||||
invalidArgumentTypeError = errorPrefix + "%d argument is expected of %s type"
|
||||
genericError = errorPrefix + "%s"
|
||||
argOutOfBoundsError = errorPrefix + "%d argument is out of bounds (%d)"
|
||||
zeroDivisionError = errorPrefix + "Zero divisor passed"
|
||||
nonIntModuloError = errorPrefix + "Non-integer argument(s) passed for modulo"
|
||||
)
|
||||
|
||||
func formatError(format string, function string, values ...interface{}) error {
|
||||
args := []interface{}{function}
|
||||
args = append(args, values...)
|
||||
return fmt.Errorf(format, args...)
|
||||
}
|
|
@ -66,16 +66,6 @@ var (
|
|||
x509_decode = "x509_decode"
|
||||
)
|
||||
|
||||
const (
|
||||
errorPrefix = "JMESPath function '%s': "
|
||||
invalidArgumentTypeError = errorPrefix + "%d argument is expected of %s type"
|
||||
genericError = errorPrefix + "%s"
|
||||
argOutOfBoundsError = errorPrefix + "%d argument is out of bounds (%d)"
|
||||
zeroDivisionError = errorPrefix + "Zero divisor passed"
|
||||
undefinedQuoError = errorPrefix + "Undefined quotient"
|
||||
nonIntModuloError = errorPrefix + "Non-integer argument(s) passed for modulo"
|
||||
)
|
||||
|
||||
func GetFunctions() []FunctionEntry {
|
||||
return []FunctionEntry{{
|
||||
FunctionEntry: gojmespath.FunctionEntry{
|
||||
|
@ -629,17 +619,17 @@ func jpRegexReplaceAll(arguments []interface{}) (interface{}, error) {
|
|||
|
||||
src, err := ifaceToString(arguments[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAll, 2, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexReplaceAll, 2, "String or Real")
|
||||
}
|
||||
|
||||
repl, err := ifaceToString(arguments[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAll, 3, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexReplaceAll, 3, "String or Real")
|
||||
}
|
||||
|
||||
reg, err := regexp.Compile(regex.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(genericError, regexReplaceAll, err.Error())
|
||||
return nil, formatError(genericError, regexReplaceAll, err.Error())
|
||||
}
|
||||
return string(reg.ReplaceAll([]byte(src), []byte(repl))), nil
|
||||
}
|
||||
|
@ -653,17 +643,17 @@ func jpRegexReplaceAllLiteral(arguments []interface{}) (interface{}, error) {
|
|||
|
||||
src, err := ifaceToString(arguments[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAllLiteral, 2, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexReplaceAllLiteral, 2, "String or Real")
|
||||
}
|
||||
|
||||
repl, err := ifaceToString(arguments[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAllLiteral, 3, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexReplaceAllLiteral, 3, "String or Real")
|
||||
}
|
||||
|
||||
reg, err := regexp.Compile(regex.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(genericError, regexReplaceAllLiteral, err.Error())
|
||||
return nil, formatError(genericError, regexReplaceAllLiteral, err.Error())
|
||||
}
|
||||
return string(reg.ReplaceAllLiteral([]byte(src), []byte(repl))), nil
|
||||
}
|
||||
|
@ -677,7 +667,7 @@ func jpRegexMatch(arguments []interface{}) (interface{}, error) {
|
|||
|
||||
src, err := ifaceToString(arguments[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexMatch, 2, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexMatch, 2, "String or Real")
|
||||
}
|
||||
|
||||
return regexp.Match(regex.String(), []byte(src))
|
||||
|
@ -691,7 +681,7 @@ func jpPatternMatch(arguments []interface{}) (interface{}, error) {
|
|||
|
||||
src, err := ifaceToString(arguments[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, regexMatch, 2, "String or Real")
|
||||
return nil, formatError(invalidArgumentTypeError, regexMatch, 2, "String or Real")
|
||||
}
|
||||
|
||||
return wildcard.Match(pattern.String(), src), nil
|
||||
|
@ -701,13 +691,13 @@ func jpLabelMatch(arguments []interface{}) (interface{}, error) {
|
|||
labelMap, ok := arguments[0].(map[string]interface{})
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, labelMatch, 0, "Object")
|
||||
return nil, formatError(invalidArgumentTypeError, labelMatch, 0, "Object")
|
||||
}
|
||||
|
||||
matchMap, ok := arguments[1].(map[string]interface{})
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, labelMatch, 1, "Object")
|
||||
return nil, formatError(invalidArgumentTypeError, labelMatch, 1, "Object")
|
||||
}
|
||||
|
||||
for key, value := range labelMap {
|
||||
|
@ -871,11 +861,11 @@ func jpParseYAML(arguments []interface{}) (interface{}, error) {
|
|||
func jpItems(arguments []interface{}) (interface{}, error) {
|
||||
keyName, ok := arguments[1].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 1, "String")
|
||||
return nil, formatError(invalidArgumentTypeError, items, arguments, 1, "String")
|
||||
}
|
||||
valName, ok := arguments[2].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 2, "String")
|
||||
return nil, formatError(invalidArgumentTypeError, items, arguments, 2, "String")
|
||||
}
|
||||
switch input := arguments[0].(type) {
|
||||
case map[string]interface{}:
|
||||
|
@ -903,18 +893,18 @@ func jpItems(arguments []interface{}) (interface{}, error) {
|
|||
}
|
||||
return arrayOfObj, nil
|
||||
default:
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 0, "Object or Array")
|
||||
return nil, formatError(invalidArgumentTypeError, items, arguments, 0, "Object or Array")
|
||||
}
|
||||
}
|
||||
|
||||
func jpObjectFromLists(arguments []interface{}) (interface{}, error) {
|
||||
keys, ok := arguments[0].([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 0, "Array")
|
||||
return nil, formatError(invalidArgumentTypeError, objectFromLists, arguments, 0, "Array")
|
||||
}
|
||||
values, ok := arguments[1].([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 1, "Array")
|
||||
return nil, formatError(invalidArgumentTypeError, objectFromLists, arguments, 1, "Array")
|
||||
}
|
||||
|
||||
output := map[string]interface{}{}
|
||||
|
@ -922,7 +912,7 @@ func jpObjectFromLists(arguments []interface{}) (interface{}, error) {
|
|||
for i, ikey := range keys {
|
||||
key, err := ifaceToString(ikey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(invalidArgumentTypeError, arguments, 0, "StringArray")
|
||||
return nil, formatError(invalidArgumentTypeError, objectFromLists, arguments, 0, "StringArray")
|
||||
}
|
||||
if i < len(values) {
|
||||
output[key] = values[i]
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
package jmespath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func validateArg(f string, arguments []interface{}, index int, expectedType reflect.Kind) (reflect.Value, error) {
|
||||
if index >= len(arguments) {
|
||||
return reflect.Value{}, fmt.Errorf(argOutOfBoundsError, f, index+1, len(arguments))
|
||||
return reflect.Value{}, formatError(argOutOfBoundsError, f, index+1, len(arguments))
|
||||
}
|
||||
arg := reflect.ValueOf(arguments[index])
|
||||
if arg.Type().Kind() != expectedType {
|
||||
return reflect.Value{}, fmt.Errorf(invalidArgumentTypeError, f, index+1, expectedType.String())
|
||||
return reflect.Value{}, formatError(invalidArgumentTypeError, f, index+1, expectedType.String())
|
||||
}
|
||||
return arg, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue