mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-15 17:51:20 +00:00
Added in-notin operator
This commit is contained in:
parent
e8c4050d49
commit
b589169b5e
6 changed files with 83 additions and 199 deletions
|
@ -233,7 +233,10 @@ spec:
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
type: string
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: array
|
||||||
|
items: {}
|
||||||
generate:
|
generate:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|
|
@ -235,7 +235,10 @@ spec:
|
||||||
- NotIn
|
- NotIn
|
||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
type: string
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: array
|
||||||
|
items: {}
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
|
|
|
@ -235,7 +235,10 @@ spec:
|
||||||
- NotIn
|
- NotIn
|
||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
type: string
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: array
|
||||||
|
items: {}
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1068,6 +1068,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0=
|
||||||
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -2,9 +2,7 @@ package operator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||||
|
@ -27,131 +25,76 @@ type InHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Evaluate evaluates expression with In Operator
|
//Evaluate evaluates expression with In Operator
|
||||||
func (eh InHandler) Evaluate(key, value interface{}) bool {
|
func (in InHandler) Evaluate(key, value interface{}) bool {
|
||||||
var err error
|
var err error
|
||||||
//TODO: decouple variables from evaluation
|
//TODO: decouple variables from evaluation
|
||||||
// substitute the variables
|
// substitute the variables
|
||||||
if key, err = eh.subHandler(eh.log, eh.ctx, key); err != nil {
|
if key, err = in.subHandler(in.log, in.ctx, key); err != nil {
|
||||||
// Failed to resolve the variable
|
// Failed to resolve the variable
|
||||||
eh.log.Error(err, "Failed to resolve variable", "variable", key)
|
in.log.Error(err, "Failed to resolve variable", "variable", key)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if value, err = eh.subHandler(eh.log, eh.ctx, value); err != nil {
|
if value, err = in.subHandler(in.log, in.ctx, value); err != nil {
|
||||||
// Failed to resolve the variable
|
// Failed to resolve the variable
|
||||||
eh.log.Error(err, "Failed to resolve variable", "variable", value)
|
in.log.Error(err, "Failed to resolve variable", "variable", value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// key and value need to be of same type
|
// key should be avaliable in value
|
||||||
switch typedKey := key.(type) {
|
switch typedKey := key.(type) {
|
||||||
case bool:
|
|
||||||
return eh.validateValuewithBoolPattern(typedKey, value)
|
|
||||||
case int:
|
|
||||||
return eh.validateValuewithIntPattern(int64(typedKey), value)
|
|
||||||
case int64:
|
|
||||||
return eh.validateValuewithIntPattern(typedKey, value)
|
|
||||||
case float64:
|
|
||||||
return eh.validateValuewithFloatPattern(typedKey, value)
|
|
||||||
case string:
|
case string:
|
||||||
return eh.validateValuewithStringPattern(typedKey, value)
|
return in.validateValuewithStringPattern(typedKey, value)
|
||||||
case map[string]interface{}:
|
default:
|
||||||
return eh.validateValueWithMapPattern(typedKey, value)
|
in.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in InHandler) validateValuewithStringPattern(key string, value interface{}) (keyExists bool) {
|
||||||
|
invalidType, keyExists := ValidateStringPattern(key, value)
|
||||||
|
if invalidType {
|
||||||
|
in.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyExists
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateStringPattern(key string, value interface{}) (invalidType bool, keyExists bool) {
|
||||||
|
stringType := reflect.TypeOf("")
|
||||||
|
switch valuesAvaliable := value.(type) {
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
return eh.validateValueWithSlicePattern(typedKey, value)
|
for _, val := range valuesAvaliable {
|
||||||
|
if reflect.TypeOf(val) != stringType {
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
if key == val {
|
||||||
|
keyExists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
eh.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
|
return true, false
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return invalidType, keyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eh InHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
|
func (in InHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
|
||||||
if val, ok := value.([]interface{}); ok {
|
|
||||||
return reflect.DeepEqual(key, val)
|
|
||||||
}
|
|
||||||
eh.log.Info("Expected type []interface{}", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eh InHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
|
func (in InHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
|
||||||
if val, ok := value.(map[string]interface{}); ok {
|
|
||||||
return reflect.DeepEqual(key, val)
|
|
||||||
}
|
|
||||||
eh.log.Info("Expected type map[string]interface{}", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eh InHandler) validateValuewithStringPattern(key string, value interface{}) bool {
|
func (in InHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
|
||||||
if val, ok := value.(string); ok {
|
|
||||||
return key == val
|
|
||||||
}
|
|
||||||
|
|
||||||
eh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eh InHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
|
func (in InHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
|
||||||
switch typedValue := value.(type) {
|
|
||||||
case int:
|
|
||||||
// check that float has not fraction
|
|
||||||
if key == math.Trunc(key) {
|
|
||||||
return int(key) == typedValue
|
|
||||||
}
|
|
||||||
eh.log.Info("Expected type float, found int", "typedValue", typedValue)
|
|
||||||
case int64:
|
|
||||||
// check that float has not fraction
|
|
||||||
if key == math.Trunc(key) {
|
|
||||||
return int64(key) == typedValue
|
|
||||||
}
|
|
||||||
eh.log.Info("Expected type float, found int", "typedValue", typedValue)
|
|
||||||
case float64:
|
|
||||||
return typedValue == key
|
|
||||||
case string:
|
|
||||||
// extract float from string
|
|
||||||
float64Num, err := strconv.ParseFloat(typedValue, 64)
|
|
||||||
if err != nil {
|
|
||||||
eh.log.Error(err, "Failed to parse float64 from string")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return float64Num == key
|
|
||||||
default:
|
|
||||||
eh.log.Info("Expected type float", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eh InHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
|
func (in InHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
|
||||||
typedValue, ok := value.(bool)
|
return false
|
||||||
if !ok {
|
|
||||||
eh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return key == typedValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (eh InHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
|
|
||||||
switch typedValue := value.(type) {
|
|
||||||
case int:
|
|
||||||
return int64(typedValue) == key
|
|
||||||
case int64:
|
|
||||||
return typedValue == key
|
|
||||||
case float64:
|
|
||||||
// check that float has no fraction
|
|
||||||
if typedValue == math.Trunc(typedValue) {
|
|
||||||
return int64(typedValue) == key
|
|
||||||
}
|
|
||||||
eh.log.Info("Expected type int, found float", "value", typedValue, "type", fmt.Sprintf("%T", typedValue))
|
|
||||||
return false
|
|
||||||
case string:
|
|
||||||
// extract in64 from string
|
|
||||||
int64Num, err := strconv.ParseInt(typedValue, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
eh.log.Error(err, "Failed to parse int64 from string")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return int64Num == key
|
|
||||||
default:
|
|
||||||
eh.log.Info("Expected type int", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,6 @@ package operator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"github.com/nirmata/kyverno/pkg/engine/context"
|
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||||
|
@ -27,129 +24,62 @@ type NotInHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Evaluate evaluates expression with NotIn Operator
|
//Evaluate evaluates expression with NotIn Operator
|
||||||
func (neh NotInHandler) Evaluate(key, value interface{}) bool {
|
func (nin NotInHandler) Evaluate(key, value interface{}) bool {
|
||||||
var err error
|
var err error
|
||||||
//TODO: decouple variables from evaluation
|
//TODO: decouple variables from evaluation
|
||||||
// substitute the variables
|
// substitute the variables
|
||||||
if key, err = neh.subHandler(neh.log, neh.ctx, key); err != nil {
|
if key, err = nin.subHandler(nin.log, nin.ctx, key); err != nil {
|
||||||
// Failed to resolve the variable
|
// Failed to resolve the variable
|
||||||
neh.log.Error(err, "Failed to resolve variable", "variable", key)
|
nin.log.Error(err, "Failed to resolve variable", "variable", key)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if value, err = neh.subHandler(neh.log, neh.ctx, value); err != nil {
|
if value, err = nin.subHandler(nin.log, nin.ctx, value); err != nil {
|
||||||
// Failed to resolve the variable
|
// Failed to resolve the variable
|
||||||
neh.log.Error(err, "Failed to resolve variable", "variable", value)
|
nin.log.Error(err, "Failed to resolve variable", "variable", value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// key and value need to be of same type
|
// key and value need to be of same type
|
||||||
switch typedKey := key.(type) {
|
switch typedKey := key.(type) {
|
||||||
case bool:
|
|
||||||
return neh.validateValuewithBoolPattern(typedKey, value)
|
|
||||||
case int:
|
|
||||||
return neh.validateValuewithIntPattern(int64(typedKey), value)
|
|
||||||
case int64:
|
|
||||||
return neh.validateValuewithIntPattern(typedKey, value)
|
|
||||||
case float64:
|
|
||||||
return neh.validateValuewithFloatPattern(typedKey, value)
|
|
||||||
case string:
|
case string:
|
||||||
return neh.validateValuewithStringPattern(typedKey, value)
|
return nin.validateValuewithStringPattern(typedKey, value)
|
||||||
case map[string]interface{}:
|
|
||||||
return neh.validateValueWithMapPattern(typedKey, value)
|
|
||||||
case []interface{}:
|
|
||||||
return neh.validateValueWithSlicePattern(typedKey, value)
|
|
||||||
default:
|
default:
|
||||||
neh.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
|
nin.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
|
func (nin NotInHandler) validateValuewithStringPattern(key string, value interface{}) bool {
|
||||||
if val, ok := value.([]interface{}); ok {
|
invalidType, keyExists := ValidateStringPattern(key, value)
|
||||||
return !reflect.DeepEqual(key, val)
|
if invalidType {
|
||||||
|
nin.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
neh.log.Info("Expected type []interface{}", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
|
if !keyExists {
|
||||||
|
fmt.Println(".....return true......")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
fmt.Println(".....return false......")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
|
func (nin NotInHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
|
||||||
if val, ok := value.(map[string]interface{}); ok {
|
|
||||||
return !reflect.DeepEqual(key, val)
|
|
||||||
}
|
|
||||||
neh.log.Info("Expected type map[string]interface{}", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValuewithStringPattern(key string, value interface{}) bool {
|
func (nin NotInHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
|
||||||
if val, ok := value.(string); ok {
|
|
||||||
return key != val
|
|
||||||
}
|
|
||||||
neh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
|
func (nin NotInHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
|
||||||
switch typedValue := value.(type) {
|
|
||||||
case int:
|
|
||||||
// check that float has not fraction
|
|
||||||
if key == math.Trunc(key) {
|
|
||||||
return int(key) != typedValue
|
|
||||||
}
|
|
||||||
neh.log.Info("Expected type float, found int", "typedValue", typedValue)
|
|
||||||
case int64:
|
|
||||||
// check that float has not fraction
|
|
||||||
if key == math.Trunc(key) {
|
|
||||||
return int64(key) != typedValue
|
|
||||||
}
|
|
||||||
neh.log.Info("Expected type float, found int", "typedValue", typedValue)
|
|
||||||
case float64:
|
|
||||||
return typedValue != key
|
|
||||||
case string:
|
|
||||||
// extract float from string
|
|
||||||
float64Num, err := strconv.ParseFloat(typedValue, 64)
|
|
||||||
if err != nil {
|
|
||||||
neh.log.Error(err, "Failed to parse float64 from string")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return float64Num != key
|
|
||||||
default:
|
|
||||||
neh.log.Info("Expected type float", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
|
func (nin NotInHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
|
||||||
typedValue, ok := value.(bool)
|
return false
|
||||||
if !ok {
|
|
||||||
neh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return key != typedValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (neh NotInHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
|
func (nin NotInHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
|
||||||
switch typedValue := value.(type) {
|
return false
|
||||||
case int:
|
|
||||||
return int64(typedValue) != key
|
|
||||||
case int64:
|
|
||||||
return typedValue != key
|
|
||||||
case float64:
|
|
||||||
// check that float has no fraction
|
|
||||||
if typedValue == math.Trunc(typedValue) {
|
|
||||||
return int64(typedValue) != key
|
|
||||||
}
|
|
||||||
neh.log.Info("Expected type int, found float", "value", typedValue, "type", fmt.Sprintf("%T", typedValue))
|
|
||||||
return false
|
|
||||||
case string:
|
|
||||||
// extract in64 from string
|
|
||||||
int64Num, err := strconv.ParseInt(typedValue, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
neh.log.Error(err, "Failed to parse int64 from string")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return int64Num != key
|
|
||||||
default:
|
|
||||||
neh.log.Info("Expected type int", "value", value, "type", fmt.Sprintf("%T", value))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue