forked from kyverno/kyverno
-
Notifications
You must be signed in to change notification settings - Fork 2
/
notequal.go
155 lines (144 loc) · 4.73 KB
/
notequal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package operator
import (
"fmt"
"math"
"reflect"
"strconv"
"github.com/go-logr/logr"
"github.com/nirmata/kyverno/pkg/engine/context"
)
//NewNotEqualHandler returns handler to manage NotEqual operations
func NewNotEqualHandler(log logr.Logger, ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler {
return NotEqualHandler{
ctx: ctx,
subHandler: subHandler,
log: log,
}
}
//NotEqualHandler provides implementation to handle NotEqual Operator
type NotEqualHandler struct {
ctx context.EvalInterface
subHandler VariableSubstitutionHandler
log logr.Logger
}
//Evaluate evaluates expression with NotEqual Operator
func (neh NotEqualHandler) Evaluate(key, value interface{}) bool {
var err error
//TODO: decouple variables from evaluation
// substitute the variables
if key, err = neh.subHandler(neh.log, neh.ctx, key); err != nil {
// Failed to resolve the variable
neh.log.Error(err, "Failed to resolve variable", "variable", key)
return false
}
if value, err = neh.subHandler(neh.log, neh.ctx, value); err != nil {
// Failed to resolve the variable
neh.log.Error(err, "Failed to resolve variable", "variable", value)
return false
}
// key and value need to be of same 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:
return neh.validateValuewithStringPattern(typedKey, value)
case map[string]interface{}:
return neh.validateValueWithMapPattern(typedKey, value)
case []interface{}:
return neh.validateValueWithSlicePattern(typedKey, value)
default:
neh.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
return false
}
}
func (neh NotEqualHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
if val, ok := value.([]interface{}); ok {
return !reflect.DeepEqual(key, val)
}
neh.log.Info("Expected type []interface{}", "value", value, "type", fmt.Sprintf("%T", value))
return false
}
func (neh NotEqualHandler) validateValueWithMapPattern(key map[string]interface{}, 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
}
func (neh NotEqualHandler) validateValuewithStringPattern(key string, 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
}
func (neh NotEqualHandler) 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
}
func (neh NotEqualHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
typedValue, ok := value.(bool)
if !ok {
neh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value))
return false
}
return key != typedValue
}
func (neh NotEqualHandler) 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
}
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
}
}